CMS 3D CMS Logo

ApvTimingAlgorithm.cc
Go to the documentation of this file.
6 #include "TProfile.h"
7 #include "TH1.h"
8 #include <iostream>
9 #include <iomanip>
10 #include <cmath>
11 
12 using namespace sistrip;
13 
14 // ----------------------------------------------------------------------------
15 //
17  : CommissioningAlgorithm(anal), histo_(nullptr, "") {
18  ;
19 }
20 
21 // ----------------------------------------------------------------------------
22 //
23 void ApvTimingAlgorithm::extract(const std::vector<TH1*>& histos) {
24  if (!anal()) {
25  edm::LogWarning(mlCommissioning_) << "[ApvTimingAlgorithm::" << __func__ << "]"
26  << " NULL pointer to Analysis object!";
27  return;
28  }
29 
30  // Check number of histograms
31  if (histos.size() != 1) {
33  }
34 
35  // Extract FED key from histo title
36  if (!histos.empty()) {
37  anal()->fedKey(extractFedKey(histos.front()));
38  }
39 
40  // Extract histograms
41  std::vector<TH1*>::const_iterator ihis = histos.begin();
42  for (; ihis != histos.end(); ihis++) {
43  // Check for NULL pointer
44  if (!(*ihis)) {
45  continue;
46  }
47 
48  // Check name
49  SiStripHistoTitle title((*ihis)->GetName());
50  if (title.runType() != sistrip::APV_TIMING) {
52  continue;
53  }
54 
55  // Extract timing histo
56  histo_.first = *ihis;
57  histo_.second = (*ihis)->GetName();
58  }
59 }
60 
61 // ----------------------------------------------------------------------------
62 //
64  if (!anal()) {
65  edm::LogWarning(mlCommissioning_) << "[ApvTimingAlgorithm::" << __func__ << "]"
66  << " NULL pointer to base Analysis object!";
67  return;
68  }
69 
71  ApvTimingAnalysis* anal = dynamic_cast<ApvTimingAnalysis*>(tmp);
72  if (!anal) {
73  edm::LogWarning(mlCommissioning_) << "[ApvTimingAlgorithm::" << __func__ << "]"
74  << " NULL pointer to derived Analysis object!";
75  return;
76  }
77 
78  if (!histo_.first) {
80  return;
81  }
82 
83  TProfile* histo = dynamic_cast<TProfile*>(histo_.first);
84  if (!histo) {
86  return;
87  }
88 
89  // Transfer histogram contents/errors/stats to containers
90  uint16_t non_zero = 0;
91  float max = -1. * sistrip::invalid_;
92  float min = 1. * sistrip::invalid_;
93  uint16_t nbins = static_cast<uint16_t>(histo->GetNbinsX());
94  std::vector<float> bin_contents;
95  std::vector<float> bin_errors;
96  std::vector<float> bin_entries;
97  bin_contents.reserve(nbins);
98  bin_errors.reserve(nbins);
99  bin_entries.reserve(nbins);
100  for (uint16_t ibin = 0; ibin < nbins; ibin++) {
101  bin_contents.push_back(histo->GetBinContent(ibin + 1));
102  bin_errors.push_back(histo->GetBinError(ibin + 1));
103  bin_entries.push_back(histo->GetBinEntries(ibin + 1));
104  if (bin_entries[ibin]) {
105  if (bin_contents[ibin] > max) {
106  max = bin_contents[ibin];
107  }
108  if (bin_contents[ibin] < min) {
109  min = bin_contents[ibin];
110  }
111  non_zero++;
112  }
113  }
114  if (bin_contents.size() < 100) {
116  return;
117  }
118 
119  // Calculate range (max-min) and threshold level (range/2)
120  float threshold = min + (max - min) / 2.;
121  anal->base_ = min;
122  anal->peak_ = max;
123  anal->height_ = max - min;
126  return;
127  }
128 
129  // Associate samples with either "tick mark" or "baseline"
130  std::vector<float> tick;
131  std::vector<float> base;
132  for (uint16_t ibin = 0; ibin < nbins; ibin++) {
133  if (bin_entries[ibin]) {
134  if (bin_contents[ibin] < threshold) {
135  base.push_back(bin_contents[ibin]);
136  } else {
137  tick.push_back(bin_contents[ibin]);
138  }
139  }
140  }
141 
142  // Find median level of tick mark and baseline
143  float tickmark = 0.;
144  float baseline = 0.;
145  sort(tick.begin(), tick.end());
146  sort(base.begin(), base.end());
147  if (!tick.empty()) {
148  tickmark = tick[tick.size() % 2 ? tick.size() / 2 : tick.size() / 2];
149  }
150  if (!base.empty()) {
151  baseline = base[base.size() % 2 ? base.size() / 2 : base.size() / 2];
152  }
153  anal->base_ = baseline;
154  anal->peak_ = tickmark;
155  anal->height_ = tickmark - baseline;
156  if (tickmark - baseline < ApvTimingAnalysis::tickMarkHeightThreshold_) {
158  return;
159  }
160 
161  // Find rms spread in "baseline" samples
162  float mean = 0.;
163  float mean2 = 0.;
164  for (uint16_t ibin = 0; ibin < base.size(); ibin++) {
165  mean += base[ibin];
166  mean2 += base[ibin] * base[ibin];
167  }
168  if (!base.empty()) {
169  mean = mean / base.size();
170  mean2 = mean2 / base.size();
171  } else {
172  mean = 0.;
173  mean2 = 0.;
174  }
175  float baseline_rms = sqrt(fabs(mean2 - mean * mean));
176 
177  // Find rising edges (derivative across two bins > threshold)
178  std::map<uint16_t, float> edges;
179  for (uint16_t ibin = 1; ibin < nbins - 1; ibin++) {
180  if (bin_entries[ibin + 1] && bin_entries[ibin - 1]) {
181  float derivative = bin_contents[ibin + 1] - bin_contents[ibin - 1];
182  if (derivative > 3. * baseline_rms) {
183  edges[ibin] = derivative;
184  }
185  }
186  }
187  if (edges.empty()) {
189  return;
190  }
191 
192  // Iterate through "edges" map
193  uint16_t max_derivative_bin = sistrip::invalid_;
194  float max_derivative = -1. * sistrip::invalid_;
195 
196  bool found = false;
197  std::map<uint16_t, float>::iterator iter = edges.begin();
198  while (!found && iter != edges.end()) {
199  // Iterate through 50 subsequent samples
200  bool valid = true;
201  for (uint16_t ii = 0; ii < 50; ii++) {
202  uint16_t bin = iter->first + ii;
203 
204  // Calc local derivative
205  float temp = 0.;
206  if (static_cast<uint32_t>(bin) < 1 || static_cast<uint32_t>(bin + 1) >= nbins) {
207  valid = false; //@@ require complete plateau is found within histo
209  continue;
210  }
211  temp = bin_contents[bin + 1] - bin_contents[bin - 1];
212 
213  // Store max derivative
214  if (temp > max_derivative) {
215  max_derivative = temp;
216  max_derivative_bin = bin;
217  }
218 
219  // Check if samples following edge are all "high"
220  if (ii > 10 && ii < 40 && bin_entries[bin] && bin_contents[bin] < baseline + 5. * baseline_rms) {
221  valid = false;
222  }
223  }
224 
225  // Break from loop if tick mark found
226  if (valid) {
227  found = true;
228  }
229 
230  /*
231  else {
232  max_derivative = -1.*sistrip::invalid_;
233  max_derivative_bin = sistrip::invalid_;
234  //edges.erase(iter);
235  anal->addErrorCode(sistrip::rejectedCandidate_);
236  }
237  */
238 
239  iter++; // next candidate
240  }
241 
242  if (!found) { //Try tick mark recovery
243 
244  max_derivative_bin = sistrip::invalid_;
245  max_derivative = -1. * sistrip::invalid_;
246 
247  // Find rising edges_r (derivative_r across five bins > threshold)
248  std::map<uint16_t, float> edges_r;
249  for (uint16_t ibin_r = 1; ibin_r < nbins - 1; ibin_r++) {
250  if (bin_entries[ibin_r + 4] && bin_entries[ibin_r + 3] && bin_entries[ibin_r + 2] && bin_entries[ibin_r + 1] &&
251  bin_entries[ibin_r] && bin_entries[ibin_r - 1]) {
252  float derivative_r = bin_contents[ibin_r + 1] - bin_contents[ibin_r - 1];
253  float derivative_r1 = bin_contents[ibin_r + 1] - bin_contents[ibin_r];
254  float derivative_r2 = bin_contents[ibin_r + 2] - bin_contents[ibin_r + 1];
255  float derivative_r3 = bin_contents[ibin_r + 3] - bin_contents[ibin_r + 2];
256 
257  if (derivative_r > 3. * baseline_rms && derivative_r1 > 1. * baseline_rms &&
258  derivative_r2 > 1. * baseline_rms && derivative_r3 > 1. * baseline_rms) {
259  edges_r[ibin_r] = derivative_r;
260  }
261  }
262  }
263  if (edges_r.empty()) {
265  return;
266  }
267 
268  // Iterate through "edges_r" map
269  float max_derivative_r = -1. * sistrip::invalid_;
270 
271  bool found_r = false;
272  std::map<uint16_t, float>::iterator iter_r = edges_r.begin();
273  while (!found_r && iter_r != edges_r.end()) {
274  // Iterate through 50 subsequent samples
275  bool valid_r = true;
276  int lowpointcount_r = 0;
277  const int lowpointallow_r = 25; //Number of points allowed to fall below threshhold w/o invalidating tick mark
278  for (uint16_t ii_r = 0; ii_r < 50; ii_r++) {
279  uint16_t bin_r = iter_r->first + ii_r;
280 
281  // Calc local derivative_r
282  float temp_r = 0.;
283  if (static_cast<uint32_t>(bin_r) < 1 || static_cast<uint32_t>(bin_r + 1) >= nbins) {
284  valid_r = false; //@@ require complete plateau is found_r within histo
286  continue;
287  }
288  temp_r = bin_contents[bin_r + 1] - bin_contents[bin_r - 1];
289 
290  // Store max derivative_r
291  if (temp_r > max_derivative_r && ii_r < 10) {
292  max_derivative_r = temp_r;
293  max_derivative = temp_r;
294  max_derivative_bin = bin_r;
295  }
296 
297  // Check if majority of samples following edge are all "high"
298  if (ii_r > 10 && ii_r < 40 && bin_entries[bin_r] && bin_contents[bin_r] < baseline + 5. * baseline_rms) {
299  lowpointcount_r++;
300  if (lowpointcount_r > lowpointallow_r) {
301  valid_r = false;
302  }
303  }
304  }
305 
306  // Break from loop if recovery tick mark found
307  if (valid_r) {
308  found_r = true;
309  found = true;
311  } else {
312  max_derivative_r = -1. * sistrip::invalid_;
313  max_derivative = -1. * sistrip::invalid_;
314  max_derivative_bin = sistrip::invalid_;
315  //edges_r.erase(iter_r);
317  }
318 
319  iter_r++; // next candidate
320  }
321  } //End tick mark recovery
322 
323  // Record time monitorable and check tick mark height
324  if (max_derivative_bin <= sistrip::valid_) {
325  anal->time_ = max_derivative_bin * 25. / 24.;
328  }
329  } else {
331  }
332 }
CommissioningAnalysis *const anal() const
void extract(const std::vector< TH1 *> &) override
static const char unexpectedTask_[]
Derivative< X, A >::type derivative(const A &_)
Definition: Derivative.h:18
Utility class that holds histogram title.
static const char numberOfHistos_[]
base
Main Program
Definition: newFWLiteAna.py:92
static const float tickMarkHeightThreshold_
static const uint16_t valid_
Definition: Constants.h:17
static const char incompletePlateau_[]
static const char numberOfBins_[]
sistrip classes
uint32_t extractFedKey(const TH1 *const)
static const char missingTickMark_[]
static const char rejectedCandidate_[]
static const char mlCommissioning_[]
static const char tickMarkRecovered_[]
T sqrt(T t)
Definition: SSEVec.h:19
static const char tickMarkBelowThresh_[]
const Histo & histo() const
virtual void addErrorCode(const std::string &error)
const uint32_t & fedKey() const
ii
Definition: cuy.py:589
static const char smallTickMarkHeight_[]
static const uint16_t invalid_
Definition: Constants.h:16
static const char noRisingEdges_[]
static const char smallDataRange_[]
histos
Definition: combine.py:4
void analyse() override
Abstract base for derived classes that provide analysis of commissioning histograms.
Log< level::Warning, false > LogWarning
tmp
align.sh
Definition: createJobs.py:716
Analysis for timing run using APV tick marks.
static const char nullPtr_[]