CMS 3D CMS Logo

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