CMS 3D CMS Logo

CalibrationScanAlgorithm.cc
Go to the documentation of this file.
7 #include "TProfile.h"
8 #include "TF1.h"
9 #include "TH1.h"
10 #include "TVirtualFitter.h"
11 #include "TFitResult.h"
12 #include "TMath.h"
13 #include "TGraph2D.h"
14 #include "TH2F.h"
15 #include "TCanvas.h"
16 #include "TROOT.h"
17 #include <iostream>
18 #include <sstream>
19 #include <iomanip>
20 #include <cmath>
21 #include "Math/MinimizerOptions.h"
22 
23 using namespace sistrip;
24 
25 // ----------------------------------------------------------------------------
26 //
28  : CommissioningAlgorithm(anal),
29  cal_(nullptr)
30 {}
31 
32 // ----------------------------------------------------------------------------
33 //
34 void CalibrationScanAlgorithm::extract( const std::vector<TH1*>& histos) {
35 
36  if ( !anal() ) {
38  << "[CalibrationScanAlgorithm::" << __func__ << "]"
39  << " NULL pointer to base Analysis object!";
40  return;
41  }
42 
44  cal_ = dynamic_cast<CalibrationScanAnalysis*>( tmp );
45  if ( !cal_ ) {
47  << "[CalibrationScanAlgorithm::" << __func__ << "]"
48  << " NULL pointer to derived Analysis object!";
49  return;
50  }
51 
52 
53  // Extract FED key from histo title
54  if ( !histos.empty() ) { cal_->fedKey( extractFedKey( histos.front() ) ); }
55 
56  // Extract histograms
57  std::vector<TH1*>::const_iterator ihis = histos.begin();
58  unsigned int cnt = 0;
59  for ( ; ihis != histos.end(); ihis++,cnt++ ) {
60 
61  // Check for NULL pointer
62  if ( !(*ihis) ) { continue; }
63 
64  // Check name
65  SiStripHistoTitle title( (*ihis)->GetName() );
66  if ( title.runType() != sistrip::CALIBRATION_SCAN &&
68  ) {
70  continue;
71  }
72 
74  Histo histo_temp;
75  histo_temp.first = *ihis;
76  histo_temp.first->Sumw2();
77  histo_temp.second = (*ihis)->GetTitle();
78  histo_[title.extraInfo()].resize(2);
79  if(title.channel()%2 == 0)
80  histo_[title.extraInfo()][0] = histo_temp;
81  else
82  histo_[title.extraInfo()][1] = histo_temp;
83  }
84 }
85 // ----------------------------------------------------------------------------
86 //
88 
89  ROOT::Math::MinimizerOptions::SetDefaultMinimizer("Minuit2","Migrad");
90  ROOT::Math::MinimizerOptions::SetDefaultStrategy(0);
91 
92  if ( !cal_ ) {
94  << "[CalibrationScanAlgorithm::" << __func__ << "]"
95  << " NULL pointer to derived Analysis object!";
96  return;
97  }
98 
100  TFitResultPtr fit_result;
101  TF1* fit_function_turnOn = nullptr;
102  TF1* fit_function_decay = nullptr;
103  TF1* fit_function_deco = nullptr;
104  if(cal_->deconv_){
105  fit_function_deco = new TF1("fit_function_deco",fdeconv,0,400,7);
106  fit_function_deco->SetParameters(4,25,25,50,250,25,0.75);
107  } else{
108  fit_function_turnOn = new TF1("fit_function_turnOn",fturnOn,0,400,4);
109  fit_function_decay = new TF1("fit_function_decay",fdecay,0,400,3);
110  fit_function_turnOn->SetParameters(50,50,40,20);
111  fit_function_decay->SetParameters(-150,-0.01,-0.1);
112  }
113 
115  for(auto map_element : histo_){
116 
117  // add to the analysis result
118  cal_->addOneCalibrationPoint(map_element.first);
119 
120  // stored as integer the scanned isha and vfs values
121  std::vector<std::string> tokens;
122  std::string token;
123  std::istringstream tokenStream(map_element.first);
124  while (std::getline(tokenStream, token,'_')){
125  tokens.push_back(token);
126  }
127 
128  scanned_isha_.push_back(std::stoi(tokens.at(1)));
129  scanned_vfs_.push_back(std::stoi(tokens.at(3)));
130 
131  // loop on APVs
132  for(size_t iapv = 0; iapv < 2; iapv++){
133 
134  if ( !map_element.second[iapv].first ) {
136  << " NULL pointer to histogram for: "<<map_element.second[iapv].second<<" !";
137  return;
138  }
139 
140  cal_->amplitude_[map_element.first][iapv] = 0;
141  cal_->baseline_[map_element.first][iapv] = 0;
142  cal_->riseTime_[map_element.first][iapv] = 0;
143  cal_->turnOn_[map_element.first][iapv] = 0;
144  cal_->peakTime_[map_element.first][iapv] = 0;
145  cal_->undershoot_[map_element.first][iapv] = 0;
146  cal_->tail_[map_element.first][iapv] = 0;
147  cal_->decayTime_[map_element.first][iapv] = 0;
148  cal_->smearing_[map_element.first][iapv] = 0;
149  cal_->chi2_[map_element.first][iapv] = 0;
150  cal_->isvalid_[map_element.first][iapv] = true;
151 
152  if(map_element.second[iapv].first->Integral() == 0){
153  cal_->isvalid_[map_element.first][iapv] = false;
154  continue;
155  }
156 
157  // rescale the plot
158  correctDistribution(map_element.second[iapv].first,false);
159 
160  // from NOTE2009_021 : The charge injection provided by the calibration circuit is known with a precision of 5%;
161  float error= (map_element.second[iapv].first->GetMaximum()*0.05);
162  for(int i = 1; i <= map_element.second[iapv].first->GetNbinsX(); ++i)
163  map_element.second[iapv].first->SetBinError(i,error);
164 
166  if(cal_->deconv_){ // deconvolution mode
167  fit_function_deco->SetParameters(4,25,25,50,250,25,0.75);
168  fit_result = map_element.second[iapv].first->Fit(fit_function_deco,"QRS");
169 
170  if(not fit_result.Get()){
171  cal_->isvalid_[map_element.first][iapv] = false;
172  continue;
173  }
174 
176  float maximum_ampl = fit_function_deco->GetMaximum();
177  float peak_time = fit_function_deco->GetMaximumX();
178  float baseline = baseLine(fit_function_deco);
179  float turn_on_time = turnOn(fit_function_deco,baseline);
180  float rise_time = peak_time - turn_on_time;
181 
182  // start filling info
183  cal_->amplitude_[map_element.first][iapv] = maximum_ampl - baseline;
184  cal_->baseline_[map_element.first][iapv] = baseline;
185  cal_->riseTime_[map_element.first][iapv] = rise_time;
186  cal_->turnOn_[map_element.first][iapv] = turn_on_time;
187  cal_->peakTime_[map_element.first][iapv] = peak_time;
188  if(fit_function_deco->GetMinimumX() > rise_time)
189  cal_->undershoot_[map_element.first][iapv] = 100*(fit_function_deco->GetMinimum()-baseline)/(maximum_ampl - baseline);
190  else
191  cal_->undershoot_[map_element.first][iapv] = 0;
192 
193  // Bin related to peak + 125 ns
194  int lastBin = map_element.second[iapv].first->FindBin(peak_time + 125);
195  if(lastBin > map_element.second[iapv].first->GetNbinsX()-4)
196  lastBin = map_element.second[iapv].first->GetNbinsX()-4;
197 
198  // tail is the amplitude at 5 bx from the maximum
199  cal_->tail_[map_element.first][iapv] = 100*(map_element.second[iapv].first->GetBinContent(lastBin)-baseline) / (maximum_ampl - baseline);
200 
201  // reaches 1/e of the peak amplitude
202  cal_->decayTime_[map_element.first][iapv] = decayTime(fit_function_deco)-peak_time;
203  cal_->smearing_[map_element.first][iapv] = 0;
204  cal_->chi2_[map_element.first][iapv] = fit_function_deco->GetChisquare()/(map_element.second[iapv].first->GetNbinsX()-fit_function_deco->GetNpar());
205 
206  }
207  else{
208 
209  // peak mode
210  fit_function_turnOn->SetParameters(50,50,40,20);
211  fit_function_turnOn->SetRange(fit_function_turnOn->GetXmin(),map_element.second[iapv].first->GetBinCenter(map_element.second[iapv].first->GetMaximumBin())); // up to the maximum
212  fit_result = map_element.second[iapv].first->Fit(fit_function_turnOn,"QSR");
213  if(not fit_result.Get()){
214  cal_->isvalid_[map_element.first][iapv] = false;
215  continue;
216  }
217 
219  float maximum_ampl = fit_function_turnOn->GetMaximum();
220  float peak_time = fit_function_turnOn->GetMaximumX();
221  float baseline = baseLine(fit_function_turnOn);
222  float turn_on_time = turnOn(fit_function_turnOn,baseline);
223  float rise_time = peak_time - turn_on_time;
224 
225  // start filling info
226  cal_->amplitude_[map_element.first][iapv] = maximum_ampl - baseline;
227  cal_->baseline_[map_element.first][iapv] = baseline;
228  cal_->riseTime_[map_element.first][iapv] = rise_time;
229  cal_->turnOn_[map_element.first][iapv] = turn_on_time;
230  cal_->peakTime_[map_element.first][iapv] = peak_time;
231 
232  fit_function_decay->SetParameters(-150,-0.01,-0.1);
233  fit_function_decay->SetRange(map_element.second[iapv].first->GetBinCenter(map_element.second[iapv].first->GetMaximumBin())+10.,fit_function_decay->GetXmax()); // up to the maximum
234  fit_result = map_element.second[iapv].first->Fit(fit_function_decay,"QSR+");
235 
236  if(fit_result.Get() and fit_result->Status() >= 4){
237  cal_->isvalid_[map_element.first][iapv] = false;
238  continue;
239  }
240 
241  cal_->undershoot_[map_element.first][iapv] = 0;
242 
243  // Bin related to peak + 125 ns
244  int lastBin = map_element.second[iapv].first->FindBin(peak_time + 125);
245  if(lastBin > map_element.second[iapv].first->GetNbinsX()-4)
246  lastBin = map_element.second[iapv].first->GetNbinsX()-4;
247 
248  // tail is the amplitude at 5 bx from the maximum
249  cal_->tail_[map_element.first][iapv] = 100*(map_element.second[iapv].first->GetBinContent(lastBin)-baseline) / (maximum_ampl - baseline);
250 
251  // reaches 1/e of the peak amplitude
252  cal_->decayTime_[map_element.first][iapv] = decayTime(fit_function_decay)-peak_time;
253  cal_->smearing_[map_element.first][iapv] = 0;
254  cal_->chi2_[map_element.first][iapv] = (fit_function_turnOn->GetChisquare()+fit_function_decay->GetChisquare())/(map_element.second[iapv].first->GetNbinsX()-fit_function_turnOn->GetNpar()-fit_function_decay->GetNpar());
255 
256  // apply quality requirements
257  bool isvalid = true;
258  if(cal_->amplitude_[map_element.first][iapv] < CalibrationScanAnalysis::minAmplitudeThreshold_) isvalid = false;
259  if(cal_->baseline_[map_element.first][iapv] < CalibrationScanAnalysis::minBaselineThreshold_) isvalid = false;
260  else if(cal_->baseline_[map_element.first][iapv] > CalibrationScanAnalysis::maxBaselineThreshold_) isvalid = false;
261  if(cal_->decayTime_[map_element.first][iapv] < CalibrationScanAnalysis::minDecayTimeThreshold_) isvalid = false;
262  else if(cal_->decayTime_[map_element.first][iapv] > CalibrationScanAnalysis::maxDecayTimeThreshold_) isvalid = false;
263  if(cal_->peakTime_[map_element.first][iapv] < CalibrationScanAnalysis::minPeakTimeThreshold_) isvalid = false;
264  else if(cal_->peakTime_[map_element.first][iapv] > CalibrationScanAnalysis::maxPeakTimeThreshold_) isvalid = false;
265  if(cal_->riseTime_[map_element.first][iapv] < CalibrationScanAnalysis::minRiseTimeThreshold_) isvalid = false;
266  else if(cal_->riseTime_[map_element.first][iapv] > CalibrationScanAnalysis::maxRiseTimeThreshold_) isvalid = false;
267  if(cal_->turnOn_[map_element.first][iapv] < CalibrationScanAnalysis::minTurnOnThreshold_) isvalid = false;
268  else if(cal_->turnOn_[map_element.first][iapv] > CalibrationScanAnalysis::maxTurnOnThreshold_) isvalid = false;
269  if(cal_->chi2_[map_element.first][iapv] > CalibrationScanAnalysis::maxChi2Threshold_) isvalid = false;
270 
271  if(not isvalid){
272  cal_->amplitude_[map_element.first][iapv] = 0;
273  cal_->baseline_[map_element.first][iapv] = 0;
274  cal_->riseTime_[map_element.first][iapv] = 0;
275  cal_->turnOn_[map_element.first][iapv] = 0;
276  cal_->peakTime_[map_element.first][iapv] = 0;
277  cal_->undershoot_[map_element.first][iapv] = 0;
278  cal_->tail_[map_element.first][iapv] = 0;
279  cal_->decayTime_[map_element.first][iapv] = 0;
280  cal_->smearing_[map_element.first][iapv] = 0;
281  cal_->chi2_[map_element.first][iapv] = 0;
282  cal_->isvalid_[map_element.first][iapv] = false;
283  }
284  }
285  }
286  }
287 
288  if(fit_function_deco) delete fit_function_deco;
289  if(fit_function_decay) delete fit_function_decay;
290  if(fit_function_turnOn) delete fit_function_turnOn;
291 }
292 
293 // ------
294 void CalibrationScanAlgorithm::correctDistribution( TH1* histo, const bool & isShape ) const {
295  // 5 events per point in the TM loop
296  // total signal is obtained by summing 16 strips of the same calChan
297  if(not isShape){
298  for(int iBin = 0; iBin < histo->GetNbinsX(); iBin++){
299  histo->SetBinContent(iBin+1,-histo->GetBinContent(iBin+1)/16.);
300  histo->SetBinContent(iBin+1,histo->GetBinContent(iBin+1)/5.);
301  }
302  }
303  else
304  histo->Scale(1./histo->Integral());
305 }
306 
307 // ----------------------------------------------------------------------------
309  float x = f->GetXmin();
310  float xmax = 10;
311  float baseline = 0;
312  int npoints = 0;
313  for( ; x < xmax; x += 0.1) {
314  baseline += f->Eval(x);
315  npoints ++;
316  }
317  return baseline/npoints;
318 }
319 
320 // ----------------------------------------------------------------------------
321 float CalibrationScanAlgorithm::turnOn(TF1* f, const float & baseline){ // should happen within 100 ns in both deco and peak modes
322  float max_amplitude = f->GetMaximum();
323  float time = 10.;
324  for( ; time < 100 && (f->Eval(time) - baseline) < 0.05 * (max_amplitude - baseline); time += 0.1) {} // flucutation higher than 5% of the pulse height
325  return time;
326 }
327 
328 // ----------------------------------------------------------------------------
329 float CalibrationScanAlgorithm::decayTime(TF1* f){ // if we approximate the decay to an exp(-t/tau), in one constant unit, the amplited is reduced by e^{-1}
330  float xval = std::max(f->GetXmin(),f->GetMaximumX());
331  float max_amplitude = f->GetMaximum();
332  float x = xval;
333  for(; x < 1000; x = x+0.1){ // 1000 is a reasoable large bound to compute the decay time .. in case the function is bad it is useful to break the loop
334  if(f->Eval(x) < max_amplitude*exp(-1))
335  break;
336  }
337  return x;
338 }
339 
340 // --- function to extract the VFS value corresponding to decay time of 125ns, then ISHA close to 50 ns
341 void CalibrationScanAlgorithm::tuneIndependently(const int & iapv, const float & targetRiseTime, const float & targetDecayTime){
342 
343  std::map<int,std::vector<float> > decayTime_vs_vfs;
344  TString name;
345  int imap = 0;
346 
347  for(auto map_element : histo_){
348  // only consider isha values in the middle of the scanned range
351  imap++;
352  continue;
353  }
354 
355  if(cal_->isValid(map_element.first)[iapv])
356  decayTime_vs_vfs[scanned_vfs_.at(imap)].push_back(cal_->decayTime(map_element.first)[iapv]);
357 
358  if(name == "" ){ // store the base name
359  name = Form("%s",map_element.second[iapv].first->GetName());
360  name.ReplaceAll("_"+map_element.first,"");
361  }
362  imap++;
363  }
364 
365  // sort before taking the median
366  for(auto iter : decayTime_vs_vfs)
367  sort(iter.second.begin(),iter.second.end());
368 
369  name.ReplaceAll("ExpertHisto_","");
370 
371  // transform the dependance vs vfs in graph
372  cal_->decayTime_vs_vfs_.push_back(new TGraph());
373  cal_->decayTime_vs_vfs_.back()->SetName(Form("decayTime_%s",name.Data()));
374 
375  // transform the dependance vs isha in graph
376  cal_->riseTime_vs_isha_.push_back(new TGraph());
377  cal_->riseTime_vs_isha_.back()->SetName(Form("riseTime_%s",name.Data()));
378 
379  if(!decayTime_vs_vfs.empty()){
380  int ipoint = 0;
381  for(auto map_element : decayTime_vs_vfs){
382  if(!map_element.second.empty()){
383  cal_->decayTime_vs_vfs_.at(iapv)->SetPoint(ipoint,map_element.second.at(round(map_element.second.size()/2)),map_element.first);
384  ipoint++;
385  }
386  }
387 
388  double max_apv = TMath::MaxElement(cal_->decayTime_vs_vfs_.at(iapv)->GetN(),cal_->decayTime_vs_vfs_.at(iapv)->GetY());
389  double min_apv = TMath::MinElement(cal_->decayTime_vs_vfs_.at(iapv)->GetN(),cal_->decayTime_vs_vfs_.at(iapv)->GetY());
390 
391  cal_->vfs_[iapv] = cal_->decayTime_vs_vfs_.at(iapv)->Eval(targetDecayTime);
392 
393  // avoid extrapolations
394  if(cal_->vfs_[iapv] < min_apv) cal_->vfs_[iapv] = min_apv;
395  else if(cal_->vfs_[iapv] > max_apv) cal_->vfs_[iapv] = max_apv;
396 
397  // value for each isha but different ISHA
398  std::map<int,std::vector<float> > riseTime_vs_isha;
399  imap = 0;
400  // store for each isha value all rise time (changing isha)
401  for(auto map_element : histo_){
402  if(fabs(scanned_vfs_.at(imap)-cal_->vfs_[iapv]) < CalibrationScanAnalysis::VFSrange_ and cal_->isValid(map_element.first)[iapv]) //around chosen VFS by \pm 20
403  riseTime_vs_isha[scanned_isha_.at(imap)].push_back(cal_->riseTime(map_element.first)[iapv]);
404  if(name == ""){
405  name = Form("%s",map_element.second[iapv].first->GetName());
406  name.ReplaceAll("_"+map_element.first,"");
407  }
408  imap++;
409  }
410 
411  // sort before taking the median
412  for(auto iter : riseTime_vs_isha)
413  sort(iter.second.begin(),iter.second.end());
414  name.ReplaceAll("ExpertHisto_","");
415 
417  if(!riseTime_vs_isha.empty()){
418  int ipoint = 0;
419  for(auto map_element : riseTime_vs_isha){
420  if(!map_element.second.empty()){
421  cal_->riseTime_vs_isha_.at(iapv)->SetPoint(ipoint,map_element.second.at(round(map_element.second.size()/2)),map_element.first);
422  ipoint++;
423  }
424  }
425 
426  double max_apv = TMath::MaxElement(cal_->riseTime_vs_isha_.at(iapv)->GetN(),cal_->riseTime_vs_isha_.at(iapv)->GetY());
427  double min_apv = TMath::MinElement(cal_->riseTime_vs_isha_.at(iapv)->GetN(),cal_->riseTime_vs_isha_.at(iapv)->GetY());
428 
429  cal_->isha_[iapv] = cal_->riseTime_vs_isha_.at(iapv)->Eval(targetRiseTime);
430 
431  if(cal_->isha_[iapv] < min_apv) cal_->isha_[iapv] = min_apv;
432  else if(cal_->isha_[iapv] > max_apv) cal_->isha_[iapv] = max_apv;
433  }
434  else
435  cal_->isha_[iapv] = -1;
436  }
437 }
438 
440 void CalibrationScanAlgorithm::tuneSimultaneously(const int & iapv, const float & targetRiseTime,const float & targetDecayTime){
441 
442  // Build 2D graph for each APV with rise and decay time trend vs ISHA and VFS
443  cal_->decayTime_vs_isha_vfs_.push_back(new TGraph2D());
444  cal_->riseTime_vs_isha_vfs_.push_back(new TGraph2D());
445 
446  // store for each vfs value all decay time (changing vfs)
447  TString name_apv;
448  int ipoint_apv = 0;
449  int imap = 0;
450 
451  for(auto map_element : histo_){
452  if(cal_->isValid(map_element.first)[iapv]){
453  cal_->decayTime_vs_isha_vfs_.at(iapv)->SetPoint(ipoint_apv,scanned_isha_.at(imap),scanned_vfs_.at(imap),cal_->decayTime(map_element.first)[iapv]);
454  cal_->riseTime_vs_isha_vfs_.at(iapv)->SetPoint(ipoint_apv,scanned_isha_.at(imap),scanned_vfs_.at(imap),cal_->riseTime(map_element.first)[iapv]);
455  ipoint_apv++;
456  }
457  if(name_apv == ""){ // store the base name
458  name_apv = Form("%s",map_element.second[iapv].first->GetName());
459  name_apv.ReplaceAll("_"+map_element.first,"");
460  }
461  imap++;
462  }
463 
464  name_apv.ReplaceAll("ExpertHisto_","");
465 
466  cal_->decayTime_vs_isha_vfs_.at(iapv)->SetName(Form("decayTime_%s",name_apv.Data()));
467  cal_->riseTime_vs_isha_vfs_.at(iapv)->SetName(Form("riseTime_%s",name_apv.Data()));
468 
469  // Define 2D histogram for the distance between values and target
470  TH2F* hist_decay_apv = new TH2F("hist_decay_apv","hist_decay_apv",
471  500,*min_element(scanned_isha_.begin(),scanned_isha_.end()),*max_element(scanned_isha_.begin(),scanned_isha_.end()),
472  500,*min_element(scanned_vfs_.begin(),scanned_vfs_.end()),*max_element(scanned_vfs_.begin(),scanned_vfs_.end()));
473 
474  TH2F* hist_rise_apv = (TH2F*) hist_decay_apv->Clone();
475  hist_rise_apv->SetName("hist_rise_apv");
476  hist_rise_apv->Reset();
477 
478  TH2F* hist_distance = (TH2F*) hist_decay_apv->Clone();
479  hist_distance->SetName("hist_distance");
480  hist_distance->Reset();
481 
482  for(int iBin = 1; iBin <= hist_decay_apv->GetNbinsX(); iBin++){
483  for(int jBin = 1; jBin <= hist_decay_apv->GetNbinsY(); jBin++){
484  if(ipoint_apv != 0){
485  if(cal_->decayTime_vs_isha_vfs_.at(iapv)->GetN() > 10) // to make sure the interpolation can work
486  hist_decay_apv->SetBinContent(iBin,jBin,cal_->decayTime_vs_isha_vfs_.at(iapv)->Interpolate(hist_decay_apv->GetXaxis()->GetBinCenter(iBin),hist_decay_apv->GetYaxis()->GetBinCenter(jBin)));
487  if(cal_->riseTime_vs_isha_vfs_.at(iapv)->GetN() > 10)
488  hist_rise_apv->SetBinContent(iBin,jBin,cal_->riseTime_vs_isha_vfs_.at(iapv)->Interpolate(hist_rise_apv->GetXaxis()->GetBinCenter(iBin),hist_rise_apv->GetYaxis()->GetBinCenter(jBin)));
489  }
490  }
491  }
492 
493  // further smoothing --> a smooth behaviour is indeed expected
494  hist_decay_apv->Smooth();
495  hist_rise_apv->Smooth();
496 
497  for(int iBin = 1; iBin <= hist_decay_apv->GetNbinsX(); iBin++){
498  for(int jBin = 1; jBin <= hist_decay_apv->GetNbinsY(); jBin++){
499  hist_distance->SetBinContent(iBin,jBin,sqrt(pow((hist_decay_apv->GetBinContent(iBin,jBin)-targetDecayTime)/targetDecayTime,2)+
500  pow((hist_rise_apv->GetBinContent(iBin,jBin)-targetRiseTime)/targetRiseTime,2)));
501  }
502  }
503 
504  int minx,miny,minz;
505  hist_distance->GetMinimumBin(minx,miny,minz);
506 
507  cal_->isha_[iapv] = round(hist_distance->GetXaxis()->GetBinCenter(minx));
508  cal_->vfs_[iapv] = round(hist_distance->GetYaxis()->GetBinCenter(miny));
509 
510  delete hist_decay_apv;
511  delete hist_rise_apv;
512  delete hist_distance;
513 
514 }
515 
517 
518  // find the closest isha and vfs for each APV
519  int distance_apv = 10000;
520 
521  // find close by ISHA
522  for(size_t i = 0; i < scanned_isha_.size(); i++){
523  if(fabs(scanned_isha_.at(i)-cal_->bestISHA().at(apvid)) < distance_apv){
524  distance_apv = fabs(scanned_isha_.at(i)-cal_->bestISHA().at(apvid));
525  cal_->tunedISHA_.at(apvid) = scanned_isha_.at(i);
526  }
527  }
528 
529  distance_apv = 10000;
530 
531  // find close by VFS
532  for(size_t i = 0; i < scanned_vfs_.size(); i++){
533  if(fabs(scanned_vfs_.at(i)-cal_->bestVFS().at(apvid)) < distance_apv){
534  distance_apv = fabs(scanned_vfs_.at(i)-cal_->bestVFS().at(apvid));
535  cal_->tunedVFS_.at(apvid) = scanned_vfs_.at(i);
536  }
537  }
538 
540  std::string key_apv = std::string(Form("isha_%d_vfs_%d",cal_->tunedISHA().at(apvid),cal_->tunedVFS().at(apvid)));
541  if(!cal_->amplitude(key_apv).empty() ){
542  cal_->tunedAmplitude_[apvid] = cal_->amplitude(key_apv)[apvid];
543  cal_->tunedTail_[apvid] = cal_->tail(key_apv)[apvid];
544  cal_->tunedRiseTime_[apvid] = cal_->riseTime(key_apv)[apvid];
545  cal_->tunedDecayTime_[apvid] = cal_->decayTime(key_apv)[apvid];
546  cal_->tunedTurnOn_[apvid] = cal_->turnOn(key_apv)[apvid];
547  cal_->tunedPeakTime_[apvid] = cal_->peakTime(key_apv)[apvid];
548  cal_->tunedUndershoot_[apvid] = cal_->undershoot(key_apv)[apvid];
549  cal_->tunedBaseline_[apvid] = cal_->baseline(key_apv)[apvid];
550  cal_->tunedSmearing_[apvid] = cal_->smearing(key_apv)[apvid];
551  cal_->tunedChi2_[apvid] = cal_->chi2(key_apv)[apvid];
552  }
553  else{
554  cal_->tunedAmplitude_[apvid] = 0;
555  cal_->tunedTail_[apvid] = 0;
556  cal_->tunedRiseTime_[apvid] = 0;
557  cal_->tunedDecayTime_[apvid] = 0;
558  cal_->tunedTurnOn_[apvid] = 0;
559  cal_->tunedPeakTime_[apvid] = 0;
560  cal_->tunedUndershoot_[apvid] = 0;
561  cal_->tunedBaseline_[apvid] = 0;
562  cal_->tunedSmearing_[apvid] = 0;
563  cal_->tunedChi2_[apvid] = 0;
564  }
565 }
566 
567 
568 
569 
const VFloat & turnOn(const std::string &key)
static const float maxDecayTimeThreshold_
static const char unexpectedTask_[]
const uint32_t & fedKey() const
std::map< std::string, VFloat > smearing_
const Histo & histo(std::string &key, int &i)
std::map< std::string, VFloat > undershoot_
double fdecay(double *x, double *par)
std::vector< TGraph * > riseTime_vs_isha_
Utility class that holds histogram title.
std::map< std::string, VFloat > decayTime_
static const float minAmplitudeThreshold_
std::pair< TH1 *, std::string > Histo
float turnOn(TF1 *, const float &)
std::map< std::string, VFloat > tail_
const VFloat & tail(const std::string &key)
#define nullptr
std::map< std::string, VFloat > peakTime_
static const float minBaselineThreshold_
const VFloat & chi2(const std::string &key)
const VFloat & amplitude(const std::string &key)
static const float minDecayTimeThreshold_
std::map< std::string, VFloat > chi2_
static const float maxTurnOnThreshold_
void extract(const std::vector< TH1 * > &) override
sistrip classes
double fturnOn(double *x, double *par)
std::map< std::string, std::vector< Histo > > histo_
std::vector< TGraph2D * > riseTime_vs_isha_vfs_
const VBool isValid(const std::string &key)
static const float maxISHAforVFSTune_
static const float maxPeakTimeThreshold_
static const char mlCommissioning_[]
const VFloat & baseline(const std::string &key)
static const float maxChi2Threshold_
const VFloat & decayTime(const std::string &key)
T sqrt(T t)
Definition: SSEVec.h:18
uint32_t extractFedKey(const TH1 *const )
Analysis for calibration scans.
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e< void, edm::EventID const &, edm::Timestamp const & > We also list in braces which AR_WATCH_USING_METHOD_ is used for those or
Definition: Activities.doc:12
std::vector< TGraph2D * > decayTime_vs_isha_vfs_
virtual void addErrorCode(const std::string &error)
double f[11][100]
static const int npoints
static const float maxRiseTimeThreshold_
const VFloat & peakTime(const std::string &key)
static const float minISHAforVFSTune_
const VFloat & undershoot(const std::string &key)
const VFloat & smearing(const std::string &key)
double fdeconv(double *x, double *par)
std::map< std::string, VFloat > amplitude_
std::map< std::string, VFloat > riseTime_
void addOneCalibrationPoint(const std::string &key)
std::vector< TGraph * > decayTime_vs_vfs_
std::map< std::string, VFloat > turnOn_
std::vector< std::vector< double > > tmp
Definition: MVATrainer.cc:100
void tuneIndependently(const int &, const float &, const float &)
static const float minPeakTimeThreshold_
const VFloat & riseTime(const std::string &key)
CalibrationScanAnalysis * cal_
std::map< std::string, VBool > isvalid_
static const float minRiseTimeThreshold_
Abstract base for derived classes that provide analysis of commissioning histograms.
static const float maxBaselineThreshold_
void correctDistribution(TH1 *, const bool &) const
void tuneSimultaneously(const int &, const float &, const float &)
std::map< std::string, VFloat > baseline_
static const float minTurnOnThreshold_
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:40
CommissioningAnalysis *const anal() const