CMS 3D CMS Logo

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