CMS 3D CMS Logo

ConfigurableHisto.h
Go to the documentation of this file.
1 #ifndef ConfigurableAnalysis_ConfigurableHisto_H
2 #define ConfigurableAnalysis_ConfigurableHisto_H
3 
6 
7 #include "TH1.h"
8 #include "TH1F.h"
9 #include "TH2F.h"
10 #include "TProfile.h"
11 #include "THStack.h"
12 
15 
17 public:
19  ConfigurableAxis(const edm::ParameterSet& par) : nBin_(0), Min_(0), Max_(0), Label_("") {
20  Label_ = par.getParameter<std::string>("Label");
21 
22  if (par.exists("nBins")) {
23  nBin_ = par.getParameter<unsigned int>("nBins");
24  Min_ = par.getParameter<double>("Min");
25  Max_ = par.getParameter<double>("Max");
26  } else {
27  if (par.exists("vBins"))
28  vBins_ = par.getParameter<std::vector<double> >("vBins");
29  else {
30  Min_ = par.getParameter<double>("Min");
31  Max_ = par.getParameter<double>("Max");
32  }
33  }
34  }
35  bool variableSize() { return !vBins_.empty(); }
36  unsigned int nBin() {
37  if (variableSize())
38  return vBins_.size() - 1;
39  else
40  return nBin_;
41  }
42  double Min() {
43  if (variableSize())
44  return vBins_.front();
45  else
46  return Min_;
47  }
48  double Max() {
49  if (variableSize())
50  return vBins_.back();
51  else
52  return Max_;
53  }
54  const std::string& Label() { return Label_; }
55  const double* xBins() {
56  if (!vBins_.empty())
57  return &(vBins_.front());
58  else
59  return nullptr;
60  }
61 
62 private:
63  std::vector<double> vBins_;
64  unsigned int nBin_;
65  double Min_;
66  double Max_;
68 };
69 
71 public:
72  enum HType { h1, h2, prof };
74  : type_(t), h_(nullptr), name_(name), conf_(iConfig), x_(nullptr), y_(nullptr), z_(nullptr), w_(nullptr) {}
75 
76  virtual ~ConfigurableHisto() {}
77 
78  virtual ConfigurableHisto* clone() const { return new ConfigurableHisto(*this); }
79 
80  virtual void book(TFileDirectory* dir) {
83  ConfigurableAxis xAxis(xAxisPSet);
84  x_ = edm::Service<VariableHelperService>()->get().variable(xAxisPSet.getParameter<std::string>("var"));
85 
86  std::string yLabel = "";
87  bool yVBin = false;
89  if (conf_.exists("yAxis")) {
91  yAxis = ConfigurableAxis(yAxisPSet);
92  yLabel = yAxis.Label();
93  //at least TH2 or TProfile
94  if (yAxisPSet.exists("var"))
95  y_ = edm::Service<VariableHelperService>()->get().variable(yAxisPSet.getParameter<std::string>("var"));
96  yVBin = yAxis.variableSize();
97  }
98 
99  if (conf_.exists("zAxis")) {
100  throw;
101  }
102 
103  bool xVBin = xAxis.variableSize();
104 
105  if (type() == h1) {
106  //make TH1F
107  if (xVBin)
108  h_ = dir->make<TH1F>(name_.c_str(), title.c_str(), xAxis.nBin(), xAxis.xBins());
109  else
110  h_ = dir->make<TH1F>(name_.c_str(), title.c_str(), xAxis.nBin(), xAxis.Min(), xAxis.Max());
111  } else if (type() == h2) {
112  //make TH2F
113  if (xVBin) {
114  if (yVBin)
115  h_ = dir->make<TH2F>(name_.c_str(), title.c_str(), xAxis.nBin(), xAxis.xBins(), yAxis.nBin(), yAxis.xBins());
116  else
117  h_ = dir->make<TH2F>(
118  name_.c_str(), title.c_str(), xAxis.nBin(), xAxis.xBins(), yAxis.nBin(), yAxis.Min(), yAxis.Max());
119  } else {
120  if (yVBin)
121  h_ = dir->make<TH2F>(
122  name_.c_str(), title.c_str(), xAxis.nBin(), xAxis.Min(), xAxis.Max(), yAxis.nBin(), yAxis.xBins());
123  else
124  h_ = dir->make<TH2F>(name_.c_str(),
125  title.c_str(),
126  xAxis.nBin(),
127  xAxis.Min(),
128  xAxis.Max(),
129  yAxis.nBin(),
130  yAxis.Min(),
131  yAxis.Max());
132  }
133  } else if (type() == prof) {
134  //make TProfile
135  std::string pFopt = "";
136  if (conf_.exists("Option"))
137  pFopt = conf_.getParameter<std::string>("Option");
138 
139  if (xVBin)
140  h_ = dir->make<TProfile>(
141  name_.c_str(), title.c_str(), xAxis.nBin(), xAxis.xBins(), yAxis.Min(), yAxis.Max(), pFopt.c_str());
142  else
143  h_ = dir->make<TProfile>(name_.c_str(),
144  title.c_str(),
145  xAxis.nBin(),
146  xAxis.Min(),
147  xAxis.Max(),
148  yAxis.Min(),
149  yAxis.Max(),
150  pFopt.c_str());
151 
152  } else {
153  edm::LogError("ConfigurableHisto") << "cannot book: " << name_ << "\n" << conf_.dump();
154  throw;
155  }
156 
157  //cosmetics
158  h_->GetXaxis()->SetTitle(xAxis.Label().c_str());
159  h_->SetYTitle(yLabel.c_str());
160 
161  if (conf_.exists("weight")) {
162  w_ = edm::Service<VariableHelperService>()->get().variable(conf_.getParameter<std::string>("weight"));
163  }
164  }
165 
166  virtual void fill(const edm::Event& iEvent) {
167  if (!h_)
168  return;
169 
170  double weight = 1.0;
171  if (w_) {
172  if (w_->compute(iEvent))
173  weight = (*w_)(iEvent);
174  else {
175  edm::LogInfo("ConfigurableHisto") << "could not compute the weight for: " << name_ << " with config:\n"
176  << conf_.dump() << " default to 1.0";
177  }
178  }
179 
180  TProfile* pcast(nullptr);
181  TH2* h2cast(nullptr);
182  switch (type_) {
183  case h1:
184  if (!h_)
185  throw;
186  if (x_->compute(iEvent))
187  h_->Fill((*x_)(iEvent), weight);
188  else {
189  edm::LogInfo("ConfigurableHisto") << "could not fill: " << name_ << " with config:\n" << conf_.dump();
190  }
191  break;
192  case prof:
193  pcast = dynamic_cast<TProfile*>(h_);
194  if (!pcast)
195  throw;
196  if (x_->compute(iEvent) && y_->compute(iEvent))
197  pcast->Fill((*x_)(iEvent), (*y_)(iEvent), weight);
198  else {
199  edm::LogInfo("ConfigurableHisto") << "could not fill: " << name_ << " with config:\n" << conf_.dump();
200  }
201  break;
202  case h2:
203  h2cast = dynamic_cast<TH2*>(h_);
204  if (!h2cast)
205  throw;
206  if (x_->compute(iEvent) && y_->compute(iEvent))
207  h2cast->Fill((*x_)(iEvent), (*y_)(iEvent), weight);
208  else {
209  edm::LogInfo("ConfigurableHisto") << "could not fill: " << name_ << " with config:\n" << conf_.dump();
210  }
211  break;
212  }
213  }
214  const HType& type() { return type_; }
215 
216  void complete() {}
217  TH1* h() { return h_; }
218 
219 protected:
221  type_ = master.type_;
222  h_ = nullptr; //no histogram attached in copy constructor
223  name_ = master.name_;
224  conf_ = master.conf_;
225  x_ = master.x_;
226  y_ = master.y_;
227  z_ = master.z_;
228  w_ = master.w_;
229  }
231  TH1* h_;
234 
239 };
240 
242 public:
244  : ConfigurableHisto(t, name, pset), splitter_(nullptr) {
245  std::string title = pset.getParameter<std::string>("title");
246 
247  //allow for many splitters ...
248  if (pset.exists("splitters")) {
249  //you want more than one splitter
250  std::vector<std::string> splitters = pset.getParameter<std::vector<std::string> >("splitters");
251  for (unsigned int s = 0; s != splitters.size(); ++s) {
252  const CachingVariable* v = edm::Service<VariableHelperService>()->get().variable(splitters[s]);
253  const Splitter* splitter = dynamic_cast<const Splitter*>(v);
254  if (!splitter) {
255  edm::LogError("SplittingConfigurableHisto")
256  << "for: " << name_ << " the splitting variable: " << splitters[s] << " is not a Splitter";
257  continue;
258  }
259 
260  //insert in the map
261  std::vector<ConfigurableHisto*>& insertedHisto = subHistoMap_[splitter];
262  //now configure the histograms
263  unsigned int mSlots = splitter->maxSlots();
264  for (unsigned int i = 0; i != mSlots; ++i) {
265  //--- std::cout<<" slot: "<<i<<std::endl;
266  const std::string& slabel = splitter->shortLabel(i);
267  const std::string& label = splitter->label(i);
268  edm::ParameterSet mPset = pset;
269  edm::Entry e("string", title + " for " + label, true);
270  mPset.insert(true, "title", e);
271  insertedHisto.push_back(new ConfigurableHisto(t, name + slabel, mPset));
272  } //loop on slots
273  } //loop on splitters
274 
275  } //if splitters exists
276  else {
277  //single splitter
278  //get the splitting variable
279  const CachingVariable* v =
280  edm::Service<VariableHelperService>()->get().variable(pset.getParameter<std::string>("splitter"));
281  splitter_ = dynamic_cast<const Splitter*>(v);
282  if (!splitter_) {
283  edm::LogError("SplittingConfigurableHisto")
284  << "for: " << name_ << " the splitting variable: " << v->name() << " is not a Splitter";
285  } else {
286  //configure the splitted plots
287  unsigned int mSlots = splitter_->maxSlots();
288  for (unsigned int i = 0; i != mSlots; i++) {
289  const std::string& slabel = splitter_->shortLabel(i);
290  const std::string& label = splitter_->label(i);
291  edm::ParameterSet mPset = pset;
292  edm::Entry e("string", title + " for " + label, true);
293  mPset.insert(true, "title", e);
294  subHistos_.push_back(new ConfigurableHisto(t, name + slabel, mPset));
295  }
296  }
297  }
298  } //end of ctor
299 
300  void book(TFileDirectory* dir) override {
301  //book the base histogram
303 
304  if (!subHistoMap_.empty()) {
305  SubHistoMap::iterator i = subHistoMap_.begin();
306  SubHistoMap::iterator i_end = subHistoMap_.end();
307  for (; i != i_end; ++i) {
308  for (unsigned int h = 0; h != i->second.size(); ++h) {
309  i->second[h]->book(dir);
310  }
311  //book the THStack
312  std::string sName = name_ + "_" + i->first->name();
313  std::string sTitle = "Stack histogram of " + name_ + " for splitter " + i->first->name();
314  subHistoStacks_[i->first] = dir->make<THStack>(sName.c_str(), sTitle.c_str());
315  }
316  } else {
317  for (unsigned int h = 0; h != subHistos_.size(); h++) {
318  subHistos_[h]->book(dir);
319  }
320  //book a THStack
321  std::string sName = name_ + "_" + splitter_->name();
322  std::string sTitle = "Stack histogram of " + name_ + " for splitter " + splitter_->name();
323  stack_ = dir->make<THStack>(sName.c_str(), sTitle.c_str());
324  }
325  }
326 
327  ConfigurableHisto* clone() const override { return new SplittingConfigurableHisto(*this); }
328 
329  void fill(const edm::Event& e) override {
330  //fill the base histogram
332 
333  if (!subHistoMap_.empty()) {
334  SubHistoMap::iterator i = subHistoMap_.begin();
335  SubHistoMap::iterator i_end = subHistoMap_.end();
336  for (; i != i_end; ++i) {
337  const Splitter* splitter = i->first;
338  if (!splitter)
339  continue;
340  if (!splitter->compute(e))
341  continue;
342  unsigned int slot = (unsigned int)(*splitter)(e);
343  if (slot >= i->second.size()) {
344  edm::LogError("SplittingConfigurableHisto")
345  << "slot index: " << slot << " is bigger than slots size: " << i->second.size()
346  << " from variable value: " << (*splitter)(e);
347  continue;
348  }
349  //fill in the proper slot
350  i->second[slot]->fill(e);
351  }
352  } else {
353  //fill the component histograms
354  if (!splitter_)
355  return;
356  if (!splitter_->compute(e)) {
357  return;
358  }
359  unsigned int slot = (unsigned int)(*splitter_)(e);
360  if (slot >= subHistos_.size()) {
361  edm::LogError("SplittingConfigurableHisto")
362  << "slot index: " << slot << " is bigger than slots size: " << subHistos_.size()
363  << " from variable value: " << (*splitter_)(e);
364  return;
365  }
366  subHistos_[slot]->fill(e);
367  }
368  }
369 
370  void complete() {
371  if (!subHistoMap_.empty()) {
372  //fill up the stacks
373  SubHistoMap::iterator i = subHistoMap_.begin();
374  SubHistoMap::iterator i_end = subHistoMap_.end();
375  for (; i != i_end; ++i) {
376  for (unsigned int h = 0; h != i->second.size(); h++) {
377  // if (i->second[h]->h()->Integral==0) continue;// do not add empty histograms. NO, because it will be tough to merge two THStack
378  subHistoStacks_[i->first]->Add(i->second[h]->h(), i->first->label(h).c_str());
379  }
380  }
381 
382  } else {
383  //fill up the only stack
384  for (unsigned int i = 0; i != subHistos_.size(); i++) {
385  stack_->Add(subHistos_[i]->h(), splitter_->label(i).c_str());
386  }
387  }
388  }
389 
390 private:
392  splitter_ = master.splitter_;
393  if (!master.subHistoMap_.empty()) {
394  SubHistoMap::const_iterator i = master.subHistoMap_.begin();
395  SubHistoMap::const_iterator i_end = master.subHistoMap_.end();
396  for (; i != i_end; ++i) {
397  const std::vector<ConfigurableHisto*>& masterHistos = i->second;
398  std::vector<ConfigurableHisto*>& clonedHistos = subHistoMap_[i->first];
399  for (unsigned int i = 0; i != masterHistos.size(); i++) {
400  clonedHistos.push_back(masterHistos[i]->clone());
401  }
402  }
403  } else {
404  for (unsigned int i = 0; i != master.subHistos_.size(); i++) {
405  subHistos_.push_back(master.subHistos_[i]->clone());
406  }
407  }
408  }
409 
410  typedef std::map<const Splitter*, std::vector<ConfigurableHisto*> > SubHistoMap;
411  typedef std::map<const Splitter*, THStack*> SubHistoStacks;
414 
416  std::vector<ConfigurableHisto*> subHistos_;
417  // do you want to have a stack already made from the splitted histos?
418  THStack* stack_;
419 };
420 
421 #endif
def splitter(iterator, n)
Definition: confdb.py:11
const HType & type()
T getParameter(std::string const &) const
Definition: ParameterSet.h:307
const std::string shortLabel(unsigned int i) const
void book(TFileDirectory *dir) override
std::vector< double > vBins_
bool exists(std::string const &parameterName) const
checks if a parameter exists
SplittingConfigurableHisto(const SplittingConfigurableHisto &master)
void fill(const edm::Event &e) override
const std::string & Label()
unsigned int nBin_
Definition: weight.py:1
void insert(bool ok_to_replace, char const *, Entry const &)
virtual ConfigurableHisto * clone() const
Log< level::Error, false > LogError
SplittingConfigurableHisto(HType t, std::string name, edm::ParameterSet &pset)
std::vector< ConfigurableHisto * > subHistos_
char const * label
virtual void fill(const edm::Event &iEvent)
ConfigurableHisto(HType t, std::string name, edm::ParameterSet &iConfig)
const CachingVariable * y_
int iEvent
Definition: GenABIO.cc:224
const std::string & label(unsigned int i) const
virtual ~ConfigurableHisto()
ConfigurableHisto(const ConfigurableHisto &master)
unsigned int nBin()
const CachingVariable * x_
Log< level::Info, false > LogInfo
virtual void book(TFileDirectory *dir)
const CachingVariable * w_
const double * xBins()
std::map< const Splitter *, THStack * > SubHistoStacks
ConfigurableHisto * clone() const override
std::string dump(unsigned int indent=0) const
bool compute(const edm::Event &iEvent) const
edm::ParameterSet conf_
const CachingVariable * z_
const std::string & name() const
virtual unsigned int maxSlots() const
std::map< const Splitter *, std::vector< ConfigurableHisto * > > SubHistoMap
ConfigurableAxis(const edm::ParameterSet &par)