susy_cfa  b611ccad937ea179f86a1f5663960264616c0a20
generate_cfa.cpp
Go to the documentation of this file.
1 #include "generate_cfa.hpp"
2 
3 #include <stdexcept>
4 #include <string>
5 #include <vector>
6 #include <fstream>
7 
8 #include "TLeafObject.h"
9 #include "TChain.h"
10 
11 namespace{
12  std::string AllCaps(std::string str){
13  for(std::string::iterator it = str.begin();
14  it != str.end();
15  ++it){
16  *it = toupper(*it);
17  }
18  return str;
19  }
20 }
21 
23  name_(),
24  to_type_(),
25  from_type_(),
26  from_chain_a_(){
27 }
28 
29 Variable::Variable(const std::string &name, const bool from_chain_a,
30  const std::string &to_type, const std::string &from_type):
31  name_(name),
32  to_type_(to_type),
33  from_type_(from_type),
34  from_chain_a_(from_chain_a){
35  }
36 
37 Variable::Variable(const std::string &name, const bool from_chain_a,
38  const std::string &to_type):
39  name_(name),
40  to_type_(to_type),
41  from_type_(""),
42  from_chain_a_(from_chain_a){
43  }
44 
45 const std::string &Variable::Name() const{
46  return name_;
47 }
48 
49 Variable &Variable::Name(const std::string &name){
50  name_=name;
51  return *this;
52 }
53 
54 const std::string &Variable::FromType() const{
55  return from_type_;
56 }
57 
58 Variable &Variable::FromType(const std::string &from_type){
59  from_type_=from_type;
60  return *this;
61 }
62 
63 const std::string &Variable::ToType() const{
64  return to_type_;
65 }
66 
67 Variable &Variable::ToType(const std::string &to_type){
68  to_type_=to_type;
69  return *this;
70 }
71 
72 const bool &Variable::FromChainA() const{
73  return from_chain_a_;
74 }
75 
76 Variable &Variable::FromChainA(const bool from_chain_a){
77  from_chain_a_=from_chain_a;
78  return *this;
79 }
80 
81 bool Variable::Converted() const{
82  return from_type_!="" && from_type_!=to_type_;
83 }
84 
85 void GetVariables(TChain &chain, const bool is_chain_a,
86  const size_t file, const size_t num_files,
87  Dictionary &vars){
88  if(file>=num_files) throw std::logic_error("Bad file number");
89  for(int i = 0; i < chain.GetListOfLeaves()->GetSize(); ++i){
90  std::string type_name(static_cast<TLeafObject*>((chain.GetListOfLeaves()->At(i)))->GetTypeName());
91  const std::string var_name(static_cast<TLeaf*>((chain.GetListOfLeaves()->At(i)))->GetBranch()->GetName());
92 
93  //Vector and strings need special treatment
94  bool needs_ptr(false);
95  for(size_t j(type_name.find("vector"));
96  j!=std::string::npos;
97  j=type_name.find("vector",j+6)){
98  type_name.replace(j,6,"std::vector");
99  needs_ptr=true;
100  }
101  for(size_t j(type_name.find("string"));
102  j!=std::string::npos;
103  j=type_name.find("string",j+6)){
104  type_name.replace(j,6,"std::string");
105  needs_ptr=true;
106  }
107  if(needs_ptr) type_name = type_name + "*";
108 
109  if(vars.find(var_name) == vars.end()){
110  //Need to make the vector the right size
111  typedef std::vector<std::pair<bool, std::string> > OneVar;
112  typedef std::pair<std::string, OneVar > Inserter;
113  vars.insert(Inserter(var_name, OneVar(num_files)));
114  }
115 
116  if(vars[var_name].size()!=num_files){
117  throw std::logic_error("Number of files does not match.");
118  }
119 
120  if(vars[var_name].at(file)!=std::pair<bool, std::string>(false, "")
121  && vars[var_name].at(file)!=std::pair<bool, std::string>(is_chain_a, type_name)){
122  throw std::runtime_error("Conflicting definition found for "
123  +type_name+" "+var_name+" in this file.");
124  }
125 
126  vars[var_name].at(file)=std::pair<bool, std::string>(is_chain_a, type_name);
127  }
128 }
129 
130 void ClassifyVariables(const Dictionary &all_vars,
131  std::vector<Variable> &base_vars, std::vector<Variable> &virtual_vars,
132  std::vector<std::vector<Variable> > &file_vars){
133  file_vars.clear();
134  if(all_vars.size()) file_vars.resize(all_vars.begin()->second.size());
135  for(Dictionary::const_iterator var = all_vars.begin(); var!= all_vars.end(); ++var){
136  const std::string &name = var->first;
137  if(var->second.size() == 0) throw std::logic_error("No variable definitions found!");
138 
139  const bool base_is_chain_a = var->second.at(0).first;
140  std::string best_type = var->second.at(0).second;
141 
142  bool all_same_chain = true, all_same_type = true;
143  for(size_t idef = 0; idef < var->second.size(); ++idef){
144  const bool this_is_chain_a = var->second.at(idef).first;
145  const std::string this_type = var->second.at(idef).second;
146 
147  if(this_is_chain_a!=base_is_chain_a){
148  all_same_chain = false;
149  }
150 
151  if(this_type != best_type){
152  all_same_type = false;
153  if(best_type == ""){
154  best_type = this_type;
155  }else if(this_type==""){
156  //Don't need to do anything
157  }else if((best_type=="std::vector<float>*" && this_type=="std::vector<bool>*")
158  || (best_type=="std::vector<bool>*" && this_type=="std:vector<float>*")){
159  best_type = "std::vector<bool>*";
160  }else{
161  throw std::runtime_error("Unknown type preference.");
162  }
163  }
164  }
165 
166  if(all_same_chain && all_same_type){
167  base_vars.push_back(Variable(name, base_is_chain_a, best_type));
168  }else{
169  //Don't care which chain for virtual function declarations, so just use true
170  virtual_vars.push_back(Variable(name, true, best_type));
171 
172  for(size_t idef = 0; idef < var->second.size(); ++idef){
173  const bool this_is_chain_a = var->second.at(idef).first;
174  const std::string this_type = var->second.at(idef).second;
175 
176  if(this_type != ""){
177  Variable this_var(name, this_is_chain_a, best_type, this_type);
178  file_vars.at(idef).push_back(this_var);
179  }
180  }
181  }
182  }
183 }
184 
185 void WriteBaseHeader(const std::vector<Variable> &base_vars,
186  const std::vector<Variable> &virtual_vars){
187  std::ofstream hpp_file("inc/cfa_base.hpp");
188  hpp_file << "#ifndef H_CFA_BASE\n";
189  hpp_file << "#define H_CFA_BASE\n\n";
190 
191  hpp_file << "#include <vector>\n";
192  hpp_file << "#include <string>\n\n";
193 
194  hpp_file << "#include \"TChain.h\"\n\n";
195 
196  hpp_file << "class cfa_base{\n";
197  hpp_file << "public:\n";
198  hpp_file << " explicit cfa_base(const std::string &file);\n\n";
199 
200  hpp_file << " long TotalEntries() const;\n";
201  hpp_file << " virtual void GetEntry(const long entry);\n";
202  hpp_file << " short GetVersion() const;\n";
203  hpp_file << " const std::string& SampleName() const;\n";
204  hpp_file << " const std::string& SampleName(const std::string &sample_name);\n";
205  hpp_file << " void SetFile(const std::string &file_name);\n";
206  hpp_file << " void AddFiles(const std::string& files);\n\n";
207 
208  hpp_file << " virtual ~cfa_base();\n\n";
209 
210  //Print accessor function declarations for variables common to all cfA versions
211  for(std::vector<Variable>::const_iterator var = base_vars.begin();
212  var != base_vars.end();
213  ++var){
214  if(var->Converted()){
215  throw std::logic_error("Should not have converted variables in base class");
216  }
217  hpp_file << " " << var->ToType() << " const & " << var->Name() << "() const;\n";
218  }
219  hpp_file << '\n';
220 
221  //Print accessor function declarations for variables that change across cfA versions
222  for(std::vector<Variable>::const_iterator var = virtual_vars.begin();
223  var != virtual_vars.end();
224  ++var){
225  hpp_file << " __attribute__((noreturn)) virtual " << var->ToType() << " const & "
226  << var->Name() << "() const;\n";
227  }
228  hpp_file << '\n';
229 
230  hpp_file << "protected:\n";
231  hpp_file << " void PrepareNewChains();\n";
232  hpp_file << " virtual void InitializeA();\n";
233  hpp_file << " virtual void InitializeB();\n\n";
234 
235  hpp_file << " TChain chainA_, chainB_;\n";
236  hpp_file << " long entry_;\n\n";
237 
238  hpp_file << "private:\n";
239  hpp_file << " void CalcVersion();\n\n";
240 
241  hpp_file << " std::string sample_name_;\n";
242  hpp_file << " mutable long total_entries_;\n";
243  hpp_file << " short cfa_version_;\n";
244  hpp_file << " mutable bool cached_total_entries_;\n\n";
245 
246  for(std::vector<Variable>::const_iterator var = base_vars.begin();
247  var != base_vars.end();
248  ++var){
249  hpp_file << " " << var->ToType() << ' ' << var->Name() << "_;\n";
250  if(var->Converted()){
251  throw std::runtime_error("Converted variable in base class.");
252  }
253  hpp_file << " TBranch *b_" << var->Name() << "_;\n";
254  hpp_file << " mutable bool c_" << var->Name() << "_;\n";
255  }
256  hpp_file << '\n';
257 
258  hpp_file << "};\n\n";
259 
260  hpp_file << "#endif\n";
261 
262  hpp_file.close();
263 }
264 
265 void WriteBaseSource(const std::vector<Variable> &base_vars,
266  const std::vector<Variable> &virtual_vars){
267  std::ofstream cpp_file("src/cfa_base.cpp");
268 
269  cpp_file << "#include \"cfa_base.hpp\"\n\n";
270 
271  cpp_file << "#include <string>\n";
272  cpp_file << "#include <vector>\n";
273  cpp_file << "#include <sstream>\n";
274  cpp_file << "#include <stdexcept>\n\n";
275 
276  cpp_file << "#include \"TChain.h\"\n\n";
277 
278  cpp_file << "cfa_base::cfa_base(const std::string &file):\n";
279  cpp_file << " chainA_(\"chainA\"),\n";
280  cpp_file << " chainB_(\"chainB\"),\n";
281  cpp_file << " sample_name_(file),\n";
282  cpp_file << " total_entries_(0),\n";
283  cpp_file << " cfa_version_(-1),\n";
284  if(base_vars.size()){
285  cpp_file << " cached_total_entries_(false),\n";
286  std::vector<Variable>::const_iterator last(base_vars.end());
287  --last;
288  for(std::vector<Variable>::const_iterator var = base_vars.begin();
289  var != last;
290  ++var){
291  cpp_file << " " << var->Name() << "_(0),\n";
292  if(var->Converted()){
293  cpp_file << " v_" << var->Name() << "_(0),\n";
294  }
295  cpp_file << " b_" << var->Name() << "_(NULL),\n";
296  cpp_file << " c_" << var->Name() << "_(false),\n";
297  }
298  cpp_file << " " << base_vars.back().Name() << "_(0),\n";
299  if(base_vars.back().Converted()){
300  cpp_file << " v_" << base_vars.back().Name() << "_(0),\n";
301  }
302  cpp_file << " b_" << base_vars.back().Name() << "_(NULL),\n";
303  cpp_file << " c_" << base_vars.back().Name() << "_(false){\n";
304  }else{
305  cpp_file << " cached_total_entries_(false){\n";
306  }
307  cpp_file << " CalcVersion();\n";
308  cpp_file << " AddFiles(file);\n";
309  cpp_file << " PrepareNewChains();\n";
310  cpp_file << "}\n\n";
311 
312  cpp_file << "long cfa_base::TotalEntries() const{\n";
313  cpp_file << " if(!cached_total_entries_){\n";
314  cpp_file << " const long nEntriesA(chainA_.GetEntries()), nEntriesB(chainB_.GetEntries());\n";
315  cpp_file << " if (nEntriesA!=nEntriesB){\n";
316  cpp_file << " total_entries_=-1;\n";
317  cpp_file << " }else{\n";
318  cpp_file << " total_entries_=nEntriesA;\n";
319  cpp_file << " }\n";
320  cpp_file << " cached_total_entries_=true;\n";
321  cpp_file << " }\n";
322  cpp_file << " return total_entries_;\n";
323  cpp_file << "}\n\n";
324 
325  cpp_file << "void cfa_base::GetEntry(const long entry){\n";
326  //Reset cache
327  for(std::vector<Variable>::const_iterator var = base_vars.begin();
328  var != base_vars.end();
329  ++var){
330  cpp_file << " c_" << var->Name() << "_ = false;\n";
331  }
332  cpp_file << " const long entry_a = chainA_.LoadTree(entry);\n";
333  cpp_file << " const long entry_b = chainB_.LoadTree(entry);\n";
334  cpp_file << " if(entry_a!=entry_b) throw std::runtime_error(\"Entry is in different trees for chains A and B\");\n";
335  cpp_file << " entry_ = entry_a;\n";
336  cpp_file << "}\n\n";
337 
338  cpp_file << "short cfa_base::GetVersion() const{\n";
339  cpp_file << " return cfa_version_;\n";
340  cpp_file << "}\n\n";
341 
342  cpp_file << "const std::string& cfa_base::SampleName() const{\n";
343  cpp_file << " return sample_name_;\n";
344  cpp_file << "}\n\n";
345 
346  cpp_file << "const std::string& cfa_base::SampleName(const std::string &sample_name){\n";
347  cpp_file << " sample_name_=sample_name;\n";
348  cpp_file << " return sample_name_;\n";
349  cpp_file << "}\n\n";
350 
351  cpp_file << "void cfa_base::SetFile(const std::string &file_name){\n";
352  cpp_file << " cached_total_entries_=false;\n";
353  cpp_file << " chainA_.Reset(); chainB_.Reset();\n";
354  cpp_file << " AddFiles(file_name);\n";
355  cpp_file << "}\n\n";
356 
357  cpp_file << "cfa_base::~cfa_base(){\n";
358  cpp_file << "}\n\n";
359 
360  cpp_file << "void cfa_base::CalcVersion(){\n";
361  cpp_file << " size_t pos = sample_name_.rfind(\"_v\");\n";
362  cpp_file << " if(pos != std::string::npos && pos < sample_name_.size()-2){\n";
363  cpp_file << " std::istringstream iss(sample_name_.substr(pos+2));\n";
364  cpp_file << " iss >> cfa_version_;\n";
365  cpp_file << " if(iss.fail() || iss.bad()){\n";
366  cpp_file << " cfa_version_ = -1;\n";
367  cpp_file << " }\n";
368  cpp_file << " }\n";
369  cpp_file << "}\n\n";
370 
371  cpp_file << "void cfa_base::AddFiles(const std::string &file_name){\n";
372  cpp_file << " cached_total_entries_=false;\n";
373  cpp_file << " std::string dir_name = \"/cfA\";\n";
374  // cpp_file << " if(file_name.find(\"cfa_file_8\")!=std::string::npos || file_name.find(\"cfa_file_13\")!=std::string::npos) dir_name = \"/configurableAnalysis\";\n";
375  cpp_file << " if(file_name.find(\"cfa_file_8\")!=std::string::npos) dir_name = \"/configurableAnalysis\";\n";
376  cpp_file << " chainA_.Add((file_name+dir_name+\"/eventA\").c_str());\n";
377  cpp_file << " chainB_.Add((file_name+dir_name+\"/eventB\").c_str());\n";
378  cpp_file << "}\n\n";
379 
380  cpp_file << "void cfa_base::PrepareNewChains(){\n";
381  cpp_file << " InitializeA();\n";
382  cpp_file << " InitializeB();\n";
383  cpp_file << "}\n\n";
384 
385  cpp_file << "void cfa_base::InitializeA(){\n";
386  cpp_file << " chainA_.SetMakeClass(1);\n";
387  //Set chainA branch addresses
388  for(std::vector<Variable>::const_iterator var = base_vars.begin();
389  var != base_vars.end();
390  ++var){
391 
392  if(var->FromChainA()){
393  cpp_file << " chainA_.SetBranchAddress(\"" << var->Name() << "\", &"
394  << var->Name() << "_, &b_" << var->Name() << "_);\n";
395  if(var->Converted()){
396  cpp_file << " chainA_.SetBranchAddress(\"" << var->Name() << "\", &v_"
397  << var->Name() << "_, &b_" << var->Name() << "_);\n";
398  }
399  }
400  }
401  cpp_file << "}\n\n";
402 
403  cpp_file << "void cfa_base::InitializeB(){\n";
404  cpp_file << " chainB_.SetMakeClass(1);\n";
405  //Set chainB branch addresses
406  for(std::vector<Variable>::const_iterator var = base_vars.begin();
407  var != base_vars.end();
408  ++var){
409 
410  if(!var->FromChainA()){
411  cpp_file << " chainB_.SetBranchAddress(\"" << var->Name() << "\", &"
412  << var->Name() << "_, &b_" << var->Name() << "_);\n";
413  if(var->Converted()){
414  cpp_file << " chainB_.SetBranchAddress(\"" << var->Name() << "\", &v_"
415  << var->Name() << "_, &b_" << var->Name() << "_);\n";
416  }
417  }
418  }
419  cpp_file << "}\n\n";
420 
421  //Write implementation for common variable accessors
422  for(std::vector<Variable>::const_iterator var = base_vars.begin();
423  var != base_vars.end();
424  ++var){
425  if(var->Converted()){
426  throw("Should not have converted variables in base class");
427  }
428  PrintAccessor(*var, cpp_file, "cfa_base");
429  }
430 
431  //Write virtual base for variables differing across cfA versions
432  for(std::vector<Variable>::const_iterator var = virtual_vars.begin();
433  var!=virtual_vars.end();
434  ++var){
435  cpp_file << var->ToType() << " const & cfa_base::" << var->Name() << "() const{\n";
436  cpp_file << " throw std::runtime_error(\"" << var->Name()
437  << " does not exist in this cfA version.\");\n";
438  cpp_file << "}\n\n";
439  }
440 
441  cpp_file.close();
442 }
443 
444 void WriteDerivedHeader(const std::string &class_name,
445  const std::vector<Variable> &vars){
446  std::ofstream hpp_file(("inc/"+class_name+".hpp").c_str());
447 
448  hpp_file << "#ifndef H_" << AllCaps(class_name) << "\n";
449  hpp_file << "#define H_" << AllCaps(class_name) << "\n\n";
450 
451  hpp_file << "#include \"cfa_base.hpp\"\n\n";
452 
453  hpp_file << "#include <vector>\n";
454  hpp_file << "#include <string>\n\n";
455 
456  hpp_file << "#include \"TChain.h\"\n\n";
457 
458  hpp_file << "class " << class_name << ": public cfa_base{\n";
459  hpp_file << "public:\n";
460  hpp_file << " explicit " << class_name << "(const std::string &file);\n\n";
461 
462  hpp_file << " virtual void GetEntry(const long entry);\n\n";
463 
464  hpp_file << " virtual ~" << class_name << "();\n\n";
465 
466  //Print accessor functions
467  for(std::vector<Variable>::const_iterator var = vars.begin();
468  var!=vars.end();
469  ++var){
470  hpp_file << " virtual " << var->ToType() << " const & " << var->Name() << "() const;\n";
471  }
472  hpp_file << '\n';
473 
474  hpp_file << "private:\n";
475  hpp_file << " virtual void InitializeA();\n";
476  hpp_file << " virtual void InitializeB();\n\n";
477 
478  //Print member variables
479  for(std::vector<Variable>::const_iterator var = vars.begin();
480  var!=vars.end();
481  ++var){
482  hpp_file << " " << var->ToType() << ' ' << var->Name() << "_;\n";
483  if(var->Converted()){
484  hpp_file << " " << var->FromType() << " v_" << var->Name() << "_;\n";
485  }
486  hpp_file << " TBranch *b_" << var->Name() << "_;\n";
487  hpp_file << " mutable bool c_" << var->Name() << "_;\n";
488  }
489  hpp_file << "};\n\n";
490 
491  hpp_file << "#endif\n";
492 
493  hpp_file.close();
494 }
495 
496 void WriteDerivedSource(const std::string &class_name,
497  const std::vector<Variable> &vars){
498  std::ofstream cpp_file(("src/"+class_name+".cpp").c_str());
499 
500  cpp_file << "#include \"" << class_name << ".hpp\"\n\n";
501 
502  cpp_file << "#include <string>\n";
503  cpp_file << "#include <vector>\n";
504  cpp_file << "#include <sstream>\n";
505  cpp_file << "#include <stdexcept>\n\n";
506 
507  cpp_file << "#include \"TChain.h\"\n\n";
508 
509  cpp_file << class_name << "::" << class_name << "(const std::string &file):\n";
510  if(vars.size()){
511  cpp_file << " cfa_base(file),\n";
512 
513  std::vector<Variable>::const_iterator last(vars.end());
514  --last;
515  for(std::vector<Variable>::const_iterator var = vars.begin();
516  var != last;
517  ++var){
518  cpp_file << " " << var->Name() << "_(0),\n";
519  if(var->Converted()){
520  cpp_file << " v_" << var->Name() << "_(0),\n";
521  }
522  cpp_file << " b_" << var->Name() << "_(NULL),\n";
523  cpp_file << " c_" << var->Name() << "_(false),\n";
524  }
525  cpp_file << " " << vars.back().Name() << "_(0),\n";
526  if(vars.back().Converted()){
527  cpp_file << " v_" << vars.back().Name() << "_(0),\n";
528  }
529  cpp_file << " b_" << vars.back().Name() << "_(NULL),\n";
530  cpp_file << " c_" << vars.back().Name() << "_(false){\n";
531  }else{
532  cpp_file << " cfa_base(file){\n";
533  }
534 
535  cpp_file << " PrepareNewChains();\n";
536  cpp_file << "}\n\n";
537 
538  cpp_file << "void " << class_name << "::GetEntry(const long entry){\n";
539  //Reset cache
540  for(std::vector<Variable>::const_iterator var = vars.begin();
541  var != vars.end();
542  ++var){
543  cpp_file << " c_" << var->Name() << "_ = false;\n";
544  }
545  cpp_file << " cfa_base::GetEntry(entry);\n";
546  cpp_file << "}\n\n";
547 
548  cpp_file << "void " << class_name << "::InitializeA(){\n";
549  cpp_file << " cfa_base::InitializeA();\n";
550  //Set chainA branch addresses
551  for(std::vector<Variable>::const_iterator var = vars.begin();
552  var != vars.end();
553  ++var){
554 
555  if(var->FromChainA()){
556  cpp_file << " chainA_.SetBranchAddress(\"" << var->Name() << "\", &"
557  << var->Name() << "_, &b_" << var->Name() << "_);\n";
558  if(var->Converted()){
559  cpp_file << " chainA_.SetBranchAddress(\"" << var->Name() << "\", &v_"
560  << var->Name() << "_, &b_" << var->Name() << "_);\n";
561  }
562  }
563  }
564  cpp_file << "}\n\n";
565 
566  cpp_file << "void " << class_name << "::InitializeB(){\n";
567  cpp_file << " cfa_base::InitializeB();\n";
568  //Set chainB branch addresses
569  for(std::vector<Variable>::const_iterator var = vars.begin();
570  var != vars.end();
571  ++var){
572 
573  if(!var->FromChainA()){
574  cpp_file << " chainB_.SetBranchAddress(\"" << var->Name() << "\", &"
575  << var->Name() << "_, &b_" << var->Name() << "_);\n";
576  if(var->Converted()){
577  cpp_file << " chainB_.SetBranchAddress(\"" << var->Name() << "\", &v_"
578  << var->Name() << "_, &b_" << var->Name() << "_);\n";
579  }
580  }
581  }
582  cpp_file << "}\n\n";
583 
584  cpp_file << class_name << "::~" << class_name << "(){\n";
585  cpp_file << "}\n\n";
586 
587  //Define accessor functions
588  for(std::vector<Variable>::const_iterator var = vars.begin();
589  var != vars.end();
590  ++var){
591  PrintAccessor(*var, cpp_file, class_name);
592  }
593 
594  cpp_file.close();
595 }
596 
597 void AddToTypelist(const std::vector<Variable> &vars,
598  Typelist &typelist){
599  for(std::vector<Variable>::const_iterator var = vars.begin();
600  var != vars.end();
601  ++var){
602  typelist.insert(std::pair<std::string, std::string>(var->Name(), var->ToType()));
603  }
604 }
605 
606 void PrintAccessor(const Variable &var, std::ofstream &file, const std::string &class_name){
607  file << var.ToType() << " const & " << class_name << "::" << var.Name() << "() const{\n";
608  file << " if(!c_" << var.Name() << "_ && b_"<< var.Name() << "_){\n";
609  file << " b_" << var.Name() << "_->GetEntry(entry_);\n";
610  if(var.Converted()){
611  if(var.FromType()=="std::vector<float>*" && var.ToType()=="std::vector<bool>*"){
612  file << " " << var.Name() << "_->resize(v_" << var.Name() << "_->size());\n";
613  file << " for(size_t i = 0; i < " << var.Name() << "_->size(); ++i){\n";
614  file << " " << var.Name() << "_->at(i) = static_cast<bool>(v_"
615  << var.Name() << "_->at(i));\n";
616  file << " }\n";
617  }else{
618  throw std::logic_error("Cannot write accessor for requested type conversion");
619  }
620  }
621  file << " c_" << var.Name() << "_ = true;\n";
622  file << " }\n";
623  file << " return " << var.Name() << "_;\n";
624  file << "}\n\n";
625 }
626 
627 void GetRules(RepList &reps){
628  reps.clear();
629 
630  std::string new_word;
631  std::vector<std::string> rep_list;
632  std::ifstream file("txt/mux_rules.cfg");
633  while(file >> new_word){
634  if(new_word.find("--") != std::string::npos) break;
635  }
636 
637  while(file >> new_word){
638  rep_list.clear();
639  //2 here is the number of cfa versions. Should improve this to use number of example files read in
640  std::string temp;
641  for(unsigned i = 0; i < 2 && file >> temp; ++i){
642  rep_list.push_back(temp);
643  }
644 
645  reps.push_back(std::make_pair(new_word, rep_list));
646  }
647 }
648 
649 void GetReplacements(const Typelist &typelist, const RepList &pats, RepMap &reps){
650  reps.clear();
651  //Loop over all variables
652  for(Typelist::const_iterator var = typelist.begin();
653  var != typelist.end();
654  ++var){
655  const std::string& name = var->first;
656  const std::string& type = var->second;
657  //Loop over replacement rules
658  for(RepList::const_iterator pat = pats.begin();
659  pat != pats.end();
660  ++pat){
661  //Loop over words to replace in this rule
662  for(std::vector<std::string>::const_iterator to_match = pat->second.begin();
663  to_match != pat->second.end();
664  ++to_match){
665  const std::string::size_type match_loc = name.find(*to_match);
666  //if(match_loc != std::string::npos){ //Use this to search whole string (dangerous, maybe not working)
667  if(match_loc == 0){ // Use this to search at beginning of string
668  //Variable matches this replacement rule!
669  const std::string prefix = name.substr(0, match_loc);
670  const std::string suffix = name.substr(match_loc+to_match->size(), name.size());
671 
672  //Get the name of the function we're producing
673  const std::string out_name = prefix + pat->first + suffix;
674  const std::pair<std::string, std::string> key_val(out_name, type);
675 
676  //Lookup all the replacements for this new function
677  std::vector<std::string> out_vars(pat->second.size(), "");
678  for(unsigned i = 0; i < out_vars.size(); ++i){
679  const std::string test_name = prefix + pat->second.at(i) + suffix;
680  if(typelist.find(std::make_pair(test_name, type)) != typelist.end()){
681  //Found a valid match
682  out_vars.at(i) = test_name;
683  }
684  }
685 
686  //Make sure we haven't already defined the function
687  if(reps.find(key_val) != reps.end() && reps.find(key_val)->second!=out_vars){
688  throw std::runtime_error("Auto-generating the same function in multiple ways ("+type+" "+out_name+")");
689  }
690 
691  reps.insert(std::make_pair(key_val, out_vars));
692  }
693  }
694  }
695  }
696 }
697 
698 void GetOverwritten(const Typelist &typelist, const RepMap &replacements,
699  RepMap &overwritten, RepMap &new_funcs){
700  overwritten.clear();
701  new_funcs.clear();
702  for(RepMap::const_iterator it = replacements.begin();
703  it != replacements.end();
704  ++it){
705  if(typelist.find(it->first) != typelist.end()){
706  overwritten.insert(*it);
707  }else{
708  new_funcs.insert(*it);
709  }
710  }
711 }
712 
713 void WriteMergedHeader(const Typelist &typelist, const RepMap &overwritten, const RepMap &new_funcs){
714  std::ofstream hpp_file("inc/cfa.hpp");
715 
716  hpp_file << "#ifndef H_CFA_MERGED\n";
717  hpp_file << "#define H_CFA_MERGED\n\n";
718 
719  hpp_file << "#include <vector>\n";
720  hpp_file << "#include <string>\n";
721  hpp_file << "#include <typeinfo>\n\n";
722 
723  hpp_file << "#include \"TChain.h\"\n\n";
724 
725  hpp_file << "class cfa_base;\n\n";
726 
727  hpp_file << "class cfa{\n";
728  hpp_file << "public:\n";
729  hpp_file << " explicit cfa(const std::string &file, const bool is_8TeV = false);\n\n";
730 
731  hpp_file << " long TotalEntries() const;\n";
732  hpp_file << " virtual void GetEntry(const long entry);\n";
733  hpp_file << " short GetVersion() const;\n";
734  hpp_file << " const std::string& SampleName() const;\n";
735  hpp_file << " const std::string& SampleName(const std::string &sample_name);\n";
736  hpp_file << " void SetFile(const std::string &file, bool is_8TeV = false);\n";
737  hpp_file << " void AddFiles(const std::string &file);\n";
738  hpp_file << " const std::type_info& Type() const;\n\n";
739 
740  hpp_file << " virtual ~cfa();\n\n";
741 
742  //Print accessor function declarations
743  for(Typelist::const_iterator it = typelist.begin();
744  it != typelist.end();
745  ++it){
746  const std::string name = it->first;
747  const std::string type = it->second;
748 
749  if(overwritten.find(*it) != overwritten.end()){
750  hpp_file << " " << type << " const & " << name << "(const bool mux = true) const;\n";
751  }else{
752  hpp_file << " " << type << " const & " << name << "() const;\n";
753  }
754  }
755 
756  for(RepMap::const_iterator it = new_funcs.begin();
757  it != new_funcs.end();
758  ++it){
759  hpp_file << " " << it->first.second << " const & " << it->first.first << "() const;\n";
760  }
761  hpp_file << "\n";
762 
763  hpp_file << "private:\n";
764  hpp_file << " cfa_base* cfa_;\n";
765  hpp_file << "};\n\n";
766 
767  hpp_file << "#endif\n";
768 
769  hpp_file.close();
770 }
771 
772 void WriteMergedSource(const Typelist &typelist, const RepMap &overwritten, const RepMap &new_funcs,
773  const std::vector<std::string>& class_names){
774  std::ofstream cpp_file("src/cfa.cpp");
775 
776  cpp_file << "#include \"cfa.hpp\"\n\n";
777 
778  cpp_file << "#include <string>\n";
779  cpp_file << "#include <vector>\n";
780  cpp_file << "#include <sstream>\n";
781  cpp_file << "#include <stdexcept>\n";
782  cpp_file << "#include <typeinfo>\n\n";
783 
784  cpp_file << "#include \"TChain.h\"\n\n";
785 
786  cpp_file << "#include \"cfa_base.hpp\"\n";
787  cpp_file << "#include \"cfa_8.hpp\"\n";
788  cpp_file << "#include \"cfa_13.hpp\"\n\n";
789 
790  cpp_file << "cfa::cfa(const std::string &file, const bool is_8TeV):\n";
791  cpp_file << " cfa_( is_8TeV ? static_cast<cfa_base*>(new cfa_8(file)) : static_cast<cfa_base*>(new cfa_13(file)) ){\n";
792  cpp_file << "}\n\n";
793 
794  cpp_file << "long cfa::TotalEntries() const{\n";
795  cpp_file << " return cfa_->TotalEntries();\n";
796  cpp_file << "}\n\n";
797 
798  cpp_file << "void cfa::GetEntry(const long entry){\n";
799  cpp_file << " cfa_->GetEntry(entry);\n";
800  cpp_file << "}\n\n";
801 
802  cpp_file << "short cfa::GetVersion() const{\n";
803  cpp_file << " return cfa_->GetVersion();\n";
804  cpp_file << "}\n\n";
805 
806  cpp_file << "const std::string& cfa::SampleName() const{\n";
807  cpp_file << " return cfa_->SampleName();\n";
808  cpp_file << "}\n\n";
809 
810  cpp_file << "const std::string& cfa::SampleName(const std::string &sample_name){\n";
811  cpp_file << " return cfa_->SampleName(sample_name);\n";
812  cpp_file << "}\n\n";
813 
814  cpp_file << "void cfa::SetFile(const std::string &file, const bool is_8TeV){\n";
815  cpp_file << " delete cfa_; cfa_=NULL;\n";
816  cpp_file << " cfa_ = ( is_8TeV ? static_cast<cfa_base*>(new cfa_8(file)) : static_cast<cfa_base*>(new cfa_13(file)) );\n";
817  cpp_file << "}\n\n";
818 
819  cpp_file << "void cfa::AddFiles(const std::string &file){\n";
820  cpp_file << " cfa_->AddFiles(file);\n";
821  cpp_file << "}\n\n";
822 
823  cpp_file << "const std::type_info& cfa::Type() const{\n";
824  cpp_file << " return typeid(*cfa_);\n";
825  cpp_file << "}\n\n";
826 
827  cpp_file << "cfa::~cfa(){\n";
828  cpp_file << " delete cfa_; cfa_=NULL;\n";
829  cpp_file << "}\n\n";
830 
831  //Print accessor implementation for variables
832  for(Typelist::const_iterator it = typelist.begin();
833  it != typelist.end();
834  ++it){
835  const std::string name = it->first;
836  const std::string type = it->second;
837 
838  const RepMap::const_iterator over_it = overwritten.find(*it);
839  if(over_it == overwritten.end()){
840  //Function does not conflict with a mux name and just does polymorphic call
841  cpp_file << type << " const & cfa::" << name << "() const{\n";
842  cpp_file << " return cfa_->" << name << "();\n";
843  cpp_file << "}\n\n";
844  }else{
845  //Function conflicts with a mux name and needs special treatment
846  const std::vector<std::string>& funcs = over_it->second;
847  if(funcs.size() != class_names.size()) throw std::runtime_error("Could not match class names to muxes");
848 
849  cpp_file << type << " const & cfa::" << name << "(const bool mux) const{\n";
850  if(funcs.size()){
851  cpp_file << " if(mux){\n";
852  for(unsigned i = 0; i < funcs.size(); ++i){
853  cpp_file << " " << (i?"}else ":"") << "if(typeid(*cfa_)==typeid(" << class_names.at(i) << ")){\n";
854  if(funcs.at(i)!=""){
855  cpp_file << " return cfa_->" << funcs.at(i) << "();\n";
856  }else{
857  cpp_file << " throw std::logic_error(\"Function lookup unknown for class \"+std::string(typeid(*cfa_).name()));\n";
858  }
859  }
860  cpp_file << " }else{\n";
861  cpp_file << " throw std::logic_error(\"Function lookup unknown for class \"+std::string(typeid(*cfa_).name()));\n";
862  cpp_file << " }\n";
863  cpp_file << " }\n";
864  }
865  cpp_file << " return cfa_->" << name << "();\n";
866  cpp_file << "}\n\n";
867  }
868  }
869 
870  //Print functions that only exist as a result of muxing
871  for(RepMap::const_iterator it = new_funcs.begin();
872  it != new_funcs.end();
873  ++it){
874  const std::string& name = it->first.first;
875  const std::string& type = it->first.second;
876  const std::vector<std::string>& funcs = it->second;
877  if(funcs.size() != class_names.size()) throw std::runtime_error("Could not match class names to muxes");
878 
879  bool all_blank = true;
880  std::string good_name = "";
881 
882  cpp_file << type << " const & cfa::" << name << "() const{\n";
883  for(unsigned i = 0; i < funcs.size(); ++i){
884  if(all_blank && funcs.at(i)!=""){
885  all_blank = false;
886  good_name = funcs.at(i);
887  }
888  cpp_file << " " << (i?"}else ":"") << "if(typeid(*cfa_)==typeid(" << class_names.at(i) << ")){\n";
889  if(funcs.at(i)!=""){
890  cpp_file << " return cfa_->" << funcs.at(i) << "();\n";
891  }else{
892  cpp_file << " throw std::logic_error(\"Function lookup unknown for class \"+std::string(typeid(*cfa_).name()));\n";
893  }
894  }
895  cpp_file << " }else{\n";
896  cpp_file << " throw std::logic_error(\"Function lookup unknown for class \"+std::string(typeid(*cfa_).name()));\n";
897  cpp_file << " }\n";
898  cpp_file << " return cfa_->" << good_name << "();\n";
899  cpp_file << "}\n\n";
900 
901  //Make sure we found at least one valid function to call
902  if(all_blank) throw std::runtime_error("No valid function call available for "+type+name);
903  }
904 
905  cpp_file.close();
906 }
std::set< std::pair< std::string, std::string > > Typelist
void GetVariables(TChain &chain, const bool is_chain_a, const size_t file, const size_t num_files, Dictionary &vars)
void WriteBaseHeader(const std::vector< Variable > &base_vars, const std::vector< Variable > &virtual_vars)
std::vector< std::pair< std::string, std::vector< std::string > > > RepList
bool from_chain_a_
void WriteMergedSource(const Typelist &typelist, const RepMap &overwritten, const RepMap &new_funcs, const std::vector< std::string > &class_names)
void WriteDerivedSource(const std::string &class_name, const std::vector< Variable > &vars)
void WriteBaseSource(const std::vector< Variable > &base_vars, const std::vector< Variable > &virtual_vars)
void GetOverwritten(const Typelist &typelist, const RepMap &replacements, RepMap &overwritten, RepMap &new_funcs)
const std::string & Name() const
void AddToTypelist(const std::vector< Variable > &vars, Typelist &typelist)
void PrintAccessor(const Variable &var, std::ofstream &file, const std::string &class_name)
std::map< std::pair< std::string, std::string >, std::vector< std::string > > RepMap
void GetReplacements(const Typelist &typelist, const RepList &pats, RepMap &reps)
void WriteMergedHeader(const Typelist &typelist, const RepMap &overwritten, const RepMap &new_funcs)
std::string from_type_
void GetRules(RepList &reps)
void ClassifyVariables(const Dictionary &all_vars, std::vector< Variable > &base_vars, std::vector< Variable > &virtual_vars, std::vector< std::vector< Variable > > &file_vars)
std::string to_type_
const std::string & ToType() const
void WriteDerivedHeader(const std::string &class_name, const std::vector< Variable > &vars)
string name
Definition: disk_usage.cxx:14
std::string name_
const bool & FromChainA() const
std::string AllCaps(std::string str)
bool Converted() const
std::map< std::string, std::vector< std::pair< bool, std::string > > > Dictionary
const std::string & FromType() const