CMS 3D CMS Logo

SiStripAPVRestorer.cc
Go to the documentation of this file.
6 
7 #include <cmath>
8 #include <iostream>
9 #include <algorithm>
10 
12  : siStripRawDigiToken_(iC.consumes<edm::DetSetVector<SiStripRawDigi>>(edm::InputTag("siStripDigis", "VirginRaw"))),
13  siStripProcessedRawDigiToken_(
14  iC.consumes<edm::DetSetVector<SiStripProcessedRawDigi>>(edm::InputTag("MEANAPVCM"))),
15  qualityToken_(iC.esConsumes<SiStripQuality, SiStripQualityRcd>()),
16  noiseToken_(iC.esConsumes<SiStripNoises, SiStripNoisesRcd>()),
17  pedestalToken_(iC.esConsumes<SiStripPedestals, SiStripPedestalsRcd>()),
18  forceNoRestore_(conf.getParameter<bool>("ForceNoRestore")),
19  inspectAlgo_(conf.getParameter<std::string>("APVInspectMode")),
20  restoreAlgo_(conf.getParameter<std::string>("APVRestoreMode")),
21  // CM map settings
22  useRealMeanCM_(conf.getParameter<bool>("useRealMeanCM")),
23  meanCM_(conf.getParameter<int32_t>("MeanCM")),
24  deltaCMThreshold_(conf.getParameter<uint32_t>("DeltaCMThreshold")),
25  // abnormal baseline inspect
26  fraction_(conf.getParameter<double>("Fraction")),
27  deviation_(conf.getParameter<uint32_t>("Deviation")),
28  // nullInspect
29  restoreThreshold_(conf.getParameter<double>("restoreThreshold")),
30  // baseline and saturation inspect
31  nSaturatedStrip_(conf.getParameter<uint32_t>("nSaturatedStrip")),
32  // FlatRegionsFinder
33  nSigmaNoiseDerTh_(conf.getParameter<uint32_t>("nSigmaNoiseDerTh")),
34  consecThreshold_(conf.getParameter<uint32_t>("consecThreshold")),
35  nSmooth_(conf.getParameter<uint32_t>("nSmooth")),
36  distortionThreshold_(conf.getParameter<uint32_t>("distortionThreshold")),
37  applyBaselineCleaner_(conf.getParameter<bool>("ApplyBaselineCleaner")),
38  cleaningSequence_(conf.getParameter<uint32_t>("CleaningSequence")),
39  // cleaner_localmin
40  slopeX_(conf.getParameter<int32_t>("slopeX")),
41  slopeY_(conf.getParameter<int32_t>("slopeY")),
42  // cleaner_monotony
43  hitStripThreshold_(conf.getParameter<uint32_t>("hitStripThreshold")),
44  // baseline follower (restore)
45  minStripsToFit_(conf.getParameter<uint32_t>("minStripsToFit")),
46  applyBaselineRejection_(conf.getParameter<bool>("ApplyBaselineRejection")),
47  filteredBaselineMax_(conf.getParameter<double>("filteredBaselineMax")),
48  filteredBaselineDerivativeSumSquare_(conf.getParameter<double>("filteredBaselineDerivativeSumSquare")),
49  // derivative follower restorer
50  gradient_threshold_(conf.getParameter<int>("discontinuityThreshold")),
51  last_gradient_(conf.getParameter<int>("lastGradient")),
52  size_window_(conf.getParameter<int>("sizeWindow")),
53  width_cluster_(conf.getParameter<int>("widthCluster")) {
54  if (restoreAlgo_ == "BaselineFollower" && inspectAlgo_ != "BaselineFollower" && inspectAlgo_ != "Hybrid")
55  throw cms::Exception("Incompatible Algorithm")
56  << "The BaselineFollower restore method requires the BaselineFollower (or Hybrid) inspect method";
57 }
58 
60  if (noiseWatcher_.check(es)) {
62  }
63  if (qualityWatcher_.check(es)) {
65  }
66  if (pedestalWatcher_.check(es)) {
68  }
69 }
70 
72  uint16_t firstAPV,
73  const digivector_t& rawDigisPedSubtracted,
74  digivector_t& processedRawDigi,
75  const medians_t& vmedians) {
76  auto nAPVFlagged = inspect(detId, firstAPV, rawDigisPedSubtracted, vmedians);
77  restore(firstAPV, processedRawDigi);
78  return nAPVFlagged;
79 }
80 
82  uint16_t firstAPV,
83  const digivector_t& digis,
84  const medians_t& vmedians) {
85  detId_ = detId;
86 
87  apvFlags_.assign(6, "");
88  apvFlagsBoolOverride_.assign(6, false);
89  apvFlagsBool_.clear();
90  median_.assign(6, -999);
91  badAPVs_.assign(6, false);
92  smoothedMaps_.clear();
93  baselineMap_.clear();
94  for (const auto& med : vmedians) {
95  auto iAPV = med.first;
96  median_[iAPV] = med.second;
97  badAPVs_[iAPV] = qualityHandle->IsApvBad(detId_, iAPV);
98  }
99 
100  uint16_t nAPVFlagged = 0;
101  if (inspectAlgo_ == "Hybrid")
102  nAPVFlagged = hybridFormatInspect(firstAPV, digis);
103  else if (inspectAlgo_ == "HybridEmulation")
104  nAPVFlagged = hybridEmulationInspect(firstAPV, digis);
105  else if (inspectAlgo_ == "BaselineFollower")
106  nAPVFlagged = baselineFollowerInspect(firstAPV, digis);
107  else if (inspectAlgo_ == "AbnormalBaseline")
108  nAPVFlagged = abnormalBaselineInspect(firstAPV, digis);
109  else if (inspectAlgo_ == "Null")
110  nAPVFlagged = nullInspect(firstAPV, digis);
111  else if (inspectAlgo_ == "BaselineAndSaturation")
112  nAPVFlagged = baselineAndSaturationInspect(firstAPV, digis);
113  else if (inspectAlgo_ == "DerivativeFollower")
114  nAPVFlagged = forceRestoreInspect(firstAPV, digis);
115  else
116  throw cms::Exception("Unregistered Inspect Algorithm")
117  << "SiStripAPVRestorer possibilities: (Null), (AbnormalBaseline), (BaselineFollower), (BaselineAndSaturation), "
118  "(DerivativeFollower), (Hybrid), (HybridEmulation)";
119 
120  // update boolean version of APV flags
121  for (size_t i = 0; i < apvFlags_.size(); ++i) {
122  apvFlagsBool_.push_back((!apvFlags_[i].empty()) && (!apvFlagsBoolOverride_[i]));
123  }
124 
125  return nAPVFlagged;
126 }
127 
128 void SiStripAPVRestorer::restore(uint16_t firstAPV, digivector_t& digis) {
129  if (forceNoRestore_)
130  return;
131 
132  for (uint16_t iAPV = firstAPV; iAPV < digis.size() / nTotStripsPerAPV + firstAPV; ++iAPV) {
133  auto algoToUse = apvFlags_[iAPV];
134  if (!algoToUse.empty()) {
135  if (algoToUse == "Flat") {
136  flatRestore(iAPV, firstAPV, digis);
137  } else if (algoToUse == "BaselineFollower") {
138  baselineFollowerRestore(iAPV, firstAPV, median_[iAPV], digis);
139  } else if (algoToUse == "DerivativeFollower") {
140  derivativeFollowerRestore(iAPV, firstAPV, digis);
141  } else {
142  throw cms::Exception("Unregistered Restore Algorithm")
143  << "SiStripAPVRestorer possibilities: (Flat), (BaselineFollower), (DerivativeFollower)";
144  }
145  }
146  }
147 }
148 
149 // Inspect method implementations
150 
151 inline uint16_t SiStripAPVRestorer::hybridFormatInspect(uint16_t firstAPV, const digivector_t& digis) {
152  digivector_t singleAPVdigi;
153  singleAPVdigi.reserve(nTotStripsPerAPV);
154  uint16_t nAPVflagged = 0;
155  for (uint16_t iAPV = firstAPV; iAPV < digis.size() / nTotStripsPerAPV + firstAPV; ++iAPV) {
156  digimap_t smoothedmap;
157  if (!badAPVs_[iAPV]) {
158  uint16_t stripsPerAPV = 0;
159  singleAPVdigi.clear();
160  for (int16_t strip = (iAPV - firstAPV) * nTotStripsPerAPV; strip < (iAPV - firstAPV + 1) * nTotStripsPerAPV;
161  ++strip) {
162  const uint16_t adc = digis[strip];
163  singleAPVdigi.push_back(adc);
164  if (adc > 0)
165  ++stripsPerAPV;
166  }
167 
168  if (stripsPerAPV > 64) {
169  flatRegionsFinder(singleAPVdigi, smoothedmap, iAPV);
170  apvFlags_[iAPV] = restoreAlgo_; //specify any algo to make the restore
171  nAPVflagged++;
172  }
173  }
174  smoothedMaps_.emplace_hint(smoothedMaps_.end(), iAPV, std::move(smoothedmap));
175  }
176  return nAPVflagged;
177 }
178 
179 inline uint16_t SiStripAPVRestorer::baselineFollowerInspect(uint16_t firstAPV, const digivector_t& digis) {
180  digivector_t singleAPVdigi;
181  singleAPVdigi.reserve(nTotStripsPerAPV);
182  uint16_t nAPVflagged = 0;
183 
184  auto itCMMap = std::end(meanCMmap_);
185  if (useRealMeanCM_)
186  itCMMap = meanCMmap_.find(detId_);
187 
188  for (uint16_t iAPV = firstAPV; iAPV < firstAPV + digis.size() / nTotStripsPerAPV; ++iAPV) {
189  digimap_t smoothedmap;
190  if (!badAPVs_[iAPV]) {
191  float MeanAPVCM = meanCM_;
192  if (useRealMeanCM_ && (std::end(meanCMmap_) != itCMMap))
193  MeanAPVCM = itCMMap->second[iAPV];
194 
195  singleAPVdigi.clear();
196  std::copy_n(std::begin(digis) + nTotStripsPerAPV * (iAPV - firstAPV),
198  std::back_inserter(singleAPVdigi));
199 
200  const float DeltaCM = median_[iAPV] - MeanAPVCM;
201  if ((DeltaCM < 0) && (std::abs(DeltaCM) > deltaCMThreshold_)) {
202  if (!flatRegionsFinder(singleAPVdigi, smoothedmap, iAPV)) {
203  apvFlags_[iAPV] = restoreAlgo_; //specify any algo to make the restore
204  ++nAPVflagged;
205  }
206  }
207  }
208  smoothedMaps_.emplace_hint(smoothedMaps_.end(), iAPV, std::move(smoothedmap));
209  }
210  return nAPVflagged;
211 }
212 
213 inline uint16_t SiStripAPVRestorer::forceRestoreInspect(uint16_t firstAPV, const digivector_t& digis) {
214  uint16_t nAPVflagged = 0;
215  for (uint16_t iAPV = firstAPV; iAPV < firstAPV + digis.size() / nTotStripsPerAPV; ++iAPV) {
216  if (!badAPVs_[iAPV]) {
217  apvFlags_[iAPV] = restoreAlgo_; //specify any algo to make the restore
218  nAPVflagged++;
219  }
220  }
221  return nAPVflagged;
222 }
223 
224 inline uint16_t SiStripAPVRestorer::baselineAndSaturationInspect(uint16_t firstAPV, const digivector_t& digis) {
225  digivector_t singleAPVdigi;
226  singleAPVdigi.reserve(nTotStripsPerAPV);
227  uint16_t nAPVflagged = 0;
228 
229  auto itCMMap = std::end(meanCMmap_);
230  if (useRealMeanCM_)
231  itCMMap = meanCMmap_.find(detId_);
232 
233  for (uint16_t iAPV = firstAPV; iAPV < firstAPV + digis.size() / nTotStripsPerAPV; ++iAPV) {
234  if (!badAPVs_[iAPV]) {
235  float MeanAPVCM = meanCM_;
236  if (useRealMeanCM_ && (std::end(meanCMmap_) != itCMMap))
237  MeanAPVCM = itCMMap->second[iAPV];
238 
239  singleAPVdigi.clear();
240  uint16_t nSatStrip = 0;
241  for (int16_t strip = (iAPV - firstAPV) * nTotStripsPerAPV; strip < (iAPV - firstAPV + 1) * nTotStripsPerAPV;
242  ++strip) {
243  const uint16_t digi = digis[strip];
244  singleAPVdigi.push_back(digi);
245  if (digi >= 1023)
246  ++nSatStrip;
247  }
248 
249  const float DeltaCM = median_[iAPV] - MeanAPVCM;
250  if ((DeltaCM < 0) && (std::abs(DeltaCM) > deltaCMThreshold_) && (nSatStrip >= nSaturatedStrip_)) {
251  apvFlags_[iAPV] = restoreAlgo_; //specify any algo to make the restore
252  ++nAPVflagged;
253  }
254  }
255  }
256  return nAPVflagged;
257 }
258 
259 inline uint16_t SiStripAPVRestorer::abnormalBaselineInspect(uint16_t firstAPV, const digivector_t& digis) {
261 
262  uint16_t nAPVflagged = 0;
263 
264  auto itCMMap = std::end(meanCMmap_);
265  if (useRealMeanCM_)
266  itCMMap = meanCMmap_.find(detId_);
267 
268  int devCount = 0, qualityCount = 0, minstrip = 0;
269  for (uint16_t iAPV = firstAPV; iAPV < firstAPV + digis.size() / nTotStripsPerAPV; ++iAPV) {
270  if (!badAPVs_[iAPV]) {
271  float MeanAPVCM = meanCM_;
272  if (useRealMeanCM_ && (std::end(meanCMmap_) != itCMMap))
273  MeanAPVCM = itCMMap->second[iAPV];
274 
275  for (uint16_t istrip = iAPV * nTotStripsPerAPV; istrip < (iAPV + 1) * nTotStripsPerAPV; ++istrip) {
276  const auto fs = static_cast<int>(digis[istrip - firstAPV * nTotStripsPerAPV]);
277  if (!qualityHandle->IsStripBad(detQualityRange, istrip)) {
278  qualityCount++;
279  if (std::abs(fs - MeanAPVCM) > static_cast<int>(deviation_)) {
280  devCount++;
281  minstrip = std::min(fs, minstrip);
282  }
283  }
284  }
285  if (devCount > fraction_ * qualityCount) {
286  apvFlags_[iAPV] = restoreAlgo_; //specify any algo to make the restore
287  nAPVflagged++;
288  }
289  }
290  }
291  return nAPVflagged;
292 }
293 
294 inline uint16_t SiStripAPVRestorer::nullInspect(uint16_t firstAPV, const digivector_t& digis) {
296 
297  uint16_t nAPVflagged = 0;
298  for (uint16_t iAPV = firstAPV; iAPV < firstAPV + digis.size() / nTotStripsPerAPV; ++iAPV) {
299  if (!badAPVs_[iAPV]) {
300  int zeroCount = 0, qualityCount = 0;
301  for (uint16_t istrip = iAPV * nTotStripsPerAPV; istrip < (iAPV + 1) * nTotStripsPerAPV; ++istrip) {
302  const auto fs = static_cast<int>(digis[istrip - firstAPV * nTotStripsPerAPV]);
303  if (!qualityHandle->IsStripBad(detQualityRange, istrip)) {
304  qualityCount++;
305  if (fs < 1)
306  zeroCount++;
307  }
308  }
309  if (zeroCount > restoreThreshold_ * qualityCount) {
310  apvFlags_[iAPV] = restoreAlgo_; //specify any algo to make the restore
311  nAPVflagged++;
312  }
313  }
314  }
315  return nAPVflagged;
316 }
317 
318 inline uint16_t SiStripAPVRestorer::hybridEmulationInspect(uint16_t firstAPV, const digivector_t& digis) {
319  uint16_t nAPVflagged = 0;
320 
321  auto itCMMap = std::end(meanCMmap_);
322  if (useRealMeanCM_)
323  itCMMap = meanCMmap_.find(detId_);
324 
325  for (uint16_t iAPV = firstAPV; iAPV < firstAPV + digis.size() / nTotStripsPerAPV; ++iAPV) {
326  if (!badAPVs_[iAPV]) {
327  float MeanAPVCM = meanCM_;
328  if (useRealMeanCM_ && (std::end(meanCMmap_) != itCMMap))
329  MeanAPVCM = itCMMap->second[iAPV];
330 
331  const float DeltaCM = median_[iAPV] - (MeanAPVCM + 1024) / 2;
332  if ((DeltaCM < 0) && (std::abs(DeltaCM) > deltaCMThreshold_ / 2)) {
333  apvFlags_[iAPV] = "HybridEmulation";
334  ++nAPVflagged;
335  }
336  }
337  }
338  return nAPVflagged;
339 }
340 
341 // Restore method implementations
342 
344  uint16_t firstAPV,
345  float median,
346  digivector_t& digis) {
347  digivector_t baseline(size_t(nTotStripsPerAPV), 0);
348 
349  //============================= Find Flat Regions & Interpolating the baseline & subtracting the baseline =================
350  if (!smoothedMaps_.empty()) {
351  auto itSmootedMap = smoothedMaps_.find(apvN);
352  baselineFollower(itSmootedMap->second, baseline, median);
353  } else {
354  //median=0;
355  digivector_t singleAPVdigi;
356  singleAPVdigi.reserve(nTotStripsPerAPV);
357  std::copy_n(
358  std::begin(digis) + nTotStripsPerAPV * (apvN - firstAPV), nTotStripsPerAPV, std::back_inserter(singleAPVdigi));
359  digimap_t smoothedpoints;
360  flatRegionsFinder(singleAPVdigi, smoothedpoints, apvN);
361  baselineFollower(smoothedpoints, baseline, median);
362  }
363 
365  if (checkBaseline(baseline))
366  apvFlagsBoolOverride_[apvN] = true;
367  }
368 
369  //============================= subtracting the baseline =============================================
370  for (int16_t itStrip = 0; itStrip < nTotStripsPerAPV; ++itStrip) {
371  digis[nTotStripsPerAPV * (apvN - firstAPV) + itStrip] -= baseline[itStrip] - median;
372  }
373 
374  //============================= storing baseline to the map =============================================
375  baselineMap_.emplace_hint(baselineMap_.end(), apvN, std::move(baseline));
376 }
377 
378 inline void SiStripAPVRestorer::flatRestore(uint16_t apvN, uint16_t firstAPV, digivector_t& digis) {
379  digivector_t baseline(size_t(nTotStripsPerAPV), 150);
380  baseline[0] = 0;
381  baseline[nTotStripsPerAPV - 1] = 0;
382 
383  for (int16_t itStrip = 0; itStrip < nTotStripsPerAPV; ++itStrip) {
384  digis[nTotStripsPerAPV * (apvN - firstAPV) + itStrip] = baseline[itStrip];
385  }
386  baselineMap_.emplace_hint(baselineMap_.end(), apvN, std::move(baseline));
387 }
388 
389 // Baseline calculation implementation =========================================
390 bool inline SiStripAPVRestorer::flatRegionsFinder(const digivector_t& adcs, digimap_t& smoothedpoints, uint16_t apvN) {
391  smoothedpoints.clear();
392 
394 
395  //============================= Height above local minimum ===============================
396  std::vector<float> adcsLocalMinSubtracted(size_t(nTotStripsPerAPV), 0);
397  for (uint32_t istrip = 0; istrip < nTotStripsPerAPV; ++istrip) {
398  float localmin = 999.9;
399  for (uint16_t jstrip = std::max(0, static_cast<int>(istrip - nSmooth_ / 2));
400  jstrip < std::min((int)nTotStripsPerAPV, static_cast<int>(istrip + nSmooth_ / 2));
401  ++jstrip) {
402  const float nextvalue = adcs[jstrip];
403  if (nextvalue < localmin)
404  localmin = nextvalue;
405  }
406  adcsLocalMinSubtracted[istrip] = adcs[istrip] - localmin;
407  }
408 
409  //============================= Find regions with stable slopes ========================
410  digimap_t consecpoints;
411  std::vector<uint16_t> nConsStrip;
412  //Creating maps with all the neighborhood strip and putting in a nCosntStip vector how many we have
413  uint16_t consecStrips = 0;
414  for (uint32_t istrip = 0; istrip < nTotStripsPerAPV; ++istrip) {
415  const int16_t adc = adcs[istrip];
416  //if( adcsLocalMinSubtracted[istrip] < nSigmaNoiseDerTh_ * (float)noiseHandle->getNoise(istrip+apvN*128,detNoiseRange) && (adc - median) < hitStripThreshold_){
417  if (adcsLocalMinSubtracted[istrip] <
418  nSigmaNoiseDerTh_ * (float)noiseHandle->getNoiseFast(istrip + apvN * nTotStripsPerAPV, detNoiseRange)) {
419  consecpoints.emplace_hint(consecpoints.end(), istrip, adc);
420  ++consecStrips;
421  } else if (consecStrips > 0) {
422  nConsStrip.push_back(consecStrips);
423  consecStrips = 0;
424  }
425  }
426  //to cope with the last flat region of the APV
427  if (consecStrips > 0)
428  nConsStrip.push_back(consecStrips);
429 
430  //removing from the map the fist and last points in wide flat regions and erasing from the map too small regions
431  auto itConsecpoints = consecpoints.begin();
432  float MinSmoothValue = 20000., MaxSmoothValue = 0.;
433  for (const auto consecStrips : nConsStrip) {
434  if (consecStrips >= consecThreshold_) {
435  ++itConsecpoints; //skipping first point
436  uint16_t nFirstStrip = itConsecpoints->first;
437  uint16_t nLastStrip;
438  float smoothValue = 0.0;
439  float stripCount = 1;
440  for (uint16_t n = 0; n < consecStrips - 2; ++n) {
441  smoothValue += itConsecpoints->second;
442  if (stripCount == consecThreshold_) {
443  smoothValue /= (float)stripCount;
444  nLastStrip = nFirstStrip + stripCount - 1;
445  smoothedpoints.emplace_hint(smoothedpoints.end(), nFirstStrip, smoothValue);
446  smoothedpoints.emplace_hint(smoothedpoints.end(), nLastStrip, smoothValue);
447  if (smoothValue > MaxSmoothValue)
448  MaxSmoothValue = smoothValue;
449  if (smoothValue < MinSmoothValue)
450  MinSmoothValue = smoothValue;
451  nFirstStrip = nLastStrip + 1;
452  smoothValue = 0;
453  stripCount = 0;
454  }
455  ++stripCount;
456  ++itConsecpoints;
457  }
458  ++itConsecpoints; //and putting the pointer to the new seies of point
459 
460  if (stripCount > 1) {
461  //if(smoothValue>0){
462  --stripCount;
463  smoothValue /= static_cast<float>(stripCount);
464  nLastStrip = nFirstStrip + stripCount - 1;
465  smoothedpoints.emplace_hint(smoothedpoints.end(), nFirstStrip, smoothValue);
466  smoothedpoints.emplace_hint(smoothedpoints.end(), nLastStrip, smoothValue);
467  if (smoothValue > MaxSmoothValue)
468  MaxSmoothValue = smoothValue;
469  if (smoothValue < MinSmoothValue)
470  MinSmoothValue = smoothValue;
471  }
472  } else {
473  for (int n = 0; n < consecStrips; ++n)
474  ++itConsecpoints;
475  }
476  }
477 
478  if ((MaxSmoothValue - MinSmoothValue) > distortionThreshold_) {
480  baselineCleaner(adcs, smoothedpoints, apvN);
481  return false;
482  }
483  return true;
484 }
485 
486 void inline SiStripAPVRestorer::baselineCleaner(const digivector_t& adcs, digimap_t& smoothedpoints, uint16_t apvN) {
487  if (cleaningSequence_ == 0) { //default sequence used up to now
488  cleaner_HighSlopeChecker(smoothedpoints);
489  cleaner_LocalMinimumAdder(adcs, smoothedpoints, apvN);
490  } else if (cleaningSequence_ == 1) {
491  cleaner_LocalMinimumAdder(adcs, smoothedpoints, apvN);
492  cleaner_HighSlopeChecker(smoothedpoints);
493  cleaner_MonotonyChecker(smoothedpoints);
494  } else if (cleaningSequence_ == 2) {
495  cleaner_HighSlopeChecker(smoothedpoints);
496  } else if (cleaningSequence_ == 3) {
497  cleaner_LocalMinimumAdder(adcs, smoothedpoints, apvN);
498  cleaner_HighSlopeChecker(smoothedpoints);
499  } else {
500  cleaner_HighSlopeChecker(smoothedpoints);
501  cleaner_LocalMinimumAdder(adcs, smoothedpoints, apvN);
502  }
503 }
504 
506  //Removing points without monotony
507  //--------------------------------------------------------------------------------------------------
508  if (smoothedpoints.size() < 3)
509  return;
510 
511  auto it = smoothedpoints.begin();
512  while (smoothedpoints.size() > 3 && it != --(--smoothedpoints.end())) { //while we are not at the last point
513  // get info about current and next points
514  auto it2 = it;
515  const float adc1 = it2->second;
516  const float adc2 = (++it2)->second;
517  const float adc3 = (++it2)->second;
518 
519  if ((adc2 - adc1) > hitStripThreshold_ && (adc2 - adc3) > hitStripThreshold_) {
520  smoothedpoints.erase(--it2);
521  } else {
522  ++it;
523  }
524  }
525 }
526 
528  digimap_t& smoothedpoints,
529  uint16_t apvN) {
531  //inserting extra point is case of local minimum
532  //--------------------------------------------------------------------------------------------------
533  // these should be reset now for the point-insertion that follows
534 
535  if (smoothedpoints.size() >= 2) {
536  for (auto it = smoothedpoints.begin(); it != --smoothedpoints.end(); ++it) {
537  auto itNext = it;
538  ++itNext;
539  const float strip1 = it->first;
540  const float strip2 = itNext->first;
541  const float adc1 = it->second;
542  const float adc2 = itNext->second;
543  const float m = (adc2 - adc1) / (strip2 - strip1);
544 
545  //2,4
546  if ((strip2 - strip1) > slopeX_ && std::abs(adc1 - adc2) > slopeY_) {
547  float itStrip = 1;
548  float strip = itStrip + strip1;
549  while (strip < strip2) {
550  const float adc = adcs[strip];
551  const auto noise =
552  static_cast<float>(noiseHandle->getNoiseFast(strip + apvN * nTotStripsPerAPV, detNoiseRange));
553  if (adc < (adc1 + m * itStrip - 2 * noise)) {
554  smoothedpoints.emplace_hint(itNext, strip, adc);
555  ++it;
556  }
557  ++itStrip;
558  ++strip;
559  }
560  }
561  }
562  }
563 
564  const uint16_t firstStripFlat = smoothedpoints.begin()->first;
565  const uint16_t lastStripFlat = (--smoothedpoints.end())->first;
566  const int16_t firstStripFlatADC = smoothedpoints.begin()->second;
567  const int16_t lastStripFlatADC = (--smoothedpoints.end())->second;
568  if (firstStripFlat > 3) {
569  auto it = smoothedpoints.begin();
570  float strip = 0;
571  while (strip < firstStripFlat) {
572  const float adc = adcs[strip];
573  const auto noise = static_cast<float>(noiseHandle->getNoiseFast(strip + apvN * nTotStripsPerAPV, detNoiseRange));
574  if (adc < (firstStripFlatADC - 2 * noise)) {
575  smoothedpoints.emplace_hint(it, strip, adc);
576  ++it;
577  }
578  ++strip;
579  }
580  }
581  if (lastStripFlat < (nTotStripsPerAPV - 3)) {
582  float strip = lastStripFlat + 1;
583  while (strip < nTotStripsPerAPV) {
584  const float adc = adcs[strip];
585  const auto noise = static_cast<float>(noiseHandle->getNoiseFast(strip + apvN * nTotStripsPerAPV, detNoiseRange));
586  if (adc < (lastStripFlatADC - 2 * noise)) {
587  smoothedpoints.emplace_hint(smoothedpoints.end(), strip, adc);
588  }
589  ++strip;
590  }
591  }
592 }
593 
595  //Removing points in the slope is too high
596  //----------------------------------------------------------------------------
597  if (smoothedpoints.size() < 4)
598  return;
599 
600  auto it = smoothedpoints.begin();
601  while (smoothedpoints.size() > 2 && it != --smoothedpoints.end()) { //while we are not at the last point
602  //if(smoothedpoints.size() <2) break;
603  // get info about current and next points
604  auto itNext = it;
605  ++itNext;
606  const float strip1 = it->first;
607  const float strip2 = itNext->first;
608  const float adc1 = it->second;
609  const float adc2 = itNext->second;
610  const float m = (adc2 - adc1) / (strip2 - strip1);
611 
612  if (m > 2) { // in case of large positive slope, remove next point and try again from same current point
613  smoothedpoints.erase(itNext);
614  } else if (m < -2) { // in case of large negative slope, remove current point and either...
615  // move to next point if we have reached the beginning (post-increment to avoid invalidating pointer during erase) or...
616  if (it == smoothedpoints.begin())
617  smoothedpoints.erase(it++);
618  // try again from the previous point if we have not reached the beginning
619  else
620  smoothedpoints.erase(it--);
621  } else { // in case of a flat enough slope, continue on to the next point
622  ++it;
623  }
624  }
625 }
626 
627 void inline SiStripAPVRestorer::baselineFollower(const digimap_t& smoothedpoints,
628  digivector_t& baseline,
629  float median) {
630  //if not enough points
631  if (smoothedpoints.size() < minStripsToFit_) {
632  baseline.insert(baseline.begin(), nTotStripsPerAPV, median);
633  } else {
634  baseline.assign(size_t(nTotStripsPerAPV), 0);
635 
636  const auto lastIt = --smoothedpoints.end();
637  const uint16_t firstStripFlat = smoothedpoints.begin()->first;
638  const uint16_t lastStripFlat = lastIt->first;
639  const int16_t firstStripFlatADC = smoothedpoints.begin()->second;
640  const int16_t lastStripFlatADC = lastIt->second;
641 
642  //adding here the costant line at the extremities
643  baseline.erase(baseline.begin(), baseline.begin() + firstStripFlat);
644  baseline.insert(baseline.begin(), firstStripFlat, firstStripFlatADC);
645 
646  baseline.erase(baseline.begin() + lastStripFlat, baseline.end());
647  baseline.insert(baseline.end(), nTotStripsPerAPV - lastStripFlat, lastStripFlatADC);
648 
649  //IMPORTANT: the itSmoothedpointsEnd should be at least smaller than smoothedpoints.end() -1
650  for (auto itSmoothedpoints = smoothedpoints.begin(); itSmoothedpoints != (--smoothedpoints.end());
651  ++itSmoothedpoints) {
652  auto itNextSmoothedpoints = itSmoothedpoints;
653  ++itNextSmoothedpoints;
654  const float strip1 = itSmoothedpoints->first;
655  const float strip2 = itNextSmoothedpoints->first;
656  const float adc1 = itSmoothedpoints->second;
657  const float adc2 = itNextSmoothedpoints->second;
658 
659  baseline[strip1] = adc1;
660  baseline[strip2] = adc2;
661  const float m = (adc2 - adc1) / (strip2 - strip1);
662  uint16_t itStrip = strip1 + 1;
663  float stripadc = adc1 + m;
664  while (itStrip < strip2) {
665  baseline[itStrip] = stripadc;
666  ++itStrip;
667  stripadc += m;
668  }
669  }
670  }
671 }
672 
673 bool SiStripAPVRestorer::checkBaseline(const digivector_t& baseline) const {
674  // The Savitzky-Golay (S-G) filter of any left length nL, right
675  // length nR, and order m, and with an optional opt equals the
676  // derivative order (0 for the magnitude, 1 for the first
677  // derivative, etc.) can be calculated using the following
678  // Mathematica code:
679  //
680  // SavitzkyGolay[m_?IntegerQ, {nL_?IntegerQ, nR_?IntegerQ},
681  // opt___] := Module[
682  // {a, d},
683  // d = If[opt === Null, 0, If[IntegerQ[opt], opt, 0]];
684  // a = Table[
685  // If[i == 0 && j == 0, 1, i^j], {i, -nL, nR}, {j, 0,
686  // m}]; (Inverse[Transpose[a].a].Transpose[a])[[d + 1]]];
687  //
688  // The following coefficients can be then calculated by:
689  //
690  // N[Join[Table[SavitzkyGolay[2, {k, 16}], {k, 0, 16}],
691  // Table[SavitzkyGolay[2, {16, k}], {k, 15, 0, -1}]]]
692 
693  // nLR = max(nL, nR)
694  static const size_t savitzky_golay_n_l_r = 16;
695  static const float savitzky_golay_coefficient[2 * savitzky_golay_n_l_r + 1][2 * savitzky_golay_n_l_r + 1] = {
696  {0.422085,
697  0.325077,
698  0.23839,
699  0.162023,
700  0.0959752,
701  0.0402477,
702  -0.00515996,
703  -0.0402477,
704  -0.0650155,
705  -0.0794634,
706  -0.0835913,
707  -0.0773994,
708  -0.0608875,
709  -0.0340557,
710  0.00309598,
711  0.0505676,
712  0.108359},
713  {0.315789,
714  0.254902,
715  0.19969,
716  0.150155,
717  0.106295,
718  0.0681115,
719  0.0356037,
720  0.00877193,
721  -0.0123839,
722  -0.0278638,
723  -0.0376677,
724  -0.0417957,
725  -0.0402477,
726  -0.0330237,
727  -0.0201238,
728  -0.00154799,
729  0.0227038,
730  0.0526316},
731  {0.234586,
732  0.198496,
733  0.165207,
734  0.134719,
735  0.107032,
736  0.0821465,
737  0.0600619,
738  0.0407784,
739  0.024296,
740  0.0106148,
741  -0.000265369,
742  -0.00834439,
743  -0.0136223,
744  -0.0160991,
745  -0.0157747,
746  -0.0126493,
747  -0.00672269,
748  0.00200501,
749  0.0135338},
750  {0.172078, 0.153076, 0.135099, 0.118148, 0.102221, 0.0873206, 0.073445,
751  0.0605947, 0.0487697, 0.0379699, 0.0281955, 0.0194463, 0.0117225, 0.00502392,
752  -0.000649351, -0.00529733, -0.00892003, -0.0115174, -0.0130895, -0.0136364},
753  {0.123659, 0.116431, 0.109144, 0.101798, 0.0943921, 0.0869268, 0.0794021,
754  0.0718179, 0.0641743, 0.0564712, 0.0487087, 0.0408868, 0.0330054, 0.0250646,
755  0.0170644, 0.00900473, 0.000885613, -0.00729294, -0.0155309, -0.0238283, -0.0321852},
756  {0.0859684, 0.0868154, 0.0869565, 0.0863919, 0.0851214, 0.0831451, 0.080463, 0.0770751,
757  0.0729814, 0.0681818, 0.0626765, 0.0564653, 0.0495483, 0.0419255, 0.0335968, 0.0245624,
758  0.0148221, 0.00437606, -0.00677583, -0.0186335, -0.0311971, -0.0444664},
759  {0.0565217, 0.0628458, 0.0680971, 0.0722756, 0.0753811, 0.0774139, 0.0783738, 0.0782609,
760  0.0770751, 0.0748165, 0.071485, 0.0670807, 0.0616036, 0.0550536, 0.0474308, 0.0387352,
761  0.0289667, 0.0181254, 0.00621118, -0.00677583, -0.0208357, -0.0359684, -0.0521739},
762  {0.0334615, 0.0434281, 0.0521329, 0.0595759, 0.0657571, 0.0706765, 0.0743341, 0.07673,
763  0.0778641, 0.0777364, 0.0763469, 0.0736957, 0.0697826, 0.0646078, 0.0581712, 0.0504728,
764  0.0415126, 0.0312907, 0.0198069, 0.00706142, -0.00694588, -0.022215, -0.0387458, -0.0565385},
765  {0.0153846, 0.0276923, 0.0386622, 0.0482943, 0.0565886, 0.0635452, 0.0691639, 0.0734448, 0.076388,
766  0.0779933, 0.0782609, 0.0771906, 0.0747826, 0.0710368, 0.0659532, 0.0595318, 0.0517726, 0.0426756,
767  0.0322408, 0.0204682, 0.00735786, -0.0070903, -0.0228763, -0.04, -0.0584615},
768  {0.001221, 0.0149451, 0.027326, 0.0383639, 0.0480586, 0.0564103, 0.0634188, 0.0690842, 0.0734066,
769  0.0763858, 0.078022, 0.078315, 0.077265, 0.0748718, 0.0711355, 0.0660562, 0.0596337, 0.0518681,
770  0.0427595, 0.0323077, 0.0205128, 0.00737485, -0.00710623, -0.0229304, -0.0400977, -0.0586081},
771  {-0.00985222, 0.00463138, 0.0178098, 0.029683, 0.0402509, 0.0495137, 0.0574713, 0.0641236, 0.0694708,
772  0.0735127, 0.0762494, 0.0776809, 0.0778073, 0.0766284, 0.0741442, 0.0703549, 0.0652604, 0.0588607,
773  0.0511557, 0.0421456, 0.0318302, 0.0202097, 0.0072839, -0.00694708, -0.0224833, -0.0393247, -0.0574713},
774  {-0.0184729, -0.00369458, 0.00984169, 0.0221359, 0.0331881, 0.0429982, 0.0515662,
775  0.0588923, 0.0649762, 0.0698181, 0.073418, 0.0757758, 0.0768915, 0.0767652,
776  0.0753968, 0.0727864, 0.0689339, 0.0638394, 0.0575028, 0.0499242, 0.0411035,
777  0.0310408, 0.019736, 0.00718917, -0.00659972, -0.0216307, -0.0379037, -0.0554187},
778  {-0.025139, -0.0103925, 0.00318873, 0.0156046, 0.0268552, 0.0369405, 0.0458605, 0.0536151,
779  0.0602045, 0.0656285, 0.0698872, 0.0729806, 0.0749086, 0.0756714, 0.0752688, 0.0737009,
780  0.0709677, 0.0670692, 0.0620054, 0.0557763, 0.0483818, 0.039822, 0.0300969, 0.0192065,
781  0.0071508, -0.00607024, -0.0204566, -0.0360083, -0.0527253},
782  {-0.0302419, -0.0157536, -0.00234785, 0.00997537, 0.021216, 0.0313741, 0.0404497, 0.0484427,
783  0.0553532, 0.0611811, 0.0659264, 0.0695892, 0.0721695, 0.0736672, 0.0740823, 0.0734149,
784  0.0716649, 0.0688324, 0.0649174, 0.0599198, 0.0538396, 0.0466769, 0.0384316, 0.0291038,
785  0.0186934, 0.00720046, -0.00537502, -0.0190331, -0.0337736, -0.0495968},
786  {-0.0340909, -0.0200147, -0.006937, 0.00514208, 0.0162226, 0.0263045, 0.0353878, 0.0434725,
787  0.0505587, 0.0566463, 0.0617353, 0.0658257, 0.0689175, 0.0710107, 0.0721054, 0.0722014,
788  0.0712989, 0.0693978, 0.0664981, 0.0625999, 0.057703, 0.0518076, 0.0449135, 0.0370209,
789  0.0281297, 0.01824, 0.0073516, -0.00453534, -0.0174209, -0.031305, -0.0461877},
790  {-0.0369318, -0.0233688, -0.0107221, 0.00100806, 0.0118218, 0.0217192, 0.0307001, 0.0387647,
791  0.0459128, 0.0521444, 0.0574597, 0.0618585, 0.0653409, 0.0679069, 0.0695565, 0.0702896,
792  0.0701063, 0.0690066, 0.0669905, 0.0640579, 0.0602089, 0.0554435, 0.0497617, 0.0431635,
793  0.0356488, 0.0272177, 0.0178702, 0.0076063, -0.00357405, -0.0156708, -0.028684, -0.0426136},
794  {-0.038961, -0.025974, -0.0138249, -0.00251362, 0.00795978, 0.0175953, 0.026393, 0.0343527, 0.0414747,
795  0.0477587, 0.0532049, 0.0578132, 0.0615836, 0.0645161, 0.0666108, 0.0678676, 0.0682866, 0.0678676,
796  0.0666108, 0.0645161, 0.0615836, 0.0578132, 0.0532049, 0.0477587, 0.0414747, 0.0343527, 0.026393,
797  0.0175953, 0.00795978, -0.00251362, -0.0138249, -0.025974, -0.038961},
798  {-0.0426136, -0.028684, -0.0156708, -0.00357405, 0.0076063, 0.0178702, 0.0272177, 0.0356488,
799  0.0431635, 0.0497617, 0.0554435, 0.0602089, 0.0640579, 0.0669905, 0.0690066, 0.0701063,
800  0.0702896, 0.0695565, 0.0679069, 0.0653409, 0.0618585, 0.0574597, 0.0521444, 0.0459128,
801  0.0387647, 0.0307001, 0.0217192, 0.0118218, 0.00100806, -0.0107221, -0.0233688, -0.0369318},
802  {-0.0461877, -0.031305, -0.0174209, -0.00453534, 0.0073516, 0.01824, 0.0281297, 0.0370209,
803  0.0449135, 0.0518076, 0.057703, 0.0625999, 0.0664981, 0.0693978, 0.0712989, 0.0722014,
804  0.0721054, 0.0710107, 0.0689175, 0.0658257, 0.0617353, 0.0566463, 0.0505587, 0.0434725,
805  0.0353878, 0.0263045, 0.0162226, 0.00514208, -0.006937, -0.0200147, -0.0340909},
806  {-0.0495968, -0.0337736, -0.0190331, -0.00537502, 0.00720046, 0.0186934, 0.0291038, 0.0384316,
807  0.0466769, 0.0538396, 0.0599198, 0.0649174, 0.0688324, 0.0716649, 0.0734149, 0.0740823,
808  0.0736672, 0.0721695, 0.0695892, 0.0659264, 0.0611811, 0.0553532, 0.0484427, 0.0404497,
809  0.0313741, 0.021216, 0.00997537, -0.00234785, -0.0157536, -0.0302419},
810  {-0.0527253, -0.0360083, -0.0204566, -0.00607024, 0.0071508, 0.0192065, 0.0300969, 0.039822,
811  0.0483818, 0.0557763, 0.0620054, 0.0670692, 0.0709677, 0.0737009, 0.0752688, 0.0756714,
812  0.0749086, 0.0729806, 0.0698872, 0.0656285, 0.0602045, 0.0536151, 0.0458605, 0.0369405,
813  0.0268552, 0.0156046, 0.00318873, -0.0103925, -0.025139},
814  {-0.0554187, -0.0379037, -0.0216307, -0.00659972, 0.00718917, 0.019736, 0.0310408,
815  0.0411035, 0.0499242, 0.0575028, 0.0638394, 0.0689339, 0.0727864, 0.0753968,
816  0.0767652, 0.0768915, 0.0757758, 0.073418, 0.0698181, 0.0649762, 0.0588923,
817  0.0515662, 0.0429982, 0.0331881, 0.0221359, 0.00984169, -0.00369458, -0.0184729},
818  {-0.0574713, -0.0393247, -0.0224833, -0.00694708, 0.0072839, 0.0202097, 0.0318302, 0.0421456, 0.0511557,
819  0.0588607, 0.0652604, 0.0703549, 0.0741442, 0.0766284, 0.0778073, 0.0776809, 0.0762494, 0.0735127,
820  0.0694708, 0.0641236, 0.0574713, 0.0495137, 0.0402509, 0.029683, 0.0178098, 0.00463138, -0.00985222},
821  {-0.0586081, -0.0400977, -0.0229304, -0.00710623, 0.00737485, 0.0205128, 0.0323077, 0.0427595, 0.0518681,
822  0.0596337, 0.0660562, 0.0711355, 0.0748718, 0.077265, 0.078315, 0.078022, 0.0763858, 0.0734066,
823  0.0690842, 0.0634188, 0.0564103, 0.0480586, 0.0383639, 0.027326, 0.0149451, 0.001221},
824  {-0.0584615, -0.04, -0.0228763, -0.0070903, 0.00735786, 0.0204682, 0.0322408, 0.0426756, 0.0517726,
825  0.0595318, 0.0659532, 0.0710368, 0.0747826, 0.0771906, 0.0782609, 0.0779933, 0.076388, 0.0734448,
826  0.0691639, 0.0635452, 0.0565886, 0.0482943, 0.0386622, 0.0276923, 0.0153846},
827  {-0.0565385, -0.0387458, -0.022215, -0.00694588, 0.00706142, 0.0198069, 0.0312907, 0.0415126,
828  0.0504728, 0.0581712, 0.0646078, 0.0697826, 0.0736957, 0.0763469, 0.0777364, 0.0778641,
829  0.07673, 0.0743341, 0.0706765, 0.0657571, 0.0595759, 0.0521329, 0.0434281, 0.0334615},
830  {-0.0521739, -0.0359684, -0.0208357, -0.00677583, 0.00621118, 0.0181254, 0.0289667, 0.0387352,
831  0.0474308, 0.0550536, 0.0616036, 0.0670807, 0.071485, 0.0748165, 0.0770751, 0.0782609,
832  0.0783738, 0.0774139, 0.0753811, 0.0722756, 0.0680971, 0.0628458, 0.0565217},
833  {-0.0444664, -0.0311971, -0.0186335, -0.00677583, 0.00437606, 0.0148221, 0.0245624, 0.0335968,
834  0.0419255, 0.0495483, 0.0564653, 0.0626765, 0.0681818, 0.0729814, 0.0770751, 0.080463,
835  0.0831451, 0.0851214, 0.0863919, 0.0869565, 0.0868154, 0.0859684},
836  {-0.0321852, -0.0238283, -0.0155309, -0.00729294, 0.000885613, 0.00900473, 0.0170644,
837  0.0250646, 0.0330054, 0.0408868, 0.0487087, 0.0564712, 0.0641743, 0.0718179,
838  0.0794021, 0.0869268, 0.0943921, 0.101798, 0.109144, 0.116431, 0.123659},
839  {-0.0136364, -0.0130895, -0.0115174, -0.00892003, -0.00529733, -0.000649351, 0.00502392,
840  0.0117225, 0.0194463, 0.0281955, 0.0379699, 0.0487697, 0.0605947, 0.073445,
841  0.0873206, 0.102221, 0.118148, 0.135099, 0.153076, 0.172078},
842  {0.0135338,
843  0.00200501,
844  -0.00672269,
845  -0.0126493,
846  -0.0157747,
847  -0.0160991,
848  -0.0136223,
849  -0.00834439,
850  -0.000265369,
851  0.0106148,
852  0.024296,
853  0.0407784,
854  0.0600619,
855  0.0821465,
856  0.107032,
857  0.134719,
858  0.165207,
859  0.198496,
860  0.234586},
861  {0.0526316,
862  0.0227038,
863  -0.00154799,
864  -0.0201238,
865  -0.0330237,
866  -0.0402477,
867  -0.0417957,
868  -0.0376677,
869  -0.0278638,
870  -0.0123839,
871  0.00877193,
872  0.0356037,
873  0.0681115,
874  0.106295,
875  0.150155,
876  0.19969,
877  0.254902,
878  0.315789},
879  {0.108359,
880  0.0505676,
881  0.00309598,
882  -0.0340557,
883  -0.0608875,
884  -0.0773994,
885  -0.0835913,
886  -0.0794634,
887  -0.0650155,
888  -0.0402477,
889  -0.00515996,
890  0.0402477,
891  0.0959752,
892  0.162023,
893  0.23839,
894  0.325077,
895  0.422085}};
896 
897  float filtered_baseline[nTotStripsPerAPV];
898  float filtered_baseline_derivative[nTotStripsPerAPV - 1];
899 
900  // Zero filtered_baseline
901  memset(filtered_baseline, 0, nTotStripsPerAPV * sizeof(float));
902  // Filter the left edge using (nL, nR) = (0, 16) .. (15, 16) S-G
903  // filters
904  for (size_t i = 0; i < savitzky_golay_n_l_r; i++) {
905  for (size_t j = 0; j < savitzky_golay_n_l_r + 1 + i; j++) {
906  filtered_baseline[i] += savitzky_golay_coefficient[i][j] * baseline[j];
907  }
908  }
909  // Filter the middle section using the (nL, nR) = (16, 16) S-G
910  // filter, while taking advantage of the symmetry to save 16
911  // multiplications.
912  for (size_t i = savitzky_golay_n_l_r; i < nTotStripsPerAPV - savitzky_golay_n_l_r; i++) {
913  filtered_baseline[i] = savitzky_golay_coefficient[savitzky_golay_n_l_r][savitzky_golay_n_l_r] * baseline[i];
914  for (size_t j = 0; j < savitzky_golay_n_l_r; j++) {
915  filtered_baseline[i] += savitzky_golay_coefficient[savitzky_golay_n_l_r][j] *
916  (baseline[i + j - savitzky_golay_n_l_r] + baseline[i - j + savitzky_golay_n_l_r]);
917  }
918 #if 0
919  // Test that the indexing above is correct
920  float test = 0;
921  for (size_t j = 0; j < 2 * savitzky_golay_n_l_r + 1; j++) {
922  test +=
923  savitzky_golay_coefficient[savitzky_golay_n_l_r][j] *
924  baseline[i + j - savitzky_golay_n_l_r];
925  }
926  // test == filtered_baseline[i] should hold now
927 #endif
928  }
929  // Filter the right edge using (nL, nR) = (16, 15) .. (16, 0) S-G
930  // filters
931  for (size_t i = nTotStripsPerAPV - savitzky_golay_n_l_r; i < nTotStripsPerAPV; i++) {
932  for (size_t j = 0; j < nTotStripsPerAPV - i + savitzky_golay_n_l_r; j++) {
933  filtered_baseline[i] += savitzky_golay_coefficient[2 * savitzky_golay_n_l_r + i + 1 - nTotStripsPerAPV][j] *
934  baseline[i + j - savitzky_golay_n_l_r];
935  }
936  }
937  // In lieu of a spearate S-G derivative filter, the finite
938  // difference is used here (since the output is sufficiently
939  // smooth).
940  for (size_t i = 0; i < (nTotStripsPerAPV - 1); i++) {
941  filtered_baseline_derivative[i] = filtered_baseline[i + 1] - filtered_baseline[i];
942  }
943 
944  // Calculate the maximum deviation between filtered and unfiltered
945  // baseline, plus the sum square of the derivative.
946 
947  double filtered_baseline_max = 0;
948  double filtered_baseline_derivative_sum_square = 0;
949 
950  for (size_t i = 0; i < nTotStripsPerAPV; i++) {
951  const double d = filtered_baseline[i] - baseline[i];
952 
953  filtered_baseline_max = std::max(filtered_baseline_max, static_cast<double>(fabs(d)));
954  }
955  for (size_t i = 0; i < (nTotStripsPerAPV - 1); i++) {
956  filtered_baseline_derivative_sum_square += filtered_baseline_derivative[i] * filtered_baseline_derivative[i];
957  }
958 
959 #if 0
960  std::cerr << __FILE__ << ':' << __LINE__ << ": "
961  << filtered_baseline_max << ' '
962  << filtered_baseline_derivative_sum_square << std::endl;
963 #endif
964 
965  // Apply the cut
966  return !(filtered_baseline_max >= filteredBaselineMax_ ||
967  filtered_baseline_derivative_sum_square >= filteredBaselineDerivativeSumSquare_);
968 }
969 
970 //Other methods implementation ==============================================
971 //==========================================================================
972 
974  if (useRealMeanCM_) {
976  iEvent.getByToken(siStripRawDigiToken_, input);
978  } else {
980  iEvent.getByToken(siStripProcessedRawDigiToken_, inputCM);
981  createCMMapCMstored(*inputCM);
982  }
983 }
985  meanCMmap_.clear();
986  for (const auto& rawDigis : input) {
987  const auto detPedestalRange = pedestalHandle->getRange(rawDigis.id);
988  const size_t nAPVs = rawDigis.size() / nTotStripsPerAPV;
989  std::vector<float> meanCMDetSet;
990  meanCMDetSet.reserve(nAPVs);
991  for (uint16_t iAPV = 0; iAPV < nAPVs; ++iAPV) {
992  uint16_t minPed = nTotStripsPerAPV;
993  for (uint16_t strip = nTotStripsPerAPV * iAPV; strip < nTotStripsPerAPV * (iAPV + 1); ++strip) {
994  uint16_t ped = static_cast<uint16_t>(pedestalHandle->getPed(strip, detPedestalRange));
995  if (ped < minPed)
996  minPed = ped;
997  }
998  meanCMDetSet.push_back(minPed);
999  }
1000  meanCMmap_.emplace(rawDigis.id, std::move(meanCMDetSet));
1001  }
1002 }
1004  meanCMmap_.clear();
1005  for (const auto& rawDigis : input) {
1006  std::vector<float> meanCMNValue;
1007  meanCMNValue.reserve(rawDigis.size());
1009  std::begin(rawDigis), std::end(rawDigis), std::back_inserter(meanCMNValue), [](SiStripProcessedRawDigi cm) {
1010  return cm.adc();
1011  });
1012  meanCMmap_.emplace(rawDigis.id, std::move(meanCMNValue));
1013  }
1014 }
1015 
1016 //NEW algorithm designed for implementation in FW=============================
1017 //============================================================================
1018 void SiStripAPVRestorer::derivativeFollowerRestore(uint16_t apvN, uint16_t firstAPV, digivector_t& digis) {
1019  digivector_t singleAPVdigi;
1020  singleAPVdigi.clear();
1021  for (int16_t strip = (apvN - firstAPV) * nTotStripsPerAPV; strip < (apvN - firstAPV + 1) * nTotStripsPerAPV; ++strip)
1022  singleAPVdigi.push_back(digis[strip] + 1024);
1023 
1024  digimap_t discontinuities; // it will contain the start and the end of each region in which a greadient is present
1025  discontinuities.clear();
1026 
1027  digimap_t::iterator itdiscontinuities;
1028 
1029  //----Variables of the first part---//
1030 
1031  bool isMinimumAndNoMax = false;
1032  bool isFirstStrip = false;
1033 
1034  //---Variables of the second part---//
1035 
1036  int actualStripADC = 0;
1037  int previousStripADC = 0;
1038 
1039  int greadient = 0;
1040  int maximum_value = 0;
1041  const uint32_t n_high_maximum_cluster = 1025 + 1024;
1042  int high_maximum_cluster = n_high_maximum_cluster;
1043  int number_good_minimum = 0;
1044  int first_gradient = 0;
1045  int strip_first_gradient = 0;
1046  int adc_start_point_cluster_pw = 0;
1047  int auxiliary_end_cluster = 0;
1048  int first_start_cluster_strip = 0;
1049  int first_start_cluster_ADC = 0;
1050  bool isAuxiliary_Minimum = false;
1051  bool isPossible_wrong_minimum = false;
1052  bool isMax = false;
1053 
1054  //----------SECOND PART: CLUSTER FINDING--------//
1055 
1056  for (uint16_t strip = 0; strip < singleAPVdigi.size(); ++strip) {
1057  if (strip == 0) {
1058  actualStripADC = singleAPVdigi[strip];
1059  if (std::abs(singleAPVdigi[strip] - singleAPVdigi[strip + 1]) > gradient_threshold_) {
1060  isFirstStrip = true;
1061  isMinimumAndNoMax = true;
1062  discontinuities.insert(discontinuities.end(), std::pair<int, int>(strip, actualStripADC));
1063  } else if (actualStripADC > (gradient_threshold_ + 1024)) {
1064  discontinuities.insert(discontinuities.end(), std::pair<uint16_t, int16_t>(strip, 0 + 1024));
1065  isMinimumAndNoMax = true;
1066  first_start_cluster_strip = strip;
1067  first_start_cluster_ADC = 1024;
1068  }
1069 
1070  } else {
1071  previousStripADC = actualStripADC;
1072  actualStripADC = singleAPVdigi[strip];
1073  greadient = actualStripADC - previousStripADC;
1074 
1075  if (((greadient > gradient_threshold_) && (!isMax) && (!isMinimumAndNoMax))) {
1076  isMax = false;
1077  if (((std::abs(maximum_value - previousStripADC) < (2 * gradient_threshold_)) &&
1078  discontinuities.size() > 1)) { // add the || with the cluster size
1079  //to verify if the noise do not interfere and is detected fake hits
1080  isPossible_wrong_minimum = true;
1081  itdiscontinuities = --discontinuities.end();
1082  if (discontinuities.size() > 1) {
1083  --itdiscontinuities;
1084  }
1085  strip_first_gradient = itdiscontinuities->first;
1086  adc_start_point_cluster_pw = itdiscontinuities->second;
1087  first_gradient = std::abs(adc_start_point_cluster_pw - singleAPVdigi[strip_first_gradient + 1]);
1088  discontinuities.erase(++itdiscontinuities);
1089  discontinuities.erase(--discontinuities.end());
1090  }
1091 
1092  if ((discontinuities.size() % 2 == 1) && (!discontinuities.empty())) { //&&(no_minimo == 0)
1093  discontinuities.erase(--discontinuities.end());
1094  }
1095 
1096  discontinuities.insert(discontinuities.end(), std::pair<uint16_t, int16_t>(strip - 1, previousStripADC));
1097  isMinimumAndNoMax = true;
1098  maximum_value = 0;
1099  first_start_cluster_strip = strip - 1;
1100  first_start_cluster_ADC = previousStripADC;
1101 
1102  } else if ((!isMax) && ((actualStripADC - previousStripADC < 0) && (isMinimumAndNoMax))) {
1103  isMax = true;
1104  isMinimumAndNoMax = false;
1105  high_maximum_cluster = n_high_maximum_cluster;
1106  if ((previousStripADC > maximum_value) && (discontinuities.size() % 2 == 1))
1107  maximum_value = previousStripADC;
1108  }
1109 
1110  if ((isMax) && (strip < (nTotStripsPerAPV - 2))) {
1111  if (high_maximum_cluster > (std::abs(singleAPVdigi[strip + 1] - actualStripADC))) {
1112  high_maximum_cluster = singleAPVdigi[strip + 1] - actualStripADC;
1113  auxiliary_end_cluster = strip + 2;
1114  } else {
1115  auxiliary_end_cluster = nTotStripsPerAPV - 1;
1116  }
1117  }
1118 
1119  if ((isMax) && ((actualStripADC - previousStripADC) >= 0) && (size_window_ > 0) &&
1120  (strip <= ((nTotStripsPerAPV - 1) - size_window_ - 1))) {
1121  number_good_minimum = 0;
1122  for (uint16_t wintry = 0; wintry <= size_window_; wintry++) {
1123  if (std::abs(singleAPVdigi[strip + wintry] - singleAPVdigi[strip + wintry + 1]) <= last_gradient_)
1124  ++number_good_minimum;
1125  }
1126  --number_good_minimum;
1127 
1128  if (size_window_ != number_good_minimum) {
1129  isMax = false; // not Valid end Point
1130  isMinimumAndNoMax = true;
1131  }
1132 
1133  } else if ((isMax) && (strip > ((nTotStripsPerAPV - 1) - size_window_ - 1))) {
1134  isMax = true;
1135  isAuxiliary_Minimum = true; //for minimums after strip 127-SW-1
1136  }
1137 
1138  if (!discontinuities.empty()) {
1139  itdiscontinuities = --discontinuities.end();
1140  }
1141 
1142  if ((isMax) && (actualStripADC <= first_start_cluster_ADC)) {
1143  if ((std::abs(first_start_cluster_ADC - singleAPVdigi[strip + 2]) > first_gradient) &&
1144  (isPossible_wrong_minimum)) {
1145  discontinuities.erase(itdiscontinuities);
1146  discontinuities.insert(discontinuities.end(),
1147  std::pair<int, int>(strip_first_gradient, adc_start_point_cluster_pw));
1148  discontinuities.insert(discontinuities.end(), std::pair<int, int>(strip, adc_start_point_cluster_pw));
1149  } else {
1150  if ((discontinuities.size() % 2 == 0) && (discontinuities.size() > 1)) {
1151  discontinuities.erase(--discontinuities.end());
1152  }
1153  discontinuities.insert(discontinuities.end(), std::pair<int, int>(strip, actualStripADC));
1154  }
1155  isMax = false;
1156  adc_start_point_cluster_pw = 0;
1157  isPossible_wrong_minimum = false;
1158  strip_first_gradient = 0;
1159  first_start_cluster_strip = 0;
1160  first_start_cluster_ADC = 0;
1161  }
1162 
1163  if ((isMax) && ((actualStripADC - previousStripADC) >= 0) &&
1164  (!isAuxiliary_Minimum)) { //For the end Poit when strip >127-SW-1
1165  if ((std::abs(first_start_cluster_ADC - singleAPVdigi[strip + 1]) > first_gradient) &&
1166  (isPossible_wrong_minimum)) {
1167  discontinuities.erase(itdiscontinuities);
1168  discontinuities.insert(discontinuities.end(),
1169  std::pair<int, int>(strip_first_gradient, adc_start_point_cluster_pw));
1170  }
1171 
1172  if ((discontinuities.size() % 2 == 0) && (discontinuities.size() > 1)) {
1173  discontinuities.erase(--discontinuities.end());
1174  }
1175  discontinuities.insert(discontinuities.end(), std::pair<int, int>(strip - 1, previousStripADC));
1176  isMax = false;
1177  adc_start_point_cluster_pw = 0;
1178  isPossible_wrong_minimum = false;
1179  strip_first_gradient = 0;
1180  first_start_cluster_strip = 0;
1181  first_start_cluster_ADC = 0;
1182  }
1183  }
1184  }
1185 
1186  //----------THIRD PART reconstruction of the event without baseline-------//
1187 
1188  if (!discontinuities.empty()) {
1189  if ((first_start_cluster_strip) == (nTotStripsPerAPV - 1) - 1)
1190  discontinuities.insert(discontinuities.end(),
1191  std::pair<int, int>((nTotStripsPerAPV - 1), first_start_cluster_ADC));
1192  if ((isMax) && (isAuxiliary_Minimum))
1193  discontinuities.insert(discontinuities.end(),
1194  std::pair<int, int>(auxiliary_end_cluster, first_start_cluster_ADC));
1195  }
1196 
1197  if (isFirstStrip) {
1198  itdiscontinuities = discontinuities.begin();
1199  ++itdiscontinuities;
1200  ++itdiscontinuities;
1201  int firstADC = itdiscontinuities->second;
1202  --itdiscontinuities;
1203  itdiscontinuities->second = firstADC;
1204  --itdiscontinuities;
1205  itdiscontinuities->second = firstADC;
1206  }
1207 
1208  if (!discontinuities.empty()) {
1209  itdiscontinuities = discontinuities.begin();
1210  uint16_t firstStrip = itdiscontinuities->first;
1211  int16_t firstADC = itdiscontinuities->second;
1212  ++itdiscontinuities;
1213  uint16_t lastStrip = itdiscontinuities->first;
1214  int16_t secondADC = itdiscontinuities->second;
1215  ++itdiscontinuities;
1216 
1217  for (uint16_t strip = 0; strip < nTotStripsPerAPV; ++strip) {
1218  if (strip > lastStrip && itdiscontinuities != discontinuities.end()) {
1219  firstStrip = itdiscontinuities->first;
1220  firstADC = itdiscontinuities->second;
1221  ++itdiscontinuities;
1222  lastStrip = itdiscontinuities->first;
1223  secondADC = itdiscontinuities->second;
1224  ++itdiscontinuities;
1225  }
1226 
1227  if ((firstStrip <= strip) && (strip <= lastStrip) &&
1228  (0 < (singleAPVdigi[strip] - firstADC -
1229  ((secondADC - firstADC) / (lastStrip - firstStrip)) * (strip - firstStrip) - gradient_threshold_))) {
1230  digis[(apvN - firstAPV) * nTotStripsPerAPV + strip] =
1231  singleAPVdigi[strip] - firstADC -
1232  (((secondADC - firstADC) / (lastStrip - firstStrip)) * (strip - firstStrip));
1233  edm::LogWarning("NoBaseline") << "No baseline " << digis[(apvN - firstAPV) * nTotStripsPerAPV + strip] << "\n";
1234  } else {
1235  digis[(apvN - firstAPV) * nTotStripsPerAPV + strip] = 0;
1236  }
1237  }
1238  }
1239 }
1240 
1242  desc.add("ForceNoRestore", false);
1243  desc.add<std::string>("APVInspectMode", "BaselineFollower");
1244  desc.add<std::string>("APVRestoreMode", "");
1245  desc.add("useRealMeanCM", false);
1246  desc.add("MeanCM", 0);
1247  desc.add("DeltaCMThreshold", 20U);
1248  desc.add("Fraction", 0.2);
1249  desc.add("Deviation", 25U);
1250  desc.add("restoreThreshold", 0.5);
1251  desc.add("nSaturatedStrip", 2U);
1252  desc.add("nSigmaNoiseDerTh", 4U);
1253  desc.add("consecThreshold", 5U);
1254  desc.add("nSmooth", 9U);
1255  desc.add("distortionThreshold", 20U);
1256  desc.add("ApplyBaselineCleaner", true);
1257  desc.add("CleaningSequence", 1U);
1258  desc.add("slopeX", 3);
1259  desc.add("slopeY", 4);
1260  desc.add("hitStripThreshold", 40U);
1261  desc.add("minStripsToFit", 4U);
1262  desc.add("ApplyBaselineRejection", true);
1263  desc.add("filteredBaselineMax", 6.0);
1264  desc.add("filteredBaselineDerivativeSumSquare", 30.0);
1265  desc.add("discontinuityThreshold", 12);
1266  desc.add("lastGradient", 10);
1267  desc.add("sizeWindow", 1);
1268  desc.add("widthCluster", 64);
1269 }
edm::ESWatcher< SiStripQualityRcd > qualityWatcher_
SiStripAPVRestorer(const edm::ParameterSet &conf, edm::ConsumesCollector)
ESGetTokenH3DDVariant esConsumes(std::string const &Record, edm::ConsumesCollector &)
Definition: DeDxTools.cc:283
const Range getRange(const uint32_t &detID) const
void init(const edm::EventSetup &es)
bool IsApvBad(uint32_t detid, short apvNb) const
static void fillDescriptions(edm::ParameterSetDescription &desc)
T const & getData(const ESGetToken< T, R > &iToken) const noexcept(false)
Definition: EventSetup.h:119
void baselineFollowerRestore(uint16_t apvN, uint16_t firstAPV, float median, digivector_t &digis)
uint16_t baselineAndSaturationInspect(uint16_t firstAPV, const digivector_t &digis)
for(int i=first, nt=offsets[nh];i< nt;i+=gridDim.x *blockDim.x)
A signed Digi for the silicon strip detector, containing only adc information, and suitable for stori...
const SiStripPedestals * pedestalHandle
std::map< uint16_t, digimap_t > smoothedMaps_
uint16_t baselineFollowerInspect(uint16_t firstAPV, const digivector_t &digis)
double filteredBaselineDerivativeSumSquare_
const Range getRange(const uint32_t detID) const
void flatRestore(uint16_t apvN, uint16_t firstAPV, digivector_t &digis)
edm::ESGetToken< SiStripQuality, SiStripQualityRcd > qualityToken_
float getPed(const uint16_t &strip, const Range &range) const
static std::string const input
Definition: EdmProvDump.cc:50
edm::ESWatcher< SiStripNoisesRcd > noiseWatcher_
void baselineFollower(const digimap_t &, digivector_t &baseline, float median)
void loadMeanCMMap(const edm::Event &)
U second(std::pair< T, U > const &p)
edm::EDGetTokenT< edm::DetSetVector< SiStripRawDigi > > siStripRawDigiToken_
uint16_t hybridEmulationInspect(uint16_t firstAPV, const digivector_t &digis)
std::vector< std::string > apvFlags_
baselinemap_t baselineMap_
static float getNoiseFast(const uint16_t &strip, const Range &range)
Definition: SiStripNoises.h:67
int iEvent
Definition: GenABIO.cc:224
const SiStripQuality * qualityHandle
bool checkBaseline(const std::vector< int16_t > &baseline) const
void baselineCleaner(const digivector_t &adcs, digimap_t &smoothedpoints, uint16_t apvN)
void cleaner_LocalMinimumAdder(const digivector_t &adcs, digimap_t &smoothedpoints, uint16_t apvN)
void cleaner_HighSlopeChecker(digimap_t &smoothedpoints)
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
const SiStripNoises * noiseHandle
edm::EDGetTokenT< edm::DetSetVector< SiStripProcessedRawDigi > > siStripProcessedRawDigiToken_
bool flatRegionsFinder(const digivector_t &adcs, digimap_t &smoothedpoints, uint16_t apvN)
void cleaner_MonotonyChecker(digimap_t &smoothedpoints)
uint16_t inspectAndRestore(uint32_t detId, uint16_t firstAPV, const digivector_t &rawDigisPedSubtracted, digivector_t &processedRawDigi, const medians_t &vmedians)
d
Definition: ztail.py:151
void derivativeFollowerRestore(uint16_t apvN, uint16_t firstAPV, digivector_t &digis)
void createCMMapCMstored(const edm::DetSetVector< SiStripProcessedRawDigi > &input)
edm::ESGetToken< SiStripPedestals, SiStripPedestalsRcd > pedestalToken_
uint16_t hybridFormatInspect(uint16_t firstAPV, const digivector_t &digis)
edm::ESWatcher< SiStripPedestalsRcd > pedestalWatcher_
std::vector< bool > apvFlagsBoolOverride_
std::map< uint16_t, digi_t > digimap_t
bool IsStripBad(uint32_t detid, short strip) const
edm::ESGetToken< SiStripNoises, SiStripNoisesRcd > noiseToken_
uint16_t nullInspect(uint16_t firstAPV, const digivector_t &digis)
std::vector< std::pair< short, float > > medians_t
std::vector< bool > badAPVs_
bool check(const edm::EventSetup &iSetup)
Definition: ESWatcher.h:57
const Range getRange(const uint32_t detID) const
std::vector< bool > apvFlagsBool_
T median(std::vector< T > values)
Definition: median.h:16
HLT enums.
uint16_t abnormalBaselineInspect(uint16_t firstAPV, const digivector_t &digis)
std::pair< ContainerIterator, ContainerIterator > Range
std::vector< digi_t > digivector_t
std::vector< float > median_
void restore(uint16_t firstAPV, digivector_t &digis)
uint16_t forceRestoreInspect(uint16_t firstAPV, const digivector_t &digis)
static constexpr uint16_t nTotStripsPerAPV
Log< level::Warning, false > LogWarning
std::pair< ContainerIterator, ContainerIterator > Range
Definition: SiStripNoises.h:47
A Digi for the silicon strip detector, containing only adc information, and suitable for storing raw ...
def move(src, dest)
Definition: eostools.py:511
void createCMMapRealPed(const edm::DetSetVector< SiStripRawDigi > &input)
uint16_t *__restrict__ uint16_t const *__restrict__ adc
uint16_t inspect(uint32_t detId, uint16_t firstAPV, const digivector_t &digis, const medians_t &vmedians)
unsigned transform(const HcalDetId &id, unsigned transformCode)