NAGASH 0.9.8
Next Generation Analysis System
Loading...
Searching...
No Matches
NAGASHMakeClass.cxx
Go to the documentation of this file.
1// Generate LoopEvent Class under NAGASH Framework
2// Similar to TTree::MakeClass
3// Modified by : Wenhao Ma
4#include "NAGASH/Global.h"
5
6#include "TLeaf.h"
7#include "TLeafObject.h"
8#include "TObjString.h"
9#include "TBranch.h"
10#include "TBranchElement.h"
11#include "TBranchObject.h"
12#include "TChainElement.h"
13#include "TStreamerElement.h"
14
15using namespace std;
16
17// Return the name of the branch pointer needed by MakeClass
18static TString R__GetBranchPointerName(TLeaf *leaf, Bool_t replace = kTRUE)
19{
20 TLeaf *leafcount = leaf->GetLeafCount();
21 TBranch *branch = leaf->GetBranch();
22
23 TString branchname(branch->GetName());
24
25 if (branch->GetNleaves() <= 1)
26 {
27 if (branch->IsA() != TBranchObject::Class())
28 {
29 if (!leafcount)
30 {
31 TBranch *mother = branch->GetMother();
32 const char *ltitle = leaf->GetTitle();
33 if (mother && mother != branch)
34 {
35 branchname = mother->GetName();
36 if (branchname[branchname.Length() - 1] != '.')
37 {
38 branchname += ".";
39 }
40 if (strncmp(branchname.Data(), ltitle, branchname.Length()) == 0)
41 {
42 branchname = "";
43 }
44 }
45 else
46 {
47 branchname = "";
48 }
49 branchname += ltitle;
50 }
51 }
52 }
53 if (replace)
54 {
55 char *bname = (char *)branchname.Data();
56 char *twodim = (char *)strstr(bname, "[");
57 if (twodim)
58 *twodim = 0;
59 while (*bname)
60 {
61 if (*bname == '.')
62 *bname = '_';
63 if (*bname == ',')
64 *bname = '_';
65 if (*bname == ':')
66 *bname = '_';
67 if (*bname == '<')
68 *bname = '_';
69 if (*bname == '>')
70 *bname = '_';
71 bname++;
72 }
73 }
74 return branchname;
75}
76
77// add std:: to STL container type
78// It's weird that ROOT did nothing on this
79TString AddStdPrefix(const char *TypeName)
80{
81 TString type(TypeName);
82 type.ReplaceAll("string", "std::string");
83 type.ReplaceAll("vector", "std::vector");
84 type.ReplaceAll("list", "std::list");
85 type.ReplaceAll("deque", "std::deque");
86 type.ReplaceAll("set", "std::set");
87 type.ReplaceAll("multiset", "std::multiset");
88
89 return type;
90}
91
92int main(int argc, char **argv)
93{
94 // initial tree
95 if (argc != 4)
96 {
97 cout << "Usage : " << argv[0] << " (file name) (tree name) (class name)" << endl;
98 return -1;
99 }
100
101 TFile *infile = new TFile(argv[1]);
102 if (!infile)
103 {
104 Error("MakeClass", "Input file does not exist");
105 return -1;
106 }
107
108 TTree *tree = (TTree *)infile->Get(argv[2]);
109 if (!tree)
110 {
111 Error("MakeClass", "Input tree does not exist");
112 return -1;
113 }
114
115 const char *classname = argv[3];
116
117 // the following code are modified from TTreePlayer::MakeClass
118 TString opt = "";
119 opt.ToLower();
120
121 // Connect output files
122 if (!classname)
123 classname = tree->GetName();
124
125 TString thead;
126 thead.Form("%s.h", classname);
127 FILE *fp = fopen(thead, "w");
128 if (!fp)
129 {
130 Error("MakeClass", "cannot open output file %s", thead.Data());
131 return 3;
132 }
133 TString tcimp;
134 tcimp.Form("%s.cxx", classname);
135 FILE *fpc = fopen(tcimp, "w");
136 if (!fpc)
137 {
138 Error("MakeClass", "cannot open output file %s", tcimp.Data());
139 fclose(fp);
140 return 3;
141 }
142 TString treefile;
143 if (tree->GetDirectory() && tree->GetDirectory()->GetFile())
144 {
145 treefile = tree->GetDirectory()->GetFile()->GetName();
146 }
147 else
148 {
149 treefile = "Memory Directory";
150 }
151 // In the case of a chain, the GetDirectory information usually does
152 // pertain to the Chain itself but to the currently loaded tree.
153 // So we can not rely on it.
154 Bool_t ischain = tree->InheritsFrom(TChain::Class());
155 Bool_t isHbook = tree->InheritsFrom("THbookTree");
156 if (isHbook)
157 treefile = tree->GetTitle();
158
159 //======================Generate classname.h=====================
160 // Print header
161 TObjArray *leaves = tree->GetListOfLeaves();
162 Int_t nleaves = leaves ? leaves->GetEntriesFast() : 0;
163 TDatime td;
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());
167 if (!ischain)
168 {
169 fprintf(fp, "// from TTree %s/%s\n", tree->GetName(), tree->GetTitle());
170 fprintf(fp, "// found on file: %s\n", treefile.Data());
171 }
172 else
173 {
174 fprintf(fp, "// from TChain %s/%s\n", tree->GetName(), tree->GetTitle());
175 }
176 fprintf(fp, "//////////////////////////////////////////////////////////\n");
177 fprintf(fp, "\n");
178 fprintf(fp, "#pragma once\n");
179 fprintf(fp, "\n");
180 fprintf(fp, "#include \"NAGASH/NAGASH.h\"\n");
181 // fprintf(fp, "using namespace std; // I don't know why ROOT generated this file without std:: prefix on STL objects");
182
183 /*
184 if (isHbook)
185 fprintf(fp, "#include <THbookFile.h>\n");
186 if (opt.Contains("selector"))
187 fprintf(fp, "#include <TSelector.h>\n");
188 */
189
190 // See if we can add any #include about the user data.
191 Int_t l;
192 /*
193 fprintf(fp, "\n// Header file for the classes stored in the TTree if any.\n");
194 TList listOfHeaders;
195 listOfHeaders.SetOwner();
196 for (l = 0; l < nleaves; l++)
197 {
198 TLeaf *leaf = (TLeaf *)leaves->UncheckedAt(l);
199 TBranch *branch = leaf->GetBranch();
200 TClass *cl = TClass::GetClass(branch->GetClassName());
201 if (cl && cl->IsLoaded() && !listOfHeaders.FindObject(cl->GetName()))
202 {
203 const char *declfile = cl->GetDeclFileName();
204 if (declfile && declfile[0])
205 {
206 static const char *precstl = "prec_stl/";
207 static const unsigned int precstl_len = strlen(precstl);
208 static const char *rootinclude = "include/";
209 static const unsigned int rootinclude_len = strlen(rootinclude);
210 if (strncmp(declfile, precstl, precstl_len) == 0)
211 {
212 fprintf(fp, "#include <%s>\n", declfile + precstl_len);
213 listOfHeaders.Add(new TNamed(cl->GetName(), declfile + precstl_len));
214 }
215 else if (strncmp(declfile, "/usr/include/", 13) == 0)
216 {
217 fprintf(fp, "#include <%s>\n", declfile + strlen("/include/c++/"));
218 listOfHeaders.Add(new TNamed(cl->GetName(), declfile + strlen("/include/c++/")));
219 }
220 else if (strstr(declfile, "/include/c++/") != 0)
221 {
222 fprintf(fp, "#include <%s>\n", declfile + strlen("/include/c++/"));
223 listOfHeaders.Add(new TNamed(cl->GetName(), declfile + strlen("/include/c++/")));
224 }
225 else if (strncmp(declfile, rootinclude, rootinclude_len) == 0)
226 {
227 fprintf(fp, "#include <%s>\n", declfile + rootinclude_len);
228 listOfHeaders.Add(new TNamed(cl->GetName(), declfile + rootinclude_len));
229 }
230 else
231 {
232 fprintf(fp, "#include \"%s\"\n", declfile);
233 listOfHeaders.Add(new TNamed(cl->GetName(), declfile));
234 }
235 }
236 }
237 }
238 */
239
240 // First loop on all leaves to generate dimension declarations
241 Int_t len, lenb;
242 char blen[1024];
243 char *bname;
244 Int_t *leaflen = new Int_t[nleaves];
245 TObjArray *leafs = new TObjArray(nleaves);
246 for (l = 0; l < nleaves; l++)
247 {
248 TLeaf *leaf = (TLeaf *)leaves->UncheckedAt(l);
249 leafs->AddAt(new TObjString(leaf->GetName()), l);
250 leaflen[l] = leaf->GetMaximum();
251 }
252 if (ischain)
253 {
254 // In case of a chain, one must find the maximum dimension of each leaf
255 // One must be careful and not assume that all Trees in the chain
256 // have the same leaves and in the same order!
257 TChain *chain = (TChain *)tree;
258 Int_t ntrees = chain->GetNtrees();
259 for (Int_t file = 0; file < ntrees; file++)
260 {
261 Long64_t first = chain->GetTreeOffset()[file];
262 chain->LoadTree(first);
263 for (l = 0; l < nleaves; l++)
264 {
265 TObjString *obj = (TObjString *)leafs->At(l);
266 TLeaf *leaf = chain->GetLeaf(obj->GetName());
267 if (leaf)
268 {
269 leaflen[l] = TMath::Max(leaflen[l], leaf->GetMaximum());
270 }
271 }
272 }
273 chain->LoadTree(0);
274 }
275
276 fprintf(fp, "\n");
277 if (opt.Contains("selector"))
278 {
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");
282 }
283 else
284 {
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");
292 }
293
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++)
297 {
298 TLeaf *leaf = (TLeaf *)leaves->UncheckedAt(l);
299 strlcpy(blen, leaf->GetName(), sizeof(blen));
300 bname = &blen[0];
301 while (*bname)
302 {
303 if (*bname == '.')
304 *bname = '_';
305 if (*bname == ',')
306 *bname = '_';
307 if (*bname == ':')
308 *bname = '_';
309 if (*bname == '<')
310 *bname = '_';
311 if (*bname == '>')
312 *bname = '_';
313 bname++;
314 }
315 lenb = strlen(blen);
316 if (blen[lenb - 1] == '_')
317 {
318 blen[lenb - 1] = 0;
319 len = leaflen[l];
320 if (len <= 0)
321 len = 1;
322 fprintf(fp, " static constexpr Int_t kMax%s = %d;\n", blen, len);
323 }
324 }
325 delete[] leaflen;
326 leafs->Delete();
327 delete leafs;
328
329 // second loop on all leaves to generate type declarations
330 fprintf(fp, "\n // Declaration of leaf types\n");
331 TLeaf *leafcount;
332 TLeafObject *leafobj;
333 TBranchElement *bre = 0;
334 const char *headOK = " ";
335 const char *headcom = " //";
336 const char *head;
337 char branchname[1024];
338 char aprefix[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++)
345 {
346 Int_t kmax = 0;
347 head = headOK;
348 leafStatus[l] = 0;
349 TLeaf *leaf = (TLeaf *)leaves->UncheckedAt(l);
350 len = leaf->GetLen();
351 if (len <= 0)
352 len = 1;
353 leafcount = leaf->GetLeafCount();
354 TBranch *branch = leaf->GetBranch();
355 branchname[0] = 0;
356 strlcpy(branchname, branch->GetName(), sizeof(branchname));
357 strlcpy(aprefix, branch->GetName(), sizeof(aprefix));
358 if (!branches.FindObject(branch))
359 branches.Add(branch);
360 else
361 leafStatus[l] = 1;
362 if (branch->GetNleaves() > 1)
363 {
364 // More than one leaf for the branch we need to distinguish them
365 strlcat(branchname, ".", sizeof(branchname));
366 strlcat(branchname, leaf->GetTitle(), sizeof(branchname));
367 if (leafcount)
368 {
369 // remove any dimension in title
370 char *dim = (char *)strstr(branchname, "[");
371 if (dim)
372 dim[0] = 0;
373 }
374 }
375 else
376 {
377 strlcpy(branchname, branch->GetName(), sizeof(branchname));
378 }
379 char *twodim = (char *)strstr(leaf->GetTitle(), "][");
380 bname = branchname;
381 while (*bname)
382 {
383 if (*bname == '.')
384 *bname = '_';
385 if (*bname == ',')
386 *bname = '_';
387 if (*bname == ':')
388 *bname = '_';
389 if (*bname == '<')
390 *bname = '_';
391 if (*bname == '>')
392 *bname = '_';
393 bname++;
394 }
395 if (branch->IsA() == TBranchObject::Class())
396 {
397 if (branch->GetListOfBranches()->GetEntriesFast())
398 {
399 leafStatus[l] = 1;
400 continue;
401 }
402 leafobj = (TLeafObject *)leaf;
403 if (!leafobj->GetClass())
404 {
405 leafStatus[l] = 1;
406 head = headcom;
407 }
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);
412 continue;
413 }
414 if (leafcount)
415 {
416 len = leafcount->GetMaximum();
417 if (len <= 0)
418 len = 1;
419 strlcpy(blen, leafcount->GetName(), sizeof(blen));
420 bname = &blen[0];
421 while (*bname)
422 {
423 if (*bname == '.')
424 *bname = '_';
425 if (*bname == ',')
426 *bname = '_';
427 if (*bname == ':')
428 *bname = '_';
429 if (*bname == '<')
430 *bname = '_';
431 if (*bname == '>')
432 *bname = '_';
433 bname++;
434 }
435 lenb = strlen(blen);
436 if (blen[lenb - 1] == '_')
437 {
438 blen[lenb - 1] = 0;
439 kmax = 1;
440 }
441 else
442 snprintf(blen, sizeof(blen), "%d", len);
443 }
444 if (branch->IsA() == TBranchElement::Class())
445 {
446 bre = (TBranchElement *)branch;
447 if (bre->GetType() != 3 && bre->GetType() != 4 && bre->GetStreamerType() <= 0 && bre->GetListOfBranches()->GetEntriesFast())
448 {
449 leafStatus[l] = 0;
450 }
451 if (bre->GetType() == 3 || bre->GetType() == 4)
452 {
453 fprintf(fp, " %-15s %s_;\n", "Int_t", branchname);
454 continue;
455 }
456 if (bre->IsBranchFolder())
457 {
458 auto ModifiedType = AddStdPrefix(bre->GetClassName());
459 fprintf(fp, " %-15s *%s;\n", ModifiedType.Data(), branchname);
460 mustInit.Add(bre);
461 continue;
462 }
463 else
464 {
465 if (branch->GetListOfBranches()->GetEntriesFast())
466 {
467 leafStatus[l] = 1;
468 }
469 }
470 if (bre->GetStreamerType() < 0)
471 {
472 if (branch->GetListOfBranches()->GetEntriesFast())
473 {
474 auto ModifiedType = AddStdPrefix(bre->GetClassName());
475 fprintf(fp, "%s%-15s *%s;\n", headcom, ModifiedType.Data(), branchname);
476 }
477 else
478 {
479 auto ModifiedType = AddStdPrefix(bre->GetClassName());
480 fprintf(fp, "%s%-15s *%s;\n", head, ModifiedType.Data(), branchname);
481 mustInit.Add(bre);
482 }
483 continue;
484 }
485 if (bre->GetStreamerType() == 0)
486 {
487 if (!TClass::GetClass(bre->GetClassName())->HasInterpreterInfo())
488 {
489 leafStatus[l] = 1;
490 head = headcom;
491 }
492 auto ModifiedType = AddStdPrefix(bre->GetClassName());
493 fprintf(fp, "%s%-15s *%s;\n", head, ModifiedType.Data(), branchname);
494 if (leafStatus[l] == 0)
495 mustInit.Add(bre);
496 continue;
497 }
498 if (bre->GetStreamerType() > 60)
499 {
500 TClass *cle = TClass::GetClass(bre->GetClassName());
501 if (!cle)
502 {
503 leafStatus[l] = 1;
504 continue;
505 }
506 if (bre->GetStreamerType() == 66)
507 leafStatus[l] = 0;
508 char brename[256];
509 strlcpy(brename, bre->GetName(), 255);
510 char *bren = brename;
511 char *adot = strrchr(bren, '.');
512 if (adot)
513 bren = adot + 1;
514 char *brack = strchr(bren, '[');
515 if (brack)
516 *brack = 0;
517 TStreamerElement *elem = (TStreamerElement *)cle->GetStreamerInfo()->GetElements()->FindObject(bren);
518 if (elem)
519 {
520 if (elem->IsA() == TStreamerBase::Class())
521 {
522 leafStatus[l] = 1;
523 continue;
524 }
525 if (!TClass::GetClass(elem->GetTypeName()))
526 {
527 leafStatus[l] = 1;
528 continue;
529 }
530 if (!TClass::GetClass(elem->GetTypeName())->HasInterpreterInfo())
531 {
532 leafStatus[l] = 1;
533 head = headcom;
534 }
535 if (leafcount)
536 {
537 auto ModifiedType = AddStdPrefix(elem->GetTypeName());
538 fprintf(fp, "%s%-15s %s[kMax%s];\n", head, ModifiedType.Data(), branchname, blen);
539 }
540 else
541 {
542 auto ModifiedType = AddStdPrefix(elem->GetTypeName());
543 fprintf(fp, "%s%-15s %s;\n", head, ModifiedType.Data(), branchname);
544 }
545 }
546 else
547 {
548 if (!TClass::GetClass(bre->GetClassName())->HasInterpreterInfo())
549 {
550 leafStatus[l] = 1;
551 head = headcom;
552 }
553 auto ModifiedType = AddStdPrefix(bre->GetClassName());
554 fprintf(fp, "%s%-15s %s;\n", head, ModifiedType.Data(), branchname);
555 }
556 continue;
557 }
558 }
559 if (strlen(leaf->GetTypeName()) == 0)
560 {
561 leafStatus[l] = 1;
562 continue;
563 }
564 if (leafcount)
565 {
566 // len = leafcount->GetMaximum();
567 // strlcpy(blen,leafcount->GetName(),sizeof(blen));
568 // bname = &blen[0];
569 // while (*bname) {if (*bname == '.') *bname='_'; bname++;}
570 // lenb = strlen(blen);
571 // Int_t kmax = 0;
572 // if (blen[lenb-1] == '_') {blen[lenb-1] = 0; kmax = 1;}
573 // else sprintf(blen,"%d",len);
574
575 const char *stars = " ";
576 if (bre && bre->GetBranchCount2())
577 {
578 stars = "*";
579 }
580 // Dimensions can be in the branchname for a split Object with a fix length C array.
581 // Theses dimensions HAVE TO be placed after the dimension explicited by leafcount
582 TString dimensions;
583 char *dimInName = (char *)strstr(branchname, "[");
584 if (twodim || dimInName)
585 {
586 if (dimInName)
587 {
588 dimensions = dimInName;
589 dimInName[0] = 0; // terminate branchname before the array dimensions.
590 }
591 if (twodim)
592 dimensions += (char *)(twodim + 1);
593 }
594 const char *leafcountName = leafcount->GetName();
595 char b2len[1024];
596 if (bre && bre->GetBranchCount2())
597 {
598 TLeaf *l2 = (TLeaf *)bre->GetBranchCount2()->GetListOfLeaves()->At(0);
599 strlcpy(b2len, l2->GetName(), sizeof(b2len));
600 bname = &b2len[0];
601 while (*bname)
602 {
603 if (*bname == '.')
604 *bname = '_';
605 if (*bname == ',')
606 *bname = '_';
607 if (*bname == ':')
608 *bname = '_';
609 if (*bname == '<')
610 *bname = '_';
611 if (*bname == '>')
612 *bname = '_';
613 bname++;
614 }
615 leafcountName = b2len;
616 }
617 if (dimensions.Length())
618 {
619 if (kmax)
620 {
621 auto ModifiedType = AddStdPrefix(leaf->GetTypeName());
622 fprintf(fp, " %-14s %s%s[kMax%s]%s; //[%s]\n", ModifiedType.Data(), stars,
623 branchname, blen, dimensions.Data(), leafcountName);
624 }
625 else
626 {
627 auto ModifiedType = AddStdPrefix(leaf->GetTypeName());
628 fprintf(fp, " %-14s %s%s[%d]%s; //[%s]\n", ModifiedType.Data(), stars,
629 branchname, len, dimensions.Data(), leafcountName);
630 }
631 }
632 else
633 {
634 if (kmax)
635 {
636 auto ModifiedType = AddStdPrefix(leaf->GetTypeName());
637 fprintf(fp, " %-14s %s%s[kMax%s]; //[%s]\n", ModifiedType.Data(), stars, branchname, blen, leafcountName);
638 }
639 else
640 {
641 auto ModifiedType = AddStdPrefix(leaf->GetTypeName());
642 fprintf(fp, " %-14s %s%s[%d]; //[%s]\n", ModifiedType.Data(), stars, branchname, len, leafcountName);
643 }
644 }
645 if (stars[0] == '*')
646 {
647 TNamed *n;
648 if (kmax)
649 n = new TNamed(branchname, Form("kMax%s", blen));
650 else
651 n = new TNamed(branchname, Form("%d", len));
652 mustInitArr.Add(n);
653 }
654 }
655 else
656 {
657 if (strstr(branchname, "["))
658 len = 1;
659 if (len < 2)
660 {
661 auto ModifiedType = AddStdPrefix(leaf->GetTypeName());
662 fprintf(fp, " %-15s %s;\n", ModifiedType.Data(), branchname);
663 }
664 else
665 {
666 if (twodim)
667 {
668 auto ModifiedType = AddStdPrefix(leaf->GetTypeName());
669 fprintf(fp, " %-15s %s%s;\n", ModifiedType.Data(), branchname, (char *)strstr(leaf->GetTitle(), "["));
670 }
671 else
672 {
673 auto ModifiedType = AddStdPrefix(leaf->GetTypeName());
674 fprintf(fp, " %-15s %s[%d];\n", ModifiedType.Data(), branchname, len);
675 }
676 }
677 }
678 }
679
680 // generate list of branches
681 fprintf(fp, "\n");
682 fprintf(fp, " // List of branches\n");
683 for (l = 0; l < nleaves; l++)
684 {
685 if (leafStatus[l])
686 continue;
687 TLeaf *leaf = (TLeaf *)leaves->UncheckedAt(l);
688 fprintf(fp, " TBranch *b_%s; //!\n", R__GetBranchPointerName(leaf).Data());
689 }
690
691 // generate class member functions prototypes
692 if (opt.Contains("selector"))
693 {
694 fprintf(fp, "\n");
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);
711 fprintf(fp, "};\n");
712 fprintf(fp, "\n");
713 }
714 else
715 {
716 fprintf(fp, "\n\n");
717 fprintf(fp, "private:\n");
718 fprintf(fp, "// here user can define their own variables\n\n");
719 fprintf(fp, "};\n\n");
720 /*
721 fprintf(fp, "\n");
722 fprintf(fp, "#endif\n");
723 fprintf(fp, "\n");
724 */
725 }
726 // generate code for class constructor
727 /*
728 fprintf(fp, "#ifdef %s_cxx\n", classname);
729 if (!opt.Contains("selector"))
730 {
731 fprintf(fp, "%s::%s(TTree *tree) : fChain(0) \n", classname, classname);
732 fprintf(fp, "{\n");
733 fprintf(fp, "// if parameter tree is not specified (or zero), connect the file\n");
734 fprintf(fp, "// used to generate this class and read the Tree.\n");
735 fprintf(fp, " if (tree == 0) {\n");
736 if (ischain)
737 {
738 fprintf(fp, "\n#ifdef SINGLE_TREE\n");
739 fprintf(fp, " // The following code should be used if you want this class to access\n");
740 fprintf(fp, " // a single tree instead of a chain\n");
741 }
742 if (isHbook)
743 {
744 fprintf(fp, " THbookFile *f = (THbookFile*)gROOT->GetListOfBrowsables()->FindObject(\"%s\");\n",
745 treefile.Data());
746 fprintf(fp, " if (!f) {\n");
747 fprintf(fp, " f = new THbookFile(\"%s\");\n", treefile.Data());
748 fprintf(fp, " }\n");
749 Int_t hid;
750 sscanf(tree->GetName(), "h%d", &hid);
751 fprintf(fp, " tree = (TTree*)f->Get(%d);\n\n", hid);
752 }
753 else
754 {
755 fprintf(fp, " TFile *f = (TFile*)gROOT->GetListOfFiles()->FindObject(\"%s\");\n", treefile.Data());
756 fprintf(fp, " if (!f || !f->IsOpen()) {\n");
757 fprintf(fp, " f = new TFile(\"%s\");\n", treefile.Data());
758 fprintf(fp, " }\n");
759 if (tree->GetDirectory() != tree->GetCurrentFile())
760 {
761 fprintf(fp, " TDirectory * dir = (TDirectory*)f->Get(\"%s\");\n", tree->GetDirectory()->GetPath());
762 fprintf(fp, " dir->GetObject(\"%s\",tree);\n\n", tree->GetName());
763 }
764 else
765 {
766 fprintf(fp, " f->GetObject(\"%s\",tree);\n\n", tree->GetName());
767 }
768 }
769 if (ischain)
770 {
771 fprintf(fp, "#else // SINGLE_TREE\n\n");
772 fprintf(fp, " // The following code should be used if you want this class to access a chain\n");
773 fprintf(fp, " // of trees.\n");
774 fprintf(fp, " TChain * chain = new TChain(\"%s\",\"%s\");\n",
775 tree->GetName(), tree->GetTitle());
776 {
777 R__LOCKGUARD(gROOTMutex);
778 TIter next(((TChain *)tree)->GetListOfFiles());
779 TChainElement *element;
780 while ((element = (TChainElement *)next()))
781 {
782 fprintf(fp, " chain->Add(\"%s/%s\");\n", element->GetTitle(), element->GetName());
783 }
784 }
785 fprintf(fp, " tree = chain;\n");
786 fprintf(fp, "#endif // SINGLE_TREE\n\n");
787 }
788 fprintf(fp, " }\n");
789 fprintf(fp, " Init(tree);\n");
790 fprintf(fp, "}\n");
791 fprintf(fp, "\n");
792 }
793
794 // generate code for class destructor()
795 if (!opt.Contains("selector"))
796 {
797 fprintf(fp, "%s::~%s()\n", classname, classname);
798 fprintf(fp, "{\n");
799 fprintf(fp, " if (!fChain) return;\n");
800 if (isHbook)
801 {
802 //fprintf(fp," delete fChain->GetCurrentFile();\n");
803 }
804 else
805 {
806 fprintf(fp, " delete fChain->GetCurrentFile();\n");
807 }
808 fprintf(fp, "}\n");
809 fprintf(fp, "\n");
810 }
811 // generate code for class member function GetEntry()
812 if (!opt.Contains("selector"))
813 {
814 fprintf(fp, "Int_t %s::GetEntry(Long64_t entry)\n", classname);
815 fprintf(fp, "{\n");
816 fprintf(fp, "// Read contents of entry.\n");
817
818 fprintf(fp, " if (!fChain) return 0;\n");
819 fprintf(fp, " return fChain->GetEntry(entry);\n");
820 fprintf(fp, "}\n");
821 }
822 // generate code for class member function LoadTree()
823 if (!opt.Contains("selector"))
824 {
825 fprintf(fp, "Long64_t %s::LoadTree(Long64_t entry)\n", classname);
826 fprintf(fp, "{\n");
827 fprintf(fp, "// Set the environment to read one entry\n");
828 fprintf(fp, " if (!fChain) return -5;\n");
829 fprintf(fp, " Long64_t centry = fChain->LoadTree(entry);\n");
830 fprintf(fp, " if (centry < 0) return centry;\n");
831 fprintf(fp, " if (fChain->GetTreeNumber() != fCurrent) {\n");
832 fprintf(fp, " fCurrent = fChain->GetTreeNumber();\n");
833 fprintf(fp, " Notify();\n");
834 fprintf(fp, " }\n");
835 fprintf(fp, " return centry;\n");
836 fprintf(fp, "}\n");
837 fprintf(fp, "\n");
838 }
839 */
840 // generate code for class member function Init(), first pass = get branch pointer
841 fprintf(fp, "inline NAGASH::StatusCode %s::InitializeData()\n", classname);
842 fprintf(fp, "{\n");
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");
848 fprintf(fp, " {\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");
852 if (mustInit.Last())
853 {
854 TIter next(&mustInit);
855 TObject *obj;
856 fprintf(fp, " // Set object pointer\n");
857 while ((obj = next()))
858 {
859 if (obj->InheritsFrom(TBranch::Class()))
860 {
861 strlcpy(branchname, ((TBranch *)obj)->GetName(), sizeof(branchname));
862 }
863 else if (obj->InheritsFrom(TLeaf::Class()))
864 {
865 strlcpy(branchname, ((TLeaf *)obj)->GetName(), sizeof(branchname));
866 }
867 branchname[1023] = 0;
868 bname = branchname;
869 while (*bname)
870 {
871 if (*bname == '.')
872 *bname = '_';
873 if (*bname == ',')
874 *bname = '_';
875 if (*bname == ':')
876 *bname = '_';
877 if (*bname == '<')
878 *bname = '_';
879 if (*bname == '>')
880 *bname = '_';
881 bname++;
882 }
883 fprintf(fp, " %s = 0;\n", branchname);
884 }
885 }
886 if (mustInitArr.Last())
887 {
888 TIter next(&mustInitArr);
889 TNamed *info;
890 fprintf(fp, " // Set array pointer\n");
891 while ((info = (TNamed *)next()))
892 {
893 fprintf(fp, " for(int i=0; i<%s; ++i) %s[i] = 0;\n", info->GetTitle(), info->GetName());
894 }
895 fprintf(fp, "\n");
896 }
897 fprintf(fp, " // Set branch addresses and branch pointers\n");
898 /*
899 fprintf(fp, " if (!tree) return;\n");
900 fprintf(fp, " fChain = tree;\n");
901 if (!opt.Contains("selector"))
902 fprintf(fp, " fCurrent = -1;\n");
903 fprintf(fp, " fChain->SetMakeClass(1);\n");
904 fprintf(fp, "\n");
905 */
906 for (l = 0; l < nleaves; l++)
907 {
908 if (leafStatus[l])
909 continue;
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));
915
916 if (branch->GetNleaves() > 1)
917 {
918 // More than one leaf for the branch we need to distinguish them
919 strlcpy(branchname, branch->GetName(), sizeof(branchname));
920 strlcat(branchname, ".", sizeof(branchname));
921 strlcat(branchname, leaf->GetTitle(), sizeof(branchname));
922 if (leafcount)
923 {
924 // remove any dimension in title
925 char *dim = (char *)strstr(branchname, "[");
926 if (dim)
927 dim[0] = 0;
928 }
929 }
930 else
931 {
932 strlcpy(branchname, branch->GetName(), sizeof(branchname));
933 if (branch->IsA() == TBranchElement::Class())
934 {
935 bre = (TBranchElement *)branch;
936 if (bre->GetType() == 3 || bre->GetType() == 4)
937 strlcat(branchname, "_", sizeof(branchname));
938 }
939 }
940 bname = branchname;
941 char *brak = strstr(branchname, "[");
942 if (brak)
943 *brak = 0;
944 char *twodim = (char *)strstr(bname, "[");
945 if (twodim)
946 *twodim = 0;
947 while (*bname)
948 {
949 if (*bname == '.')
950 *bname = '_';
951 if (*bname == ',')
952 *bname = '_';
953 if (*bname == ':')
954 *bname = '_';
955 if (*bname == '<')
956 *bname = '_';
957 if (*bname == '>')
958 *bname = '_';
959 bname++;
960 }
961 const char *maybedisable = "";
962 if (branch != tree->GetBranch(branch->GetName()))
963 {
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 = "// ";
966 }
967 if (branch->IsA() == TBranchObject::Class())
968 {
969 if (branch->GetListOfBranches()->GetEntriesFast())
970 {
971 fprintf(fp, "%s RootTreeUser()->SetBranchAddress(\"%s\",(void*)-1,&b_%s);\n", maybedisable, branch->GetName(), R__GetBranchPointerName(leaf).Data());
972 continue;
973 }
974 strlcpy(branchname, branch->GetName(), sizeof(branchname));
975 }
976 if (branch->IsA() == TBranchElement::Class())
977 {
978 if (((TBranchElement *)branch)->GetType() == 3)
979 len = 1;
980 if (((TBranchElement *)branch)->GetType() == 4)
981 len = 1;
982 }
983 if (leafcount)
984 len = leafcount->GetMaximum() + 1;
985 if (len > 1)
986 fprintf(fp, "%s RootTreeUser()->SetBranchAddress(\"%s\", %s, &b_%s);\n",
987 maybedisable, branch->GetName(), branchname, R__GetBranchPointerName(leaf).Data());
988 else
989 fprintf(fp, "%s RootTreeUser()->SetBranchAddress(\"%s\", &%s, &b_%s);\n",
990 maybedisable, branch->GetName(), branchname, R__GetBranchPointerName(leaf).Data());
991 }
992 // must call Notify in case of MakeClass
993 /*
994 if (!opt.Contains("selector"))
995 {
996 fprintf(fp, " Notify();\n");
997 }
998 */
999
1000 fprintf(fp, "\n");
1001 fprintf(fp, " return NAGASH::StatusCode::SUCCESS;\n");
1002 fprintf(fp, "}\n");
1003 fprintf(fp, "\n");
1004
1005 /*
1006 // generate code for class member function Notify()
1007 fprintf(fp, "Bool_t %s::Notify()\n", classname);
1008 fprintf(fp, "{\n");
1009 fprintf(fp, " // The Notify() function is called when a new file is opened. This\n"
1010 " // can be either for a new TTree in a TChain or when when a new TTree\n"
1011 " // is started when using PROOF. It is normally not necessary to make changes\n"
1012 " // to the generated code, but the routine can be extended by the\n"
1013 " // user if needed. The return value is currently not used.\n\n");
1014 fprintf(fp, " return kTRUE;\n");
1015 fprintf(fp, "}\n");
1016 fprintf(fp, "\n");
1017
1018 // generate code for class member function Show()
1019 if (!opt.Contains("selector"))
1020 {
1021 fprintf(fp, "void %s::Show(Long64_t entry)\n", classname);
1022 fprintf(fp, "{\n");
1023 fprintf(fp, "// Print contents of entry.\n");
1024 fprintf(fp, "// If entry is not specified, print current entry\n");
1025
1026 fprintf(fp, " if (!fChain) return;\n");
1027 fprintf(fp, " fChain->Show(entry);\n");
1028 fprintf(fp, "}\n");
1029 }
1030 // generate code for class member function Cut()
1031 if (!opt.Contains("selector"))
1032 {
1033 fprintf(fp, "Int_t %s::Cut(Long64_t entry)\n", classname);
1034 fprintf(fp, "{\n");
1035 fprintf(fp, "// This function may be called from Loop.\n");
1036 fprintf(fp, "// returns 1 if entry is accepted.\n");
1037 fprintf(fp, "// returns -1 otherwise.\n");
1038
1039 fprintf(fp, " return 1;\n");
1040 fprintf(fp, "}\n");
1041 }
1042 fprintf(fp, "#endif // #ifdef %s_cxx\n", classname);
1043 */
1044
1045 //======================Generate classname.C=====================
1046 if (!opt.Contains("selector"))
1047 {
1048 // generate code for class member function Loop()
1049 fprintf(fpc, "#include \"%s.h\"\n", classname);
1050 fprintf(fpc, "\n");
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");
1057
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");
1063
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");
1069 }
1070 if (opt.Contains("selector"))
1071 {
1072 // generate usage comments and list of includes
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");
1099 fprintf(fpc, "\n");
1100 // generate code for class member function Begin
1101 fprintf(fpc, "\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");
1107 fprintf(fpc, "\n");
1108 fprintf(fpc, " TString option = GetOption();\n");
1109 fprintf(fpc, "\n");
1110 fprintf(fpc, "}\n");
1111 // generate code for class member function SlaveBegin
1112 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");
1118 fprintf(fpc, "\n");
1119 fprintf(fpc, " TString option = GetOption();\n");
1120 fprintf(fpc, "\n");
1121 fprintf(fpc, "}\n");
1122 // generate code for class member function Process
1123 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"
1133 " //\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"
1137 " //\n"
1138 " // The processing can be stopped by calling Abort().\n"
1139 " //\n"
1140 " // Use fStatus to set the return value of TTree::Process().\n"
1141 " //\n"
1142 " // The return value is currently not used.\n\n",
1143 classname);
1144 fprintf(fpc, "\n");
1145 fprintf(fpc, " return kTRUE;\n");
1146 fprintf(fpc, "}\n");
1147 // generate code for class member function SlaveTerminate
1148 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.");
1154 fprintf(fpc, "\n");
1155 fprintf(fpc, "\n");
1156 fprintf(fpc, "}\n");
1157 // generate code for class member function Terminate
1158 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.");
1164 fprintf(fpc, "\n");
1165 fprintf(fpc, "\n");
1166 fprintf(fpc, "}\n");
1167 }
1168 Info("MakeClass", "Files: %s and %s generated from TTree: %s", thead.Data(), tcimp.Data(), tree->GetName());
1169 delete[] leafStatus;
1170
1171 fclose(fp);
1172 fclose(fpc);
1173
1174 return 0;
1175}
Some global definitions.
int main(int argc, char **argv)
static TString R__GetBranchPointerName(TLeaf *leaf, Bool_t replace=kTRUE)
TString AddStdPrefix(const char *TypeName)