ra4_draw  4bd0201e3d922d42bd545d4b045ed44db33454a4
generate_baby.cxx
Go to the documentation of this file.
1 
17 #include "core/generate_baby.hpp"
18 
19 #define ERROR(x) throw std::runtime_error(string("Error in file ")+__FILE__+" at line "+to_string(__LINE__)+" (in "+__func__+"): "+x);
20 #define DBG(x) std::cout << "In " << __FILE__ << " at line " << __LINE__ << " (in function " << __func__ << "): " << x << std::endl;
21 
22 #include <cctype>
23 
24 #include <string>
25 #include <vector>
26 #include <stdexcept>
27 #include <fstream>
28 #include <iostream>
29 #include <algorithm>
30 
31 using namespace std;
32 
33 int main(int argc, char *argv[]){
34  set<string> files;
35  for(int argi = 1; argi < argc; ++argi){
36  files.insert(argv[argi]);
37  }
38 
39  set<Variable> vars = GetVariables(files);
40  WriteBaseHeader(vars, files);
41  WriteBaseSource(vars);
42  for(const auto &file: files){
43  WriteSpecializedHeader(vars, file);
44  WriteSpecializedSource(vars, file);
45  }
46 }
47 
54 SimpleVariable::SimpleVariable(const string &type, const string &name):
55  type_(type),
56  name_(name){
57  }
58 
63 Variable::Variable(const string &name):
64  name_(name),
65  type_map_(){
66 }
67 
72 const std::string & Variable::Name() const{
73  return name_;
74 }
75 
80 std::string & Variable::Name(){
81  return name_;
82 }
83 
91 string Variable::Type() const{
92  if(ImplementInBase() || VirtualInBase()){
93  for(const auto &var: type_map_){
94  if(var.second != "") return var.second;
95  }
96  }
97  return "";
98 }
99 
109 string Variable::Type(const string &baby_type) const{
110  if(HasEntry(baby_type)){
111  return type_map_.at(baby_type);
112  }else{
113  return "";
114  }
115 }
116 
124 string Variable::DecoratedType() const{
125  string type = Type();
126  if(type.find("std::") != string::npos){
127  type = type+"*";
128  }
129  return type;
130 }
131 
142 string Variable::DecoratedType(const string &baby_type) const{
143  string type = Type(baby_type);
144  if(type.find("std::") != string::npos){
145  type = type+"*";
146  }
147  return type;
148 }
149 
156 bool Variable::HasEntry(const string &baby_type) const{
157  return type_map_.find(baby_type) != type_map_.cend();
158 }
159 
167 void Variable::SetEntry(const string &baby_type,
168  const string &type){
169  type_map_[baby_type] = type;
170 }
171 
180  set<string> type_set = GetTypeSet();
181  return type_set.size()==1 && *(type_set.cbegin()) != "";
182 }
183 
193  set<string> type_set = GetTypeSet();
194 
195  //type_set should contain one real type and an empty type indicating absence
196  //from some Baby classes
197  if(type_set.size() != 2) return false;
198  auto iter = type_set.cbegin();
199  string first_type = *iter;
200  ++iter;
201  string second_type = *iter;
202  return (first_type != "" && second_type == "")
203  || (first_type == "" && second_type != "");
204 }
205 
213 bool Variable::ImplementIn(const std::string &baby_type) const{
214  return VirtualInBase() && Type(baby_type)!="";
215 }
216 
225 bool Variable::NotInBase() const{
226  set<string> type_set = GetTypeSet();
227  if(type_set.size() == 2){
228  auto iter = type_set.cbegin();
229  string first_type = *iter;
230  ++iter;
231  string second_type = *iter;
232  return (first_type != second_type)
233  && (first_type != "")
234  && (second_type != "");
235  }else{
236  return type_set.size() >= 3;
237  }
238 }
239 
247 bool Variable::EverythingIn(const string &baby_type) const{
248  return NotInBase() && Type(baby_type)!="";
249 }
250 
259 bool Variable::operator<(const Variable &other) const{
260  return name_ < other.name_;
261 }
262 
270 set<string> Variable::GetTypeSet() const{
271  set<string> types;
272  for(const auto &type: type_map_){
273  types.insert(type.second);
274  }
275  return types;
276 }
277 
278 /*!/brief Reads files to get variable names and associated types
279 
280  \param[in] files Set of files to be read. Typically everything in
281  txt/variables
282 
283  \return All variables with associated types used for each derived Baby class
284 */
285 set<Variable> GetVariables(const set<string> &files){
286  vector<Variable> vars;
287  for(const auto &file: files){
288  ifstream ifs("txt/variables/"+file);
289  for(string line; std::getline(ifs, line); ){
290  if(IsComment(line)) continue;
291  SimpleVariable simple_var = GetVariable(line);
292  Variable var(simple_var.name_);
293  vector<Variable>::iterator this_var = vars.end();
294  for(auto iter = vars.begin();
295  iter != vars.end();
296  ++iter){
297  if(iter->Name() == var.Name()) this_var = iter;
298  }
299  if(this_var != vars.end()){
300  this_var->SetEntry(file, simple_var.type_);
301  }else{
302  var.SetEntry(file, simple_var.type_);
303  vars.push_back(var);
304  }
305  }
306  }
307 
308  for(auto &var: vars){
309  for(const auto &file: files){
310  if(!var.HasEntry(file)) var.SetEntry(file, "");
311  }
312  }
313 
314  return {vars.cbegin(), vars.cend()};
315 }
316 
325 bool IsComment(const string &line){
326  if(line.size() <= 2) return true;
327  for(const auto &letter: line){
328  if(letter == ' ') continue;
329  if(isalpha(letter) || letter == '_'){
330  return false;
331  }else{
332  return true;
333  }
334  }
335  return true;
336 }
337 
345  RemoveExtraSpaces(line);
346  auto loc = line.rfind(';');
347  if(loc != string::npos) line = line.substr(0,loc);
348  loc = line.rfind(' ');
349  if(loc == string::npos){
350  ERROR("Could not separate type and variable in "+line);
351  return SimpleVariable("", line);
352  }else{
353  return SimpleVariable(line.substr(0,loc), line.substr(loc+1));
354  }
355 }
356 
361 void RemoveExtraSpaces(string &line){
362  size_t loc = line.find_first_not_of(" ");
363  if(loc != string::npos){
364  line = line.substr(loc);
365  }
366  while((loc = line.find(" ", loc)) != string::npos){
367  line.replace(loc, 2, " ");
368  ++loc;
369  }
370  loc = line.find_last_not_of(" ");
371  if(loc != string::npos){
372  line = line.substr(0, loc+1);
373  }
374 }
375 
383 string ToUpper(string x){
384  for(size_t i = 0; i < x.size(); ++i){
385  x.at(i) = toupper(x.at(i));
386  }
387  return x;
388 }
389 
397 string ToLower(string x){
398  for(size_t i = 0; i < x.size(); ++i){
399  x.at(i) = tolower(x.at(i));
400  }
401  return x;
402 }
403 
410 void WriteBaseHeader(const set<Variable> &vars,
411  const set<string> &types){
412  ofstream file("inc/core/baby.hpp");
413  file << "#ifndef H_BABY\n";
414  file << "#define H_BABY\n\n";
415 
416  file << "#include <vector>\n";
417  file << "#include <set>\n";
418  file << "#include <memory>\n";
419  file << "#include <string>\n\n";
420 
421  file << "#include \"TChain.h\"\n\n";
422  file << "#include \"TString.h\"\n\n";
423 
424  file << "class Process;\n";
425  file << "class NamedFunc;\n\n";
426 
427  file << "class Baby{\n";
428  file << "private:\n";
429  file << " class Activator{\n";
430  file << " public:\n";
431  file << " Activator(Baby &baby);\n";
432  file << " ~Activator();\n\n";
433 
434  file << " private:\n";
435  file << " Baby & baby_;\n\n";
436 
437  file << " Activator(const Activator &) = delete;\n";
438  file << " Activator & operator=(const Activator &) = delete;\n";
439  file << " Activator(Activator &&) = delete;\n";
440  file << " Activator & operator=(Activator &&) = delete;\n";
441  file << " };\n\n";
442 
443  file << "public:\n";
444  file << " explicit Baby(const std::set<std::string> &file_names,\n";
445  file << " const std::set<const Process*> &processes = std::set<const Process*>{});\n";
446  file << " Baby(Baby &&) = default;\n";
447  file << " Baby& operator=(Baby &&) = default;\n";
448  file << " virtual ~Baby() = default;\n\n";
449 
450  file << " long GetEntries() const;\n";
451  file << " virtual void GetEntry(long entry);\n\n";
452 
453  file << " const std::set<std::string> & FileNames() const;\n\n";
454  file << " int SampleType() const;\n";
455  file << " int SetSampleType(const TString &filename);\n\n";
456 
457  file << " std::set<const Process*> processes_;\n\n";
458 
459  for(const auto &var: vars){
460  if(var.ImplementInBase()){
461  file << " "
462  << var.DecoratedType() << " const & "
463  << var.Name() << "() const;\n";
464  }else if(var.VirtualInBase()){
465  file << " virtual "
466  << var.DecoratedType() << " const & "
467  << var.Name() << "() const = 0;\n";
468  }
469  }
470  file << "\n";
471 
472  file << " const std::unique_ptr<TChain> & GetTree() const;\n\n";
473 
474  file << " static NamedFunc GetFunction(const std::string &var_name);\n\n";
475 
476  file << " std::unique_ptr<Activator> Activate();\n\n";
477 
478  file << "protected:\n";
479  file << " virtual void Initialize();\n\n";
480 
481  file << " std::unique_ptr<TChain> chain_;//!<Chain to load variables from\n";
482  file << " long entry_;//!<Current entry\n\n";
483 
484  file << "private:\n";
485  file << " friend class Activator;\n\n";
486 
487  file << " Baby() = delete;\n";
488  file << " Baby(const Baby &) = delete;\n";
489  file << " Baby& operator=(const Baby &) = delete;\n\n";
490 
491  file << " std::set<std::string> file_names_;//!<Files loaded into TChain\n";
492  file << " int sample_type_;//!< Integer indicating what kind of sample the first file has\n";
493  file << " mutable long total_entries_;//!<Cached number of events in TChain\n";
494  file << " mutable bool cached_total_entries_;//!<Flag if cached event count up to date\n\n";
495 
496  file << " void ActivateChain();\n";
497  file << " void DeactivateChain();\n\n";
498 
499  for(const auto &var: vars){
500  if(!var.ImplementInBase()) continue;
501  file << " "
502  << var.DecoratedType() << " "
503  << var.Name() << "_;//!<Cached value of " << var.Name() << '\n';
504  file << " TBranch *b_" << var.Name() << "_;//!<Branch from which "
505  << var.Name() << " is read\n";
506  file << " mutable bool c_" << var.Name() << "_;//!<Flag if cached "
507  << var.Name() << " up to date\n";
508  }
509  file << "};\n\n";
510 
511  for(const auto &type: types){
512  file << "#include \"core/baby_" << type << ".hpp\"\n";
513  }
514  file << '\n';
515 
516  file << "#endif" << endl;
517  file.close();
518 }
519 
524 void WriteBaseSource(const set<Variable> &vars){
525  ofstream file("src/core/baby.cpp");
526  file << "/*! \\class Baby\n\n";
527 
528  file << " \\brief Abstract base class for access to ntuple variables\n\n";
529 
530  file << " Loads variables on demand and caches for fast repeated use within an event.\n\n";
531 
532  file << " A derived class is used for each known ntuple format. Variables and functions\n";
533  file << " are kept in this base class whenever possible, and placed in the derived classes\n";
534  file << " only when necessary. All variables that are identical across derived Baby\n";
535  file << " classes are implemented fully in this base class. Others are implemented with\n";
536  file << " dummy virtual accessor functions and internal member variables in the base\n";
537  file << " class, with derived classes providing a real implementation of the accessor if\n";
538  file << " the variable is defined in the corresponding ntuple format. If the variable has\n";
539  file << " inconsistent types across the ntuple formats, then each derived class must\n";
540  file << " provide all necessary accessors and internal variables; in such a case, access\n";
541  file << " through this abstract base is not possible.\n";
542  file << "*/\n";
543 
544  file << "#include \"core/baby.hpp\"\n\n";
545 
546  file << "#include <mutex>\n";
547  file << "#include <type_traits>\n";
548  file << "#include <utility>\n";
549  file << "#include <stdexcept>\n\n";
550 
551  file << "#include \"core/named_func.hpp\"\n";
552  file << "#include \"core/utilities.hpp\"\n\n";
553 
554  file << "using namespace std;\n\n";
555 
556  file << "namespace{\n";
557  file << " using ScalarType = NamedFunc::ScalarType;\n";
558  file << " using VectorType = NamedFunc::VectorType;\n";
559  file << " using ScalarFunc = NamedFunc::ScalarFunc;\n";
560  file << " using VectorFunc = NamedFunc::VectorFunc;\n\n";
561 
562  file << " /*!\\brief Get dummy NamedFunc in case of substitution failure\n\n";
563 
564  file << " \\param[in] name Name of function/variable\n\n";
565 
566  file << " \\return Dummy NamedFunc that always returns 0\n";
567  file << " */\n";
568  file << " template<typename T>\n";
569  file << " NamedFunc GetFunction(T,\n";
570  file << " const string &name){\n";
571  file << " DBG(\"Could not find appropriate type for \\\"\" << name << \".\\\"\");\n";
572  file << " return NamedFunc(name, [](const Baby &){return 0.;}, false);\n";
573  file << " }\n\n";
574 
575  file << " /*!\\brief Get NamedFunc for a function returning a scalar\n\n";
576 
577  file << " \\param[in] baby_func Member function pointer to variable accessor\n\n";
578 
579  file << " \\param[in] name Name of function/variable\n\n";
580 
581  file << " \\return NamedFunc that returns appropriate scalar\n";
582  file << " */\n";
583  file << " template<typename T>\n";
584  file << " NamedFunc GetFunction(T const &(Baby::*baby_func)() const,\n";
585  file << " const string &name){\n";
586  file << " return NamedFunc(name,\n";
587  file << " [baby_func](const Baby &b){\n";
588  file << " return ScalarType((b.*baby_func)());\n";
589  file << " });\n";
590  file << " }\n\n";
591 
592  file << " /*!\\brief Get NamedFunc for a function returning a vector\n\n";
593 
594  file << " \\param[in] baby_func Member function pointer to variable accessor\n\n";
595 
596  file << " \\param[in] name Name of function/variable\n\n";
597 
598  file << " \\return NamedFunc that returns appropriate vectorr\n";
599  file << " */\n";
600  file << " template<typename T>\n";
601  file << " NamedFunc GetFunction(vector<T>* const &(Baby::*baby_func)() const,\n";
602  file << " const string &name){\n";
603  file << " return NamedFunc(name,\n";
604  file << " [baby_func](const Baby &b){\n";
605  file << " const auto &raw = (b.*baby_func)();\n";
606  file << " return VectorType(raw->cbegin(), raw->cend());\n";
607  file << " });\n";
608  file << " }\n\n";
609 
610  bool have_vector_double = false;
611  for(auto var = vars.cbegin(); var != vars.cend() && !have_vector_double; ++var){
612  if(var->Type().find("vector<double>") != string::npos){
613  have_vector_double = true;
614  }
615  }
616 
617  if(have_vector_double){
618  file << " template<>\n";
619  file << " NamedFunc GetFunction<vector<double>* const &(Baby::*)() const>(vector<double>* const &(Baby::*baby_func)() const,\n";
620  file << " const string &name){\n";
621  file << " return NamedFunc(name, [baby_func](const Baby &b){return *((b.*baby_func)());}, true);\n";
622  file << " }\n";
623  }
624  file << "}\n\n";
625 
626  file << "Baby::Activator::Activator(Baby &baby):\n";
627  file << " baby_(baby){\n";
628  file << " baby_.ActivateChain();\n";
629  file << "}\n\n";
630 
631  file << "Baby::Activator::~Activator(){\n";
632  file << " baby_.DeactivateChain();\n";
633  file << "}\n\n";
634 
635  file << "/*!\\brief Standard constructor\n\n";
636 
637  file << " \\param[in] file_names ntuple files to read from\n";
638  file << "*/\n";
639  file << "Baby::Baby(const set<string> &file_names,\n";
640  file << " const set<const Process*> &processes):\n";
641  file << " processes_(processes),\n";
642  file << " chain_(nullptr),\n";
643  file << " file_names_(file_names),\n";
644  file << " total_entries_(0),\n";
645  auto last_base = vars.cbegin();
646  bool found_in_base = false;
647  for(auto iter = vars.cbegin(); iter != vars.cend(); ++iter){
648  if(iter->ImplementInBase()){
649  last_base = iter;
650  found_in_base = true;
651  }
652  }
653  if(vars.size() == 0 || !found_in_base){
654  file << " cached_total_entries_(false){\n";
655  }else{
656  file << " cached_total_entries_(false),\n";
657  for(auto var = vars.cbegin(); var != last_base; ++var){
658  if(!var->ImplementInBase()) continue;
659  file << " " << var->Name() << "_{},\n";
660  file << " b_" << var->Name() << "_(nullptr),\n";
661  file << " c_" << var->Name() << "_(false),\n";
662  }
663  file << " " << last_base->Name() << "_{},\n";
664  file << " b_" << last_base->Name() << "_(nullptr),\n";
665  file << " c_" << last_base->Name() << "_(false){\n";
666  }
667  file << " TString filename=\"\";\n";
668  file << " if(file_names_.size()) filename = *file_names_.cbegin();\n";
669  file << " sample_type_ = SetSampleType(filename);\n";
670  file << "}\n";
671 
672  file << "/*!\\brief Get number of entries in TChain and cache it\n\n";
673 
674  file << " \\return Number of entries in TChain\n";
675  file << "*/\n";
676  file << "long Baby::GetEntries() const{\n";
677  file << " if(!cached_total_entries_){\n";
678  file << " cached_total_entries_ = true;\n";
679  file << " lock_guard<mutex> lock(Multithreading::root_mutex);\n";
680  file << " total_entries_ = chain_->GetEntries();\n";
681  file << " }\n";
682  file << " return total_entries_;\n";
683  file << "}\n\n";
684 
685  file << "/*!\\brief Change current entry\n\n";
686 
687  file << " \\param[in] entry Entry number to load\n";
688  file << "*/\n";
689  file << "void Baby::GetEntry(long entry){\n";
690  for(const auto &var: vars){
691  if(!var.ImplementInBase()) continue;
692  file << " c_" << var.Name() << "_ = false;\n";
693  }
694  file << " lock_guard<mutex> lock(Multithreading::root_mutex);\n";
695  file << " entry_ = chain_->LoadTree(entry);\n";
696  file << "}\n\n";
697 
698  file << "const std::set<std::string> & Baby::FileNames() const{\n";
699  file << " return file_names_;\n";
700  file << "}\n\n";
701 
702  file << "// Return integer with sample type\n";
703  file << "int Baby::SampleType() const{\n";
704  file << " return sample_type_;\n";
705  file << "}\n\n";
706 
707  file << "int Baby::SetSampleType(const TString &filename){\n";
708  file << " int st = 0;\n";
709  file << " if(filename.Contains(\"SMS\")) st = 10;\n";
710  file << " if(filename.Contains(\"_TTJets\")) st = 20;\n";
711  file << " if(filename.Contains(\"_WJets\")) st = 30;\n";
712  file << " if(filename.Contains(\"DYJets\")) st = 40;\n";
713  file << " if(filename.Contains(\"_ZJets\")) st = 41;\n";
714  file << " if(filename.Contains(\"_ST_\")) st = 50;\n";
715  file << " if(filename.Contains(\"_QCD\")) st = 60;\n";
716  file << " if(filename.Contains(\"_TTWJets\"))st = 70;\n";
717  file << " if(filename.Contains(\"_TTZ\")) st = 71;\n";
718  file << " if(filename.Contains(\"_TTG\")) st = 72;\n";
719  file << " return st;\n";
720  file << "}\n\n";
721 
722  file << "/*! \\brief Get underlying TChain for this Baby\n\n";
723 
724  file << " \\return Pointer to underlying TChain\n";
725  file << "*/\n";
726  file << "const unique_ptr<TChain> & Baby::GetTree() const{\n";
727  file << " return chain_;\n";
728  file << "}\n\n";
729 
730  file << "/*! \\brief Get a NamedFunc accessing specified variable\n\n";
731 
732  file << " \\return NamedFunc which returns specified variable from a Baby\n";
733  file << "*/\n";
734  file << "NamedFunc Baby::GetFunction(const std::string &var_name){\n";
735  if(vars.size() != 0){
736  file << " if(var_name == \"" << vars.cbegin()->Name() << "\"){\n";
737  file << " return ::GetFunction(&Baby::" << vars.cbegin()->Name() << ", \"" << vars.cbegin()->Name() << "\");\n";
738  for(auto var = ++vars.cbegin(); var != vars.cend(); ++var){
739  file << " }else if(var_name == \"" << var->Name() << "\"){\n";
740  file << " return ::GetFunction(&Baby::" << var->Name() << ", \"" << var->Name() << "\");\n";
741  }
742  file << " }else{\n";
743  file << " DBG(\"Function lookup failed for \\\"\" << var_name << \"\\\"\");\n";
744  file << " return NamedFunc(var_name,\n";
745  file << " [](const Baby &){\n";
746  file << " return 0.;\n";
747  file << " });\n";
748  file << " }\n";
749  }else{
750  file << " DBG(\"No variables defined in Baby.\");\n";
751  file << " return NamedFunc(var_name,\n";
752  file << " [](const Baby &){\n";
753  file << " return 0.;\n";
754  file << " });\n";
755  }
756  file << "}\n\n";
757 
758  file << "unique_ptr<Baby::Activator> Baby::Activate(){\n";
759  file << " return unique_ptr<Baby::Activator>(new Baby::Activator(*this));\n";
760  file << "}\n\n";
761 
762  file << "/*! \\brief Setup all branches\n";
763  file << "*/\n";
764  file << "void Baby::Initialize(){\n";
765  file << " chain_->SetMakeClass(1);\n";
766  for(const auto &var: vars){
767  if(!var.ImplementInBase()) continue;
768  file << " chain_->SetBranchAddress(\"" << var.Name() << "\", &" << var.Name() << "_, &b_" << var.Name() << "_);\n";
769  }
770  file << "}\n\n";
771 
772  file << "void Baby::ActivateChain(){\n";
773  file << " if(chain_) ERROR(\"Chain has already been initialized\");\n";
774  file << " lock_guard<mutex> lock(Multithreading::root_mutex);\n";
775  file << " chain_ = unique_ptr<TChain>(new TChain(\"tree\"));\n";
776  file << " for(const auto &file: file_names_){\n";
777  file << " chain_->Add(file.c_str());\n";
778  file << " }\n";
779  file << " Initialize();\n";
780  file << "}\n\n";
781 
782  file << "void Baby::DeactivateChain(){\n";
783  file << " lock_guard<mutex> lock(Multithreading::root_mutex);\n";
784  file << " chain_.reset();\n";
785  file << "}\n\n";
786 
787  for(const auto &var: vars){
788  if(!var.ImplementInBase()) continue;
789  file << "/*! \\brief Get " << var.Name() << " for current event and cache it\n\n";
790 
791  file << " \\return " << var.Name() << " for current event\n";
792  file << "*/\n";
793  file << var.DecoratedType() << " const & Baby::" << var.Name() << "() const{\n";
794  file << " if(!c_" << var.Name() << "_ && b_" << var.Name() << "_){\n";
795  file << " b_" << var.Name() << "_->GetEntry(entry_);\n";
796  file << " c_" << var.Name() << "_ = true;\n";
797  file << " }\n";
798  file << " return " << var.Name() << "_;\n";
799  file << "}\n\n";
800  }
801  file << flush;
802  file.close();
803 }
804 
811 void WriteSpecializedHeader(const set<Variable> &vars, const string &type){
812  ofstream file("inc/core/baby_"+type+".hpp");
813  file << "#ifndef H_BABY_" << ToUpper(type) << "\n";
814  file << "#define H_BABY_" << ToUpper(type) << "\n\n";
815 
816  file << "#include \"core/baby.hpp\"\n\n";
817 
818  file << "class Baby_" << type << ": virtual public Baby{\n";
819  file << "public:\n";
820  file << " explicit Baby_" << type << "(const std::set<std::string> &file_names, const std::set<const Process*> &processes = std::set<const Process*>{});\n";
821  file << " virtual ~Baby_" << type << "() = default;\n\n";
822 
823  file << " virtual void GetEntry(long entry);\n\n";
824 
825  for(const auto &var: vars){
826  if(var.VirtualInBase()){
827  if(var.ImplementIn(type)){
828  file << " virtual " << var.DecoratedType() << " const & " << var.Name() << "() const;\n";
829  }else{
830  file << " __attribute__((noreturn)) virtual " << var.DecoratedType()
831  << " const & " << var.Name() << "() const;\n";
832  }
833  }else if(var.EverythingIn(type)){
834  file << " " << var.DecoratedType(type) << " const & " << var.Name() << "() const;\n";
835  }
836  }
837  file << "\n";
838 
839  file << "private:\n";
840  file << " Baby_" << type << "() = delete;\n";
841  file << " Baby_" << type << "(const Baby_" << type << " &) = delete;\n";
842  file << " Baby_" << type << "& operator=(const Baby_" << type << " &) = delete;\n";
843  file << " Baby_" << type << "(Baby_" << type << " &&) = delete;\n";
844  file << " Baby_" << type << "& operator=(Baby_" << type << " &&) = delete;\n";
845 
846  file << " virtual void Initialize();\n\n";
847 
848  for(const auto &var: vars){
849  if(var.ImplementIn(type) || var.EverythingIn(type)){
850  file << " " << var.DecoratedType(type) << " "
851  << var.Name() << "_;//!<Cached value of " << var.Name() << '\n';
852  file << " TBranch *b_" << var.Name() << "_;\n//!<Branch from which "
853  << var.Name() << " is read\n";
854  file << " mutable bool c_" << var.Name() << "_;//!<Flag if cached "
855  << var.Name() << " up to date\n";
856  }
857  }
858  file << "};\n\n";
859 
860  file << "#endif" << endl;
861  file.close();
862 }
863 
871 void WriteSpecializedSource(const set<Variable> &vars, const string &type){
872  ofstream file("src/core/baby_"+type+".cpp");
873  file << "/*! \\class Baby_" << type << "\n\n";
874 
875  file << " \\brief Derived class to access variables in " << type << " format ntuples\n\n";
876 
877  file << " For variables not shared by all ntuple formats, the abstract base class Baby\n";
878  file << " cannot implement functions to get them, and derived classes must do the work.\n";
879  file << " This class implements getter functions for variables in the " << type << " format\n";
880  file << " ntuples, and dummy getters that throw an error for any variable not in " << type;
881  file << " format ntuples.\n";
882  file << "*/\n";
883  file << "#include \"core/baby_" << type << ".hpp\"\n\n";
884 
885  file << "#include \"core/utilities.hpp\"\n\n";
886 
887  file << "using namespace std;\n\n";
888 
889  file << "/*!\\brief Standard constructor\n\n";
890 
891  file << " \\param[in] file_names ntuple files to read from\n";
892  file << "*/\n";
893  file << "Baby_" << type << "::Baby_" << type << "(const set<string> &file_names, const set<const Process*> &processes):\n";
894  int implemented_here = 0;
895  for(const auto & var: vars){
896  if(var.ImplementIn(type) || var.EverythingIn(type)) ++implemented_here;
897  }
898  if(implemented_here == 0){
899  file << " Baby(file_names, processes){\n";
900  }else{
901  file << " Baby(file_names, processes),\n";
902  set<Variable>::const_iterator last = vars.cend();
903  for(auto var = vars.cbegin(); var != vars.cend(); ++var){
904  if(var->ImplementIn(type) || var->EverythingIn(type)){
905  last = var;
906  }
907  }
908  for(auto var = vars.cbegin(); var != vars.cend(); ++var){
909  if(var->ImplementIn(type) || var->EverythingIn(type)){
910  file << " " << var->Name() << "_{},\n";
911  file << " b_" << var->Name() << "_(nullptr),\n";
912  if(var != last){
913  file << " c_" << var->Name() << "_(false),\n";
914  }else{
915  file << " c_" << var->Name() << "_(false){\n";
916  }
917  }
918  }
919  }
920  file << "}\n\n";
921 
922  file << "/*!\\brief Change current entry\n\n";
923 
924  file << " \\param[in] entry Entry number to load\n";
925  file << "*/\n";
926  file << "void Baby_" << type << "::GetEntry(long entry){\n";
927  for(const auto &var: vars){
928  if(var.ImplementIn(type) || var.EverythingIn(type)){
929  file << " c_" << var.Name() << "_ = false;\n";
930  }
931  }
932  file << " Baby::GetEntry(entry);\n";
933  file << "}\n\n";
934 
935  file << "/*! \\brief Setup all branches\n";
936  file << "*/\n";
937  file << "void Baby_" << type << "::Initialize(){\n";
938  file << " Baby::Initialize();\n";
939  for(const auto &var: vars){
940  if(var.ImplementIn(type) || var.EverythingIn(type)){
941  file << " chain_->SetBranchAddress(\"" << var.Name() << "\", &"
942  << var.Name() << "_, &b_" << var.Name() << "_);\n";
943  }
944  }
945  file << "}\n";
946 
947  for(const auto &var: vars){
948  if(var.ImplementIn(type) || var.EverythingIn(type)){
949  file << "/*!\\brief Get " << var.Name() << " for current event and cache it\n\n";
950 
951  file << " \\return " << var.Name() << " for current event\n";
952  file << "*/\n";
953  file << var.DecoratedType(type) << " const & Baby_" << type << "::" << var.Name() << "() const{\n";
954  file << " if(!c_" << var.Name() << "_ && b_" << var.Name() << "_){\n";
955  file << " b_" << var.Name() << "_->GetEntry(entry_);\n";
956  file << " c_" << var.Name() << "_ = true;\n";
957  file << " }\n";
958  file << " return " << var.Name() << "_;\n";
959  file << "}\n\n";
960  }else if(var.VirtualInBase()){
961  file << "/*!\\brief Dummy getter for " << var.Name() << ". Throws error\n\n";
962 
963  file << " \\return Never returns. Throws error.\n";
964  file << "*/\n";
965  file << var.DecoratedType() << " const & Baby_" << type << "::" << var.Name() << "() const{\n";
966  file << " ERROR(\"" << var.DecoratedType() << ' ' << var.Name()
967  << " not available in babies of type " << type << ".\");\n";
968  file << "}\n\n";
969  }
970  }
971 
972  file << flush;
973  file.close();
974 }
bool ImplementIn(const std::string &baby_type) const
Check if variable needs accessor implemented in a derived Baby class.
set< Variable > GetVariables(const set< string > &files)
void WriteSpecializedSource(const set< Variable > &vars, const string &type)
Writes a derived Baby source file.
bool VirtualInBase() const
Check if variable should have pure virtual method in Baby.
bool HasEntry(const std::string &baby_type) const
Check if a derived Baby class has this variable.
SimpleVariable(const std::string &type, const std::string &name)
Standard constructor.
bool EverythingIn(const std::string &baby_type) const
Check if variable needs declaration and definition in a derived class.
bool ImplementInBase() const
Check if variable can be implemented directly in Baby.
std::string type_
Type of variable (e.g., int, float, etc.)
const std::string & Name() const
Get variable name.
void RemoveExtraSpaces(string &line)
Removes leading, trailing, and double spaced from a text line.
#define ERROR(x)
STL namespace.
void SetEntry(const std::string &baby_type, const std::string &type)
Set the type of this variable for use in a derived Baby class.
void WriteBaseSource(const set< Variable > &vars)
Writes src/baby.cpp.
std::set< std::string > GetTypeSet() const
Get all types (int, float, etc.) used across derived Baby classes.
std::string DecoratedType() const
Get type with "std::" and "*" if needed.
bool NotInBase() const
Check if variable is completely absent in base Baby.
Pairs a type and name of a variable accessible via Baby.
std::string Type() const
Get one type for variable across all Baby classes.
bool IsComment(const string &line)
Check if line in variable list file is a comment (blank)
std::map< std::string, std::string > type_map_
Map from Baby type (basic, full, etc.) to variabl type (int, float, etc.)
std::string name_
Name of variable (e.g., ht, met, etc.)
string ToLower(string x)
Replaces all upper case letters with lower case equivalent.
bool operator<(const Variable &other) const
Comparison operator allows storing Variable in set.
void WriteBaseHeader(const set< Variable > &vars, const set< string > &types)
Writes inc/baby.hpp.
Variable(const std::string &name)
Standard constructor.
void WriteSpecializedHeader(const set< Variable > &vars, const string &type)
Writes a derived Baby header file.
std::string name_
Name of variable (e.g., ht, met, etc.)
A variable to be accessible in Baby classes.
string ToUpper(string x)
Replaces all lower case letters with upper case equivalent.
SimpleVariable GetVariable(string line)
Extracts variable type and name from line from variable text files.
int main(int argc, char *argv[])