CMS 3D CMS Logo

GctFormatTranslateMCLegacy.cc

Go to the documentation of this file.
00001 #include "EventFilter/GctRawToDigi/src/GctFormatTranslateMCLegacy.h"
00002 
00003 // C++ headers
00004 #include <iostream>
00005 #include <cassert>
00006 
00007 // Framework headers
00008 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00009 
00010 // Namespace resolution
00011 using std::cout;
00012 using std::endl;
00013 using std::pair;
00014 using std::make_pair;
00015 using std::vector;
00016 
00017 // INITIALISE STATIC VARIABLES
00018 GctFormatTranslateMCLegacy::BlockLengthMap GctFormatTranslateMCLegacy::m_blockLength = GctFormatTranslateMCLegacy::BlockLengthMap();
00019 GctFormatTranslateMCLegacy::BlockNameMap GctFormatTranslateMCLegacy::m_blockName = GctFormatTranslateMCLegacy::BlockNameMap();
00020 GctFormatTranslateMCLegacy::BlockIdToUnpackFnMap GctFormatTranslateMCLegacy::m_blockUnpackFn = GctFormatTranslateMCLegacy::BlockIdToUnpackFnMap();
00021 GctFormatTranslateMCLegacy::BlkToRctCrateMap GctFormatTranslateMCLegacy::m_rctEmCrate = GctFormatTranslateMCLegacy::BlkToRctCrateMap();
00022 GctFormatTranslateMCLegacy::BlkToRctCrateMap GctFormatTranslateMCLegacy::m_rctJetCrate = GctFormatTranslateMCLegacy::BlkToRctCrateMap();
00023 GctFormatTranslateMCLegacy::BlockIdToEmCandIsoBoundMap GctFormatTranslateMCLegacy::m_internEmIsoBounds = GctFormatTranslateMCLegacy::BlockIdToEmCandIsoBoundMap();
00024 
00025 
00026 // PUBLIC METHODS
00027 
00028 GctFormatTranslateMCLegacy::GctFormatTranslateMCLegacy(bool hltMode, bool unpackSharedRegions):
00029   GctFormatTranslateBase(hltMode, unpackSharedRegions)
00030 {
00031   static bool initClass = true;
00032 
00033   if(initClass)
00034   {
00035     initClass = false;
00036 
00037     /*** Setup BlockID to BlockLength Map ***/
00038     // Miscellaneous Blocks
00039     m_blockLength.insert(make_pair(0x000,0));      // NULL
00040     m_blockLength.insert(make_pair(0x0ff,198));    // Temporary hack: All RCT Calo Regions for CMSSW pack/unpack
00041     // ConcJet FPGA
00042     m_blockLength.insert(make_pair(0x583,8));      // ConcJet: Jet Cands and Counts Output to GT
00043     // ConcElec FPGA
00044     m_blockLength.insert(make_pair(0x683,6));      // ConcElec: EM Cands and Energy Sums Output to GT
00045     // Electron Leaf FPGAs
00046     m_blockLength.insert(make_pair(0x804,15));     // Leaf0ElecPosEtaU1: Raw Input
00047     m_blockLength.insert(make_pair(0x884,12));     // Leaf0ElecPosEtaU2: Raw Input
00048     m_blockLength.insert(make_pair(0xc04,15));     // Leaf0ElecNegEtaU1: Raw Input
00049     m_blockLength.insert(make_pair(0xc84,12));     // Leaf0ElecNegEtaU2: Raw Input
00050 
00051 
00052     /*** Setup BlockID to BlockName Map ***/
00053     // Miscellaneous Blocks
00054     m_blockName.insert(make_pair(0x000,"NULL"));
00055     m_blockName.insert(make_pair(0x0ff,"All RCT Calo Regions"));  // Temporary hack: All RCT Calo Regions for CMSSW pack/unpack
00056     // ConcJet FPGA
00057     m_blockName.insert(make_pair(0x583,"ConcJet: Jet Cands and Counts Output to GT"));
00058     // ConcElec FPGA
00059     m_blockName.insert(make_pair(0x683,"ConcElec: EM Cands and Energy Sums Output to GT"));
00060     // Electron Leaf FPGAs
00061     m_blockName.insert(make_pair(0x804,"Leaf0ElecPosEtaU1: Raw Input"));
00062     m_blockName.insert(make_pair(0x884,"Leaf0ElecPosEtaU2: Raw Input"));
00063     m_blockName.insert(make_pair(0xc04,"Leaf0ElecNegEtaU1: Raw Input"));
00064     m_blockName.insert(make_pair(0xc84,"Leaf0ElecNegEtaU2: Raw Input"));
00065 
00066 
00067     /*** Setup BlockID to Unpack-Function Map ***/
00068     // Miscellaneous Blocks
00069     m_blockUnpackFn[0x000] = &GctFormatTranslateMCLegacy::blockDoNothing;                    // NULL
00070     m_blockUnpackFn[0x0ff] = &GctFormatTranslateMCLegacy::blockToAllRctCaloRegions;          // Temporary hack: All RCT Calo Regions for CMSSW pack/unpack
00071     // ConcJet FPGA                                                             
00072     m_blockUnpackFn[0x583] = &GctFormatTranslateMCLegacy::blockToGctJetCandsAndCounts;       // ConcJet: Jet Cands and Counts Output to GT
00073     // ConcElec FPGA                                                            
00074     m_blockUnpackFn[0x683] = &GctFormatTranslateMCLegacy::blockToGctEmCandsAndEnergySums;    // ConcElec: EM Cands and Energy Sums Output to GT
00075     // Electron Leaf FPGAs                                                      
00076     m_blockUnpackFn[0x804] = &GctFormatTranslateMCLegacy::blockToFibresAndToRctEmCand;       // Leaf0ElecPosEtaU1: Raw Input
00077     m_blockUnpackFn[0x884] = &GctFormatTranslateMCLegacy::blockToFibresAndToRctEmCand;       // Leaf0ElecPosEtaU2: Raw Input
00078     m_blockUnpackFn[0xc04] = &GctFormatTranslateMCLegacy::blockToFibresAndToRctEmCand;       // Leaf0ElecNegEtaU1: Raw Input
00079     m_blockUnpackFn[0xc84] = &GctFormatTranslateMCLegacy::blockToFibresAndToRctEmCand;       // Leaf0ElecNegEtaU2: Raw Input
00080 
00081 
00082     /*** Setup RCT Em Crate Map ***/
00083     m_rctEmCrate[0x804] = 13;
00084     m_rctEmCrate[0x884] = 9;
00085     m_rctEmCrate[0xc04] = 4;
00086     m_rctEmCrate[0xc84] = 0;
00087 
00088 
00089     /*** Setup RCT jet crate map. ***/
00090     // No entries required!
00091 
00092 
00093     /*** Setup Block ID map for pipeline payload positions of isolated Internal EM Cands. ***/
00094     // No entries required!
00095   }
00096 }
00097 
00098 GctFormatTranslateMCLegacy::~GctFormatTranslateMCLegacy()
00099 {
00100 }
00101 
00102 GctBlockHeader GctFormatTranslateMCLegacy::generateBlockHeader(const unsigned char * data) const
00103 {
00104   // Turn the four 8-bit header words into the full 32-bit header.
00105   uint32_t hdr = data[0] + (data[1]<<8) + (data[2]<<16) + (data[3]<<24);
00106 
00107   //  Bit mapping of header:
00108   //  ----------------------
00109   //  11:0   => block_id  Unique pipeline identifier.
00110   //   - 3:0    =>> pipe_id There can be up to 16 different pipelines per FPGA.
00111   //   - 6:4    =>> reserved  Do not use yet. Set to zero.
00112   //   - 11:7   =>> fpga geograpical add  The VME geographical address of the FPGA.
00113   //  15:12  => event_id  Determined locally.  Not reset by Resync.
00114   //  19:16  => number_of_time_samples  If time samples 15 or more then value = 15.
00115   //  31:20  => event_bxId  The bunch crossing the data was recorded.
00116 
00117   uint32_t blockId = hdr & 0xfff;
00118   uint32_t blockLength = 0;  // Set to zero until we know it's a valid block
00119   uint32_t nSamples = (hdr>>16) & 0xf;
00120   uint32_t bxId = (hdr>>20) & 0xfff;
00121   uint32_t eventId = (hdr>>12) & 0xf;
00122   bool valid = (blockLengthMap().find(blockId) != blockLengthMap().end());
00123 
00124   if(valid) { blockLength = blockLengthMap().find(blockId)->second; }
00125   
00126   return GctBlockHeader(blockId, blockLength, nSamples, bxId, eventId, valid);  
00127 }
00128 
00129 // conversion
00130 bool GctFormatTranslateMCLegacy::convertBlock(const unsigned char * data, const GctBlockHeader& hdr)
00131 {
00132   // if the block has no time samples, don't bother with it.
00133   if ( hdr.nSamples() < 1 ) { return true; }
00134 
00135   if(!checkBlock(hdr)) { return false; }  // Check the block to see if it's possible to unpack.
00136 
00137   // The header validity check above will protect against
00138   // the map::find() method returning the end of the map,
00139   // assuming the block header definitions are up-to-date.
00140   (this->*m_blockUnpackFn.find(hdr.blockId())->second)(data, hdr);  // Calls the correct unpack function, based on block ID.
00141   
00142   return true;
00143 }
00144 
00145 // Output EM Candidates and energy sums packing
00146 void GctFormatTranslateMCLegacy::writeGctOutEmAndEnergyBlock(unsigned char * d,
00147                                                              const L1GctEmCandCollection* iso,
00148                                                              const L1GctEmCandCollection* nonIso,
00149                                                              const L1GctEtTotalCollection* etTotal,
00150                                                              const L1GctEtHadCollection* etHad,
00151                                                              const L1GctEtMissCollection* etMiss)
00152 {
00153   // Set up a vector of the collections for easy iteration.
00154   vector<const L1GctEmCandCollection*> emCands(NUM_EM_CAND_CATEGORIES);
00155   emCands.at(NON_ISO_EM_CANDS)=nonIso;
00156   emCands.at(ISO_EM_CANDS)=iso;
00157   
00158   /* To hold the offsets within the EM candidate collections for the bx=0 candidates.
00159    * The capture index doesn't seem to get set properly by the emulator, so take the
00160    * first bx=0 cand as the highest energy EM cand, and the fourth as the lowest. */
00161   vector<unsigned> bx0EmCandOffsets(NUM_EM_CAND_CATEGORIES);
00162 
00163   // Loop over the different catagories of EM cands to find the bx=0 offsets.
00164   for(unsigned int iCat = 0 ; iCat < NUM_EM_CAND_CATEGORIES ; ++iCat)
00165   {
00166     const L1GctEmCandCollection * cands = emCands.at(iCat);
00167     unsigned& offset = bx0EmCandOffsets.at(iCat);
00168     if(!findBx0OffsetInCollection(offset, cands)) { LogDebug("GCT") << "No EM candidates with bx=0!\nAborting packing of GCT EM Cand and Energy Sum Output!"; return; }
00169     if((cands->size()-offset) < 4) { LogDebug("GCT") << "Insufficient EM candidates with bx=0!\nAborting packing of GCT EM Cand and Energy Sum Output!"; return; }
00170   }
00171   
00172   unsigned bx0EtTotalOffset, bx0EtHadOffset, bx0EtMissOffset;
00173   if(!findBx0OffsetInCollection(bx0EtTotalOffset, etTotal)) { LogDebug("GCT") << "No Et Total value for bx=0!\nAborting packing of GCT EM Cand and Energy Sum Output!"; return; }
00174   if(!findBx0OffsetInCollection(bx0EtHadOffset, etHad)) { LogDebug("GCT") << "No Et Hadronic value for bx=0!\nAborting packing of GCT EM Cand and Energy Sum Output!"; return; }
00175   if(!findBx0OffsetInCollection(bx0EtMissOffset, etMiss)) { LogDebug("GCT") << "No Et Miss value for bx=0!\nAborting packing of GCT EM Cand and Energy Sum Output!"; return; } 
00176   
00177   // We should now have all requisite data, so we can get on with packing
00178 
00179   unsigned nSamples = 1; // ** NOTE can only currenly do 1 timesample! **
00180   
00181   // write header
00182   writeRawHeader(d, 0x683, nSamples);   
00183   
00184   d=d+4;  // move to the block payload.
00185 
00186   // FIRST DO EM CANDS
00187 
00188   // re-interpret payload pointer to 16 bit.
00189   uint16_t * p16 = reinterpret_cast<uint16_t *>(d);
00190 
00191   for (unsigned iCat=0; iCat < NUM_EM_CAND_CATEGORIES; ++iCat)   // loop over non-iso/iso candidates categories
00192   {
00193     const L1GctEmCandCollection * em = emCands.at(iCat);   // The current category of EM cands.
00194     const unsigned bx0Offset = bx0EmCandOffsets.at(iCat);  // The offset in the EM cand collection to the bx=0 cands.
00195     
00196     uint16_t * cand = p16 + (iCat*4);
00197 
00198     *cand = em->at(bx0Offset).raw();
00199     cand++;
00200     *cand = em->at(bx0Offset + 2).raw();
00201     cand += nSamples;
00202     *cand = em->at(bx0Offset + 1).raw();
00203     cand++;
00204     *cand = em->at(bx0Offset + 3).raw();
00205   }
00206   
00207   // NOW DO ENERGY SUMS
00208   // assumes these are all 1-object collections, ie. central BX only
00209   p16+=8;  // Move past EM cands
00210   *p16 = etTotal->at(bx0EtTotalOffset).raw();  // Et Total - 16 bits.
00211   p16++;
00212   *p16 = etHad->at(bx0EtHadOffset).raw();  // Et Hadronic - next 16 bits
00213   p16++;
00214   uint32_t * p32 = reinterpret_cast<uint32_t *>(p16);  // For writing Missing Et (32-bit raw data)
00215   *p32 = etMiss->at(bx0EtMissOffset).raw();  // Et Miss on final 32 bits of block payload.
00216 }
00217 
00218 void GctFormatTranslateMCLegacy::writeGctOutJetBlock(unsigned char * d,
00219                                                      const L1GctJetCandCollection* cenJets,
00220                                                      const L1GctJetCandCollection* forJets,
00221                                                      const L1GctJetCandCollection* tauJets, 
00222                                                      const L1GctHFRingEtSumsCollection* hfRingSums,
00223                                                      const L1GctHFBitCountsCollection* hfBitCounts)
00224 {
00225   // Set up a vector of the collections for easy iteration.
00226   vector<const L1GctJetCandCollection*> jets(NUM_JET_CATEGORIES);
00227   jets.at(CENTRAL_JETS)=cenJets;
00228   jets.at(FORWARD_JETS)=forJets;
00229   jets.at(TAU_JETS)=tauJets;
00230 
00231   /* To hold the offsets within the three jet cand collections for the bx=0 jets.
00232    * The capture index doesn't seem to get set properly by the emulator, so take the
00233    * first bx=0 jet as the highest energy jet, and the fourth as the lowest. */
00234   vector<unsigned> bx0JetCandOffsets(NUM_JET_CATEGORIES);
00235 
00236   // Loop over the different catagories of jets to find the bx=0 offsets.
00237   for(unsigned int iCat = 0 ; iCat < NUM_JET_CATEGORIES ; ++iCat)
00238   {
00239     const L1GctJetCandCollection * jetCands = jets.at(iCat);
00240     unsigned& offset = bx0JetCandOffsets.at(iCat);
00241     if(!findBx0OffsetInCollection(offset, jetCands)) { LogDebug("GCT") << "No jet candidates with bx=0!\nAborting packing of GCT Jet Output!"; return; }
00242     if((jetCands->size()-offset) < 4) { LogDebug("GCT") << "Insufficient jet candidates with bx=0!\nAborting packing of GCT Jet Output!"; return; }
00243   }
00244   
00245   // Now find the collection offsets for the HfRingSums and HfBitCounts with bx=0
00246   unsigned bx0HfRingSumsOffset, bx0HfBitCountsOffset;
00247   if(!findBx0OffsetInCollection(bx0HfRingSumsOffset, hfRingSums)) { LogDebug("GCT") << "No ring sums with bx=0!\nAborting packing of GCT Jet Output!"; return; }
00248   if(!findBx0OffsetInCollection(bx0HfBitCountsOffset, hfBitCounts)) { LogDebug("GCT") << "No bit counts with bx=0!\nAborting packing of GCT Jet Output!"; return; }
00249 
00250   // Now write the header, as we should now have all requisite data.
00251   writeRawHeader(d, 0x583, 1);  // ** NOTE can only currenly do 1 timesample! **
00252   
00253   d=d+4;  // move forward past the block header to the block payload.
00254 
00255   // FIRST DO JET CANDS
00256   // re-interpret pointer to 16 bits - the space allocated for each Jet candidate.
00257   uint16_t * p16 = reinterpret_cast<uint16_t *>(d);
00258   
00259   const unsigned categoryOffset = 4;  // Offset to jump from one jet category to the next.
00260   const unsigned nextCandPairOffset = 2;  // Offset to jump to next candidate pair.
00261 
00262   // Loop over the different catagories of jets
00263   for(unsigned iCat = 0 ; iCat < NUM_JET_CATEGORIES ; ++iCat)
00264   {
00265     const L1GctJetCandCollection * jetCands = jets.at(iCat); // The current category of jet cands.
00266     const unsigned cand0Offset = iCat*categoryOffset;       // the offset on p16 to get the rank 0 Jet Cand of the correct category.
00267     const unsigned bx0Offset = bx0JetCandOffsets.at(iCat);  // The offset in the jet cand collection to the bx=0 jets.
00268     
00269     p16[cand0Offset] = jetCands->at(bx0Offset).raw();  // rank 0 jet in bx=0
00270     p16[cand0Offset + nextCandPairOffset] = jetCands->at(bx0Offset + 1).raw(); // rank 1 jet in bx=0
00271     p16[cand0Offset + 1] = jetCands->at(bx0Offset + 2).raw(); // rank 2 jet in bx=0
00272     p16[cand0Offset + nextCandPairOffset + 1] = jetCands->at(bx0Offset + 3).raw(); // rank 3 jet in bx=0.
00273   }
00274   
00275   // NOW DO JET COUNTS
00276   d=d+24;  // move forward past the jet cands to the jet counts section
00277 
00278   // re-interpret pointer to 32 bit.
00279   uint32_t * p32 = reinterpret_cast<uint32_t *>(d);
00280   
00281   uint32_t tmp = hfBitCounts->at(bx0HfBitCountsOffset).raw() & 0xfff;
00282   tmp |= hfRingSums->at(bx0HfRingSumsOffset).etSum(0)<<12;
00283   tmp |= hfRingSums->at(bx0HfRingSumsOffset).etSum(1)<<16;
00284   tmp |= hfRingSums->at(bx0HfRingSumsOffset).etSum(2)<<19;
00285   tmp |= hfRingSums->at(bx0HfRingSumsOffset).etSum(3)<<22;
00286   p32[0] = tmp;
00287   p32[1] = 0x5555c000;
00288 }
00289 
00290 void GctFormatTranslateMCLegacy::writeRctEmCandBlocks(unsigned char * d, const L1CaloEmCollection * rctEm)
00291 {
00292   // This method is one giant "temporary" hack for CMSSW_1_8_X and CMSSW_2_0_0.
00293 
00294   if(rctEm->size() == 0 || rctEm->size()%144 != 0)  // Should be 18 crates * 2 types (iso/noniso) * 4 electrons = 144 for 1 bx.
00295   {
00296     LogDebug("GCT") << "Block pack error: bad L1CaloEmCollection size detected!\n"
00297                     << "Aborting packing of RCT EM Cand data!";
00298     return;
00299   }
00300 
00301   // Need 18 sets of EM fibre data, since 18 RCT crates  
00302   EmuToSfpData emuToSfpData[18];
00303 
00304   // Fill in the input arrays with the data from the digi  
00305   for(unsigned i=0, size=rctEm->size(); i < size ; ++i)
00306   {
00307     const L1CaloEmCand &cand = rctEm->at(i);
00308     if(cand.bx() != 0) { continue; }  // Only interested in bunch crossing zero for now!
00309     unsigned crateNum = cand.rctCrate();
00310     unsigned index = cand.index();
00311     
00312     // Some error checking.
00313     assert(crateNum < 18); // Only 18 RCT crates!
00314     assert(index < 4); // Should only be 4 cands of each type per crate!
00315     
00316     if(cand.isolated())
00317     {
00318       emuToSfpData[crateNum].eIsoRank[index] = cand.rank();
00319       emuToSfpData[crateNum].eIsoCardId[index] = cand.rctCard();
00320       emuToSfpData[crateNum].eIsoRegionId[index] = cand.rctRegion();
00321     }
00322     else
00323     {
00324       emuToSfpData[crateNum].eNonIsoRank[index] = cand.rank();
00325       emuToSfpData[crateNum].eNonIsoCardId[index] = cand.rctCard();
00326       emuToSfpData[crateNum].eNonIsoRegionId[index] = cand.rctRegion();
00327     }
00328     // Note doing nothing with the MIP bit and Q bit arrays as we are not
00329     // interested in them; these arrays will contain uninitialised junk
00330     // and so you will get out junk for sourcecard output 0 - I.e. don't
00331     // trust sfp[0][0] or sfp[1][0] output!. 
00332   }
00333 
00334   // Now run the conversion
00335   for(unsigned c = 0 ; c < 18 ; ++c)
00336   {
00337     srcCardRouting().EMUtoSFP(emuToSfpData[c].eIsoRank, emuToSfpData[c].eIsoCardId, emuToSfpData[c].eIsoRegionId,
00338                               emuToSfpData[c].eNonIsoRank, emuToSfpData[c].eNonIsoCardId, emuToSfpData[c].eNonIsoRegionId,
00339                               emuToSfpData[c].mipBits, emuToSfpData[c].qBits, emuToSfpData[c].sfp);
00340   }
00341   
00342   // Now pack up the data into the RAW format.
00343   BlkToRctCrateMap::iterator blockStartCrateIter;
00344   for(blockStartCrateIter = rctEmCrateMap().begin() ; blockStartCrateIter != rctEmCrateMap().end() ; ++blockStartCrateIter)
00345   {
00346     unsigned blockId = blockStartCrateIter->first;
00347     unsigned startCrate = blockStartCrateIter->second;
00348     unsigned blockLength_32bit = blockLengthMap()[blockId];
00349     
00350     writeRawHeader(d, blockId, 1);
00351     d+=4; // move past header.
00352     
00353     // Want a 16 bit pointer to push the 16 bit data in.
00354     uint16_t * p16 = reinterpret_cast<uint16_t *>(const_cast<unsigned char *>(d));
00355     
00356     for(unsigned iCrate=startCrate, end=startCrate + blockLength_32bit/3 ; iCrate < end ; ++iCrate)
00357     {
00358       for(unsigned iOutput = 1 ; iOutput < 4 ; ++iOutput)  // skipping output 0 as that is Q-bit/MIP-bit data.
00359       {
00360         for(unsigned iCycle = 0 ; iCycle < 2 ; ++iCycle)
00361         {
00362           *p16 = emuToSfpData[iCrate].sfp[iCycle][iOutput];
00363           ++p16;
00364         }
00365       } 
00366     }
00367     
00368     // Now move d onto the location of the next block header
00369     d+=(blockLength_32bit*4);
00370   }
00371 }
00372 
00373 void GctFormatTranslateMCLegacy::writeAllRctCaloRegionBlock(unsigned char * d, const L1CaloRegionCollection * rctCalo)
00374 {
00375   // This method is one giant "temporary" hack for CMSSW_1_8_X and CMSSW_2_0_0.
00376 
00377   if(rctCalo->size() == 0 || rctCalo->size()%396 != 0)  // Should be 396 calo regions for 1 bx.
00378   {
00379     LogDebug("GCT") << "Block pack error: bad L1CaloRegionCollection size detected!\n"
00380                     << "Aborting packing of RCT Calo Region data!";
00381     return;
00382   }
00383 
00384   writeRawHeader(d, 0x0ff, 1);
00385   d+=4; // move past header.
00386 
00387   // Want a 16 bit pointer to push the 16 bit data in.
00388   uint16_t * p16 = reinterpret_cast<uint16_t *>(const_cast<unsigned char *>(d));
00389  
00390   for(unsigned i=0, size=rctCalo->size(); i < size ; ++i)
00391   {
00392     const L1CaloRegion &reg = rctCalo->at(i);
00393     if(reg.bx() != 0) { continue; }  // Only interested in bunch crossing zero for now!
00394     const unsigned crateNum = reg.rctCrate();
00395     const unsigned regionIndex = reg.rctRegionIndex();
00396     assert(crateNum < 18); // Only 18 RCT crates!
00397     
00398     // Gotta make the raw data as there currently isn't a method of getting raw from L1CaloRegion
00399     const uint16_t raw =  reg.et()                        | 
00400                          (reg.overFlow()  ? 0x400  : 0x0) |
00401                          (reg.fineGrain() ? 0x800  : 0x0) |
00402                          (reg.mip()       ? 0x1000 : 0x0) |
00403                          (reg.quiet()     ? 0x2000 : 0x0);
00404  
00405     unsigned offset = 0;  // for storing calculated raw data offset.   
00406     if(reg.isHbHe())  // Is a barrel/endcap region
00407     {
00408       const unsigned cardNum = reg.rctCard();
00409       assert(cardNum < 7);  // 7 RCT cards per crate for the barrel/endcap
00410       assert(regionIndex < 2); // regionIndex less than 2 for barrel/endcap
00411       
00412       // Calculate position in the raw data from crateNum, cardNum, and regionIndex
00413       offset = crateNum*22 + cardNum*2 + regionIndex;
00414     }
00415     else  // Must be forward region
00416     {
00417       assert(regionIndex < 8); // regionIndex less than 8 for forward calorimeter.
00418       offset = crateNum*22 + 14 + regionIndex;
00419     }
00420     p16[offset] = raw;  // Write raw data in correct place!
00421   }
00422 }
00423 
00424 
00425 // PROTECTED METHODS
00426 
00427 uint32_t GctFormatTranslateMCLegacy::generateRawHeader(const uint32_t blockId,
00428                                                        const uint32_t nSamples,
00429                                                        const uint32_t bxId,
00430                                                        const uint32_t eventId) const
00431 {
00432   //  Bit mapping of header:
00433   //  ----------------------
00434   //  11:0   => block_id  Unique pipeline identifier.
00435   //   - 3:0    =>> pipe_id There can be up to 16 different pipelines per FPGA.
00436   //   - 6:4    =>> reserved  Do not use yet. Set to zero.
00437   //   - 11:7   =>> fpga geograpical add  The VME geographical address of the FPGA.
00438   //  15:12  => event_id  Determined locally.  Not reset by Resync.
00439   //  19:16  => number_of_time_samples  If time samples 15 or more then value = 15.
00440   //  31:20  => event_bxId  The bunch crossing the data was recorded.
00441 
00442   return ((bxId & 0xfff) << 20) | ((nSamples & 0xf) << 16) | ((eventId & 0xf) << 12) | (blockId & 0xfff);
00443 }
00444 
00445 
00446 // PRIVATE METHODS
00447 
00448 // Output EM Candidates unpacking
00449 void GctFormatTranslateMCLegacy::blockToGctEmCandsAndEnergySums(const unsigned char * d, const GctBlockHeader& hdr)
00450 {
00451   const unsigned int id = hdr.blockId();
00452   const unsigned int nSamples = hdr.nSamples();
00453 
00454   // Re-interpret pointer.  p16 will be pointing at the 16 bit word that
00455   // contains the rank0 non-isolated electron of the zeroth time-sample.
00456   const uint16_t * p16 = reinterpret_cast<const uint16_t *>(d);
00457 
00458   // UNPACK EM CANDS
00459 
00460   const unsigned int emCandCategoryOffset = nSamples * 4;  // Offset to jump from the non-iso electrons to the isolated ones.
00461   const unsigned int timeSampleOffset = nSamples * 2;  // Offset to jump to next candidate pair in the same time-sample.
00462 
00463   unsigned int samplesToUnpack = 1;
00464   if(!hltMode()) { samplesToUnpack = nSamples; }  // Only if not running in HLT mode do we want more than 1 timesample. 
00465 
00466   for (unsigned int iso=0; iso<2; ++iso)  // loop over non-iso/iso candidate pairs
00467   {
00468     bool isoFlag = (iso==1);
00469 
00470     // Get the correct collection to put them in.
00471     L1GctEmCandCollection* em;
00472     if (isoFlag) { em = colls()->gctIsoEm(); }
00473     else { em = colls()->gctNonIsoEm(); }
00474 
00475     for (unsigned int bx=0; bx<samplesToUnpack; ++bx) // loop over time samples
00476     {
00477       // cand0Offset will give the offset on p16 to get the rank 0 candidate
00478       // of the correct category and timesample.
00479       const unsigned int cand0Offset = iso*emCandCategoryOffset + bx*2;
00480 
00481       em->push_back(L1GctEmCand(p16[cand0Offset], isoFlag, id, 0, bx));  // rank0 electron
00482       em->push_back(L1GctEmCand(p16[cand0Offset + timeSampleOffset], isoFlag, id, 1, bx));  // rank1 electron
00483       em->push_back(L1GctEmCand(p16[cand0Offset + 1], isoFlag, id, 2, bx));  // rank2 electron
00484       em->push_back(L1GctEmCand(p16[cand0Offset + timeSampleOffset + 1], isoFlag, id, 3, bx));  // rank3 electron
00485     }
00486   }
00487 
00488   p16 += emCandCategoryOffset * 2;  // Move the pointer over the data we've already unpacked.
00489 
00490   // UNPACK ENERGY SUMS
00491   // NOTE: we are only unpacking one timesample of these currently!
00492 
00493   colls()->gctEtTot()->push_back(L1GctEtTotal(p16[0]));  // Et total (timesample 0).
00494   colls()->gctEtHad()->push_back(L1GctEtHad(p16[1]));  // Et hadronic (timesample 0).
00495 
00496   // 32-bit pointer for getting Missing Et.
00497   const uint32_t * p32 = reinterpret_cast<const uint32_t *>(p16);
00498 
00499   colls()->gctEtMiss()->push_back(L1GctEtMiss(p32[nSamples])); // Et Miss (timesample 0).
00500 }
00501 
00502 void GctFormatTranslateMCLegacy::blockToGctJetCandsAndCounts(const unsigned char * d, const GctBlockHeader& hdr)
00503 {
00504   const unsigned int id = hdr.blockId();  // Capture block ID.
00505   const unsigned int nSamples = hdr.nSamples();  // Number of time-samples.
00506 
00507   // Re-interpret block payload pointer to 16 bits so it sees one candidate at a time.
00508   // p16 points to the start of the block payload, at the rank0 tau jet candidate.
00509   const uint16_t * p16 = reinterpret_cast<const uint16_t *>(d);
00510 
00511   // UNPACK JET CANDS
00512 
00513   const unsigned int jetCandCategoryOffset = nSamples * 4;  // Offset to jump from one jet category to the next.
00514   const unsigned int timeSampleOffset = nSamples * 2;  // Offset to jump to next candidate pair in the same time-sample.
00515 
00516   unsigned int samplesToUnpack = 1;
00517   if(!hltMode()) { samplesToUnpack = nSamples; }  // Only if not running in HLT mode do we want more than 1 timesample. 
00518 
00519   // Loop over the different catagories of jets
00520   for(unsigned int iCat = 0 ; iCat < NUM_JET_CATEGORIES ; ++iCat)
00521   {
00522     L1GctJetCandCollection * const jets = gctJets(iCat);
00523     assert(jets->empty()); // The supplied vector should be empty.
00524 
00525     bool tauflag = (iCat == TAU_JETS);
00526     bool forwardFlag = (iCat == FORWARD_JETS);
00527 
00528     // Loop over the different timesamples (bunch crossings).
00529     for(unsigned int bx = 0 ; bx < samplesToUnpack ; ++bx)
00530     {
00531       // cand0Offset will give the offset on p16 to get the rank 0 Jet Cand of the correct category and timesample.
00532       const unsigned int cand0Offset = iCat*jetCandCategoryOffset + bx*2;
00533 
00534       // Rank 0 Jet.
00535       jets->push_back(L1GctJetCand(p16[cand0Offset], tauflag, forwardFlag, id, 0, bx));
00536       // Rank 1 Jet.
00537       jets->push_back(L1GctJetCand(p16[cand0Offset + timeSampleOffset], tauflag, forwardFlag, id, 1, bx));
00538       // Rank 2 Jet.
00539       jets->push_back(L1GctJetCand(p16[cand0Offset + 1],  tauflag, forwardFlag, id, 2, bx));
00540       // Rank 3 Jet.
00541       jets->push_back(L1GctJetCand(p16[cand0Offset + timeSampleOffset + 1], tauflag, forwardFlag, id, 3, bx));
00542     }
00543   }
00544 
00545   p16 += NUM_JET_CATEGORIES * jetCandCategoryOffset; // Move the pointer over the data we've already unpacked.
00546 
00547   // NOW UNPACK: HFBitCounts, HFRingEtSums and Missing Ht
00548   // NOTE: we are only unpacking one timesample of these currently!
00549 
00550   // Re-interpret block payload pointer to 32 bits so it sees six jet counts at a time.
00551   const uint32_t * p32 = reinterpret_cast<const uint32_t *>(p16);
00552 
00553   // Channel 0 carries both HF counts and sums
00554   colls()->gctHfBitCounts()->push_back(L1GctHFBitCounts::fromConcHFBitCounts(id,6,0,p32[0])); 
00555   colls()->gctHfRingEtSums()->push_back(L1GctHFRingEtSums::fromConcRingSums(id,6,0,p32[0]));
00556 
00557   // Channel 1 carries Missing HT.  Would be found at p32[nSamples].  Excluded from 22X backport for now.
00558 }
00559 
00560 // Input EM Candidates unpacking
00561 // this is the last time I deal the RCT bit assignment travesty!!!
00562 void GctFormatTranslateMCLegacy::blockToRctEmCand(const unsigned char * d, const GctBlockHeader& hdr)
00563 {
00564   // Don't want to do this in HLT optimisation mode!
00565   if(hltMode()) { LogDebug("GCT") << "HLT mode - skipping unpack of RCT EM Cands"; return; }
00566 
00567   unsigned int id = hdr.blockId();
00568   unsigned int nSamples = hdr.nSamples();
00569   unsigned int length = hdr.blockLength();
00570 
00571   // re-interpret pointer
00572   uint16_t * p = reinterpret_cast<uint16_t *>(const_cast<unsigned char *>(d));
00573 
00574   // arrays of source card data
00575   uint16_t sfp[2][4]; // [ cycle ] [ SFP ]
00576   uint16_t eIsoRank[4];
00577   uint16_t eIsoCard[4];
00578   uint16_t eIsoRgn[4];
00579   uint16_t eNonIsoRank[4];
00580   uint16_t eNonIsoCard[4];
00581   uint16_t eNonIsoRgn[4];
00582   uint16_t MIPbits[7][2];
00583   uint16_t QBits[7][2];
00584 
00585   unsigned int bx = 0;
00586 
00587   // loop over crates
00588   for (unsigned int crate=rctEmCrateMap()[id]; crate<rctEmCrateMap()[id]+length/3; ++crate) {
00589 
00590     // read SC SFP words
00591     for (unsigned short iSfp=0 ; iSfp<4 ; ++iSfp) {
00592       for (unsigned short cyc=0 ; cyc<2 ; ++cyc) {
00593         if (iSfp==0) { sfp[cyc][iSfp] = 0; } // muon bits
00594         else {                               // EM candidate
00595           sfp[cyc][iSfp] = *p;
00596           ++p;
00597         }
00598       }
00599       p = p + 2*(nSamples-1);
00600     }
00601 
00602     // fill SC arrays
00603     srcCardRouting().SFPtoEMU(eIsoRank, eIsoCard, eIsoRgn, eNonIsoRank, eNonIsoCard, eNonIsoRgn, MIPbits, QBits, sfp);
00604     
00605     // create EM cands
00606     for (unsigned short int i=0; i<4; ++i) {
00607       colls()->rctEm()->push_back( L1CaloEmCand( eIsoRank[i], eIsoRgn[i], eIsoCard[i], crate, true, i, bx) );
00608     }
00609     for (unsigned short int i=0; i<4; ++i) {
00610       colls()->rctEm()->push_back( L1CaloEmCand( eNonIsoRank[i], eNonIsoRgn[i], eNonIsoCard[i], crate, false, i, bx) );
00611     }
00612   }
00613 }
00614 
00615 // Fibre unpacking
00616 void GctFormatTranslateMCLegacy::blockToFibres(const unsigned char * d, const GctBlockHeader& hdr)
00617 {
00618   // Don't want to do this in HLT optimisation mode!
00619   if(hltMode()) { LogDebug("GCT") << "HLT mode - skipping unpack of GCT Fibres"; return; }
00620   
00621   unsigned int id = hdr.blockId();
00622   unsigned int nSamples = hdr.nSamples();
00623   unsigned int length = hdr.blockLength();
00624 
00625   // re-interpret pointer
00626   uint32_t * p = reinterpret_cast<uint32_t *>(const_cast<unsigned char *>(d));
00627 
00628   for (unsigned int i=0; i<length; ++i) {
00629     for (unsigned int bx=0; bx<nSamples; ++bx) {
00630       colls()->gctFibres()->push_back( L1GctFibreWord(*p, id, i, bx) );
00631       ++p;
00632     }
00633   } 
00634 }
00635 
00636 void GctFormatTranslateMCLegacy::blockToFibresAndToRctEmCand(const unsigned char * d, const GctBlockHeader& hdr)
00637 {
00638   this->blockToRctEmCand(d, hdr);
00639   this->blockToFibres(d, hdr);
00640 }
00641 
00642 void GctFormatTranslateMCLegacy::blockToAllRctCaloRegions(const unsigned char * d, const GctBlockHeader& hdr)
00643 {
00644   // Don't want to do this in HLT optimisation mode!
00645   if(hltMode()) { LogDebug("GCT") << "HLT mode - skipping unpack of RCT Calo Regions"; return; }
00646 
00647   // This method is one giant "temporary" hack whilst waiting for proper
00648   // pipeline formats for the RCT calo region data.
00649   
00650   const int nSamples = hdr.nSamples();  // Number of time-samples.
00651 
00652   // Re-interpret block payload pointer to 16 bits
00653   const uint16_t * p16 = reinterpret_cast<const uint16_t *>(d);
00654   
00655   for(unsigned iCrate = 0 ; iCrate < 18 ; ++iCrate)
00656   {
00657     // Barrel and endcap regions
00658     for(unsigned iCard = 0 ; iCard < 7 ; ++iCard)
00659     {
00660       // Samples
00661       for(int16_t iSample = 0 ; iSample < nSamples ; ++iSample)
00662       {
00663         // Two regions per card (and per 32-bit word).
00664         for(unsigned iRegion = 0 ; iRegion < 2 ; ++iRegion)
00665         {
00666           L1CaloRegionDetId id(iCrate, iCard, iRegion);
00667           colls()->rctCalo()->push_back(L1CaloRegion(*p16, id.ieta(), id.iphi(), iSample));
00668           ++p16; //advance pointer
00669         }
00670       }
00671     }
00672     // Forward regions (8 regions numbered 0 through 7, packed in 4 sets of pairs)
00673     for(unsigned iRegionPairNum = 0 ; iRegionPairNum < 4 ; ++iRegionPairNum)
00674     {
00675       // Samples
00676       for(int16_t iSample = 0 ; iSample < nSamples ; ++iSample)
00677       {
00678         // two regions in a pair
00679         for(unsigned iPair = 0 ; iPair < 2 ; ++iPair)
00680         {
00681           // For forward regions, RCTCard=999
00682           L1CaloRegionDetId id(iCrate, 999, iRegionPairNum*2 + iPair);
00683           colls()->rctCalo()->push_back(L1CaloRegion(*p16, id.ieta(), id.iphi(), iSample));
00684           ++p16; //advance pointer
00685         }
00686       }
00687     }
00688   }
00689 }
00690 
00691 template <typename Collection> 
00692 bool GctFormatTranslateMCLegacy::findBx0OffsetInCollection(unsigned& bx0Offset, const Collection* coll)
00693 {
00694   bool foundBx0 = false;
00695   unsigned size = coll->size();
00696   for(bx0Offset = 0 ; bx0Offset < size ; ++bx0Offset)
00697   {
00698     if(coll->at(bx0Offset).bx() == 0) { foundBx0 = true; break; }
00699   }
00700   return foundBx0;
00701 }

Generated on Tue Jun 9 17:34:41 2009 for CMSSW by  doxygen 1.5.4