CMS 3D CMS Logo

OptoScanAlgorithm.cc
Go to the documentation of this file.
7 #include "TProfile.h"
8 #include "TH1.h"
9 #include <iostream>
10 #include <sstream>
11 #include <iomanip>
12 
13 using namespace sistrip;
14 
15 // ----------------------------------------------------------------------------
16 //
19  histos_(4, std::vector<Histo>(3, Histo(nullptr, ""))),
20  targetGain_(pset.getParameter<double>("TargetGain")) {
21  edm::LogInfo(mlCommissioning_) << "[PedestalsAlgorithm::" << __func__ << "]"
22  << " Set target gain to: " << targetGain_;
23 }
24 
25 // ----------------------------------------------------------------------------
26 //
27 void OptoScanAlgorithm::extract(const std::vector<TH1*>& histos) {
28  if (!anal()) {
29  edm::LogWarning(mlCommissioning_) << "[OptoScanAlgorithm::" << __func__ << "]"
30  << " NULL pointer to Analysis object!";
31  return;
32  }
33 
34  // Check number of histograms
35  if (histos.size() != 12) {
37  }
38 
39  // Extract FED key from histo title
40  if (!histos.empty())
41  anal()->fedKey(extractFedKey(histos.front()));
42 
43  // Extract histograms
44  std::vector<TH1*>::const_iterator ihis = histos.begin();
45  for (; ihis != histos.end(); ihis++) {
46  // Check for NULL pointer
47  if (!(*ihis)) {
48  continue;
49  }
50 
51  // Check name
52  SiStripHistoTitle title((*ihis)->GetName());
53  if (title.runType() != sistrip::OPTO_SCAN) {
55  continue;
56  }
57 
58  // Extract gain setting and digital high/low info
59  uint16_t gain = sistrip::invalid_;
60  if (title.extraInfo().find(sistrip::extrainfo::gain_) != std::string::npos) {
61  std::stringstream ss;
62  ss << title.extraInfo().substr(
63  title.extraInfo().find(sistrip::extrainfo::gain_) + (sizeof(sistrip::extrainfo::gain_) - 1), 1);
64  ss >> std::dec >> gain;
65  }
66  uint16_t digital = sistrip::invalid_;
67  if (title.extraInfo().find(sistrip::extrainfo::digital_) != std::string::npos) {
68  std::stringstream ss;
69  ss << title.extraInfo().substr(
70  title.extraInfo().find(sistrip::extrainfo::digital_) + (sizeof(sistrip::extrainfo::digital_) - 1), 1);
71  ss >> std::dec >> digital;
72  }
73  bool baseline_rms = false;
74  if (title.extraInfo().find(sistrip::extrainfo::baselineRms_) != std::string::npos) {
75  baseline_rms = true;
76  }
77 
78  if (gain <= 3) {
79  if (digital <= 1) {
80  histos_[gain][digital].first = *ihis;
81  histos_[gain][digital].second = (*ihis)->GetName();
82  } else if (baseline_rms) {
83  histos_[gain][2].first = *ihis;
84  histos_[gain][2].second = (*ihis)->GetName();
85  } else {
87  }
88  } else {
90  }
91  }
92 }
93 
94 // ----------------------------------------------------------------------------
95 //
97  if (!anal()) {
98  edm::LogWarning(mlCommissioning_) << "[OptoScanAlgorithm::" << __func__ << "]"
99  << " NULL pointer to base Analysis object!";
100  return;
101  }
102 
104  OptoScanAnalysis* anal = dynamic_cast<OptoScanAnalysis*>(tmp);
105  if (!anal) {
106  edm::LogWarning(mlCommissioning_) << "[OptoScanAlgorithm::" << __func__ << "]"
107  << " NULL pointer to derived Analysis object!";
108  return;
109  }
110 
111  // Iterate through four gain settings
112  for (uint16_t igain = 0; igain < 4; igain++) {
113  // Select histos appropriate for gain setting
114  TH1* base_his = histos_[igain][0].first;
115  TH1* peak_his = histos_[igain][1].first;
116  TH1* noise_his = histos_[igain][2].first;
117 
118  if (!base_his) {
120  return;
121  }
122 
123  if (!peak_his) {
125  return;
126  }
127 
128  if (!noise_his) {
130  return;
131  }
132 
133  TProfile* base_histo = dynamic_cast<TProfile*>(base_his);
134  if (!base_histo) {
136  return;
137  }
138 
139  TProfile* peak_histo = dynamic_cast<TProfile*>(peak_his);
140  if (!peak_histo) {
142  return;
143  }
144 
145  TProfile* noise_histo = dynamic_cast<TProfile*>(noise_his);
146  if (!noise_histo) {
148  return;
149  }
150 
151  // Check histogram binning
152  uint16_t nbins = static_cast<uint16_t>(peak_histo->GetNbinsX());
153  if (static_cast<uint16_t>(base_histo->GetNbinsX()) != nbins) {
155  if (static_cast<uint16_t>(base_histo->GetNbinsX()) < nbins) {
156  nbins = static_cast<uint16_t>(base_histo->GetNbinsX());
157  }
158  }
159 
160  // Some containers
161  std::vector<float> peak_contents(0);
162  std::vector<float> peak_errors(0);
163  std::vector<float> peak_entries(0);
164  std::vector<float> base_contents(0);
165  std::vector<float> base_errors(0);
166  std::vector<float> base_entries(0);
167  std::vector<float> noise_contents(0);
168  std::vector<float> noise_errors(0);
169  std::vector<float> noise_entries(0);
170  float peak_max = -1. * sistrip::invalid_;
171  float peak_min = 1. * sistrip::invalid_;
172  float base_max = -1. * sistrip::invalid_;
173  float base_min = 1. * sistrip::invalid_;
174  float noise_max = -1. * sistrip::invalid_;
175  float noise_min = 1. * sistrip::invalid_;
176 
177  // Transfer histogram contents/errors/stats to containers
178  for (uint16_t ibin = 0; ibin < nbins; ibin++) {
179  // Peak histogram
180  peak_contents.push_back(peak_histo->GetBinContent(ibin + 1));
181  peak_errors.push_back(peak_histo->GetBinError(ibin + 1));
182  peak_entries.push_back(peak_histo->GetBinEntries(ibin + 1));
183  if (peak_entries[ibin]) {
184  if (peak_contents[ibin] > peak_max) {
185  peak_max = peak_contents[ibin];
186  }
187  if (peak_contents[ibin] < peak_min && ibin) {
188  peak_min = peak_contents[ibin];
189  }
190  }
191 
192  // Base histogram
193  base_contents.push_back(base_histo->GetBinContent(ibin + 1));
194  base_errors.push_back(base_histo->GetBinError(ibin + 1));
195  base_entries.push_back(base_histo->GetBinEntries(ibin + 1));
196  if (base_entries[ibin]) {
197  if (base_contents[ibin] > base_max) {
198  base_max = base_contents[ibin];
199  }
200  if (base_contents[ibin] < base_min && ibin) {
201  base_min = base_contents[ibin];
202  }
203  }
204 
205  // Noise histogram
206  noise_contents.push_back(noise_histo->GetBinContent(ibin + 1));
207  noise_errors.push_back(noise_histo->GetBinError(ibin + 1));
208  noise_entries.push_back(noise_histo->GetBinEntries(ibin + 1));
209  if (noise_entries[ibin]) {
210  if (noise_contents[ibin] > noise_max) {
211  noise_max = noise_contents[ibin];
212  }
213  if (noise_contents[ibin] < noise_min && ibin) {
214  noise_min = noise_contents[ibin];
215  }
216  }
217  }
218 
219  // Find "zero light" level and error
220  //@@ record bias setting used for zero light level
221  //@@ zero light error changes wrt gain setting ???
222  float zero_light_level = sistrip::invalid_;
223  float zero_light_error = sistrip::invalid_;
224  for (uint16_t ibin = 0; ibin < nbins; ibin++) {
225  if (base_entries[ibin]) {
226  zero_light_level = base_contents[ibin];
227  zero_light_error = base_errors[ibin];
228  break;
229  }
230  }
231 
232  float zero_light_thres = sistrip::invalid_;
233  if (zero_light_level <= sistrip::maximum_ && zero_light_error <= sistrip::maximum_) {
234  zero_light_thres = zero_light_level + 5. * zero_light_error;
235  } else {
236  std::stringstream ss;
237  ss << sistrip::invalidZeroLightLevel_ << "ForGain" << igain;
238  anal->addErrorCode(ss.str());
239  continue;
240  }
241 
242  // Find range of base histogram
243  float base_range = base_max - base_min;
244 
245  // Find overlapping max/min region that constrains range of linear fit
246  float max = peak_max < base_max ? peak_max : base_max;
247  float min = peak_min > base_min ? peak_min : base_min;
248  float range = max - min;
249 
250  // Container identifying whether samples from 'base' histo are above "zero light"
251  std::vector<bool> above_zero_light;
252  above_zero_light.resize(3, true);
253 
254  // Linear fits to top of peak and base curves and one to bottom of base curve
255  sistrip::LinearFit peak_high;
256  sistrip::LinearFit base_high;
257  sistrip::LinearFit base_low;
258 
259  // Iterate through histogram bins
260  uint16_t peak_bin = 0;
261  uint16_t base_bin = 0;
262  uint16_t low_bin = 0;
263  for (uint16_t ibin = 0; ibin < nbins; ibin++) {
264  // Record whether consecutive samples from 'base' histo are above the "zero light" level
265  if (base_entries[ibin]) {
266  above_zero_light.erase(above_zero_light.begin());
267  if (base_contents[ibin] > zero_light_thres) {
268  above_zero_light.push_back(true);
269  } else {
270  above_zero_light.push_back(false);
271  }
272  if (above_zero_light.size() != 3) {
273  above_zero_light.resize(3, false);
274  }
275  }
276 
277  // Linear fit to peak histogram
278  if (peak_entries[ibin] && peak_contents[ibin] > (min + 0.2 * range) &&
279  peak_contents[ibin] < (min + 0.8 * range)) {
280  if (!peak_bin) {
281  peak_bin = ibin;
282  }
283  if ((ibin - peak_bin) < 10) {
284  peak_high.add(ibin, peak_contents[ibin]); //@@ should weight using bin error or bin contents (sqrt(N)/N)
285  }
286  }
287  // Linear fit to base histogram
288  if (base_entries[ibin] && base_contents[ibin] > (min + 0.2 * range) &&
289  base_contents[ibin] < (min + 0.8 * range)) {
290  if (!base_bin) {
291  base_bin = ibin;
292  }
293  if ((ibin - base_bin) < 10) {
294  base_high.add(ibin, base_contents[ibin]); //@@ should weight using bin error or bin contents (sqrt(N)/N)
295  }
296  }
297  // Low linear fit to base histogram
298  if (base_entries[ibin] &&
299  //@@ above_zero_light[0] && above_zero_light[1] && above_zero_light[2] &&
300  base_contents[ibin] > (base_min + 0.2 * base_range) && base_contents[ibin] < (base_min + 0.6 * base_range)) {
301  if (!low_bin) {
302  low_bin = ibin;
303  }
304  if ((ibin - low_bin) < 10) {
305  base_low.add(ibin, base_contents[ibin]); //@@ should weight using bin error or bin contents (sqrt(N)/N)
306  }
307  }
308  }
309 
310  // Extract width between two curves at midpoint within range
311  float mid = min + 0.5 * range;
312  sistrip::LinearFit::Params peak_params;
313  sistrip::LinearFit::Params base_params;
314  peak_high.fit(peak_params);
315  base_high.fit(base_params);
316 
317  float peak_pos = sistrip::invalid_;
318  float base_pos = sistrip::invalid_;
319  float width = sistrip::invalid_;
320  if (peak_params.b_ > 0.) {
321  peak_pos = (mid - peak_params.a_) / peak_params.b_;
322  }
323  if (base_params.b_ > 0.) {
324  base_pos = (mid - base_params.a_) / base_params.b_;
325  }
326  if (base_pos < sistrip::valid_ && peak_pos < sistrip::valid_) {
327  width = base_pos - peak_pos;
328  }
329 
330  // Extrapolate to zero light to find "lift off"
331  sistrip::LinearFit::Params low_params;
332  base_low.fit(low_params);
333  float lift_off = sistrip::invalid_;
334  if (low_params.b_ > 0.) {
335  lift_off = (zero_light_level - low_params.a_) / low_params.b_;
336  }
337 
338  // ---------- Set all parameters ----------
339 
340  // Slope of baseline
341  if (low_params.b_ > 0.) {
342  anal->baseSlope_[igain] = low_params.b_;
343  }
344 
345  // Check "lift off" value and set bias setting accordingly
346  if (lift_off <= sistrip::maximum_) {
347  anal->bias_[igain] = static_cast<uint16_t>(lift_off) + 2;
348  } else {
350  }
351 
352  // Calculate "lift off" (in mA)
353  if (lift_off <= sistrip::maximum_) {
354  anal->liftOff_[igain] = 0.45 * lift_off;
355  }
356 
357  // Calculate laser threshold (in mA)
358  if (width < sistrip::invalid_) {
359  anal->threshold_[igain] = 0.45 * (lift_off - width / 2.);
360  }
361 
362  // Set "zero light" level
363  anal->zeroLight_[igain] = zero_light_level;
364 
365  // Set link noise
366  uint16_t bin_number = sistrip::invalid_;
367  if (anal->threshold_[igain] < sistrip::valid_) {
368  // Old calculation, used in commissioning in 2008
369  // always leads to zero link noise
370  // bin_number = static_cast<uint16_t>( anal->threshold_[igain] / 0.45 );
371  // New calculation asked by Karl et al, for commissioning in 2009
372  bin_number = (uint16_t)(lift_off + width / 3.);
373  }
374  if (bin_number < sistrip::valid_) {
375  if (bin_number < noise_contents.size()) {
376  anal->linkNoise_[igain] = noise_contents[bin_number];
377  } else {
379  }
380  }
381 
382  // Calculate tick mark height
383  if (low_params.b_ <= sistrip::maximum_ && width <= sistrip::maximum_) {
384  anal->tickHeight_[igain] = width * low_params.b_;
385  }
386 
387  // Set measured gain
388  if (anal->tickHeight_[igain] < sistrip::invalid_ - 1.) {
389  anal->measGain_[igain] = anal->tickHeight_[igain] * OptoScanAnalysis::fedAdcGain_ / 0.800;
390  } else {
391  anal->measGain_[igain] = sistrip::invalid_;
392  }
393 
394  } // gain loop
395 
396  // Iterate through four gain settings and identify optimum gain setting
397  const float target_gain =
398  targetGain_; //0.863; // changed from 0.8 to avoid choice of low tickheights (Xtof, SL, 15/6/2009)
399 
400  float diff_in_gain = sistrip::invalid_;
401  for (uint16_t igain = 0; igain < 4; igain++) {
402  // Check for sensible gain value
403  if (anal->measGain_[igain] > sistrip::maximum_) {
404  continue;
405  }
406 
407  // Find optimum gain setting
408  if (fabs(anal->measGain_[igain] - target_gain) < diff_in_gain) {
409  anal->gain_ = igain;
410  diff_in_gain = fabs(anal->measGain_[igain] - target_gain);
411  }
412  }
413 
414  // Check optimum gain setting
415  if (anal->gain_ > sistrip::maximum_) {
417  }
418 }
419 
420 // ----------------------------------------------------------------------------
421 //
422 CommissioningAlgorithm::Histo OptoScanAlgorithm::histo(const uint16_t& gain, const uint16_t& digital_level) const {
423  if (gain <= 3 && digital_level <= 1) {
424  return histos_[gain][digital_level];
425  } else {
426  return Histo(nullptr, "");
427  }
428 }
Histogram-based analysis for opto bias/gain scan.
CommissioningAnalysis *const anal() const
static const char unexpectedTask_[]
Histo histo(const uint16_t &gain, const uint16_t &digital_level) const
Utility class that holds histogram title.
void analyse() override
static const char numberOfHistos_[]
static const char unexpectedExtraInfo_[]
static const uint16_t valid_
Definition: Constants.h:17
static const char numberOfBins_[]
sistrip classes
static const char baselineRms_[]
uint32_t extractFedKey(const TH1 *const)
static const float fedAdcGain_
static const char mlCommissioning_[]
static const uint16_t maximum_
Definition: Constants.h:20
virtual void addErrorCode(const std::string &error)
void extract(const std::vector< TH1 *> &) override
const uint32_t & fedKey() const
static const char digital_[]
std::vector< std::vector< Histo > > histos_
void add(const float &value_x, const float &value_y)
Definition: Utility.cc:10
static const uint16_t defaultBiasSetting_
Log< level::Info, false > LogInfo
std::pair< TH1 *, std::string > Histo
static const uint16_t invalid_
Definition: Constants.h:16
static const char gain_[]
Abstract base for derived classes that provide analysis of commissioning histograms.
static const uint16_t defaultGainSetting_
Log< level::Warning, false > LogWarning
void fit(Params &fit_params)
Definition: Utility.cc:37
tmp
align.sh
Definition: createJobs.py:716
static const char unexpectedBinNumber_[]
static const char nullPtr_[]
static const char invalidZeroLightLevel_[]