92int main(
int argc,
char **argv)
97 cout <<
"Usage : " << argv[0] <<
" (file name) (tree name) (class name)" << endl;
101 TFile *infile =
new TFile(argv[1]);
104 Error(
"MakeClass",
"Input file does not exist");
108 TTree *tree = (TTree *)infile->Get(argv[2]);
111 Error(
"MakeClass",
"Input tree does not exist");
115 const char *classname = argv[3];
123 classname = tree->GetName();
126 thead.Form(
"%s.h", classname);
127 FILE *fp = fopen(thead,
"w");
130 Error(
"MakeClass",
"cannot open output file %s", thead.Data());
134 tcimp.Form(
"%s.cxx", classname);
135 FILE *fpc = fopen(tcimp,
"w");
138 Error(
"MakeClass",
"cannot open output file %s", tcimp.Data());
143 if (tree->GetDirectory() && tree->GetDirectory()->GetFile())
145 treefile = tree->GetDirectory()->GetFile()->GetName();
149 treefile =
"Memory Directory";
154 Bool_t ischain = tree->InheritsFrom(TChain::Class());
155 Bool_t isHbook = tree->InheritsFrom(
"THbookTree");
157 treefile = tree->GetTitle();
161 TObjArray *leaves = tree->GetListOfLeaves();
162 Int_t nleaves = leaves ? leaves->GetEntriesFast() : 0;
164 fprintf(fp,
"//////////////////////////////////////////////////////////\n");
165 fprintf(fp,
"// This class has been automatically generated on\n");
166 fprintf(fp,
"// %s by ROOT version %s\n", td.AsString(), gROOT->GetVersion());
169 fprintf(fp,
"// from TTree %s/%s\n", tree->GetName(), tree->GetTitle());
170 fprintf(fp,
"// found on file: %s\n", treefile.Data());
174 fprintf(fp,
"// from TChain %s/%s\n", tree->GetName(), tree->GetTitle());
176 fprintf(fp,
"//////////////////////////////////////////////////////////\n");
178 fprintf(fp,
"#pragma once\n");
180 fprintf(fp,
"#include \"NAGASH/NAGASH.h\"\n");
244 Int_t *leaflen =
new Int_t[nleaves];
245 TObjArray *leafs =
new TObjArray(nleaves);
246 for (l = 0; l < nleaves; l++)
248 TLeaf *leaf = (TLeaf *)leaves->UncheckedAt(l);
249 leafs->AddAt(
new TObjString(leaf->GetName()), l);
250 leaflen[l] = leaf->GetMaximum();
257 TChain *chain = (TChain *)tree;
258 Int_t ntrees = chain->GetNtrees();
259 for (Int_t file = 0; file < ntrees; file++)
261 Long64_t first = chain->GetTreeOffset()[file];
262 chain->LoadTree(first);
263 for (l = 0; l < nleaves; l++)
265 TObjString *obj = (TObjString *)leafs->At(l);
266 TLeaf *leaf = chain->GetLeaf(obj->GetName());
269 leaflen[l] = TMath::Max(leaflen[l], leaf->GetMaximum());
277 if (opt.Contains(
"selector"))
279 fprintf(fp,
"class %s : public TSelector {\n", classname);
280 fprintf(fp,
"public :\n");
281 fprintf(fp,
" TTree *fChain; //!pointer to the analyzed TTree or TChain\n");
285 fprintf(fp,
"class %s : public NAGASH::LoopEvent{\n", classname);
286 fprintf(fp,
"public :\n");
287 fprintf(fp,
" %s(const NAGASH::ConfigTool &c) : NAGASH::LoopEvent(c) {} // Constructor\n", classname);
288 fprintf(fp,
" virtual NAGASH::StatusCode InitializeData() override;\n");
289 fprintf(fp,
" virtual NAGASH::StatusCode InitializeUser() override;\n");
290 fprintf(fp,
" virtual NAGASH::StatusCode Execute() override;\n");
291 fprintf(fp,
" virtual NAGASH::StatusCode Finalize() override;\n");
294 fprintf(fp,
"\n// Fixed size dimensions of array or collections stored in the TTree if any.\n");
295 leaves = tree->GetListOfLeaves();
296 for (l = 0; l < nleaves; l++)
298 TLeaf *leaf = (TLeaf *)leaves->UncheckedAt(l);
299 strlcpy(blen, leaf->GetName(),
sizeof(blen));
316 if (blen[lenb - 1] ==
'_')
322 fprintf(fp,
" static constexpr Int_t kMax%s = %d;\n", blen, len);
330 fprintf(fp,
"\n // Declaration of leaf types\n");
332 TLeafObject *leafobj;
333 TBranchElement *bre = 0;
334 const char *headOK =
" ";
335 const char *headcom =
" //";
337 char branchname[1024];
339 TObjArray branches(100);
340 TObjArray mustInit(100);
341 TObjArray mustInitArr(100);
342 mustInitArr.SetOwner(kFALSE);
343 Int_t *leafStatus =
new Int_t[nleaves];
344 for (l = 0; l < nleaves; l++)
349 TLeaf *leaf = (TLeaf *)leaves->UncheckedAt(l);
350 len = leaf->GetLen();
353 leafcount = leaf->GetLeafCount();
354 TBranch *branch = leaf->GetBranch();
356 strlcpy(branchname, branch->GetName(),
sizeof(branchname));
357 strlcpy(aprefix, branch->GetName(),
sizeof(aprefix));
358 if (!branches.FindObject(branch))
359 branches.Add(branch);
362 if (branch->GetNleaves() > 1)
365 strlcat(branchname,
".",
sizeof(branchname));
366 strlcat(branchname, leaf->GetTitle(),
sizeof(branchname));
370 char *dim = (
char *)strstr(branchname,
"[");
377 strlcpy(branchname, branch->GetName(),
sizeof(branchname));
379 char *twodim = (
char *)strstr(leaf->GetTitle(),
"][");
395 if (branch->IsA() == TBranchObject::Class())
397 if (branch->GetListOfBranches()->GetEntriesFast())
402 leafobj = (TLeafObject *)leaf;
403 if (!leafobj->GetClass())
408 auto ModifiedType =
AddStdPrefix(leafobj->GetTypeName());
409 fprintf(fp,
"%s%-15s *%s;\n", head, ModifiedType.Data(), leafobj->GetName());
410 if (leafStatus[l] == 0)
411 mustInit.Add(leafobj);
416 len = leafcount->GetMaximum();
419 strlcpy(blen, leafcount->GetName(),
sizeof(blen));
436 if (blen[lenb - 1] ==
'_')
442 snprintf(blen,
sizeof(blen),
"%d", len);
444 if (branch->IsA() == TBranchElement::Class())
446 bre = (TBranchElement *)branch;
447 if (bre->GetType() != 3 && bre->GetType() != 4 && bre->GetStreamerType() <= 0 && bre->GetListOfBranches()->GetEntriesFast())
451 if (bre->GetType() == 3 || bre->GetType() == 4)
453 fprintf(fp,
" %-15s %s_;\n",
"Int_t", branchname);
456 if (bre->IsBranchFolder())
459 fprintf(fp,
" %-15s *%s;\n", ModifiedType.Data(), branchname);
465 if (branch->GetListOfBranches()->GetEntriesFast())
470 if (bre->GetStreamerType() < 0)
472 if (branch->GetListOfBranches()->GetEntriesFast())
475 fprintf(fp,
"%s%-15s *%s;\n", headcom, ModifiedType.Data(), branchname);
480 fprintf(fp,
"%s%-15s *%s;\n", head, ModifiedType.Data(), branchname);
485 if (bre->GetStreamerType() == 0)
487 if (!TClass::GetClass(bre->GetClassName())->HasInterpreterInfo())
493 fprintf(fp,
"%s%-15s *%s;\n", head, ModifiedType.Data(), branchname);
494 if (leafStatus[l] == 0)
498 if (bre->GetStreamerType() > 60)
500 TClass *cle = TClass::GetClass(bre->GetClassName());
506 if (bre->GetStreamerType() == 66)
509 strlcpy(brename, bre->GetName(), 255);
510 char *bren = brename;
511 char *adot = strrchr(bren,
'.');
514 char *brack = strchr(bren,
'[');
517 TStreamerElement *elem = (TStreamerElement *)cle->GetStreamerInfo()->GetElements()->FindObject(bren);
520 if (elem->IsA() == TStreamerBase::Class())
525 if (!TClass::GetClass(elem->GetTypeName()))
530 if (!TClass::GetClass(elem->GetTypeName())->HasInterpreterInfo())
538 fprintf(fp,
"%s%-15s %s[kMax%s];\n", head, ModifiedType.Data(), branchname, blen);
543 fprintf(fp,
"%s%-15s %s;\n", head, ModifiedType.Data(), branchname);
548 if (!TClass::GetClass(bre->GetClassName())->HasInterpreterInfo())
554 fprintf(fp,
"%s%-15s %s;\n", head, ModifiedType.Data(), branchname);
559 if (strlen(leaf->GetTypeName()) == 0)
575 const char *stars =
" ";
576 if (bre && bre->GetBranchCount2())
583 char *dimInName = (
char *)strstr(branchname,
"[");
584 if (twodim || dimInName)
588 dimensions = dimInName;
592 dimensions += (
char *)(twodim + 1);
594 const char *leafcountName = leafcount->GetName();
596 if (bre && bre->GetBranchCount2())
598 TLeaf *l2 = (TLeaf *)bre->GetBranchCount2()->GetListOfLeaves()->At(0);
599 strlcpy(b2len, l2->GetName(),
sizeof(b2len));
615 leafcountName = b2len;
617 if (dimensions.Length())
622 fprintf(fp,
" %-14s %s%s[kMax%s]%s; //[%s]\n", ModifiedType.Data(), stars,
623 branchname, blen, dimensions.Data(), leafcountName);
628 fprintf(fp,
" %-14s %s%s[%d]%s; //[%s]\n", ModifiedType.Data(), stars,
629 branchname, len, dimensions.Data(), leafcountName);
637 fprintf(fp,
" %-14s %s%s[kMax%s]; //[%s]\n", ModifiedType.Data(), stars, branchname, blen, leafcountName);
642 fprintf(fp,
" %-14s %s%s[%d]; //[%s]\n", ModifiedType.Data(), stars, branchname, len, leafcountName);
649 n =
new TNamed(branchname, Form(
"kMax%s", blen));
651 n =
new TNamed(branchname, Form(
"%d", len));
657 if (strstr(branchname,
"["))
662 fprintf(fp,
" %-15s %s;\n", ModifiedType.Data(), branchname);
669 fprintf(fp,
" %-15s %s%s;\n", ModifiedType.Data(), branchname, (
char *)strstr(leaf->GetTitle(),
"["));
674 fprintf(fp,
" %-15s %s[%d];\n", ModifiedType.Data(), branchname, len);
682 fprintf(fp,
" // List of branches\n");
683 for (l = 0; l < nleaves; l++)
687 TLeaf *leaf = (TLeaf *)leaves->UncheckedAt(l);
692 if (opt.Contains(
"selector"))
695 fprintf(fp,
" %s(TTree * /*tree*/ =0) : fChain(0) { }\n", classname);
696 fprintf(fp,
" virtual ~%s() { }\n", classname);
697 fprintf(fp,
" virtual Int_t Version() const { return 2; }\n");
698 fprintf(fp,
" virtual void Begin(TTree *tree);\n");
699 fprintf(fp,
" virtual void SlaveBegin(TTree *tree);\n");
700 fprintf(fp,
" virtual void Init(TTree *tree);\n");
701 fprintf(fp,
" virtual Bool_t Notify();\n");
702 fprintf(fp,
" virtual Bool_t Process(Long64_t entry);\n");
703 fprintf(fp,
" virtual Int_t GetEntry(Long64_t entry, Int_t getall = 0) { return fChain ? fChain->GetTree()->GetEntry(entry, getall) : 0; }\n");
704 fprintf(fp,
" virtual void SetOption(const char *option) { fOption = option; }\n");
705 fprintf(fp,
" virtual void SetObject(TObject *obj) { fObject = obj; }\n");
706 fprintf(fp,
" virtual void SetInputList(TList *input) { fInput = input; }\n");
707 fprintf(fp,
" virtual TList *GetOutputList() const { return fOutput; }\n");
708 fprintf(fp,
" virtual void SlaveTerminate();\n");
709 fprintf(fp,
" virtual void Terminate();\n\n");
710 fprintf(fp,
" ClassDef(%s,0);\n", classname);
717 fprintf(fp,
"private:\n");
718 fprintf(fp,
"// here user can define their own variables\n\n");
719 fprintf(fp,
"};\n\n");
841 fprintf(fp,
"inline NAGASH::StatusCode %s::InitializeData()\n", classname);
843 fprintf(fp,
" // The InitializeData() function is used to open ROOT file, get TTree into\n"
844 " // RootTreeUser. And call TTree::SetBranchAddress to set the address of variables\n"
845 " // User need not to modify this function.\n\n");
846 fprintf(fp,
" RootFileUser()->GetObject(\"%s\", RootTreeUser());\n", argv[2]);
847 fprintf(fp,
" if (RootTreeUser() == nullptr)\n");
849 fprintf(fp,
" MSGUser()->MSG(NAGASH::MSGLevel::ERROR,\"Wrong TTree name\");\n");
850 fprintf(fp,
" return NAGASH::StatusCode::FAILURE;\n");
851 fprintf(fp,
" }\n\n");
854 TIter next(&mustInit);
856 fprintf(fp,
" // Set object pointer\n");
857 while ((obj = next()))
859 if (obj->InheritsFrom(TBranch::Class()))
861 strlcpy(branchname, ((TBranch *)obj)->GetName(),
sizeof(branchname));
863 else if (obj->InheritsFrom(TLeaf::Class()))
865 strlcpy(branchname, ((TLeaf *)obj)->GetName(),
sizeof(branchname));
867 branchname[1023] = 0;
883 fprintf(fp,
" %s = 0;\n", branchname);
886 if (mustInitArr.Last())
888 TIter next(&mustInitArr);
890 fprintf(fp,
" // Set array pointer\n");
891 while ((info = (TNamed *)next()))
893 fprintf(fp,
" for(int i=0; i<%s; ++i) %s[i] = 0;\n", info->GetTitle(), info->GetName());
897 fprintf(fp,
" // Set branch addresses and branch pointers\n");
906 for (l = 0; l < nleaves; l++)
910 TLeaf *leaf = (TLeaf *)leaves->UncheckedAt(l);
911 len = leaf->GetLen();
912 leafcount = leaf->GetLeafCount();
913 TBranch *branch = leaf->GetBranch();
914 strlcpy(aprefix, branch->GetName(),
sizeof(aprefix));
916 if (branch->GetNleaves() > 1)
919 strlcpy(branchname, branch->GetName(),
sizeof(branchname));
920 strlcat(branchname,
".",
sizeof(branchname));
921 strlcat(branchname, leaf->GetTitle(),
sizeof(branchname));
925 char *dim = (
char *)strstr(branchname,
"[");
932 strlcpy(branchname, branch->GetName(),
sizeof(branchname));
933 if (branch->IsA() == TBranchElement::Class())
935 bre = (TBranchElement *)branch;
936 if (bre->GetType() == 3 || bre->GetType() == 4)
937 strlcat(branchname,
"_",
sizeof(branchname));
941 char *brak = strstr(branchname,
"[");
944 char *twodim = (
char *)strstr(bname,
"[");
961 const char *maybedisable =
"";
962 if (branch != tree->GetBranch(branch->GetName()))
964 Error(
"MakeClass",
"The branch named %s (full path name: %s) is hidden by another branch of the same name and its data will not be loaded.", branch->GetName(),
R__GetBranchPointerName(leaf, kFALSE).Data());
965 maybedisable =
"// ";
967 if (branch->IsA() == TBranchObject::Class())
969 if (branch->GetListOfBranches()->GetEntriesFast())
971 fprintf(fp,
"%s RootTreeUser()->SetBranchAddress(\"%s\",(void*)-1,&b_%s);\n", maybedisable, branch->GetName(),
R__GetBranchPointerName(leaf).Data());
974 strlcpy(branchname, branch->GetName(),
sizeof(branchname));
976 if (branch->IsA() == TBranchElement::Class())
978 if (((TBranchElement *)branch)->GetType() == 3)
980 if (((TBranchElement *)branch)->GetType() == 4)
984 len = leafcount->GetMaximum() + 1;
986 fprintf(fp,
"%s RootTreeUser()->SetBranchAddress(\"%s\", %s, &b_%s);\n",
989 fprintf(fp,
"%s RootTreeUser()->SetBranchAddress(\"%s\", &%s, &b_%s);\n",
1001 fprintf(fp,
" return NAGASH::StatusCode::SUCCESS;\n");
1046 if (!opt.Contains(
"selector"))
1049 fprintf(fpc,
"#include \"%s.h\"\n", classname);
1051 fprintf(fpc,
"// User can use \"using namespace NAGASH;\" to avoid extra work.\n\n");
1052 fprintf(fpc,
"NAGASH::StatusCode %s::InitializeUser()\n", classname);
1053 fprintf(fpc,
"{\n");
1054 fprintf(fpc,
" // In this function, User can initialize their own variables, e.g. PlotGroup\n");
1055 fprintf(fpc,
" return NAGASH::StatusCode::SUCCESS;\n");
1056 fprintf(fpc,
"}\n\n");
1058 fprintf(fpc,
"NAGASH::StatusCode %s::Execute()\n", classname);
1059 fprintf(fpc,
"{\n");
1060 fprintf(fpc,
" // In this function, User do what they want for each entry in the TTree\n");
1061 fprintf(fpc,
" return NAGASH::StatusCode::SUCCESS;\n");
1062 fprintf(fpc,
"}\n\n");
1064 fprintf(fpc,
"NAGASH::StatusCode %s::Finalize()\n", classname);
1065 fprintf(fpc,
"{\n");
1066 fprintf(fpc,
" // In this function, User can do something after process the entries in a single file\n");
1067 fprintf(fpc,
" return NAGASH::StatusCode::SUCCESS;\n");
1068 fprintf(fpc,
"}\n\n");
1070 if (opt.Contains(
"selector"))
1073 fprintf(fpc,
"#define %s_cxx\n", classname);
1074 fprintf(fpc,
"// The class definition in %s.h has been generated automatically\n", classname);
1075 fprintf(fpc,
"// by the ROOT utility TTree::MakeSelector(). This class is derived\n");
1076 fprintf(fpc,
"// from the ROOT class TSelector. For more information on the TSelector\n"
1077 "// framework see $ROOTSYS/README/README.SELECTOR or the ROOT User Manual.\n\n");
1078 fprintf(fpc,
"// The following methods are defined in this file:\n");
1079 fprintf(fpc,
"// Begin(): called every time a loop on the tree starts,\n");
1080 fprintf(fpc,
"// a convenient place to create your histograms.\n");
1081 fprintf(fpc,
"// SlaveBegin(): called after Begin(), when on PROOF called only on the\n"
1082 "// slave servers.\n");
1083 fprintf(fpc,
"// Process(): called for each event, in this function you decide what\n");
1084 fprintf(fpc,
"// to read and fill your histograms.\n");
1085 fprintf(fpc,
"// SlaveTerminate: called at the end of the loop on the tree, when on PROOF\n"
1086 "// called only on the slave servers.\n");
1087 fprintf(fpc,
"// Terminate(): called at the end of the loop on the tree,\n");
1088 fprintf(fpc,
"// a convenient place to draw/fit your histograms.\n");
1089 fprintf(fpc,
"//\n");
1090 fprintf(fpc,
"// To use this file, try the following session on your Tree T:\n");
1091 fprintf(fpc,
"//\n");
1092 fprintf(fpc,
"// root> T->Process(\"%s.C\")\n", classname);
1093 fprintf(fpc,
"// root> T->Process(\"%s.C\",\"some options\")\n", classname);
1094 fprintf(fpc,
"// root> T->Process(\"%s.C+\")\n", classname);
1095 fprintf(fpc,
"//\n\n");
1096 fprintf(fpc,
"#include \"%s\"\n", thead.Data());
1097 fprintf(fpc,
"#include <TH2.h>\n");
1098 fprintf(fpc,
"#include <TStyle.h>\n");
1102 fprintf(fpc,
"void %s::Begin(TTree * /*tree*/)\n", classname);
1103 fprintf(fpc,
"{\n");
1104 fprintf(fpc,
" // The Begin() function is called at the start of the query.\n");
1105 fprintf(fpc,
" // When running with PROOF Begin() is only called on the client.\n");
1106 fprintf(fpc,
" // The tree argument is deprecated (on PROOF 0 is passed).\n");
1108 fprintf(fpc,
" TString option = GetOption();\n");
1110 fprintf(fpc,
"}\n");
1113 fprintf(fpc,
"void %s::SlaveBegin(TTree * /*tree*/)\n", classname);
1114 fprintf(fpc,
"{\n");
1115 fprintf(fpc,
" // The SlaveBegin() function is called after the Begin() function.\n");
1116 fprintf(fpc,
" // When running with PROOF SlaveBegin() is called on each slave server.\n");
1117 fprintf(fpc,
" // The tree argument is deprecated (on PROOF 0 is passed).\n");
1119 fprintf(fpc,
" TString option = GetOption();\n");
1121 fprintf(fpc,
"}\n");
1124 fprintf(fpc,
"Bool_t %s::Process(Long64_t entry)\n", classname);
1125 fprintf(fpc,
"{\n");
1126 fprintf(fpc,
" // The Process() function is called for each entry in the tree (or possibly\n"
1127 " // keyed object in the case of PROOF) to be processed. The entry argument\n"
1128 " // specifies which entry in the currently loaded tree is to be processed.\n"
1129 " // It can be passed to either %s::GetEntry() or TBranch::GetEntry()\n"
1130 " // to read either all or the required parts of the data. When processing\n"
1131 " // keyed objects with PROOF, the object is already loaded and is available\n"
1132 " // via the fObject pointer.\n"
1134 " // This function should contain the \"body\" of the analysis. It can contain\n"
1135 " // simple or elaborate selection criteria, run algorithms on the data\n"
1136 " // of the event and typically fill histograms.\n"
1138 " // The processing can be stopped by calling Abort().\n"
1140 " // Use fStatus to set the return value of TTree::Process().\n"
1142 " // The return value is currently not used.\n\n",
1145 fprintf(fpc,
" return kTRUE;\n");
1146 fprintf(fpc,
"}\n");
1149 fprintf(fpc,
"void %s::SlaveTerminate()\n", classname);
1150 fprintf(fpc,
"{\n");
1151 fprintf(fpc,
" // The SlaveTerminate() function is called after all entries or objects\n"
1152 " // have been processed. When running with PROOF SlaveTerminate() is called\n"
1153 " // on each slave server.");
1156 fprintf(fpc,
"}\n");
1159 fprintf(fpc,
"void %s::Terminate()\n", classname);
1160 fprintf(fpc,
"{\n");
1161 fprintf(fpc,
" // The Terminate() function is the last function to be called during\n"
1162 " // a query. It always runs on the client, it can be used to present\n"
1163 " // the results graphically or save the results to file.");
1166 fprintf(fpc,
"}\n");
1168 Info(
"MakeClass",
"Files: %s and %s generated from TTree: %s", thead.Data(), tcimp.Data(), tree->GetName());
1169 delete[] leafStatus;