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