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