CMS 3D CMS Logo

HcalTriggerPrimitiveAlgo.cc
Go to the documentation of this file.
2 
6 
10 
13 
16 
18 
19 #include <iostream>
20 
21 using namespace std;
22 
24  const std::vector<double>& w,
25  int latency,
26  uint32_t FG_threshold,
27  const std::vector<uint32_t>& FG_HF_thresholds,
28  uint32_t ZS_threshold,
29  int numberOfSamples,
35  int numberOfSamplesZDC,
36  int numberOfPresamplesZDC,
38  uint32_t minSignalThreshold,
39  uint32_t PMT_NoiseThreshold)
40  : incoder_(nullptr),
41  outcoder_(nullptr),
42  theThreshold(0),
43  peakfind_(pf),
44  weights_(w),
45  latency_(latency),
46  FG_threshold_(FG_threshold),
47  FG_HF_thresholds_(FG_HF_thresholds),
48  ZS_threshold_(ZS_threshold),
49  numberOfSamples_(numberOfSamples),
50  numberOfPresamples_(numberOfPresamples),
51  numberOfFilterPresamplesHBQIE11_(numberOfFilterPresamplesHBQIE11),
52  numberOfFilterPresamplesHEQIE11_(numberOfFilterPresamplesHEQIE11),
53  numberOfSamplesHF_(numberOfSamplesHF),
54  numberOfPresamplesHF_(numberOfPresamplesHF),
55  numberOfSamplesZDC_(numberOfSamplesZDC),
56  numberOfPresamplesZDC_(numberOfPresamplesZDC),
57  useTDCInMinBiasBits_(useTDCInMinBiasBits),
58  minSignalThreshold_(minSignalThreshold),
59  PMT_NoiseThreshold_(PMT_NoiseThreshold),
60  NCTScaleShift(0),
61  RCTScaleShift(0),
62  peak_finder_algorithm_(2),
63  override_parameters_() {
64  //No peak finding setting (for Fastsim)
65  if (!peakfind_) {
66  numberOfSamples_ = 1;
72  }
73  // Switch to integer for comparisons - remove compiler warning
75 }
76 
78 
80  upgrade_hb_ = hb;
81  upgrade_he_ = he;
82  upgrade_hf_ = hf;
83 }
84 
85 void HcalTriggerPrimitiveAlgo::setFixSaturationFlag(bool fix_saturation) { fix_saturation_ = fix_saturation; }
86 
89 
90  if (override_parameters_.exists("ADCThresholdHF")) {
91  override_adc_hf_ = true;
92  override_adc_hf_value_ = override_parameters_.getParameter<uint32_t>("ADCThresholdHF");
93  }
94  if (override_parameters_.exists("TDCMaskHF")) {
95  override_tdc_hf_ = true;
96  override_tdc_hf_value_ = override_parameters_.getParameter<unsigned long long>("TDCMaskHF");
97  }
98 }
99 
101  // TODO: Need to add support for seperate 28, 29 in HE
102  //Hack for 300_pre10, should be removed.
103  if (frame.id().depth() == 5)
104  return;
105 
106  std::vector<HcalTrigTowerDetId> ids = theTrigTowerGeometry->towerIds(frame.id());
107  assert(ids.size() == 1 || ids.size() == 2);
108  IntegerCaloSamples samples1(ids[0], int(frame.size()));
109 
110  samples1.setPresamples(frame.presamples());
111  incoder_->adc2Linear(frame, samples1);
112 
113  std::vector<bool> msb;
114  incoder_->lookupMSB(frame, msb);
115 
116  if (ids.size() == 2) {
117  // make a second trigprim for the other one, and split the energy
118  IntegerCaloSamples samples2(ids[1], samples1.size());
119  for (int i = 0; i < samples1.size(); ++i) {
120  samples1[i] = uint32_t(samples1[i] * 0.5);
121  samples2[i] = samples1[i];
122  }
123  samples2.setPresamples(frame.presamples());
124  addSignal(samples2);
125  addFG(ids[1], msb);
126  }
127  addSignal(samples1);
128  addFG(ids[0], msb);
129 }
130 
132  if (frame.id().depth() == 1 || frame.id().depth() == 2) {
133  std::vector<HcalTrigTowerDetId> ids = theTrigTowerGeometry->towerIds(frame.id());
134  std::vector<HcalTrigTowerDetId>::const_iterator it;
135  for (it = ids.begin(); it != ids.end(); ++it) {
136  HcalTrigTowerDetId trig_tower_id = *it;
137  IntegerCaloSamples samples(trig_tower_id, frame.size());
138  samples.setPresamples(frame.presamples());
140 
141  // Don't add to final collection yet
142  // HF PMT veto sum is calculated in analyzerHF()
143  IntegerCaloSamples zero_samples(trig_tower_id, frame.size());
144  zero_samples.setPresamples(frame.presamples());
145  addSignal(zero_samples);
146 
147  // Pre-LS1 Configuration
148  if (trig_tower_id.version() == 0) {
149  // Mask off depths: fgid is the same for both depths
150  uint32_t fgid = (frame.id().maskDepth());
151 
152  if (theTowerMapFGSum.find(trig_tower_id) == theTowerMapFGSum.end()) {
153  SumFGContainer sumFG;
154  theTowerMapFGSum.insert(std::pair<HcalTrigTowerDetId, SumFGContainer>(trig_tower_id, sumFG));
155  }
156 
157  SumFGContainer& sumFG = theTowerMapFGSum[trig_tower_id];
158  SumFGContainer::iterator sumFGItr;
159  for (sumFGItr = sumFG.begin(); sumFGItr != sumFG.end(); ++sumFGItr) {
160  if (sumFGItr->id() == fgid) {
161  break;
162  }
163  }
164  // If find
165  if (sumFGItr != sumFG.end()) {
166  for (int i = 0; i < samples.size(); ++i) {
167  (*sumFGItr)[i] += samples[i];
168  }
169  } else {
170  //Copy samples (change to fgid)
171  IntegerCaloSamples sumFGSamples(DetId(fgid), samples.size());
172  sumFGSamples.setPresamples(samples.presamples());
173  for (int i = 0; i < samples.size(); ++i) {
174  sumFGSamples[i] = samples[i];
175  }
176  sumFG.push_back(sumFGSamples);
177  }
178 
179  // set veto to true if Long or Short less than threshold
180  if (HF_Veto.find(fgid) == HF_Veto.end()) {
181  vector<bool> vetoBits(samples.size(), false);
182  HF_Veto[fgid] = vetoBits;
183  }
184  for (int i = 0; i < samples.size(); ++i) {
185  if (samples[i] < minSignalThreshold_) {
186  HF_Veto[fgid][i] = true;
187  }
188  }
189  }
190  // HF 1x1
191  else if (trig_tower_id.version() == 1) {
192  uint32_t fgid = (frame.id().maskDepth());
193  HFDetails& details = theHFDetailMap[trig_tower_id][fgid];
194  // Check the frame type to determine long vs short
195  if (frame.id().depth() == 1) { // Long
196  details.long_fiber = samples;
197  details.LongDigi = frame;
198  } else if (frame.id().depth() == 2) { // Short
199  details.short_fiber = samples;
200  details.ShortDigi = frame;
201  } else {
202  // Neither long nor short... So we have no idea what to do
203  edm::LogWarning("HcalTPAlgo") << "Unable to figure out what to do with data frame for " << frame.id();
204  return;
205  }
206  }
207  // Uh oh, we are in a bad/unknown state! Things will start crashing.
208  else {
209  return;
210  }
211  }
212  }
213 }
214 
216  //HcalDetId detId = frame.detid();
217  DetId detId = DetId(frame.detid());
218  if (detId.det() == DetId::Hcal) {
219  HcalDetId detId = frame.detid();
220  // prevent QIE10 calibration channels from entering TP emulation
221  if (detId.subdet() != HcalForward)
222  return;
223 
224  auto ids = theTrigTowerGeometry->towerIds(frame.id());
225  for (const auto& id : ids) {
226  if (id.version() == 0) {
227  edm::LogError("HcalTPAlgo") << "Encountered QIE10 data frame mapped to TP version 0:" << id;
228  continue;
229  }
230  int nsamples = frame.samples();
231 
232  IntegerCaloSamples samples(id, nsamples);
233  samples.setPresamples(frame.presamples());
234  incoder_->adc2Linear(frame, samples, false);
235 
236  // Don't add to final collection yet
237  // HF PMT veto sum is calculated in analyzerHF()
238  IntegerCaloSamples zero_samples(id, nsamples);
239  zero_samples.setPresamples(frame.presamples());
240  addSignal(zero_samples);
241 
242  auto fid = HcalDetId(frame.id());
243  auto& details = theHFUpgradeDetailMap[id][fid.maskDepth()];
244  auto& detail = details[fid.depth() - 1];
245  detail.samples = samples;
246  detail.digi = frame;
247  detail.validity.resize(nsamples);
248  detail.passTDC.resize(nsamples);
249  incoder_->lookupMSB(frame, detail.fgbits);
250  for (int idx = 0; idx < nsamples; ++idx) {
251  detail.validity[idx] = validChannel(frame, idx);
252  detail.passTDC[idx] = passTDC(frame, idx);
253  }
254  }
255  } else if (detId.det() == DetId::Calo && detId.subdetId() == HcalZDCDetId::SubdetectorId) {
256  HcalZDCDetId detId = frame.detid();
257  if (detId.section() != HcalZDCDetId::EM && detId.section() != HcalZDCDetId::HAD) {
258  return;
259  }
260 
261  auto ids = theTrigTowerGeometry->towerIds_ZDC(frame.id());
262  for (const auto& id : ids) {
263  int nsamples = frame.samples();
264 
265  IntegerCaloSamples samples(id, nsamples);
266  IntegerCaloSamples samples_PUsub(id, nsamples);
267 
268  samples.setPresamples(frame.presamples());
269  samples_PUsub.setPresamples(frame.presamples());
270 
271  incoder_->adc2Linear(frame, samples, false);
272  incoder_->adc2Linear(frame, samples_PUsub, true);
273 
274  for (int i = 1; i < samples.size(); ++i) {
275  if (samples_PUsub[i - 1] > samples[i])
276  samples[i] = 0;
277  else
278  samples[i] -= samples_PUsub[i - 1];
279  }
280 
282  }
283  }
284 }
285 
287  HcalDetId detId(frame.id());
288  // prevent QIE11 calibration channels from entering TP emulation
289  if (detId.subdet() != HcalEndcap && detId.subdet() != HcalBarrel)
290  return;
291 
292  std::vector<HcalTrigTowerDetId> ids = theTrigTowerGeometry->towerIds(detId);
293  assert(ids.size() == 1 || ids.size() == 2);
294  IntegerCaloSamples samples1(ids[0], int(frame.samples()));
295 
296  samples1.setPresamples(frame.presamples());
297  incoder_->adc2Linear(frame, samples1);
298 
299  std::vector<std::bitset<2>> msb(frame.samples(), 0);
300  incoder_->lookupMSB(frame, msb);
301 
302  if (ids.size() == 2) {
303  // make a second trigprim for the other one, and share the energy
304  IntegerCaloSamples samples2(ids[1], samples1.size());
305  for (int i = 0; i < samples1.size(); ++i) {
306  samples1[i] = uint32_t(samples1[i]);
307  samples2[i] = samples1[i];
308  }
309  samples2.setPresamples(frame.presamples());
310  addSignal(samples2);
311  addUpgradeFG(ids[1], detId.depth(), msb);
312  addUpgradeTDCFG(ids[1], frame);
313  }
314  addSignal(samples1);
315  addUpgradeFG(ids[0], detId.depth(), msb);
316  addUpgradeTDCFG(ids[0], frame);
317 }
318 
321  SumMap::iterator itr = theSumMap.find(id);
322 
323  if (itr == theSumMap.end()) {
324  theSumMap.insert(std::make_pair(id, samples));
325  } else {
326  // wish CaloSamples had a +=
327  for (int i = 0; i < samples.size(); ++i) {
328  (itr->second)[i] += samples[i];
329  }
330  }
331 
332  // if fix_saturation == true, keep track of tower with saturated input LUT
333  if (fix_saturation_) {
334  SatMap::iterator itr_sat = theSatMap.find(id);
335 
336  assert((itr == theSumMap.end()) == (itr_sat == theSatMap.end()));
337 
338  if (itr_sat == theSatMap.end()) {
339  vector<bool> check_sat;
340  for (int i = 0; i < samples.size(); ++i) {
341  if (!(samples[i] < QIE11_LINEARIZATION_ET)) {
342  check_sat.push_back(true);
343  } else
344  check_sat.push_back(false);
345  }
346  theSatMap.insert(std::make_pair(id, check_sat));
347  } else {
348  for (int i = 0; i < samples.size(); ++i) {
349  if (!(samples[i] < QIE11_LINEARIZATION_ET))
350  (itr_sat->second)[i] = true;
351  }
352  }
353  }
354 }
355 
357  int shrink = weights_.size() - 1;
358  std::vector<bool>& msb = fgMap_[samples.id()];
359  IntegerCaloSamples sum(samples.id(), samples.size());
360 
361  //slide algo window
362  for (int ibin = 0; ibin < int(samples.size()) - shrink; ++ibin) {
363  int algosumvalue = 0;
364  for (unsigned int i = 0; i < weights_.size(); i++) {
365  //add up value * scale factor
366  algosumvalue += int(samples[ibin + i] * weights_[i]);
367  }
368  if (algosumvalue < 0)
369  sum[ibin] = 0; // low-side
370  //high-side
371  //else if (algosumvalue>QIE8_LINEARIZATION_ET) sum[ibin]=QIE8_LINEARIZATION_ET;
372  else
373  sum[ibin] = algosumvalue; //assign value to sum[]
374  }
375 
376  // Align digis and TP
377  int dgPresamples = samples.presamples();
378  int tpPresamples = numberOfPresamples_;
379  int shift = dgPresamples - tpPresamples;
380  int dgSamples = samples.size();
381  int tpSamples = numberOfSamples_;
382  if (peakfind_) {
383  if ((shift < shrink) || (shift + tpSamples + shrink > dgSamples - (peak_finder_algorithm_ - 1))) {
384  edm::LogInfo("HcalTriggerPrimitiveAlgo::analyze")
385  << "TP presample or size from the configuration file is out of the accessible range. Using digi values from "
386  "data instead...";
387  shift = shrink;
388  tpPresamples = dgPresamples - shrink;
389  tpSamples = dgSamples - (peak_finder_algorithm_ - 1) - shrink - shift;
390  }
391  }
392 
393  std::vector<int> finegrain(tpSamples, false);
394 
395  IntegerCaloSamples output(samples.id(), tpSamples);
396  output.setPresamples(tpPresamples);
397 
398  for (int ibin = 0; ibin < tpSamples; ++ibin) {
399  // ibin - index for output TP
400  // idx - index for samples + shift
401  int idx = ibin + shift;
402 
403  //Peak finding
404  if (peakfind_) {
405  bool isPeak = false;
406  switch (peak_finder_algorithm_) {
407  case 1:
408  isPeak = (samples[idx] > samples[idx - 1] && samples[idx] >= samples[idx + 1] && samples[idx] > theThreshold);
409  break;
410  case 2:
411  isPeak = (sum[idx] > sum[idx - 1] && sum[idx] >= sum[idx + 1] && sum[idx] > theThreshold);
412  break;
413  default:
414  break;
415  }
416 
417  if (isPeak) {
418  output[ibin] = std::min<unsigned int>(sum[idx], QIE8_LINEARIZATION_ET);
419  finegrain[ibin] = msb[idx];
420  }
421  // Not a peak
422  else
423  output[ibin] = 0;
424  } else { // No peak finding, just output running sum
425  output[ibin] = std::min<unsigned int>(sum[idx], QIE8_LINEARIZATION_ET);
426  finegrain[ibin] = msb[idx];
427  }
428 
429  // Only Pegged for 1-TS algo.
430  if (peak_finder_algorithm_ == 1) {
433  }
434  }
435  outcoder_->compress(output, finegrain, result);
436 }
437 
439  vector<bool> sample_saturation,
441  const HcalFinegrainBit& fg_algo) {
442  HcalDetId detId(samples.id());
443 
444  // Get the |ieta| for current sample
445  int theIeta = detId.ietaAbs();
446 
447  unsigned int dgSamples = samples.size();
448  unsigned int dgPresamples = samples.presamples();
449 
450  unsigned int tpSamples = numberOfSamples_;
451  unsigned int tpPresamples = numberOfPresamples_;
452 
453  unsigned int filterSamples = weightsQIE11_[theIeta].size();
454  unsigned int filterPresamples = theIeta > theTrigTowerGeometry->topology().lastHBRing()
457 
458  unsigned int shift = dgPresamples - tpPresamples;
459 
460  // shrink keeps the FIR filter from going off the end of the 8TS vector
461  unsigned int shrink = filterSamples - 1;
462 
463  auto& msb = fgUpgradeMap_[samples.id()];
464  auto& timingTDC = fgUpgradeTDCMap_[samples.id()];
465  IntegerCaloSamples sum(samples.id(), samples.size());
466 
467  std::vector<HcalTrigTowerDetId> ids = theTrigTowerGeometry->towerIds(detId);
468 
469  // keep track of tower with saturated energy and force the total TP saturated
470  bool force_saturation[samples.size()];
471  for (int i = 0; i < samples.size(); i++) {
472  force_saturation[i] = false;
473  }
474 
475  //slide algo window
476  for (unsigned int ibin = 0; ibin < dgSamples - shrink; ++ibin) {
477  int algosumvalue = 0;
478  bool check_sat = false;
479  //TP energy calculation for PFA2
480  if (weightsQIE11_[theIeta][0] == 255) {
481  for (unsigned int i = 0; i < filterSamples; i++) {
482  //add up value * scale factor
483  // In addition, divide by two in the 10 degree phi segmentation region
484  // to mimic 5 degree segmentation for the trigger
485  unsigned int sample = samples[ibin + i];
486 
487  if (fix_saturation_ && (sample_saturation.size() > ibin + i))
488  check_sat = (check_sat | sample_saturation[ibin + i] | (sample > QIE11_MAX_LINEARIZATION_ET));
489 
492 
493  // Usually use a segmentation factor of 1.0 but for ieta >= 21 use 2
494  int segmentationFactor = 1;
495  if (ids.size() == 2) {
496  segmentationFactor = 2;
497  }
498 
499  algosumvalue += int(sample / segmentationFactor);
500  }
501  if (algosumvalue < 0)
502  sum[ibin] = 0; // low-side
503  //high-side
504  //else if (algosumvalue>QIE11_LINEARIZATION_ET) sum[ibin]=QIE11_LINEARIZATION_ET;
505  else
506  sum[ibin] = algosumvalue; //assign value to sum[]
507 
508  if (check_sat)
509  force_saturation[ibin] = true;
510  //TP energy calculation for PFA1' and PFA1
511  } else {
512  //add up value * scale factor
513  // In addition, divide by two in the 10 degree phi segmentation region
514  // to mimic 5 degree segmentation for the trigger
515  int sampleTS = samples[ibin + 1];
516  int sampleTSminus1 = samples[ibin];
517 
518  if (fix_saturation_ && (sample_saturation.size() > ibin + 1))
519  check_sat = (sample_saturation[ibin + 1] || (sampleTS >= QIE11_MAX_LINEARIZATION_ET) ||
520  sample_saturation[ibin] || (sampleTSminus1 >= QIE11_MAX_LINEARIZATION_ET));
521 
522  if (sampleTS > QIE11_MAX_LINEARIZATION_ET)
523  sampleTS = QIE11_MAX_LINEARIZATION_ET;
524 
525  if (sampleTSminus1 > QIE11_MAX_LINEARIZATION_ET)
526  sampleTSminus1 = QIE11_MAX_LINEARIZATION_ET;
527 
528  // Usually use a segmentation factor of 1.0 but for ieta >= 21 use 2
529  int segmentationFactor = 1;
530  if (ids.size() == 2) {
531  segmentationFactor = 2;
532  }
533 
534  // Based on the |ieta| of the sample, retrieve the correct region weight
535  int theWeight = weightsQIE11_[theIeta][0];
536 
537  algosumvalue = ((sampleTS << 8) - (sampleTSminus1 * theWeight)) / 256 / segmentationFactor;
538 
539  if (algosumvalue < 0)
540  sum[ibin] = 0; // low-side
541  //high-side
542  //else if (algosumvalue>QIE11_LINEARIZATION_ET) sum[ibin]=QIE11_LINEARIZATION_ET;
543  else
544  sum[ibin] = algosumvalue; //assign value to sum[]
545 
546  if (check_sat)
547  force_saturation[ibin] = true;
548  }
549  }
550 
551  std::vector<int> finegrain(tpSamples, false);
552 
553  IntegerCaloSamples output(samples.id(), tpSamples);
554  output.setPresamples(tpPresamples);
555 
556  for (unsigned int ibin = 0; ibin < tpSamples; ++ibin) {
557  // ibin - index for output TP
558  // idx - index for samples + shift - filterPresamples
559  int idx = ibin + shift - filterPresamples;
560 
561  // When idx is <= 0 peakfind would compare out-of-bounds of the vector. Avoid this ambiguity
562  if (idx <= 0) {
563  output[ibin] = 0;
564  continue;
565  }
566 
567  //Only run the peak-finder when the PFA2 FIR filter is running, which corresponds to weights = 1
568  if (weightsQIE11_[theIeta][0] == 255) {
569  bool isPeak = (sum[idx] > sum[idx - 1] && sum[idx] >= sum[idx + 1] && sum[idx] > theThreshold);
570  if (isPeak) {
571  output[ibin] = std::min<unsigned int>(sum[idx], QIE11_MAX_LINEARIZATION_ET);
572 
573  if (fix_saturation_ && force_saturation[idx] && ids.size() == 2)
575  else if (fix_saturation_ && force_saturation[idx])
577 
578  } else {
579  // Not a peak
580  output[ibin] = 0;
581  }
582  } else {
583  output[ibin] = std::min<unsigned int>(sum[idx], QIE11_MAX_LINEARIZATION_ET);
584 
585  if (fix_saturation_ && force_saturation[idx] && ids.size() == 2)
587  else if (fix_saturation_ && force_saturation[idx])
589  }
590  // peak-finding is not applied for FG bits
591  // compute(msb) returns two bits (MIP). compute(timingTDC,ids) returns 6 bits (1 depth, 1 prompt, 1 delayed 01, 1 delayed 10, 2 reserved)
592  finegrain[ibin] = fg_algo.compute(timingTDC[idx + filterPresamples], ids[0]).to_ulong() |
593  fg_algo.compute(msb[idx + filterPresamples]).to_ulong() << 4;
594  if (ibin == tpPresamples && (idx + filterPresamples) != dgPresamples)
595  edm::LogError("HcalTriggerPritimveAlgo")
596  << "TP SOI (tpPresamples = " << tpPresamples
597  << ") is not aligned with digi SOI (dgPresamples = " << dgPresamples << ")";
598  }
599  outcoder_->compress(output, finegrain, result);
600 }
601 
604 
605  unsigned int tpSamples;
606  unsigned int tpPresamples;
607 
608  tpSamples = samples.size();
609  tpPresamples = samples.presamples();
610  result.setSize(tpSamples);
611  result.setPresamples(tpPresamples);
612 
613  IntegerCaloSamples output(samples.id(), tpSamples);
614  output.setPresamples(tpPresamples);
615 
616  for (int i = 0; i < samples.size(); i++) {
619  else
620  output[i] = samples[i];
621  HcalTriggerPrimitiveSample zdcSample(output[i]);
622  result.setSample(i, zdcSample);
623  }
624 }
625 
628  const int hf_lumi_shift) {
630 
631  // Align digis and TP
632  int dgPresamples = samples.presamples();
633  int tpPresamples = numberOfPresamplesHF_;
634  int shift = dgPresamples - tpPresamples;
635  int dgSamples = samples.size();
636  int tpSamples = numberOfSamplesHF_;
637  if (shift < 0 || shift + tpSamples > dgSamples) {
638  edm::LogInfo("HcalTriggerPrimitiveAlgo::analyzeHF")
639  << "TP presample or size from the configuration file is out of the accessible range. Using digi values from "
640  "data instead...";
641  tpPresamples = dgPresamples;
642  shift = 0;
643  tpSamples = dgSamples;
644  }
645 
646  std::vector<int> finegrain(tpSamples, false);
647 
648  TowerMapFGSum::const_iterator tower2fg = theTowerMapFGSum.find(detId);
649  assert(tower2fg != theTowerMapFGSum.end());
650 
651  const SumFGContainer& sumFG = tower2fg->second;
652  // Loop over all L+S pairs that mapped from samples.id()
653  // Note: 1 samples.id() = 6 x (L+S) without noZS
654  for (SumFGContainer::const_iterator sumFGItr = sumFG.begin(); sumFGItr != sumFG.end(); ++sumFGItr) {
655  const std::vector<bool>& veto = HF_Veto[sumFGItr->id().rawId()];
656  for (int ibin = 0; ibin < tpSamples; ++ibin) {
657  int idx = ibin + shift;
658  // if not vetod, add L+S to total sum and calculate FG
659  bool vetoed = idx < int(veto.size()) && veto[idx];
660  if (!(vetoed && (*sumFGItr)[idx] > PMT_NoiseThreshold_)) {
661  samples[idx] += (*sumFGItr)[idx];
662  finegrain[ibin] = (finegrain[ibin] || (*sumFGItr)[idx] >= FG_threshold_);
663  }
664  }
665  }
666 
667  IntegerCaloSamples output(samples.id(), tpSamples);
668  output.setPresamples(tpPresamples);
669 
670  for (int ibin = 0; ibin < tpSamples; ++ibin) {
671  int idx = ibin + shift;
672  output[ibin] = samples[idx] >> hf_lumi_shift;
673  static const int MAX_OUTPUT = QIE8_LINEARIZATION_ET; // QIE8_LINEARIZATION_ET = 1023
674  if (output[ibin] > MAX_OUTPUT)
675  output[ibin] = MAX_OUTPUT;
676  }
677  outcoder_->compress(output, finegrain, result);
678 }
679 
682  const int hf_lumi_shift,
683  const HcalFeatureBit* embit) {
684  // Align digis and TP
685  const int SHIFT = samples.presamples() - numberOfPresamplesHF_;
686  assert(SHIFT >= 0);
687  assert((SHIFT + numberOfSamplesHF_) <= samples.size());
688 
689  // Try to find the HFDetails from the map corresponding to our samples
690  const HcalTrigTowerDetId detId(samples.id());
691  HFDetailMap::const_iterator it = theHFDetailMap.find(detId);
692  // Missing values will give an empty digi
693  if (it == theHFDetailMap.end()) {
694  return;
695  }
696 
697  std::vector<std::bitset<2>> finegrain(numberOfSamplesHF_, false);
698 
699  // Set up out output of IntergerCaloSamples
701  output.setPresamples(numberOfPresamplesHF_);
702 
703  for (const auto& item : it->second) {
704  auto& details = item.second;
705  for (int ibin = 0; ibin < numberOfSamplesHF_; ++ibin) {
706  const int IDX = ibin + SHIFT;
707  int long_fiber_val = 0;
708  if (IDX < details.long_fiber.size()) {
709  long_fiber_val = details.long_fiber[IDX];
710  }
711  int short_fiber_val = 0;
712  if (IDX < details.short_fiber.size()) {
713  short_fiber_val = details.short_fiber[IDX];
714  }
715  output[ibin] += (long_fiber_val + short_fiber_val);
716 
717  uint32_t ADCLong = details.LongDigi[ibin].adc();
718  uint32_t ADCShort = details.ShortDigi[ibin].adc();
719 
720  if (details.LongDigi.id().ietaAbs() >= FIRST_FINEGRAIN_TOWER) {
721  finegrain[ibin][1] = (ADCLong > FG_HF_thresholds_[0] || ADCShort > FG_HF_thresholds_[0]);
722 
723  if (embit != nullptr)
724  finegrain[ibin][0] = embit->fineGrainbit(details.ShortDigi, details.LongDigi, ibin);
725  }
726  }
727  }
728 
729  for (int bin = 0; bin < numberOfSamplesHF_; ++bin) {
730  static const unsigned int MAX_OUTPUT = QIE8_LINEARIZATION_ET; // QIE8_LINEARIZATION_ET = 1023
731  output[bin] = min({MAX_OUTPUT, output[bin] >> hf_lumi_shift});
732  }
733 
734  std::vector<int> finegrain_converted;
735  finegrain_converted.reserve(finegrain.size());
736  for (const auto& fg : finegrain)
737  finegrain_converted.push_back(fg.to_ulong());
738  outcoder_->compress(output, finegrain_converted, result);
739 }
740 
741 bool HcalTriggerPrimitiveAlgo::passTDC(const QIE10DataFrame& digi, int ts) const {
743  auto adc_threshold = parameters->getADCThresholdHF();
744  auto tdc_mask = parameters->getTDCMaskHF();
745 
746  if (override_adc_hf_)
747  adc_threshold = override_adc_hf_value_;
748  if (override_tdc_hf_)
749  tdc_mask = override_tdc_hf_value_;
750 
751  if (digi[ts].adc() < adc_threshold)
752  return true;
753 
754  return (1ul << digi[ts].le_tdc()) & tdc_mask;
755 }
756 
758  // channels with invalid data should not contribute to the sum
759  if (digi.linkError() || ts >= digi.samples() || !digi[ts].ok())
760  return false;
761 
763  if (mask)
764  return false;
765 
766  return true;
767 }
768 
771  const int hf_lumi_shift,
772  const HcalFeatureBit* embit) {
773  // Align digis and TP
774  const int shift = samples.presamples() - numberOfPresamplesHF_;
775  assert(shift >= 0);
776  assert((shift + numberOfSamplesHF_) <= samples.size());
777  assert(hf_lumi_shift >= 2);
778 
779  // Try to find the HFDetails from the map corresponding to our samples
780  const HcalTrigTowerDetId detId(samples.id());
781  auto it = theHFUpgradeDetailMap.find(detId);
782  // Missing values will give an empty digi
783  if (it == theHFUpgradeDetailMap.end()) {
784  return;
785  }
786 
787  std::vector<std::bitset<2>> finegrain(numberOfSamplesHF_, false);
788 
789  // Set up out output of IntergerCaloSamples
791  output.setPresamples(numberOfPresamplesHF_);
792 
793  for (const auto& item : it->second) {
794  auto& details = item.second;
795  for (int ibin = 0; ibin < numberOfSamplesHF_; ++ibin) {
796  const int idx = ibin + shift;
797 
798  int long_fiber_val = 0;
799  int long_fiber_count = 0;
800  int short_fiber_val = 0;
801  int short_fiber_count = 0;
802 
803  bool saturated = false;
804 
805  for (auto i : {0, 2}) {
806  if (idx < details[i].samples.size() and details[i].validity[idx] and details[i].passTDC[idx]) {
807  long_fiber_val += details[i].samples[idx];
808  saturated = saturated || (details[i].samples[idx] == QIE10_LINEARIZATION_ET);
809  ++long_fiber_count;
810  }
811  }
812  for (auto i : {1, 3}) {
813  if (idx < details[i].samples.size() and details[i].validity[idx] and details[i].passTDC[idx]) {
814  short_fiber_val += details[i].samples[idx];
815  saturated = saturated || (details[i].samples[idx] == QIE10_LINEARIZATION_ET);
816  ++short_fiber_count;
817  }
818  }
819 
820  if (saturated) {
822  } else {
823  // For details of the energy handling, see:
824  // https://cms-docdb.cern.ch/cgi-bin/DocDB/ShowDocument?docid=12306
825  // If both readouts are valid, average of the two energies is taken
826  // division by 2 is compensated by adjusting the total scale shift in the end
827  if (long_fiber_count == 2)
828  long_fiber_val >>= 1;
829  if (short_fiber_count == 2)
830  short_fiber_val >>= 1;
831 
832  auto sum = long_fiber_val + short_fiber_val;
833  // Similar to above, if both channels are valid,
834  // average of the two energies is calculated
835  // division by 2 here is also compensated by adjusting the total scale shift in the end
836  if (long_fiber_count > 0 and short_fiber_count > 0)
837  sum >>= 1;
838 
839  output[ibin] += sum;
840  }
841 
842  for (const auto& detail : details) {
843  if (idx < int(detail.digi.size()) and detail.validity[idx] and
844  HcalDetId(detail.digi.id()).ietaAbs() >= FIRST_FINEGRAIN_TOWER) {
845  if (useTDCInMinBiasBits_ && !detail.passTDC[idx])
846  continue;
847  finegrain[ibin][1] = finegrain[ibin][1] or detail.fgbits[idx][0];
848  // what is commonly called the "second" HF min-bias bit is
849  // actually the 0-th bit, which can also be used instead for the EM bit
850  // (called finegrain[ibin][0] below) in non-HI running
851  finegrain[ibin][0] = finegrain[ibin][0] or detail.fgbits[idx][1];
852  }
853  }
854  // the EM bit is only used if the "second" FG bit is disabled
855  if (embit != nullptr and FG_HF_thresholds_.at(1) != 255) {
856  finegrain[ibin][0] = embit->fineGrainbit(details[1].digi,
857  details[3].digi,
858  details[0].digi,
859  details[2].digi,
860  details[1].validity[idx],
861  details[3].validity[idx],
862  details[0].validity[idx],
863  details[2].validity[idx],
864  idx);
865  }
866  }
867  }
868 
869  for (int bin = 0; bin < numberOfSamplesHF_; ++bin) {
870  output[bin] = min({(unsigned int)QIE10_MAX_LINEARIZATION_ET, output[bin] >> (hf_lumi_shift - 2)});
871  }
872  std::vector<int> finegrain_converted;
873  finegrain_converted.reserve(finegrain.size());
874  for (const auto& fg : finegrain)
875  finegrain_converted.push_back(fg.to_ulong());
876  outcoder_->compress(output, finegrain_converted, result);
877 }
878 
880  for (HcalTrigPrimDigiCollection::iterator tp = result.begin(); tp != result.end(); ++tp) {
881  bool ZS = true;
882  for (int i = 0; i < tp->size(); ++i) {
883  if (tp->sample(i).compressedEt() > ZS_threshold_I_) {
884  ZS = false;
885  break;
886  }
887  }
888  if (ZS)
889  tp->setZSInfo(false, true);
890  else
891  tp->setZSInfo(true, false);
892  }
893 }
894 
896  const HcalElectronicsMap* emap,
898  std::set<uint32_t> FrontEndErrors;
899 
901  const FEDRawData& raw = rawraw->FEDData(i);
902  if (raw.size() < 12)
903  continue;
904  const HcalDCCHeader* dccHeader = (const HcalDCCHeader*)(raw.data());
905  if (!dccHeader)
906  continue;
907  HcalHTRData htr;
908  for (int spigot = 0; spigot < HcalDCCHeader::SPIGOT_COUNT; spigot++) {
909  if (!dccHeader->getSpigotPresent(spigot))
910  continue;
911  dccHeader->getSpigotData(spigot, htr, raw.size());
912  int dccid = dccHeader->getSourceId();
913  int errWord = htr.getErrorsWord() & 0x1FFFF;
914  bool HTRError = (!htr.check() || htr.isHistogramEvent() || (errWord & 0x800) != 0);
915 
916  if (HTRError) {
917  bool valid = false;
918  for (int fchan = 0; fchan < 3 && !valid; fchan++) {
919  for (int fib = 0; fib < 9 && !valid; fib++) {
920  HcalElectronicsId eid(fchan, fib, spigot, dccid - FEDNumbering::MINHCALFEDID);
921  eid.setHTR(htr.readoutVMECrateId(), htr.htrSlot(), htr.htrTopBottom());
922  DetId detId = emap->lookup(eid);
923  if (detId.null())
924  continue;
925  HcalSubdetector subdet = (HcalSubdetector(detId.subdetId()));
926  if (detId.det() != 4 || (subdet != HcalBarrel && subdet != HcalEndcap && subdet != HcalForward))
927  continue;
928  std::vector<HcalTrigTowerDetId> ids = theTrigTowerGeometry->towerIds(detId);
929  for (std::vector<HcalTrigTowerDetId>::const_iterator triggerId = ids.begin(); triggerId != ids.end();
930  ++triggerId) {
931  FrontEndErrors.insert(triggerId->rawId());
932  }
933  //valid = true;
934  }
935  }
936  }
937  }
938  }
939 
940  // Loop over TP collection
941  // Set TP to zero if there is FE Format Error
942  HcalTriggerPrimitiveSample zeroSample(0);
943  for (HcalTrigPrimDigiCollection::iterator tp = result.begin(); tp != result.end(); ++tp) {
944  if (FrontEndErrors.find(tp->id().rawId()) != FrontEndErrors.end()) {
945  for (int i = 0; i < tp->size(); ++i)
946  tp->setSample(i, zeroSample);
947  }
948  }
949 }
950 
951 void HcalTriggerPrimitiveAlgo::addFG(const HcalTrigTowerDetId& id, std::vector<bool>& msb) {
952  FGbitMap::iterator itr = fgMap_.find(id);
953  if (itr != fgMap_.end()) {
954  std::vector<bool>& _msb = itr->second;
955  for (size_t i = 0; i < msb.size(); ++i)
956  _msb[i] = _msb[i] || msb[i];
957  } else
958  fgMap_[id] = msb;
959 }
960 
963  return false;
964  if (id.ietaAbs() > LAST_FINEGRAIN_TOWER)
965  return false;
966  if (id.ietaAbs() == HBHE_OVERLAP_TOWER and not upgrade_hb_)
967  return false;
968  return true;
969 }
970 
972  // This tower (ietaAbs == 16) does not accept upgraded FG bits,
973  // but needs pseudo legacy ones to ensure that the tower is processed
974  // even when the QIE8 depths in front of it do not have energy deposits.
975  if (id.ietaAbs() == HBHE_OVERLAP_TOWER and not upgrade_hb_)
976  return true;
977  return false;
978 }
979 
981  // Depth 7 for TT 26, 27, and 28 is not considered a fine grain depth.
982  // However, the trigger tower for these ieta should still be added to the fgUpgradeMap_
983  // Otherwise, depth 7-only signal will not be analyzed.
984  unsigned int aieta = id.ietaAbs();
985  if (aieta >= FIRST_DEPTH7_TOWER and aieta <= LAST_FINEGRAIN_TOWER and depth > LAST_FINEGRAIN_DEPTH)
986  return true;
987  return false;
988 }
989 
991  int depth,
992  const std::vector<std::bitset<2>>& bits) {
993  if (not validUpgradeFG(id, depth)) {
994  if (needLegacyFG(id)) {
995  std::vector<bool> pseudo(bits.size(), false);
996  addFG(id, pseudo);
997  } else if (needUpgradeID(id, depth)) {
998  // If the tower id is not in the map yet
999  // then for safety's sake add it, otherwise, no need
1000  // Likewise, we're here with non-fg depth 7 so the bits are not to be added
1001  auto it = fgUpgradeMap_.find(id);
1002  if (it == fgUpgradeMap_.end()) {
1003  FGUpgradeContainer element;
1004  element.resize(bits.size());
1005  fgUpgradeMap_.insert(std::make_pair(id, element));
1006  }
1007  }
1008 
1009  return;
1010  }
1011 
1012  auto it = fgUpgradeMap_.find(id);
1013  if (it == fgUpgradeMap_.end()) {
1014  FGUpgradeContainer element;
1015  element.resize(bits.size());
1016  it = fgUpgradeMap_.insert(std::make_pair(id, element)).first;
1017  }
1018  for (unsigned int i = 0; i < bits.size(); ++i) {
1019  it->second[i][0][depth - 1] = bits[i][0];
1020  it->second[i][1][depth - 1] = bits[i][1];
1021  }
1022 }
1023 
1025  HcalDetId detId(frame.id());
1026  if (detId.subdet() != HcalEndcap && detId.subdet() != HcalBarrel)
1027  return;
1028 
1029  std::vector<HcalTrigTowerDetId> ids = theTrigTowerGeometry->towerIds(detId);
1030  assert(ids.size() == 1 || ids.size() == 2);
1031  IntegerCaloSamples samples1(ids[0], int(frame.samples()));
1032  samples1.setPresamples(frame.presamples());
1033  incoder_->adc2Linear(frame, samples1); // use linearization LUT
1034  std::vector<unsigned short> bits12_15 = incoder_->group0FGbits(frame); // get 4 energy bits (12-15) from group 0 LUT
1035 
1036  bool is_compressed = false;
1037  if (detId.subdet() == HcalBarrel) {
1038  is_compressed = (frame.flavor() == 3);
1039  // 0 if frame.flavor is 0 (uncompressed), 1 if frame.flavor is 3 (compressed)
1040  }
1041 
1042  auto it = fgUpgradeTDCMap_.find(id);
1043  if (it == fgUpgradeTDCMap_.end()) {
1044  FGUpgradeTDCContainer element;
1045  element.resize(frame.samples());
1046  it = fgUpgradeTDCMap_.insert(std::make_pair(id, element)).first;
1047  }
1048  for (int i = 0; i < frame.samples(); i++) {
1049  it->second[i][detId.depth() - 1] =
1050  std::make_pair(std::make_pair(bits12_15[i], is_compressed), std::make_pair(frame[i].tdc(), samples1[i]));
1051  }
1052 }
1053 
1055  // Names are just abs(ieta) for HBHE
1056  std::vector<std::string> ietaStrs = weightsQIE11.getParameterNames();
1057  for (auto& ietaStr : ietaStrs) {
1058  // Strip off "ieta" part of key and just use integer value in map
1059  auto const& v = weightsQIE11.getParameter<std::vector<int>>(ietaStr);
1060  weightsQIE11_[std::stoi(ietaStr.substr(4))] = {{v[0], v[1]}};
1061  }
1062 }
1063 
1065  // Simple map of |ieta| in HBHE to weight
1066  // Only one weight for SOI-1 TS
1067  weightsQIE11_[aieta] = {{weight, 255}};
1068 }
1069 
1071  if (algo <= 0 || algo > 2)
1072  throw cms::Exception("ERROR: Only algo 1 & 2 are supported.") << std::endl;
1074 }
1075 
1077 
bool validUpgradeFG(const HcalTrigTowerDetId &id, int depth) const
void addUpgradeTDCFG(const HcalTrigTowerDetId &id, const QIE11DataFrame &frame)
void analyze(IntegerCaloSamples &samples, HcalTriggerPrimitiveDigi &result)
adds the actual digis
bool isHistogramEvent() const
Is this event a histogram event? (do not call standard unpack in this case!!!!!)
Definition: HcalHTRData.cc:409
void runFEFormatError(const FEDRawDataCollection *rawraw, const HcalElectronicsMap *emap, HcalTrigPrimDigiCollection &result)
T getParameter(std::string const &) const
Definition: ParameterSet.h:307
std::vector< uint32_t > FG_HF_thresholds_
HFUpgradeDetailMap theHFUpgradeDetailMap
constexpr edm::DataFrame::id_type id() const
void analyzeHF(IntegerCaloSamples &samples, HcalTriggerPrimitiveDigi &result, const int hf_lumi_shift)
int getSpigotData(int nspigot, HcalHTRData &decodeTool, int validSize) const
static const int QIE10_MAX_LINEARIZATION_ET
T w() const
uint32_t getMask() const
get mask for channel validity and self trigger information
void analyzeHF2016(const IntegerCaloSamples &SAMPLES, HcalTriggerPrimitiveDigi &result, const int HF_LUMI_SHIFT, const HcalFeatureBit *HCALFEM)
bool exists(std::string const &parameterName) const
checks if a parameter exists
void analyzeHFQIE10(const IntegerCaloSamples &SAMPLES, HcalTriggerPrimitiveDigi &result, const int HF_LUMI_SHIFT, const HcalFeatureBit *HCALFEM)
const DetId lookup(HcalElectronicsId fId) const
lookup the logical detid associated with the given electronics id
bool needLegacyFG(const HcalTrigTowerDetId &id) const
const HcalTPGCompressor * outcoder_
size_t size() const
Lenght of the data buffer in bytes.
Definition: FEDRawData.h:48
Definition: weight.py:1
void lookupMSB(const HBHEDataFrame &df, std::vector< bool > &msb) const
void setPresamples(int pre)
set presample information
void addFG(const HcalTrigTowerDetId &id, std::vector< bool > &msb)
std::vector< unsigned short > group0FGbits(const QIE11DataFrame &df) const
Log< level::Error, false > LogError
assert(be >=bs)
static const int QIE10_ZDC_MAX_LINEARIZATION_ET
std::array< std::array< int, 2 >, 29 > weightsQIE11_
const HcalTopology & topology() const
ALPAKA_FN_ACC ALPAKA_FN_INLINE uint32_t ietaAbs(uint32_t id)
std::vector< IntegerCaloSamples > SumFGContainer
void compress(const IntegerCaloSamples &ics, const std::vector< int > &fineGrain, HcalTriggerPrimitiveDigi &digi) const
const HcalTrigTowerGeometry * theTrigTowerGeometry
const HcalDbService * conditions_
weightsQIE11
hardware algo
unsigned int htrSlot() const
HcalElectronicsId-style HTR slot.
Definition: HcalHTRData.cc:365
unsigned int htrTopBottom() const
HcalElectronicsId-style HTR top/bottom (1=top/0=bottom)
Definition: HcalHTRData.cc:369
void setWeightQIE11(int aieta, int weight)
int lastHBRing() const
Definition: HcalTopology.h:92
int getSourceId() const
Definition: HcalDCCHeader.h:33
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e< void, edm::EventID const &, edm::Timestamp const & > We also list in braces which AR_WATCH_USING_METHOD_ is used for those or
Definition: Activities.doc:12
Definition: helper.h:56
bool needUpgradeID(const HcalTrigTowerDetId &id, int depth) const
HcalSubdetector
Definition: HcalAssistant.h:31
HcalTriggerPrimitiveAlgo(bool pf, const std::vector< double > &w, int latency, uint32_t FG_threshold, const std::vector< uint32_t > &FG_HF_thresholds, uint32_t ZS_threshold, int numberOfSamples, int numberOfPresamples, int numberOfFilterPresamplesHBQIE11, int numberOfFilterPresamplesHEQIE11, int numberOfSamplesHF, int numberOfPresamplesHF, int numberOfSamplesZDC, int numberOfPresamplesZDC, bool useTDCInMinBiasBits, uint32_t minSignalThreshold=0, uint32_t PMT_NoiseThreshold=0)
const HcalTPChannelParameter * getHcalTPChannelParameter(const HcalGenericDetId &fId, bool throwOnFail=true) const
const HcalTPParameters * getHcalTPParameters() const
const FEDRawData & FEDData(int fedid) const
retrieve data for fed
void runZS(HcalTrigPrimDigiCollection &tp)
std::vector< T >::iterator iterator
constexpr bool linkError() const
void analyzeQIE11(IntegerCaloSamples &samples, std::vector< bool > sample_saturation, HcalTriggerPrimitiveDigi &result, const HcalFinegrainBit &fg_algo)
Log< level::Info, false > LogInfo
std::vector< HcalFinegrainBit::TowerTDC > FGUpgradeTDCContainer
std::vector< HcalFinegrainBit::Tower > FGUpgradeContainer
Definition: DetId.h:17
std::bitset< 2 > compute(const Tower &) const
virtual bool fineGrainbit(const QIE10DataFrame &short1, const QIE10DataFrame &short2, const QIE10DataFrame &long1, const QIE10DataFrame &long2, bool validShort1, bool validShort2, bool validLong1, bool validLong2, int idx) const =0
unsigned long long override_tdc_hf_value_
static const int QIE11_MAX_LINEARIZATION_ET
void adc2Linear(const HBHEDataFrame &df, IntegerCaloSamples &ics) const override
void addUpgradeFG(const HcalTrigTowerDetId &id, int depth, const std::vector< std::bitset< 2 >> &bits)
const HcaluLUTTPGCoder * incoder_
static const int SPIGOT_COUNT
Definition: HcalDCCHeader.h:20
unsigned int getErrorsWord() const
Get the errors word.
Definition: HcalHTRData.h:162
bool getSpigotPresent(unsigned int nspigot) const
Read the "PRESENT" bit for this spigot.
static unsigned int const shift
bool passTDC(const QIE10DataFrame &digi, int ts) const
const unsigned char * data() const
Return a const pointer to the beginning of the data buffer.
Definition: FEDRawData.cc:24
static constexpr int32_t SubdetectorId
Definition: HcalZDCDetId.h:35
Definition: output.py:1
unsigned int readoutVMECrateId() const
HcalElectronicsId-style VME crate number.
Definition: HcalHTRData.cc:373
bool validChannel(const QIE10DataFrame &digi, int ts) const
Log< level::Warning, false > LogWarning
int version() const
get the version code for the trigger tower
void analyzeZDC(IntegerCaloSamples &samples, HcalTriggerPrimitiveDigi &result)
Readout chain identification for Hcal.
void addSignal(const HBHEDataFrame &frame)
adds the signal to the map
std::vector< HcalTrigTowerDetId > towerIds(const HcalDetId &cellId) const
the mapping to and from DetIds
void setUpgradeFlags(bool hb, bool he, bool hf)
void overrideParameters(const edm::ParameterSet &ps)
bool check() const
Check for a good event Requires a minimum length, matching wordcount and length, not an empty event...
Definition: HcalHTRData.cc:63
void setWeightsQIE11(const edm::ParameterSet &weightsQIE11)
constexpr int samples() const
total number of samples in the digi
uint16_t *__restrict__ uint16_t const *__restrict__ adc
void setFixSaturationFlag(bool fix_saturation)
std::vector< HcalTrigTowerDetId > towerIds_ZDC(const HcalZDCDetId &cellId) const