CMS 3D CMS Logo

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