CMS 3D CMS Logo

HBHEPhase1Reconstructor.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Package: RecoLocalCalo/HcalRecProducers
4 // Class: HBHEPhase1Reconstructor
5 //
13 //
14 // Original Author: Igor Volobouev
15 // Created: Tue, 21 Jun 2016 00:56:40 GMT
16 //
17 //
18 
19 // system include files
20 #include <cmath>
21 #include <vector>
22 #include <utility>
23 #include <algorithm>
24 
25 // user include files
33 
36 
42 
48 
50 
52 
57 
60 
61 // Parser for Phase 1 HB/HE reco algorithms
63 
64 // Some helper functions
65 namespace {
66  // Class for making SiPM/QIE11 look like HPD/QIE8. HPD/QIE8
67  // needs only pedestal and gain to convert charge into energy.
68  // Due to nonlinearities, response of SiPM/QIE11 is substantially
69  // more complicated. It is possible to calculate all necessary
70  // quantities from the charge and the info stored in the DB every
71  // time the raw charge is needed. However, it does not make sense
72  // to retrieve DB contents stored by channel for every time slice.
73  // Because of this, we look things up only once, in the constructor.
74  template <class DFrame>
75  class RawChargeFromSample {
76  public:
77  inline RawChargeFromSample(const int sipmQTSShift,
78  const int sipmQNTStoSum,
79  const HcalDbService& cond,
80  const HcalChannelProperties& properties,
81  const CaloSamples& cs,
82  const int soi,
83  const DFrame& frame,
84  const int maxTS) {}
85 
86  inline double getRawCharge(const double decodedCharge, const double pedestal) const { return decodedCharge; }
87  };
88 
89  template <>
90  class RawChargeFromSample<QIE11DataFrame> {
91  public:
92  inline RawChargeFromSample(const int sipmQTSShift,
93  const int sipmQNTStoSum,
94  const HcalDbService& cond,
95  const HcalChannelProperties& properties,
96  const CaloSamples& cs,
97  const int soi,
98  const QIE11DataFrame& frame,
99  const int maxTS)
100  : siPMParameter_(*properties.siPMParameter),
101  fcByPE_(siPMParameter_.getFCByPE()),
102  corr_(cond.getHcalSiPMCharacteristics()->getNonLinearities(siPMParameter_.getType())) {
103  if (fcByPE_ <= 0.0)
104  throw cms::Exception("HBHEPhase1BadDB") << "Invalid fC/PE conversion factor" << std::endl;
105 
106  const int firstTS = std::max(soi + sipmQTSShift, 0);
107  const int lastTS = std::min(firstTS + sipmQNTStoSum, maxTS);
108  double sipmQ = 0.0;
109 
110  for (int ts = firstTS; ts < lastTS; ++ts) {
111  const float pedestal = properties.pedsAndGains[frame[ts].capid()].pedestal(false);
112  sipmQ += (cs[ts] - pedestal);
113  }
114 
115  const double effectivePixelsFired = sipmQ / fcByPE_;
116  factor_ = corr_.getRecoCorrectionFactor(effectivePixelsFired);
117  }
118 
119  inline double getRawCharge(const double decodedCharge, const double pedestal) const {
120  return (decodedCharge - pedestal) * factor_ + pedestal;
121 
122  // Old version of TS-by-TS corrections looked as follows:
123  // const double sipmQ = decodedCharge - pedestal;
124  // const double nPixelsFired = sipmQ/fcByPE_;
125  // return sipmQ*corr_.getRecoCorrectionFactor(nPixelsFired) + pedestal;
126  }
127 
128  private:
129  const HcalSiPMParameter& siPMParameter_;
130  double fcByPE_;
131  HcalSiPMnonlinearity corr_;
132  double factor_;
133  };
134 
135  float getTDCTimeFromSample(const QIE11DataFrame::Sample& s) { return HcalSpecialTimes::getTDCTime(s.tdc()); }
136 
137  float getTDCTimeFromSample(const HcalQIESample&) { return HcalSpecialTimes::UNKNOWN_T_NOTDC; }
138 
139  float getDifferentialChargeGain(const HcalQIECoder& coder,
140  const HcalQIEShape& shape,
141  const unsigned adc,
142  const unsigned capid,
143  const bool isQIE11) {
144  // We have 5-bit ADC mantissa in QIE8 and 6-bit in QIE11
145  static const unsigned mantissaMaskQIE8 = 0x1f;
146  static const unsigned mantissaMaskQIE11 = 0x3f;
147 
148  const float q = coder.charge(shape, adc, capid);
149  const unsigned mantissaMask = isQIE11 ? mantissaMaskQIE11 : mantissaMaskQIE8;
150  const unsigned mantissa = adc & mantissaMask;
151 
152  // First, check if we are in the two lowest or two highest ADC
153  // values for this range. Assume that they have the lowest and
154  // the highest gain in the range, respectively.
155  if (mantissa == 0U || mantissa == mantissaMask - 1U)
156  return coder.charge(shape, adc + 1U, capid) - q;
157  else if (mantissa == 1U || mantissa == mantissaMask)
158  return q - coder.charge(shape, adc - 1U, capid);
159  else {
160  const float qup = coder.charge(shape, adc + 1U, capid);
161  const float qdown = coder.charge(shape, adc - 1U, capid);
162  const float upGain = qup - q;
163  const float downGain = q - qdown;
164  const float averageGain = (qup - qdown) / 2.f;
165  if (std::abs(upGain - downGain) < 0.01f * averageGain)
166  return averageGain;
167  else {
168  // We are in the gain transition region.
169  // Need to determine if we are in the lower
170  // gain ADC count or in the higher one.
171  // This can be done by figuring out if the
172  // "up" gain is more consistent then the
173  // "down" gain.
174  const float q2up = coder.charge(shape, adc + 2U, capid);
175  const float q2down = coder.charge(shape, adc - 2U, capid);
176  const float upGain2 = q2up - qup;
177  const float downGain2 = qdown - q2down;
178  if (std::abs(upGain2 - upGain) < std::abs(downGain2 - downGain))
179  return upGain;
180  else
181  return downGain;
182  }
183  }
184  }
185 
186  // The first element of the pair indicates presence of optical
187  // link errors. The second indicated presence of capid errors.
188  std::pair<bool, bool> findHWErrors(const HBHEDataFrame& df, const unsigned len) {
189  bool linkErr = false;
190  bool capidErr = false;
191  if (len) {
192  int expectedCapid = df[0].capid();
193  for (unsigned i = 0; i < len; ++i) {
194  if (df[i].er())
195  linkErr = true;
196  if (df[i].capid() != expectedCapid)
197  capidErr = true;
198  expectedCapid = (expectedCapid + 1) % 4;
199  }
200  }
201  return std::pair<bool, bool>(linkErr, capidErr);
202  }
203 
204  std::pair<bool, bool> findHWErrors(const QIE11DataFrame& df, const unsigned /* len */) {
205  return std::pair<bool, bool>(df.linkError(), df.capidError());
206  }
207 
208  std::unique_ptr<HBHEStatusBitSetter> parse_HBHEStatusBitSetter(const edm::ParameterSet& psdigi) {
209  return std::make_unique<HBHEStatusBitSetter>(
210  psdigi.getParameter<double>("nominalPedestal"),
211  psdigi.getParameter<double>("hitEnergyMinimum"),
212  psdigi.getParameter<int>("hitMultiplicityThreshold"),
213  psdigi.getParameter<std::vector<edm::ParameterSet> >("pulseShapeParameterSets"));
214  }
215 
216  std::unique_ptr<HBHEPulseShapeFlagSetter> parse_HBHEPulseShapeFlagSetter(const edm::ParameterSet& psPulseShape,
217  const bool setLegacyFlags) {
218  return std::make_unique<HBHEPulseShapeFlagSetter>(
219  psPulseShape.getParameter<double>("MinimumChargeThreshold"),
220  psPulseShape.getParameter<double>("TS4TS5ChargeThreshold"),
221  psPulseShape.getParameter<double>("TS3TS4ChargeThreshold"),
222  psPulseShape.getParameter<double>("TS3TS4UpperChargeThreshold"),
223  psPulseShape.getParameter<double>("TS5TS6ChargeThreshold"),
224  psPulseShape.getParameter<double>("TS5TS6UpperChargeThreshold"),
225  psPulseShape.getParameter<double>("R45PlusOneRange"),
226  psPulseShape.getParameter<double>("R45MinusOneRange"),
227  psPulseShape.getParameter<unsigned int>("TrianglePeakTS"),
228  psPulseShape.getParameter<std::vector<double> >("LinearThreshold"),
229  psPulseShape.getParameter<std::vector<double> >("LinearCut"),
230  psPulseShape.getParameter<std::vector<double> >("RMS8MaxThreshold"),
231  psPulseShape.getParameter<std::vector<double> >("RMS8MaxCut"),
232  psPulseShape.getParameter<std::vector<double> >("LeftSlopeThreshold"),
233  psPulseShape.getParameter<std::vector<double> >("LeftSlopeCut"),
234  psPulseShape.getParameter<std::vector<double> >("RightSlopeThreshold"),
235  psPulseShape.getParameter<std::vector<double> >("RightSlopeCut"),
236  psPulseShape.getParameter<std::vector<double> >("RightSlopeSmallThreshold"),
237  psPulseShape.getParameter<std::vector<double> >("RightSlopeSmallCut"),
238  psPulseShape.getParameter<std::vector<double> >("TS4TS5LowerThreshold"),
239  psPulseShape.getParameter<std::vector<double> >("TS4TS5LowerCut"),
240  psPulseShape.getParameter<std::vector<double> >("TS4TS5UpperThreshold"),
241  psPulseShape.getParameter<std::vector<double> >("TS4TS5UpperCut"),
242  psPulseShape.getParameter<bool>("UseDualFit"),
243  psPulseShape.getParameter<bool>("TriangleIgnoreSlow"),
244  setLegacyFlags);
245  }
246 
247  // Determine array index shift so that a partial copy
248  // of an array maps index "soi" into index "soiWanted"
249  // under the constraint that there must be no out of
250  // bounds access.
251  const int determineIndexShift(const int soi, const int nRead, const int soiWanted, const int nReadWanted) {
252  assert(nReadWanted <= nRead);
253  if (soi < 0 || soi >= nRead)
254  return 0;
255  else
256  return std::clamp(soi - soiWanted, 0, nRead - nReadWanted);
257  }
258 
259  // Function for packing TDC data from the QIE11 data frame.
260  // We want to pack five 6-bit TDC counts so that the soi
261  // falls on index 3.
262  uint32_t packTDCData(const QIE11DataFrame& frame, const int soi) {
263  using namespace CaloRecHitAuxSetter;
264 
265  const unsigned six_bits_mask = 0x3f;
266  const int soiWanted = 3;
267  const int nRead = frame.size();
268  const int nTSToCopy = std::min(5, nRead);
269  const int tsShift = determineIndexShift(soi, nRead, soiWanted, nTSToCopy);
270 
271  uint32_t packed = 0;
272  for (int ts = 0; ts < nTSToCopy; ++ts)
273  setField(&packed, six_bits_mask, ts * 6, frame[ts + tsShift].tdc());
274 
275  // Set bit 30 indicating presence of TDC values
276  setBit(&packed, 30, true);
277  return packed;
278  }
279 } // namespace
280 
281 //
282 // class declaration
283 //
285 public:
287  ~HBHEPhase1Reconstructor() override;
288 
289  static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
290 
291 private:
292  void beginRun(edm::Run const&, edm::EventSetup const&) override;
293  void endRun(edm::Run const&, edm::EventSetup const&) override;
294  void produce(edm::Event&, const edm::EventSetup&) override;
295 
296  // Configuration parameters
304  bool tsFromDB_;
307  bool use8ts_;
310 
311  // Parameters for turning status bit setters on/off
318 
319  // Other members
322  std::unique_ptr<AbsHBHEPhase1Algo> reco_;
323  std::unique_ptr<AbsHcalAlgoData> recoConfig_;
325 
326  // Status bit setters
327  const HBHENegativeEFilter* negEFilter_; // We don't manage this pointer
328  std::unique_ptr<HBHEStatusBitSetter> hbheFlagSetterQIE8_;
329  std::unique_ptr<HBHEStatusBitSetter> hbheFlagSetterQIE11_;
330  std::unique_ptr<HBHEPulseShapeFlagSetter> hbhePulseShapeFlagSetterQIE8_;
331  std::unique_ptr<HBHEPulseShapeFlagSetter> hbhePulseShapeFlagSetterQIE11_;
332 
333  // ES tokens
339 
340  // For the function below, arguments "infoColl" and/or "rechits"
341  // are allowed to be null.
342  template <class DataFrame, class Collection>
343  void processData(const Collection& coll,
344  const HcalTopology& htopo,
345  const HcalDbService& cond,
346  const HcalChannelPropertiesVec& prop,
347  const bool isRealData,
349  HBHEChannelInfoCollection* infoColl,
350  HBHERecHitCollection* rechits);
351 
352  // Methods for setting rechit status bits
354  const HcalCoder& coder,
355  const HBHEChannelInfo& info,
356  const HcalCalibrations& calib,
357  int soi,
358  HBHERecHit* rh);
360  const HcalCoder& coder,
361  const HBHEChannelInfo& info,
362  const HcalCalibrations& calib,
363  int soi,
364  HBHERecHit* rh);
366 
368 };
369 
370 //
371 // constructors and destructor
372 //
374  : algoConfigClass_(conf.getParameter<std::string>("algoConfigClass")),
375  processQIE8_(conf.getParameter<bool>("processQIE8")),
376  processQIE11_(conf.getParameter<bool>("processQIE11")),
377  saveInfos_(conf.getParameter<bool>("saveInfos")),
378  saveDroppedInfos_(conf.getParameter<bool>("saveDroppedInfos")),
379  makeRecHits_(conf.getParameter<bool>("makeRecHits")),
380  dropZSmarkedPassed_(conf.getParameter<bool>("dropZSmarkedPassed")),
381  tsFromDB_(conf.getParameter<bool>("tsFromDB")),
382  recoParamsFromDB_(conf.getParameter<bool>("recoParamsFromDB")),
383  saveEffectivePedestal_(conf.getParameter<bool>("saveEffectivePedestal")),
384  use8ts_(conf.getParameter<bool>("use8ts")),
385  sipmQTSShift_(conf.getParameter<int>("sipmQTSShift")),
386  sipmQNTStoSum_(conf.getParameter<int>("sipmQNTStoSum")),
387  setNegativeFlagsQIE8_(conf.getParameter<bool>("setNegativeFlagsQIE8")),
388  setNegativeFlagsQIE11_(conf.getParameter<bool>("setNegativeFlagsQIE11")),
389  setNoiseFlagsQIE8_(conf.getParameter<bool>("setNoiseFlagsQIE8")),
390  setNoiseFlagsQIE11_(conf.getParameter<bool>("setNoiseFlagsQIE11")),
391  setPulseShapeFlagsQIE8_(conf.getParameter<bool>("setPulseShapeFlagsQIE8")),
392  setPulseShapeFlagsQIE11_(conf.getParameter<bool>("setPulseShapeFlagsQIE11")),
393  reco_(parseHBHEPhase1AlgoDescription(conf.getParameter<edm::ParameterSet>("algorithm"), consumesCollector())),
394  negEFilter_(nullptr) {
395  // Check that the reco algorithm has been successfully configured
396  if (!reco_.get())
397  throw cms::Exception("HBHEPhase1BadConfig") << "Invalid HBHEPhase1Algo algorithm configuration" << std::endl;
398  if (reco_->isConfigurable()) {
399  if ("HFPhase1PMTParams" != algoConfigClass_) {
400  throw cms::Exception("HBHEPhase1BadConfig")
401  << "Invalid HBHEPhase1Reconstructor \"algoConfigClass\" parameter value \"" << algoConfigClass_ << '"'
402  << std::endl;
403  }
404  recoConfigToken_ = esConsumes<edm::Transition::BeginRun>();
405  }
406 
407  // Configure the status bit setters that have been turned on
408  if (setNoiseFlagsQIE8_)
409  hbheFlagSetterQIE8_ = parse_HBHEStatusBitSetter(conf.getParameter<edm::ParameterSet>("flagParametersQIE8"));
410 
412  hbheFlagSetterQIE11_ = parse_HBHEStatusBitSetter(conf.getParameter<edm::ParameterSet>("flagParametersQIE11"));
413 
416  parse_HBHEPulseShapeFlagSetter(conf.getParameter<edm::ParameterSet>("pulseShapeParametersQIE8"),
417  conf.getParameter<bool>("setLegacyFlagsQIE8"));
418 
421  parse_HBHEPulseShapeFlagSetter(conf.getParameter<edm::ParameterSet>("pulseShapeParametersQIE11"),
422  conf.getParameter<bool>("setLegacyFlagsQIE11"));
423 
424  // Consumes and produces statements
425  if (processQIE8_)
426  tok_qie8_ = consumes<HBHEDigiCollection>(conf.getParameter<edm::InputTag>("digiLabelQIE8"));
427 
428  if (processQIE11_)
429  tok_qie11_ = consumes<QIE11DigiCollection>(conf.getParameter<edm::InputTag>("digiLabelQIE11"));
430 
431  if (saveInfos_)
432  produces<HBHEChannelInfoCollection>();
433 
434  if (makeRecHits_)
435  produces<HBHERecHitCollection>();
436 
437  // ES tokens
438  htopoToken_ = esConsumes<HcalTopology, HcalRecNumberingRecord>();
439  conditionsToken_ = esConsumes<HcalDbService, HcalDbRecord>();
440  propertiesToken_ = esConsumes<HcalChannelPropertiesVec, HcalChannelPropertiesRecord>();
442  negToken_ = esConsumes<HBHENegativeEFilter, HBHENegativeEFilterRcd>();
444  feMapToken_ = esConsumes<HcalFrontEndMap, HcalFrontEndMapRcd, edm::Transition::BeginRun>();
445 }
446 
448  // do anything here that needs to be done at destruction time
449  // (e.g. close files, deallocate resources etc.)
450 }
451 
452 //
453 // member functions
454 //
455 template <class DFrame, class Collection>
456 void HBHEPhase1Reconstructor::processData(const Collection& coll,
457  const HcalTopology& htopo,
458  const HcalDbService& cond,
459  const HcalChannelPropertiesVec& prop,
460  const bool isRealData,
461  HBHEChannelInfo* channelInfo,
463  HBHERecHitCollection* rechits) {
464  // If "saveDroppedInfos_" flag is set, fill the info with something
465  // meaningful even if the database tells us to drop this channel.
466  // Note that this flag affects only "infos", the rechits are still
467  // not going to be constructed from such channels.
468  const bool skipDroppedChannels = !(infos && saveDroppedInfos_);
469 
470  // Iterate over the input collection
471  for (typename Collection::const_iterator it = coll.begin(); it != coll.end(); ++it) {
472  const DFrame& frame(*it);
473  const HcalDetId cell(frame.id());
474 
475  // Protection against calibration channels which are not
476  // in the database but can still come in the QIE11DataFrame
477  // in the laser calibs, etc.
478  const HcalSubdetector subdet = cell.subdet();
479  if (!(subdet == HcalSubdetector::HcalBarrel || subdet == HcalSubdetector::HcalEndcap))
480  continue;
481 
482  // Look up the channel properties. This lookup is O(1).
483  const HcalChannelProperties& properties(prop.at(htopo.detId2denseId(cell)));
484 
485  // Check if the database tells us to drop this channel
486  if (properties.taggedBadByDb && skipDroppedChannels)
487  continue;
488 
489  // Check if the channel is zero suppressed
490  bool dropByZS = false;
492  if (frame.zsMarkAndPass())
493  dropByZS = true;
494  if (dropByZS && skipDroppedChannels)
495  continue;
496 
497  // ADC decoding tool
498  const HcalCoderDb coder(*properties.channelCoder, *properties.shape);
499 
500  const bool saveEffectivePeds = channelInfo->hasEffectivePedestals();
501  const double fcByPE = properties.siPMParameter->getFCByPE();
502  double darkCurrent = 0.;
503  double lambda = 0.;
504  const double noisecorr = properties.siPMParameter->getauxi2();
505  if (!saveEffectivePeds || saveInfos_) {
506  // needed for the dark current in the M2 in alternative of the effectivePed
507  darkCurrent = properties.siPMParameter->getDarkCurrent();
508  lambda = cond.getHcalSiPMCharacteristics()->getCrossTalk(properties.siPMParameter->getType());
509  }
510 
511  // ADC to fC conversion
512  CaloSamples cs;
513  coder.adc2fC(frame, cs);
514 
515  // Prepare to iterate over time slices
516  const int nRead = cs.size();
517  const int maxTS = std::min(nRead, static_cast<int>(HBHEChannelInfo::MAXSAMPLES));
518  const int soi = tsFromDB_ ? properties.paramTs->firstSample() : frame.presamples();
519  const bool badSOI = !(maxTS >= 3 && soi > 0 && soi < maxTS - 1);
520  if (badSOI) {
521  edm::LogWarning("HBHEDigi") << " bad SOI/maxTS in cell " << cell
522  << "\n expect maxTS >= 3 && soi > 0 && soi < maxTS - 1"
523  << "\n got maxTS = " << maxTS << ", SOI = " << soi;
524  }
525 
526  const RawChargeFromSample<DFrame> rcfs(sipmQTSShift_, sipmQNTStoSum_, cond, properties, cs, soi, frame, maxTS);
527  int soiCapid = 4;
528 
529  // Typical expected cases:
530  // maxTS = 10, SOI = 4 (typical 10-TS situation, in data or MC)
531  // maxTS = 10, SOI = 5 (new, for better modeling of SiPM noise in MC)
532  // maxTS = 8, SOI = 3 (typical 8-TS situation in data)
533  //
534  // We want to fill the HBHEChannelInfo object with either
535  // 8 or 10 time slices, depending on the maxTS value and
536  // on the "use8ts_" parameter setting. If we want 8 time
537  // slices in the HBHEChannelInfo, we want the SOI to fall
538  // on the time slice number 3. For now, this number is not
539  // expected to change and will be hardwired.
540  //
541  int nTSToCopy = maxTS;
542  int tsShift = 0;
543  if (maxTS > 8 && use8ts_) {
544  const int soiWanted = 3;
545 
546  // We need to chop off the excess time slices
547  // and configure the TS shift for filling
548  // HBHEChannelInfo from the data frame.
549  nTSToCopy = 8;
550  tsShift = determineIndexShift(soi, nRead, soiWanted, nTSToCopy);
551  }
552 
553  // Go over time slices and fill the samples
554  for (int copyTS = 0; copyTS < nTSToCopy; ++copyTS) {
555  const int inputTS = copyTS + tsShift;
556  auto s(frame[inputTS]);
557  const uint8_t adc = s.adc();
558  const int capid = s.capid();
559  const HcalPipelinePedestalAndGain& pAndGain(properties.pedsAndGains.at(capid));
560 
561  // Always use QIE-only pedestal for this computation
562  const double rawCharge = rcfs.getRawCharge(cs[inputTS], pAndGain.pedestal(false));
563  const float t = getTDCTimeFromSample(s);
564  const float dfc = getDifferentialChargeGain(
565  *properties.channelCoder, *properties.shape, adc, capid, channelInfo->hasTimeInfo());
566  channelInfo->setSample(copyTS,
567  adc,
568  dfc,
569  rawCharge,
570  pAndGain.pedestal(saveEffectivePeds),
571  pAndGain.pedestalWidth(saveEffectivePeds),
572  pAndGain.gain(),
573  pAndGain.gainWidth(),
574  t);
575  if (inputTS == soi)
576  soiCapid = capid;
577  }
578 
579  // Fill the overall channel info items
580  const int fitSoi = soi - tsShift;
581  const int pulseShapeID = properties.paramTs->pulseShapeID();
582  const std::pair<bool, bool> hwerr = findHWErrors(frame, maxTS);
583  channelInfo->setChannelInfo(cell,
584  pulseShapeID,
585  nTSToCopy,
586  fitSoi,
587  soiCapid,
588  darkCurrent,
589  fcByPE,
590  lambda,
591  noisecorr,
592  hwerr.first,
593  hwerr.second,
594  properties.taggedBadByDb || dropByZS || badSOI);
595 
596  // If needed, add the channel info to the output collection
597  const bool makeThisRechit = !channelInfo->isDropped();
598  if (infos && (saveDroppedInfos_ || makeThisRechit))
599  infos->push_back(*channelInfo);
600 
601  // Reconstruct the rechit
602  if (rechits && makeThisRechit) {
603  const HcalRecoParam* pptr = nullptr;
604  if (recoParamsFromDB_)
605  pptr = properties.paramTs;
606  HBHERecHit rh = reco_->reconstruct(*channelInfo, pptr, *properties.calib, isRealData);
607  if (rh.id().rawId()) {
608  setAsicSpecificBits(frame, coder, *channelInfo, *properties.calib, soi, &rh);
609  setCommonStatusBits(*channelInfo, *properties.calib, &rh);
610  rechits->push_back(rh);
611  }
612  }
613  }
614 }
615 
617  const HcalCalibrations& /* calib */,
618  HBHERecHit* /* rh */) {}
619 
621  const HcalCoder& coder,
622  const HBHEChannelInfo& info,
623  const HcalCalibrations& calib,
624  int /* soi */,
625  HBHERecHit* rh) {
626  if (setNoiseFlagsQIE8_)
627  hbheFlagSetterQIE8_->rememberHit(*rh);
628 
630  hbhePulseShapeFlagSetterQIE8_->SetPulseShapeFlags(*rh, frame, coder, calib);
631 
634 
635  rh->setAuxTDC(0U);
636 }
637 
639  const HcalCoder& coder,
640  const HBHEChannelInfo& info,
641  const HcalCalibrations& calib,
642  const int soi,
643  HBHERecHit* rh) {
645  hbheFlagSetterQIE11_->rememberHit(*rh);
646 
648  hbhePulseShapeFlagSetterQIE11_->SetPulseShapeFlags(*rh, frame, coder, calib);
649 
652 
653  rh->setAuxTDC(packTDCData(frame, soi));
654 }
655 
657  double ts[HBHEChannelInfo::MAXSAMPLES];
658  const unsigned nRead = info.nSamples();
659  for (unsigned i = 0; i < nRead; ++i)
660  ts[i] = info.tsCharge(i);
661  const bool passes = negEFilter_->checkPassFilter(info.id(), &ts[0], nRead);
662  if (!passes)
664 }
665 
666 // ------------ method called to produce the data ------------
668  using namespace edm;
669 
670  // Get the Hcal topology
671  const HcalTopology* htopo = &eventSetup.getData(htopoToken_);
672 
673  // Fetch the calibrations
675  const HcalChannelPropertiesVec* prop = &eventSetup.getData(propertiesToken_);
676 
677  // Configure the negative energy filter
679  negEFilter_ = &eventSetup.getData(negToken_);
680  }
681 
682  // Find the input data
683  unsigned maxOutputSize = 0;
685  if (processQIE8_) {
686  e.getByToken(tok_qie8_, hbDigis);
687  maxOutputSize += hbDigis->size();
688  }
689 
691  if (processQIE11_) {
692  e.getByToken(tok_qie11_, heDigis);
693  maxOutputSize += heDigis->size();
694  }
695 
696  // Create new output collections
697  std::unique_ptr<HBHEChannelInfoCollection> infos;
698  if (saveInfos_) {
699  infos = std::make_unique<HBHEChannelInfoCollection>();
700  infos->reserve(maxOutputSize);
701  }
702 
703  std::unique_ptr<HBHERecHitCollection> out;
704  if (makeRecHits_) {
705  out = std::make_unique<HBHERecHitCollection>();
706  out->reserve(maxOutputSize);
707  }
708 
709  // Process the input collections, filling the output ones
710  const bool isData = e.isRealData();
711  if (processQIE8_) {
712  if (setNoiseFlagsQIE8_)
713  hbheFlagSetterQIE8_->Clear();
714 
715  HBHEChannelInfo channelInfo(false, false);
716  processData<HBHEDataFrame>(*hbDigis, *htopo, *conditions, *prop, isData, &channelInfo, infos.get(), out.get());
717  if (setNoiseFlagsQIE8_)
718  hbheFlagSetterQIE8_->SetFlagsFromRecHits(*out);
719  }
720 
721  if (processQIE11_) {
723  hbheFlagSetterQIE11_->Clear();
724 
725  HBHEChannelInfo channelInfo(true, saveEffectivePedestal_);
726  processData<QIE11DataFrame>(*heDigis, *htopo, *conditions, *prop, isData, &channelInfo, infos.get(), out.get());
728  hbheFlagSetterQIE11_->SetFlagsFromRecHits(*out);
729  }
730 
731  // Add the output collections to the event record
732  if (saveInfos_)
733  e.put(std::move(infos));
734  if (makeRecHits_)
735  e.put(std::move(out));
736 }
737 
738 // ------------ method called when starting to processes a run ------------
740  if (reco_->isConfigurable()) {
741  recoConfig_ = std::make_unique<HFPhase1PMTParams>(es.getData(recoConfigToken_));
742  if (!reco_->configure(recoConfig_.get()))
743  throw cms::Exception("HBHEPhase1BadConfig")
744  << "Failed to configure HBHEPhase1Algo algorithm from EventSetup" << std::endl;
745  }
746 
748  if (auto handle = es.getHandle(feMapToken_)) {
749  const HcalFrontEndMap& hfemap = *handle;
750  if (setNoiseFlagsQIE8_)
751  hbheFlagSetterQIE8_->SetFrontEndMap(&hfemap);
753  hbheFlagSetterQIE11_->SetFrontEndMap(&hfemap);
754  } else {
755  edm::LogWarning("EventSetup") << "HBHEPhase1Reconstructor failed to get HcalFrontEndMap!" << std::endl;
756  }
757  }
758 
759  reco_->beginRun(r, es);
760 }
761 
763 
764 #define add_param_set(name) \
765  edm::ParameterSetDescription name; \
766  name.setAllowAnything(); \
767  desc.add<edm::ParameterSetDescription>(#name, name)
768 
769 // ------------ method fills 'descriptions' with the allowed parameters for the module ------------
772 
773  desc.add<edm::InputTag>("digiLabelQIE8");
774  desc.add<edm::InputTag>("digiLabelQIE11");
775  desc.add<std::string>("algoConfigClass");
776  desc.add<bool>("processQIE8");
777  desc.add<bool>("processQIE11");
778  desc.add<bool>("saveInfos");
779  desc.add<bool>("saveDroppedInfos");
780  desc.add<bool>("makeRecHits");
781  desc.add<bool>("dropZSmarkedPassed");
782  desc.add<bool>("tsFromDB");
783  desc.add<bool>("recoParamsFromDB");
784  desc.add<bool>("saveEffectivePedestal", false);
785  desc.add<bool>("use8ts", false);
786  desc.add<int>("sipmQTSShift", 0);
787  desc.add<int>("sipmQNTStoSum", 3);
788  desc.add<bool>("setNegativeFlagsQIE8");
789  desc.add<bool>("setNegativeFlagsQIE11");
790  desc.add<bool>("setNoiseFlagsQIE8");
791  desc.add<bool>("setNoiseFlagsQIE11");
792  desc.add<bool>("setPulseShapeFlagsQIE8");
793  desc.add<bool>("setPulseShapeFlagsQIE11");
794  desc.add<bool>("setLegacyFlagsQIE8");
795  desc.add<bool>("setLegacyFlagsQIE11");
796 
802 
803  descriptions.addDefault(desc);
804 }
805 
806 //define this as a plug-in
HBHEPhase1Reconstructor(const edm::ParameterSet &)
std::unique_ptr< HBHEPulseShapeFlagSetter > hbhePulseShapeFlagSetterQIE8_
constexpr void setBit(uint32_t *u, const unsigned bitnum, const bool b)
const HBHENegativeEFilter * negEFilter_
void processData(const Collection &coll, const HcalTopology &htopo, const HcalDbService &cond, const HcalChannelPropertiesVec &prop, const bool isRealData, HBHEChannelInfo *info, HBHEChannelInfoCollection *infoColl, HBHERecHitCollection *rechits)
T getParameter(std::string const &) const
Definition: ParameterSet.h:307
static const TGPicture * info(bool iBackgroundIsBlack)
const HcalSiPMParameter * siPMParameter
int maxTS(DIGI const &digi, double ped=0)
Definition: Utilities.h:103
edm::ESGetToken< HFPhase1PMTParams, HFPhase1PMTParamsRcd > recoConfigToken_
T const & getData(const ESGetToken< T, R > &iToken) const noexcept(false)
Definition: EventSetup.h:119
constexpr void setField(uint32_t *u, const unsigned mask, const unsigned offset, const unsigned value)
void setCommonStatusBits(const HBHEChannelInfo &info, const HcalCalibrations &calib, HBHERecHit *rh)
std::unique_ptr< HBHEStatusBitSetter > hbheFlagSetterQIE11_
std::unique_ptr< HBHEStatusBitSetter > hbheFlagSetterQIE8_
constexpr bool hasEffectivePedestals() const
size_type size() const
const HcalQIEShape * shape
void beginRun(edm::Run const &, edm::EventSetup const &) override
const HcalRecoParam * paramTs
constexpr unsigned int firstSample() const
Definition: HcalRecoParam.h:31
std::array< HcalPipelinePedestalAndGain, 4 > pedsAndGains
void push_back(T const &t)
unsigned int detId2denseId(const DetId &id) const override
return a linear packed id
edm::ESGetToken< HBHENegativeEFilter, HBHENegativeEFilterRcd > negToken_
float getFCByPE() const
get fcByPE
float getDarkCurrent() const
get dark current
std::unique_ptr< AbsHBHEPhase1Algo > parseHBHEPhase1AlgoDescription(const edm::ParameterSet &ps, edm::ConsumesCollector iC)
assert(be >=bs)
constexpr void setFlagField(uint32_t value, int base, int width=1)
Definition: CaloRecHit.h:36
constexpr void setAuxTDC(const uint32_t aux)
Definition: HBHERecHit.h:58
constexpr float getTDCTime(const int tdc)
constexpr HcalSubdetector subdet() const
get the subdetector
Definition: HcalDetId.h:138
void adc2fC(const HBHEDataFrame &df, CaloSamples &lf) const override
Definition: HcalCoderDb.cc:73
edm::ESGetToken< HcalTopology, HcalRecNumberingRecord > htopoToken_
void addDefault(ParameterSetDescription const &psetDescription)
static const unsigned MAXSAMPLES
void endRun(edm::Run const &, edm::EventSetup const &) override
constexpr unsigned int pulseShapeID() const
Definition: HcalRecoParam.h:33
std::vector< HcalChannelProperties > HcalChannelPropertiesVec
edm::EDGetTokenT< QIE11DigiCollection > tok_qie11_
edm::EDGetTokenT< HBHEDigiCollection > tok_qie8_
HcalSubdetector
Definition: HcalAssistant.h:31
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
double f[11][100]
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
std::unique_ptr< AbsHBHEPhase1Algo > reco_
void runHBHENegativeEFilter(const HBHEChannelInfo &info, HBHERecHit *rh)
ESHandle< T > getHandle(const ESGetToken< T, R > &iToken) const
Definition: EventSetup.h:130
constexpr void setChannelInfo(const HcalDetId &detId, const int recoShape, const unsigned nSamp, const unsigned iSoi, const int iCapid, const double darkCurrent, const double fcByPE, const double lambda, const double noisecorr, const bool linkError, const bool capidError, const bool dropThisChannel)
const HcalCalibrations * calib
edm::ESGetToken< HcalDbService, HcalDbRecord > conditionsToken_
std::unique_ptr< HBHEPulseShapeFlagSetter > hbhePulseShapeFlagSetterQIE11_
constexpr bool isDropped() const
constexpr HcalDetId id() const
get the id
Definition: HBHERecHit.h:41
edm::ESGetToken< HcalFrontEndMap, HcalFrontEndMapRcd > feMapToken_
constexpr uint32_t rawId() const
get the raw id
Definition: DetId.h:57
constexpr bool hasTimeInfo() const
float getauxi2() const
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
int getType() const
get SiPM type
constexpr float UNKNOWN_T_NOTDC
HLT enums.
std::unique_ptr< AbsHcalAlgoData > recoConfig_
Log< level::Warning, false > LogWarning
edm::ESGetToken< HcalChannelPropertiesVec, HcalChannelPropertiesRecord > propertiesToken_
bool checkPassFilter(const HcalDetId &id, const double *ts, unsigned lenTS) const
def move(src, dest)
Definition: eostools.py:511
void produce(edm::Event &, const edm::EventSetup &) override
float charge(const HcalQIEShape &fShape, unsigned fAdc, unsigned fCapId) const
ADC [0..127] + capid [0..3] -> fC conversion.
Definition: HcalQIECoder.cc:20
Definition: Run.h:45
constexpr void setSample(const unsigned ts, const uint8_t rawADC, const float differentialChargeGain, const double q, const double ped, const double pedWidth, const double g, const double gainWidth, const float t)
uint16_t *__restrict__ uint16_t const *__restrict__ adc
void setAsicSpecificBits(const HBHEDataFrame &frame, const HcalCoder &coder, const HBHEChannelInfo &info, const HcalCalibrations &calib, int soi, HBHERecHit *rh)
#define add_param_set(name)
edm::ParameterSetDescription fillDescriptionForParseHBHEPhase1Algo()
const HcalQIECoder * channelCoder