CMS 3D CMS Logo

GctFormatTranslateMCLegacy.cc
Go to the documentation of this file.
2 
3 // C++ headers
4 #include <iostream>
5 #include <cassert>
6 
7 // Framework headers
9 
10 // Namespace resolution
11 using std::cout;
12 using std::endl;
13 using std::pair;
14 using std::make_pair;
15 using std::vector;
16 
17 // INITIALISE STATIC VARIABLES
18 /*** Setup BlockID to BlockLength Map ***/
20  // Miscellaneous Blocks
21  {0x000,0}, // NULL
22  {0x0ff,198}, // Temporary hack: All RCT Calo Regions for CMSSW pack/unpack
23  // ConcJet FPGA
24  {0x583,8}, // ConcJet: Jet Cands and Counts Output to GT
25  // ConcElec FPGA
26  {0x683,6}, // ConcElec: EM Cands and Energy Sums Output to GT
27  // Electron Leaf FPGAs
28  {0x804,15}, // Leaf0ElecPosEtaU1: Raw Input
29  {0x884,12}, // Leaf0ElecPosEtaU2: Raw Input
30  {0xc04,15}, // Leaf0ElecNegEtaU1: Raw Input
31  {0xc84,12}
32 }; // Leaf0ElecNegEtaU2: Raw Input
33 
34 /*** Setup BlockID to BlockName Map ***/
36  // Miscellaneous Blocks
37  {0x000,"NULL"},
38  {0x0ff,"All RCT Calo Regions"}, // Temporary hack: All RCT Calo Regions for CMSSW pack/unpack
39  // ConcJet FPGA
40  {0x583,"ConcJet: Jet Cands and Counts Output to GT"},
41  // ConcElec FPGA
42  {0x683,"ConcElec: EM Cands and Energy Sums Output to GT"},
43  // Electron Leaf FPGAs
44  {0x804,"Leaf0ElecPosEtaU1: Raw Input"},
45  {0x884,"Leaf0ElecPosEtaU2: Raw Input"},
46  {0xc04,"Leaf0ElecNegEtaU1: Raw Input"},
47  {0xc84,"Leaf0ElecNegEtaU2: Raw Input"}
48 };
49 
50 /*** Setup BlockID to Unpack-Function Map ***/
52  // Miscellaneous Blocks
54  {0x0ff,&GctFormatTranslateMCLegacy::blockToAllRctCaloRegions}, // Temporary hack: All RCT Calo Regions for CMSSW pack/unpack
55  // ConcJet FPGA
56  {0x583,&GctFormatTranslateMCLegacy::blockToGctJetCandsAndCounts}, // ConcJet: Jet Cands and Counts Output to GT
57  // ConcElec FPGA
58  {0x683,&GctFormatTranslateMCLegacy::blockToGctEmCandsAndEnergySums}, // ConcElec: EM Cands and Energy Sums Output to GT
59  // Electron Leaf FPGAs
60  {0x804,&GctFormatTranslateMCLegacy::blockToFibresAndToRctEmCand}, // Leaf0ElecPosEtaU1: Raw Input
61  {0x884,&GctFormatTranslateMCLegacy::blockToFibresAndToRctEmCand}, // Leaf0ElecPosEtaU2: Raw Input
62  {0xc04,&GctFormatTranslateMCLegacy::blockToFibresAndToRctEmCand}, // Leaf0ElecNegEtaU1: Raw Input
63  {0xc84,&GctFormatTranslateMCLegacy::blockToFibresAndToRctEmCand} // Leaf0ElecNegEtaU2: Raw Input
64 };
65 
66 /*** Setup RCT Em Crate Map ***/
68  {0x804,13},
69  {0x884,9},
70  {0xc04,4},
71  {0xc84,0}
72 };
73 
74 
75 /*** Setup RCT jet crate map. ***/
76 // No entries required!
78 
79 /*** Setup Block ID map for pipeline payload positions of isolated Internal EM Cands. ***/
80 // No entries required!
82 
83 
84 // PUBLIC METHODS
85 
86 GctFormatTranslateMCLegacy::GctFormatTranslateMCLegacy(bool hltMode, bool unpackSharedRegions):
87  GctFormatTranslateBase(hltMode, unpackSharedRegions)
88 {
89 }
90 
92 {
93 }
94 
96 {
97  // Turn the four 8-bit header words into the full 32-bit header.
98  uint32_t hdr = data[0] + (data[1]<<8) + (data[2]<<16) + (data[3]<<24);
99 
100  // Bit mapping of header:
101  // ----------------------
102  // 11:0 => block_id Unique pipeline identifier.
103  // - 3:0 =>> pipe_id There can be up to 16 different pipelines per FPGA.
104  // - 6:4 =>> reserved Do not use yet. Set to zero.
105  // - 11:7 =>> fpga geograpical add The VME geographical address of the FPGA.
106  // 15:12 => event_id Determined locally. Not reset by Resync.
107  // 19:16 => number_of_time_samples If time samples 15 or more then value = 15.
108  // 31:20 => event_bxId The bunch crossing the data was recorded.
109 
110  uint32_t blockId = hdr & 0xfff;
111  uint32_t blockLength = 0; // Set to zero until we know it's a valid block
112  uint32_t nSamples = (hdr>>16) & 0xf;
113  uint32_t bxId = (hdr>>20) & 0xfff;
114  uint32_t eventId = (hdr>>12) & 0xf;
115  bool valid = (blockLengthMap().find(blockId) != blockLengthMap().end());
116 
117  if(valid) { blockLength = blockLengthMap().find(blockId)->second; }
118 
119  return GctBlockHeader(blockId, blockLength, nSamples, bxId, eventId, valid);
120 }
121 
122 // conversion
123 bool GctFormatTranslateMCLegacy::convertBlock(const unsigned char * data, const GctBlockHeader& hdr)
124 {
125  // if the block has no time samples, don't bother with it.
126  if ( hdr.nSamples() < 1 ) { return true; }
127 
128  if(!checkBlock(hdr)) { return false; } // Check the block to see if it's possible to unpack.
129 
130  // The header validity check above will protect against
131  // the map::find() method returning the end of the map,
132  // assuming the block header definitions are up-to-date.
133  (this->*m_blockUnpackFn.find(hdr.blockId())->second)(data, hdr); // Calls the correct unpack function, based on block ID.
134 
135  return true;
136 }
137 
138 // Output EM Candidates and energy sums packing
140  const L1GctEmCandCollection* iso,
141  const L1GctEmCandCollection* nonIso,
142  const L1GctEtTotalCollection* etTotal,
143  const L1GctEtHadCollection* etHad,
144  const L1GctEtMissCollection* etMiss)
145 {
146  // Set up a vector of the collections for easy iteration.
147  vector<const L1GctEmCandCollection*> emCands(NUM_EM_CAND_CATEGORIES);
148  emCands.at(NON_ISO_EM_CANDS)=nonIso;
149  emCands.at(ISO_EM_CANDS)=iso;
150 
151  /* To hold the offsets within the EM candidate collections for the bx=0 candidates.
152  * The capture index doesn't seem to get set properly by the emulator, so take the
153  * first bx=0 cand as the highest energy EM cand, and the fourth as the lowest. */
154  vector<unsigned> bx0EmCandOffsets(NUM_EM_CAND_CATEGORIES);
155 
156  // Loop over the different catagories of EM cands to find the bx=0 offsets.
157  for(unsigned int iCat = 0 ; iCat < NUM_EM_CAND_CATEGORIES ; ++iCat)
158  {
159  const L1GctEmCandCollection * cands = emCands.at(iCat);
160  unsigned& offset = bx0EmCandOffsets.at(iCat);
161  if(!findBx0OffsetInCollection(offset, cands)) { LogDebug("GCT") << "No EM candidates with bx=0!\nAborting packing of GCT EM Cand and Energy Sum Output!"; return; }
162  if((cands->size()-offset) < 4) { LogDebug("GCT") << "Insufficient EM candidates with bx=0!\nAborting packing of GCT EM Cand and Energy Sum Output!"; return; }
163  }
164 
165  unsigned bx0EtTotalOffset, bx0EtHadOffset, bx0EtMissOffset;
166  if(!findBx0OffsetInCollection(bx0EtTotalOffset, etTotal)) { LogDebug("GCT") << "No Et Total value for bx=0!\nAborting packing of GCT EM Cand and Energy Sum Output!"; return; }
167  if(!findBx0OffsetInCollection(bx0EtHadOffset, etHad)) { LogDebug("GCT") << "No Et Hadronic value for bx=0!\nAborting packing of GCT EM Cand and Energy Sum Output!"; return; }
168  if(!findBx0OffsetInCollection(bx0EtMissOffset, etMiss)) { LogDebug("GCT") << "No Et Miss value for bx=0!\nAborting packing of GCT EM Cand and Energy Sum Output!"; return; }
169 
170  // We should now have all requisite data, so we can get on with packing
171 
172  unsigned nSamples = 1; // ** NOTE can only currenly do 1 timesample! **
173 
174  // write header
175  writeRawHeader(d, 0x683, nSamples);
176 
177  d=d+4; // move to the block payload.
178 
179  // FIRST DO EM CANDS
180 
181  // re-interpret payload pointer to 16 bit.
182  uint16_t * p16 = reinterpret_cast<uint16_t *>(d);
183 
184  for (unsigned iCat=0; iCat < NUM_EM_CAND_CATEGORIES; ++iCat) // loop over non-iso/iso candidates categories
185  {
186  const L1GctEmCandCollection * em = emCands.at(iCat); // The current category of EM cands.
187  const unsigned bx0Offset = bx0EmCandOffsets.at(iCat); // The offset in the EM cand collection to the bx=0 cands.
188 
189  uint16_t * cand = p16 + (iCat*4);
190 
191  *cand = em->at(bx0Offset).raw();
192  cand++;
193  *cand = em->at(bx0Offset + 2).raw();
194  cand += nSamples;
195  *cand = em->at(bx0Offset + 1).raw();
196  cand++;
197  *cand = em->at(bx0Offset + 3).raw();
198  }
199 
200  // NOW DO ENERGY SUMS
201  // assumes these are all 1-object collections, ie. central BX only
202  p16+=8; // Move past EM cands
203  *p16 = etTotal->at(bx0EtTotalOffset).raw(); // Et Total - 16 bits.
204  p16++;
205  *p16 = etHad->at(bx0EtHadOffset).raw(); // Et Hadronic - next 16 bits
206  p16++;
207  uint32_t * p32 = reinterpret_cast<uint32_t *>(p16); // For writing Missing Et (32-bit raw data)
208  *p32 = etMiss->at(bx0EtMissOffset).raw(); // Et Miss on final 32 bits of block payload.
209 }
210 
212  const L1GctJetCandCollection* cenJets,
213  const L1GctJetCandCollection* forJets,
214  const L1GctJetCandCollection* tauJets,
215  const L1GctHFRingEtSumsCollection* hfRingSums,
216  const L1GctHFBitCountsCollection* hfBitCounts,
217  const L1GctHtMissCollection* htMiss)
218 {
219  // Set up a vector of the collections for easy iteration.
220  vector<const L1GctJetCandCollection*> jets(NUM_JET_CATEGORIES);
221  jets.at(CENTRAL_JETS)=cenJets;
222  jets.at(FORWARD_JETS)=forJets;
223  jets.at(TAU_JETS)=tauJets;
224 
225  /* To hold the offsets within the three jet cand collections for the bx=0 jets.
226  * The capture index doesn't seem to get set properly by the emulator, so take the
227  * first bx=0 jet as the highest energy jet, and the fourth as the lowest. */
228  vector<unsigned> bx0JetCandOffsets(NUM_JET_CATEGORIES);
229 
230  // Loop over the different catagories of jets to find the bx=0 offsets.
231  for(unsigned int iCat = 0 ; iCat < NUM_JET_CATEGORIES ; ++iCat)
232  {
233  const L1GctJetCandCollection * jetCands = jets.at(iCat);
234  unsigned& offset = bx0JetCandOffsets.at(iCat);
235  if(!findBx0OffsetInCollection(offset, jetCands)) { LogDebug("GCT") << "No jet candidates with bx=0!\nAborting packing of GCT Jet Output!"; return; }
236  if((jetCands->size()-offset) < 4) { LogDebug("GCT") << "Insufficient jet candidates with bx=0!\nAborting packing of GCT Jet Output!"; return; }
237  }
238 
239  // Now find the collection offsets for the HfRingSums, HfBitCounts, and HtMiss with bx=0
240  unsigned bx0HfRingSumsOffset, bx0HfBitCountsOffset, bx0HtMissOffset;
241  if(!findBx0OffsetInCollection(bx0HfRingSumsOffset, hfRingSums)) { LogDebug("GCT") << "No ring sums with bx=0!\nAborting packing of GCT Jet Output!"; return; }
242  if(!findBx0OffsetInCollection(bx0HfBitCountsOffset, hfBitCounts)) { LogDebug("GCT") << "No bit counts with bx=0!\nAborting packing of GCT Jet Output!"; return; }
243  if(!findBx0OffsetInCollection(bx0HtMissOffset, htMiss)) { LogDebug("GCT") << "No missing Ht with bx=0!\nAborting packing of GCT Jet Output!"; return; }
244 
245  // Now write the header, as we should now have all requisite data.
246  writeRawHeader(d, 0x583, 1); // ** NOTE can only currenly do 1 timesample! **
247 
248  d=d+4; // move forward past the block header to the block payload.
249 
250  // FIRST DO JET CANDS
251  // re-interpret pointer to 16 bits - the space allocated for each Jet candidate.
252  uint16_t * p16 = reinterpret_cast<uint16_t *>(d);
253 
254  const unsigned categoryOffset = 4; // Offset to jump from one jet category to the next.
255  const unsigned nextCandPairOffset = 2; // Offset to jump to next candidate pair.
256 
257  // Loop over the different catagories of jets
258  for(unsigned iCat = 0 ; iCat < NUM_JET_CATEGORIES ; ++iCat)
259  {
260  const L1GctJetCandCollection * jetCands = jets.at(iCat); // The current category of jet cands.
261  const unsigned cand0Offset = iCat*categoryOffset; // the offset on p16 to get the rank 0 Jet Cand of the correct category.
262  const unsigned bx0Offset = bx0JetCandOffsets.at(iCat); // The offset in the jet cand collection to the bx=0 jets.
263 
264  p16[cand0Offset] = jetCands->at(bx0Offset).raw(); // rank 0 jet in bx=0
265  p16[cand0Offset + nextCandPairOffset] = jetCands->at(bx0Offset + 1).raw(); // rank 1 jet in bx=0
266  p16[cand0Offset + 1] = jetCands->at(bx0Offset + 2).raw(); // rank 2 jet in bx=0
267  p16[cand0Offset + nextCandPairOffset + 1] = jetCands->at(bx0Offset + 3).raw(); // rank 3 jet in bx=0.
268  }
269 
270  // NOW DO JET COUNTS
271  d=d+24; // move forward past the jet cands to the jet counts section
272 
273  // re-interpret pointer to 32 bit.
274  uint32_t * p32 = reinterpret_cast<uint32_t *>(d);
275 
276  uint32_t tmp = hfBitCounts->at(bx0HfBitCountsOffset).raw() & 0xfff;
277  tmp |= hfRingSums->at(bx0HfRingSumsOffset).etSum(0)<<12;
278  tmp |= hfRingSums->at(bx0HfRingSumsOffset).etSum(1)<<16;
279  tmp |= hfRingSums->at(bx0HfRingSumsOffset).etSum(2)<<19;
280  tmp |= hfRingSums->at(bx0HfRingSumsOffset).etSum(3)<<22;
281  p32[0] = tmp;
282 
283  const L1GctHtMiss& bx0HtMiss = htMiss->at(bx0HtMissOffset);
284  uint32_t htMissRaw = 0x5555c000 |
285  (bx0HtMiss.overFlow() ? 0x1000 : 0x0000) |
286  ((bx0HtMiss.et() & 0x7f) << 5) |
287  ((bx0HtMiss.phi() & 0x1f));
288 
289  p32[1] = htMissRaw;
290 }
291 
293 {
294  // This method is one giant "temporary" hack for CMSSW_1_8_X and CMSSW_2_0_0.
295 
296  if(rctEm->size() == 0 || rctEm->size()%144 != 0) // Should be 18 crates * 2 types (iso/noniso) * 4 electrons = 144 for 1 bx.
297  {
298  LogDebug("GCT") << "Block pack error: bad L1CaloEmCollection size detected!\n"
299  << "Aborting packing of RCT EM Cand data!";
300  return;
301  }
302 
303  // Need 18 sets of EM fibre data, since 18 RCT crates
304  SourceCardRouting::EmuToSfpData emuToSfpData[18];
305 
306  // Fill in the input arrays with the data from the digi
307  for(unsigned i=0, size=rctEm->size(); i < size ; ++i)
308  {
309  const L1CaloEmCand &cand = rctEm->at(i);
310  if(cand.bx() != 0) { continue; } // Only interested in bunch crossing zero for now!
311  unsigned crateNum = cand.rctCrate();
312  unsigned index = cand.index();
313 
314  // Some error checking.
315  assert(crateNum < 18); // Only 18 RCT crates!
316  assert(index < 4); // Should only be 4 cands of each type per crate!
317 
318  if(cand.isolated())
319  {
320  emuToSfpData[crateNum].eIsoRank[index] = cand.rank();
321  emuToSfpData[crateNum].eIsoCardId[index] = cand.rctCard();
322  emuToSfpData[crateNum].eIsoRegionId[index] = cand.rctRegion();
323  }
324  else
325  {
326  emuToSfpData[crateNum].eNonIsoRank[index] = cand.rank();
327  emuToSfpData[crateNum].eNonIsoCardId[index] = cand.rctCard();
328  emuToSfpData[crateNum].eNonIsoRegionId[index] = cand.rctRegion();
329  }
330  // Note doing nothing with the MIP bit and Q bit arrays as we are not
331  // interested in them; these arrays will contain uninitialised junk
332  // and so you will get out junk for sourcecard output 0 - I.e. don't
333  // trust sfp[0][0] or sfp[1][0] output!.
334  }
335 
336  // Now run the conversion
337  for(unsigned c = 0 ; c < 18 ; ++c)
338  {
339  srcCardRouting().EMUtoSFP(emuToSfpData[c].eIsoRank, emuToSfpData[c].eIsoCardId, emuToSfpData[c].eIsoRegionId,
340  emuToSfpData[c].eNonIsoRank, emuToSfpData[c].eNonIsoCardId, emuToSfpData[c].eNonIsoRegionId,
341  emuToSfpData[c].mipBits, emuToSfpData[c].qBits, emuToSfpData[c].sfp);
342  }
343 
344  // Now pack up the data into the RAW format.
345  for(auto blockStartCrateIter = rctEmCrateMap().begin() ; blockStartCrateIter != rctEmCrateMap().end() ; ++blockStartCrateIter)
346  {
347  unsigned blockId = blockStartCrateIter->first;
348  unsigned startCrate = blockStartCrateIter->second;
349  auto found = blockLengthMap().find(blockId);
350  //assert(found != blockLengthMap().end());
351  unsigned blockLength_32bit = found->second;
352 
353 
354  writeRawHeader(d, blockId, 1);
355  d+=4; // move past header.
356 
357  // Want a 16 bit pointer to push the 16 bit data in.
358  uint16_t * p16 = reinterpret_cast<uint16_t *>(const_cast<unsigned char *>(d));
359 
360  for(unsigned iCrate=startCrate, end=startCrate + blockLength_32bit/3 ; iCrate < end ; ++iCrate)
361  {
362  for(unsigned iOutput = 1 ; iOutput < 4 ; ++iOutput) // skipping output 0 as that is Q-bit/MIP-bit data.
363  {
364  for(unsigned iCycle = 0 ; iCycle < 2 ; ++iCycle)
365  {
366  *p16 = emuToSfpData[iCrate].sfp[iCycle][iOutput];
367  ++p16;
368  }
369  }
370  }
371 
372  // Now move d onto the location of the next block header
373  d+=(blockLength_32bit*4);
374  }
375 }
376 
378 {
379  // This method is one giant "temporary" hack for CMSSW_1_8_X and CMSSW_2_0_0.
380 
381  if(rctCalo->size() == 0 || rctCalo->size()%396 != 0) // Should be 396 calo regions for 1 bx.
382  {
383  LogDebug("GCT") << "Block pack error: bad L1CaloRegionCollection size detected!\n"
384  << "Aborting packing of RCT Calo Region data!";
385  return;
386  }
387 
388  writeRawHeader(d, 0x0ff, 1);
389  d+=4; // move past header.
390 
391  // Want a 16 bit pointer to push the 16 bit data in.
392  uint16_t * p16 = reinterpret_cast<uint16_t *>(const_cast<unsigned char *>(d));
393 
394  for(unsigned i=0, size=rctCalo->size(); i < size ; ++i)
395  {
396  const L1CaloRegion &reg = rctCalo->at(i);
397  if(reg.bx() != 0) { continue; } // Only interested in bunch crossing zero for now!
398  const unsigned crateNum = reg.rctCrate();
399  const unsigned regionIndex = reg.rctRegionIndex();
400  assert(crateNum < 18); // Only 18 RCT crates!
401 
402  // Gotta make the raw data as there currently isn't a method of getting raw from L1CaloRegion
403  const uint16_t raw = reg.et() |
404  (reg.overFlow() ? 0x400 : 0x0) |
405  (reg.fineGrain() ? 0x800 : 0x0) |
406  (reg.mip() ? 0x1000 : 0x0) |
407  (reg.quiet() ? 0x2000 : 0x0);
408 
409  unsigned offset = 0; // for storing calculated raw data offset.
410  if(reg.isHbHe()) // Is a barrel/endcap region
411  {
412  const unsigned cardNum = reg.rctCard();
413  assert(cardNum < 7); // 7 RCT cards per crate for the barrel/endcap
414  assert(regionIndex < 2); // regionIndex less than 2 for barrel/endcap
415 
416  // Calculate position in the raw data from crateNum, cardNum, and regionIndex
417  offset = crateNum*22 + cardNum*2 + regionIndex;
418  }
419  else // Must be forward region
420  {
421  assert(regionIndex < 8); // regionIndex less than 8 for forward calorimeter.
422  offset = crateNum*22 + 14 + regionIndex;
423  }
424  p16[offset] = raw; // Write raw data in correct place!
425  }
426 }
427 
428 
429 // PROTECTED METHODS
430 
431 uint32_t GctFormatTranslateMCLegacy::generateRawHeader(const uint32_t blockId,
432  const uint32_t nSamples,
433  const uint32_t bxId,
434  const uint32_t eventId) const
435 {
436  // Bit mapping of header:
437  // ----------------------
438  // 11:0 => block_id Unique pipeline identifier.
439  // - 3:0 =>> pipe_id There can be up to 16 different pipelines per FPGA.
440  // - 6:4 =>> reserved Do not use yet. Set to zero.
441  // - 11:7 =>> fpga geograpical add The VME geographical address of the FPGA.
442  // 15:12 => event_id Determined locally. Not reset by Resync.
443  // 19:16 => number_of_time_samples If time samples 15 or more then value = 15.
444  // 31:20 => event_bxId The bunch crossing the data was recorded.
445 
446  return ((bxId & 0xfff) << 20) | ((nSamples & 0xf) << 16) | ((eventId & 0xf) << 12) | (blockId & 0xfff);
447 }
448 
449 
450 // PRIVATE METHODS
451 
452 // Output EM Candidates unpacking
454 {
455  const unsigned int id = hdr.blockId();
456  const unsigned int nSamples = hdr.nSamples();
457 
458  // Re-interpret pointer. p16 will be pointing at the 16 bit word that
459  // contains the rank0 non-isolated electron of the zeroth time-sample.
460  const uint16_t * p16 = reinterpret_cast<const uint16_t *>(d);
461 
462  // UNPACK EM CANDS
463 
464  const unsigned int emCandCategoryOffset = nSamples * 4; // Offset to jump from the non-iso electrons to the isolated ones.
465  const unsigned int timeSampleOffset = nSamples * 2; // Offset to jump to next candidate pair in the same time-sample.
466 
467  unsigned int samplesToUnpack = 1;
468  if(!hltMode()) { samplesToUnpack = nSamples; } // Only if not running in HLT mode do we want more than 1 timesample.
469 
470  for (unsigned int iso=0; iso<2; ++iso) // loop over non-iso/iso candidate pairs
471  {
472  bool isoFlag = (iso==1);
473 
474  // Get the correct collection to put them in.
476  if (isoFlag) { em = colls()->gctIsoEm(); }
477  else { em = colls()->gctNonIsoEm(); }
478 
479  for (unsigned int bx=0; bx<samplesToUnpack; ++bx) // loop over time samples
480  {
481  // cand0Offset will give the offset on p16 to get the rank 0 candidate
482  // of the correct category and timesample.
483  const unsigned int cand0Offset = iso*emCandCategoryOffset + bx*2;
484 
485  em->push_back(L1GctEmCand(p16[cand0Offset], isoFlag, id, 0, bx)); // rank0 electron
486  em->push_back(L1GctEmCand(p16[cand0Offset + timeSampleOffset], isoFlag, id, 1, bx)); // rank1 electron
487  em->push_back(L1GctEmCand(p16[cand0Offset + 1], isoFlag, id, 2, bx)); // rank2 electron
488  em->push_back(L1GctEmCand(p16[cand0Offset + timeSampleOffset + 1], isoFlag, id, 3, bx)); // rank3 electron
489  }
490  }
491 
492  p16 += emCandCategoryOffset * 2; // Move the pointer over the data we've already unpacked.
493 
494  // UNPACK ENERGY SUMS
495  // NOTE: we are only unpacking one timesample of these currently!
496 
497  colls()->gctEtTot()->push_back(L1GctEtTotal(p16[0])); // Et total (timesample 0).
498  colls()->gctEtHad()->push_back(L1GctEtHad(p16[1])); // Et hadronic (timesample 0).
499 
500  // 32-bit pointer for getting Missing Et.
501  const uint32_t * p32 = reinterpret_cast<const uint32_t *>(p16);
502 
503  colls()->gctEtMiss()->push_back(L1GctEtMiss(p32[nSamples])); // Et Miss (timesample 0).
504 }
505 
507 {
508  const unsigned int id = hdr.blockId(); // Capture block ID.
509  const unsigned int nSamples = hdr.nSamples(); // Number of time-samples.
510 
511  // Re-interpret block payload pointer to 16 bits so it sees one candidate at a time.
512  // p16 points to the start of the block payload, at the rank0 tau jet candidate.
513  const uint16_t * p16 = reinterpret_cast<const uint16_t *>(d);
514 
515  // UNPACK JET CANDS
516 
517  const unsigned int jetCandCategoryOffset = nSamples * 4; // Offset to jump from one jet category to the next.
518  const unsigned int timeSampleOffset = nSamples * 2; // Offset to jump to next candidate pair in the same time-sample.
519 
520  unsigned int samplesToUnpack = 1;
521  if(!hltMode()) { samplesToUnpack = nSamples; } // Only if not running in HLT mode do we want more than 1 timesample.
522 
523  // Loop over the different catagories of jets
524  for(unsigned int iCat = 0 ; iCat < NUM_JET_CATEGORIES ; ++iCat)
525  {
526  L1GctJetCandCollection * const jets = gctJets(iCat);
527  assert(jets->empty()); // The supplied vector should be empty.
528 
529  bool tauflag = (iCat == TAU_JETS);
530  bool forwardFlag = (iCat == FORWARD_JETS);
531 
532  // Loop over the different timesamples (bunch crossings).
533  for(unsigned int bx = 0 ; bx < samplesToUnpack ; ++bx)
534  {
535  // cand0Offset will give the offset on p16 to get the rank 0 Jet Cand of the correct category and timesample.
536  const unsigned int cand0Offset = iCat*jetCandCategoryOffset + bx*2;
537 
538  // Rank 0 Jet.
539  jets->push_back(L1GctJetCand(p16[cand0Offset], tauflag, forwardFlag, id, 0, bx));
540  // Rank 1 Jet.
541  jets->push_back(L1GctJetCand(p16[cand0Offset + timeSampleOffset], tauflag, forwardFlag, id, 1, bx));
542  // Rank 2 Jet.
543  jets->push_back(L1GctJetCand(p16[cand0Offset + 1], tauflag, forwardFlag, id, 2, bx));
544  // Rank 3 Jet.
545  jets->push_back(L1GctJetCand(p16[cand0Offset + timeSampleOffset + 1], tauflag, forwardFlag, id, 3, bx));
546  }
547  }
548 
549  p16 += NUM_JET_CATEGORIES * jetCandCategoryOffset; // Move the pointer over the data we've already unpacked.
550 
551  // NOW UNPACK: HFBitCounts, HFRingEtSums and Missing Ht
552  // NOTE: we are only unpacking one timesample of these currently!
553 
554  // Re-interpret block payload pointer to 32 bits so it sees six jet counts at a time.
555  const uint32_t * p32 = reinterpret_cast<const uint32_t *>(p16);
556 
557  // Channel 0 carries both HF counts and sums
558  colls()->gctHfBitCounts()->push_back(L1GctHFBitCounts::fromConcHFBitCounts(id,6,0,p32[0]));
559  colls()->gctHfRingEtSums()->push_back(L1GctHFRingEtSums::fromConcRingSums(id,6,0,p32[0]));
560 
561  // Channel 1 carries Missing HT.
562  colls()->gctHtMiss()->push_back(L1GctHtMiss(p32[nSamples], 0));
563 }
564 
565 // Input EM Candidates unpacking
566 // this is the last time I deal the RCT bit assignment travesty!!!
567 void GctFormatTranslateMCLegacy::blockToRctEmCand(const unsigned char * d, const GctBlockHeader& hdr)
568 {
569  // Don't want to do this in HLT optimisation mode!
570  if(hltMode()) { LogDebug("GCT") << "HLT mode - skipping unpack of RCT EM Cands"; return; }
571 
572  unsigned int id = hdr.blockId();
573  unsigned int nSamples = hdr.nSamples();
574  unsigned int length = hdr.blockLength();
575 
576  // re-interpret pointer
577  uint16_t * p = reinterpret_cast<uint16_t *>(const_cast<unsigned char *>(d));
578 
579  // arrays of source card data
580  uint16_t sfp[2][4]; // [ cycle ] [ SFP ]
581  uint16_t eIsoRank[4];
582  uint16_t eIsoCard[4];
583  uint16_t eIsoRgn[4];
584  uint16_t eNonIsoRank[4];
585  uint16_t eNonIsoCard[4];
586  uint16_t eNonIsoRgn[4];
587  uint16_t MIPbits[7][2];
588  uint16_t QBits[7][2];
589 
590  unsigned int bx = 0;
591 
592  // loop over crates
593  auto found = rctEmCrateMap().find(id);
594  assert(found != rctEmCrateMap().end());
595  for (unsigned int crate=found->second; crate<found->second+length/3; ++crate) {
596 
597  // read SC SFP words
598  for (unsigned short iSfp=0 ; iSfp<4 ; ++iSfp) {
599  for (unsigned short cyc=0 ; cyc<2 ; ++cyc) {
600  if (iSfp==0) { sfp[cyc][iSfp] = 0; } // muon bits
601  else { // EM candidate
602  sfp[cyc][iSfp] = *p;
603  ++p;
604  }
605  }
606  p = p + 2*(nSamples-1);
607  }
608 
609  // fill SC arrays
610  srcCardRouting().SFPtoEMU(eIsoRank, eIsoCard, eIsoRgn, eNonIsoRank, eNonIsoCard, eNonIsoRgn, MIPbits, QBits, sfp);
611 
612  // create EM cands
613  for (unsigned short int i=0; i<4; ++i) {
614  colls()->rctEm()->push_back( L1CaloEmCand( eIsoRank[i], eIsoRgn[i], eIsoCard[i], crate, true, i, bx) );
615  }
616  for (unsigned short int i=0; i<4; ++i) {
617  colls()->rctEm()->push_back( L1CaloEmCand( eNonIsoRank[i], eNonIsoRgn[i], eNonIsoCard[i], crate, false, i, bx) );
618  }
619  }
620 }
621 
622 // Fibre unpacking
623 void GctFormatTranslateMCLegacy::blockToFibres(const unsigned char * d, const GctBlockHeader& hdr)
624 {
625  // Don't want to do this in HLT optimisation mode!
626  if(hltMode()) { LogDebug("GCT") << "HLT mode - skipping unpack of GCT Fibres"; return; }
627 
628  unsigned int id = hdr.blockId();
629  unsigned int nSamples = hdr.nSamples();
630  unsigned int length = hdr.blockLength();
631 
632  // re-interpret pointer
633  uint32_t * p = reinterpret_cast<uint32_t *>(const_cast<unsigned char *>(d));
634 
635  for (unsigned int i=0; i<length; ++i) {
636  for (unsigned int bx=0; bx<nSamples; ++bx) {
637  colls()->gctFibres()->push_back( L1GctFibreWord(*p, id, i, bx) );
638  ++p;
639  }
640  }
641 }
642 
644 {
645  this->blockToRctEmCand(d, hdr);
646  this->blockToFibres(d, hdr);
647 }
648 
650 {
651  // Don't want to do this in HLT optimisation mode!
652  if(hltMode()) { LogDebug("GCT") << "HLT mode - skipping unpack of RCT Calo Regions"; return; }
653 
654  // This method is one giant "temporary" hack whilst waiting for proper
655  // pipeline formats for the RCT calo region data.
656 
657  const int nSamples = hdr.nSamples(); // Number of time-samples.
658 
659  // Re-interpret block payload pointer to 16 bits
660  const uint16_t * p16 = reinterpret_cast<const uint16_t *>(d);
661 
662  for(unsigned iCrate = 0 ; iCrate < 18 ; ++iCrate)
663  {
664  // Barrel and endcap regions
665  for(unsigned iCard = 0 ; iCard < 7 ; ++iCard)
666  {
667  // Samples
668  for(int16_t iSample = 0 ; iSample < nSamples ; ++iSample)
669  {
670  // Two regions per card (and per 32-bit word).
671  for(unsigned iRegion = 0 ; iRegion < 2 ; ++iRegion)
672  {
673  L1CaloRegionDetId id(iCrate, iCard, iRegion);
674  colls()->rctCalo()->push_back(L1CaloRegion(*p16, id.ieta(), id.iphi(), iSample));
675  ++p16; //advance pointer
676  }
677  }
678  }
679  // Forward regions (8 regions numbered 0 through 7, packed in 4 sets of pairs)
680  for(unsigned iRegionPairNum = 0 ; iRegionPairNum < 4 ; ++iRegionPairNum)
681  {
682  // Samples
683  for(int16_t iSample = 0 ; iSample < nSamples ; ++iSample)
684  {
685  // two regions in a pair
686  for(unsigned iPair = 0 ; iPair < 2 ; ++iPair)
687  {
688  // For forward regions, RCTCard=999
689  L1CaloRegionDetId id(iCrate, 999, iRegionPairNum*2 + iPair);
690  colls()->rctCalo()->push_back(L1CaloRegion(*p16, id.ieta(), id.iphi(), iSample));
691  ++p16; //advance pointer
692  }
693  }
694  }
695  }
696 }
697 
698 template <typename Collection>
699 bool GctFormatTranslateMCLegacy::findBx0OffsetInCollection(unsigned& bx0Offset, const Collection* coll)
700 {
701  bool foundBx0 = false;
702  unsigned size = coll->size();
703  for(bx0Offset = 0 ; bx0Offset < size ; ++bx0Offset)
704  {
705  if(coll->at(bx0Offset).bx() == 0) { foundBx0 = true; break; }
706  }
707  return foundBx0;
708 }
#define LogDebug(id)
size
Write out results.
int16_t bx() const
get bunch-crossing index
Definition: L1CaloRegion.h:192
void writeGctOutEmAndEnergyBlock(unsigned char *d, const L1GctEmCandCollection *iso, const L1GctEmCandCollection *nonIso, const L1GctEtTotalCollection *etTotal, const L1GctEtHadCollection *etHad, const L1GctEtMissCollection *etMiss)
Writes GCT output EM and energy sums block into an unsigned char array, starting at the position poin...
L1GctHFBitCountsCollection *const gctHfBitCounts() const
GCT output: Hadronic-Forward bit-counts collection.
std::vector< L1CaloEmCand > L1CaloEmCollection
unsigned et() const
get Et
Definition: L1CaloRegion.h:116
L1GctEmCandCollection *const gctNonIsoEm() const
GCT output: Non-isolated EM candidate collection.
virtual uint32_t generateRawHeader(const uint32_t blockId, const uint32_t nSamples, const uint32_t bxId, const uint32_t eventId) const override
Returns a raw 32-bit header word generated from the blockId, number of time samples, bunch-crossing and event IDs.
void writeAllRctCaloRegionBlock(unsigned char *d, const L1CaloRegionCollection *rctCalo)
Writes the giant hack that is the RCT Calo Regions block.
Global Calorimeter Trigger SC -> CC fibre data word.
bool overFlow() const
get overflow
Definition: L1CaloRegion.h:122
bool checkBlock(const GctBlockHeader &hdr) const
Performs checks on the block header to see if the block is possible to unpack or not.
L1CaloEmCollection *const rctEm() const
Input electrons from the RCT to the GCT.
std::vector< L1GctEtMiss > L1GctEtMissCollection
unsigned rctCrate() const
get RCT crate ID
Definition: L1CaloRegion.h:165
L1GctHtMissCollection *const gctHtMiss() const
GCT output: Missing Ht collection.
std::vector< L1GctHFRingEtSums > L1GctHFRingEtSumsCollection
unsigned rctCard() const
get RCT reciever card ID (valid output for HB/HE)
Definition: L1CaloRegion.h:168
void blockToFibresAndToRctEmCand(const unsigned char *d, const GctBlockHeader &hdr)
unpack Fibres and RCT EM Candidates
void SFPtoEMU(unsigned short(&eIsoRank)[4], unsigned short(&eIsoCardId)[4], unsigned short(&eIsoRegionId)[4], unsigned short(&eNonIsoRank)[4], unsigned short(&eNonIsoCardId)[4], unsigned short(&eNonIsoRegionId)[4], unsigned short(&MIPbits)[7][2], unsigned short(&Qbits)[7][2], unsigned short(&SFP)[2][4]) const
Struct of all data needed for running the emulator to SFP (sourcecard optical output) conversion...
virtual const BlockLengthMap & blockLengthMap() const override final
get the static block ID to block-length map.
std::vector< L1GctEtHad > L1GctEtHadCollection
void writeRctEmCandBlocks(unsigned char *d, const L1CaloEmCollection *rctEm)
Writes the 4 RCT EM Candidate blocks.
Level-1 Trigger jet candidate.
Definition: L1GctJetCand.h:18
Abstract interface for RawToDigi/DigiToRaw conversions of GCT data.
static const BlockNameMap m_blockName
Map to hold a description for each block number.
Level-1 Region Calorimeter Trigger EM candidate.
Definition: L1CaloEmCand.h:18
void writeRawHeader(unsigned char *data, uint32_t blockId, uint32_t nSamples) const
Writes a raw block header into the raw data array for a given block ID and number of time-samples...
Persistable copy of missing Et measured at Level-1.
Definition: L1GctEtMiss.h:18
const SourceCardRouting & srcCardRouting() const
Protected interface to the unpackSharedRegions commissioning option.
unsigned rctRegionIndex() const
get RCT region index
Definition: L1CaloRegion.h:171
Level-1 Trigger EM candidate at output of GCT.
Definition: L1GctEmCand.h:22
void writeGctOutJetBlock(unsigned char *d, const L1GctJetCandCollection *cenJets, const L1GctJetCandCollection *forJets, const L1GctJetCandCollection *tauJets, const L1GctHFRingEtSumsCollection *hfRingSums, const L1GctHFBitCountsCollection *hfBitCounts, const L1GctHtMissCollection *htMiss)
Writes GCT output jet cands and counts into an unsigned char array, starting at the position pointed ...
virtual bool convertBlock(const unsigned char *d, const GctBlockHeader &hdr) override
Get digis from the block - will return true if it succeeds, false otherwise.
void blockToGctEmCandsAndEnergySums(const unsigned char *d, const GctBlockHeader &hdr)
unpack GCT EM Candidates and energy sums.
std::vector< L1GctEtTotal > L1GctEtTotalCollection
bool quiet() const
get quiet bit
Definition: L1CaloRegion.h:134
void EMUtoSFP(unsigned short(&eIsoRank)[4], unsigned short(&eIsoCardId)[4], unsigned short(&eIsoRegionId)[4], unsigned short(&eNonIsoRank)[4], unsigned short(&eNonIsoCardId)[4], unsigned short(&eNonIsoRegionId)[4], unsigned short(&MIPbits)[7][2], unsigned short(&Qbits)[7][2], unsigned short(&SFP)[2][4]) const
virtual const BlkToRctCrateMap & rctEmCrateMap() const override final
get static the block ID to RCT crate map for electrons.
std::vector< L1GctHFBitCounts > L1GctHFBitCountsCollection
U second(std::pair< T, U > const &p)
std::vector< L1GctJetCand > L1GctJetCandCollection
GctFormatTranslateMCLegacy(bool hltMode=false, bool unpackSharedRegions=false)
Constructor.
static const BlockLengthMap m_blockLength
Map to translate block number to fundamental size of a block (i.e. for 1 time-sample).
L1GctEtTotalCollection *const gctEtTot() const
GCT output: Total Et collection.
GctUnpackCollections *const colls() const
Protected access to the GCT Unpack Collections.
bool overFlow() const
get the overflow
Definition: L1GctHtMiss.h:63
Persistable copy of total Et measured at Level-1.
Definition: L1GctEtTotal.h:18
virtual GctBlockHeader generateBlockHeader(const unsigned char *data) const override
Generate a block header from four 8-bit values.
unsigned rctCrate() const
get RCT crate
Definition: L1CaloEmCand.h:53
Simple class for holding the basic attributes of an 32-bit block header.
bool isolated() const
which stream did this come from
Definition: L1CaloEmCand.h:56
vector< PseudoJet > jets
int16_t bx() const
get bunch-crossing index
Definition: L1CaloEmCand.h:62
bool mip() const
get MIP bit
Definition: L1CaloRegion.h:131
unsigned rank() const
get rank bits
Definition: L1CaloEmCand.h:44
unsigned rctCard() const
get RCT receiver card
Definition: L1CaloEmCand.h:47
void blockToRctEmCand(const unsigned char *d, const GctBlockHeader &hdr)
unpack RCT EM Candidates
unsigned et() const
get the magnitude
Definition: L1GctHtMiss.h:60
L1GctEtMissCollection *const gctEtMiss() const
GCT output: Missing Et collection.
bool isHbHe() const
Definition: L1CaloRegion.h:162
#define end
Definition: vmac.h:37
std::map< unsigned int, unsigned int > BlockLengthMap
Block ID to Block Length map.
void blockDoNothing(const unsigned char *d, const GctBlockHeader &hdr)
The null unpack function - obviously common to all formats.
bool hltMode() const
Protected interface to get HLT optimisation mode flag.
constexpr size_t nSamples
Persistable copy of total Ht measured at Level-1.
Definition: L1GctEtHad.h:18
uint32_t blockLength() const
Get the fundamental block length (for 1 time sample)
static L1GctHFRingEtSums fromConcRingSums(const uint16_t capBlock, const uint16_t capIndex, const int16_t bx, const uint32_t data)
std::vector< L1GctHtMiss > L1GctHtMissCollection
L1GctJetCandCollection *const gctJets(const unsigned cat) const
Get a specific jet candandiate collection using the JetCandCategory enumeration.
void blockToGctJetCandsAndCounts(const unsigned char *d, const GctBlockHeader &hdr)
Unpack GCT Jet Candidates and jet counts.
JetCorrectorParametersCollection coll
Definition: classes.h:10
L1GctHFRingEtSumsCollection *const gctHfRingEtSums() const
GCT output: Hadronic-Forward ring-sums collection.
Persistable copy of missing Et measured at Level-1.
Definition: L1GctHtMiss.h:16
bool fineGrain() const
get fine grain bit
Definition: L1CaloRegion.h:128
static const BlkToRctCrateMap m_rctJetCrate
Map to relate capture block ID to the RCT crate the data originated from (for jets).
unsigned index() const
get index on cable
Definition: L1CaloEmCand.h:59
static const BlockIdToUnpackFnMap m_blockUnpackFn
Block ID to unpack function map.
std::vector< std::vector< double > > tmp
Definition: MVATrainer.cc:100
L1GctFibreCollection *const gctFibres() const
Raw fibre input to the GCT.
L1GctEmCandCollection *const gctIsoEm() const
GCT output: Isolated EM candidate collection.
#define begin
Definition: vmac.h:30
unsigned rctRegion() const
get RCT region ID
Definition: L1CaloEmCand.h:50
char data[epos_bytes_allocation]
Definition: EPOS_Wrapper.h:82
L1GctEtHadCollection *const gctEtHad() const
GCT output: Hadronic transverse-energy (Ht) collection.
A calorimeter trigger region (sum of 4x4 trigger towers)
Definition: L1CaloRegion.h:22
static L1GctHFBitCounts fromConcHFBitCounts(const uint16_t capBlock, const uint16_t capIndex, const int16_t bx, const uint32_t data)
void blockToFibres(const unsigned char *d, const GctBlockHeader &hdr)
unpack Fibres
static const BlkToRctCrateMap m_rctEmCrate
Map to relate capture block ID to the RCT crate the data originated from (for electrons).
std::map< unsigned int, IsoBoundaryPair > BlockIdToEmCandIsoBoundMap
A typdef for mapping Block IDs to IsoBoundaryPairs.
std::vector< L1CaloRegion > L1CaloRegionCollection
uint32_t blockId() const
Get the block ID.
std::map< unsigned int, unsigned int > BlkToRctCrateMap
Typedef for mapping block ID to RCT crate.
std::map< unsigned int, std::string > BlockNameMap
Block ID to Block Description map.
virtual ~GctFormatTranslateMCLegacy()
Destructor.
std::map< unsigned int, PtrToUnpackFn > BlockIdToUnpackFnMap
Typedef for a block ID to unpack function map.
bool findBx0OffsetInCollection(unsigned &bx0Offset, const Collection *coll)
Template function (used in packing) that will find the offset to first item in a collection vector wh...
uint32_t nSamples() const
Get the number of time samples.
void blockToAllRctCaloRegions(const unsigned char *d, const GctBlockHeader &hdr)
Unpack All RCT Calo Regions (&#39;orrible hack for DigiToRaw use)
static const BlockIdToEmCandIsoBoundMap m_internEmIsoBounds
unsigned phi() const
get the Et
Definition: L1GctHtMiss.h:66
L1CaloRegionCollection *const rctCalo() const
Input calo regions from the RCT to the GCT.
std::vector< L1GctEmCand > L1GctEmCandCollection