Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TTreePlayer.cxx
Go to the documentation of this file.
1// @(#)root/treeplayer:$Id$
2// Author: Rene Brun 12/01/96
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12/**
13 * \defgroup treeplayer TreePlayer Library
14 * \brief It contains utilities to plot data stored in a TTree.
15 * \sa Tree package documentation
16 * \sa Chapter about Trees and Selectors in the Users Guide
17 * \sa ROOT examples in tutorials and test directories: Event application, benchmarks
18 */
19
20/** \class TTreePlayer
21
22Implement some of the functionality of the class TTree requiring access to
23extra libraries (Histogram, display, etc).
24*/
25
26#include "TTreePlayer.h"
27
28#include <cstring>
29#include <cstdio>
30#include <cstdlib>
31#include <iostream>
32#include <fstream>
33
34#include "TROOT.h"
35#include "TApplication.h"
36#include "TSystem.h"
37#include "TFile.h"
38#include "TEnv.h"
39#include "TEventList.h"
40#include "TEntryList.h"
41#include "TBranchObject.h"
42#include "TBranchElement.h"
43#include "TStreamerInfo.h"
44#include "TStreamerElement.h"
45#include "TLeafObject.h"
46#include "TLeafF.h"
47#include "TLeafD.h"
48#include "TLeafC.h"
49#include "TLeafB.h"
50#include "TLeafI.h"
51#include "TLeafS.h"
52#include "TMath.h"
53#include "TH1.h"
54#include "TPolyMarker.h"
55#include "TPolyMarker3D.h"
56#include "TText.h"
57#include "TDirectory.h"
58#include "TClonesArray.h"
59#include "TClass.h"
60#include "TVirtualPad.h"
61#include "TProfile.h"
62#include "TProfile2D.h"
63#include "TTreeFormula.h"
64#include "TTreeFormulaManager.h"
65#include "TStyle.h"
66#include "Foption.h"
67#include "TTreeResult.h"
68#include "TTreeRow.h"
69#include "TPrincipal.h"
70#include "TChain.h"
71#include "TChainElement.h"
72#include "TF1.h"
73#include "TVirtualFitter.h"
74#include "THLimitsFinder.h"
75#include "TSelectorDraw.h"
76#include "TSelectorEntries.h"
77#include "TPluginManager.h"
78#include "TObjString.h"
79#include "TTreeProxyGenerator.h"
81#include "TTreeIndex.h"
82#include "TChainIndex.h"
83#include "TRefProxy.h"
84#include "TRefArrayProxy.h"
85#include "TVirtualMonitoring.h"
86#include "TTreeCache.h"
87#include "TVirtualMutex.h"
88#include "ThreadLocalStorage.h"
89#include "strlcpy.h"
90#include "snprintf.h"
91
92#include "HFitInterface.h"
93#include "Fit/BinData.h"
94#include "Fit/UnBinData.h"
96
97
99
101
103
104////////////////////////////////////////////////////////////////////////////////
105/// Default Tree constructor.
106
108{
109 fTree = nullptr;
110 fScanFileName = nullptr;
111 fScanRedirect = false;
112 fSelectedRows = 0;
113 fDimension = 0;
114 fHistogram = nullptr;
115 fFormulaList = new TList();
116 fFormulaList->SetOwner(true);
117 fSelector = new TSelectorDraw();
118 fSelectorFromFile = nullptr;
119 fSelectorClass = nullptr;
120 fSelectorUpdate = nullptr;
121 fInput = new TList();
122 fInput->Add(new TNamed("varexp",""));
123 fInput->Add(new TNamed("selection",""));
125 {
127 gROOT->GetListOfCleanups()->Add(this);
128 }
131}
132
133////////////////////////////////////////////////////////////////////////////////
134/// Tree destructor.
135
137{
138 delete fFormulaList;
139 delete fSelector;
141 fInput->Delete();
142 delete fInput;
144 gROOT->GetListOfCleanups()->Remove(this);
145}
146
147////////////////////////////////////////////////////////////////////////////////
148/// Build the index for the tree (see TTree::BuildIndex)
149
150TVirtualIndex *TTreePlayer::BuildIndex(const TTree *T, const char *majorname, const char *minorname)
151{
153 if (dynamic_cast<const TChain*>(T)) {
154 index = new TChainIndex(T, majorname, minorname);
155 if (index->IsZombie()) {
156 delete index;
157 Error("BuildIndex", "Creating a TChainIndex unsuccessful - switching to TTreeIndex");
158 }
159 else
160 return index;
161 }
162 return new TTreeIndex(T,majorname,minorname);
163}
164
165////////////////////////////////////////////////////////////////////////////////
166/// Copy a Tree with selection, make a clone of this Tree header, then copy the
167/// selected entries.
168///
169/// - selection is a standard selection expression (see TTreePlayer::Draw)
170/// - option is reserved for possible future use
171/// - nentries is the number of entries to process (default is all)
172/// - first is the first entry to process (default is 0)
173///
174/// IMPORTANT: The copied tree stays connected with this tree until this tree
175/// is deleted. In particular, any changes in branch addresses
176/// in this tree are forwarded to the clone trees. Any changes
177/// made to the branch addresses of the copied trees are over-ridden
178/// anytime this tree changes its branch addresses.
179/// Once this tree is deleted, all the addresses of the copied tree
180/// are reset to their default values.
181///
182/// The following example illustrates how to copy some events from the Tree
183/// generated in $ROOTSYS/test/Event
184/// ~~~{.cpp}
185/// gSystem->Load("libEvent");
186/// TFile f("Event.root");
187/// TTree *T = (TTree*)f.Get("T");
188/// Event *event = new Event();
189/// T->SetBranchAddress("event",&event);
190/// TFile f2("Event2.root","recreate");
191/// TTree *T2 = T->CopyTree("fNtrack<595");
192/// T2->Write();
193/// ~~~
194
196 Long64_t firstentry)
197{
198
199 // we make a copy of the tree header
200 TTree *tree = fTree->CloneTree(0);
201 if (tree == nullptr) return nullptr;
202
203 // The clone should not delete any shared i/o buffers.
204 TObjArray* branches = tree->GetListOfBranches();
205 Int_t nb = branches->GetEntriesFast();
206 for (Int_t i = 0; i < nb; ++i) {
207 TBranch* br = (TBranch*) branches->UncheckedAt(i);
209 ((TBranchElement*) br)->ResetDeleteObject();
210 }
211 }
212
213 Long64_t entry,entryNumber;
215
216 // Compile selection expression if there is one
217 TTreeFormula *select = nullptr; // no need to interfere with fSelect since we
218 // handle the loop explicitly below and can call
219 // UpdateFormulaLeaves ourselves.
220 if (strlen(selection)) {
221 select = new TTreeFormula("Selection",selection,fTree);
222 if (!select || !select->GetNdim()) {
223 delete select;
224 delete tree;
225 return nullptr;
226 }
227 fFormulaList->Add(select);
228 }
229
230 //loop on the specified entries
231 Int_t tnumber = -1;
232 for (entry=firstentry;entry<firstentry+nentries;entry++) {
233 entryNumber = fTree->GetEntryNumber(entry);
234 if (entryNumber < 0) break;
235 Long64_t localEntry = fTree->LoadTree(entryNumber);
236 if (localEntry < 0) break;
237 if (tnumber != fTree->GetTreeNumber()) {
238 tnumber = fTree->GetTreeNumber();
239 if (select) select->UpdateFormulaLeaves();
240 }
241 if (select) {
242 Int_t ndata = select->GetNdata();
243 bool keep = false;
244 for(Int_t current = 0; current<ndata && !keep; current++) {
245 keep |= (select->EvalInstance(current) != 0);
246 }
247 if (!keep) continue;
248 }
249 fTree->GetEntry(entryNumber);
250 tree->Fill();
251 }
253 return tree;
254}
255
256////////////////////////////////////////////////////////////////////////////////
257/// Delete any selector created by this object.
258/// The selector has been created using TSelector::GetSelector(file)
259
261{
263 if (fSelectorClass->IsLoaded()) {
264 delete fSelectorFromFile;
265 }
266 }
267 fSelectorFromFile = nullptr;
268 fSelectorClass = nullptr;
269}
270
271////////////////////////////////////////////////////////////////////////////////
272/// Draw the result of a C++ script.
273///
274/// The macrofilename and optionally cutfilename are assumed to contain
275/// at least a method with the same name as the file. The method
276/// should return a value that can be automatically cast to
277/// respectively a double and a boolean.
278///
279/// Both methods will be executed in a context such that the
280/// branch names can be used as C++ variables. This is
281/// accomplished by generating a TTreeProxy (see MakeProxy)
282/// and including the files in the proper location.
283///
284/// If the branch name can not be used a proper C++ symbol name,
285/// it will be modified as follow:
286/// - white spaces are removed
287/// - if the leading character is not a letter, an underscore is inserted
288/// - < and > are replace by underscores
289/// - * is replaced by st
290/// - & is replaced by rf
291///
292/// If a cutfilename is specified, for each entry, we execute
293/// ~~~{.cpp}
294/// if (cutfilename()) htemp->Fill(macrofilename());
295/// ~~~
296/// If no cutfilename is specified, for each entry we execute
297/// ~~~{.cpp}
298/// htemp(macrofilename());
299/// ~~~
300/// The default for the histogram are the same as for
301/// TTreePlayer::DrawSelect
302
303Long64_t TTreePlayer::DrawScript(const char* wrapperPrefix,
304 const char *macrofilename, const char *cutfilename,
306{
307 if (!macrofilename || strlen(macrofilename)==0) return 0;
308
309 TString aclicMode;
310 TString arguments;
311 TString io;
312 TString realcutname;
313 if (cutfilename && strlen(cutfilename))
314 realcutname = gSystem->SplitAclicMode(cutfilename, aclicMode, arguments, io);
315
316 // we ignore the aclicMode for the cutfilename!
317 TString realname = gSystem->SplitAclicMode(macrofilename, aclicMode, arguments, io);
318
319 TString selname = wrapperPrefix;
320
321 ROOT::Internal::TTreeProxyGenerator gp(fTree,realname,realcutname,selname,option,3);
322
323 selname = gp.GetFileName();
324 if (aclicMode.Length()==0) {
325 Warning("DrawScript","TTreeProxy does not work in interpreted mode yet. The script will be compiled.");
326 aclicMode = "+";
327 }
328 selname.Append(aclicMode);
329
330 Info("DrawScript","%s",Form("Will process tree/chain using %s",selname.Data()));
331 Long64_t result = fTree->Process(selname,option,nentries,firstentry);
332 fTree->SetNotify(nullptr);
333
334 // could delete the file selname+".h"
335 // However this would remove the optimization of avoiding a useless
336 // recompilation if the user ask for the same thing twice!
337
338 return result;
339}
340
341////////////////////////////////////////////////////////////////////////////////
342/// Draw expression varexp for specified entries that matches the selection.
343/// Returns -1 in case of error or number of selected events in case of success.
344///
345/// See the documentation of TTree::Draw for the complete details.
346
347Long64_t TTreePlayer::DrawSelect(const char *varexp0, const char *selection, Option_t *option,Long64_t nentries, Long64_t firstentry)
348{
349 if (fTree->GetEntriesFriend() == 0) return 0;
350
351 // Let's see if we have a filename as arguments instead of
352 // a TTreeFormula expression.
353
354 TString possibleFilename = varexp0;
355 Ssiz_t dot_pos = possibleFilename.Last('.');
356 if ( dot_pos != kNPOS
357 && possibleFilename.Index("Alt$")<0 && possibleFilename.Index("Entries$")<0
358 && possibleFilename.Index("LocalEntries$")<0
359 && possibleFilename.Index("Length$")<0 && possibleFilename.Index("Entry$")<0
360 && possibleFilename.Index("LocalEntry$")<0
361 && possibleFilename.Index("Min$")<0 && possibleFilename.Index("Max$")<0
362 && possibleFilename.Index("MinIf$")<0 && possibleFilename.Index("MaxIf$")<0
363 && possibleFilename.Index("Iteration$")<0 && possibleFilename.Index("Sum$")<0
364 && possibleFilename.Index(">")<0 && possibleFilename.Index("<")<0
365 && gSystem->IsFileInIncludePath(possibleFilename.Data())) {
366
367 if (selection && strlen(selection) && !gSystem->IsFileInIncludePath(selection)) {
368 Error("DrawSelect",
369 "Drawing using a C++ file currently requires that both the expression and the selection are files\n\t\"%s\" is not a file",
370 selection);
371 return 0;
372 }
373 return DrawScript("generatedSel",varexp0,selection,option,nentries,firstentry);
374
375 } else {
376 possibleFilename = selection;
377 if (possibleFilename.Index("Alt$")<0 && possibleFilename.Index("Entries$")<0
378 && possibleFilename.Index("LocalEntries$")<0
379 && possibleFilename.Index("Length$")<0 && possibleFilename.Index("Entry$")<0
380 && possibleFilename.Index("LocalEntry$")<0
381 && possibleFilename.Index("Min$")<0 && possibleFilename.Index("Max$")<0
382 && possibleFilename.Index("MinIf$")<0 && possibleFilename.Index("MaxIf$")<0
383 && possibleFilename.Index("Iteration$")<0 && possibleFilename.Index("Sum$")<0
384 && possibleFilename.Index(">")<0 && possibleFilename.Index("<")<0
385 && gSystem->IsFileInIncludePath(possibleFilename.Data())) {
386
387 Error("DrawSelect",
388 "Drawing using a C++ file currently requires that both the expression and the selection are files\n\t\"%s\" is not a file",
389 varexp0);
390 return 0;
391 }
392 }
393
394 Long64_t oldEstimate = fTree->GetEstimate();
395 TEventList *evlist = fTree->GetEventList();
396 TEntryList *elist = fTree->GetEntryList();
397 if (evlist && elist){
398 elist->SetBit(kCanDelete, true);
399 }
400 TNamed *cvarexp = (TNamed*)fInput->FindObject("varexp");
401 TNamed *cselection = (TNamed*)fInput->FindObject("selection");
402 if (cvarexp) cvarexp->SetTitle(varexp0);
403 if (cselection) cselection->SetTitle(selection);
404
405 TString opt = option;
406 opt.ToLower();
407 bool optpara = false;
408 bool optcandle = false;
409 bool optgl5d = false;
410 bool optnorm = false;
411 if (opt.Contains("norm")) {optnorm = true; opt.ReplaceAll("norm",""); opt.ReplaceAll(" ","");}
412 if (opt.Contains("para")) optpara = true;
413 if (opt.Contains("candle")) optcandle = true;
414 if (opt.Contains("gl5d")) optgl5d = true;
415 bool pgl = gStyle->GetCanvasPreferGL();
416 if (optgl5d) {
418 if (!gPad) {
419 if (pgl == false) gStyle->SetCanvasPreferGL(true);
420 gROOT->ProcessLineFast("new TCanvas();");
421 }
422 }
423
424 // Do not process more than fMaxEntryLoop entries
426
427 // invoke the selector
428 Long64_t nrows = Process(fSelector,option,nentries,firstentry);
429 fSelectedRows = nrows;
431
432 //*-* an Event List
433 if (fDimension <= 0) {
434 fTree->SetEstimate(oldEstimate);
435 if (fSelector->GetCleanElist()) {
436 // We are in the case where the input list was reset!
437 fTree->SetEntryList(elist);
438 delete fSelector->GetObject();
439 }
440 return nrows;
441 }
442
443 // Draw generated histogram
444 Long64_t drawflag = fSelector->GetDrawFlag();
445 Int_t action = fSelector->GetAction();
446 bool draw = false;
447 if (!drawflag && !opt.Contains("goff")) draw = true;
448 if (!optcandle && !optpara) fHistogram = (TH1*)fSelector->GetObject();
449 if (optnorm) {
451 if (sumh != 0) fHistogram->Scale(1./sumh);
452 }
453
454 if (drawflag) {
455 if (gPad) {
456 if (!opt.Contains("same") && !opt.Contains("goff")) {
457 gPad->DrawFrame(-1.,-1.,1.,1.);
458 TText *text_empty = new TText(0.,0.,"Empty");
459 text_empty->SetTextAlign(22);
460 text_empty->SetTextFont(42);
461 text_empty->SetTextSize(0.1);
462 text_empty->SetTextColor(1);
463 text_empty->Draw();
464 }
465 } else {
466 Warning("DrawSelect", "The selected TTree subset is empty.");
467 }
468 }
469
470 //*-*- 1-D distribution
471 if (fDimension == 1 && !(optpara||optcandle)) {
473 if (draw) fHistogram->Draw(opt.Data());
474
475 //*-*- 2-D distribution
476 } else if (fDimension == 2 && !(optpara||optcandle)) {
479 if (action == 4) {
480 if (draw) fHistogram->Draw(opt.Data());
481 } else {
482 bool graph = false;
483 Int_t l = opt.Length();
484 if (l == 0 || opt == "same") graph = true;
485 if (opt.Contains("p") || opt.Contains("*") || opt.Contains("l")) graph = true;
486 if (opt.Contains("surf") || opt.Contains("lego") || opt.Contains("cont")) graph = false;
487 if (opt.Contains("col") || opt.Contains("hist") || opt.Contains("scat")) graph = false;
488 if (!graph) {
489 if (draw) fHistogram->Draw(opt.Data());
490 } else {
491 if (fSelector->GetOldHistogram() && draw) fHistogram->Draw(opt.Data());
492 }
493 }
494 //*-*- 3-D distribution
495 } else if (fDimension == 3 && !(optpara||optcandle)) {
499 if (action == 23) {
500 if (draw) fHistogram->Draw(opt.Data());
501 } else if (action == 33) {
502 if (draw) {
503 if (opt.Contains("z")) fHistogram->Draw("func z");
504 else fHistogram->Draw("func");
505 }
506 } else {
507 Int_t noscat = opt.Length();
508 if (opt.Contains("same")) noscat -= 4;
509 if (noscat) {
510 if (draw) fHistogram->Draw(opt.Data());
511 } else {
512 if (fSelector->GetOldHistogram() && draw) fHistogram->Draw(opt.Data());
513 }
514 }
515 //*-*- 4-D distribution
516 } else if (fDimension == 4 && !(optpara||optcandle)) {
520 if (draw) fHistogram->Draw(opt.Data());
521 Int_t ncolors = gStyle->GetNumberOfColors();
522 TObjArray *pms = (TObjArray*)fHistogram->GetListOfFunctions()->FindObject("polymarkers");
523 for (Int_t col=0;col<ncolors;col++) {
524 if (!pms) continue;
525 TPolyMarker3D *pm3d = (TPolyMarker3D*)pms->UncheckedAt(col);
526 if (draw) pm3d->Draw();
527 }
528 //*-*- Parallel Coordinates or Candle chart.
529 } else if (fDimension > 1 && (optpara || optcandle)) {
530 if (draw) {
531 TObject* para = fSelector->GetObject();
532 fTree->Draw(">>enlist",selection,"entrylist",nentries,firstentry);
533 TObject *enlist = gDirectory->FindObject("enlist");
534 gROOT->ProcessLine(Form("TParallelCoord::SetEntryList((TParallelCoord*)0x%zx,(TEntryList*)0x%zx)",
535 (size_t)para, (size_t)enlist));
536 }
537 //*-*- 5d with gl
538 } else if (fDimension == 5 && optgl5d) {
539 gROOT->ProcessLineFast(Form("(new TGL5DDataSet((TTree *)0x%zx))->Draw(\"%s\");", (size_t)fTree, opt.Data()));
541 }
542
544 return fSelectedRows;
545}
546
547////////////////////////////////////////////////////////////////////////////////
548/// Fit a projected item(s) from a Tree.
549/// Returns -1 in case of error or number of selected events in case of success.
550///
551/// The formula is a TF1 expression.
552///
553/// See TTree::Draw for explanations of the other parameters.
554///
555/// By default the temporary histogram created is called htemp.
556/// If varexp contains >>hnew , the new histogram created is called hnew
557/// and it is kept in the current directory.
558/// Example:
559/// ~~~{.cpp}
560/// tree.Fit("pol4","sqrt(x)>>hsqrt","y>0")
561/// will fit sqrt(x) and save the histogram as "hsqrt" in the current
562/// directory.
563/// ~~~
564///
565/// The function returns the status of the histogram fit (see TH1::Fit)
566/// If no entries were selected, the function returns -1;
567/// (i.e. fitResult is null if the fit is OK)
568
569Int_t TTreePlayer::Fit(const char *formula ,const char *varexp, const char *selection,Option_t *option ,Option_t *goption,Long64_t nentries, Long64_t firstentry)
570{
571 Int_t nch = option ? strlen(option) + 10 : 10;
572 char *opt = new char[nch];
573 if (option) strlcpy(opt,option,nch-1);
574 else strlcpy(opt,"goff",5);
575
576 Long64_t nsel = DrawSelect(varexp,selection,opt,nentries,firstentry);
577
578 delete [] opt;
579 Int_t fitResult = -1;
580
581 if (fHistogram && nsel > 0) {
582 fitResult = fHistogram->Fit(formula,option,goption);
583 }
584 return fitResult;
585}
586
587////////////////////////////////////////////////////////////////////////////////
588/// Return the number of entries matching the selection.
589/// Return -1 in case of errors.
590///
591/// If the selection uses any arrays or containers, we return the number
592/// of entries where at least one element match the selection.
593/// GetEntries is implemented using the selector class TSelectorEntries,
594/// which can be used directly (see code in TTreePlayer::GetEntries) for
595/// additional option.
596/// If SetEventList was used on the TTree or TChain, only that subset
597/// of entries will be considered.
598
599Long64_t TTreePlayer::GetEntries(const char *selection)
600{
601 TSelectorEntries s(selection);
602 fTree->Process(&s);
603 fTree->SetNotify(nullptr);
604 return s.GetSelectedRows();
605}
606
607////////////////////////////////////////////////////////////////////////////////
608/// return the number of entries to be processed
609/// this function checks that nentries is not bigger than the number
610/// of entries in the Tree or in the associated TEventlist
611
613{
614 Long64_t lastentry = firstentry + nentries - 1;
615 if (lastentry > fTree->GetEntriesFriend()-1) {
616 lastentry = fTree->GetEntriesFriend() - 1;
617 nentries = lastentry - firstentry + 1;
618 }
619 //TEventList *elist = fTree->GetEventList();
620 //if (elist && elist->GetN() < nentries) nentries = elist->GetN();
621 TEntryList *elist = fTree->GetEntryList();
622 if (elist && elist->GetN() < nentries) nentries = elist->GetN();
623 return nentries;
624}
625
626////////////////////////////////////////////////////////////////////////////////
627/// Return name corresponding to colindex in varexp.
628///
629/// - varexp is a string of names separated by :
630/// - index is an array with pointers to the start of name[i] in varexp
631
632const char *TTreePlayer::GetNameByIndex(TString &varexp, Int_t *index,Int_t colindex)
633{
634 TTHREAD_TLS_DECL(std::string,column);
635 if (colindex<0 ) return "";
636 Int_t i1,n;
637 i1 = index[colindex] + 1;
638 n = index[colindex+1] - i1;
639 column = varexp(i1,n).Data();
640 // return (const char*)Form((const char*)column);
641 return column.c_str();
642}
643
644////////////////////////////////////////////////////////////////////////////////
645/// Return the name of the branch pointer needed by MakeClass/MakeSelector
646
647static TString R__GetBranchPointerName(TLeaf *leaf, bool replace = true)
648{
649 TLeaf *leafcount = leaf->GetLeafCount();
650 TBranch *branch = leaf->GetBranch();
651
652 TString branchname( branch->GetName() );
653
654 if ( branch->GetNleaves() <= 1 ) {
655 if (branch->IsA() != TBranchObject::Class()) {
656 if (!leafcount) {
657 TBranch *mother = branch->GetMother();
658 const char* ltitle = leaf->GetTitle();
659 if (mother && mother!=branch) {
660 branchname = mother->GetName();
661 if (branchname[branchname.Length()-1]!='.') {
662 branchname += ".";
663 }
664 if (strncmp(branchname.Data(),ltitle,branchname.Length())==0) {
665 branchname = "";
666 }
667 } else {
668 branchname = "";
669 }
670 branchname += ltitle;
671 }
672 }
673 }
674 if (replace) {
675 char *bname = (char*)branchname.Data();
676 char *twodim = (char*)strstr(bname,"[");
677 if (twodim) *twodim = 0;
678 while (*bname) {
679 if (*bname == '.') *bname='_';
680 if (*bname == ',') *bname='_';
681 if (*bname == ':') *bname='_';
682 if (*bname == '<') *bname='_';
683 if (*bname == '>') *bname='_';
684 if (*bname == '#') *bname='_';
685 if (*bname == '@') *bname='_';
686 bname++;
687 }
688 }
689 return branchname;
690}
691
692////////////////////////////////////////////////////////////////////////////////
693/// Generate skeleton analysis class for this Tree.
694///
695/// The following files are produced: classname.h and classname.C
696/// If classname is 0, classname will be called "nameoftree.
697///
698/// The generated code in classname.h includes the following:
699/// - Identification of the original Tree and Input file name
700/// - Definition of analysis class (data and functions)
701/// - the following class functions:
702/// - constructor (connecting by default the Tree file)
703/// - GetEntry(Long64_t entry)
704/// - Init(TTree *tree) to initialize a new TTree
705/// - Show(Long64_t entry) to read and Dump entry
706///
707/// The generated code in classname.C includes only the main
708/// analysis function Loop.
709///
710/// To use this function:
711/// - connect your Tree file (eg: TFile f("myfile.root");)
712/// - T->MakeClass("MyClass");
713///
714/// where T is the name of the Tree in file myfile.root
715/// and MyClass.h, MyClass.C the name of the files created by this function.
716/// In a ROOT session, you can do:
717/// ~~~{.cpp}
718/// root> .L MyClass.C
719/// root> MyClass t
720/// root> t.GetEntry(12); // Fill t data members with entry number 12
721/// root> t.Show(); // Show values of entry 12
722/// root> t.Show(16); // Read and show values of entry 16
723/// root> t.Loop(); // Loop on all entries
724/// ~~~
725/// NOTE: Do not use the code generated for one Tree in case of a TChain.
726/// Maximum dimensions calculated on the basis of one TTree only
727/// might be too small when processing all the TTrees in one TChain.
728/// Instead of myTree.MakeClass(.., use myChain.MakeClass(..
729
730Int_t TTreePlayer::MakeClass(const char *classname, const char *option)
731{
732 TString opt = option;
733 opt.ToLower();
734
735 // Connect output files
736 const TString fileNameStem = classname ? classname : fTree->GetName();
737 const TString cppClassName = ROOT::Internal::GetCppName(fileNameStem);
738 if (cppClassName != fileNameStem)
739 Warning("TTreePlayer::MakeClass", "The %s name provided ('%s') is not a valid C++ identifier and will be converted to '%s'.",(classname ? "class" : "tree"), fileNameStem.Data(), cppClassName.Data());
740
741 TString thead;
742 thead.Form("%s.h", fileNameStem.Data());
743 FILE *fp = fopen(thead, "w");
744 if (!fp) {
745 Error("MakeClass","cannot open output file %s", thead.Data());
746 return 3;
747 }
748 TString tcimp;
749 tcimp.Form("%s.C", fileNameStem.Data());
750 FILE *fpc = fopen(tcimp, "w");
751 if (!fpc) {
752 Error("MakeClass","cannot open output file %s", tcimp.Data());
753 fclose(fp);
754 return 3;
755 }
756 TString treefile;
757 if (fTree->GetDirectory() && fTree->GetDirectory()->GetFile()) {
758 treefile = fTree->GetDirectory()->GetFile()->GetName();
759 } else {
760 treefile = "Memory Directory";
761 }
762 // In the case of a chain, the GetDirectory information usually does
763 // pertain to the Chain itself but to the currently loaded tree.
764 // So we can not rely on it.
765 bool ischain = fTree->InheritsFrom(TChain::Class());
766 bool isHbook = fTree->InheritsFrom("THbookTree");
767 if (isHbook)
768 treefile = fTree->GetTitle();
769
770//======================Generate classname.h=====================
771 // Print header
772 TObjArray *leaves = fTree->GetListOfLeaves();
773 Int_t nleaves = leaves ? leaves->GetEntriesFast() : 0;
774 TDatime td;
775 fprintf(fp,"//////////////////////////////////////////////////////////\n");
776 fprintf(fp,"// This class has been automatically generated on\n");
777 fprintf(fp,"// %s by ROOT version %s\n",td.AsString(),gROOT->GetVersion());
778 if (!ischain) {
779 fprintf(fp,"// from TTree %s/%s\n",fTree->GetName(),fTree->GetTitle());
780 fprintf(fp,"// found on file: %s\n",treefile.Data());
781 } else {
782 fprintf(fp,"// from TChain %s/%s\n",fTree->GetName(),fTree->GetTitle());
783 }
784 fprintf(fp,"//////////////////////////////////////////////////////////\n");
785 fprintf(fp,"\n");
786 fprintf(fp,"#ifndef %s_h\n",cppClassName.Data());
787 fprintf(fp,"#define %s_h\n",cppClassName.Data());
788 fprintf(fp,"\n");
789 fprintf(fp,"#include <TROOT.h>\n");
790 fprintf(fp,"#include <TChain.h>\n");
791 fprintf(fp,"#include <TFile.h>\n");
792 if (isHbook) fprintf(fp,"#include <THbookFile.h>\n");
793 if (opt.Contains("selector")) fprintf(fp,"#include <TSelector.h>\n");
794
795 // See if we can add any #include about the user data.
796 Int_t l;
797 fprintf(fp,"\n// Header file for the classes stored in the TTree if any.\n");
798 TList listOfHeaders;
799 listOfHeaders.SetOwner();
800 for (l=0;l<nleaves;l++) {
801 TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(l);
802 TBranch *branch = leaf->GetBranch();
803 TClass *cl = TClass::GetClass(branch->GetClassName());
804 if (cl && cl->IsLoaded() && !listOfHeaders.FindObject(cl->GetName())) {
805 const char *declfile = cl->GetDeclFileName();
806 if (declfile && declfile[0]) {
807 static const char *precstl = "prec_stl/";
808 static const unsigned int precstl_len = strlen(precstl);
809 static const char *rootinclude = "include/";
810 static const unsigned int rootinclude_len = strlen(rootinclude);
811 if (strncmp(declfile,precstl,precstl_len) == 0) {
812 fprintf(fp,"#include <%s>\n",declfile+precstl_len);
813 listOfHeaders.Add(new TNamed(cl->GetName(),declfile+precstl_len));
814 } else if (strncmp(declfile,"/usr/include/",13) == 0) {
815 fprintf(fp,"#include <%s>\n",declfile+strlen("/include/c++/"));
816 listOfHeaders.Add(new TNamed(cl->GetName(),declfile+strlen("/include/c++/")));
817 } else if (strstr(declfile,"/include/c++/") != nullptr) {
818 fprintf(fp,"#include <%s>\n",declfile+strlen("/include/c++/"));
819 listOfHeaders.Add(new TNamed(cl->GetName(),declfile+strlen("/include/c++/")));
820 } else if (strncmp(declfile,rootinclude,rootinclude_len) == 0) {
821 fprintf(fp,"#include <%s>\n",declfile+rootinclude_len);
822 listOfHeaders.Add(new TNamed(cl->GetName(),declfile+rootinclude_len));
823 } else {
824 fprintf(fp,"#include \"%s\"\n",declfile);
825 listOfHeaders.Add(new TNamed(cl->GetName(),declfile));
826 }
827 }
828 }
829 }
830
831 // First loop on all leaves to generate dimension declarations
832 Int_t len, lenb;
833 char blen[1024];
834 char *bname;
835 Int_t *leaflen = new Int_t[nleaves];
836 TObjArray *leafs = new TObjArray(nleaves);
837 for (l=0;l<nleaves;l++) {
838 TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(l);
839 leafs->AddAt(new TObjString(leaf->GetName()),l);
840 leaflen[l] = leaf->GetMaximum();
841 }
842 if (ischain) {
843 // In case of a chain, one must find the maximum dimension of each leaf
844 // One must be careful and not assume that all Trees in the chain
845 // have the same leaves and in the same order!
846 TChain *chain = (TChain*)fTree;
847 Int_t ntrees = chain->GetNtrees();
848 for (Int_t file=0;file<ntrees;file++) {
849 Long64_t first = chain->GetTreeOffset()[file];
850 chain->LoadTree(first);
851 for (l=0;l<nleaves;l++) {
852 TObjString *obj = (TObjString*)leafs->At(l);
853 TLeaf *leaf = chain->GetLeaf(obj->GetName());
854 if (leaf) {
855 leaflen[l] = TMath::Max(leaflen[l],leaf->GetMaximum());
856 }
857 }
858 }
859 chain->LoadTree(0);
860 }
861
862 fprintf(fp,"\n");
863 if (opt.Contains("selector")) {
864 fprintf(fp,"class %s : public TSelector {\n",cppClassName.Data());
865 fprintf(fp,"public :\n");
866 fprintf(fp," TTree *fChain; //!pointer to the analyzed TTree or TChain\n");
867 } else {
868 fprintf(fp,"class %s {\n",cppClassName.Data());
869 fprintf(fp,"public :\n");
870 fprintf(fp," TTree *fChain; //!pointer to the analyzed TTree or TChain\n");
871 fprintf(fp," Int_t fCurrent; //!current Tree number in a TChain\n");
872 }
873
874 fprintf(fp,"\n// Fixed size dimensions of array or collections stored in the TTree if any.\n");
875 leaves = fTree->GetListOfLeaves();
876 for (l=0;l<nleaves;l++) {
877 TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(l);
878 strlcpy(blen,leaf->GetName(),sizeof(blen));
879 bname = &blen[0];
880 while (*bname) {
881 if (*bname == '.') *bname='_';
882 if (*bname == ',') *bname='_';
883 if (*bname == ':') *bname='_';
884 if (*bname == '<') *bname='_';
885 if (*bname == '>') *bname='_';
886 bname++;
887 }
888 lenb = strlen(blen);
889 if (blen[lenb-1] == '_') {
890 blen[lenb-1] = 0;
891 len = leaflen[l];
892 if (len <= 0) len = 1;
893 fprintf(fp," static constexpr Int_t kMax%s = %d;\n",blen,len);
894 }
895 }
896 delete [] leaflen;
897 leafs->Delete();
898 delete leafs;
899
900// second loop on all leaves to generate type declarations
901 fprintf(fp,"\n // Declaration of leaf types\n");
902 TLeaf *leafcount;
903 TLeafObject *leafobj;
904 TBranchElement *bre=nullptr;
905 const char *headOK = " ";
906 const char *headcom = " //";
907 const char *head;
908 char branchname[1024];
909 char aprefix[1024];
910 TObjArray branches(100);
911 TObjArray mustInit(100);
912 TObjArray mustInitArr(100);
913 mustInitArr.SetOwner(false);
914 Int_t *leafStatus = new Int_t[nleaves];
915 for (l=0;l<nleaves;l++) {
916 Int_t kmax = 0;
917 head = headOK;
918 leafStatus[l] = 0;
919 TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(l);
920 len = leaf->GetLen(); if (len<=0) len = 1;
921 leafcount =leaf->GetLeafCount();
922 TBranch *branch = leaf->GetBranch();
923 branchname[0] = 0;
924 strlcpy(branchname,branch->GetName(),sizeof(branchname));
925 strlcpy(aprefix,branch->GetName(),sizeof(aprefix));
926 if (!branches.FindObject(branch)) branches.Add(branch);
927 else leafStatus[l] = 1;
928 if ( branch->GetNleaves() > 1) {
929 // More than one leaf for the branch we need to distinguish them
930 strlcat(branchname,".",sizeof(branchname));
931 strlcat(branchname,leaf->GetTitle(),sizeof(branchname));
932 if (leafcount) {
933 // remove any dimension in title
934 char *dim = (char*)strstr(branchname,"["); if (dim) dim[0] = 0;
935 }
936 } else {
937 strlcpy(branchname,branch->GetName(),sizeof(branchname));
938 }
939 char *twodim = (char*)strstr(leaf->GetTitle(),"][");
940 bname = branchname;
941 while (*bname) {
942 if (*bname == '.') *bname='_';
943 if (*bname == ',') *bname='_';
944 if (*bname == ':') *bname='_';
945 if (*bname == '<') *bname='_';
946 if (*bname == '>') *bname='_';
947 bname++;
948 }
949 if (branch->IsA() == TBranchObject::Class()) {
950 if (branch->GetListOfBranches()->GetEntriesFast()) {leafStatus[l] = 1; continue;}
951 leafobj = (TLeafObject*)leaf;
952 if (!leafobj->GetClass()) {leafStatus[l] = 1; head = headcom;}
953 fprintf(fp,"%s%-15s *%s;\n",head,leafobj->GetTypeName(), leafobj->GetName());
954 if (leafStatus[l] == 0) mustInit.Add(leafobj);
955 continue;
956 }
957 if (leafcount) {
958 len = leafcount->GetMaximum();
959 if (len<=0) len = 1;
960 strlcpy(blen,leafcount->GetName(),sizeof(blen));
961 bname = &blen[0];
962 while (*bname) {
963 if (*bname == '.') *bname='_';
964 if (*bname == ',') *bname='_';
965 if (*bname == ':') *bname='_';
966 if (*bname == '<') *bname='_';
967 if (*bname == '>') *bname='_';
968 bname++;
969 }
970 lenb = strlen(blen);
971 if (blen[lenb-1] == '_') {blen[lenb-1] = 0; kmax = 1;}
972 else snprintf(blen,sizeof(blen),"%d",len);
973 }
974 if (branch->IsA() == TBranchElement::Class()) {
975 bre = (TBranchElement*)branch;
976 if (bre->GetType() != 3 && bre->GetType() != 4
977 && bre->GetStreamerType() <= 0 && bre->GetListOfBranches()->GetEntriesFast()) {
978 leafStatus[l] = 0;
979 }
980 if (bre->GetType() == 3 || bre->GetType() == 4) {
981 fprintf(fp," %-15s %s_;\n","Int_t", ROOT::Internal::GetCppName(branchname).Data());
982 continue;
983 }
984 if (bre->IsBranchFolder()) {
985 fprintf(fp," %-15s *%s;\n",bre->GetClassName(), ROOT::Internal::GetCppName(branchname).Data());
986 mustInit.Add(bre);
987 continue;
988 } else {
989 if (branch->GetListOfBranches()->GetEntriesFast()) {leafStatus[l] = 1;}
990 }
991 if (bre->GetStreamerType() < 0) {
992 if (branch->GetListOfBranches()->GetEntriesFast()) {
993 fprintf(fp,"%s%-15s *%s;\n",headcom,bre->GetClassName(), ROOT::Internal::GetCppName(branchname).Data());
994 } else {
995 fprintf(fp,"%s%-15s *%s;\n",head,bre->GetClassName(), ROOT::Internal::GetCppName(branchname).Data());
996 mustInit.Add(bre);
997 }
998 continue;
999 }
1000 if (bre->GetStreamerType() == 0) {
1001 if (!TClass::GetClass(bre->GetClassName())->HasInterpreterInfo()) {leafStatus[l] = 1; head = headcom;}
1002 fprintf(fp,"%s%-15s *%s;\n",head,bre->GetClassName(), ROOT::Internal::GetCppName(branchname).Data());
1003 if (leafStatus[l] == 0) mustInit.Add(bre);
1004 continue;
1005 }
1006 if (bre->GetStreamerType() > 60) {
1007 TClass *cle = TClass::GetClass(bre->GetClassName());
1008 if (!cle) {leafStatus[l] = 1; continue;}
1009 if (bre->GetStreamerType() == 66) leafStatus[l] = 0;
1010 char brename[256];
1011 strlcpy(brename,bre->GetName(),255);
1012 char *bren = brename;
1013 char *adot = strrchr(bren,'.');
1014 if (adot) bren = adot+1;
1015 char *brack = strchr(bren,'[');
1016 if (brack) *brack = 0;
1018 if (elem) {
1019 if (elem->IsA() == TStreamerBase::Class()) {leafStatus[l] = 1; continue;}
1020 if (!TClass::GetClass(elem->GetTypeName())) {leafStatus[l] = 1; continue;}
1021 if (!TClass::GetClass(elem->GetTypeName())->HasInterpreterInfo()) {leafStatus[l] = 1; head = headcom;}
1022 if (leafcount) fprintf(fp,"%s%-15s %s[kMax%s];\n",head,elem->GetTypeName(), ROOT::Internal::GetCppName(branchname).Data(),blen);
1023 else fprintf(fp,"%s%-15s %s;\n",head,elem->GetTypeName(), ROOT::Internal::GetCppName(branchname).Data());
1024 } else {
1025 if (!TClass::GetClass(bre->GetClassName())->HasInterpreterInfo()) {leafStatus[l] = 1; head = headcom;}
1026 fprintf(fp,"%s%-15s %s;\n",head,bre->GetClassName(), ROOT::Internal::GetCppName(branchname).Data());
1027 }
1028 continue;
1029 }
1030 }
1031 if (strlen(leaf->GetTypeName()) == 0) {leafStatus[l] = 1; continue;}
1032 if (leafcount) {
1033 //len = leafcount->GetMaximum();
1034 //strlcpy(blen,leafcount->GetName(),sizeof(blen));
1035 //bname = &blen[0];
1036 //while (*bname) {if (*bname == '.') *bname='_'; bname++;}
1037 //lenb = strlen(blen);
1038 //Int_t kmax = 0;
1039 //if (blen[lenb-1] == '_') {blen[lenb-1] = 0; kmax = 1;}
1040 //else sprintf(blen,"%d",len);
1041
1042 const char *stars = " ";
1043 if (bre && bre->GetBranchCount2()) {
1044 stars = "*";
1045 }
1046 // Dimensions can be in the branchname for a split Object with a fix length C array.
1047 // Theses dimensions HAVE TO be placed after the dimension explicited by leafcount
1048 TString dimensions;
1049 char *dimInName = (char*) strstr(branchname,"[");
1050 if ( twodim || dimInName ) {
1051 if (dimInName) {
1052 dimensions = dimInName;
1053 dimInName[0] = 0; // terminate branchname before the array dimensions.
1054 }
1055 if (twodim) dimensions += (char*)(twodim+1);
1056 }
1057 const char* leafcountName = leafcount->GetName();
1058 char b2len[1024];
1059 if (bre && bre->GetBranchCount2()) {
1060 TLeaf * l2 = (TLeaf*)bre->GetBranchCount2()->GetListOfLeaves()->At(0);
1061 strlcpy(b2len,l2->GetName(),sizeof(b2len));
1062 bname = &b2len[0];
1063 while (*bname) {
1064 if (*bname == '.') *bname='_';
1065 if (*bname == ',') *bname='_';
1066 if (*bname == ':') *bname='_';
1067 if (*bname == '<') *bname='_';
1068 if (*bname == '>') *bname='_';
1069 bname++;
1070 }
1071 leafcountName = b2len;
1072 }
1073 if (dimensions.Length()) {
1074 if (kmax) fprintf(fp," %-14s %s%s[kMax%s]%s; //[%s]\n",leaf->GetTypeName(), stars,
1075 ROOT::Internal::GetCppName(branchname).Data(),blen,dimensions.Data(),leafcountName);
1076 else fprintf(fp," %-14s %s%s[%d]%s; //[%s]\n",leaf->GetTypeName(), stars,
1077 ROOT::Internal::GetCppName(branchname).Data(),len,dimensions.Data(),leafcountName);
1078 } else {
1079 if (kmax) fprintf(fp," %-14s %s%s[kMax%s]; //[%s]\n",leaf->GetTypeName(), stars, ROOT::Internal::GetCppName(branchname).Data(),blen,leafcountName);
1080 else fprintf(fp," %-14s %s%s[%d]; //[%s]\n",leaf->GetTypeName(), stars, ROOT::Internal::GetCppName(branchname).Data(),len,leafcountName);
1081 }
1082 if (stars[0]=='*') {
1083 TNamed *n;
1084 if (kmax) n = new TNamed(branchname, Form("kMax%s",blen));
1085 else n = new TNamed(branchname, Form("%d",len));
1086 mustInitArr.Add(n);
1087 }
1088 } else {
1089 if (strstr(branchname,"[")) len = 1;
1090 if (len < 2) fprintf(fp," %-15s %s;\n",leaf->GetTypeName(), ROOT::Internal::GetCppName(branchname).Data());
1091 else {
1092 if (twodim) fprintf(fp," %-15s %s%s;\n",leaf->GetTypeName(), ROOT::Internal::GetCppName(branchname).Data(),(char*)strstr(leaf->GetTitle(),"["));
1093 else fprintf(fp," %-15s %s[%d];\n",leaf->GetTypeName(), ROOT::Internal::GetCppName(branchname).Data(),len);
1094 }
1095 }
1096 }
1097
1098// generate list of branches
1099 fprintf(fp,"\n");
1100 fprintf(fp," // List of branches\n");
1101 for (l=0;l<nleaves;l++) {
1102 if (leafStatus[l]) continue;
1103 TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(l);
1104 fprintf(fp," TBranch *b_%s; //!\n",R__GetBranchPointerName(leaf).Data());
1105 }
1106
1107// generate class member functions prototypes
1108 if (opt.Contains("selector")) {
1109 fprintf(fp,"\n");
1110 fprintf(fp," %s(TTree * /*tree*/ =0) : fChain(0) { }\n",cppClassName.Data()) ;
1111 fprintf(fp," ~%s() override { }\n",cppClassName.Data());
1112 fprintf(fp," Int_t Version() const override { return 2; }\n");
1113 fprintf(fp," void Begin(TTree *tree) override;\n");
1114 fprintf(fp," void SlaveBegin(TTree *tree) override;\n");
1115 fprintf(fp," void Init(TTree *tree) override;\n");
1116 fprintf(fp," bool Notify() override;\n");
1117 fprintf(fp," bool Process(Long64_t entry) override;\n");
1118 fprintf(fp," Int_t GetEntry(Long64_t entry, Int_t getall = 0) override { return fChain ? fChain->GetTree()->GetEntry(entry, getall) : 0; }\n");
1119 fprintf(fp," void SetOption(const char *option) override { fOption = option; }\n");
1120 fprintf(fp," void SetObject(TObject *obj) override { fObject = obj; }\n");
1121 fprintf(fp," void SetInputList(TList *input) override { fInput = input; }\n");
1122 fprintf(fp," TList* GetOutputList() const override { return fOutput; }\n");
1123 fprintf(fp," void SlaveTerminate() override;\n");
1124 fprintf(fp," void Terminate() override;\n\n");
1125 fprintf(fp," ClassDefOverride(%s,0);\n",cppClassName.Data());
1126 fprintf(fp,"};\n");
1127 fprintf(fp,"\n");
1128 fprintf(fp,"#endif\n");
1129 fprintf(fp,"\n");
1130 } else {
1131 fprintf(fp,"\n");
1132 fprintf(fp," %s(TTree *tree=0);\n",cppClassName.Data());
1133 fprintf(fp," virtual ~%s();\n",cppClassName.Data());
1134 fprintf(fp," virtual Int_t Cut(Long64_t entry);\n");
1135 fprintf(fp," virtual Int_t GetEntry(Long64_t entry);\n");
1136 fprintf(fp," virtual Long64_t LoadTree(Long64_t entry);\n");
1137 fprintf(fp," virtual void Init(TTree *tree);\n");
1138 fprintf(fp," virtual void Loop();\n");
1139 fprintf(fp," virtual bool Notify();\n");
1140 fprintf(fp," virtual void Show(Long64_t entry = -1);\n");
1141 fprintf(fp,"};\n");
1142 fprintf(fp,"\n");
1143 fprintf(fp,"#endif\n");
1144 fprintf(fp,"\n");
1145 }
1146// generate code for class constructor
1147 fprintf(fp,"#ifdef %s_cxx\n",cppClassName.Data());
1148 if (!opt.Contains("selector")) {
1149 fprintf(fp,"%s::%s(TTree *tree) : fChain(0) \n",cppClassName.Data(),cppClassName.Data());
1150 fprintf(fp,"{\n");
1151 fprintf(fp,"// if parameter tree is not specified (or zero), connect the file\n");
1152 fprintf(fp,"// used to generate this class and read the Tree.\n");
1153 fprintf(fp," if (tree == 0) {\n");
1154 if (ischain) {
1155 fprintf(fp,"\n#ifdef SINGLE_TREE\n");
1156 fprintf(fp," // The following code should be used if you want this class to access\n");
1157 fprintf(fp," // a single tree instead of a chain\n");
1158 }
1159 if (isHbook) {
1160 fprintf(fp," THbookFile *f = (THbookFile*)gROOT->GetListOfBrowsables()->FindObject(\"%s\");\n",
1161 treefile.Data());
1162 fprintf(fp," if (!f) {\n");
1163 fprintf(fp," f = new THbookFile(\"%s\");\n",treefile.Data());
1164 fprintf(fp," }\n");
1165 Int_t hid;
1166 sscanf(fTree->GetName(),"h%d",&hid);
1167 fprintf(fp," tree = (TTree*)f->Get(%d);\n\n",hid);
1168 } else {
1169 fprintf(fp," TFile *f = (TFile*)gROOT->GetListOfFiles()->FindObject(\"%s\");\n",treefile.Data());
1170 fprintf(fp," if (!f || !f->IsOpen()) {\n");
1171 fprintf(fp," f = new TFile(\"%s\");\n",treefile.Data());
1172 fprintf(fp," }\n");
1173 if (fTree->GetDirectory() != fTree->GetCurrentFile()) {
1174 fprintf(fp," TDirectory * dir = (TDirectory*)f->Get(\"%s\");\n",fTree->GetDirectory()->GetPath());
1175 fprintf(fp," dir->GetObject(\"%s\",tree);\n\n",fTree->GetName());
1176 } else {
1177 fprintf(fp," f->GetObject(\"%s\",tree);\n\n",fTree->GetName());
1178 }
1179 }
1180 if (ischain) {
1181 fprintf(fp,"#else // SINGLE_TREE\n\n");
1182 fprintf(fp," // The following code should be used if you want this class to access a chain\n");
1183 fprintf(fp," // of trees.\n");
1184 fprintf(fp," TChain * chain = new TChain(\"%s\",\"%s\");\n",
1185 fTree->GetName(),fTree->GetTitle());
1186 {
1188 TIter next(((TChain*)fTree)->GetListOfFiles());
1189 TChainElement *element;
1190 while ((element = (TChainElement*)next())) {
1191 fprintf(fp," chain->Add(\"%s/%s\");\n",element->GetTitle(),element->GetName());
1192 }
1193 }
1194 fprintf(fp," tree = chain;\n");
1195 fprintf(fp,"#endif // SINGLE_TREE\n\n");
1196 }
1197 fprintf(fp," }\n");
1198 fprintf(fp," Init(tree);\n");
1199 fprintf(fp,"}\n");
1200 fprintf(fp,"\n");
1201 }
1202
1203// generate code for class destructor()
1204 if (!opt.Contains("selector")) {
1205 fprintf(fp,"%s::~%s()\n",cppClassName.Data(),cppClassName.Data());
1206 fprintf(fp,"{\n");
1207 fprintf(fp," if (!fChain) return;\n");
1208 if (isHbook) {
1209 //fprintf(fp," delete fChain->GetCurrentFile();\n");
1210 } else {
1211 fprintf(fp," delete fChain->GetCurrentFile();\n");
1212 }
1213 fprintf(fp,"}\n");
1214 fprintf(fp,"\n");
1215 }
1216// generate code for class member function GetEntry()
1217 if (!opt.Contains("selector")) {
1218 fprintf(fp,"Int_t %s::GetEntry(Long64_t entry)\n",cppClassName.Data());
1219 fprintf(fp,"{\n");
1220 fprintf(fp,"// Read contents of entry.\n");
1221
1222 fprintf(fp," if (!fChain) return 0;\n");
1223 fprintf(fp," return fChain->GetEntry(entry);\n");
1224 fprintf(fp,"}\n");
1225 }
1226// generate code for class member function LoadTree()
1227 if (!opt.Contains("selector")) {
1228 fprintf(fp,"Long64_t %s::LoadTree(Long64_t entry)\n",cppClassName.Data());
1229 fprintf(fp,"{\n");
1230 fprintf(fp,"// Set the environment to read one entry\n");
1231 fprintf(fp," if (!fChain) return -5;\n");
1232 fprintf(fp," Long64_t centry = fChain->LoadTree(entry);\n");
1233 fprintf(fp," if (centry < 0) return centry;\n");
1234 fprintf(fp," if (fChain->GetTreeNumber() != fCurrent) {\n");
1235 fprintf(fp," fCurrent = fChain->GetTreeNumber();\n");
1236 fprintf(fp," Notify();\n");
1237 fprintf(fp," }\n");
1238 fprintf(fp," return centry;\n");
1239 fprintf(fp,"}\n");
1240 fprintf(fp,"\n");
1241 }
1242
1243// generate code for class member function Init(), first pass = get branch pointer
1244 fprintf(fp,"void %s::Init(TTree *tree)\n",cppClassName.Data());
1245 fprintf(fp,"{\n");
1246 fprintf(fp," // The Init() function is called when the selector needs to initialize\n"
1247 " // a new tree or chain. Typically here the branch addresses and branch\n"
1248 " // pointers of the tree will be set.\n"
1249 " // It is normally not necessary to make changes to the generated\n"
1250 " // code, but the routine can be extended by the user if needed.\n"
1251 " // Init() will be called many times when running on PROOF\n"
1252 " // (once per file to be processed).\n\n");
1253 if (mustInit.Last()) {
1254 TIter next(&mustInit);
1255 TObject *obj;
1256 fprintf(fp," // Set object pointer\n");
1257 while( (obj = next()) ) {
1258 if (obj->InheritsFrom(TBranch::Class())) {
1259 strlcpy(branchname,((TBranch*)obj)->GetName(),sizeof(branchname));
1260 } else if (obj->InheritsFrom(TLeaf::Class())) {
1261 strlcpy(branchname,((TLeaf*)obj)->GetName(),sizeof(branchname));
1262 }
1263 branchname[1023]=0;
1264 bname = branchname;
1265 while (*bname) {
1266 if (*bname == '.') *bname='_';
1267 if (*bname == ',') *bname='_';
1268 if (*bname == ':') *bname='_';
1269 if (*bname == '<') *bname='_';
1270 if (*bname == '>') *bname='_';
1271 bname++;
1272 }
1273 fprintf(fp," %s = 0;\n",ROOT::Internal::GetCppName(branchname).Data() );
1274 }
1275 }
1276 if (mustInitArr.Last()) {
1277 TIter next(&mustInitArr);
1278 TNamed *info;
1279 fprintf(fp," // Set array pointer\n");
1280 while( (info = (TNamed*)next()) ) {
1281 fprintf(fp," for(int i=0; i<%s; ++i) %s[i] = 0;\n",info->GetTitle(),info->GetName());
1282 }
1283 fprintf(fp,"\n");
1284 }
1285 fprintf(fp," // Set branch addresses and branch pointers\n");
1286 fprintf(fp," if (!tree) return;\n");
1287 fprintf(fp," fChain = tree;\n");
1288 if (!opt.Contains("selector")) fprintf(fp," fCurrent = -1;\n");
1289 fprintf(fp," fChain->SetMakeClass(1);\n");
1290 fprintf(fp,"\n");
1291 for (l=0;l<nleaves;l++) {
1292 if (leafStatus[l]) continue;
1293 TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(l);
1294 len = leaf->GetLen();
1295 leafcount =leaf->GetLeafCount();
1296 TBranch *branch = leaf->GetBranch();
1297 strlcpy(aprefix,branch->GetName(),sizeof(aprefix));
1298
1299 if ( branch->GetNleaves() > 1) {
1300 // More than one leaf for the branch we need to distinguish them
1301 strlcpy(branchname,branch->GetName(),sizeof(branchname));
1302 strlcat(branchname,".",sizeof(branchname));
1303 strlcat(branchname,leaf->GetTitle(),sizeof(branchname));
1304 if (leafcount) {
1305 // remove any dimension in title
1306 char *dim = (char*)strstr(branchname,"["); if (dim) dim[0] = 0;
1307 }
1308 } else {
1309 strlcpy(branchname,branch->GetName(),sizeof(branchname));
1310 if (branch->IsA() == TBranchElement::Class()) {
1311 bre = (TBranchElement*)branch;
1312 if (bre->GetType() == 3 || bre->GetType()==4) strlcat(branchname,"_",sizeof(branchname));
1313 }
1314 }
1315 bname = branchname;
1316 char *brak = strstr(branchname,"["); if (brak) *brak = 0;
1317 char *twodim = (char*)strstr(bname,"["); if (twodim) *twodim = 0;
1318 while (*bname) {
1319 if (*bname == '.') *bname='_';
1320 if (*bname == ',') *bname='_';
1321 if (*bname == ':') *bname='_';
1322 if (*bname == '<') *bname='_';
1323 if (*bname == '>') *bname='_';
1324 bname++;
1325 }
1326 const char *maybedisable = "";
1327 if (branch != fTree->GetBranch(branch->GetName())) {
1328 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,false).Data());
1329 maybedisable = "// ";
1330 }
1331 if (branch->IsA() == TBranchObject::Class()) {
1332 if (branch->GetListOfBranches()->GetEntriesFast()) {
1333 fprintf(fp,"%s fChain->SetBranchAddress(\"%s\",(void*)-1,&b_%s);\n",maybedisable,branch->GetName(),R__GetBranchPointerName(leaf).Data());
1334 continue;
1335 }
1336 strlcpy(branchname,branch->GetName(),sizeof(branchname));
1337 }
1338 if (branch->IsA() == TBranchElement::Class()) {
1339 if (((TBranchElement*)branch)->GetType() == 3) len =1;
1340 if (((TBranchElement*)branch)->GetType() == 4) len =1;
1341 }
1342 if (leafcount) len = leafcount->GetMaximum()+1;
1343 if (len > 1) fprintf(fp,"%s fChain->SetBranchAddress(\"%s\", %s, &b_%s);\n",
1344 maybedisable,branch->GetName(), ROOT::Internal::GetCppName(branchname).Data(), R__GetBranchPointerName(leaf).Data());
1345 else fprintf(fp,"%s fChain->SetBranchAddress(\"%s\", &%s, &b_%s);\n",
1346 maybedisable,branch->GetName(), ROOT::Internal::GetCppName(branchname).Data(), R__GetBranchPointerName(leaf).Data());
1347 }
1348 //must call Notify in case of MakeClass
1349 if (!opt.Contains("selector")) {
1350 fprintf(fp," Notify();\n");
1351 }
1352
1353 fprintf(fp,"}\n");
1354 fprintf(fp,"\n");
1355
1356// generate code for class member function Notify()
1357 fprintf(fp,"bool %s::Notify()\n",cppClassName.Data());
1358 fprintf(fp,"{\n");
1359 fprintf(fp," // The Notify() function is called when a new file is opened. This\n"
1360 " // can be either for a new TTree in a TChain or when when a new TTree\n"
1361 " // is started when using PROOF. It is normally not necessary to make changes\n"
1362 " // to the generated code, but the routine can be extended by the\n"
1363 " // user if needed. The return value is currently not used.\n\n");
1364 fprintf(fp," return true;\n");
1365 fprintf(fp,"}\n");
1366 fprintf(fp,"\n");
1367
1368// generate code for class member function Show()
1369 if (!opt.Contains("selector")) {
1370 fprintf(fp,"void %s::Show(Long64_t entry)\n",cppClassName.Data());
1371 fprintf(fp,"{\n");
1372 fprintf(fp,"// Print contents of entry.\n");
1373 fprintf(fp,"// If entry is not specified, print current entry\n");
1374
1375 fprintf(fp," if (!fChain) return;\n");
1376 fprintf(fp," fChain->Show(entry);\n");
1377 fprintf(fp,"}\n");
1378 }
1379// generate code for class member function Cut()
1380 if (!opt.Contains("selector")) {
1381 fprintf(fp,"Int_t %s::Cut(Long64_t entry)\n",cppClassName.Data());
1382 fprintf(fp,"{\n");
1383 fprintf(fp,"// This function may be called from Loop.\n");
1384 fprintf(fp,"// returns 1 if entry is accepted.\n");
1385 fprintf(fp,"// returns -1 otherwise.\n");
1386
1387 fprintf(fp," return 1;\n");
1388 fprintf(fp,"}\n");
1389 }
1390 fprintf(fp,"#endif // #ifdef %s_cxx\n",cppClassName.Data());
1391
1392//======================Generate classname.C=====================
1393 if (!opt.Contains("selector")) {
1394 // generate code for class member function Loop()
1395 fprintf(fpc,"#define %s_cxx\n",cppClassName.Data());
1396 fprintf(fpc,"#include \"%s\"\n",thead.Data());
1397 fprintf(fpc,"#include <TH2.h>\n");
1398 fprintf(fpc,"#include <TStyle.h>\n");
1399 fprintf(fpc,"#include <TCanvas.h>\n");
1400 fprintf(fpc,"\n");
1401 fprintf(fpc,"void %s::Loop()\n",cppClassName.Data());
1402 fprintf(fpc,"{\n");
1403 fprintf(fpc,"// In a ROOT session, you can do:\n");
1404 fprintf(fpc,"// root> .L %s.C\n",fileNameStem.Data());
1405 fprintf(fpc,"// root> %s t\n",cppClassName.Data());
1406 fprintf(fpc,"// root> t.GetEntry(12); // Fill t data members with entry number 12\n");
1407 fprintf(fpc,"// root> t.Show(); // Show values of entry 12\n");
1408 fprintf(fpc,"// root> t.Show(16); // Read and show values of entry 16\n");
1409 fprintf(fpc,"// root> t.Loop(); // Loop on all entries\n");
1410 fprintf(fpc,"//\n");
1411 fprintf(fpc,"\n// This is the loop skeleton where:\n");
1412 fprintf(fpc,"// jentry is the global entry number in the chain\n");
1413 fprintf(fpc,"// ientry is the entry number in the current Tree\n");
1414 fprintf(fpc,"// Note that the argument to GetEntry must be:\n");
1415 fprintf(fpc,"// jentry for TChain::GetEntry\n");
1416 fprintf(fpc,"// ientry for TTree::GetEntry and TBranch::GetEntry\n");
1417 fprintf(fpc,"//\n");
1418 fprintf(fpc,"// To read only selected branches, Insert statements like:\n");
1419 fprintf(fpc,"// METHOD1:\n");
1420 fprintf(fpc,"// fChain->SetBranchStatus(\"*\",0); // disable all branches\n");
1421 fprintf(fpc,"// fChain->SetBranchStatus(\"branchname\",1); // activate branchname\n");
1422 fprintf(fpc,"// METHOD2: replace line\n");
1423 fprintf(fpc,"// fChain->GetEntry(jentry); //read all branches\n");
1424 fprintf(fpc,"//by b_branchname->GetEntry(ientry); //read only this branch\n");
1425 fprintf(fpc," if (fChain == 0) return;\n");
1426 fprintf(fpc,"\n Long64_t nentries = fChain->GetEntriesFast();\n");
1427 fprintf(fpc,"\n Long64_t nbytes = 0, nb = 0;\n");
1428 fprintf(fpc," for (Long64_t jentry=0; jentry<nentries;jentry++) {\n");
1429 fprintf(fpc," Long64_t ientry = LoadTree(jentry);\n");
1430 fprintf(fpc," if (ientry < 0) break;\n");
1431 fprintf(fpc," nb = fChain->GetEntry(jentry); nbytes += nb;\n");
1432 fprintf(fpc," // if (Cut(ientry) < 0) continue;\n");
1433 fprintf(fpc," }\n");
1434 fprintf(fpc,"}\n");
1435 }
1436 if (opt.Contains("selector")) {
1437 // generate usage comments and list of includes
1438 fprintf(fpc,"#define %s_cxx\n",cppClassName.Data());
1439 fprintf(fpc,"// The class definition in %s.h has been generated automatically\n",fileNameStem.Data());
1440 fprintf(fpc,"// by the ROOT utility TTree::MakeSelector(). This class is derived\n");
1441 fprintf(fpc,"// from the ROOT class TSelector. For more information on the TSelector\n"
1442 "// framework see $ROOTSYS/README/README.SELECTOR or the ROOT User Manual.\n\n");
1443 fprintf(fpc,"// The following methods are defined in this file:\n");
1444 fprintf(fpc,"// Begin(): called every time a loop on the tree starts,\n");
1445 fprintf(fpc,"// a convenient place to create your histograms.\n");
1446 fprintf(fpc,"// SlaveBegin(): called after Begin(), when on PROOF called only on the\n"
1447 "// slave servers.\n");
1448 fprintf(fpc,"// Process(): called for each event, in this function you decide what\n");
1449 fprintf(fpc,"// to read and fill your histograms.\n");
1450 fprintf(fpc,"// SlaveTerminate: called at the end of the loop on the tree, when on PROOF\n"
1451 "// called only on the slave servers.\n");
1452 fprintf(fpc,"// Terminate(): called at the end of the loop on the tree,\n");
1453 fprintf(fpc,"// a convenient place to draw/fit your histograms.\n");
1454 fprintf(fpc,"//\n");
1455 fprintf(fpc,"// To use this file, try the following session on your Tree T:\n");
1456 fprintf(fpc,"//\n");
1457 fprintf(fpc,"// root> T->Process(\"%s.C\")\n",fileNameStem.Data());
1458 fprintf(fpc,"// root> T->Process(\"%s.C\",\"some options\")\n",fileNameStem.Data());
1459 fprintf(fpc,"// root> T->Process(\"%s.C+\")\n",fileNameStem.Data());
1460 fprintf(fpc,"//\n\n");
1461 fprintf(fpc,"#include \"%s\"\n",thead.Data());
1462 fprintf(fpc,"#include <TH2.h>\n");
1463 fprintf(fpc,"#include <TStyle.h>\n");
1464 fprintf(fpc,"\n");
1465 // generate code for class member function Begin
1466 fprintf(fpc,"\n");
1467 fprintf(fpc,"void %s::Begin(TTree * /*tree*/)\n",cppClassName.Data());
1468 fprintf(fpc,"{\n");
1469 fprintf(fpc," // The Begin() function is called at the start of the query.\n");
1470 fprintf(fpc," // When running with PROOF Begin() is only called on the client.\n");
1471 fprintf(fpc," // The tree argument is deprecated (on PROOF 0 is passed).\n");
1472 fprintf(fpc,"\n");
1473 fprintf(fpc," TString option = GetOption();\n");
1474 fprintf(fpc,"\n");
1475 fprintf(fpc,"}\n");
1476 // generate code for class member function SlaveBegin
1477 fprintf(fpc,"\n");
1478 fprintf(fpc,"void %s::SlaveBegin(TTree * /*tree*/)\n",cppClassName.Data());
1479 fprintf(fpc,"{\n");
1480 fprintf(fpc," // The SlaveBegin() function is called after the Begin() function.\n");
1481 fprintf(fpc," // When running with PROOF SlaveBegin() is called on each slave server.\n");
1482 fprintf(fpc," // The tree argument is deprecated (on PROOF 0 is passed).\n");
1483 fprintf(fpc,"\n");
1484 fprintf(fpc," TString option = GetOption();\n");
1485 fprintf(fpc,"\n");
1486 fprintf(fpc,"}\n");
1487 // generate code for class member function Process
1488 fprintf(fpc,"\n");
1489 fprintf(fpc,"bool %s::Process(Long64_t entry)\n",cppClassName.Data());
1490 fprintf(fpc,"{\n");
1491 fprintf(fpc," // The Process() function is called for each entry in the tree (or possibly\n"
1492 " // keyed object in the case of PROOF) to be processed. The entry argument\n"
1493 " // specifies which entry in the currently loaded tree is to be processed.\n"
1494 " // It can be passed to either %s::GetEntry() or TBranch::GetEntry()\n"
1495 " // to read either all or the required parts of the data. When processing\n"
1496 " // keyed objects with PROOF, the object is already loaded and is available\n"
1497 " // via the fObject pointer.\n"
1498 " //\n"
1499 " // This function should contain the \"body\" of the analysis. It can contain\n"
1500 " // simple or elaborate selection criteria, run algorithms on the data\n"
1501 " // of the event and typically fill histograms.\n"
1502 " //\n"
1503 " // The processing can be stopped by calling Abort().\n"
1504 " //\n"
1505 " // Use fStatus to set the return value of TTree::Process().\n"
1506 " //\n"
1507 " // The return value is currently not used.\n\n", cppClassName.Data());
1508 fprintf(fpc,"\n");
1509 fprintf(fpc," return true;\n");
1510 fprintf(fpc,"}\n");
1511 // generate code for class member function SlaveTerminate
1512 fprintf(fpc,"\n");
1513 fprintf(fpc,"void %s::SlaveTerminate()\n",cppClassName.Data());
1514 fprintf(fpc,"{\n");
1515 fprintf(fpc," // The SlaveTerminate() function is called after all entries or objects\n"
1516 " // have been processed. When running with PROOF SlaveTerminate() is called\n"
1517 " // on each slave server.");
1518 fprintf(fpc,"\n");
1519 fprintf(fpc,"\n");
1520 fprintf(fpc,"}\n");
1521 // generate code for class member function Terminate
1522 fprintf(fpc,"\n");
1523 fprintf(fpc,"void %s::Terminate()\n",cppClassName.Data());
1524 fprintf(fpc,"{\n");
1525 fprintf(fpc," // The Terminate() function is the last function to be called during\n"
1526 " // a query. It always runs on the client, it can be used to present\n"
1527 " // the results graphically or save the results to file.");
1528 fprintf(fpc,"\n");
1529 fprintf(fpc,"\n");
1530 fprintf(fpc,"}\n");
1531 }
1532 Info("MakeClass","Files: %s and %s generated from TTree: %s",thead.Data(),tcimp.Data(),fTree->GetName());
1533 delete [] leafStatus;
1534 fclose(fp);
1535 fclose(fpc);
1536
1537 return 0;
1538}
1539
1540
1541////////////////////////////////////////////////////////////////////////////////
1542/// Generate skeleton function for this Tree
1543///
1544/// The function code is written on filename.
1545/// If filename is 0, filename will be called nameoftree.C
1546///
1547/// The generated code includes the following:
1548/// - Identification of the original Tree and Input file name
1549/// - Connection of the Tree file
1550/// - Declaration of Tree variables
1551/// - Setting of branches addresses
1552/// - A skeleton for the entry loop
1553///
1554/// To use this function:
1555/// - connect your Tree file (eg: TFile f("myfile.root");)
1556/// - T->MakeCode("anal.C");
1557/// where T is the name of the Tree in file myfile.root
1558/// and anal.C the name of the file created by this function.
1559///
1560/// NOTE: Since the implementation of this function, a new and better
1561/// function TTree::MakeClass() has been developed.
1562
1564{
1565// Connect output file
1566 TString tfile;
1567 if (filename)
1568 tfile = filename;
1569 else
1570 tfile.Form("%s.C", fTree->GetName());
1571 FILE *fp = fopen(tfile, "w");
1572 if (!fp) {
1573 Error("MakeCode","cannot open output file %s", tfile.Data());
1574 return 3;
1575 }
1576 TString treefile;
1577 if (fTree->GetDirectory() && fTree->GetDirectory()->GetFile()) {
1578 treefile = fTree->GetDirectory()->GetFile()->GetName();
1579 } else {
1580 treefile = "Memory Directory";
1581 }
1582 // In the case of a chain, the GetDirectory information usually does
1583 // pertain to the Chain itself but to the currently loaded tree.
1584 // So we can not rely on it.
1585 bool ischain = fTree->InheritsFrom(TChain::Class());
1586
1587// Print header
1588 TObjArray *leaves = fTree->GetListOfLeaves();
1589 Int_t nleaves = leaves ? leaves->GetEntriesFast() : 0;
1590 TDatime td;
1591 fprintf(fp,"{\n");
1592 fprintf(fp,"//////////////////////////////////////////////////////////\n");
1593 fprintf(fp,"// This file has been automatically generated \n");
1594 fprintf(fp,"// (%s by ROOT version%s)\n",td.AsString(),gROOT->GetVersion());
1595 if (!ischain) {
1596 fprintf(fp,"// from TTree %s/%s\n",fTree->GetName(),fTree->GetTitle());
1597 fprintf(fp,"// found on file: %s\n",treefile.Data());
1598 } else {
1599 fprintf(fp,"// from TChain %s/%s\n",fTree->GetName(),fTree->GetTitle());
1600 }
1601 fprintf(fp,"//////////////////////////////////////////////////////////\n");
1602 fprintf(fp,"\n");
1603 fprintf(fp,"\n");
1604
1605
1606// Reset and file connect
1607 fprintf(fp,"//Reset ROOT and connect tree file\n");
1608 fprintf(fp," gROOT->Reset();\n");
1609 if (ischain) {
1610 fprintf(fp,"\n#ifdef SINGLE_TREE\n");
1611 fprintf(fp," // The following code should be used if you want this code to access\n");
1612 fprintf(fp," // a single tree instead of a chain\n");
1613 }
1614 fprintf(fp," TFile *f = (TFile*)gROOT->GetListOfFiles()->FindObject(\"%s\");\n",treefile.Data());
1615 fprintf(fp," if (!f) {\n");
1616 fprintf(fp," f = new TFile(\"%s\");\n",treefile.Data());
1617 fprintf(fp," }\n");
1618 if (fTree->GetDirectory() != fTree->GetCurrentFile()) {
1619 fprintf(fp," TDirectory * dir = (TDirectory*)f->Get(\"%s\");\n",fTree->GetDirectory()->GetPath());
1620 fprintf(fp," dir->GetObject(\"%s\",tree);\n\n",fTree->GetName());
1621 } else {
1622 fprintf(fp," f->GetObject(\"%s\",tree);\n\n",fTree->GetName());
1623 }
1624 if (ischain) {
1625 fprintf(fp,"#else // SINGLE_TREE\n\n");
1626 fprintf(fp," // The following code should be used if you want this code to access a chain\n");
1627 fprintf(fp," // of trees.\n");
1628 fprintf(fp," TChain *%s = new TChain(\"%s\",\"%s\");\n",
1630 {
1632 TIter next(((TChain*)fTree)->GetListOfFiles());
1633 TChainElement *element;
1634 while ((element = (TChainElement*)next())) {
1635 fprintf(fp," %s->Add(\"%s/%s\");\n",fTree->GetName(),element->GetTitle(),element->GetName());
1636 }
1637 }
1638 fprintf(fp,"#endif // SINGLE_TREE\n\n");
1639 }
1640
1641// First loop on all leaves to generate type declarations
1642 fprintf(fp,"//Declaration of leaves types\n");
1643 Int_t len, l;
1644 TLeaf *leafcount;
1645 TLeafObject *leafobj;
1646 char *bname;
1647 const char *headOK = " ";
1648 const char *headcom = " //";
1649 const char *head;
1650 char branchname[1024];
1651 for (l=0;l<nleaves;l++) {
1652 TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(l);
1653 len = leaf->GetLen();
1654 leafcount =leaf->GetLeafCount();
1655 TBranch *branch = leaf->GetBranch();
1656 if (branch->GetListOfBranches()->GetEntriesFast() > 0) continue;
1657
1658 if ( branch->GetNleaves() > 1) {
1659 // More than one leaf for the branch we need to distinguish them
1660 strlcpy(branchname,branch->GetName(),sizeof(branchname));
1661 strlcat(branchname,".",sizeof(branchname));
1662 strlcat(branchname,leaf->GetTitle(),sizeof(branchname));
1663 if (leafcount) {
1664 // remove any dimension in title
1665 char *dim = (char*)strstr(branchname,"[");
1666 if (dim) dim[0] = 0;
1667 }
1668 } else {
1669 if (leafcount) strlcpy(branchname,branch->GetName(),sizeof(branchname));
1670 else strlcpy(branchname,leaf->GetTitle(),sizeof(branchname));
1671 }
1672 char *twodim = (char*)strstr(leaf->GetTitle(),"][");
1673 bname = branchname;
1674 while (*bname) {
1675 if (*bname == '.') *bname='_';
1676 if (*bname == ',') *bname='_';
1677 if (*bname == ':') *bname='_';
1678 if (*bname == '<') *bname='_';
1679 if (*bname == '>') *bname='_';
1680 bname++;
1681 }
1682 if (branch->IsA() == TBranchObject::Class()) {
1683 leafobj = (TLeafObject*)leaf;
1684 if (leafobj->GetClass()) head = headOK;
1685 else head = headcom;
1686 fprintf(fp,"%s%-15s *%s = 0;\n",head,leafobj->GetTypeName(), leafobj->GetName());
1687 continue;
1688 }
1689 if (leafcount) {
1690 len = leafcount->GetMaximum();
1691 // Dimensions can be in the branchname for a split Object with a fix length C array.
1692 // Theses dimensions HAVE TO be placed after the dimension explicited by leafcount
1693 char *dimInName = (char*) strstr(branchname,"[");
1694 TString dimensions;
1695 if ( twodim || dimInName ) {
1696 if (dimInName) {
1697 dimensions = dimInName;
1698 dimInName[0] = 0; // terminate branchname before the array dimensions.
1699 }
1700 if (twodim) dimensions += (char*)(twodim+1);
1701 }
1702 if (dimensions.Length()) {
1703 fprintf(fp," %-15s %s[%d]%s;\n",leaf->GetTypeName(), branchname,len,dimensions.Data());
1704 } else {
1705 fprintf(fp," %-15s %s[%d];\n",leaf->GetTypeName(), branchname,len);
1706 }
1707 } else {
1708 if (strstr(branchname,"[")) len = 1;
1709 if (len < 2) fprintf(fp," %-15s %s;\n",leaf->GetTypeName(), branchname);
1710 else fprintf(fp," %-15s %s[%d];\n",leaf->GetTypeName(), branchname,len);
1711 }
1712 }
1713
1714// Second loop on all leaves to set the corresponding branch address
1715 fprintf(fp,"\n // Set branch addresses.\n");
1716 for (l=0;l<nleaves;l++) {
1717 TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(l);
1718 len = leaf->GetLen();
1719 leafcount =leaf->GetLeafCount();
1720 TBranch *branch = leaf->GetBranch();
1721
1722 if ( branch->GetNleaves() > 1) {
1723 // More than one leaf for the branch we need to distinguish them
1724 strlcpy(branchname,branch->GetName(),sizeof(branchname));
1725 strlcat(branchname,".",sizeof(branchname));
1726 strlcat(branchname,leaf->GetTitle(),sizeof(branchname));
1727 if (leafcount) {
1728 // remove any dimension in title
1729 char *dim = (char*)strstr(branchname,"[");
1730 if (dim) dim[0] = 0;
1731 }
1732 } else {
1733 if (leafcount) strlcpy(branchname,branch->GetName(),sizeof(branchname));
1734 else strlcpy(branchname,leaf->GetTitle(),sizeof(branchname));
1735 }
1736 bname = branchname;
1737 while (*bname) {
1738 if (*bname == '.') *bname='_';
1739 if (*bname == ',') *bname='_';
1740 if (*bname == ':') *bname='_';
1741 if (*bname == '<') *bname='_';
1742 if (*bname == '>') *bname='_';
1743 bname++;
1744 }
1745 char *brak = strstr(branchname,"[");
1746 if (brak) *brak = 0;
1747 head = headOK;
1748 if (branch->IsA() == TBranchObject::Class()) {
1749 strlcpy(branchname,branch->GetName(),sizeof(branchname));
1750 leafobj = (TLeafObject*)leaf;
1751 if (!leafobj->GetClass()) head = headcom;
1752 }
1753 if (leafcount) len = leafcount->GetMaximum()+1;
1754 if (len > 1 || brak) fprintf(fp,"%s%s->SetBranchAddress(\"%s\",%s);\n",head,fTree->GetName(),branch->GetName(),branchname);
1755 else fprintf(fp,"%s%s->SetBranchAddress(\"%s\",&%s);\n",head,fTree->GetName(),branch->GetName(),branchname);
1756 }
1757
1758//Generate instructions to make the loop on entries
1759 fprintf(fp,"\n// This is the loop skeleton\n");
1760 fprintf(fp,"// To read only selected branches, Insert statements like:\n");
1761 fprintf(fp,"// %s->SetBranchStatus(\"*\",0); // disable all branches\n",fTree->GetName());
1762 fprintf(fp,"// %s->SetBranchStatus(\"branchname\",1); // activate branchname\n",GetName());
1763 fprintf(fp,"\n Long64_t nentries = %s->GetEntries();\n",fTree->GetName());
1764 fprintf(fp,"\n Long64_t nbytes = 0;\n");
1765 fprintf(fp,"// for (Long64_t i=0; i<nentries;i++) {\n");
1766 fprintf(fp,"// nbytes += %s->GetEntry(i);\n",fTree->GetName());
1767 fprintf(fp,"// }\n");
1768 fprintf(fp,"}\n");
1769
1770 printf("Macro: %s generated from Tree: %s\n",tfile.Data(), fTree->GetName());
1771 fclose(fp);
1772
1773 return 0;
1774}
1775
1776////////////////////////////////////////////////////////////////////////////////
1777/// Generate a skeleton analysis class for this Tree using TBranchProxy.
1778/// TBranchProxy is the base of a class hierarchy implementing an
1779/// indirect access to the content of the branches of a TTree.
1780///
1781/// "proxyClassname" is expected to be of the form:
1782/// ~~~{.cpp}
1783/// [path/]fileprefix
1784/// ~~~
1785/// The skeleton will then be generated in the file:
1786/// ~~~{.cpp}
1787/// fileprefix.h
1788/// ~~~
1789/// located in the current directory or in 'path/' if it is specified.
1790/// The class generated will be named 'fileprefix'.
1791/// If the fileprefix contains a period, the right side of the period
1792/// will be used as the extension (instead of 'h') and the left side
1793/// will be used as the classname.
1794///
1795/// "macrofilename" and optionally "cutfilename" are expected to point
1796/// to source file which will be included in by the generated skeletong.
1797/// Method of the same name as the file(minus the extension and path)
1798/// will be called by the generated skeleton's Process method as follow:
1799/// ~~~{.cpp}
1800/// [if (cutfilename())] htemp->Fill(macrofilename());
1801/// ~~~
1802/// "option" can be used select some of the optional features during
1803/// the code generation. The possible options are:
1804/// - nohist : indicates that the generated ProcessFill should not
1805/// fill the histogram.
1806///
1807/// 'maxUnrolling' controls how deep in the class hierarchy does the
1808/// system 'unroll' class that are not split. 'unrolling' a class
1809/// will allow direct access to its data members a class (this
1810/// emulates the behavior of TTreeFormula).
1811///
1812/// The main features of this skeleton are:
1813///
1814/// * on-demand loading of branches
1815/// * ability to use the 'branchname' as if it was a data member
1816/// * protection against array out-of-bound
1817/// * ability to use the branch data as object (when the user code is available)
1818///
1819/// For example with Event.root, if
1820/// ~~~{.cpp}
1821/// Double_t somepx = fTracks.fPx[2];
1822/// ~~~
1823/// is executed by one of the method of the skeleton,
1824/// somepx will be updated with the current value of fPx of the 3rd track.
1825///
1826/// Both macrofilename and the optional cutfilename are expected to be
1827/// the name of source files which contain at least a free standing
1828/// function with the signature:
1829/// ~~~{.cpp}
1830/// x_t macrofilename(); // i.e function with the same name as the file
1831/// ~~~
1832/// and
1833/// ~~~{.cpp}
1834/// y_t cutfilename(); // i.e function with the same name as the file
1835/// ~~~
1836/// x_t and y_t needs to be types that can convert respectively to a double
1837/// and a bool (because the skeleton uses:
1838/// ~~~{.cpp}
1839/// if (cutfilename()) htemp->Fill(macrofilename());
1840/// ~~~
1841/// This 2 functions are run in a context such that the branch names are
1842/// available as local variables of the correct (read-only) type.
1843///
1844/// Note that if you use the same 'variable' twice, it is more efficient
1845/// to 'cache' the value. For example
1846/// ~~~{.cpp}
1847/// Int_t n = fEventNumber; // Read fEventNumber
1848/// if (n<10 || n>10) { ... }
1849/// ~~~
1850/// is more efficient than
1851/// ~~~{.cpp}
1852/// if (fEventNumber<10 || fEventNumber>10)
1853/// ~~~
1854/// Access to TClonesArray.
1855///
1856/// If a branch (or member) is a TClonesArray (let's say fTracks), you
1857/// can access the TClonesArray itself by using ->:
1858/// ~~~{.cpp}
1859/// fTracks->GetLast();
1860/// ~~~
1861/// However this will load the full TClonesArray object and its content.
1862/// To quickly read the size of the TClonesArray use (note the dot):
1863/// ~~~{.cpp}
1864/// fTracks.GetEntries();
1865/// ~~~
1866/// This will read only the size from disk if the TClonesArray has been
1867/// split.
1868/// To access the content of the TClonesArray, use the [] operator:
1869/// ~~~
1870/// float px = fTracks[i].fPx; // fPx of the i-th track
1871/// ~~~
1872/// Warning:
1873///
1874/// The variable actually use for access are 'wrapper' around the
1875/// real data type (to add autoload for example) and hence getting to
1876/// the data involves the implicit call to a C++ conversion operator.
1877/// This conversion is automatic in most case. However it is not invoked
1878/// in a few cases, in particular in variadic function (like printf).
1879/// So when using printf you should either explicitly cast the value or
1880/// use any intermediary variable:
1881/// ~~~{.cpp}
1882/// fprintf(stdout,"trs[%d].a = %d\n",i,(int)trs.a[i]);
1883/// ~~~
1884/// Also, optionally, the generated selector will also call methods named
1885/// macrofilename_methodname in each of 6 main selector methods if the method
1886/// macrofilename_methodname exist (Where macrofilename is stripped of its
1887/// extension).
1888///
1889/// Concretely, with the script named h1analysisProxy.C,
1890///
1891/// - The method calls the method (if it exist)
1892/// - Begin -> void h1analysisProxy_Begin(TTree*);
1893/// - SlaveBegin -> void h1analysisProxy_SlaveBegin(TTree*);
1894/// - Notify -> bool h1analysisProxy_Notify();
1895/// - Process -> bool h1analysisProxy_Process(Long64_t);
1896/// - SlaveTerminate -> void h1analysisProxy_SlaveTerminate();
1897/// - Terminate -> void h1analysisProxy_Terminate();
1898///
1899/// If a file name macrofilename.h (or .hh, .hpp, .hxx, .hPP, .hXX) exist
1900/// it is included before the declaration of the proxy class. This can
1901/// be used in particular to insure that the include files needed by
1902/// the macro file are properly loaded.
1903///
1904/// The default histogram is accessible via the variable named 'htemp'.
1905///
1906/// If the library of the classes describing the data in the branch is
1907/// loaded, the skeleton will add the needed `include` statements and
1908/// give the ability to access the object stored in the branches.
1909///
1910/// To draw px using the file `hsimple.root (generated by the
1911/// hsimple.C tutorial), we need a file named hsimple.cxx:
1912///
1913/// ~~~{.cpp}
1914/// double hsimple() {
1915/// return px;
1916/// }
1917/// ~~~
1918/// MakeProxy can then be used indirectly via the TTree::Draw interface
1919/// as follow:
1920/// ~~~{.cpp}
1921/// new TFile("hsimple.root")
1922/// ntuple->Draw("hsimple.cxx");
1923/// ~~~
1924/// A more complete example is available in the tutorials directory:
1925/// h1analysisProxy.cxx , h1analysProxy.h and h1analysisProxyCut.C
1926/// which reimplement the selector found in h1analysis.C
1927
1928Int_t TTreePlayer::MakeProxy(const char *proxyClassname,
1929 const char *macrofilename, const char *cutfilename,
1930 const char *option, Int_t maxUnrolling)
1931{
1932 if (macrofilename==nullptr || strlen(macrofilename)==0 ) {
1933 // We currently require a file name for the script
1934 Error("MakeProxy","A file name for the user script is required");
1935 return 0;
1936 }
1937
1938 ROOT::Internal::TTreeProxyGenerator gp(fTree,macrofilename,cutfilename,proxyClassname,option,maxUnrolling);
1939
1940 return 0;
1941}
1942
1943
1944////////////////////////////////////////////////////////////////////////////////
1945/// Generate skeleton selector class for this tree.
1946///
1947/// The following files are produced: classname.h and classname.C.
1948/// If classname is 0, the selector will be called "nameoftree".
1949/// The option can be used to specify the branches that will have a data member.
1950/// - If option is empty, readers will be generated for each leaf.
1951/// - If option is "@", readers will be generated for the topmost branches.
1952/// - Individual branches can also be picked by their name:
1953/// - "X" generates readers for leaves of X.
1954/// - "@X" generates a reader for X as a whole.
1955/// - "@X;Y" generates a reader for X as a whole and also readers for the
1956/// leaves of Y.
1957/// - For further examples see the figure below.
1958///
1959/// \image html ttree_makeselector_option_examples.png
1960///
1961/// The generated code in classname.h includes the following:
1962/// - Identification of the original Tree and Input file name
1963/// - Definition of selector class (data and functions)
1964/// - The following class functions:
1965/// - constructor and destructor
1966/// - void Begin(TTree *tree)
1967/// - void SlaveBegin(TTree *tree)
1968/// - void Init(TTree *tree)
1969/// - bool Notify()
1970/// - bool Process(Long64_t entry)
1971/// - void Terminate()
1972/// - void SlaveTerminate()
1973///
1974/// The selector derives from TSelector.
1975/// The generated code in classname.C includes empty functions defined above.
1976///
1977/// To use this function:
1978/// - connect your Tree file (eg: `TFile f("myfile.root");`)
1979/// - `T->MakeSelector("myselect");`
1980/// where `T` is the name of the Tree in file `myfile.root`
1981/// and `myselect.h`, `myselect.C` the name of the files created by this
1982/// function.
1983///
1984/// In a ROOT session, you can do:
1985/// ~~~ {.cpp}
1986/// root > T->Process("myselect.C")
1987/// ~~~
1989{
1990 if (!classname) classname = fTree->GetName();
1991
1993
1994 return 0;
1995}
1996
1997
1998////////////////////////////////////////////////////////////////////////////////
1999/// Interface to the Principal Components Analysis class.
2000///
2001/// Create an instance of TPrincipal
2002/// Fill it with the selected variables
2003///
2004/// - if option "n" is specified, the TPrincipal object is filled with
2005/// normalized variables.
2006/// - If option "p" is specified, compute the principal components
2007/// - If option "p" and "d" print results of analysis
2008/// - If option "p" and "h" generate standard histograms
2009/// - If option "p" and "c" generate code of conversion functions
2010///
2011/// return a pointer to the TPrincipal object. It is the user responsibility
2012/// to delete this object.
2013///
2014/// The option default value is "np"
2015///
2016/// See TTreePlayer::DrawSelect for explanation of the other parameters.
2017
2018TPrincipal *TTreePlayer::Principal(const char *varexp, const char *selection, Option_t *option, Long64_t nentries, Long64_t firstentry)
2019{
2020 TTreeFormula **var;
2021 std::vector<TString> cnames;
2022 TString opt = option;
2023 opt.ToLower();
2024 TPrincipal *principal = nullptr;
2025 Long64_t entry,entryNumber;
2026 Int_t i,nch;
2027 Int_t ncols = 8; // by default first 8 columns are printed only
2028 TObjArray *leaves = fTree->GetListOfLeaves();
2029 Int_t nleaves = leaves->GetEntriesFast();
2030 if (nleaves < ncols) ncols = nleaves;
2031 nch = varexp ? strlen(varexp) : 0;
2032
2033 nentries = GetEntriesToProcess(firstentry, nentries);
2034
2035//*-*- Compile selection expression if there is one
2036 TTreeFormula *select = nullptr;
2037 if (strlen(selection)) {
2038 select = new TTreeFormula("Selection",selection,fTree);
2039 if (!select) return principal;
2040 if (!select->GetNdim()) { delete select; return principal; }
2041 fFormulaList->Add(select);
2042 }
2043//*-*- if varexp is empty, take first 8 columns by default
2044 int allvar = 0;
2045 if (varexp && !strcmp(varexp, "*")) { ncols = nleaves; allvar = 1; }
2046 if (nch == 0 || allvar) {
2047 for (i=0;i<ncols;i++) {
2048 cnames.push_back( ((TLeaf*)leaves->At(i))->GetName() );
2049 }
2050//*-*- otherwise select only the specified columns
2051 } else {
2052 ncols = fSelector->SplitNames(varexp,cnames);
2053 }
2054 var = new TTreeFormula* [ncols];
2055 Double_t *xvars = new Double_t[ncols];
2056
2057//*-*- Create the TreeFormula objects corresponding to each column
2058 for (i=0;i<ncols;i++) {
2059 var[i] = new TTreeFormula("Var1",cnames[i].Data(),fTree);
2060 fFormulaList->Add(var[i]);
2061 }
2062
2063//*-*- Create a TreeFormulaManager to coordinate the formulas
2064 TTreeFormulaManager *manager=nullptr;
2065 if (fFormulaList->LastIndex()>=0) {
2066 manager = new TTreeFormulaManager;
2067 for(i=0;i<=fFormulaList->LastIndex();i++) {
2068 manager->Add((TTreeFormula*)fFormulaList->At(i));
2069 }
2070 manager->Sync();
2071 }
2072
2073//*-* Build the TPrincipal object
2074 if (opt.Contains("n")) principal = new TPrincipal(ncols, "n");
2075 else principal = new TPrincipal(ncols);
2076
2077//*-*- loop on all selected entries
2078 fSelectedRows = 0;
2079 Int_t tnumber = -1;
2080 for (entry=firstentry;entry<firstentry+nentries;entry++) {
2081 entryNumber = fTree->GetEntryNumber(entry);
2082 if (entryNumber < 0) break;
2083 Long64_t localEntry = fTree->LoadTree(entryNumber);
2084 if (localEntry < 0) break;
2085 if (tnumber != fTree->GetTreeNumber()) {
2086 tnumber = fTree->GetTreeNumber();
2087 if (manager) manager->UpdateFormulaLeaves();
2088 }
2089 int ndata = 1;
2090 if (manager && manager->GetMultiplicity()) {
2091 ndata = manager->GetNdata();
2092 }
2093
2094 for(int inst=0;inst<ndata;inst++) {
2095 bool loaded = false;
2096 if (select) {
2097 if (select->EvalInstance(inst) == 0) {
2098 continue;
2099 }
2100 }
2101
2102 if (inst==0) loaded = true;
2103 else if (!loaded) {
2104 // EvalInstance(0) always needs to be called so that
2105 // the proper branches are loaded.
2106 for (i=0;i<ncols;i++) {
2107 var[i]->EvalInstance(0);
2108 }
2109 loaded = true;
2110 }
2111
2112 for (i=0;i<ncols;i++) {
2113 xvars[i] = var[i]->EvalInstance(inst);
2114 }
2115 principal->AddRow(xvars);
2116 }
2117 }
2118
2119 //*-* some actions with principal ?
2120 if (opt.Contains("p")) {
2121 principal->MakePrincipals(); // Do the actual analysis
2122 if (opt.Contains("d")) principal->Print();
2123 if (opt.Contains("h")) principal->MakeHistograms();
2124 if (opt.Contains("c")) principal->MakeCode();
2125 }
2126
2127//*-*- delete temporary objects
2129 delete [] var;
2130 delete [] xvars;
2131
2132 return principal;
2133}
2134
2135////////////////////////////////////////////////////////////////////////////////
2136/// Process this tree executing the TSelector code in the specified filename.
2137/// The return value is -1 in case of error and TSelector::GetStatus() in
2138/// in case of success.
2139///
2140/// The code in filename is loaded (interpreted or compiled, see below),
2141/// filename must contain a valid class implementation derived from TSelector,
2142/// where TSelector has the following member functions:
2143///
2144/// - Begin(): called every time a loop on the tree starts,
2145/// a convenient place to create your histograms.
2146/// - SlaveBegin(): called after Begin(), when on PROOF called only on the
2147/// slave servers.
2148/// - Process(): called for each event, in this function you decide what
2149/// to read and fill your histograms.
2150/// - SlaveTerminate: called at the end of the loop on the tree, when on PROOF
2151/// called only on the slave servers.
2152/// - Terminate(): called at the end of the loop on the tree,
2153/// a convenient place to draw/fit your histograms.
2154///
2155/// If filename is of the form file.C, the file will be interpreted.
2156/// If filename is of the form file.C++, the file file.C will be compiled
2157/// and dynamically loaded.
2158///
2159/// If filename is of the form file.C+, the file file.C will be compiled
2160/// and dynamically loaded. At next call, if file.C is older than file.o
2161/// and file.so, the file.C is not compiled, only file.so is loaded.
2162///
2163/// ### NOTE 1
2164/// It may be more interesting to invoke directly the other Process function
2165/// accepting a TSelector* as argument.eg
2166/// ~~~{.cpp}
2167/// MySelector *selector = (MySelector*)TSelector::GetSelector(filename);
2168/// selector->CallSomeFunction(..);
2169/// mytree.Process(selector,..);
2170/// ~~~
2171/// ### NOTE 2
2172/// One should not call this function twice with the same selector file
2173/// in the same script. If this is required, proceed as indicated in NOTE1,
2174/// by getting a pointer to the corresponding TSelector,eg
2175///#### workaround 1
2176/// ~~~{.cpp}
2177///void stubs1() {
2178/// TSelector *selector = TSelector::GetSelector("h1test.C");
2179/// TFile *f1 = new TFile("stubs_nood_le1.root");
2180/// TTree *h1 = (TTree*)f1->Get("h1");
2181/// h1->Process(selector);
2182/// TFile *f2 = new TFile("stubs_nood_le1_coarse.root");
2183/// TTree *h2 = (TTree*)f2->Get("h1");
2184/// h2->Process(selector);
2185///}
2186/// ~~~
2187/// or use ACLIC to compile the selector
2188///#### workaround 2
2189/// ~~~{.cpp}
2190///void stubs2() {
2191/// TFile *f1 = new TFile("stubs_nood_le1.root");
2192/// TTree *h1 = (TTree*)f1->Get("h1");
2193/// h1->Process("h1test.C+");
2194/// TFile *f2 = new TFile("stubs_nood_le1_coarse.root");
2195/// TTree *h2 = (TTree*)f2->Get("h1");
2196/// h2->Process("h1test.C+");
2197///}
2198/// ~~~
2199
2201{
2202 DeleteSelectorFromFile(); //delete previous selector if any
2203
2204 // This might reloads the script and delete your option
2205 // string! so let copy it first:
2206 TString opt(option);
2207 TString file(filename);
2208 TSelector *selector = TSelector::GetSelector(file);
2209 if (!selector) return -1;
2210
2211 fSelectorFromFile = selector;
2212 fSelectorClass = selector->IsA();
2213
2214 Long64_t nsel = Process(selector,opt,nentries,firstentry);
2215 return nsel;
2216}
2217
2218////////////////////////////////////////////////////////////////////////////////
2219/// Process this tree executing the code in the specified selector.
2220/// The return value is -1 in case of error and TSelector::GetStatus() in
2221/// in case of success.
2222///
2223/// The TSelector class has the following member functions:
2224///
2225/// - Begin(): called every time a loop on the tree starts,
2226/// a convenient place to create your histograms.
2227/// - SlaveBegin(): called after Begin(), when on PROOF called only on the
2228/// slave servers.
2229/// - Process(): called for each event, in this function you decide what
2230/// to read and fill your histograms.
2231/// - SlaveTerminate: called at the end of the loop on the tree, when on PROOF
2232/// called only on the slave servers.
2233/// - Terminate(): called at the end of the loop on the tree,
2234/// a convenient place to draw/fit your histograms.
2235///
2236/// If the Tree (Chain) has an associated EventList, the loop is on the nentries
2237/// of the EventList, starting at firstentry, otherwise the loop is on the
2238/// specified Tree entries.
2239
2241{
2242 nentries = GetEntriesToProcess(firstentry, nentries);
2243
2245
2246 fTree->SetNotify(selector);
2247
2248 selector->SetOption(option);
2249
2250 selector->Begin(fTree); //<===call user initialization function
2251 selector->SlaveBegin(fTree); //<===call user initialization function
2252 if (selector->Version() >= 2)
2253 selector->Init(fTree);
2254 selector->Notify();
2255
2257 gMonitoringWriter->SendProcessingStatus("STARTED",true);
2258
2259 bool process = (selector->GetAbort() != TSelector::kAbortProcess &&
2260 (selector->Version() != 0 || selector->GetStatus() != -1)) ? true : false;
2261 if (process) {
2262
2263 Long64_t readbytesatstart = 0;
2264 readbytesatstart = TFile::GetFileBytesRead();
2265
2266 //set the file cache
2267 TTreeCache *tpf = nullptr;
2268 TFile *curfile = fTree->GetCurrentFile();
2269 if (curfile) {
2270 tpf = (TTreeCache*)curfile->GetCacheRead(fTree);
2271 if (tpf)
2272 tpf->SetEntryRange(firstentry,firstentry+nentries);
2273 else {
2274 // Create the TTreeCache with the default size unless the
2275 // user explicitly disabled it.
2276 fTree->EnableCache();
2277 tpf = (TTreeCache*)curfile->GetCacheRead(fTree);
2278 if (tpf) tpf->SetEntryRange(firstentry,firstentry+nentries);
2279 }
2280 }
2281
2282 //Create a timer to get control in the entry loop(s)
2283 TProcessEventTimer *timer = nullptr;
2284 Int_t interval = fTree->GetTimerInterval();
2285 if (!gROOT->IsBatch() && interval)
2286 timer = new TProcessEventTimer(interval);
2287
2288 //loop on entries (elist or all entries)
2289 Long64_t entry, entryNumber, localEntry;
2290
2291 bool useCutFill = selector->Version() == 0;
2292
2293 // force the first monitoring info
2296
2297 //trying to set the first tree, because in the Draw function
2298 //the tree corresponding to firstentry has already been loaded,
2299 //so it is not set in the entry list
2300 fSelectorUpdate = selector;
2302
2303 for (entry=firstentry;entry<firstentry+nentries;entry++) {
2304 entryNumber = fTree->GetEntryNumber(entry);
2305 if (entryNumber < 0) break;
2306 if (timer && timer->ProcessEvents()) break;
2307 if (gROOT->IsInterrupted()) break;
2308 localEntry = fTree->LoadTree(entryNumber);
2309 if (localEntry < 0) break;
2310 if(useCutFill) {
2311 if (selector->ProcessCut(localEntry))
2312 selector->ProcessFill(localEntry); //<==call user analysis function
2313 } else {
2314 selector->Process(localEntry); //<==call user analysis function
2315 }
2317 gMonitoringWriter->SendProcessingProgress((entry-firstentry),TFile::GetFileBytesRead()-readbytesatstart,true);
2318 if (selector->GetAbort() == TSelector::kAbortProcess) break;
2319 if (selector->GetAbort() == TSelector::kAbortFile) {
2320 // Skip to the next file.
2321 entry += fTree->GetTree()->GetEntries() - localEntry;
2322 // Reset the abort status.
2323 selector->ResetAbort();
2324 }
2325 }
2326 delete timer;
2327 //we must reset the cache
2328 {
2329 TFile *curfile2 = fTree->GetCurrentFile();
2330 if (curfile2 && fTree->GetCacheSize() > 0) {
2331 tpf = (TTreeCache*)curfile2->GetCacheRead(fTree);
2332 if (tpf) tpf->SetEntryRange(0,0);
2333 }
2334 }
2335 }
2336
2337 process = (selector->GetAbort() != TSelector::kAbortProcess &&
2338 (selector->Version() != 0 || selector->GetStatus() != -1)) ? true : false;
2339 Long64_t res = (process) ? 0 : -1;
2340 if (process) {
2341 selector->SlaveTerminate(); //<==call user termination function
2342 selector->Terminate(); //<==call user termination function
2343 res = selector->GetStatus();
2344 }
2345 fTree->SetNotify(nullptr); // Detach the selector from the tree.
2346 fSelectorUpdate = nullptr;
2349
2350 return res;
2351}
2352
2353////////////////////////////////////////////////////////////////////////////////
2354/// cleanup pointers in the player pointing to obj
2355
2357{
2358 if (fHistogram == obj) fHistogram = nullptr;
2359}
2360
2361////////////////////////////////////////////////////////////////////////////////
2362/// \brief Loop on Tree and print entries passing selection. Interactive
2363/// pagination break is on by default.
2364/// \param varexp If varexp is 0 (or "") then print only first 8 columns.
2365/// If varexp = "*" print all columns. Otherwise a columns selection can
2366/// be made using "var1:var2:var3".
2367/// \param selection a text formula selecting which entries to scan
2368/// \param firstentry first entry to scan
2369/// \param nentries total number of entries to scan (starting from firstentry). Defaults to all entries.
2370/// \return The function returns the number of entries passing the selection.
2371///
2372/// By default 50 lines are shown and you are asked for `<CR>` or `q`
2373/// to see the next 50 lines. Depending on the Tree structure, one entry might
2374/// be printed across several lines, distinguished by the `Instance` column.
2375/// You can change the default number of lines to be shown before `<CR>` or `q`
2376/// via mytree->SetScanField(maxlines) where maxlines is 50 by default.
2377/// If maxlines is set to 0 all entries of the Tree are shown, and you are
2378/// not prompted to press `<CR>` or `q` to end the loop.
2379///
2380/// This option is interesting when dumping the contents of a Tree to
2381/// an ascii file, eg from the command line.
2382/// ### with ROOT 5
2383/// ~~~{.cpp}
2384/// root [0] tree->SetScanField(0);
2385/// root [1] tree->Scan("*"); >tree.log
2386/// ~~~
2387/// ### with ROOT 6
2388/// ~~~{.cpp}
2389/// root [0] tree->SetScanField(0);
2390/// root [1] .> tree.log
2391/// tree->Scan("*");
2392/// .>
2393/// ~~~
2394/// will create a file tree.log
2395///
2396/// Arrays (within an entry) are printed in their linear forms.
2397/// If several arrays with multiple dimensions are printed together,
2398/// they will NOT be synchronized. For example print
2399/// arr1[4][2] and arr2[2][3] will results in a printing similar to:
2400/// ~~~{.cpp}
2401/// ***********************************************
2402/// * Row * Instance * arr1 * arr2 *
2403/// ***********************************************
2404/// * x * 0 * arr1[0][0]* arr2[0][0]*
2405/// * x * 1 * arr1[0][1]* arr2[0][1]*
2406/// * x * 2 * arr1[1][0]* arr2[0][2]*
2407/// * x * 3 * arr1[1][1]* arr2[1][0]*
2408/// * x * 4 * arr1[2][0]* arr2[1][1]*
2409/// * x * 5 * arr1[2][1]* arr2[1][2]*
2410/// * x * 6 * arr1[3][0]* *
2411/// * x * 7 * arr1[3][1]* *
2412/// ~~~
2413/// However, if there is a selection criterion which is an array, then
2414/// all the formulas will be synchronized with the selection criterion
2415/// (see TTreePlayer::DrawSelect for more information).
2416///
2417/// \param option The options string can contains the following parameters:
2418///
2419/// - lenmax=dd
2420/// Where 'dd' is the maximum number of elements per array that should
2421/// be printed. If 'dd' is 0, all elements are printed (this is the
2422/// default)
2423/// - colsize=ss
2424/// Where 'ss' will be used as the default size for all the column
2425/// If this options is not specified, the default column size is 9
2426/// - precision=pp
2427/// Where 'pp' will be used as the default 'precision' for the
2428/// printing format.
2429/// - col=xxx
2430/// Where 'xxx' is colon (:) delimited list of printing format for
2431/// each column. The format string should follow the printf format
2432/// specification. The value given will be prefixed by % and, if no
2433/// conversion specifier is given, will be suffixed by the letter g.
2434/// before being passed to fprintf. If no format is specified for a
2435/// column, the default is used (aka ${colsize}.${precision}g )
2436///
2437/// For example:
2438/// ~~~{.cpp}
2439/// tree->Scan("a:b:c","","colsize=30 precision=3 col=::20.10:#x:5ld");
2440/// ~~~
2441/// Will print 3 columns, the first 2 columns will be 30 characters long,
2442/// the third columns will be 20 characters long. The printing format used
2443/// for the columns (assuming they are numbers) will be respectively:
2444/// ~~~ {.cpp}
2445/// %30.3g %30.3g %20.10g %#x %5ld
2446/// ~~~
2447
2448Long64_t TTreePlayer::Scan(const char *varexp, const char *selection,
2449 Option_t * option,
2450 Long64_t nentries, Long64_t firstentry)
2451{
2452
2453 TString opt = option;
2454 opt.ToLower();
2455 UInt_t ui;
2456 UInt_t lenmax = 0;
2457 UInt_t colDefaultSize = 9;
2458 UInt_t colPrecision = 9;
2459 std::vector<TString> colFormats;
2460 std::vector<Int_t> colSizes;
2461
2462 if (opt.Contains("lenmax=")) {
2463 int start = opt.Index("lenmax=");
2464 int numpos = start + strlen("lenmax=");
2465 int numlen = 0;
2466 int len = opt.Length();
2467 while( (numpos+numlen<len) && isdigit(opt[numpos+numlen]) ) numlen++;
2468 TString num = opt(numpos,numlen);
2469 opt.Remove(start,strlen("lenmax")+numlen);
2470
2471 lenmax = atoi(num.Data());
2472 }
2473 if (opt.Contains("colsize=")) {
2474 int start = opt.Index("colsize=");
2475 int numpos = start + strlen("colsize=");
2476 int numlen = 0;
2477 int len = opt.Length();
2478 while( (numpos+numlen<len) && isdigit(opt[numpos+numlen]) ) numlen++;
2479 TString num = opt(numpos,numlen);
2480 opt.Remove(start,strlen("size")+numlen);
2481
2482 colDefaultSize = atoi(num.Data());
2483 colPrecision = colDefaultSize;
2484 if (colPrecision>18) colPrecision = 18;
2485 }
2486 if (opt.Contains("precision=")) {
2487 int start = opt.Index("precision=");
2488 int numpos = start + strlen("precision=");
2489 int numlen = 0;
2490 int len = opt.Length();
2491 while( (numpos+numlen<len) && isdigit(opt[numpos+numlen]) ) numlen++;
2492 TString num = opt(numpos,numlen);
2493 opt.Remove(start,strlen("precision")+numlen);
2494
2495 colPrecision = atoi(num.Data());
2496 }
2497 TString defFormat = Form("%d.%d",colDefaultSize,colPrecision);
2498 if (opt.Contains("col=")) {
2499 int start = opt.Index("col=");
2500 int numpos = start + strlen("col=");
2501 int numlen = 0;
2502 int len = opt.Length();
2503 while( (numpos+numlen<len) &&
2504 (isdigit(opt[numpos+numlen])
2505 || opt[numpos+numlen] == 'c'
2506 || opt[numpos+numlen] == 'd'
2507 || opt[numpos+numlen] == 'i'
2508 || opt[numpos+numlen] == 'o'
2509 || opt[numpos+numlen] == 'x'
2510 || opt[numpos+numlen] == 'X'
2511 || opt[numpos+numlen] == 'u'
2512 || opt[numpos+numlen] == 'f'
2513 || opt[numpos+numlen] == 'e'
2514 || opt[numpos+numlen] == 'E'
2515 || opt[numpos+numlen] == 'g'
2516 || opt[numpos+numlen] == 'G'
2517 || opt[numpos+numlen] == 'l'
2518 || opt[numpos+numlen] == 'L'
2519 || opt[numpos+numlen] == 'h'
2520 || opt[numpos+numlen] == 's'
2521 || opt[numpos+numlen] == '#'
2522 || opt[numpos+numlen]=='.'
2523 || opt[numpos+numlen]==':')) numlen++;
2524 TString flist = opt(numpos,numlen);
2525 opt.Remove(start,strlen("col")+numlen);
2526
2527 int i = 0;
2528 while(i<flist.Length() && flist[i]==':') {
2529 colFormats.push_back(defFormat);
2530 colSizes.push_back(colDefaultSize);
2531 ++i;
2532 }
2533 for(; i<flist.Length(); ++i) {
2534 int next = flist.Index(":",i);
2535 if (next==i) {
2536 colFormats.push_back(defFormat);
2537 } else if (next==kNPOS) {
2538 colFormats.push_back(flist(i,flist.Length()-i));
2539 i = flist.Length();
2540 } else {
2541 colFormats.push_back(flist(i,next-i));
2542 i = next;
2543 }
2544 UInt_t siz = atoi(colFormats[colFormats.size()-1].Data());
2545 colSizes.push_back( siz ? siz : colDefaultSize );
2546 }
2547 }
2548
2549 TTreeFormula **var;
2550 std::vector<TString> cnames;
2551 TString onerow;
2552 Long64_t entry,entryNumber;
2553 Int_t i,nch;
2554 UInt_t ncols = 8; // by default first 8 columns are printed only
2555 std::ofstream out;
2556 const char *fname = nullptr;
2557 TString fownname;
2558 if (fScanRedirect) {
2559 fTree->SetScanField(0); // no page break if Scan is redirected
2560 fname = fScanFileName;
2561 if (!fname) fname = "";
2562 Int_t lenfile = strlen(fname);
2563 if (!lenfile) {
2564 fownname = fTree->GetName();
2565 fownname.Append("-scan.dat");
2566 fname = fownname.Data();
2567 }
2568 out.open(fname, std::ios::out);
2569 if (!out.good ()) {
2570 Error("Scan","Can not open file for redirection");
2571 return 0;
2572 }
2573 }
2574 TObjArray *leaves = fTree->GetListOfLeaves();
2575 if (leaves==nullptr) return 0;
2576 UInt_t nleaves = leaves->GetEntriesFast();
2577 if (nleaves < ncols) ncols = nleaves;
2578 nch = varexp ? strlen(varexp) : 0;
2579
2580 nentries = GetEntriesToProcess(firstentry, nentries);
2581
2582//*-*- Compile selection expression if there is one
2583 TTreeFormula *select = nullptr;
2584 if (selection && strlen(selection)) {
2585 select = new TTreeFormula("Selection",selection,fTree);
2586 if (!select) return -1;
2587 if (!select->GetNdim()) { delete select; return -1; }
2588 fFormulaList->Add(select);
2589 }
2590//*-*- if varexp is empty, take first 8 columns by default
2591 int allvar = 0;
2592 if (varexp && !strcmp(varexp, "*")) { ncols = nleaves; allvar = 1; }
2593 if (nch == 0 || allvar) {
2594 UInt_t ncs = ncols;
2595 ncols = 0;
2596 for (ui=0;ui<ncs;++ui) {
2597 TLeaf *lf = (TLeaf*)leaves->At(ui);
2598 if (lf->GetBranch()->GetListOfBranches()->GetEntries() > 0) continue;
2599 cnames.push_back( lf->GetBranch()->GetMother()->GetName() );
2600 if (cnames[ncols] == lf->GetName() ) {
2601 // Already complete, let move on.
2602 } else if (cnames[ncols][cnames[ncols].Length()-1]=='.') {
2603 cnames[ncols] = lf->GetBranch()->GetName(); // name of branch already include mother's name
2604 } else {
2606 TBranchElement *mother = (TBranchElement*)lf->GetBranch()->GetMother();
2607 if (mother->GetType() == 3 || mother->GetType() == 4) {
2608 // The name of the mother branch is embedded in the sub-branch names.
2609 cnames[ncols] = lf->GetBranch()->GetName();
2610 ++ncols;
2611 continue;
2612 }
2613 }
2614 if (!strchr(lf->GetBranch()->GetName() ,'[') ) {
2615 cnames[ncols].Append('.');
2616 cnames[ncols].Append( lf->GetBranch()->GetName() );
2617 }
2618 }
2619 if (lf->GetBranch()->IsA() == TBranch::Class() ||
2620 strcmp( lf->GetBranch()->GetName(), lf->GetName() ) != 0 ) {
2621 cnames[ncols].Append('.');
2622 cnames[ncols].Append( lf->GetName() );
2623 }
2624 ++ncols;
2625 }
2626//*-*- otherwise select only the specified columns
2627 } else {
2628
2629 ncols = fSelector->SplitNames(varexp, cnames);
2630
2631 }
2632 var = new TTreeFormula* [ncols];
2633
2634 for(ui=colFormats.size();ui<ncols;++ui) {
2635 colFormats.push_back(defFormat);
2636 colSizes.push_back(colDefaultSize);
2637 }
2638
2639//*-*- Create the TreeFormula objects corresponding to each column
2640 for (ui=0;ui<ncols;ui++) {
2641 var[ui] = new TTreeFormula("Var1",cnames[ui].Data(),fTree);
2642 fFormulaList->Add(var[ui]);
2643 }
2644
2645//*-*- Create a TreeFormulaManager to coordinate the formulas
2646 TTreeFormulaManager *manager=nullptr;
2647 bool hasArray = false;
2648 bool forceDim = false;
2649 if (fFormulaList->LastIndex()>=0) {
2650 if (select) {
2651 if (select->GetManager()->GetMultiplicity() > 0 ) {
2652 manager = new TTreeFormulaManager;
2653 for(i=0;i<=fFormulaList->LastIndex();i++) {
2654 manager->Add((TTreeFormula*)fFormulaList->At(i));
2655 }
2656 manager->Sync();
2657 }
2658 }
2659 for(i=0;i<=fFormulaList->LastIndex();i++) {
2660 TTreeFormula *form = ((TTreeFormula*)fFormulaList->At(i));
2661 switch( form->GetManager()->GetMultiplicity() ) {
2662 case 1:
2663 case 2:
2664 hasArray = true;
2665 forceDim = true;
2666 break;
2667 case -1:
2668 forceDim = true;
2669 break;
2670 case 0:
2671 break;
2672 }
2673
2674 }
2675 }
2676
2677//*-*- Print header
2678 onerow = "***********";
2679 if (hasArray) onerow += "***********";
2680
2681 for (ui=0;ui<ncols;ui++) {
2682 TString starFormat = Form("*%%%d.%ds",colSizes[ui]+2,colSizes[ui]+2);
2683 onerow += Form(starFormat.Data(),var[ui]->PrintValue(-2));
2684 }
2685 if (fScanRedirect)
2686 out<<onerow.Data()<<"*"<<std::endl;
2687 else
2688 printf("%s*\n",onerow.Data());
2689 onerow = "* Row ";
2690 if (hasArray) onerow += "* Instance ";
2691 for (ui=0;ui<ncols;ui++) {
2692 TString numbFormat = Form("* %%%d.%ds ",colSizes[ui],colSizes[ui]);
2693 onerow += Form(numbFormat.Data(),var[ui]->PrintValue(-1));
2694 }
2695 if (fScanRedirect)
2696 out<<onerow.Data()<<"*"<<std::endl;
2697 else
2698 printf("%s*\n",onerow.Data());
2699 onerow = "***********";
2700 if (hasArray) onerow += "***********";
2701 for (ui=0;ui<ncols;ui++) {
2702 TString starFormat = Form("*%%%d.%ds",colSizes[ui]+2,colSizes[ui]+2);
2703 onerow += Form(starFormat.Data(),var[ui]->PrintValue(-2));
2704 }
2705 if (fScanRedirect)
2706 out<<onerow.Data()<<"*"<<std::endl;
2707 else
2708 printf("%s*\n",onerow.Data());
2709//*-*- loop on all selected entries
2710 fSelectedRows = 0;
2711 Int_t tnumber = -1;
2712 bool exitloop = false;
2713 for (entry=firstentry;
2714 entry<(firstentry+nentries) && !exitloop;
2715 entry++) {
2716 entryNumber = fTree->GetEntryNumber(entry);
2717 if (entryNumber < 0) break;
2718 Long64_t localEntry = fTree->LoadTree(entryNumber);
2719 if (localEntry < 0) break;
2720 if (tnumber != fTree->GetTreeNumber()) {
2721 tnumber = fTree->GetTreeNumber();
2722 if (manager) manager->UpdateFormulaLeaves();
2723 else {
2724 for(i=0;i<=fFormulaList->LastIndex();i++) {
2726 }
2727 }
2728 }
2729
2730 int ndata = 1;
2731 if (forceDim) {
2732
2733 if (manager) {
2734
2735 ndata = manager->GetNdata(true);
2736
2737 } else {
2738
2739 // let's print the max number of column
2740 for (ui=0;ui<ncols;ui++) {
2741 if (ndata < var[ui]->GetNdata() ) {
2742 ndata = var[ui]->GetNdata();
2743 }
2744 }
2745 if (select && select->GetNdata()==0) ndata = 0;
2746 }
2747
2748 }
2749
2750 if (lenmax && ndata>(int)lenmax) ndata = lenmax;
2751 bool loaded = false;
2752 for(int inst=0;inst<ndata;inst++) {
2753 if (select) {
2754 if (select->EvalInstance(inst) == 0) {
2755 continue;
2756 }
2757 }
2758 if (inst==0) loaded = true;
2759 else if (!loaded) {
2760 // EvalInstance(0) always needs to be called so that
2761 // the proper branches are loaded.
2762 for (ui=0;ui<ncols;ui++) {
2763 var[ui]->EvalInstance(0);
2764 }
2765 loaded = true;
2766 }
2767 onerow = Form("* %8lld ",entryNumber);
2768 if (hasArray) {
2769 onerow += Form("* %8d ",inst);
2770 }
2771 for (ui=0;ui<ncols;++ui) {
2772 TString numbFormat = Form("* %%%d.%ds ",colSizes[ui],colSizes[ui]);
2773 if (var[ui]->GetNdim()) onerow += Form(numbFormat.Data(),var[ui]->PrintValue(0,inst,colFormats[ui].Data()));
2774 else {
2775 TString emptyForm = Form("* %%%dc ",colSizes[ui]);
2776 onerow += Form(emptyForm.Data(),' ');
2777 }
2778 }
2779 fSelectedRows++;
2780 if (fScanRedirect)
2781 out<<onerow.Data()<<"*"<<std::endl;
2782 else
2783 printf("%s*\n",onerow.Data());
2784 if (fTree->GetScanField() > 0 && fSelectedRows > 0) {
2785 if (fSelectedRows%fTree->GetScanField() == 0) {
2786 fprintf(stderr,"Type <CR> to continue or q to quit ==> ");
2787 int answer, readch;
2788 readch = getchar();
2789 answer = readch;
2790 while (readch != '\n' && readch != EOF) readch = getchar();
2791 if (answer == 'q' || answer == 'Q') {
2792 exitloop = true;
2793 break;
2794 }
2795 }
2796 }
2797 }
2798 }
2799 onerow = "***********";
2800 if (hasArray) onerow += "***********";
2801 for (ui=0;ui<ncols;ui++) {
2802 TString starFormat = Form("*%%%d.%ds",colSizes[ui]+2,colSizes[ui]+2);
2803 onerow += Form(starFormat.Data(),var[ui]->PrintValue(-2));
2804 }
2805 if (fScanRedirect)
2806 out<<onerow.Data()<<"*"<<std::endl;
2807 else
2808 printf("%s*\n",onerow.Data());
2809 if (select) Printf("==> %lld selected %s", fSelectedRows,
2810 fSelectedRows == 1 ? "entry" : "entries");
2811 if (fScanRedirect) printf("File <%s> created\n", fname);
2812
2813//*-*- delete temporary objects
2815 // The TTreeFormulaManager is deleted by the last TTreeFormula.
2816 delete [] var;
2817 return fSelectedRows;
2818}
2819
2820////////////////////////////////////////////////////////////////////////////////
2821/// Loop on Tree and return TSQLResult object containing entries passing
2822/// selection. If varexp is 0 (or "") then print only first 8 columns.
2823/// If varexp = "*" print all columns. Otherwise a columns selection can
2824/// be made using "var1:var2:var3". In case of error 0 is returned otherwise
2825/// a TSQLResult object which must be deleted by the user.
2826
2827TSQLResult *TTreePlayer::Query(const char *varexp, const char *selection,
2828 Option_t *, Long64_t nentries, Long64_t firstentry)
2829{
2830 TTreeFormula **var;
2831 std::vector<TString> cnames;
2832 TString onerow;
2833 Long64_t entry,entryNumber;
2834 Int_t i,nch;
2835 Int_t ncols = 8; // by default first 8 columns are printed only
2836 TObjArray *leaves = fTree->GetListOfLeaves();
2837 Int_t nleaves = leaves->GetEntriesFast();
2838 if (nleaves < ncols) ncols = nleaves;
2839 nch = varexp ? strlen(varexp) : 0;
2840
2841 nentries = GetEntriesToProcess(firstentry, nentries);
2842
2843 // compile selection expression if there is one
2844 TTreeFormula *select = nullptr;
2845 if (strlen(selection)) {
2846 select = new TTreeFormula("Selection",selection,fTree);
2847 if (!select) return nullptr;
2848 if (!select->GetNdim()) { delete select; return nullptr; }
2849 fFormulaList->Add(select);
2850 }
2851
2852 // if varexp is empty, take first 8 columns by default
2853 int allvar = 0;
2854 if (varexp && !strcmp(varexp, "*")) { ncols = nleaves; allvar = 1; }
2855 if (nch == 0 || allvar) {
2856 for (i=0;i<ncols;i++) {
2857 cnames.push_back( ((TLeaf*)leaves->At(i))->GetName() );
2858 }
2859 } else {
2860 // otherwise select only the specified columns
2861 ncols = fSelector->SplitNames(varexp,cnames);
2862 }
2863 var = new TTreeFormula* [ncols];
2864
2865 // create the TreeFormula objects corresponding to each column
2866 for (i=0;i<ncols;i++) {
2867 var[i] = new TTreeFormula("Var1",cnames[i].Data(),fTree);
2868 fFormulaList->Add(var[i]);
2869 }
2870
2871 // fill header info into result object
2872 TTreeResult *res = new TTreeResult(ncols);
2873 for (i = 0; i < ncols; i++) {
2874 res->AddField(i, var[i]->PrintValue(-1));
2875 }
2876
2877 //*-*- Create a TreeFormulaManager to coordinate the formulas
2878 TTreeFormulaManager *manager=nullptr;
2879 if (fFormulaList->LastIndex()>=0) {
2880 manager = new TTreeFormulaManager;
2881 for(i=0;i<=fFormulaList->LastIndex();i++) {
2882 manager->Add((TTreeFormula*)fFormulaList->At(i));
2883 }
2884 manager->Sync();
2885 }
2886
2887 // loop on all selected entries
2888 const char *aresult;
2889 Int_t len;
2890 char *arow = new char[ncols*50];
2891 fSelectedRows = 0;
2892 Int_t tnumber = -1;
2893 Int_t *fields = new Int_t[ncols];
2894 for (entry=firstentry;entry<firstentry+nentries;entry++) {
2895 entryNumber = fTree->GetEntryNumber(entry);
2896 if (entryNumber < 0) break;
2897 Long64_t localEntry = fTree->LoadTree(entryNumber);
2898 if (localEntry < 0) break;
2899 if (tnumber != fTree->GetTreeNumber()) {
2900 tnumber = fTree->GetTreeNumber();
2901 for (i=0;i<ncols;i++) var[i]->UpdateFormulaLeaves();
2902 }
2903
2904 Int_t ndata = 1;
2905 if (manager && manager->GetMultiplicity()) {
2906 ndata = manager->GetNdata();
2907 }
2908
2909 if (select) {
2910 select->GetNdata();
2911 if (select->EvalInstance(0) == 0) continue;
2912 }
2913
2914 bool loaded = false;
2915 for(int inst=0;inst<ndata;inst++) {
2916 if (select) {
2917 if (select->EvalInstance(inst) == 0) {
2918 continue;
2919 }
2920 }
2921
2922 if (inst==0) loaded = true;
2923 else if (!loaded) {
2924 // EvalInstance(0) always needs to be called so that
2925 // the proper branches are loaded.
2926 for (i=0;i<ncols;i++) {
2927 var[i]->EvalInstance(0);
2928 }
2929 loaded = true;
2930 }
2931 for (i=0;i<ncols;i++) {
2932 aresult = var[i]->PrintValue(0,inst);
2933 len = strlen(aresult)+1;
2934 if (i == 0) {
2935 memcpy(arow,aresult,len);
2936 fields[i] = len;
2937 } else {
2938 memcpy(arow+fields[i-1],aresult,len);
2939 fields[i] = fields[i-1] + len;
2940 }
2941 }
2942 res->AddRow(new TTreeRow(ncols,fields,arow));
2943 fSelectedRows++;
2944 }
2945 }
2946
2947 // delete temporary objects
2949 // The TTreeFormulaManager is deleted by the last TTreeFormula.
2950 delete [] fields;
2951 delete [] arow;
2952 delete [] var;
2953
2954 return res;
2955}
2956
2957////////////////////////////////////////////////////////////////////////////////
2958/// Set number of entries to estimate variable limits.
2959
2961{
2963}
2964
2965////////////////////////////////////////////////////////////////////////////////
2966/// Start the TTreeViewer on this TTree.
2967///
2968/// - ww is the width of the canvas in pixels
2969/// - wh is the height of the canvas in pixels
2970
2972{
2973 // unused variables
2974 (void) ww;
2975 (void) wh;
2976
2977 if (!gApplication)
2979 // make sure that the Gpad and GUI libs are loaded
2980
2981 TString hname = gEnv->GetValue("TreeViewer.Name", "TTreeViewer");
2982
2984 if (gApplication)
2985 gApplication->InitializeGraphics(hname == "RTreeViewer");
2986
2987 if (gROOT->IsBatch()) {
2988 if ((hname != "RTreeViewer") || gROOT->IsWebDisplayBatch()) {
2989 Warning("StartViewer", "The tree viewer cannot run in batch mode");
2990 return;
2991 }
2992 }
2993
2994 if (auto h = gROOT->GetPluginManager()->FindHandler("TVirtualTreeViewer", hname.Data())) {
2995 if (h->LoadPlugin() != -1)
2996 h->ExecPlugin(1, fTree);
2997 }
2998}
2999
3000////////////////////////////////////////////////////////////////////////////////
3001/// Unbinned fit of one or more variable(s) from a Tree.
3002///
3003/// funcname is a TF1 function.
3004///
3005/// See TTree::Draw for explanations of the other parameters.
3006///
3007/// Fit the variable varexp using the function funcname using the
3008/// selection cuts given by selection.
3009///
3010/// The list of fit options is given in parameter option.
3011///
3012/// - option = "Q" Quiet mode (minimum printing)
3013/// - option = "V" Verbose mode (default is between Q and V)
3014/// - option = "E" Perform better Errors estimation using Minos technique
3015/// - option = "M" More. Improve fit results
3016/// - option = "D" Draw the projected histogram with the fitted function
3017/// normalized to the number of selected rows
3018/// and multiplied by the bin width
3019///
3020/// You can specify boundary limits for some or all parameters via
3021/// ~~~{.cpp}
3022/// func->SetParLimits(p_number, parmin, parmax);
3023/// ~~~
3024/// if parmin>=parmax, the parameter is fixed
3025///
3026/// Note that you are not forced to fix the limits for all parameters.
3027/// For example, if you fit a function with 6 parameters, you can do:
3028/// ~~~{.cpp}
3029/// func->SetParameters(0,3.1,1.e-6,0.1,-8,100);
3030/// func->SetParLimits(4,-10,-4);
3031/// func->SetParLimits(5, 1,1);
3032/// ~~~
3033/// With this setup, parameters 0->3 can vary freely
3034/// - Parameter 4 has boundaries [-10,-4] with initial value -8
3035/// - Parameter 5 is fixed to 100.
3036///
3037/// For the fit to be meaningful, the function must be self-normalized.
3038///
3039/// i.e. It must have the same integral regardless of the parameter
3040/// settings. Otherwise the fit will effectively just maximize the
3041/// area.
3042///
3043/// It is mandatory to have a normalization variable
3044/// which is fixed for the fit. e.g.
3045/// ~~~{.cpp}
3046/// TF1* f1 = new TF1("f1", "gaus(0)/sqrt(2*3.14159)/[2]", 0, 5);
3047/// f1->SetParameters(1, 3.1, 0.01);
3048/// f1->SetParLimits(0, 1, 1); // fix the normalization parameter to 1
3049/// data->UnbinnedFit("f1", "jpsimass", "jpsipt>3.0");
3050/// ~~~
3051///
3052/// 1, 2 and 3 Dimensional fits are supported.
3053/// See also TTree::Fit
3054///
3055/// ### Return status
3056///
3057/// The function return the status of the fit in the following form
3058/// ~~~{.cpp}
3059/// fitResult = migradResult + 10*minosResult + 100*hesseResult + 1000*improveResult
3060/// ~~~
3061/// - The fitResult is 0 is the fit is OK.
3062/// - The fitResult is negative in case of an error not connected with the fit.
3063/// - The number of entries used in the fit can be obtained via
3064/// ~~~{.cpp}
3065/// mytree.GetSelectedRows();
3066/// ~~~
3067/// - If the number of selected entries is null the function returns -1
3068///
3069/// new implementation using new Fitter classes
3070
3071Int_t TTreePlayer::UnbinnedFit(const char *funcname ,const char *varexp, const char *selection,Option_t *option ,Long64_t nentries, Long64_t firstentry)
3072{
3073 // function is given by name, find it in gROOT
3074 TF1* fitfunc = (TF1*)gROOT->GetFunction(funcname);
3075 if (!fitfunc) { Error("UnbinnedFit", "Unknown function: %s",funcname); return 0; }
3076
3077 Int_t npar = fitfunc->GetNpar();
3078 if (npar <=0) { Error("UnbinnedFit", "Illegal number of parameters = %d",npar); return 0; }
3079
3080 // Spin through the data to select out the events of interest
3081 // Make sure that the arrays V1,etc are created large enough to accommodate
3082 // all entries
3083 Long64_t oldEstimate = fTree->GetEstimate();
3086
3087 // build FitOptions
3088 TString opt = option;
3089 opt.ToUpper();
3090 Foption_t fitOption;
3091 if (opt.Contains("Q")) fitOption.Quiet = 1;
3092 if (opt.Contains("V")){fitOption.Verbose = 1; fitOption.Quiet = 0;}
3093 if (opt.Contains("E")) fitOption.Errors = 1;
3094 if (opt.Contains("M")) fitOption.More = 1;
3095 if (!opt.Contains("D")) fitOption.Nograph = 1; // what about 0
3096 // could add range and automatic normalization of functions and gradient
3097
3098 TString drawOpt = "goff";
3099 if (!fitOption.Nograph) drawOpt = "";
3100 Long64_t nsel = DrawSelect(varexp, selection,drawOpt, nentries, firstentry);
3101
3102 if (!fitOption.Nograph && GetSelectedRows() <= 0 && GetDimension() > 4) {
3103 Info("UnbinnedFit","Ignore option D with more than 4 variables");
3104 nsel = DrawSelect(varexp, selection,"goff", nentries, firstentry);
3105 }
3106
3107 //if no selected entries return
3108 Long64_t nrows = GetSelectedRows();
3109
3110 if (nrows <= 0) {
3111 Error("UnbinnedFit", "Cannot fit: no entries selected");
3112 return -1;
3113 }
3114
3115 // Check that function has same dimension as number of variables
3116 Int_t ndim = GetDimension();
3117 // do not check with TF1::GetNdim() since it returns 1 for TF1 classes created with
3118 // a C function with larger dimension
3119
3120
3121 // use pointer stored in the tree (not copy the data in)
3122 std::vector<double *> vlist(ndim);
3123 for (int i = 0; i < ndim; ++i)
3124 vlist[i] = fSelector->GetVal(i);
3125
3126 // fill the fit data object
3127 // the object will be then managed by the fitted classes - however it will be invalid when the
3128 // data pointers (given by fSelector->GetVal() ) wil be invalidated
3129 ROOT::Fit::UnBinData * fitdata = new ROOT::Fit::UnBinData(nrows, ndim, vlist.begin());
3130
3131
3132
3134 TFitResultPtr ret = ROOT::Fit::UnBinFit(fitdata,fitfunc, fitOption, minOption);
3135
3136 //reset estimate
3137 fTree->SetEstimate(oldEstimate);
3138
3139 //if option "D" is specified, draw the projected histogram
3140 //with the fitted function normalized to the number of selected rows
3141 //and multiplied by the bin width
3142 if (!fitOption.Nograph && fHistogram) {
3143 if (fHistogram->GetDimension() < 2) {
3144 TH1 *hf = (TH1*)fHistogram->Clone("unbinnedFit");
3145 hf->SetLineWidth(3);
3146 hf->Reset();
3147 Int_t nbins = fHistogram->GetXaxis()->GetNbins();
3148 Double_t norm = ((Double_t)nsel)*fHistogram->GetXaxis()->GetBinWidth(1);
3149 for (Int_t bin=1;bin<=nbins;bin++) {
3150 Double_t func = norm*fitfunc->Eval(hf->GetBinCenter(bin));
3151 hf->SetBinContent(bin,func);
3152 }
3153 fHistogram->GetListOfFunctions()->Add(hf,"lsame");
3154 }
3155 fHistogram->Draw();
3156 }
3157
3158
3159 return int(ret);
3160
3161}
3162
3163////////////////////////////////////////////////////////////////////////////////
3164/// this function is called by TChain::LoadTree when a new Tree is loaded.
3165/// Because Trees in a TChain may have a different list of leaves, one
3166/// must update the leaves numbers in the TTreeFormula used by the TreePlayer.
3167
3169{
3170 if (fSelector) fSelector->Notify();
3171 if (fSelectorUpdate){
3172 //If the selector is writing into a TEntryList, the entry list's
3173 //sublists need to be changed according to the loaded tree
3175 //FIXME: should be more consistent with selector from file
3176 TObject *obj = fSelector->GetObject();
3177 if (obj){
3180 }
3181 }
3182 }
3185 TEntryList *elist=nullptr;
3186 while ((elist=(TEntryList*)next())){
3187 if (elist->InheritsFrom(TEntryList::Class())){
3188 elist->SetTree(fTree->GetTree());
3189 }
3190 }
3191 }
3192 }
3193
3194 if (fFormulaList->GetSize()) {
3196 while (lnk) {
3197 lnk->GetObject()->Notify();
3198 lnk = lnk->Next();
3199 }
3200 }
3201}
#define R__EXTERN
Definition DllImport.h:26
#define h(i)
Definition RSha256.hxx:106
double Double_t
Definition RtypesCore.h:59
constexpr Ssiz_t kNPOS
Definition RtypesCore.h:117
long long Long64_t
Definition RtypesCore.h:69
const char Option_t
Definition RtypesCore.h:66
#define ClassImp(name)
Definition Rtypes.h:382
R__EXTERN TApplication * gApplication
#define gDirectory
Definition TDirectory.h:384
R__EXTERN TEnv * gEnv
Definition TEnv.h:170
Option_t Option_t option
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char filename
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t UChar_t len
int nentries
R__EXTERN TVirtualMutex * gROOTMutex
Definition TROOT.h:63
#define gROOT
Definition TROOT.h:406
char * Form(const char *fmt,...)
Formats a string in a circular formatting buffer.
Definition TString.cxx:2489
void Printf(const char *fmt,...)
Formats a string in a circular formatting buffer and prints the string.
Definition TString.cxx:2503
R__EXTERN TStyle * gStyle
Definition TStyle.h:436
R__EXTERN TSystem * gSystem
Definition TSystem.h:561
TVirtualFitter * tFitter
R__EXTERN Foption_t Foption
static TString R__GetBranchPointerName(TLeaf *leaf, bool replace=true)
Return the name of the branch pointer needed by MakeClass/MakeSelector.
R__EXTERN TVirtualMonitoringWriter * gMonitoringWriter
#define R__LOCKGUARD(mutex)
#define gPad
#define snprintf
Definition civetweb.c:1540
Class describing the un-binned data sets (just x coordinates values) of any dimensions.
Definition UnBinData.h:46
virtual Int_t GetNdim() const
Definition TFormula.h:237
void InitializeGraphics(Bool_t only_web=kFALSE)
Initialize the graphics environment.
static void CreateApplication()
Static function used to create a default application environment.
static void NeedGraphicsLibs()
Static method.
virtual void SetLineWidth(Width_t lwidth)
Set the line width.
Definition TAttLine.h:43
virtual void SetTextAlign(Short_t align=11)
Set the text alignment.
Definition TAttText.h:42
virtual void SetTextColor(Color_t tcolor=1)
Set the text color.
Definition TAttText.h:44
virtual void SetTextFont(Font_t tfont=62)
Set the text font.
Definition TAttText.h:46
virtual void SetTextSize(Float_t tsize=1)
Set the text size.
Definition TAttText.h:47
Int_t GetNbins() const
Definition TAxis.h:125
virtual Double_t GetBinWidth(Int_t bin) const
Return bin width.
Definition TAxis.cxx:542
A Branch for the case of an object.
static TClass * Class()
const char * GetClassName() const override
Return the name of the user class whose content is stored in this branch, if any.
Int_t GetStreamerType() const
TBranchElement * GetBranchCount2() const
Int_t GetType() const
bool IsBranchFolder() const
static TClass * Class()
A TTree is a list of TBranches.
Definition TBranch.h:93
virtual const char * GetClassName() const
Return the name of the user class whose content is stored in this branch, if any.
Definition TBranch.cxx:1324
static TClass * Class()
TObjArray * GetListOfBranches()
Definition TBranch.h:246
TClass * IsA() const override
Definition TBranch.h:295
Int_t GetNleaves() const
Definition TBranch.h:249
TObjArray * GetListOfLeaves()
Definition TBranch.h:247
TBranch * GetMother() const
Get our top-level parent branch in the tree.
Definition TBranch.cxx:2127
A TChainElement describes a component of a TChain.
A Chain Index.
Definition TChainIndex.h:40
A chain is a collection of files containing TTree objects.
Definition TChain.h:33
static TClass * Class()
Long64_t * GetTreeOffset() const
Definition TChain.h:121
Long64_t LoadTree(Long64_t entry) override
Find the tree which contains entry, and set it as the current tree.
Definition TChain.cxx:1324
Int_t GetNtrees() const
Definition TChain.h:99
TLeaf * GetLeaf(const char *branchname, const char *leafname) override
Return a pointer to the leaf name in the current tree.
Definition TChain.cxx:1078
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition TClass.h:81
void AdoptReferenceProxy(TVirtualRefProxy *proxy)
Adopt the Reference proxy pointer to indicate that this class represents a reference.
Definition TClass.cxx:6754
Bool_t HasInterpreterInfo() const
Definition TClass.h:410
Bool_t IsLoaded() const
Return true if the shared library of this class is currently in the a process's memory.
Definition TClass.cxx:5981
TVirtualStreamerInfo * GetStreamerInfo(Int_t version=0, Bool_t isTransient=kFALSE) const
returns a pointer to the TVirtualStreamerInfo object for version If the object does not exist,...
Definition TClass.cxx:4668
Bool_t InheritsFrom(const char *cl) const override
Return kTRUE if this class inherits from a class with name "classname".
Definition TClass.cxx:4943
const char * GetDeclFileName() const
Return name of the file containing the declaration of this class.
Definition TClass.cxx:3532
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition TClass.cxx:3037
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
This class stores the date and time with a precision of one second in an unsigned 32 bit word (950130...
Definition TDatime.h:37
const char * AsString() const
Return the date & time as a string (ctime() format).
Definition TDatime.cxx:102
TDirectory::TContext keeps track and restore the current directory.
Definition TDirectory.h:89
virtual const char * GetPath() const
Returns the full path of the directory.
virtual TFile * GetFile() const
Definition TDirectory.h:220
A List of entry numbers in a TTree or TChain.
Definition TEntryList.h:26
static TClass * Class()
virtual void SetTree(const TTree *tree)
If a list for a tree with such name and filename exists, sets it as the current sublist If not,...
virtual Long64_t GetN() const
Definition TEntryList.h:78
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition TEnv.cxx:491
<div class="legacybox"><h2>Legacy Code</h2> TEventList is a legacy interface: there will be no bug fi...
Definition TEventList.h:31
1-Dim function class
Definition TF1.h:233
virtual Int_t GetNpar() const
Definition TF1.h:509
virtual Double_t Eval(Double_t x, Double_t y=0, Double_t z=0, Double_t t=0) const
Evaluate this function.
Definition TF1.cxx:1439
A ROOT file is an on-disk file, usually with extension .root, that stores objects in a file-system-li...
Definition TFile.h:53
static Long64_t GetFileBytesRead()
Static function returning the total number of bytes read from all files.
Definition TFile.cxx:4571
TFileCacheRead * GetCacheRead(const TObject *tree=nullptr) const
Return a pointer to the current read cache.
Definition TFile.cxx:1259
Provides an indirection to the TFitResult class and with a semantics identical to a TFitResult pointe...
TH1 is the base class of all histogram classes in ROOT.
Definition TH1.h:59
virtual Double_t GetBinCenter(Int_t bin) const
Return bin center for 1D histogram.
Definition TH1.cxx:9174
@ kNoAxis
NOTE: Must always be 0 !!!
Definition TH1.h:72
virtual Int_t GetDimension() const
Definition TH1.h:284
virtual void Reset(Option_t *option="")
Reset this histogram: contents, errors, etc.
Definition TH1.cxx:7132
TAxis * GetXaxis()
Definition TH1.h:325
virtual TFitResultPtr Fit(const char *formula, Option_t *option="", Option_t *goption="", Double_t xmin=0, Double_t xmax=0)
Fit histogram with function fname.
Definition TH1.cxx:3906
void Draw(Option_t *option="") override
Draw this histogram with options.
Definition TH1.cxx:3068
virtual void SetBinContent(Int_t bin, Double_t content)
Set bin content see convention for numbering bins in TH1::GetBin In case the bin number is greater th...
Definition TH1.cxx:9255
virtual UInt_t SetCanExtend(UInt_t extendBitMask)
Make the histogram axes extendable / not extendable according to the bit mask returns the previous bi...
Definition TH1.cxx:6678
TList * GetListOfFunctions() const
Definition TH1.h:245
virtual void Scale(Double_t c1=1, Option_t *option="")
Multiply this histogram by a constant c1.
Definition TH1.cxx:6633
TObject * Clone(const char *newname="") const override
Make a complete copy of the underlying object.
Definition TH1.cxx:2754
virtual Double_t GetSumOfWeights() const
Return the sum of weights excluding under/overflows.
Definition TH1.cxx:7950
virtual void LabelsDeflate(Option_t *axis="X")
Reduce the number of bins for the axis passed in the option to the number of bins having a label.
Definition TH1.cxx:5274
A TLeaf for a general object derived from TObject.
Definition TLeafObject.h:31
TClass * GetClass() const
Definition TLeafObject.h:59
const char * GetTypeName() const override
Returns name of leaf type.
A TLeaf describes individual elements of a TBranch See TBranch structure in TTree.
Definition TLeaf.h:57
virtual Int_t GetMaximum() const
Definition TLeaf.h:134
virtual const char * GetTypeName() const
Definition TLeaf.h:139
virtual Int_t GetLen() const
Return the number of effective elements of this leaf, for the current entry.
Definition TLeaf.cxx:404
virtual TLeaf * GetLeafCount() const
If this leaf stores a variable-sized array or a multi-dimensional array whose last dimension has vari...
Definition TLeaf.h:121
TBranch * GetBranch() const
Definition TLeaf.h:116
static TClass * Class()
A doubly linked list.
Definition TList.h:38
void Clear(Option_t *option="") override
Remove all objects from the list.
Definition TList.cxx:400
TObject * FindObject(const char *name) const override
Find an object in this list using its name.
Definition TList.cxx:576
void Add(TObject *obj) override
Definition TList.h:81
virtual TObjLink * FirstLink() const
Definition TList.h:102
void Delete(Option_t *option="") override
Remove all objects from the list AND delete all heap based objects.
Definition TList.cxx:468
TObject * At(Int_t idx) const override
Returns the object at position idx. Returns 0 if idx is out of range.
Definition TList.cxx:355
The TNamed class is the base class for all named ROOT classes.
Definition TNamed.h:29
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition TNamed.cxx:164
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
const char * GetTitle() const override
Returns title of object.
Definition TNamed.h:48
An array of TObjects.
Definition TObjArray.h:31
Int_t GetEntriesFast() const
Definition TObjArray.h:58
void AddAt(TObject *obj, Int_t idx) override
Add object at position ids.
TObject * Last() const override
Return the object in the last filled slot. Returns 0 if no entries.
Int_t GetEntries() const override
Return the number of objects in array (i.e.
void Delete(Option_t *option="") override
Remove all objects from the array AND delete all heap based objects.
TObject * At(Int_t idx) const override
Definition TObjArray.h:164
TObject * UncheckedAt(Int_t i) const
Definition TObjArray.h:84
TObject * FindObject(const char *name) const override
Find an object in this collection using its name.
void Add(TObject *obj) override
Definition TObjArray.h:68
Collectable string class.
Definition TObjString.h:28
const char * GetName() const override
Returns name of object.
Definition TObjString.h:38
Mother of all ROOT objects.
Definition TObject.h:41
virtual Bool_t Notify()
This method must be overridden to handle object notification (the base implementation is no-op).
Definition TObject.cxx:611
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:456
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:991
virtual TObject * FindObject(const char *name) const
Must be redefined in derived classes.
Definition TObject.cxx:420
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:798
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:542
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1005
virtual void Draw(Option_t *option="")
Default Draw method for all objects.
Definition TObject.cxx:292
@ kCanDelete
if object in a list can be deleted
Definition TObject.h:62
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition TObject.cxx:979
A 3D polymarker.
void Draw(Option_t *option="") override
Draws 3-D polymarker with its current attributes.
Principal Components Analysis (PCA)
Definition TPrincipal.h:21
Bool_t ProcessEvents()
Process events if timer did time out.
Definition TSystem.cxx:92
A container proxy, which allows to access references stored in a TRefArray from TTree::Draw.
A specialized TSelector for TTree::Draw.
virtual void SetEstimate(Long64_t n)
Set number of entries to estimate variable limits.
TTreeFormula * GetVar3() const
See TSelectorDraw::GetVar.
virtual Long64_t GetDrawFlag() const
TH1 * GetOldHistogram() const
virtual UInt_t SplitNames(const TString &varexp, std::vector< TString > &names)
Build Index array for names in varexp.
TObject * GetObject() const
TTreeFormula * GetVar2() const
See TSelectorDraw::GetVar.
virtual Int_t GetAction() const
TTreeFormula * GetVar1() const
See TSelectorDraw::GetVar.
virtual Int_t GetDimension() const
virtual Double_t * GetVal(Int_t i) const
Return the last values corresponding to the i-th component of the formula being processed (where the ...
bool Notify() override
This function is called at the first entry of a new tree in a chain.
virtual bool GetCleanElist() const
The class is derived from the ROOT class TSelector.
virtual Long64_t GetSelectedRows() const
A TSelector object is used by the TTree::Draw, TTree::Scan, TTree::Process to navigate in a TTree and...
Definition TSelector.h:31
virtual EAbort GetAbort() const
Definition TSelector.h:73
virtual void ProcessFill(Long64_t)
This method is called for all selected entries.
@ kAbortProcess
Definition TSelector.h:34
virtual void Init(TTree *)
Definition TSelector.h:53
virtual int Version() const
Definition TSelector.h:52
virtual bool ProcessCut(Long64_t)
This method is called before processing entry.
virtual bool Process(Long64_t)
The Process() function is called for each entry in the tree (or possibly keyed object in the case of ...
TClass * IsA() const override
Definition TSelector.h:79
virtual void SlaveBegin(TTree *)
Definition TSelector.h:55
bool Notify() override
This method must be overridden to handle object notification (the base implementation is no-op).
Definition TSelector.h:56
virtual void SetOption(const char *option)
Definition TSelector.h:64
virtual Long64_t GetStatus() const
Definition TSelector.h:58
virtual void SetInputList(TList *input)
Definition TSelector.h:66
virtual TList * GetOutputList() const
Definition TSelector.h:69
virtual void SlaveTerminate()
Definition TSelector.h:70
virtual void ResetAbort()
Definition TSelector.h:74
virtual void Begin(TTree *)
Definition TSelector.h:54
virtual void Terminate()
Definition TSelector.h:71
static TSelector * GetSelector(const char *filename)
The code in filename is loaded (interpreted or compiled, see below), filename must contain a valid cl...
Int_t LastIndex() const
static TClass * Class()
const char * GetTypeName() const
TClass * IsA() const override
Basic string class.
Definition TString.h:139
Ssiz_t Length() const
Definition TString.h:417
void ToLower()
Change string to lower-case.
Definition TString.cxx:1182
const char * Data() const
Definition TString.h:376
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition TString.h:704
Ssiz_t Last(char c) const
Find last occurrence of a character c.
Definition TString.cxx:931
void ToUpper()
Change string to upper case.
Definition TString.cxx:1195
TString & Remove(Ssiz_t pos)
Definition TString.h:685
TString & Append(const char *cs)
Definition TString.h:572
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition TString.cxx:2356
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:632
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:651
Bool_t GetCanvasPreferGL() const
Definition TStyle.h:187
void SetCanvasPreferGL(Bool_t prefer=kTRUE)
Definition TStyle.h:341
Int_t GetNumberOfColors() const
Return number of colors in the color palette.
Definition TStyle.cxx:1175
virtual Bool_t IsFileInIncludePath(const char *name, char **fullpath=nullptr)
Return true if 'name' is a file that can be found in the ROOT include path or the current directory.
Definition TSystem.cxx:966
virtual TString SplitAclicMode(const char *filename, TString &mode, TString &args, TString &io) const
This method split a filename of the form:
Definition TSystem.cxx:4258
Base class for several text objects.
Definition TText.h:22
A cache to speed-up the reading of ROOT datasets.
Definition TTreeCache.h:32
virtual void SetEntryRange(Long64_t emin, Long64_t emax)
Set the minimum and maximum entry number to be processed this information helps to optimize the numbe...
Used to coordinate one or more TTreeFormula objects.
virtual void UpdateFormulaLeaves()
This function could be called TTreePlayer::UpdateFormulaLeaves, itself called by TChain::LoadTree whe...
virtual Int_t GetNdata(bool forceLoadDim=false)
Return number of available instances in the formulas.
virtual void Add(TTreeFormula *)
Add a new formula to the list of formulas managed The manager of the formula will be changed and the ...
virtual bool Sync()
Synchronize all the formulae.
virtual Int_t GetMultiplicity() const
Used to pass a selection expression to the Tree drawing routine.
virtual bool IsInteger(bool fast=true) const
Return TRUE if the formula corresponds to one single Tree leaf and this leaf is short,...
TTreeFormulaManager * GetManager() const
virtual char * PrintValue(Int_t mode=0) const
Return value of variable as a string.
T EvalInstance(Int_t i=0, const char *stringStack[]=nullptr)
Evaluate this treeformula.
virtual void UpdateFormulaLeaves()
This function is called TTreePlayer::UpdateFormulaLeaves, itself called by TChain::LoadTree when a ne...
virtual Int_t GetNdata()
Return number of available instances in the formula.
A Tree Index with majorname and minorname.
Definition TTreeIndex.h:29
Implement some of the functionality of the class TTree requiring access to extra libraries (Histogram...
Definition TTreePlayer.h:37
Int_t MakeCode(const char *filename) override
Generate skeleton function for this Tree.
TTree * CopyTree(const char *selection, Option_t *option, Long64_t nentries, Long64_t firstentry) override
Copy a Tree with selection, make a clone of this Tree header, then copy the selected entries.
Long64_t DrawSelect(const char *varexp, const char *selection, Option_t *option, Long64_t nentries, Long64_t firstentry) override
Draw expression varexp for specified entries that matches the selection.
TList * fInput
! input list to the selector
Definition TTreePlayer.h:53
void DeleteSelectorFromFile()
Delete any selector created by this object.
void SetEstimate(Long64_t n) override
Set number of entries to estimate variable limits.
Int_t UnbinnedFit(const char *formula, const char *varexp, const char *selection, Option_t *option, Long64_t nentries, Long64_t firstentry) override
Unbinned fit of one or more variable(s) from a Tree.
void RecursiveRemove(TObject *obj) override
cleanup pointers in the player pointing to obj
Long64_t DrawScript(const char *wrapperPrefix, const char *macrofilename, const char *cutfilename, Option_t *option, Long64_t nentries, Long64_t firstentry) override
Draw the result of a C++ script.
TSelectorDraw * fSelector
! Pointer to current selector
Definition TTreePlayer.h:50
void SetTree(TTree *t) override
Long64_t GetSelectedRows() const override
Definition TTreePlayer.h:81
Int_t MakeReader(const char *classname, Option_t *option) override
Generate skeleton selector class for this tree.
const char * GetNameByIndex(TString &varexp, Int_t *index, Int_t colindex)
Return name corresponding to colindex in varexp.
Long64_t fSelectedRows
Number of selected entries.
Definition TTreePlayer.h:48
Long64_t Scan(const char *varexp, const char *selection, Option_t *option, Long64_t nentries, Long64_t firstentry) override
Loop on Tree and print entries passing selection.
TSelector * fSelectorFromFile
! Pointer to a user defined selector created by this TTreePlayer object
Definition TTreePlayer.h:51
const char * fScanFileName
Name of the file where Scan is redirected.
Definition TTreePlayer.h:46
TList * fFormulaList
! Pointer to a list of coordinated list TTreeFormula (used by Scan and Query)
Definition TTreePlayer.h:54
bool fScanRedirect
Switch to redirect TTree::Scan output to a file.
Definition TTreePlayer.h:45
TTree * fTree
! Pointer to current Tree
Definition TTreePlayer.h:44
void StartViewer(Int_t ww, Int_t wh) override
Start the TTreeViewer on this TTree.
Int_t MakeProxy(const char *classname, const char *macrofilename=nullptr, const char *cutfilename=nullptr, const char *option=nullptr, Int_t maxUnrolling=3) override
Generate a skeleton analysis class for this Tree using TBranchProxy.
Int_t MakeClass(const char *classname, Option_t *option) override
Generate skeleton analysis class for this Tree.
TPrincipal * Principal(const char *varexp, const char *selection, Option_t *option, Long64_t nentries, Long64_t firstentry) override
Interface to the Principal Components Analysis class.
TSelector * fSelectorUpdate
! Set to the selector address when it's entry list needs to be updated by the UpdateFormulaLeaves fun...
Definition TTreePlayer.h:55
TH1 * fHistogram
! Pointer to histogram used for the projection
Definition TTreePlayer.h:49
void UpdateFormulaLeaves() override
this function is called by TChain::LoadTree when a new Tree is loaded.
Long64_t Process(const char *filename, Option_t *option, Long64_t nentries, Long64_t firstentry) override
Process this tree executing the TSelector code in the specified filename.
TSQLResult * Query(const char *varexp, const char *selection, Option_t *option, Long64_t nentries, Long64_t firstentry) override
Loop on Tree and return TSQLResult object containing entries passing selection.
TClass * fSelectorClass
! Pointer to the actual class of the TSelectorFromFile
Definition TTreePlayer.h:52
Long64_t GetEntries(const char *selection) override
Return the number of entries matching the selection.
Int_t GetDimension() const override
Definition TTreePlayer.h:74
Int_t fDimension
Dimension of the current expression.
Definition TTreePlayer.h:47
TVirtualIndex * BuildIndex(const TTree *T, const char *majorname, const char *minorname) override
Build the index for the tree (see TTree::BuildIndex)
TTreePlayer()
Default Tree constructor.
~TTreePlayer() override
Tree destructor.
Int_t Fit(const char *formula, const char *varexp, const char *selection, Option_t *option, Option_t *goption, Long64_t nentries, Long64_t firstentry) override
Fit a projected item(s) from a Tree.
virtual Long64_t GetEntriesToProcess(Long64_t firstentry, Long64_t nentries) const
return the number of entries to be processed this function checks that nentries is not bigger than th...
Class defining interface to a TTree query result with the same interface as for SQL databases.
Definition TTreeResult.h:34
void AddRow(TSQLRow *row)
Adopt a row to result set.
void AddField(Int_t field, const char *fieldname)
Add field name to result set.
Class defining interface to a row of a TTree query result.
Definition TTreeRow.h:29
A TTree represents a columnar dataset.
Definition TTree.h:79
bool EnableCache()
Enable the TTreeCache unless explicitly disabled for this TTree by a prior call to SetCacheSize(0).
Definition TTree.cxx:2675
virtual TBranch * GetBranch(const char *name)
Return pointer to the branch with the given name in this tree or its friends.
Definition TTree.cxx:5284
virtual Int_t GetScanField() const
Definition TTree.h:551
virtual Int_t GetEntry(Long64_t entry, Int_t getall=0)
Read all branches of entry and return total number of bytes read.
Definition TTree.cxx:5628
virtual Long64_t GetEstimate() const
Definition TTree.h:507
virtual TObjArray * GetListOfLeaves()
Definition TTree.h:529
TFile * GetCurrentFile() const
Return pointer to the current file.
Definition TTree.cxx:5469
void Draw(Option_t *opt) override
Default Draw method for all objects.
Definition TTree.h:431
virtual void SetNotify(TObject *obj)
Sets the address of the object to be notified when the tree is loaded.
Definition TTree.cxx:9221
TDirectory * GetDirectory() const
Definition TTree.h:462
virtual TEntryList * GetEntryList()
Returns the entry list assigned to this tree.
Definition TTree.cxx:5844
virtual Long64_t Process(const char *filename, Option_t *option="", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)
Process this tree executing the TSelector code in the specified filename.
Definition TTree.cxx:7440
virtual Long64_t GetEntries() const
Definition TTree.h:463
virtual void SetEstimate(Long64_t nentries=1000000)
Set number of entries to estimate variable limits.
Definition TTree.cxx:9100
virtual Long64_t GetEntryNumber(Long64_t entry) const
Return entry number corresponding to entry.
Definition TTree.cxx:5855
virtual TTree * CloneTree(Long64_t nentries=-1, Option_t *option="")
Create a clone of this tree and copy nentries.
Definition TTree.cxx:3129
virtual TTree * GetTree() const
Definition TTree.h:557
virtual void SetEntryList(TEntryList *list, Option_t *opt="")
Set an EntryList.
Definition TTree.cxx:9036
virtual Long64_t LoadTree(Long64_t entry)
Set current entry.
Definition TTree.cxx:6463
TEventList * GetEventList() const
Definition TTree.h:513
virtual Long64_t GetEntriesFriend() const
Return pointer to the 1st Leaf named name in any Branch of this Tree or any branch in the list of fri...
Definition TTree.cxx:5502
virtual Int_t GetTreeNumber() const
Definition TTree.h:559
virtual Int_t GetTimerInterval() const
Definition TTree.h:554
virtual void SetScanField(Int_t n=50)
Sets the default maximum number of lines to be shown before <CR> when calling Scan().
Definition TTree.h:691
virtual Long64_t GetCacheSize() const
Definition TTree.h:453
virtual Long64_t GetMaxEntryLoop() const
Definition TTree.h:537
Abstract Base Class for Fitting.
Abstract interface for Tree Index.
virtual Bool_t SendProcessingProgress(Double_t, Double_t, Bool_t=kFALSE)
virtual Bool_t SendProcessingStatus(const char *, Bool_t=kFALSE)
virtual TObjArray * GetElements() const =0
const Int_t n
Definition legend1.C:16
TFitResultPtr UnBinFit(ROOT::Fit::UnBinData *data, TF1 *f1, Foption_t &option, const ROOT::Math::MinimizerOptions &moption)
fit an unbin data set (from tree or from histogram buffer) using a TF1 pointer and fit options.
Definition HFitImpl.cxx:821
TString GetCppName(TString name)
Convert a valid TTree branch name or filename into a valid C++ variable name.
Short_t Max(Short_t a, Short_t b)
Returns the largest of a and b.
Definition TMathBase.h:250
Short_t Min(Short_t a, Short_t b)
Returns the smallest of a and b.
Definition TMathBase.h:198
Definition graph.py:1
int Nograph
Definition Foption.h:42
int Quiet
Definition Foption.h:29
int More
Definition Foption.h:38
int Errors
Definition Foption.h:37
int Verbose
Definition Foption.h:30
TLine l
Definition textangle.C:4