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