TTTT Analysis  0.1
container.hpp
1 #ifndef root_container_hpp
2 #define root_container_hpp
3 #include <iostream>
4 #include <utility>
5 #include <map>
6 
7 #include "TROOT.h"
8 #include "TFile.h"
9 #include "TCanvas.h"
10 #include "TGraph.h"
11 #include "TH1.h"
12 #include "TH2.h"
13 
14 #include "TMVA/Factory.h"
15 #include "TMVA/DataLoader.h"
16 #include "TMVA/DataSetInfo.h"
17 
18 #include "filval/container.hpp"
19 
20 namespace fv::root::util{
26  void save_as(TObject* container, const std::string& fname, const SaveOption& option = SaveOption::PNG) {
27 
28  auto save_img = [](TObject* container, const std::string& fname){
29  TCanvas* c1 = new TCanvas("c1");
30  container->Draw();
31  c1->Draw();
32  c1->SaveAs(fname.c_str());
33  delete c1;
34  };
35 
36  auto save_bin = [](TObject* container){
37  INFO("Saving object: " << container->GetName() << " into file " << gDirectory->GetName());
38  container->Write(container->GetName(), TObject::kOverwrite);
39  };
40 
41  switch(option){
42  case PNG:
43  save_img(container, fname+".png"); break;
44  case PDF:
45  save_img(container, fname+".pdf"); break;
46  case ROOT:
47  save_bin(container); break;
48  default:
49  break;
50  }
51  }
52 
53 
65  void save_as_stl(void* container, const std::string& type_name,
66  const std::string& obj_name,
67  const SaveOption& option = SaveOption::PNG) {
68  switch(option){
69  case PNG:
70  INFO("Cannot save STL container " << type_name <<" as png");
71  break;
72  case PDF:
73  INFO("Cannot save STL container " << type_name <<" as pdf");
74  break;
75  case ROOT:
76  /* DEBUG("Writing object \"" << obj_name << "\" of type \"" << type_name << "\"\n"); */
77  gDirectory->WriteObjectAny(container, type_name.c_str(), obj_name.c_str());
78  break;
79  default:
80  break;
81  }
82  }
83 }
84 
85 namespace fv::root {
86 
87 template <typename V>
88 class _ContainerTH1 : public Container<TH1,V>{
89  private:
90  void _fill(){
91  if (this->container == nullptr){
92  if (this->value == nullptr){
93  CRITICAL("Container: \"" << this->get_name() << "\" has a null Value object. "
94  << "Probably built with imcompatible type",-1);
95  }
96  this->container = new TH1D(this->get_name().c_str(), this->title.c_str(),
97  this->nbins, this->low, this->high);
98  this->container->SetXTitle(label_x.c_str());
99  this->container->SetYTitle(label_y.c_str());
100  }
101  _do_fill();
102  }
103 
104  protected:
105  std::string title;
106  std::string label_x;
107  std::string label_y;
108  int nbins;
109  double low;
110  double high;
111 
112  virtual void _do_fill() = 0;
113 
114  public:
115  explicit _ContainerTH1(const std::string &name, const std::string& title, Value<V>* value,
116  int nbins, double low, double high,
117  const std::string& label_x = "",
118  const std::string& label_y = "")
119  :Container<TH1,V>(name, value),
120  title(title), nbins(nbins), low(low), high(high),
121  label_x(label_x), label_y(label_y) { }
122 
123  void save_as(const std::string& fname, const SaveOption& option = SaveOption::PNG) {
124  util::save_as(this->get_container(), fname, option);
125  }
126 };
127 
128 template <typename V>
129 class ContainerTH1 : public _ContainerTH1<V>{
130  using _ContainerTH1<V>::_ContainerTH1;
131  void _do_fill(){
132  this->container->Fill(this->value->get_value());
133  }
134  public:
135  GenContainer* clone_as(const std::string& new_name){
136  return new ContainerTH1<V>(new_name, this->title, this->value, this->nbins, this->low, this->high, this->label_x, this->label_y);
137  }
138 };
139 
140 template <typename V>
141 class ContainerTH1Many : public _ContainerTH1<std::vector<V>>{
142  using _ContainerTH1<std::vector<V>>::_ContainerTH1;
143  void _do_fill(){
144  for(V x : this->value->get_value())
145  this->container->Fill(x);
146  }
147  public:
148  GenContainer* clone_as(const std::string& new_name){
149  return new ContainerTH1Many<V>(new_name, this->title, this->value, this->nbins, this->low, this->high, this->label_x, this->label_y);
150  }
151 };
152 
153 
154 
155 template <typename V>
156 class _ContainerTH2 : public Container<TH2,std::pair<V,V>>{
157  private:
158  void _fill(){
159  if (this->container == nullptr){
160  if (this->value == nullptr){
161  CRITICAL("Container: \"" << this->get_name() << "\" has a null Value object. "
162  << "Probably built with imcompatible type",-1);
163  }
164  this->container = new TH2D(this->get_name().c_str(), this->title.c_str(),
165  this->nbins_x, this->low_x, this->high_x,
166  this->nbins_y, this->low_y, this->high_y);
167  this->container->SetXTitle(label_x.c_str());
168  this->container->SetYTitle(label_y.c_str());
169  }
170  _do_fill(this->value->get_value());
171  }
172 
173  protected:
174  std::string title;
175  std::string label_x;
176  std::string label_y;
177  int nbins_x;
178  int nbins_y;
179  double low_x;
180  double low_y;
181  double high_x;
182  double high_y;
183 
184  virtual void _do_fill(std::pair<V,V>& val) = 0;
185 
186  public:
187  explicit _ContainerTH2(const std::string& name, const std::string& title,
188  Value<std::pair<V, V>>* value,
189  int nbins_x, double low_x, double high_x,
190  int nbins_y, double low_y, double high_y,
191  const std::string& label_x = "",
192  const std::string& label_y = "")
193  :Container<TH2,std::pair<V,V>>(name, value),
194  title(title),
195  nbins_x(nbins_x), low_x(low_x), high_x(high_x),
196  nbins_y(nbins_y), low_y(low_y), high_y(high_y),
197  label_x(label_x), label_y(label_y) { }
198 
199  void save_as(const std::string& fname, const SaveOption& option = SaveOption::PNG) {
200  util::save_as(this->get_container(), fname, option);
201  }
202 };
203 
204 template <typename V>
205 class ContainerTH2 : public _ContainerTH2<V>{
206  using _ContainerTH2<V>::_ContainerTH2;
207  void _do_fill(std::pair<V,V>& val){
208  this->container->Fill(val.first,val.second);
209  }
210  public:
211  GenContainer* clone_as(const std::string& new_name){
212  return new ContainerTH2<V>(new_name, this->title, this->value, this->nbins_x, this->low_x, this->high_x,
213  this->nbins_y, this->low_y, this->high_y, this->label_x, this->label_y);
214  }
215 };
216 
217 template <typename V>
218 class ContainerTH2Many : public _ContainerTH2<std::vector<V>>{
219  using _ContainerTH2<std::vector<V>>::_ContainerTH2;
220  void _do_fill(std::pair<std::vector<V>,std::vector<V>>& val){
221  int min_size = std::min(val.first.size(), val.second.size());
222  for(int i=0; i<min_size; i++)
223  this->container->Fill(val.first[i],val.second[i]);
224  }
225  public:
226  GenContainer* clone_as(const std::string& new_name){
227  return new ContainerTH2Many<V>(new_name, this->title, this->value, this->nbins_x, this->low_x, this->high_x,
228  this->nbins_y, this->low_y, this->high_y, this->label_x, this->label_y);
229  }
230 };
231 
232 template <typename V>
233 class ContainerTGraph : public Container<TGraph,std::pair<V,V>>{
234  private:
235  std::vector<V> x_data;
236  std::vector<V> y_data;
237  std::string title;
238  bool data_modified;
239  void _fill(){
240  auto val = this->value->get_value();
241  x_data.push_back(val.first);
242  y_data.push_back(val.second);
243  data_modified = true;
244  }
245  public:
246  ContainerTGraph(const std::string& name, const std::string& title, Value<std::pair<V, V>>* value)
247  :Container<TGraph,std::pair<V,V>>(name, value),
248  data_modified(false){
249  this->container = new TGraph();
250  }
251 
252  TGraph* get_container(){
253  if (data_modified){
254  delete this->container;
255  this->container = new TGraph(x_data.size(), x_data.data(), y_data.data());
256  this->container->SetName(this->get_name().c_str());
257  this->container->SetTitle(title.c_str());
258  data_modified = false;
259  }
260  return this->container;
261  }
262 
263  GenContainer* clone_as(const std::string& new_name){
264  return new ContainerTGraph<V>(new_name, this->title, this->value);
265  }
266 
267  void save_as(const std::string& fname, const SaveOption& option = SaveOption::PNG) {
268  util::save_as(get_container(), fname, option);
269  }
270 };
271 
272 template <typename V>
273 class Vector : public Container<std::vector<V>,V>{
274  private:
275 
276  void _fill(){
277  this->container->push_back(this->value->get_value());
278  }
279  public:
280  Vector(const std::string& name, Value<V>* value)
281  :Container<std::vector<V>,V>(name, value){
282  this->container = new std::vector<V>;
283  }
284 
285  GenContainer* clone_as(const std::string& new_name){
286  return new Vector<V>(new_name, this->value);
287  }
288 
289  void save_as(const std::string& fname, const SaveOption& option = SaveOption::PNG) {
290  std::string type_name = "std::vector<"+fv::util::get_type_name(typeid(V))+">";
291  util::save_as_stl(this->get_container(), type_name, this->get_name(), option);
292  }
293 };
294 
295 template <typename V, typename D>
296 class _Counter : public Container<std::map<D,int>,V>{
297  public:
298  explicit _Counter(const std::string& name, Value<V>* value)
299  :Container<std::map<D,int>,V>(name, value) {
300  this->container = new std::map<D,int>;
301  }
302 
303  void save_as(const std::string& fname, const SaveOption& option = SaveOption::PNG) {
304  std::string type_name = "std::map<"+fv::util::get_type_name(typeid(D))+",int>";
305  util::save_as_stl(this->get_container(), type_name, this->get_name(), option);
306  }
307 };
308 
309 
314 template <typename V>
315 class Counter : public _Counter<V,V>{
316  using _Counter<V,V>::_Counter;
317  void _fill(){
318  (*this->container)[this->value->get_value()]++;
319  }
320  public:
321  GenContainer* clone_as(const std::string& new_name){
322  return new Counter<V>(new_name, this->value);
323  }
324 };
325 
329 template <typename V>
330 class CounterMany : public _Counter<std::vector<V>,V>{
331  using _Counter<std::vector<V>,V>::_Counter;
332  void _fill(){
333  for(V& val : this->value->get_value())
334  (*this->container)[val]++;
335  }
336  public:
337  GenContainer* clone_as(const std::string& new_name){
338  return new CounterMany<V>(new_name, this->value);
339  }
340 };
341 
342 class PassCount : public Container<int,bool>{
343  private:
344 
345  void _fill(){
346  if(this->value->get_value()){
347  (*this->container)++;
348  }
349  }
350  public:
351  PassCount(const std::string& name, Value<bool>* value)
352  :Container<int,bool>(name, value){
353  this->container = new int(0);
354  }
355 
356  GenContainer* clone_as(const std::string& new_name){
357  return new PassCount(new_name, this->value);
358  }
359 
360  void save_as(const std::string& fname, const SaveOption& option = SaveOption::PNG) {
361  //ROOT(hilariously) cannot serialize basic data types, we wrap this
362  //in a vector.
363  std::vector<int> v({*this->get_container()});
364  util::save_as_stl(&v, "std::vector<int>", this->get_name(), option);
365  }
366 };
367 
368 
369 template <typename... ArgTypes>
370 class MVA : public Container<TMVA::DataLoader,typename MVAData<ArgTypes...>::type>{
371  private:
372  std::vector<std::pair<std::string,std::string>> methods;
373 
374  std::string cut;
375  std::string opt;
376 
377  void _fill(){
378  std::tuple<ArgTypes...> t;
379  typename MVAData<ArgTypes...>::type& event = this->value->get_value();
380  bool is_training, is_signal;
381  double weight;
382  std::tie(is_training, is_signal, weight, t) = event;
383  std::vector<double> v = t2v<double>(t);
384  if (is_signal){
385  if (is_training){
386  this->container->AddSignalTrainingEvent(v, weight);
387  } else {
388  this->container->AddSignalTestEvent(v, weight);
389  }
390  } else {
391  if (is_training){
392  this->container->AddBackgroundTrainingEvent(v, weight);
393  } else {
394  this->container->AddBackgroundTestEvent(v, weight);
395  }
396  }
397  }
398  public:
399  MVA(const std::string& name, MVAData<ArgTypes...>* value, const std::string& cut = "", const std::string& opt = "")
400  :Container<TMVA::DataLoader,typename MVAData<ArgTypes...>::type>(name, value),
401  cut(cut), opt(opt) {
402  this->container = new TMVA::DataLoader(name);
403  for (std::pair<std::string,char>& p : value->get_label_types()){
404  this->container->AddVariable(p.first, p.second);
405  }
406  }
407 
408  void add_method(const std::string& method_name, const std::string& method_params) {
409  methods.push_back(std::make_pair(method_name, method_params));
410  }
411 
412  GenContainer* clone_as(const std::string& new_name){
413  auto mva = new MVA<ArgTypes...>(new_name, (MVAData<ArgTypes...>*)this->value, this->cut, this->opt);
414  mva->methods = methods;
415  return mva;
416  }
417 
418  void save_as(const std::string& fname, const SaveOption& option = SaveOption::PNG) {
419  TFile* outputFile = gDirectory->GetFile();
420 
421  this->container->PrepareTrainingAndTestTree(cut.c_str(), opt.c_str());
422  TMVA::Factory *factory = new TMVA::Factory("TMVAClassification", outputFile,
423  "!V:!Silent:Color:DrawProgressBar:Transformations=I;D;P;G,D:AnalysisType=Classification");
424 
425  TMVA::Types& types = TMVA::Types::Instance();
426  for(auto& p : methods){
427  std::string method_name, method_params;
428  std::tie(method_name, method_params) = p;
429  TMVA::Types::EMVA method_type = types.GetMethodType(method_name);
430  factory->BookMethod(this->container, method_type, method_name, method_params);
431  }
432 
433  // Train MVAs using the set of training events
434  factory->TrainAllMethods();
435  // Evaluate all MVAs using the set of test events
436  factory->TestAllMethods();
437  // Evaluate and compare performance of all configured MVAs
438  factory->EvaluateAllMethods();
439 
440  delete factory;
441  }
442 };
443 }
444 #endif // root_container_hpp
Same as Counter but accepts multiple values per fill.
Definition: container.hpp:330
A Counter that keeps a mapping of the number of occurances of each input value.
Definition: container.hpp:315
STL namespace.
SaveOption
Enumeration of different options that can be used to save Containers.
Definition: container.hpp:69
Generic, untyped parent class of Container.
Definition: container.hpp:79
Definition: api.hpp:8
A class that is used to "hold" values.
Definition: container.hpp:134