CMS 3D CMS Logo

HistogramManager.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Package: SiPixelPhase1Common
4 // Class : HistogramManager
5 //
7 
8 #include <sstream>
9 #include <boost/algorithm/string.hpp>
10 
11 // Geometry stuff
15 
16 // Logger
18 
20  GeometryInterface& geo)
21  : iConfig(iconfig),
22  geometryInterface(geo),
23  enabled(iconfig.getParameter<bool>("enabled")),
24  perLumiHarvesting(iconfig.getParameter<bool>("perLumiHarvesting")),
25  bookUndefined(iconfig.getParameter<bool>("bookUndefined")),
26  top_folder_name(iconfig.getParameter<std::string>("topFolderName")),
27  name(iconfig.getParameter<std::string>("name")),
28  title(iconfig.getParameter<std::string>("title")),
29  xlabel(iconfig.getParameter<std::string>("xlabel")),
30  ylabel(iconfig.getParameter<std::string>("ylabel")),
31  dimensions(iconfig.getParameter<int>("dimensions")),
32  range_x_nbins(iconfig.getParameter<int>("range_nbins")),
33  range_x_min(iconfig.getParameter<double>("range_min")),
34  range_x_max(iconfig.getParameter<double>("range_max")),
35  range_y_nbins(iconfig.getParameter<int>("range_y_nbins")),
36  range_y_min(iconfig.getParameter<double>("range_y_min")),
37  range_y_max(iconfig.getParameter<double>("range_y_max")) {
38  auto spec_configs = iconfig.getParameter<edm::VParameterSet>("specs");
39  for (auto spec : spec_configs) {
40  // this would fit better in SummationSpecification(...), but it has to
41  // happen here.
42  auto conf = spec.getParameter<edm::ParameterSet>("conf");
43  if (!conf.getParameter<bool>("enabled")) continue;
45  }
46 }
47 
49  specs.push_back(spec);
50  tables.push_back(Table());
51  counters.push_back(Table());
53  fastpath.push_back(nullptr);
54 }
55 
56 // This is the hottest function in the HistogramManager. Make sure it does not
57 // allocate memory or other expensive things.
58 // Currently the GeometryInterface::extract (some virtual calls) and the map
59 // lookups should be the most expensive things, but they should only happen if
60 // the module changed from the last call; an optimization that fails when row/
61 // col are used.
62 // fillInternal (called from here) does more lookups on the geometry, if EXTEND
63 // is used; we do not attempt the optimization there since in most cases row/
64 // col are involved.
65 void HistogramManager::fill(double x, double y, DetId sourceModule,
66  const edm::Event* sourceEvent, int col, int row) {
67  if (!enabled) return;
68 
69  // We only need to check the module here, since the fastpath is only used to
70  // determine which plot is filled (not which bin inside) and fillInternal
71  // re-extracts whatever it needs for the axis.
72  // Since do not support booking based on ROC or time, the plot can only depend
73  // on the module.
74  // The sourceEvent check is not really effective (pointer is always the same)
75  // but needed for initialisation.
76  // NOTE that this might change if we want to support per-ROC booking
77  // NOTE that we could even cache the bin to fill if iq and spec are identical,
78  // also across HistogramManagers.
79  bool cached = false;
80  if (sourceModule == this->iq.sourceModule
81  && sourceEvent == this->iq.sourceEvent) {
82  cached = true;
83  }
84  iq = GeometryInterface::InterestingQuantities{sourceEvent, sourceModule,
85  int16_t(col), int16_t(row)};
86  for (unsigned int i = 0; i < specs.size(); i++) {
87  auto& s = specs[i];
88  auto& t = s.steps[0].type == SummationStep::COUNT ? counters[i] : tables[i];
89  if (!cached) { // recompute ME to fill (aka fastpath)
90  significantvalues[i].clear();
91  geometryInterface.extractColumns(s.steps[0].columns, iq,
93  auto histo = t.find(significantvalues[i]);
94  if (histo == t.end()) {
95  if (bookUndefined) {
96  edm::LogError("HistogramManager") << "Missing Histogram!\n"
97  << "name " << tables[i].begin()->second.th1->GetName() << "\n";
98  assert(!"Histogram not booked! Probably inconsistent geometry description.");
99  }
100  fastpath[i] = nullptr;
101  } else {
102  fastpath[i] = &(histo->second);
103  }
104  }
105  // A fastpath of nullptr means there is no ME for this iq, which can be
106  // a valid cached result.
107  if (fastpath[i]) {
108  if (s.steps[0].type == SummationStep::COUNT) {
109  fastpath[i]->count++;
110  } else {
111  fillInternal(x, y, this->dimensions, iq, s.steps.begin()+1, s.steps.end(), *(fastpath[i]));
112  }
113  }
114  }
115 }
116 void HistogramManager::fill(double x, DetId sourceModule,
117  const edm::Event* sourceEvent, int col, int row) {
118  assert(this->dimensions == 1);
119  fill(x, 0.0, sourceModule, sourceEvent, col, row);
120 }
121 void HistogramManager::fill(DetId sourceModule, const edm::Event* sourceEvent,
122  int col, int row) {
123  assert(this->dimensions == 0);
124  fill(0.0, 0.0, sourceModule, sourceEvent, col, row);
125 }
126 
127 void HistogramManager::fillInternal(double x, double y, int n_parameters,
129  std::vector<SummationStep>::iterator first,
130  std::vector<SummationStep>::iterator last,
132 
133  double fx = 0, fy = 0, fz = 0;
134  int tot_parameters = n_parameters;
135  for (auto it = first; it != last; ++it) {
136  if (it->stage != SummationStep::STAGE1) break;
137  // The specification builder precomputes where x and y go, this loop will
138  // always do 3 iterations to set x, y, z. The builder does not know how
139  // many parameters we have, so we have to check that and count the total.
140  switch (it->type) {
142  if (it->arg[0] == '1' && n_parameters >= 1) fx = x;
143  if (it->arg[0] == '2' && n_parameters >= 2) fx = y;
144  break;
146  if (it->arg[0] == '1' && n_parameters >= 1) fy = x;
147  if (it->arg[0] == '2' && n_parameters >= 2) fy = y;
148  break;
150  if (it->arg[0] == '1' && n_parameters >= 1) fz = x;
151  if (it->arg[0] == '2' && n_parameters >= 2) fz = y;
152  break;
154  fx = geometryInterface.extract(it->columns[0], iq).second;
155  tot_parameters++;
156  break;
158  fy = geometryInterface.extract(it->columns[0], iq).second;
159  tot_parameters++;
160  break;
162  break; // profile does not make a difference here, only in booking
163  default:
164  assert(!"illegal step in STAGE1!");
165  }
166  }
167 
168  switch(tot_parameters) {
169  case 1:
170  dest.me->Fill(fx);
171  break;
172  case 2:
173  dest.me->Fill(fx, fy);
174  break;
175  case 3:
176  dest.me->Fill(fx, fy, fz);
177  break;
178  default:
179  edm::LogError("HistogramManager") << "got " << tot_parameters << " dimensions\n"
180  << "name " << dest.th1->GetName() << "\n";
181  assert(!"More than 3 dimensions should never occur.");
182  }
183 }
184 
185 
186 // This is only used for ndigis-like counting. It could be more optimized, but
187 // is probably fine for a per-event thing.
189  if (!enabled) return;
190  for (unsigned int i = 0; i < specs.size(); i++) {
191  auto& s = specs[i];
192  auto& t = tables[i];
193  auto& c = counters[i];
194  if (s.steps[0].type != SummationStep::COUNT) continue; // no counting, done
195  assert((s.steps.size() >= 2 && s.steps[1].type == SummationStep::GROUPBY)
196  || !"Incomplete spec (but this cannot be caught in Python)");
197  for (auto& e : c) {
198  // the iq on the counter can only be a _sample_, since many modules
199  // could be grouped on one counter. Even worse, the sourceEvent ptr
200  // could be dangling if the counter was not touched in this event, so
201  // we replace it. row/col are most likely useless as well.
202  auto iq = e.second.iq_sample;
203  iq.sourceEvent = sourceEvent;
204 
205  significantvalues[i].clear();
206  geometryInterface.extractColumns(s.steps[1].columns, iq,
208  auto histo = t.find(significantvalues[i]);
209  if (histo == t.end()) {
210  if (!bookUndefined) continue;
211  edm::LogError("HistogramManager") << "Histogram Missing!\n"
212  << "name " << t.begin()->second.th1->GetName() << "\n"
213  << "ctr " << " detid " << iq.sourceModule << "\n";
214  assert(!"Histogram not booked! (per-event) Probably inconsistent geometry description.");
215  }
216  fillInternal(e.second.count, 0, 1, iq, s.steps.begin()+2, s.steps.end(), histo->second);
217  e.second.count = 0;
218  }
219  }
220 }
221 
222 std::pair<std::string, std::string>
225  SummationStep const* upto) {
226  std::ostringstream dir("");
227  std::string suffix = "";
228 
229  // we omit the last value here, to get all disks next to each other etc.
230  if (!significantvalues.empty()) {
231  for (auto it = significantvalues.begin();
232  it != (significantvalues.end()-1); ++it) {
233  auto name = geometryInterface.formatValue(it->first, it->second);
234  if (name == "") continue;
235  dir << name << "/";
236  }
237  auto e = significantvalues[significantvalues.size()-1];
238  suffix = "_" + geometryInterface.formatValue(e.first, e.second);
239  }
240 
241  // PERF: this is actually independent of significantvalues and iq
242  std::string name = this->name;
243  for (SummationStep const& step : s.steps) {
244  if (&step == upto) break;
245  switch (step.type) {
247  name = "num_" + name;
248  break;
251  if (step.stage != SummationStep::STAGE1) break;
252  GeometryInterface::Column col0 = step.columns[0];
253  std::string colname = geometryInterface.pretty(col0);
254  name = name + "_per_" + colname;
255  break;}
256  case SummationStep::REDUCE: {
257  auto red = step.arg;
258  boost::algorithm::to_lower(red);
259  name = red + "_" + name;
260  break;}
261  default:
262  // Maybe PROFILE is worth showing.
263  break; // not visible in name
264  }
265  }
266  return std::make_pair(top_folder_name + "/" + dir.str(), name + suffix);
267 }
268 
269 
271  edm::EventSetup const& iSetup) {
272  if (!geometryInterface.loaded()) {
273  geometryInterface.load(iSetup);
274  }
275  if (!enabled) return;
276 
277  struct MEInfo {
278  int dimensions = 1;
279  double range_x_min = 1e12;
280  double range_x_max = -1e12;
281  double range_y_min = 1e12;
282  double range_y_max = -1e12;
283  double range_z_min = 1e12; // z range carried around but unused
284  double range_z_max = -1e12;
285  int range_x_nbins = 0;
286  int range_y_nbins = 0;
287  int range_z_nbins = 0;
288  GeometryInterface::Value binwidth_x = 0; // override nbins for geom-things
289  GeometryInterface::Value binwidth_y = 0;
290  std::string title, xlabel, ylabel, zlabel;
291  bool do_profile = false;
292  };
293  std::map<GeometryInterface::Values, MEInfo> toBeBooked;
294 
295  for (unsigned int i = 0; i < specs.size(); i++) {
296  auto& s = specs[i];
297  auto& t = tables[i];
298  auto& c = counters[i];
299  toBeBooked.clear();
300  bool bookCounters = false;
301 
302  auto firststep = s.steps.begin();
303  int n_parameters = this->dimensions;
304 
305  if (firststep->type != SummationStep::GROUPBY) {
306  ++firststep;
307  n_parameters = 1;
308  bookCounters = true;
309  }
310 
311  auto laststep = std::find_if(s.steps.begin(), s.steps.end(),
312  [](SummationStep const& step) { return step.stage == SummationStep::STAGE2; });
313 
315 
316  for (auto iq : geometryInterface.allModules()) {
317 
318  if (bookCounters) {
319  // add an entry for the counting step if present
320  geometryInterface.extractColumns(s.steps[0].columns, iq,
321  significantvalues);
322  c[significantvalues].iq_sample = iq;
323  }
324 
325  geometryInterface.extractColumns(firststep->columns, iq,
326  significantvalues);
327  if (!bookUndefined) {
328  // skip if any column is UNDEFINED
329  bool ok = true;
330  for (auto e : significantvalues)
331  if (e.second == GeometryInterface::UNDEFINED) ok = false;
332  if (!ok) continue;
333  }
334 
335  auto histo = toBeBooked.find(significantvalues);
336  if (histo == toBeBooked.end()) {
337  // create new histo
338  MEInfo& mei = toBeBooked[significantvalues];
339  mei.title = this->title;
340  if (bookCounters)
341  mei.title = "Number of " + mei.title + " per Event and "
342  + geometryInterface.pretty(*(s.steps[0].columns.end()-1));
343  std::string xlabel = bookCounters ? "#" + this->xlabel : this->xlabel;
344 
345  // refer to fillInternal() for the actual execution
346  // compute labels, title, type, user-set ranges here
347  int tot_parameters = n_parameters;
348 
349 #define SET_AXIS(to, from) \
350  mei.to##label = from##label; \
351  mei.range_##to##_min = ((it->nbins == -1) ? this->range_##from##_min : it->xmin); \
352  mei.range_##to##_max = ((it->nbins == -1) ? this->range_##from##_max : it->xmax); \
353  mei.range_##to##_nbins = ((it->nbins == -1) ? this->range_##from##_nbins : it->nbins)
354 
355 
356  for (auto it = firststep+1; it != laststep; ++it) {
357  switch (it->type) {
359  if (it->arg[0] == '1' && n_parameters >= 1) { SET_AXIS(x, x); } // TODO: make use of current nbins, xmin, xmax if set
360  if (it->arg[0] == '2' && n_parameters >= 2) { SET_AXIS(x, y); }
361  break;
363  if (it->arg[0] == '1' && n_parameters >= 1) { SET_AXIS(y, x); }
364  if (it->arg[0] == '2' && n_parameters >= 2) { SET_AXIS(y, y); }
365  break;
367  if (it->arg[0] == '1' && n_parameters >= 1) { SET_AXIS(z, x); }
368  if (it->arg[0] == '2' && n_parameters >= 2) { SET_AXIS(z, y); }
369  break;
371  assert(mei.range_x_nbins == 0);
372  auto col = it->columns[0];
373  mei.xlabel = geometryInterface.pretty(col);
374  mei.title = mei.title + " by " + mei.xlabel;
376  mei.range_x_min = geometryInterface.minValue(col);
378  mei.range_x_max = geometryInterface.maxValue(col);
379  mei.binwidth_x = geometryInterface.binWidth(col);
380  tot_parameters++; }
381  break;
383  auto col = it->columns[0];
384  mei.ylabel = geometryInterface.pretty(col);
385  mei.title = mei.title + " by " + mei.ylabel;
387  mei.range_y_min = geometryInterface.minValue(col);
389  mei.range_y_max = geometryInterface.maxValue(col);
390  mei.binwidth_y = geometryInterface.binWidth(col);
391  tot_parameters++; }
392  break;
394  mei.do_profile = true;
395  break;
396  default:
397  assert(!"illegal step in STAGE1! (booking)");
398  }
399  }
400  mei.dimensions = tot_parameters;
401  if (mei.do_profile) mei.title = "Profile of " + mei.title;
402  if (!mei.zlabel.empty()) mei.title = mei.title + " (Z: " + mei.zlabel + ")";
403  }
404  // only update range
405  MEInfo& mei = toBeBooked[significantvalues];
406  double val;
407 
408  for (auto it = firststep+1; it != laststep; ++it) {
409  switch (it->type) {
411  val = geometryInterface.extract(it->columns[0], iq).second;
412  if (val == GeometryInterface::UNDEFINED) break;
413  mei.range_x_min = std::min(mei.range_x_min, val);
414  mei.range_x_max = std::max(mei.range_x_max, val);
415  break;
417  val = geometryInterface.extract(it->columns[0], iq).second;
418  if (val == GeometryInterface::UNDEFINED) break;
419  mei.range_y_min = std::min(mei.range_y_min, val);
420  mei.range_y_max = std::max(mei.range_y_max, val);
421  break;
422  default: // ignore the rest, code above will catch bugs
423  break;
424  }
425  }
426  }
427 
428  // Now do the actual booking.
429  for (auto& e : toBeBooked) {
430  AbstractHistogram& h = t[e.first];
431  MEInfo& mei = e.second;
432  auto name = makePathName(s, e.first, &(*laststep));
433  iBooker.setCurrentFolder(name.first);
434 
435  // determine nbins for geometry derived quantities
436  // due to how we counted above, we need to include lower and upper bound
437  // For Coord-values, which are not precisely aligned with the bins, we force
438  // alignment.
439  if (mei.binwidth_x != 0) {
440  double range = (mei.range_x_max - mei.range_x_min)/mei.binwidth_x;
441  if ((range - int(range)) == 0.0) {
442  mei.range_x_min -= mei.binwidth_x/2;
443  mei.range_x_max += mei.binwidth_x/2;
444  } else {
445  mei.range_x_min = std::floor(mei.range_x_min/mei.binwidth_x)*mei.binwidth_x;
446  mei.range_x_max = std::ceil(mei.range_x_max/mei.binwidth_x)*mei.binwidth_x;
447  }
448  mei.range_x_nbins = int((mei.range_x_max - mei.range_x_min)/mei.binwidth_x);
449  }
450  if (mei.binwidth_y != 0) {
451  double range = (mei.range_y_max - mei.range_y_min)/mei.binwidth_y;
452  if ((range - int(range)) == 0.0) {
453  mei.range_y_min -= mei.binwidth_y/2;
454  mei.range_y_max += mei.binwidth_y/2;
455  } else {
456  mei.range_y_min = std::floor(mei.range_y_min/mei.binwidth_y)*mei.binwidth_y;
457  mei.range_y_max = std::ceil(mei.range_y_max/mei.binwidth_y)*mei.binwidth_y;
458  }
459  mei.range_y_nbins = int((mei.range_y_max - mei.range_y_min)/mei.binwidth_y);
460  }
461 
462  if (mei.dimensions == 1) {
463  h.me = iBooker.book1D(name.second, (mei.title + ";" + mei.xlabel).c_str(),
464  mei.range_x_nbins, mei.range_x_min, mei.range_x_max);
465  } else if (mei.dimensions == 2 && !mei.do_profile) {
466  h.me = iBooker.book2D(name.second, (mei.title + ";" + mei.xlabel + ";" + mei.ylabel).c_str(),
467  mei.range_x_nbins, mei.range_x_min, mei.range_x_max,
468  mei.range_y_nbins, mei.range_y_min, mei.range_y_max);
469  } else if (mei.dimensions == 2 && mei.do_profile) {
470  h.me = iBooker.bookProfile(name.second, (mei.title + ";" + mei.xlabel + ";" + mei.ylabel).c_str(),
471  mei.range_x_nbins, mei.range_x_min, mei.range_x_max, 0.0, 0.0, "");
472  } else if (mei.dimensions == 3 && mei.do_profile) {
473  h.me = iBooker.bookProfile2D(name.second, (mei.title + ";" + mei.xlabel + ";" + mei.ylabel).c_str(),
474  mei.range_x_nbins, mei.range_x_min, mei.range_x_max,
475  mei.range_y_nbins, mei.range_y_min, mei.range_y_max,
476  0.0, 0.0); // Z range is ignored if min==max
477  } else {
478  edm::LogError("HistogramManager") << "Illegal Histogram!\n"
479  << "name " << name.second << "\n"
480  << "dim " << mei.dimensions << " profile " << mei.do_profile << "\n";
481  assert(!"Illegal Histogram kind.");
482  }
483  h.th1 = h.me->getTH1();
484  }
485  }
486 }
487 
488 
489 
491  DQMStore::IGetter& iGetter,
492  edm::LuminosityBlock const& lumiBlock,
493  edm::EventSetup const& iSetup) {
494  if (!enabled) return;
495  // this should also give us the GeometryInterface for offline, though it is a
496  // bit dirty and might explode.
497  if (!geometryInterface.loaded()) {
498  geometryInterface.load(iSetup);
499  }
500  if (perLumiHarvesting) {
501  this->lumisection = &lumiBlock; // "custom" steps can use this
502  executeHarvesting(iBooker, iGetter);
503  this->lumisection = nullptr;
504  }
505 }
506 
508  DQMStore::IGetter& iGetter) {
509  t.clear();
511  auto firststep = s.steps.begin();
512  if (firststep->type != SummationStep::GROUPBY) ++firststep;
513  auto laststep = std::find_if(s.steps.begin(), s.steps.end(),
514  [](SummationStep const& step) { return step.stage == SummationStep::STAGE2; });
515 
516  for (auto iq : geometryInterface.allModules()) {
517 
518  geometryInterface.extractColumns(firststep->columns, iq,
519  significantvalues);
520 
521  auto histo = t.find(significantvalues);
522  if (histo == t.end()) {
523  auto name = makePathName(s, significantvalues, &(*laststep));
524  std::string path = name.first + name.second;
525  MonitorElement* me = iGetter.get(path);
526  if (!me) {
527  if (bookUndefined)
528  edm::LogError("HistogramManager") << "ME " << path << " not found\n";
529  // else this will happen quite often
530  } else {
532  histo.me = me;
533  histo.th1 = histo.me->getTH1();
534  histo.iq_sample = iq;
535  }
536  }
537  }
538 }
539 
541  DQMStore::IBooker& iBooker, SummationSpecification const& s) {
542  // Simple regrouping, sum histos if they end up in the same place.
543  Table out;
545  for (auto& e : t) {
546  TH1* th1 = e.second.th1;
547  geometryInterface.extractColumns(step.columns, e.second.iq_sample,
548  significantvalues);
549  AbstractHistogram& new_histo = out[significantvalues];
550  if (!new_histo.me) {
551  auto name = makePathName(s, significantvalues, &step);
552  iBooker.setCurrentFolder(name.first);
553  if (dynamic_cast<TH1F*>(th1)) new_histo.me = iBooker.book1D(name.second, (TH1F*) th1);
554  else if (dynamic_cast<TH2F*>(th1)) new_histo.me = iBooker.book2D(name.second, (TH2F*) th1);
555  else if (dynamic_cast<TProfile*>(th1)) new_histo.me = iBooker.bookProfile(name.second, (TProfile*) th1);
556  else if (dynamic_cast<TProfile2D*>(th1)) new_histo.me = iBooker.bookProfile2D(name.second, (TProfile2D*) th1);
557  else assert(!"No idea how to book this.");
558  new_histo.th1 = new_histo.me->getTH1();
559  new_histo.iq_sample = e.second.iq_sample;
560  } else {
561  new_histo.th1->Add(th1);
562  }
563  }
564  t.swap(out);
565 }
566 
568  std::string const& reduce_type, DQMStore::IBooker& iBooker, SummationSpecification const& s) {
569  // For the moment only X.
570  // first pass determines the range.
571  std::map<GeometryInterface::Values, int> nbins;
572  // separators collects meta info for the render plugin about the boundaries.
573  // for each EXTEND, this is added to the axis label. In total this is not
574  // fully correct since we have to assume the the substructure of each sub-
575  // histogram is the same, which is e.g. not true for layers. It still works
576  // since layers only contain leaves (ladders).
577  std::map<GeometryInterface::Values, std::string> separators;
578 
580 
581  for (auto& e : t) {
582  geometryInterface.extractColumns(step.columns, e.second.iq_sample,
583  significantvalues);
584  int& n = nbins[significantvalues];
585  assert(e.second.th1 || !"invalid histogram");
586  // if we reduce, every histogram only needs one bin
587  int bins = reduce_type != "" ? 1 : e.second.th1->GetXaxis()->GetNbins();
588  if (bins > 1) separators[significantvalues] += std::to_string(n) + ",";
589  n += bins;
590  }
591  for (auto& e : separators) e.second = "(" + e.second + ")/";
592 
593  Table out;
594  for (auto& e : t) {
595  geometryInterface.extractColumns(step.columns, e.second.iq_sample,
596  significantvalues);
597  TH1* th1 = e.second.th1;
598  assert(th1);
599 
600  AbstractHistogram& new_histo = out[significantvalues];
601  if (!new_histo.me) {
602  // we put the name of the actual, last column of a input histo there.
603  std::string colname = geometryInterface.pretty((e.first.end()-1)->first);
604 
605  auto separator = separators[significantvalues];
606 
607  auto name = makePathName(s, significantvalues, &step);
608  auto title = std::string("") + th1->GetTitle() + " per " + colname + ";" +
609  colname + separator +
610  (reduce_type != "" ? th1->GetYaxis()->GetTitle() : th1->GetXaxis()->GetTitle()) + ";" +
611  (reduce_type != "" ? reduce_type + " of " + th1->GetXaxis()->GetTitle() : th1->GetYaxis()->GetTitle());
612  iBooker.setCurrentFolder(name.first);
613 
614  if (th1->GetDimension() == 1) {
615  new_histo.me = iBooker.book1D(name.second, title,
616  nbins[significantvalues], 0.5, nbins[significantvalues] + 0.5);
617  } else {
618  assert(!"2D extend not implemented in harvesting.");
619  }
620  new_histo.th1 = new_histo.me->getTH1();
621  new_histo.iq_sample = e.second.iq_sample;
622  new_histo.count = 1; // used as a fill pointer. Assumes histograms are
623  // ordered correctly (map should provide that)
624  }
625 
626  // now add data.
627  if (new_histo.th1->GetDimension() == 1) {
628  if (reduce_type == "") { // no reduction, concatenate
629  for (int i = 1; i <= th1->GetXaxis()->GetNbins(); i++) {
630  new_histo.th1->SetBinContent(new_histo.count, th1->GetBinContent(i));
631  new_histo.th1->SetBinError(new_histo.count, th1->GetBinError(i));
632  new_histo.count += 1;
633  }
634  } else if (reduce_type == "MEAN") {
635  new_histo.th1->SetBinContent(new_histo.count, th1->GetMean());
636  new_histo.th1->SetBinError(new_histo.count, th1->GetMeanError());
637  new_histo.count += 1;
638  } else {
639  assert(!"Reduction type not supported");
640  }
641  } else {
642  assert(!"2D extend not implemented in harvesting.");
643  }
644  }
645  t.swap(out);
646 }
647 
649  DQMStore::IGetter& iGetter) {
650  if (!enabled) return;
651  // Debug output
652  for (auto& s : specs) {
653  edm::LogInfo log("HistogramManager");
654  log << "Specs for " << name << " ";
655  s.dump(log, geometryInterface);
656  }
657 
658  for (unsigned int i = 0; i < specs.size(); i++) {
659  auto& s = specs[i];
660  auto& t = tables[i];
661  loadFromDQMStore(s, t, iGetter);
662 
663  std::string reduce_type = "";
664 
665  // now execute step2.
666  for (SummationStep const& step : s.steps) {
667  if (step.stage == SummationStep::STAGE2) {
668  switch (step.type) {
669  case SummationStep::SAVE:
670  // no explicit implementation atm.
671  break;
673  executeGroupBy(step, t, iBooker, s);
674  break;
676  // reduction is done in the following EXTEND
677  reduce_type = step.arg;
678  break;
680  executeExtend(step, t, reduce_type, iBooker, s);
681  reduce_type = "";
682  break;
684  assert(!"EXTEND_Y currently not supported in harvesting.");
685  break;
686  default:
687  assert(!"Operation not supported in harvesting.");
688  }
689  }
690  }
691  }
692 }
void executeHarvesting(DQMStore::IBooker &iBooker, DQMStore::IGetter &iGetter)
T getParameter(std::string const &) const
string separator
Definition: mps_merge.py:79
MonitorElement * me
GeometryInterface::InterestingQuantities iq_sample
void addSpec(SummationSpecification spec)
FWCore Framework interface EventSetupRecordImplementation h
Helper function to determine trigger accepts.
MonitorElement * bookProfile(Args &&...args)
Definition: DQMStore.h:113
std::vector< GeometryInterface::Column > columns
void executePerLumiHarvesting(DQMStore::IBooker &iBooker, DQMStore::IGetter &iGetter, edm::LuminosityBlock const &lumiBlock, edm::EventSetup const &iSetup)
std::vector< ParameterSet > VParameterSet
Definition: ParameterSet.h:33
std::string pretty(Column col)
void executeGroupBy(SummationStep const &step, Table &t, DQMStore::IBooker &iBooker, SummationSpecification const &s)
TH1 * getTH1() const
std::string formatValue(Column, Value)
std::vector< SummationSpecification > specs
Value binWidth(ID id)
std::pair< std::string, std::string > makePathName(SummationSpecification const &s, GeometryInterface::Values const &, SummationStep const *upto)
std::vector< SummationStep > steps
std::string top_folder_name
void fill(DetId sourceModule, const edm::Event *sourceEvent=0, int col=0, int row=0)
void Fill(long long x)
void fillInternal(double x, double y, int n_parameters, GeometryInterface::InterestingQuantities const &iq, std::vector< SummationStep >::iterator first, std::vector< SummationStep >::iterator last, AbstractHistogram &dest)
std::string xlabel
Value maxValue(ID id)
void executeExtend(SummationStep const &step, Table &t, std::string const &reduction, DQMStore::IBooker &iBooker, SummationSpecification const &s)
void setCurrentFolder(std::string const &fullpath)
Definition: DQMStore.cc:268
void loadFromDQMStore(SummationSpecification &s, Table &t, DQMStore::IGetter &iGetter)
void load(edm::EventSetup const &iSetup)
void extractColumns(std::vector< Column > const &names, InterestingQuantities const &iq, Values &out)
MonitorElement * bookProfile2D(Args &&...args)
Definition: DQMStore.h:114
MonitorElement * book1D(Args &&...args)
Definition: DQMStore.h:106
T min(T a, T b)
Definition: MathUtil.h:58
static const Value UNDEFINED
std::string ylabel
std::vector< std::pair< Column, Value > > Values
MonitorElement * get(std::string const &path)
Definition: DQMStore.cc:303
Definition: DetId.h:18
std::vector< AbstractHistogram * > fastpath
std::vector< GeometryInterface::Values > significantvalues
MonitorElement * book2D(Args &&...args)
Definition: DQMStore.h:109
xlabel
Definition: compare.py:29
std::map< GeometryInterface::Values, AbstractHistogram > Table
HistogramManager(const edm::ParameterSet &iConfig, GeometryInterface &geo)
std::vector< Table > tables
edm::LuminosityBlock const * lumisection
Value minValue(ID id)
std::pair< Column, Value > extract(Column const &col, InterestingQuantities const &iq)
col
Definition: cuy.py:1010
std::vector< Table > counters
std::vector< InterestingQuantities > const & allModules()
step
Definition: StallMonitor.cc:94
dbl *** dir
Definition: mlp_gen.cc:35
void executePerEventHarvesting(edm::Event const *ev)
void book(DQMStore::IBooker &iBooker, edm::EventSetup const &iSetup)
GeometryInterface::InterestingQuantities iq
#define SET_AXIS(to, from)
GeometryInterface & geometryInterface