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,
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 
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());
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());
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 
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) {
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  //TP energy calculation for PFA2
443  if (weightsQIE11_[theIeta][0] == 255) {
444  for (unsigned int i = 0; i < filterSamples; i++) {
445  //add up value * scale factor
446  // In addition, divide by two in the 10 degree phi segmentation region
447  // to mimic 5 degree segmentation for the trigger
448  unsigned int sample = samples[ibin + i];
449 
450  if (fix_saturation_ && (sample_saturation.size() > ibin + i))
451  check_sat = (check_sat | sample_saturation[ibin + i] | (sample > QIE11_MAX_LINEARIZATION_ET));
452 
455 
456  // Usually use a segmentation factor of 1.0 but for ieta >= 21 use 2
457  int segmentationFactor = 1;
458  if (ids.size() == 2) {
459  segmentationFactor = 2;
460  }
461 
462  algosumvalue += int(sample / segmentationFactor);
463  }
464  if (algosumvalue < 0)
465  sum[ibin] = 0; // low-side
466  //high-side
467  //else if (algosumvalue>QIE11_LINEARIZATION_ET) sum[ibin]=QIE11_LINEARIZATION_ET;
468  else
469  sum[ibin] = algosumvalue; //assign value to sum[]
470 
471  if (check_sat)
472  force_saturation[ibin] = true;
473  //TP energy calculation for PFA1' and PFA1
474  } else {
475  //add up value * scale factor
476  // In addition, divide by two in the 10 degree phi segmentation region
477  // to mimic 5 degree segmentation for the trigger
478  int sampleTS = samples[ibin + 1];
479  int sampleTSminus1 = samples[ibin];
480 
481  if (fix_saturation_ && (sample_saturation.size() > ibin + 1))
482  check_sat = (sample_saturation[ibin + 1] || (sampleTS >= QIE11_MAX_LINEARIZATION_ET) ||
483  sample_saturation[ibin] || (sampleTSminus1 >= QIE11_MAX_LINEARIZATION_ET));
484 
485  if (sampleTS > QIE11_MAX_LINEARIZATION_ET)
486  sampleTS = QIE11_MAX_LINEARIZATION_ET;
487 
488  if (sampleTSminus1 > QIE11_MAX_LINEARIZATION_ET)
489  sampleTSminus1 = QIE11_MAX_LINEARIZATION_ET;
490 
491  // Usually use a segmentation factor of 1.0 but for ieta >= 21 use 2
492  int segmentationFactor = 1;
493  if (ids.size() == 2) {
494  segmentationFactor = 2;
495  }
496 
497  // Based on the |ieta| of the sample, retrieve the correct region weight
498  int theWeight = weightsQIE11_[theIeta][0];
499 
500  algosumvalue = ((sampleTS << 8) - (sampleTSminus1 * theWeight)) / 256 / segmentationFactor;
501 
502  if (algosumvalue < 0)
503  sum[ibin] = 0; // low-side
504  //high-side
505  //else if (algosumvalue>QIE11_LINEARIZATION_ET) sum[ibin]=QIE11_LINEARIZATION_ET;
506  else
507  sum[ibin] = algosumvalue; //assign value to sum[]
508 
509  if (check_sat)
510  force_saturation[ibin] = true;
511  }
512  }
513 
514  std::vector<int> finegrain(tpSamples, false);
515 
516  IntegerCaloSamples output(samples.id(), tpSamples);
517  output.setPresamples(tpPresamples);
518 
519  for (unsigned int ibin = 0; ibin < tpSamples; ++ibin) {
520  // ibin - index for output TP
521  // idx - index for samples + shift - filterPresamples
522  int idx = ibin + shift - filterPresamples;
523 
524  // When idx is <= 0 peakfind would compare out-of-bounds of the vector. Avoid this ambiguity
525  if (idx <= 0) {
526  output[ibin] = 0;
527  continue;
528  }
529 
530  //Only run the peak-finder when the PFA2 FIR filter is running, which corresponds to weights = 1
531  if (weightsQIE11_[theIeta][0] == 255) {
532  bool isPeak = (sum[idx] > sum[idx - 1] && sum[idx] >= sum[idx + 1] && sum[idx] > theThreshold);
533  if (isPeak) {
534  output[ibin] = std::min<unsigned int>(sum[idx], QIE11_MAX_LINEARIZATION_ET);
535 
536  if (fix_saturation_ && force_saturation[idx] && ids.size() == 2)
538  else if (fix_saturation_ && force_saturation[idx])
540 
541  } else {
542  // Not a peak
543  output[ibin] = 0;
544  }
545  } else {
546  output[ibin] = std::min<unsigned int>(sum[idx], QIE11_MAX_LINEARIZATION_ET);
547 
548  if (fix_saturation_ && force_saturation[idx] && ids.size() == 2)
550  else if (fix_saturation_ && force_saturation[idx])
552  }
553  // peak-finding is not applied for FG bits
554  // compute(msb) returns two bits (MIP). compute(timingTDC,ids) returns 6 bits (1 depth, 1 prompt, 1 delayed 01, 1 delayed 10, 2 reserved)
555  finegrain[ibin] = fg_algo.compute(timingTDC[idx + filterPresamples], ids[0]).to_ulong() |
556  fg_algo.compute(msb[idx + filterPresamples]).to_ulong() << 4;
557  if (ibin == tpPresamples && (idx + filterPresamples) != dgPresamples)
558  edm::LogError("HcalTriggerPritimveAlgo")
559  << "TP SOI (tpPresamples = " << tpPresamples
560  << ") is not aligned with digi SOI (dgPresamples = " << dgPresamples << ")";
561  }
562  outcoder_->compress(output, finegrain, result);
563 }
564 
567  const int hf_lumi_shift) {
569 
570  // Align digis and TP
571  int dgPresamples = samples.presamples();
572  int tpPresamples = numberOfPresamplesHF_;
573  int shift = dgPresamples - tpPresamples;
574  int dgSamples = samples.size();
575  int tpSamples = numberOfSamplesHF_;
576  if (shift < 0 || shift + tpSamples > dgSamples) {
577  edm::LogInfo("HcalTriggerPrimitiveAlgo::analyzeHF")
578  << "TP presample or size from the configuration file is out of the accessible range. Using digi values from "
579  "data instead...";
580  tpPresamples = dgPresamples;
581  shift = 0;
582  tpSamples = dgSamples;
583  }
584 
585  std::vector<int> finegrain(tpSamples, false);
586 
587  TowerMapFGSum::const_iterator tower2fg = theTowerMapFGSum.find(detId);
588  assert(tower2fg != theTowerMapFGSum.end());
589 
590  const SumFGContainer& sumFG = tower2fg->second;
591  // Loop over all L+S pairs that mapped from samples.id()
592  // Note: 1 samples.id() = 6 x (L+S) without noZS
593  for (SumFGContainer::const_iterator sumFGItr = sumFG.begin(); sumFGItr != sumFG.end(); ++sumFGItr) {
594  const std::vector<bool>& veto = HF_Veto[sumFGItr->id().rawId()];
595  for (int ibin = 0; ibin < tpSamples; ++ibin) {
596  int idx = ibin + shift;
597  // if not vetod, add L+S to total sum and calculate FG
598  bool vetoed = idx < int(veto.size()) && veto[idx];
599  if (!(vetoed && (*sumFGItr)[idx] > PMT_NoiseThreshold_)) {
600  samples[idx] += (*sumFGItr)[idx];
601  finegrain[ibin] = (finegrain[ibin] || (*sumFGItr)[idx] >= FG_threshold_);
602  }
603  }
604  }
605 
606  IntegerCaloSamples output(samples.id(), tpSamples);
607  output.setPresamples(tpPresamples);
608 
609  for (int ibin = 0; ibin < tpSamples; ++ibin) {
610  int idx = ibin + shift;
611  output[ibin] = samples[idx] >> hf_lumi_shift;
612  static const int MAX_OUTPUT = QIE8_LINEARIZATION_ET; // QIE8_LINEARIZATION_ET = 1023
613  if (output[ibin] > MAX_OUTPUT)
614  output[ibin] = MAX_OUTPUT;
615  }
616  outcoder_->compress(output, finegrain, result);
617 }
618 
621  const int hf_lumi_shift,
622  const HcalFeatureBit* embit) {
623  // Align digis and TP
624  const int SHIFT = samples.presamples() - numberOfPresamplesHF_;
625  assert(SHIFT >= 0);
626  assert((SHIFT + numberOfSamplesHF_) <= samples.size());
627 
628  // Try to find the HFDetails from the map corresponding to our samples
629  const HcalTrigTowerDetId detId(samples.id());
630  HFDetailMap::const_iterator it = theHFDetailMap.find(detId);
631  // Missing values will give an empty digi
632  if (it == theHFDetailMap.end()) {
633  return;
634  }
635 
636  std::vector<std::bitset<2>> finegrain(numberOfSamplesHF_, false);
637 
638  // Set up out output of IntergerCaloSamples
640  output.setPresamples(numberOfPresamplesHF_);
641 
642  for (const auto& item : it->second) {
643  auto& details = item.second;
644  for (int ibin = 0; ibin < numberOfSamplesHF_; ++ibin) {
645  const int IDX = ibin + SHIFT;
646  int long_fiber_val = 0;
647  if (IDX < details.long_fiber.size()) {
648  long_fiber_val = details.long_fiber[IDX];
649  }
650  int short_fiber_val = 0;
651  if (IDX < details.short_fiber.size()) {
652  short_fiber_val = details.short_fiber[IDX];
653  }
654  output[ibin] += (long_fiber_val + short_fiber_val);
655 
656  uint32_t ADCLong = details.LongDigi[ibin].adc();
657  uint32_t ADCShort = details.ShortDigi[ibin].adc();
658 
659  if (details.LongDigi.id().ietaAbs() >= FIRST_FINEGRAIN_TOWER) {
660  finegrain[ibin][1] = (ADCLong > FG_HF_thresholds_[0] || ADCShort > FG_HF_thresholds_[0]);
661 
662  if (embit != nullptr)
663  finegrain[ibin][0] = embit->fineGrainbit(details.ShortDigi, details.LongDigi, ibin);
664  }
665  }
666  }
667 
668  for (int bin = 0; bin < numberOfSamplesHF_; ++bin) {
669  static const unsigned int MAX_OUTPUT = QIE8_LINEARIZATION_ET; // QIE8_LINEARIZATION_ET = 1023
670  output[bin] = min({MAX_OUTPUT, output[bin] >> hf_lumi_shift});
671  }
672 
673  std::vector<int> finegrain_converted;
674  finegrain_converted.reserve(finegrain.size());
675  for (const auto& fg : finegrain)
676  finegrain_converted.push_back(fg.to_ulong());
677  outcoder_->compress(output, finegrain_converted, result);
678 }
679 
680 bool HcalTriggerPrimitiveAlgo::passTDC(const QIE10DataFrame& digi, int ts) const {
682  auto adc_threshold = parameters->getADCThresholdHF();
683  auto tdc_mask = parameters->getTDCMaskHF();
684 
685  if (override_adc_hf_)
686  adc_threshold = override_adc_hf_value_;
687  if (override_tdc_hf_)
688  tdc_mask = override_tdc_hf_value_;
689 
690  if (digi[ts].adc() < adc_threshold)
691  return true;
692 
693  return (1ul << digi[ts].le_tdc()) & tdc_mask;
694 }
695 
697  // channels with invalid data should not contribute to the sum
698  if (digi.linkError() || ts >= digi.samples() || !digi[ts].ok())
699  return false;
700 
702  if (mask)
703  return false;
704 
705  return true;
706 }
707 
710  const int hf_lumi_shift,
711  const HcalFeatureBit* embit) {
712  // Align digis and TP
713  const int shift = samples.presamples() - numberOfPresamplesHF_;
714  assert(shift >= 0);
715  assert((shift + numberOfSamplesHF_) <= samples.size());
716  assert(hf_lumi_shift >= 2);
717 
718  // Try to find the HFDetails from the map corresponding to our samples
719  const HcalTrigTowerDetId detId(samples.id());
720  auto it = theHFUpgradeDetailMap.find(detId);
721  // Missing values will give an empty digi
722  if (it == theHFUpgradeDetailMap.end()) {
723  return;
724  }
725 
726  std::vector<std::bitset<2>> finegrain(numberOfSamplesHF_, false);
727 
728  // Set up out output of IntergerCaloSamples
730  output.setPresamples(numberOfPresamplesHF_);
731 
732  for (const auto& item : it->second) {
733  auto& details = item.second;
734  for (int ibin = 0; ibin < numberOfSamplesHF_; ++ibin) {
735  const int idx = ibin + shift;
736 
737  int long_fiber_val = 0;
738  int long_fiber_count = 0;
739  int short_fiber_val = 0;
740  int short_fiber_count = 0;
741 
742  bool saturated = false;
743 
744  for (auto i : {0, 2}) {
745  if (idx < details[i].samples.size() and details[i].validity[idx] and details[i].passTDC[idx]) {
746  long_fiber_val += details[i].samples[idx];
747  saturated = saturated || (details[i].samples[idx] == QIE10_LINEARIZATION_ET);
748  ++long_fiber_count;
749  }
750  }
751  for (auto i : {1, 3}) {
752  if (idx < details[i].samples.size() and details[i].validity[idx] and details[i].passTDC[idx]) {
753  short_fiber_val += details[i].samples[idx];
754  saturated = saturated || (details[i].samples[idx] == QIE10_LINEARIZATION_ET);
755  ++short_fiber_count;
756  }
757  }
758 
759  if (saturated) {
761  } else {
762  // For details of the energy handling, see:
763  // https://cms-docdb.cern.ch/cgi-bin/DocDB/ShowDocument?docid=12306
764  // If both readouts are valid, average of the two energies is taken
765  // division by 2 is compensated by adjusting the total scale shift in the end
766  if (long_fiber_count == 2)
767  long_fiber_val >>= 1;
768  if (short_fiber_count == 2)
769  short_fiber_val >>= 1;
770 
771  auto sum = long_fiber_val + short_fiber_val;
772  // Similar to above, if both channels are valid,
773  // average of the two energies is calculated
774  // division by 2 here is also compensated by adjusting the total scale shift in the end
775  if (long_fiber_count > 0 and short_fiber_count > 0)
776  sum >>= 1;
777 
778  output[ibin] += sum;
779  }
780 
781  for (const auto& detail : details) {
782  if (idx < int(detail.digi.size()) and detail.validity[idx] and
783  HcalDetId(detail.digi.id()).ietaAbs() >= FIRST_FINEGRAIN_TOWER) {
784  if (useTDCInMinBiasBits_ && !detail.passTDC[idx])
785  continue;
786  finegrain[ibin][1] = finegrain[ibin][1] or detail.fgbits[idx][0];
787  // what is commonly called the "second" HF min-bias bit is
788  // actually the 0-th bit, which can also be used instead for the EM bit
789  // (called finegrain[ibin][0] below) in non-HI running
790  finegrain[ibin][0] = finegrain[ibin][0] or detail.fgbits[idx][1];
791  }
792  }
793  // the EM bit is only used if the "second" FG bit is disabled
794  if (embit != nullptr and FG_HF_thresholds_.at(1) != 255) {
795  finegrain[ibin][0] = embit->fineGrainbit(details[1].digi,
796  details[3].digi,
797  details[0].digi,
798  details[2].digi,
799  details[1].validity[idx],
800  details[3].validity[idx],
801  details[0].validity[idx],
802  details[2].validity[idx],
803  idx);
804  }
805  }
806  }
807 
808  for (int bin = 0; bin < numberOfSamplesHF_; ++bin) {
809  output[bin] = min({(unsigned int)QIE10_MAX_LINEARIZATION_ET, output[bin] >> (hf_lumi_shift - 2)});
810  }
811  std::vector<int> finegrain_converted;
812  finegrain_converted.reserve(finegrain.size());
813  for (const auto& fg : finegrain)
814  finegrain_converted.push_back(fg.to_ulong());
815  outcoder_->compress(output, finegrain_converted, result);
816 }
817 
819  for (HcalTrigPrimDigiCollection::iterator tp = result.begin(); tp != result.end(); ++tp) {
820  bool ZS = true;
821  for (int i = 0; i < tp->size(); ++i) {
822  if (tp->sample(i).compressedEt() > ZS_threshold_I_) {
823  ZS = false;
824  break;
825  }
826  }
827  if (ZS)
828  tp->setZSInfo(false, true);
829  else
830  tp->setZSInfo(true, false);
831  }
832 }
833 
835  const HcalElectronicsMap* emap,
837  std::set<uint32_t> FrontEndErrors;
838 
840  const FEDRawData& raw = rawraw->FEDData(i);
841  if (raw.size() < 12)
842  continue;
843  const HcalDCCHeader* dccHeader = (const HcalDCCHeader*)(raw.data());
844  if (!dccHeader)
845  continue;
846  HcalHTRData htr;
847  for (int spigot = 0; spigot < HcalDCCHeader::SPIGOT_COUNT; spigot++) {
848  if (!dccHeader->getSpigotPresent(spigot))
849  continue;
850  dccHeader->getSpigotData(spigot, htr, raw.size());
851  int dccid = dccHeader->getSourceId();
852  int errWord = htr.getErrorsWord() & 0x1FFFF;
853  bool HTRError = (!htr.check() || htr.isHistogramEvent() || (errWord & 0x800) != 0);
854 
855  if (HTRError) {
856  bool valid = false;
857  for (int fchan = 0; fchan < 3 && !valid; fchan++) {
858  for (int fib = 0; fib < 9 && !valid; fib++) {
859  HcalElectronicsId eid(fchan, fib, spigot, dccid - FEDNumbering::MINHCALFEDID);
860  eid.setHTR(htr.readoutVMECrateId(), htr.htrSlot(), htr.htrTopBottom());
861  DetId detId = emap->lookup(eid);
862  if (detId.null())
863  continue;
864  HcalSubdetector subdet = (HcalSubdetector(detId.subdetId()));
865  if (detId.det() != 4 || (subdet != HcalBarrel && subdet != HcalEndcap && subdet != HcalForward))
866  continue;
867  std::vector<HcalTrigTowerDetId> ids = theTrigTowerGeometry->towerIds(detId);
868  for (std::vector<HcalTrigTowerDetId>::const_iterator triggerId = ids.begin(); triggerId != ids.end();
869  ++triggerId) {
870  FrontEndErrors.insert(triggerId->rawId());
871  }
872  //valid = true;
873  }
874  }
875  }
876  }
877  }
878 
879  // Loop over TP collection
880  // Set TP to zero if there is FE Format Error
881  HcalTriggerPrimitiveSample zeroSample(0);
882  for (HcalTrigPrimDigiCollection::iterator tp = result.begin(); tp != result.end(); ++tp) {
883  if (FrontEndErrors.find(tp->id().rawId()) != FrontEndErrors.end()) {
884  for (int i = 0; i < tp->size(); ++i)
885  tp->setSample(i, zeroSample);
886  }
887  }
888 }
889 
890 void HcalTriggerPrimitiveAlgo::addFG(const HcalTrigTowerDetId& id, std::vector<bool>& msb) {
891  FGbitMap::iterator itr = fgMap_.find(id);
892  if (itr != fgMap_.end()) {
893  std::vector<bool>& _msb = itr->second;
894  for (size_t i = 0; i < msb.size(); ++i)
895  _msb[i] = _msb[i] || msb[i];
896  } else
897  fgMap_[id] = msb;
898 }
899 
902  return false;
903  if (id.ietaAbs() > LAST_FINEGRAIN_TOWER)
904  return false;
905  if (id.ietaAbs() == HBHE_OVERLAP_TOWER and not upgrade_hb_)
906  return false;
907  return true;
908 }
909 
911  // This tower (ietaAbs == 16) does not accept upgraded FG bits,
912  // but needs pseudo legacy ones to ensure that the tower is processed
913  // even when the QIE8 depths in front of it do not have energy deposits.
914  if (id.ietaAbs() == HBHE_OVERLAP_TOWER and not upgrade_hb_)
915  return true;
916  return false;
917 }
918 
920  // Depth 7 for TT 26, 27, and 28 is not considered a fine grain depth.
921  // However, the trigger tower for these ieta should still be added to the fgUpgradeMap_
922  // Otherwise, depth 7-only signal will not be analyzed.
923  unsigned int aieta = id.ietaAbs();
924  if (aieta >= FIRST_DEPTH7_TOWER and aieta <= LAST_FINEGRAIN_TOWER and depth > LAST_FINEGRAIN_DEPTH)
925  return true;
926  return false;
927 }
928 
930  int depth,
931  const std::vector<std::bitset<2>>& bits) {
932  if (not validUpgradeFG(id, depth)) {
933  if (needLegacyFG(id)) {
934  std::vector<bool> pseudo(bits.size(), false);
935  addFG(id, pseudo);
936  } else if (needUpgradeID(id, depth)) {
937  // If the tower id is not in the map yet
938  // then for safety's sake add it, otherwise, no need
939  // Likewise, we're here with non-fg depth 7 so the bits are not to be added
940  auto it = fgUpgradeMap_.find(id);
941  if (it == fgUpgradeMap_.end()) {
942  FGUpgradeContainer element;
943  element.resize(bits.size());
944  fgUpgradeMap_.insert(std::make_pair(id, element));
945  }
946  }
947 
948  return;
949  }
950 
951  auto it = fgUpgradeMap_.find(id);
952  if (it == fgUpgradeMap_.end()) {
953  FGUpgradeContainer element;
954  element.resize(bits.size());
955  it = fgUpgradeMap_.insert(std::make_pair(id, element)).first;
956  }
957  for (unsigned int i = 0; i < bits.size(); ++i) {
958  it->second[i][0][depth - 1] = bits[i][0];
959  it->second[i][1][depth - 1] = bits[i][1];
960  }
961 }
962 
964  HcalDetId detId(frame.id());
965  if (detId.subdet() != HcalEndcap && detId.subdet() != HcalBarrel)
966  return;
967 
968  std::vector<HcalTrigTowerDetId> ids = theTrigTowerGeometry->towerIds(detId);
969  assert(ids.size() == 1 || ids.size() == 2);
970  IntegerCaloSamples samples1(ids[0], int(frame.samples()));
971  samples1.setPresamples(frame.presamples());
972  incoder_->adc2Linear(frame, samples1); // use linearization LUT
973  std::vector<unsigned short> bits12_15 = incoder_->group0FGbits(frame); // get 4 energy bits (12-15) from group 0 LUT
974 
975  bool is_compressed = false;
976  if (detId.subdet() == HcalBarrel) {
977  is_compressed = (frame.flavor() == 3);
978  // 0 if frame.flavor is 0 (uncompressed), 1 if frame.flavor is 3 (compressed)
979  }
980 
981  auto it = fgUpgradeTDCMap_.find(id);
982  if (it == fgUpgradeTDCMap_.end()) {
983  FGUpgradeTDCContainer element;
984  element.resize(frame.samples());
985  it = fgUpgradeTDCMap_.insert(std::make_pair(id, element)).first;
986  }
987  for (int i = 0; i < frame.samples(); i++) {
988  it->second[i][detId.depth() - 1] =
989  std::make_pair(std::make_pair(bits12_15[i], is_compressed), std::make_pair(frame[i].tdc(), samples1[i]));
990  }
991 }
992 
994  // Names are just abs(ieta) for HBHE
995  std::vector<std::string> ietaStrs = weightsQIE11.getParameterNames();
996  for (auto& ietaStr : ietaStrs) {
997  // Strip off "ieta" part of key and just use integer value in map
998  auto const& v = weightsQIE11.getParameter<std::vector<int>>(ietaStr);
999  weightsQIE11_[std::stoi(ietaStr.substr(4))] = {{v[0], v[1]}};
1000  }
1001 }
1002 
1004  // Simple map of |ieta| in HBHE to weight
1005  // Only one weight for SOI-1 TS
1006  weightsQIE11_[aieta] = {{weight, 255}};
1007 }
1008 
1010  if (algo <= 0 || algo > 2)
1011  throw cms::Exception("ERROR: Only algo 1 & 2 are supported.") << std::endl;
1013 }
1014 
1016 
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
constexpr uint32_t bits
Definition: gpuClustering.h:25
bool needLegacyFG(const HcalTrigTowerDetId &id) const
const HcalTPGCompressor * outcoder_
size_t size() const
Lenght of the data buffer in bytes.
Definition: FEDRawData.h:45
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)
std::array< std::array< int, 2 >, 29 > weightsQIE11_
constexpr uint32_t mask
Definition: gpuClustering.h:26
const HcalTopology & topology() const
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
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
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)
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
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
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)