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 if (!classname) classname = fTree->GetName();
737
738 TString thead;
739 thead.Form("%s.h", classname);
740 FILE *fp = fopen(thead, "w");
741 if (!fp) {
742 Error("MakeClass","cannot open output file %s", thead.Data());
743 return 3;
744 }
745 TString tcimp;
746 tcimp.Form("%s.C", classname);
747 FILE *fpc = fopen(tcimp, "w");
748 if (!fpc) {
749 Error("MakeClass","cannot open output file %s", tcimp.Data());
750 fclose(fp);
751 return 3;
752 }
753 TString treefile;
754 if (fTree->GetDirectory() && fTree->GetDirectory()->GetFile()) {
755 treefile = fTree->GetDirectory()->GetFile()->GetName();
756 } else {
757 treefile = "Memory Directory";
758 }
759 // In the case of a chain, the GetDirectory information usually does
760 // pertain to the Chain itself but to the currently loaded tree.
761 // So we can not rely on it.
762 bool ischain = fTree->InheritsFrom(TChain::Class());
763 bool isHbook = fTree->InheritsFrom("THbookTree");
764 if (isHbook)
765 treefile = fTree->GetTitle();
766
767//======================Generate classname.h=====================
768 // Print header
769 TObjArray *leaves = fTree->GetListOfLeaves();
770 Int_t nleaves = leaves ? leaves->GetEntriesFast() : 0;
771 TDatime td;
772 fprintf(fp,"//////////////////////////////////////////////////////////\n");
773 fprintf(fp,"// This class has been automatically generated on\n");
774 fprintf(fp,"// %s by ROOT version %s\n",td.AsString(),gROOT->GetVersion());
775 if (!ischain) {
776 fprintf(fp,"// from TTree %s/%s\n",fTree->GetName(),fTree->GetTitle());
777 fprintf(fp,"// found on file: %s\n",treefile.Data());
778 } else {
779 fprintf(fp,"// from TChain %s/%s\n",fTree->GetName(),fTree->GetTitle());
780 }
781 fprintf(fp,"//////////////////////////////////////////////////////////\n");
782 fprintf(fp,"\n");
783 fprintf(fp,"#ifndef %s_h\n",classname);
784 fprintf(fp,"#define %s_h\n",classname);
785 fprintf(fp,"\n");
786 fprintf(fp,"#include <TROOT.h>\n");
787 fprintf(fp,"#include <TChain.h>\n");
788 fprintf(fp,"#include <TFile.h>\n");
789 if (isHbook) fprintf(fp,"#include <THbookFile.h>\n");
790 if (opt.Contains("selector")) fprintf(fp,"#include <TSelector.h>\n");
791
792 // See if we can add any #include about the user data.
793 Int_t l;
794 fprintf(fp,"\n// Header file for the classes stored in the TTree if any.\n");
795 TList listOfHeaders;
796 listOfHeaders.SetOwner();
797 for (l=0;l<nleaves;l++) {
798 TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(l);
799 TBranch *branch = leaf->GetBranch();
800 TClass *cl = TClass::GetClass(branch->GetClassName());
801 if (cl && cl->IsLoaded() && !listOfHeaders.FindObject(cl->GetName())) {
802 const char *declfile = cl->GetDeclFileName();
803 if (declfile && declfile[0]) {
804 static const char *precstl = "prec_stl/";
805 static const unsigned int precstl_len = strlen(precstl);
806 static const char *rootinclude = "include/";
807 static const unsigned int rootinclude_len = strlen(rootinclude);
808 if (strncmp(declfile,precstl,precstl_len) == 0) {
809 fprintf(fp,"#include <%s>\n",declfile+precstl_len);
810 listOfHeaders.Add(new TNamed(cl->GetName(),declfile+precstl_len));
811 } else if (strncmp(declfile,"/usr/include/",13) == 0) {
812 fprintf(fp,"#include <%s>\n",declfile+strlen("/include/c++/"));
813 listOfHeaders.Add(new TNamed(cl->GetName(),declfile+strlen("/include/c++/")));
814 } else if (strstr(declfile,"/include/c++/") != nullptr) {
815 fprintf(fp,"#include <%s>\n",declfile+strlen("/include/c++/"));
816 listOfHeaders.Add(new TNamed(cl->GetName(),declfile+strlen("/include/c++/")));
817 } else if (strncmp(declfile,rootinclude,rootinclude_len) == 0) {
818 fprintf(fp,"#include <%s>\n",declfile+rootinclude_len);
819 listOfHeaders.Add(new TNamed(cl->GetName(),declfile+rootinclude_len));
820 } else {
821 fprintf(fp,"#include \"%s\"\n",declfile);
822 listOfHeaders.Add(new TNamed(cl->GetName(),declfile));
823 }
824 }
825 }
826 }
827
828 // First loop on all leaves to generate dimension declarations
829 Int_t len, lenb;
830 char blen[1024];
831 char *bname;
832 Int_t *leaflen = new Int_t[nleaves];
833 TObjArray *leafs = new TObjArray(nleaves);
834 for (l=0;l<nleaves;l++) {
835 TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(l);
836 leafs->AddAt(new TObjString(leaf->GetName()),l);
837 leaflen[l] = leaf->GetMaximum();
838 }
839 if (ischain) {
840 // In case of a chain, one must find the maximum dimension of each leaf
841 // One must be careful and not assume that all Trees in the chain
842 // have the same leaves and in the same order!
843 TChain *chain = (TChain*)fTree;
844 Int_t ntrees = chain->GetNtrees();
845 for (Int_t file=0;file<ntrees;file++) {
846 Long64_t first = chain->GetTreeOffset()[file];
847 chain->LoadTree(first);
848 for (l=0;l<nleaves;l++) {
849 TObjString *obj = (TObjString*)leafs->At(l);
850 TLeaf *leaf = chain->GetLeaf(obj->GetName());
851 if (leaf) {
852 leaflen[l] = TMath::Max(leaflen[l],leaf->GetMaximum());
853 }
854 }
855 }
856 chain->LoadTree(0);
857 }
858
859 fprintf(fp,"\n");
860 if (opt.Contains("selector")) {
861 fprintf(fp,"class %s : public TSelector {\n",classname);
862 fprintf(fp,"public :\n");
863 fprintf(fp," TTree *fChain; //!pointer to the analyzed TTree or TChain\n");
864 } else {
865 fprintf(fp,"class %s {\n",classname);
866 fprintf(fp,"public :\n");
867 fprintf(fp," TTree *fChain; //!pointer to the analyzed TTree or TChain\n");
868 fprintf(fp," Int_t fCurrent; //!current Tree number in a TChain\n");
869 }
870
871 fprintf(fp,"\n// Fixed size dimensions of array or collections stored in the TTree if any.\n");
872 leaves = fTree->GetListOfLeaves();
873 for (l=0;l<nleaves;l++) {
874 TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(l);
875 strlcpy(blen,leaf->GetName(),sizeof(blen));
876 bname = &blen[0];
877 while (*bname) {
878 if (*bname == '.') *bname='_';
879 if (*bname == ',') *bname='_';
880 if (*bname == ':') *bname='_';
881 if (*bname == '<') *bname='_';
882 if (*bname == '>') *bname='_';
883 bname++;
884 }
885 lenb = strlen(blen);
886 if (blen[lenb-1] == '_') {
887 blen[lenb-1] = 0;
888 len = leaflen[l];
889 if (len <= 0) len = 1;
890 fprintf(fp," static constexpr Int_t kMax%s = %d;\n",blen,len);
891 }
892 }
893 delete [] leaflen;
894 leafs->Delete();
895 delete leafs;
896
897// second loop on all leaves to generate type declarations
898 fprintf(fp,"\n // Declaration of leaf types\n");
899 TLeaf *leafcount;
900 TLeafObject *leafobj;
901 TBranchElement *bre=nullptr;
902 const char *headOK = " ";
903 const char *headcom = " //";
904 const char *head;
905 char branchname[1024];
906 char aprefix[1024];
907 TObjArray branches(100);
908 TObjArray mustInit(100);
909 TObjArray mustInitArr(100);
910 mustInitArr.SetOwner(false);
911 Int_t *leafStatus = new Int_t[nleaves];
912 for (l=0;l<nleaves;l++) {
913 Int_t kmax = 0;
914 head = headOK;
915 leafStatus[l] = 0;
916 TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(l);
917 len = leaf->GetLen(); if (len<=0) len = 1;
918 leafcount =leaf->GetLeafCount();
919 TBranch *branch = leaf->GetBranch();
920 branchname[0] = 0;
921 strlcpy(branchname,branch->GetName(),sizeof(branchname));
922 strlcpy(aprefix,branch->GetName(),sizeof(aprefix));
923 if (!branches.FindObject(branch)) branches.Add(branch);
924 else leafStatus[l] = 1;
925 if ( branch->GetNleaves() > 1) {
926 // More than one leaf for the branch we need to distinguish them
927 strlcat(branchname,".",sizeof(branchname));
928 strlcat(branchname,leaf->GetTitle(),sizeof(branchname));
929 if (leafcount) {
930 // remove any dimension in title
931 char *dim = (char*)strstr(branchname,"["); if (dim) dim[0] = 0;
932 }
933 } else {
934 strlcpy(branchname,branch->GetName(),sizeof(branchname));
935 }
936 char *twodim = (char*)strstr(leaf->GetTitle(),"][");
937 bname = branchname;
938 while (*bname) {
939 if (*bname == '.') *bname='_';
940 if (*bname == ',') *bname='_';
941 if (*bname == ':') *bname='_';
942 if (*bname == '<') *bname='_';
943 if (*bname == '>') *bname='_';
944 bname++;
945 }
946 if (branch->IsA() == TBranchObject::Class()) {
947 if (branch->GetListOfBranches()->GetEntriesFast()) {leafStatus[l] = 1; continue;}
948 leafobj = (TLeafObject*)leaf;
949 if (!leafobj->GetClass()) {leafStatus[l] = 1; head = headcom;}
950 fprintf(fp,"%s%-15s *%s;\n",head,leafobj->GetTypeName(), leafobj->GetName());
951 if (leafStatus[l] == 0) mustInit.Add(leafobj);
952 continue;
953 }
954 if (leafcount) {
955 len = leafcount->GetMaximum();
956 if (len<=0) len = 1;
957 strlcpy(blen,leafcount->GetName(),sizeof(blen));
958 bname = &blen[0];
959 while (*bname) {
960 if (*bname == '.') *bname='_';
961 if (*bname == ',') *bname='_';
962 if (*bname == ':') *bname='_';
963 if (*bname == '<') *bname='_';
964 if (*bname == '>') *bname='_';
965 bname++;
966 }
967 lenb = strlen(blen);
968 if (blen[lenb-1] == '_') {blen[lenb-1] = 0; kmax = 1;}
969 else snprintf(blen,sizeof(blen),"%d",len);
970 }
971 if (branch->IsA() == TBranchElement::Class()) {
972 bre = (TBranchElement*)branch;
973 if (bre->GetType() != 3 && bre->GetType() != 4
974 && bre->GetStreamerType() <= 0 && bre->GetListOfBranches()->GetEntriesFast()) {
975 leafStatus[l] = 0;
976 }
977 if (bre->GetType() == 3 || bre->GetType() == 4) {
978 fprintf(fp," %-15s %s_;\n","Int_t", branchname);
979 continue;
980 }
981 if (bre->IsBranchFolder()) {
982 fprintf(fp," %-15s *%s;\n",bre->GetClassName(), branchname);
983 mustInit.Add(bre);
984 continue;
985 } else {
986 if (branch->GetListOfBranches()->GetEntriesFast()) {leafStatus[l] = 1;}
987 }
988 if (bre->GetStreamerType() < 0) {
989 if (branch->GetListOfBranches()->GetEntriesFast()) {
990 fprintf(fp,"%s%-15s *%s;\n",headcom,bre->GetClassName(), branchname);
991 } else {
992 fprintf(fp,"%s%-15s *%s;\n",head,bre->GetClassName(), branchname);
993 mustInit.Add(bre);
994 }
995 continue;
996 }
997 if (bre->GetStreamerType() == 0) {
998 if (!TClass::GetClass(bre->GetClassName())->HasInterpreterInfo()) {leafStatus[l] = 1; head = headcom;}
999 fprintf(fp,"%s%-15s *%s;\n",head,bre->GetClassName(), branchname);
1000 if (leafStatus[l] == 0) mustInit.Add(bre);
1001 continue;
1002 }
1003 if (bre->GetStreamerType() > 60) {
1004 TClass *cle = TClass::GetClass(bre->GetClassName());
1005 if (!cle) {leafStatus[l] = 1; continue;}
1006 if (bre->GetStreamerType() == 66) leafStatus[l] = 0;
1007 char brename[256];
1008 strlcpy(brename,bre->GetName(),255);
1009 char *bren = brename;
1010 char *adot = strrchr(bren,'.');
1011 if (adot) bren = adot+1;
1012 char *brack = strchr(bren,'[');
1013 if (brack) *brack = 0;
1015 if (elem) {
1016 if (elem->IsA() == TStreamerBase::Class()) {leafStatus[l] = 1; continue;}
1017 if (!TClass::GetClass(elem->GetTypeName())) {leafStatus[l] = 1; continue;}
1018 if (!TClass::GetClass(elem->GetTypeName())->HasInterpreterInfo()) {leafStatus[l] = 1; head = headcom;}
1019 if (leafcount) fprintf(fp,"%s%-15s %s[kMax%s];\n",head,elem->GetTypeName(), branchname,blen);
1020 else fprintf(fp,"%s%-15s %s;\n",head,elem->GetTypeName(), branchname);
1021 } else {
1022 if (!TClass::GetClass(bre->GetClassName())->HasInterpreterInfo()) {leafStatus[l] = 1; head = headcom;}
1023 fprintf(fp,"%s%-15s %s;\n",head,bre->GetClassName(), branchname);
1024 }
1025 continue;
1026 }
1027 }
1028 if (strlen(leaf->GetTypeName()) == 0) {leafStatus[l] = 1; continue;}
1029 if (leafcount) {
1030 //len = leafcount->GetMaximum();
1031 //strlcpy(blen,leafcount->GetName(),sizeof(blen));
1032 //bname = &blen[0];
1033 //while (*bname) {if (*bname == '.') *bname='_'; bname++;}
1034 //lenb = strlen(blen);
1035 //Int_t kmax = 0;
1036 //if (blen[lenb-1] == '_') {blen[lenb-1] = 0; kmax = 1;}
1037 //else sprintf(blen,"%d",len);
1038
1039 const char *stars = " ";
1040 if (bre && bre->GetBranchCount2()) {
1041 stars = "*";
1042 }
1043 // Dimensions can be in the branchname for a split Object with a fix length C array.
1044 // Theses dimensions HAVE TO be placed after the dimension explicited by leafcount
1045 TString dimensions;
1046 char *dimInName = (char*) strstr(branchname,"[");
1047 if ( twodim || dimInName ) {
1048 if (dimInName) {
1049 dimensions = dimInName;
1050 dimInName[0] = 0; // terminate branchname before the array dimensions.
1051 }
1052 if (twodim) dimensions += (char*)(twodim+1);
1053 }
1054 const char* leafcountName = leafcount->GetName();
1055 char b2len[1024];
1056 if (bre && bre->GetBranchCount2()) {
1057 TLeaf * l2 = (TLeaf*)bre->GetBranchCount2()->GetListOfLeaves()->At(0);
1058 strlcpy(b2len,l2->GetName(),sizeof(b2len));
1059 bname = &b2len[0];
1060 while (*bname) {
1061 if (*bname == '.') *bname='_';
1062 if (*bname == ',') *bname='_';
1063 if (*bname == ':') *bname='_';
1064 if (*bname == '<') *bname='_';
1065 if (*bname == '>') *bname='_';
1066 bname++;
1067 }
1068 leafcountName = b2len;
1069 }
1070 if (dimensions.Length()) {
1071 if (kmax) fprintf(fp," %-14s %s%s[kMax%s]%s; //[%s]\n",leaf->GetTypeName(), stars,
1072 branchname,blen,dimensions.Data(),leafcountName);
1073 else fprintf(fp," %-14s %s%s[%d]%s; //[%s]\n",leaf->GetTypeName(), stars,
1074 branchname,len,dimensions.Data(),leafcountName);
1075 } else {
1076 if (kmax) fprintf(fp," %-14s %s%s[kMax%s]; //[%s]\n",leaf->GetTypeName(), stars, branchname,blen,leafcountName);
1077 else fprintf(fp," %-14s %s%s[%d]; //[%s]\n",leaf->GetTypeName(), stars, branchname,len,leafcountName);
1078 }
1079 if (stars[0]=='*') {
1080 TNamed *n;
1081 if (kmax) n = new TNamed(branchname, Form("kMax%s",blen));
1082 else n = new TNamed(branchname, Form("%d",len));
1083 mustInitArr.Add(n);
1084 }
1085 } else {
1086 if (strstr(branchname,"[")) len = 1;
1087 if (len < 2) fprintf(fp," %-15s %s;\n",leaf->GetTypeName(), branchname);
1088 else {
1089 if (twodim) fprintf(fp," %-15s %s%s;\n",leaf->GetTypeName(), branchname,(char*)strstr(leaf->GetTitle(),"["));
1090 else fprintf(fp," %-15s %s[%d];\n",leaf->GetTypeName(), branchname,len);
1091 }
1092 }
1093 }
1094
1095// generate list of branches
1096 fprintf(fp,"\n");
1097 fprintf(fp," // List of branches\n");
1098 for (l=0;l<nleaves;l++) {
1099 if (leafStatus[l]) continue;
1100 TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(l);
1101 fprintf(fp," TBranch *b_%s; //!\n",R__GetBranchPointerName(leaf).Data());
1102 }
1103
1104// generate class member functions prototypes
1105 if (opt.Contains("selector")) {
1106 fprintf(fp,"\n");
1107 fprintf(fp," %s(TTree * /*tree*/ =0) : fChain(0) { }\n",classname) ;
1108 fprintf(fp," ~%s() override { }\n",classname);
1109 fprintf(fp," Int_t Version() const override { return 2; }\n");
1110 fprintf(fp," void Begin(TTree *tree) override;\n");
1111 fprintf(fp," void SlaveBegin(TTree *tree) override;\n");
1112 fprintf(fp," void Init(TTree *tree) override;\n");
1113 fprintf(fp," bool Notify() override;\n");
1114 fprintf(fp," bool Process(Long64_t entry) override;\n");
1115 fprintf(fp," Int_t GetEntry(Long64_t entry, Int_t getall = 0) override { return fChain ? fChain->GetTree()->GetEntry(entry, getall) : 0; }\n");
1116 fprintf(fp," void SetOption(const char *option) override { fOption = option; }\n");
1117 fprintf(fp," void SetObject(TObject *obj) override { fObject = obj; }\n");
1118 fprintf(fp," void SetInputList(TList *input) override { fInput = input; }\n");
1119 fprintf(fp," TList* GetOutputList() const override { return fOutput; }\n");
1120 fprintf(fp," void SlaveTerminate() override;\n");
1121 fprintf(fp," void Terminate() override;\n\n");
1122 fprintf(fp," ClassDefOverride(%s,0);\n",classname);
1123 fprintf(fp,"};\n");
1124 fprintf(fp,"\n");
1125 fprintf(fp,"#endif\n");
1126 fprintf(fp,"\n");
1127 } else {
1128 fprintf(fp,"\n");
1129 fprintf(fp," %s(TTree *tree=0);\n",classname);
1130 fprintf(fp," virtual ~%s();\n",classname);
1131 fprintf(fp," virtual Int_t Cut(Long64_t entry);\n");
1132 fprintf(fp," virtual Int_t GetEntry(Long64_t entry);\n");
1133 fprintf(fp," virtual Long64_t LoadTree(Long64_t entry);\n");
1134 fprintf(fp," virtual void Init(TTree *tree);\n");
1135 fprintf(fp," virtual void Loop();\n");
1136 fprintf(fp," virtual bool Notify();\n");
1137 fprintf(fp," virtual void Show(Long64_t entry = -1);\n");
1138 fprintf(fp,"};\n");
1139 fprintf(fp,"\n");
1140 fprintf(fp,"#endif\n");
1141 fprintf(fp,"\n");
1142 }
1143// generate code for class constructor
1144 fprintf(fp,"#ifdef %s_cxx\n",classname);
1145 if (!opt.Contains("selector")) {
1146 fprintf(fp,"%s::%s(TTree *tree) : fChain(0) \n",classname,classname);
1147 fprintf(fp,"{\n");
1148 fprintf(fp,"// if parameter tree is not specified (or zero), connect the file\n");
1149 fprintf(fp,"// used to generate this class and read the Tree.\n");
1150 fprintf(fp," if (tree == 0) {\n");
1151 if (ischain) {
1152 fprintf(fp,"\n#ifdef SINGLE_TREE\n");
1153 fprintf(fp," // The following code should be used if you want this class to access\n");
1154 fprintf(fp," // a single tree instead of a chain\n");
1155 }
1156 if (isHbook) {
1157 fprintf(fp," THbookFile *f = (THbookFile*)gROOT->GetListOfBrowsables()->FindObject(\"%s\");\n",
1158 treefile.Data());
1159 fprintf(fp," if (!f) {\n");
1160 fprintf(fp," f = new THbookFile(\"%s\");\n",treefile.Data());
1161 fprintf(fp," }\n");
1162 Int_t hid;
1163 sscanf(fTree->GetName(),"h%d",&hid);
1164 fprintf(fp," tree = (TTree*)f->Get(%d);\n\n",hid);
1165 } else {
1166 fprintf(fp," TFile *f = (TFile*)gROOT->GetListOfFiles()->FindObject(\"%s\");\n",treefile.Data());
1167 fprintf(fp," if (!f || !f->IsOpen()) {\n");
1168 fprintf(fp," f = new TFile(\"%s\");\n",treefile.Data());
1169 fprintf(fp," }\n");
1170 if (fTree->GetDirectory() != fTree->GetCurrentFile()) {
1171 fprintf(fp," TDirectory * dir = (TDirectory*)f->Get(\"%s\");\n",fTree->GetDirectory()->GetPath());
1172 fprintf(fp," dir->GetObject(\"%s\",tree);\n\n",fTree->GetName());
1173 } else {
1174 fprintf(fp," f->GetObject(\"%s\",tree);\n\n",fTree->GetName());
1175 }
1176 }
1177 if (ischain) {
1178 fprintf(fp,"#else // SINGLE_TREE\n\n");
1179 fprintf(fp," // The following code should be used if you want this class to access a chain\n");
1180 fprintf(fp," // of trees.\n");
1181 fprintf(fp," TChain * chain = new TChain(\"%s\",\"%s\");\n",
1182 fTree->GetName(),fTree->GetTitle());
1183 {
1185 TIter next(((TChain*)fTree)->GetListOfFiles());
1186 TChainElement *element;
1187 while ((element = (TChainElement*)next())) {
1188 fprintf(fp," chain->Add(\"%s/%s\");\n",element->GetTitle(),element->GetName());
1189 }
1190 }
1191 fprintf(fp," tree = chain;\n");
1192 fprintf(fp,"#endif // SINGLE_TREE\n\n");
1193 }
1194 fprintf(fp," }\n");
1195 fprintf(fp," Init(tree);\n");
1196 fprintf(fp,"}\n");
1197 fprintf(fp,"\n");
1198 }
1199
1200// generate code for class destructor()
1201 if (!opt.Contains("selector")) {
1202 fprintf(fp,"%s::~%s()\n",classname,classname);
1203 fprintf(fp,"{\n");
1204 fprintf(fp," if (!fChain) return;\n");
1205 if (isHbook) {
1206 //fprintf(fp," delete fChain->GetCurrentFile();\n");
1207 } else {
1208 fprintf(fp," delete fChain->GetCurrentFile();\n");
1209 }
1210 fprintf(fp,"}\n");
1211 fprintf(fp,"\n");
1212 }
1213// generate code for class member function GetEntry()
1214 if (!opt.Contains("selector")) {
1215 fprintf(fp,"Int_t %s::GetEntry(Long64_t entry)\n",classname);
1216 fprintf(fp,"{\n");
1217 fprintf(fp,"// Read contents of entry.\n");
1218
1219 fprintf(fp," if (!fChain) return 0;\n");
1220 fprintf(fp," return fChain->GetEntry(entry);\n");
1221 fprintf(fp,"}\n");
1222 }
1223// generate code for class member function LoadTree()
1224 if (!opt.Contains("selector")) {
1225 fprintf(fp,"Long64_t %s::LoadTree(Long64_t entry)\n",classname);
1226 fprintf(fp,"{\n");
1227 fprintf(fp,"// Set the environment to read one entry\n");
1228 fprintf(fp," if (!fChain) return -5;\n");
1229 fprintf(fp," Long64_t centry = fChain->LoadTree(entry);\n");
1230 fprintf(fp," if (centry < 0) return centry;\n");
1231 fprintf(fp," if (fChain->GetTreeNumber() != fCurrent) {\n");
1232 fprintf(fp," fCurrent = fChain->GetTreeNumber();\n");
1233 fprintf(fp," Notify();\n");
1234 fprintf(fp," }\n");
1235 fprintf(fp," return centry;\n");
1236 fprintf(fp,"}\n");
1237 fprintf(fp,"\n");
1238 }
1239
1240// generate code for class member function Init(), first pass = get branch pointer
1241 fprintf(fp,"void %s::Init(TTree *tree)\n",classname);
1242 fprintf(fp,"{\n");
1243 fprintf(fp," // The Init() function is called when the selector needs to initialize\n"
1244 " // a new tree or chain. Typically here the branch addresses and branch\n"
1245 " // pointers of the tree will be set.\n"
1246 " // It is normally not necessary to make changes to the generated\n"
1247 " // code, but the routine can be extended by the user if needed.\n"
1248 " // Init() will be called many times when running on PROOF\n"
1249 " // (once per file to be processed).\n\n");
1250 if (mustInit.Last()) {
1251 TIter next(&mustInit);
1252 TObject *obj;
1253 fprintf(fp," // Set object pointer\n");
1254 while( (obj = next()) ) {
1255 if (obj->InheritsFrom(TBranch::Class())) {
1256 strlcpy(branchname,((TBranch*)obj)->GetName(),sizeof(branchname));
1257 } else if (obj->InheritsFrom(TLeaf::Class())) {
1258 strlcpy(branchname,((TLeaf*)obj)->GetName(),sizeof(branchname));
1259 }
1260 branchname[1023]=0;
1261 bname = branchname;
1262 while (*bname) {
1263 if (*bname == '.') *bname='_';
1264 if (*bname == ',') *bname='_';
1265 if (*bname == ':') *bname='_';
1266 if (*bname == '<') *bname='_';
1267 if (*bname == '>') *bname='_';
1268 bname++;
1269 }
1270 fprintf(fp," %s = 0;\n",branchname );
1271 }
1272 }
1273 if (mustInitArr.Last()) {
1274 TIter next(&mustInitArr);
1275 TNamed *info;
1276 fprintf(fp," // Set array pointer\n");
1277 while( (info = (TNamed*)next()) ) {
1278 fprintf(fp," for(int i=0; i<%s; ++i) %s[i] = 0;\n",info->GetTitle(),info->GetName());
1279 }
1280 fprintf(fp,"\n");
1281 }
1282 fprintf(fp," // Set branch addresses and branch pointers\n");
1283 fprintf(fp," if (!tree) return;\n");
1284 fprintf(fp," fChain = tree;\n");
1285 if (!opt.Contains("selector")) fprintf(fp," fCurrent = -1;\n");
1286 fprintf(fp," fChain->SetMakeClass(1);\n");
1287 fprintf(fp,"\n");
1288 for (l=0;l<nleaves;l++) {
1289 if (leafStatus[l]) continue;
1290 TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(l);
1291 len = leaf->GetLen();
1292 leafcount =leaf->GetLeafCount();
1293 TBranch *branch = leaf->GetBranch();
1294 strlcpy(aprefix,branch->GetName(),sizeof(aprefix));
1295
1296 if ( branch->GetNleaves() > 1) {
1297 // More than one leaf for the branch we need to distinguish them
1298 strlcpy(branchname,branch->GetName(),sizeof(branchname));
1299 strlcat(branchname,".",sizeof(branchname));
1300 strlcat(branchname,leaf->GetTitle(),sizeof(branchname));
1301 if (leafcount) {
1302 // remove any dimension in title
1303 char *dim = (char*)strstr(branchname,"["); if (dim) dim[0] = 0;
1304 }
1305 } else {
1306 strlcpy(branchname,branch->GetName(),sizeof(branchname));
1307 if (branch->IsA() == TBranchElement::Class()) {
1308 bre = (TBranchElement*)branch;
1309 if (bre->GetType() == 3 || bre->GetType()==4) strlcat(branchname,"_",sizeof(branchname));
1310 }
1311 }
1312 bname = branchname;
1313 char *brak = strstr(branchname,"["); if (brak) *brak = 0;
1314 char *twodim = (char*)strstr(bname,"["); if (twodim) *twodim = 0;
1315 while (*bname) {
1316 if (*bname == '.') *bname='_';
1317 if (*bname == ',') *bname='_';
1318 if (*bname == ':') *bname='_';
1319 if (*bname == '<') *bname='_';
1320 if (*bname == '>') *bname='_';
1321 bname++;
1322 }
1323 const char *maybedisable = "";
1324 if (branch != fTree->GetBranch(branch->GetName())) {
1325 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());
1326 maybedisable = "// ";
1327 }
1328 if (branch->IsA() == TBranchObject::Class()) {
1329 if (branch->GetListOfBranches()->GetEntriesFast()) {
1330 fprintf(fp,"%s fChain->SetBranchAddress(\"%s\",(void*)-1,&b_%s);\n",maybedisable,branch->GetName(),R__GetBranchPointerName(leaf).Data());
1331 continue;
1332 }
1333 strlcpy(branchname,branch->GetName(),sizeof(branchname));
1334 }
1335 if (branch->IsA() == TBranchElement::Class()) {
1336 if (((TBranchElement*)branch)->GetType() == 3) len =1;
1337 if (((TBranchElement*)branch)->GetType() == 4) len =1;
1338 }
1339 if (leafcount) len = leafcount->GetMaximum()+1;
1340 if (len > 1) fprintf(fp,"%s fChain->SetBranchAddress(\"%s\", %s, &b_%s);\n",
1341 maybedisable,branch->GetName(), branchname, R__GetBranchPointerName(leaf).Data());
1342 else fprintf(fp,"%s fChain->SetBranchAddress(\"%s\", &%s, &b_%s);\n",
1343 maybedisable,branch->GetName(), branchname, R__GetBranchPointerName(leaf).Data());
1344 }
1345 //must call Notify in case of MakeClass
1346 if (!opt.Contains("selector")) {
1347 fprintf(fp," Notify();\n");
1348 }
1349
1350 fprintf(fp,"}\n");
1351 fprintf(fp,"\n");
1352
1353// generate code for class member function Notify()
1354 fprintf(fp,"bool %s::Notify()\n",classname);
1355 fprintf(fp,"{\n");
1356 fprintf(fp," // The Notify() function is called when a new file is opened. This\n"
1357 " // can be either for a new TTree in a TChain or when when a new TTree\n"
1358 " // is started when using PROOF. It is normally not necessary to make changes\n"
1359 " // to the generated code, but the routine can be extended by the\n"
1360 " // user if needed. The return value is currently not used.\n\n");
1361 fprintf(fp," return true;\n");
1362 fprintf(fp,"}\n");
1363 fprintf(fp,"\n");
1364
1365// generate code for class member function Show()
1366 if (!opt.Contains("selector")) {
1367 fprintf(fp,"void %s::Show(Long64_t entry)\n",classname);
1368 fprintf(fp,"{\n");
1369 fprintf(fp,"// Print contents of entry.\n");
1370 fprintf(fp,"// If entry is not specified, print current entry\n");
1371
1372 fprintf(fp," if (!fChain) return;\n");
1373 fprintf(fp," fChain->Show(entry);\n");
1374 fprintf(fp,"}\n");
1375 }
1376// generate code for class member function Cut()
1377 if (!opt.Contains("selector")) {
1378 fprintf(fp,"Int_t %s::Cut(Long64_t entry)\n",classname);
1379 fprintf(fp,"{\n");
1380 fprintf(fp,"// This function may be called from Loop.\n");
1381 fprintf(fp,"// returns 1 if entry is accepted.\n");
1382 fprintf(fp,"// returns -1 otherwise.\n");
1383
1384 fprintf(fp," return 1;\n");
1385 fprintf(fp,"}\n");
1386 }
1387 fprintf(fp,"#endif // #ifdef %s_cxx\n",classname);
1388
1389//======================Generate classname.C=====================
1390 if (!opt.Contains("selector")) {
1391 // generate code for class member function Loop()
1392 fprintf(fpc,"#define %s_cxx\n",classname);
1393 fprintf(fpc,"#include \"%s\"\n",thead.Data());
1394 fprintf(fpc,"#include <TH2.h>\n");
1395 fprintf(fpc,"#include <TStyle.h>\n");
1396 fprintf(fpc,"#include <TCanvas.h>\n");
1397 fprintf(fpc,"\n");
1398 fprintf(fpc,"void %s::Loop()\n",classname);
1399 fprintf(fpc,"{\n");
1400 fprintf(fpc,"// In a ROOT session, you can do:\n");
1401 fprintf(fpc,"// root> .L %s.C\n",classname);
1402 fprintf(fpc,"// root> %s t\n",classname);
1403 fprintf(fpc,"// root> t.GetEntry(12); // Fill t data members with entry number 12\n");
1404 fprintf(fpc,"// root> t.Show(); // Show values of entry 12\n");
1405 fprintf(fpc,"// root> t.Show(16); // Read and show values of entry 16\n");
1406 fprintf(fpc,"// root> t.Loop(); // Loop on all entries\n");
1407 fprintf(fpc,"//\n");
1408 fprintf(fpc,"\n// This is the loop skeleton where:\n");
1409 fprintf(fpc,"// jentry is the global entry number in the chain\n");
1410 fprintf(fpc,"// ientry is the entry number in the current Tree\n");
1411 fprintf(fpc,"// Note that the argument to GetEntry must be:\n");
1412 fprintf(fpc,"// jentry for TChain::GetEntry\n");
1413 fprintf(fpc,"// ientry for TTree::GetEntry and TBranch::GetEntry\n");
1414 fprintf(fpc,"//\n");
1415 fprintf(fpc,"// To read only selected branches, Insert statements like:\n");
1416 fprintf(fpc,"// METHOD1:\n");
1417 fprintf(fpc,"// fChain->SetBranchStatus(\"*\",0); // disable all branches\n");
1418 fprintf(fpc,"// fChain->SetBranchStatus(\"branchname\",1); // activate branchname\n");
1419 fprintf(fpc,"// METHOD2: replace line\n");
1420 fprintf(fpc,"// fChain->GetEntry(jentry); //read all branches\n");
1421 fprintf(fpc,"//by b_branchname->GetEntry(ientry); //read only this branch\n");
1422 fprintf(fpc," if (fChain == 0) return;\n");
1423 fprintf(fpc,"\n Long64_t nentries = fChain->GetEntriesFast();\n");
1424 fprintf(fpc,"\n Long64_t nbytes = 0, nb = 0;\n");
1425 fprintf(fpc," for (Long64_t jentry=0; jentry<nentries;jentry++) {\n");
1426 fprintf(fpc," Long64_t ientry = LoadTree(jentry);\n");
1427 fprintf(fpc," if (ientry < 0) break;\n");
1428 fprintf(fpc," nb = fChain->GetEntry(jentry); nbytes += nb;\n");
1429 fprintf(fpc," // if (Cut(ientry) < 0) continue;\n");
1430 fprintf(fpc," }\n");
1431 fprintf(fpc,"}\n");
1432 }
1433 if (opt.Contains("selector")) {
1434 // generate usage comments and list of includes
1435 fprintf(fpc,"#define %s_cxx\n",classname);
1436 fprintf(fpc,"// The class definition in %s.h has been generated automatically\n",classname);
1437 fprintf(fpc,"// by the ROOT utility TTree::MakeSelector(). This class is derived\n");
1438 fprintf(fpc,"// from the ROOT class TSelector. For more information on the TSelector\n"
1439 "// framework see $ROOTSYS/README/README.SELECTOR or the ROOT User Manual.\n\n");
1440 fprintf(fpc,"// The following methods are defined in this file:\n");
1441 fprintf(fpc,"// Begin(): called every time a loop on the tree starts,\n");
1442 fprintf(fpc,"// a convenient place to create your histograms.\n");
1443 fprintf(fpc,"// SlaveBegin(): called after Begin(), when on PROOF called only on the\n"
1444 "// slave servers.\n");
1445 fprintf(fpc,"// Process(): called for each event, in this function you decide what\n");
1446 fprintf(fpc,"// to read and fill your histograms.\n");
1447 fprintf(fpc,"// SlaveTerminate: called at the end of the loop on the tree, when on PROOF\n"
1448 "// called only on the slave servers.\n");
1449 fprintf(fpc,"// Terminate(): called at the end of the loop on the tree,\n");
1450 fprintf(fpc,"// a convenient place to draw/fit your histograms.\n");
1451 fprintf(fpc,"//\n");
1452 fprintf(fpc,"// To use this file, try the following session on your Tree T:\n");
1453 fprintf(fpc,"//\n");
1454 fprintf(fpc,"// root> T->Process(\"%s.C\")\n",classname);
1455 fprintf(fpc,"// root> T->Process(\"%s.C\",\"some options\")\n",classname);
1456 fprintf(fpc,"// root> T->Process(\"%s.C+\")\n",classname);
1457 fprintf(fpc,"//\n\n");
1458 fprintf(fpc,"#include \"%s\"\n",thead.Data());
1459 fprintf(fpc,"#include <TH2.h>\n");
1460 fprintf(fpc,"#include <TStyle.h>\n");
1461 fprintf(fpc,"\n");
1462 // generate code for class member function Begin
1463 fprintf(fpc,"\n");
1464 fprintf(fpc,"void %s::Begin(TTree * /*tree*/)\n",classname);
1465 fprintf(fpc,"{\n");
1466 fprintf(fpc," // The Begin() function is called at the start of the query.\n");
1467 fprintf(fpc," // When running with PROOF Begin() is only called on the client.\n");
1468 fprintf(fpc," // The tree argument is deprecated (on PROOF 0 is passed).\n");
1469 fprintf(fpc,"\n");
1470 fprintf(fpc," TString option = GetOption();\n");
1471 fprintf(fpc,"\n");
1472 fprintf(fpc,"}\n");
1473 // generate code for class member function SlaveBegin
1474 fprintf(fpc,"\n");
1475 fprintf(fpc,"void %s::SlaveBegin(TTree * /*tree*/)\n",classname);
1476 fprintf(fpc,"{\n");
1477 fprintf(fpc," // The SlaveBegin() function is called after the Begin() function.\n");
1478 fprintf(fpc," // When running with PROOF SlaveBegin() is called on each slave server.\n");
1479 fprintf(fpc," // The tree argument is deprecated (on PROOF 0 is passed).\n");
1480 fprintf(fpc,"\n");
1481 fprintf(fpc," TString option = GetOption();\n");
1482 fprintf(fpc,"\n");
1483 fprintf(fpc,"}\n");
1484 // generate code for class member function Process
1485 fprintf(fpc,"\n");
1486 fprintf(fpc,"bool %s::Process(Long64_t entry)\n",classname);
1487 fprintf(fpc,"{\n");
1488 fprintf(fpc," // The Process() function is called for each entry in the tree (or possibly\n"
1489 " // keyed object in the case of PROOF) to be processed. The entry argument\n"
1490 " // specifies which entry in the currently loaded tree is to be processed.\n"
1491 " // It can be passed to either %s::GetEntry() or TBranch::GetEntry()\n"
1492 " // to read either all or the required parts of the data. When processing\n"
1493 " // keyed objects with PROOF, the object is already loaded and is available\n"
1494 " // via the fObject pointer.\n"
1495 " //\n"
1496 " // This function should contain the \"body\" of the analysis. It can contain\n"
1497 " // simple or elaborate selection criteria, run algorithms on the data\n"
1498 " // of the event and typically fill histograms.\n"
1499 " //\n"
1500 " // The processing can be stopped by calling Abort().\n"
1501 " //\n"
1502 " // Use fStatus to set the return value of TTree::Process().\n"
1503 " //\n"
1504 " // The return value is currently not used.\n\n", classname);
1505 fprintf(fpc,"\n");
1506 fprintf(fpc," return true;\n");
1507 fprintf(fpc,"}\n");
1508 // generate code for class member function SlaveTerminate
1509 fprintf(fpc,"\n");
1510 fprintf(fpc,"void %s::SlaveTerminate()\n",classname);
1511 fprintf(fpc,"{\n");
1512 fprintf(fpc," // The SlaveTerminate() function is called after all entries or objects\n"
1513 " // have been processed. When running with PROOF SlaveTerminate() is called\n"
1514 " // on each slave server.");
1515 fprintf(fpc,"\n");
1516 fprintf(fpc,"\n");
1517 fprintf(fpc,"}\n");
1518 // generate code for class member function Terminate
1519 fprintf(fpc,"\n");
1520 fprintf(fpc,"void %s::Terminate()\n",classname);
1521 fprintf(fpc,"{\n");
1522 fprintf(fpc," // The Terminate() function is the last function to be called during\n"
1523 " // a query. It always runs on the client, it can be used to present\n"
1524 " // the results graphically or save the results to file.");
1525 fprintf(fpc,"\n");
1526 fprintf(fpc,"\n");
1527 fprintf(fpc,"}\n");
1528 }
1529 Info("MakeClass","Files: %s and %s generated from TTree: %s",thead.Data(),tcimp.Data(),fTree->GetName());
1530 delete [] leafStatus;
1531 fclose(fp);
1532 fclose(fpc);
1533
1534 return 0;
1535}
1536
1537
1538////////////////////////////////////////////////////////////////////////////////
1539/// Generate skeleton function for this Tree
1540///
1541/// The function code is written on filename.
1542/// If filename is 0, filename will be called nameoftree.C
1543///
1544/// The generated code includes the following:
1545/// - Identification of the original Tree and Input file name
1546/// - Connection of the Tree file
1547/// - Declaration of Tree variables
1548/// - Setting of branches addresses
1549/// - A skeleton for the entry loop
1550///
1551/// To use this function:
1552/// - connect your Tree file (eg: TFile f("myfile.root");)
1553/// - T->MakeCode("anal.C");
1554/// where T is the name of the Tree in file myfile.root
1555/// and anal.C the name of the file created by this function.
1556///
1557/// NOTE: Since the implementation of this function, a new and better
1558/// function TTree::MakeClass() has been developed.
1559
1561{
1562// Connect output file
1563 TString tfile;
1564 if (filename)
1565 tfile = filename;
1566 else
1567 tfile.Form("%s.C", fTree->GetName());
1568 FILE *fp = fopen(tfile, "w");
1569 if (!fp) {
1570 Error("MakeCode","cannot open output file %s", tfile.Data());
1571 return 3;
1572 }
1573 TString treefile;
1574 if (fTree->GetDirectory() && fTree->GetDirectory()->GetFile()) {
1575 treefile = fTree->GetDirectory()->GetFile()->GetName();
1576 } else {
1577 treefile = "Memory Directory";
1578 }
1579 // In the case of a chain, the GetDirectory information usually does
1580 // pertain to the Chain itself but to the currently loaded tree.
1581 // So we can not rely on it.
1582 bool ischain = fTree->InheritsFrom(TChain::Class());
1583
1584// Print header
1585 TObjArray *leaves = fTree->GetListOfLeaves();
1586 Int_t nleaves = leaves ? leaves->GetEntriesFast() : 0;
1587 TDatime td;
1588 fprintf(fp,"{\n");
1589 fprintf(fp,"//////////////////////////////////////////////////////////\n");
1590 fprintf(fp,"// This file has been automatically generated \n");
1591 fprintf(fp,"// (%s by ROOT version%s)\n",td.AsString(),gROOT->GetVersion());
1592 if (!ischain) {
1593 fprintf(fp,"// from TTree %s/%s\n",fTree->GetName(),fTree->GetTitle());
1594 fprintf(fp,"// found on file: %s\n",treefile.Data());
1595 } else {
1596 fprintf(fp,"// from TChain %s/%s\n",fTree->GetName(),fTree->GetTitle());
1597 }
1598 fprintf(fp,"//////////////////////////////////////////////////////////\n");
1599 fprintf(fp,"\n");
1600 fprintf(fp,"\n");
1601
1602
1603// Reset and file connect
1604 fprintf(fp,"//Reset ROOT and connect tree file\n");
1605 fprintf(fp," gROOT->Reset();\n");
1606 if (ischain) {
1607 fprintf(fp,"\n#ifdef SINGLE_TREE\n");
1608 fprintf(fp," // The following code should be used if you want this code to access\n");
1609 fprintf(fp," // a single tree instead of a chain\n");
1610 }
1611 fprintf(fp," TFile *f = (TFile*)gROOT->GetListOfFiles()->FindObject(\"%s\");\n",treefile.Data());
1612 fprintf(fp," if (!f) {\n");
1613 fprintf(fp," f = new TFile(\"%s\");\n",treefile.Data());
1614 fprintf(fp," }\n");
1615 if (fTree->GetDirectory() != fTree->GetCurrentFile()) {
1616 fprintf(fp," TDirectory * dir = (TDirectory*)f->Get(\"%s\");\n",fTree->GetDirectory()->GetPath());
1617 fprintf(fp," dir->GetObject(\"%s\",tree);\n\n",fTree->GetName());
1618 } else {
1619 fprintf(fp," f->GetObject(\"%s\",tree);\n\n",fTree->GetName());
1620 }
1621 if (ischain) {
1622 fprintf(fp,"#else // SINGLE_TREE\n\n");
1623 fprintf(fp," // The following code should be used if you want this code to access a chain\n");
1624 fprintf(fp," // of trees.\n");
1625 fprintf(fp," TChain *%s = new TChain(\"%s\",\"%s\");\n",
1627 {
1629 TIter next(((TChain*)fTree)->GetListOfFiles());
1630 TChainElement *element;
1631 while ((element = (TChainElement*)next())) {
1632 fprintf(fp," %s->Add(\"%s/%s\");\n",fTree->GetName(),element->GetTitle(),element->GetName());
1633 }
1634 }
1635 fprintf(fp,"#endif // SINGLE_TREE\n\n");
1636 }
1637
1638// First loop on all leaves to generate type declarations
1639 fprintf(fp,"//Declaration of leaves types\n");
1640 Int_t len, l;
1641 TLeaf *leafcount;
1642 TLeafObject *leafobj;
1643 char *bname;
1644 const char *headOK = " ";
1645 const char *headcom = " //";
1646 const char *head;
1647 char branchname[1024];
1648 for (l=0;l<nleaves;l++) {
1649 TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(l);
1650 len = leaf->GetLen();
1651 leafcount =leaf->GetLeafCount();
1652 TBranch *branch = leaf->GetBranch();
1653 if (branch->GetListOfBranches()->GetEntriesFast() > 0) continue;
1654
1655 if ( branch->GetNleaves() > 1) {
1656 // More than one leaf for the branch we need to distinguish them
1657 strlcpy(branchname,branch->GetName(),sizeof(branchname));
1658 strlcat(branchname,".",sizeof(branchname));
1659 strlcat(branchname,leaf->GetTitle(),sizeof(branchname));
1660 if (leafcount) {
1661 // remove any dimension in title
1662 char *dim = (char*)strstr(branchname,"[");
1663 if (dim) dim[0] = 0;
1664 }
1665 } else {
1666 if (leafcount) strlcpy(branchname,branch->GetName(),sizeof(branchname));
1667 else strlcpy(branchname,leaf->GetTitle(),sizeof(branchname));
1668 }
1669 char *twodim = (char*)strstr(leaf->GetTitle(),"][");
1670 bname = branchname;
1671 while (*bname) {
1672 if (*bname == '.') *bname='_';
1673 if (*bname == ',') *bname='_';
1674 if (*bname == ':') *bname='_';
1675 if (*bname == '<') *bname='_';
1676 if (*bname == '>') *bname='_';
1677 bname++;
1678 }
1679 if (branch->IsA() == TBranchObject::Class()) {
1680 leafobj = (TLeafObject*)leaf;
1681 if (leafobj->GetClass()) head = headOK;
1682 else head = headcom;
1683 fprintf(fp,"%s%-15s *%s = 0;\n",head,leafobj->GetTypeName(), leafobj->GetName());
1684 continue;
1685 }
1686 if (leafcount) {
1687 len = leafcount->GetMaximum();
1688 // Dimensions can be in the branchname for a split Object with a fix length C array.
1689 // Theses dimensions HAVE TO be placed after the dimension explicited by leafcount
1690 char *dimInName = (char*) strstr(branchname,"[");
1691 TString dimensions;
1692 if ( twodim || dimInName ) {
1693 if (dimInName) {
1694 dimensions = dimInName;
1695 dimInName[0] = 0; // terminate branchname before the array dimensions.
1696 }
1697 if (twodim) dimensions += (char*)(twodim+1);
1698 }
1699 if (dimensions.Length()) {
1700 fprintf(fp," %-15s %s[%d]%s;\n",leaf->GetTypeName(), branchname,len,dimensions.Data());
1701 } else {
1702 fprintf(fp," %-15s %s[%d];\n",leaf->GetTypeName(), branchname,len);
1703 }
1704 } else {
1705 if (strstr(branchname,"[")) len = 1;
1706 if (len < 2) fprintf(fp," %-15s %s;\n",leaf->GetTypeName(), branchname);
1707 else fprintf(fp," %-15s %s[%d];\n",leaf->GetTypeName(), branchname,len);
1708 }
1709 }
1710
1711// Second loop on all leaves to set the corresponding branch address
1712 fprintf(fp,"\n // Set branch addresses.\n");
1713 for (l=0;l<nleaves;l++) {
1714 TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(l);
1715 len = leaf->GetLen();
1716 leafcount =leaf->GetLeafCount();
1717 TBranch *branch = leaf->GetBranch();
1718
1719 if ( branch->GetNleaves() > 1) {
1720 // More than one leaf for the branch we need to distinguish them
1721 strlcpy(branchname,branch->GetName(),sizeof(branchname));
1722 strlcat(branchname,".",sizeof(branchname));
1723 strlcat(branchname,leaf->GetTitle(),sizeof(branchname));
1724 if (leafcount) {
1725 // remove any dimension in title
1726 char *dim = (char*)strstr(branchname,"[");
1727 if (dim) dim[0] = 0;
1728 }
1729 } else {
1730 if (leafcount) strlcpy(branchname,branch->GetName(),sizeof(branchname));
1731 else strlcpy(branchname,leaf->GetTitle(),sizeof(branchname));
1732 }
1733 bname = branchname;
1734 while (*bname) {
1735 if (*bname == '.') *bname='_';
1736 if (*bname == ',') *bname='_';
1737 if (*bname == ':') *bname='_';
1738 if (*bname == '<') *bname='_';
1739 if (*bname == '>') *bname='_';
1740 bname++;
1741 }
1742 char *brak = strstr(branchname,"[");
1743 if (brak) *brak = 0;
1744 head = headOK;
1745 if (branch->IsA() == TBranchObject::Class()) {
1746 strlcpy(branchname,branch->GetName(),sizeof(branchname));
1747 leafobj = (TLeafObject*)leaf;
1748 if (!leafobj->GetClass()) head = headcom;
1749 }
1750 if (leafcount) len = leafcount->GetMaximum()+1;
1751 if (len > 1 || brak) fprintf(fp,"%s%s->SetBranchAddress(\"%s\",%s);\n",head,fTree->GetName(),branch->GetName(),branchname);
1752 else fprintf(fp,"%s%s->SetBranchAddress(\"%s\",&%s);\n",head,fTree->GetName(),branch->GetName(),branchname);
1753 }
1754
1755//Generate instructions to make the loop on entries
1756 fprintf(fp,"\n// This is the loop skeleton\n");
1757 fprintf(fp,"// To read only selected branches, Insert statements like:\n");
1758 fprintf(fp,"// %s->SetBranchStatus(\"*\",0); // disable all branches\n",fTree->GetName());
1759 fprintf(fp,"// %s->SetBranchStatus(\"branchname\",1); // activate branchname\n",GetName());
1760 fprintf(fp,"\n Long64_t nentries = %s->GetEntries();\n",fTree->GetName());
1761 fprintf(fp,"\n Long64_t nbytes = 0;\n");
1762 fprintf(fp,"// for (Long64_t i=0; i<nentries;i++) {\n");
1763 fprintf(fp,"// nbytes += %s->GetEntry(i);\n",fTree->GetName());
1764 fprintf(fp,"// }\n");
1765 fprintf(fp,"}\n");
1766
1767 printf("Macro: %s generated from Tree: %s\n",tfile.Data(), fTree->GetName());
1768 fclose(fp);
1769
1770 return 0;
1771}
1772
1773////////////////////////////////////////////////////////////////////////////////
1774/// Generate a skeleton analysis class for this Tree using TBranchProxy.
1775/// TBranchProxy is the base of a class hierarchy implementing an
1776/// indirect access to the content of the branches of a TTree.
1777///
1778/// "proxyClassname" is expected to be of the form:
1779/// ~~~{.cpp}
1780/// [path/]fileprefix
1781/// ~~~
1782/// The skeleton will then be generated in the file:
1783/// ~~~{.cpp}
1784/// fileprefix.h
1785/// ~~~
1786/// located in the current directory or in 'path/' if it is specified.
1787/// The class generated will be named 'fileprefix'.
1788/// If the fileprefix contains a period, the right side of the period
1789/// will be used as the extension (instead of 'h') and the left side
1790/// will be used as the classname.
1791///
1792/// "macrofilename" and optionally "cutfilename" are expected to point
1793/// to source file which will be included in by the generated skeletong.
1794/// Method of the same name as the file(minus the extension and path)
1795/// will be called by the generated skeleton's Process method as follow:
1796/// ~~~{.cpp}
1797/// [if (cutfilename())] htemp->Fill(macrofilename());
1798/// ~~~
1799/// "option" can be used select some of the optional features during
1800/// the code generation. The possible options are:
1801/// - nohist : indicates that the generated ProcessFill should not
1802/// fill the histogram.
1803///
1804/// 'maxUnrolling' controls how deep in the class hierarchy does the
1805/// system 'unroll' class that are not split. 'unrolling' a class
1806/// will allow direct access to its data members a class (this
1807/// emulates the behavior of TTreeFormula).
1808///
1809/// The main features of this skeleton are:
1810///
1811/// * on-demand loading of branches
1812/// * ability to use the 'branchname' as if it was a data member
1813/// * protection against array out-of-bound
1814/// * ability to use the branch data as object (when the user code is available)
1815///
1816/// For example with Event.root, if
1817/// ~~~{.cpp}
1818/// Double_t somepx = fTracks.fPx[2];
1819/// ~~~
1820/// is executed by one of the method of the skeleton,
1821/// somepx will be updated with the current value of fPx of the 3rd track.
1822///
1823/// Both macrofilename and the optional cutfilename are expected to be
1824/// the name of source files which contain at least a free standing
1825/// function with the signature:
1826/// ~~~{.cpp}
1827/// x_t macrofilename(); // i.e function with the same name as the file
1828/// ~~~
1829/// and
1830/// ~~~{.cpp}
1831/// y_t cutfilename(); // i.e function with the same name as the file
1832/// ~~~
1833/// x_t and y_t needs to be types that can convert respectively to a double
1834/// and a bool (because the skeleton uses:
1835/// ~~~{.cpp}
1836/// if (cutfilename()) htemp->Fill(macrofilename());
1837/// ~~~
1838/// This 2 functions are run in a context such that the branch names are
1839/// available as local variables of the correct (read-only) type.
1840///
1841/// Note that if you use the same 'variable' twice, it is more efficient
1842/// to 'cache' the value. For example
1843/// ~~~{.cpp}
1844/// Int_t n = fEventNumber; // Read fEventNumber
1845/// if (n<10 || n>10) { ... }
1846/// ~~~
1847/// is more efficient than
1848/// ~~~{.cpp}
1849/// if (fEventNumber<10 || fEventNumber>10)
1850/// ~~~
1851/// Access to TClonesArray.
1852///
1853/// If a branch (or member) is a TClonesArray (let's say fTracks), you
1854/// can access the TClonesArray itself by using ->:
1855/// ~~~{.cpp}
1856/// fTracks->GetLast();
1857/// ~~~
1858/// However this will load the full TClonesArray object and its content.
1859/// To quickly read the size of the TClonesArray use (note the dot):
1860/// ~~~{.cpp}
1861/// fTracks.GetEntries();
1862/// ~~~
1863/// This will read only the size from disk if the TClonesArray has been
1864/// split.
1865/// To access the content of the TClonesArray, use the [] operator:
1866/// ~~~
1867/// float px = fTracks[i].fPx; // fPx of the i-th track
1868/// ~~~
1869/// Warning:
1870///
1871/// The variable actually use for access are 'wrapper' around the
1872/// real data type (to add autoload for example) and hence getting to
1873/// the data involves the implicit call to a C++ conversion operator.
1874/// This conversion is automatic in most case. However it is not invoked
1875/// in a few cases, in particular in variadic function (like printf).
1876/// So when using printf you should either explicitly cast the value or
1877/// use any intermediary variable:
1878/// ~~~{.cpp}
1879/// fprintf(stdout,"trs[%d].a = %d\n",i,(int)trs.a[i]);
1880/// ~~~
1881/// Also, optionally, the generated selector will also call methods named
1882/// macrofilename_methodname in each of 6 main selector methods if the method
1883/// macrofilename_methodname exist (Where macrofilename is stripped of its
1884/// extension).
1885///
1886/// Concretely, with the script named h1analysisProxy.C,
1887///
1888/// - The method calls the method (if it exist)
1889/// - Begin -> void h1analysisProxy_Begin(TTree*);
1890/// - SlaveBegin -> void h1analysisProxy_SlaveBegin(TTree*);
1891/// - Notify -> bool h1analysisProxy_Notify();
1892/// - Process -> bool h1analysisProxy_Process(Long64_t);
1893/// - SlaveTerminate -> void h1analysisProxy_SlaveTerminate();
1894/// - Terminate -> void h1analysisProxy_Terminate();
1895///
1896/// If a file name macrofilename.h (or .hh, .hpp, .hxx, .hPP, .hXX) exist
1897/// it is included before the declaration of the proxy class. This can
1898/// be used in particular to insure that the include files needed by
1899/// the macro file are properly loaded.
1900///
1901/// The default histogram is accessible via the variable named 'htemp'.
1902///
1903/// If the library of the classes describing the data in the branch is
1904/// loaded, the skeleton will add the needed `include` statements and
1905/// give the ability to access the object stored in the branches.
1906///
1907/// To draw px using the file `hsimple.root (generated by the
1908/// hsimple.C tutorial), we need a file named hsimple.cxx:
1909///
1910/// ~~~{.cpp}
1911/// double hsimple() {
1912/// return px;
1913/// }
1914/// ~~~
1915/// MakeProxy can then be used indirectly via the TTree::Draw interface
1916/// as follow:
1917/// ~~~{.cpp}
1918/// new TFile("hsimple.root")
1919/// ntuple->Draw("hsimple.cxx");
1920/// ~~~
1921/// A more complete example is available in the tutorials directory:
1922/// h1analysisProxy.cxx , h1analysProxy.h and h1analysisProxyCut.C
1923/// which reimplement the selector found in h1analysis.C
1924
1925Int_t TTreePlayer::MakeProxy(const char *proxyClassname,
1926 const char *macrofilename, const char *cutfilename,
1927 const char *option, Int_t maxUnrolling)
1928{
1929 if (macrofilename==nullptr || strlen(macrofilename)==0 ) {
1930 // We currently require a file name for the script
1931 Error("MakeProxy","A file name for the user script is required");
1932 return 0;
1933 }
1934
1935 ROOT::Internal::TTreeProxyGenerator gp(fTree,macrofilename,cutfilename,proxyClassname,option,maxUnrolling);
1936
1937 return 0;
1938}
1939
1940
1941////////////////////////////////////////////////////////////////////////////////
1942/// Generate skeleton selector class for this tree.
1943///
1944/// The following files are produced: classname.h and classname.C.
1945/// If classname is 0, the selector will be called "nameoftree".
1946/// The option can be used to specify the branches that will have a data member.
1947/// - If option is empty, readers will be generated for each leaf.
1948/// - If option is "@", readers will be generated for the topmost branches.
1949/// - Individual branches can also be picked by their name:
1950/// - "X" generates readers for leaves of X.
1951/// - "@X" generates a reader for X as a whole.
1952/// - "@X;Y" generates a reader for X as a whole and also readers for the
1953/// leaves of Y.
1954/// - For further examples see the figure below.
1955///
1956/// \image html ttree_makeselector_option_examples.png
1957///
1958/// The generated code in classname.h includes the following:
1959/// - Identification of the original Tree and Input file name
1960/// - Definition of selector class (data and functions)
1961/// - The following class functions:
1962/// - constructor and destructor
1963/// - void Begin(TTree *tree)
1964/// - void SlaveBegin(TTree *tree)
1965/// - void Init(TTree *tree)
1966/// - bool Notify()
1967/// - bool Process(Long64_t entry)
1968/// - void Terminate()
1969/// - void SlaveTerminate()
1970///
1971/// The selector derives from TSelector.
1972/// The generated code in classname.C includes empty functions defined above.
1973///
1974/// To use this function:
1975/// - connect your Tree file (eg: `TFile f("myfile.root");`)
1976/// - `T->MakeSelector("myselect");`
1977/// where `T` is the name of the Tree in file `myfile.root`
1978/// and `myselect.h`, `myselect.C` the name of the files created by this
1979/// function.
1980///
1981/// In a ROOT session, you can do:
1982/// ~~~ {.cpp}
1983/// root > T->Process("myselect.C")
1984/// ~~~
1986{
1987 if (!classname) classname = fTree->GetName();
1988
1990
1991 return 0;
1992}
1993
1994
1995////////////////////////////////////////////////////////////////////////////////
1996/// Interface to the Principal Components Analysis class.
1997///
1998/// Create an instance of TPrincipal
1999/// Fill it with the selected variables
2000///
2001/// - if option "n" is specified, the TPrincipal object is filled with
2002/// normalized variables.
2003/// - If option "p" is specified, compute the principal components
2004/// - If option "p" and "d" print results of analysis
2005/// - If option "p" and "h" generate standard histograms
2006/// - If option "p" and "c" generate code of conversion functions
2007///
2008/// return a pointer to the TPrincipal object. It is the user responsibility
2009/// to delete this object.
2010///
2011/// The option default value is "np"
2012///
2013/// See TTreePlayer::DrawSelect for explanation of the other parameters.
2014
2015TPrincipal *TTreePlayer::Principal(const char *varexp, const char *selection, Option_t *option, Long64_t nentries, Long64_t firstentry)
2016{
2017 TTreeFormula **var;
2018 std::vector<TString> cnames;
2019 TString opt = option;
2020 opt.ToLower();
2021 TPrincipal *principal = nullptr;
2022 Long64_t entry,entryNumber;
2023 Int_t i,nch;
2024 Int_t ncols = 8; // by default first 8 columns are printed only
2025 TObjArray *leaves = fTree->GetListOfLeaves();
2026 Int_t nleaves = leaves->GetEntriesFast();
2027 if (nleaves < ncols) ncols = nleaves;
2028 nch = varexp ? strlen(varexp) : 0;
2029
2030 nentries = GetEntriesToProcess(firstentry, nentries);
2031
2032//*-*- Compile selection expression if there is one
2033 TTreeFormula *select = nullptr;
2034 if (strlen(selection)) {
2035 select = new TTreeFormula("Selection",selection,fTree);
2036 if (!select) return principal;
2037 if (!select->GetNdim()) { delete select; return principal; }
2038 fFormulaList->Add(select);
2039 }
2040//*-*- if varexp is empty, take first 8 columns by default
2041 int allvar = 0;
2042 if (varexp && !strcmp(varexp, "*")) { ncols = nleaves; allvar = 1; }
2043 if (nch == 0 || allvar) {
2044 for (i=0;i<ncols;i++) {
2045 cnames.push_back( ((TLeaf*)leaves->At(i))->GetName() );
2046 }
2047//*-*- otherwise select only the specified columns
2048 } else {
2049 ncols = fSelector->SplitNames(varexp,cnames);
2050 }
2051 var = new TTreeFormula* [ncols];
2052 Double_t *xvars = new Double_t[ncols];
2053
2054//*-*- Create the TreeFormula objects corresponding to each column
2055 for (i=0;i<ncols;i++) {
2056 var[i] = new TTreeFormula("Var1",cnames[i].Data(),fTree);
2057 fFormulaList->Add(var[i]);
2058 }
2059
2060//*-*- Create a TreeFormulaManager to coordinate the formulas
2061 TTreeFormulaManager *manager=nullptr;
2062 if (fFormulaList->LastIndex()>=0) {
2063 manager = new TTreeFormulaManager;
2064 for(i=0;i<=fFormulaList->LastIndex();i++) {
2065 manager->Add((TTreeFormula*)fFormulaList->At(i));
2066 }
2067 manager->Sync();
2068 }
2069
2070//*-* Build the TPrincipal object
2071 if (opt.Contains("n")) principal = new TPrincipal(ncols, "n");
2072 else principal = new TPrincipal(ncols);
2073
2074//*-*- loop on all selected entries
2075 fSelectedRows = 0;
2076 Int_t tnumber = -1;
2077 for (entry=firstentry;entry<firstentry+nentries;entry++) {
2078 entryNumber = fTree->GetEntryNumber(entry);
2079 if (entryNumber < 0) break;
2080 Long64_t localEntry = fTree->LoadTree(entryNumber);
2081 if (localEntry < 0) break;
2082 if (tnumber != fTree->GetTreeNumber()) {
2083 tnumber = fTree->GetTreeNumber();
2084 if (manager) manager->UpdateFormulaLeaves();
2085 }
2086 int ndata = 1;
2087 if (manager && manager->GetMultiplicity()) {
2088 ndata = manager->GetNdata();
2089 }
2090
2091 for(int inst=0;inst<ndata;inst++) {
2092 bool loaded = false;
2093 if (select) {
2094 if (select->EvalInstance(inst) == 0) {
2095 continue;
2096 }
2097 }
2098
2099 if (inst==0) loaded = true;
2100 else if (!loaded) {
2101 // EvalInstance(0) always needs to be called so that
2102 // the proper branches are loaded.
2103 for (i=0;i<ncols;i++) {
2104 var[i]->EvalInstance(0);
2105 }
2106 loaded = true;
2107 }
2108
2109 for (i=0;i<ncols;i++) {
2110 xvars[i] = var[i]->EvalInstance(inst);
2111 }
2112 principal->AddRow(xvars);
2113 }
2114 }
2115
2116 //*-* some actions with principal ?
2117 if (opt.Contains("p")) {
2118 principal->MakePrincipals(); // Do the actual analysis
2119 if (opt.Contains("d")) principal->Print();
2120 if (opt.Contains("h")) principal->MakeHistograms();
2121 if (opt.Contains("c")) principal->MakeCode();
2122 }
2123
2124//*-*- delete temporary objects
2126 delete [] var;
2127 delete [] xvars;
2128
2129 return principal;
2130}
2131
2132////////////////////////////////////////////////////////////////////////////////
2133/// Process this tree executing the TSelector code in the specified filename.
2134/// The return value is -1 in case of error and TSelector::GetStatus() in
2135/// in case of success.
2136///
2137/// The code in filename is loaded (interpreted or compiled, see below),
2138/// filename must contain a valid class implementation derived from TSelector,
2139/// where TSelector has the following member functions:
2140///
2141/// - Begin(): called every time a loop on the tree starts,
2142/// a convenient place to create your histograms.
2143/// - SlaveBegin(): called after Begin(), when on PROOF called only on the
2144/// slave servers.
2145/// - Process(): called for each event, in this function you decide what
2146/// to read and fill your histograms.
2147/// - SlaveTerminate: called at the end of the loop on the tree, when on PROOF
2148/// called only on the slave servers.
2149/// - Terminate(): called at the end of the loop on the tree,
2150/// a convenient place to draw/fit your histograms.
2151///
2152/// If filename is of the form file.C, the file will be interpreted.
2153/// If filename is of the form file.C++, the file file.C will be compiled
2154/// and dynamically loaded.
2155///
2156/// If filename is of the form file.C+, the file file.C will be compiled
2157/// and dynamically loaded. At next call, if file.C is older than file.o
2158/// and file.so, the file.C is not compiled, only file.so is loaded.
2159///
2160/// ### NOTE 1
2161/// It may be more interesting to invoke directly the other Process function
2162/// accepting a TSelector* as argument.eg
2163/// ~~~{.cpp}
2164/// MySelector *selector = (MySelector*)TSelector::GetSelector(filename);
2165/// selector->CallSomeFunction(..);
2166/// mytree.Process(selector,..);
2167/// ~~~
2168/// ### NOTE 2
2169/// One should not call this function twice with the same selector file
2170/// in the same script. If this is required, proceed as indicated in NOTE1,
2171/// by getting a pointer to the corresponding TSelector,eg
2172///#### workaround 1
2173/// ~~~{.cpp}
2174///void stubs1() {
2175/// TSelector *selector = TSelector::GetSelector("h1test.C");
2176/// TFile *f1 = new TFile("stubs_nood_le1.root");
2177/// TTree *h1 = (TTree*)f1->Get("h1");
2178/// h1->Process(selector);
2179/// TFile *f2 = new TFile("stubs_nood_le1_coarse.root");
2180/// TTree *h2 = (TTree*)f2->Get("h1");
2181/// h2->Process(selector);
2182///}
2183/// ~~~
2184/// or use ACLIC to compile the selector
2185///#### workaround 2
2186/// ~~~{.cpp}
2187///void stubs2() {
2188/// TFile *f1 = new TFile("stubs_nood_le1.root");
2189/// TTree *h1 = (TTree*)f1->Get("h1");
2190/// h1->Process("h1test.C+");
2191/// TFile *f2 = new TFile("stubs_nood_le1_coarse.root");
2192/// TTree *h2 = (TTree*)f2->Get("h1");
2193/// h2->Process("h1test.C+");
2194///}
2195/// ~~~
2196
2198{
2199 DeleteSelectorFromFile(); //delete previous selector if any
2200
2201 // This might reloads the script and delete your option
2202 // string! so let copy it first:
2203 TString opt(option);
2204 TString file(filename);
2205 TSelector *selector = TSelector::GetSelector(file);
2206 if (!selector) return -1;
2207
2208 fSelectorFromFile = selector;
2209 fSelectorClass = selector->IsA();
2210
2211 Long64_t nsel = Process(selector,opt,nentries,firstentry);
2212 return nsel;
2213}
2214
2215////////////////////////////////////////////////////////////////////////////////
2216/// Process this tree executing the code in the specified selector.
2217/// The return value is -1 in case of error and TSelector::GetStatus() in
2218/// in case of success.
2219///
2220/// The TSelector class has the following member functions:
2221///
2222/// - Begin(): called every time a loop on the tree starts,
2223/// a convenient place to create your histograms.
2224/// - SlaveBegin(): called after Begin(), when on PROOF called only on the
2225/// slave servers.
2226/// - Process(): called for each event, in this function you decide what
2227/// to read and fill your histograms.
2228/// - SlaveTerminate: called at the end of the loop on the tree, when on PROOF
2229/// called only on the slave servers.
2230/// - Terminate(): called at the end of the loop on the tree,
2231/// a convenient place to draw/fit your histograms.
2232///
2233/// If the Tree (Chain) has an associated EventList, the loop is on the nentries
2234/// of the EventList, starting at firstentry, otherwise the loop is on the
2235/// specified Tree entries.
2236
2238{
2239 nentries = GetEntriesToProcess(firstentry, nentries);
2240
2242
2243 fTree->SetNotify(selector);
2244
2245 selector->SetOption(option);
2246
2247 selector->Begin(fTree); //<===call user initialization function
2248 selector->SlaveBegin(fTree); //<===call user initialization function
2249 if (selector->Version() >= 2)
2250 selector->Init(fTree);
2251 selector->Notify();
2252
2254 gMonitoringWriter->SendProcessingStatus("STARTED",true);
2255
2256 bool process = (selector->GetAbort() != TSelector::kAbortProcess &&
2257 (selector->Version() != 0 || selector->GetStatus() != -1)) ? true : false;
2258 if (process) {
2259
2260 Long64_t readbytesatstart = 0;
2261 readbytesatstart = TFile::GetFileBytesRead();
2262
2263 //set the file cache
2264 TTreeCache *tpf = nullptr;
2265 TFile *curfile = fTree->GetCurrentFile();
2266 if (curfile) {
2267 tpf = (TTreeCache*)curfile->GetCacheRead(fTree);
2268 if (tpf)
2269 tpf->SetEntryRange(firstentry,firstentry+nentries);
2270 else {
2271 // Create the TTreeCache with the default size unless the
2272 // user explicitly disabled it.
2273 fTree->EnableCache();
2274 tpf = (TTreeCache*)curfile->GetCacheRead(fTree);
2275 if (tpf) tpf->SetEntryRange(firstentry,firstentry+nentries);
2276 }
2277 }
2278
2279 //Create a timer to get control in the entry loop(s)
2280 TProcessEventTimer *timer = nullptr;
2281 Int_t interval = fTree->GetTimerInterval();
2282 if (!gROOT->IsBatch() && interval)
2283 timer = new TProcessEventTimer(interval);
2284
2285 //loop on entries (elist or all entries)
2286 Long64_t entry, entryNumber, localEntry;
2287
2288 bool useCutFill = selector->Version() == 0;
2289
2290 // force the first monitoring info
2293
2294 //trying to set the first tree, because in the Draw function
2295 //the tree corresponding to firstentry has already been loaded,
2296 //so it is not set in the entry list
2297 fSelectorUpdate = selector;
2299
2300 for (entry=firstentry;entry<firstentry+nentries;entry++) {
2301 entryNumber = fTree->GetEntryNumber(entry);
2302 if (entryNumber < 0) break;
2303 if (timer && timer->ProcessEvents()) break;
2304 if (gROOT->IsInterrupted()) break;
2305 localEntry = fTree->LoadTree(entryNumber);
2306 if (localEntry < 0) break;
2307 if(useCutFill) {
2308 if (selector->ProcessCut(localEntry))
2309 selector->ProcessFill(localEntry); //<==call user analysis function
2310 } else {
2311 selector->Process(localEntry); //<==call user analysis function
2312 }
2314 gMonitoringWriter->SendProcessingProgress((entry-firstentry),TFile::GetFileBytesRead()-readbytesatstart,true);
2315 if (selector->GetAbort() == TSelector::kAbortProcess) break;
2316 if (selector->GetAbort() == TSelector::kAbortFile) {
2317 // Skip to the next file.
2318 entry += fTree->GetTree()->GetEntries() - localEntry;
2319 // Reset the abort status.
2320 selector->ResetAbort();
2321 }
2322 }
2323 delete timer;
2324 //we must reset the cache
2325 {
2326 TFile *curfile2 = fTree->GetCurrentFile();
2327 if (curfile2 && fTree->GetCacheSize() > 0) {
2328 tpf = (TTreeCache*)curfile2->GetCacheRead(fTree);
2329 if (tpf) tpf->SetEntryRange(0,0);
2330 }
2331 }
2332 }
2333
2334 process = (selector->GetAbort() != TSelector::kAbortProcess &&
2335 (selector->Version() != 0 || selector->GetStatus() != -1)) ? true : false;
2336 Long64_t res = (process) ? 0 : -1;
2337 if (process) {
2338 selector->SlaveTerminate(); //<==call user termination function
2339 selector->Terminate(); //<==call user termination function
2340 res = selector->GetStatus();
2341 }
2342 fTree->SetNotify(nullptr); // Detach the selector from the tree.
2343 fSelectorUpdate = nullptr;
2346
2347 return res;
2348}
2349
2350////////////////////////////////////////////////////////////////////////////////
2351/// cleanup pointers in the player pointing to obj
2352
2354{
2355 if (fHistogram == obj) fHistogram = nullptr;
2356}
2357
2358////////////////////////////////////////////////////////////////////////////////
2359/// \brief Loop on Tree and print entries passing selection. Interactive
2360/// pagination break is on by default.
2361/// \param varexp If varexp is 0 (or "") then print only first 8 columns.
2362/// If varexp = "*" print all columns. Otherwise a columns selection can
2363/// be made using "var1:var2:var3".
2364/// \param selection a text formula selecting which entries to scan
2365/// \param firstentry first entry to scan
2366/// \param nentries total number of entries to scan (starting from firstentry). Defaults to all entries.
2367/// \return The function returns the number of entries passing the selection.
2368///
2369/// By default 50 lines are shown and you are asked for `<CR>` or `q`
2370/// to see the next 50 lines. Depending on the Tree structure, one entry might
2371/// be printed across several lines, distinguished by the `Instance` column.
2372/// You can change the default number of lines to be shown before `<CR>` or `q`
2373/// via mytree->SetScanField(maxlines) where maxlines is 50 by default.
2374/// If maxlines is set to 0 all entries of the Tree are shown, and you are
2375/// not prompted to press `<CR>` or `q` to end the loop.
2376///
2377/// This option is interesting when dumping the contents of a Tree to
2378/// an ascii file, eg from the command line.
2379/// ### with ROOT 5
2380/// ~~~{.cpp}
2381/// root [0] tree->SetScanField(0);
2382/// root [1] tree->Scan("*"); >tree.log
2383/// ~~~
2384/// ### with ROOT 6
2385/// ~~~{.cpp}
2386/// root [0] tree->SetScanField(0);
2387/// root [1] .> tree.log
2388/// tree->Scan("*");
2389/// .>
2390/// ~~~
2391/// will create a file tree.log
2392///
2393/// Arrays (within an entry) are printed in their linear forms.
2394/// If several arrays with multiple dimensions are printed together,
2395/// they will NOT be synchronized. For example print
2396/// arr1[4][2] and arr2[2][3] will results in a printing similar to:
2397/// ~~~{.cpp}
2398/// ***********************************************
2399/// * Row * Instance * arr1 * arr2 *
2400/// ***********************************************
2401/// * x * 0 * arr1[0][0]* arr2[0][0]*
2402/// * x * 1 * arr1[0][1]* arr2[0][1]*
2403/// * x * 2 * arr1[1][0]* arr2[0][2]*
2404/// * x * 3 * arr1[1][1]* arr2[1][0]*
2405/// * x * 4 * arr1[2][0]* arr2[1][1]*
2406/// * x * 5 * arr1[2][1]* arr2[1][2]*
2407/// * x * 6 * arr1[3][0]* *
2408/// * x * 7 * arr1[3][1]* *
2409/// ~~~
2410/// However, if there is a selection criterion which is an array, then
2411/// all the formulas will be synchronized with the selection criterion
2412/// (see TTreePlayer::DrawSelect for more information).
2413///
2414/// \param option The options string can contains the following parameters:
2415///
2416/// - lenmax=dd
2417/// Where 'dd' is the maximum number of elements per array that should
2418/// be printed. If 'dd' is 0, all elements are printed (this is the
2419/// default)
2420/// - colsize=ss
2421/// Where 'ss' will be used as the default size for all the column
2422/// If this options is not specified, the default column size is 9
2423/// - precision=pp
2424/// Where 'pp' will be used as the default 'precision' for the
2425/// printing format.
2426/// - col=xxx
2427/// Where 'xxx' is colon (:) delimited list of printing format for
2428/// each column. The format string should follow the printf format
2429/// specification. The value given will be prefixed by % and, if no
2430/// conversion specifier is given, will be suffixed by the letter g.
2431/// before being passed to fprintf. If no format is specified for a
2432/// column, the default is used (aka ${colsize}.${precision}g )
2433///
2434/// For example:
2435/// ~~~{.cpp}
2436/// tree->Scan("a:b:c","","colsize=30 precision=3 col=::20.10:#x:5ld");
2437/// ~~~
2438/// Will print 3 columns, the first 2 columns will be 30 characters long,
2439/// the third columns will be 20 characters long. The printing format used
2440/// for the columns (assuming they are numbers) will be respectively:
2441/// ~~~ {.cpp}
2442/// %30.3g %30.3g %20.10g %#x %5ld
2443/// ~~~
2444
2445Long64_t TTreePlayer::Scan(const char *varexp, const char *selection,
2446 Option_t * option,
2447 Long64_t nentries, Long64_t firstentry)
2448{
2449
2450 TString opt = option;
2451 opt.ToLower();
2452 UInt_t ui;
2453 UInt_t lenmax = 0;
2454 UInt_t colDefaultSize = 9;
2455 UInt_t colPrecision = 9;
2456 std::vector<TString> colFormats;
2457 std::vector<Int_t> colSizes;
2458
2459 if (opt.Contains("lenmax=")) {
2460 int start = opt.Index("lenmax=");
2461 int numpos = start + strlen("lenmax=");
2462 int numlen = 0;
2463 int len = opt.Length();
2464 while( (numpos+numlen<len) && isdigit(opt[numpos+numlen]) ) numlen++;
2465 TString num = opt(numpos,numlen);
2466 opt.Remove(start,strlen("lenmax")+numlen);
2467
2468 lenmax = atoi(num.Data());
2469 }
2470 if (opt.Contains("colsize=")) {
2471 int start = opt.Index("colsize=");
2472 int numpos = start + strlen("colsize=");
2473 int numlen = 0;
2474 int len = opt.Length();
2475 while( (numpos+numlen<len) && isdigit(opt[numpos+numlen]) ) numlen++;
2476 TString num = opt(numpos,numlen);
2477 opt.Remove(start,strlen("size")+numlen);
2478
2479 colDefaultSize = atoi(num.Data());
2480 colPrecision = colDefaultSize;
2481 if (colPrecision>18) colPrecision = 18;
2482 }
2483 if (opt.Contains("precision=")) {
2484 int start = opt.Index("precision=");
2485 int numpos = start + strlen("precision=");
2486 int numlen = 0;
2487 int len = opt.Length();
2488 while( (numpos+numlen<len) && isdigit(opt[numpos+numlen]) ) numlen++;
2489 TString num = opt(numpos,numlen);
2490 opt.Remove(start,strlen("precision")+numlen);
2491
2492 colPrecision = atoi(num.Data());
2493 }
2494 TString defFormat = Form("%d.%d",colDefaultSize,colPrecision);
2495 if (opt.Contains("col=")) {
2496 int start = opt.Index("col=");
2497 int numpos = start + strlen("col=");
2498 int numlen = 0;
2499 int len = opt.Length();
2500 while( (numpos+numlen<len) &&
2501 (isdigit(opt[numpos+numlen])
2502 || opt[numpos+numlen] == 'c'
2503 || opt[numpos+numlen] == 'd'
2504 || opt[numpos+numlen] == 'i'
2505 || opt[numpos+numlen] == 'o'
2506 || opt[numpos+numlen] == 'x'
2507 || opt[numpos+numlen] == 'X'
2508 || opt[numpos+numlen] == 'u'
2509 || opt[numpos+numlen] == 'f'
2510 || opt[numpos+numlen] == 'e'
2511 || opt[numpos+numlen] == 'E'
2512 || opt[numpos+numlen] == 'g'
2513 || opt[numpos+numlen] == 'G'
2514 || opt[numpos+numlen] == 'l'
2515 || opt[numpos+numlen] == 'L'
2516 || opt[numpos+numlen] == 'h'
2517 || opt[numpos+numlen] == 's'
2518 || opt[numpos+numlen] == '#'
2519 || opt[numpos+numlen]=='.'
2520 || opt[numpos+numlen]==':')) numlen++;
2521 TString flist = opt(numpos,numlen);
2522 opt.Remove(start,strlen("col")+numlen);
2523
2524 int i = 0;
2525 while(i<flist.Length() && flist[i]==':') {
2526 colFormats.push_back(defFormat);
2527 colSizes.push_back(colDefaultSize);
2528 ++i;
2529 }
2530 for(; i<flist.Length(); ++i) {
2531 int next = flist.Index(":",i);
2532 if (next==i) {
2533 colFormats.push_back(defFormat);
2534 } else if (next==kNPOS) {
2535 colFormats.push_back(flist(i,flist.Length()-i));
2536 i = flist.Length();
2537 } else {
2538 colFormats.push_back(flist(i,next-i));
2539 i = next;
2540 }
2541 UInt_t siz = atoi(colFormats[colFormats.size()-1].Data());
2542 colSizes.push_back( siz ? siz : colDefaultSize );
2543 }
2544 }
2545
2546 TTreeFormula **var;
2547 std::vector<TString> cnames;
2548 TString onerow;
2549 Long64_t entry,entryNumber;
2550 Int_t i,nch;
2551 UInt_t ncols = 8; // by default first 8 columns are printed only
2552 std::ofstream out;
2553 const char *fname = nullptr;
2554 TString fownname;
2555 if (fScanRedirect) {
2556 fTree->SetScanField(0); // no page break if Scan is redirected
2557 fname = fScanFileName;
2558 if (!fname) fname = "";
2559 Int_t lenfile = strlen(fname);
2560 if (!lenfile) {
2561 fownname = fTree->GetName();
2562 fownname.Append("-scan.dat");
2563 fname = fownname.Data();
2564 }
2565 out.open(fname, std::ios::out);
2566 if (!out.good ()) {
2567 Error("Scan","Can not open file for redirection");
2568 return 0;
2569 }
2570 }
2571 TObjArray *leaves = fTree->GetListOfLeaves();
2572 if (leaves==nullptr) return 0;
2573 UInt_t nleaves = leaves->GetEntriesFast();
2574 if (nleaves < ncols) ncols = nleaves;
2575 nch = varexp ? strlen(varexp) : 0;
2576
2577 nentries = GetEntriesToProcess(firstentry, nentries);
2578
2579//*-*- Compile selection expression if there is one
2580 TTreeFormula *select = nullptr;
2581 if (selection && strlen(selection)) {
2582 select = new TTreeFormula("Selection",selection,fTree);
2583 if (!select) return -1;
2584 if (!select->GetNdim()) { delete select; return -1; }
2585 fFormulaList->Add(select);
2586 }
2587//*-*- if varexp is empty, take first 8 columns by default
2588 int allvar = 0;
2589 if (varexp && !strcmp(varexp, "*")) { ncols = nleaves; allvar = 1; }
2590 if (nch == 0 || allvar) {
2591 UInt_t ncs = ncols;
2592 ncols = 0;
2593 for (ui=0;ui<ncs;++ui) {
2594 TLeaf *lf = (TLeaf*)leaves->At(ui);
2595 if (lf->GetBranch()->GetListOfBranches()->GetEntries() > 0) continue;
2596 cnames.push_back( lf->GetBranch()->GetMother()->GetName() );
2597 if (cnames[ncols] == lf->GetName() ) {
2598 // Already complete, let move on.
2599 } else if (cnames[ncols][cnames[ncols].Length()-1]=='.') {
2600 cnames[ncols] = lf->GetBranch()->GetName(); // name of branch already include mother's name
2601 } else {
2603 TBranchElement *mother = (TBranchElement*)lf->GetBranch()->GetMother();
2604 if (mother->GetType() == 3 || mother->GetType() == 4) {
2605 // The name of the mother branch is embedded in the sub-branch names.
2606 cnames[ncols] = lf->GetBranch()->GetName();
2607 ++ncols;
2608 continue;
2609 }
2610 }
2611 if (!strchr(lf->GetBranch()->GetName() ,'[') ) {
2612 cnames[ncols].Append('.');
2613 cnames[ncols].Append( lf->GetBranch()->GetName() );
2614 }
2615 }
2616 if (lf->GetBranch()->IsA() == TBranch::Class() ||
2617 strcmp( lf->GetBranch()->GetName(), lf->GetName() ) != 0 ) {
2618 cnames[ncols].Append('.');
2619 cnames[ncols].Append( lf->GetName() );
2620 }
2621 ++ncols;
2622 }
2623//*-*- otherwise select only the specified columns
2624 } else {
2625
2626 ncols = fSelector->SplitNames(varexp, cnames);
2627
2628 }
2629 var = new TTreeFormula* [ncols];
2630
2631 for(ui=colFormats.size();ui<ncols;++ui) {
2632 colFormats.push_back(defFormat);
2633 colSizes.push_back(colDefaultSize);
2634 }
2635
2636//*-*- Create the TreeFormula objects corresponding to each column
2637 for (ui=0;ui<ncols;ui++) {
2638 var[ui] = new TTreeFormula("Var1",cnames[ui].Data(),fTree);
2639 fFormulaList->Add(var[ui]);
2640 }
2641
2642//*-*- Create a TreeFormulaManager to coordinate the formulas
2643 TTreeFormulaManager *manager=nullptr;
2644 bool hasArray = false;
2645 bool forceDim = false;
2646 if (fFormulaList->LastIndex()>=0) {
2647 if (select) {
2648 if (select->GetManager()->GetMultiplicity() > 0 ) {
2649 manager = new TTreeFormulaManager;
2650 for(i=0;i<=fFormulaList->LastIndex();i++) {
2651 manager->Add((TTreeFormula*)fFormulaList->At(i));
2652 }
2653 manager->Sync();
2654 }
2655 }
2656 for(i=0;i<=fFormulaList->LastIndex();i++) {
2657 TTreeFormula *form = ((TTreeFormula*)fFormulaList->At(i));
2658 switch( form->GetManager()->GetMultiplicity() ) {
2659 case 1:
2660 case 2:
2661 hasArray = true;
2662 forceDim = true;
2663 break;
2664 case -1:
2665 forceDim = true;
2666 break;
2667 case 0:
2668 break;
2669 }
2670
2671 }
2672 }
2673
2674//*-*- Print header
2675 onerow = "***********";
2676 if (hasArray) onerow += "***********";
2677
2678 for (ui=0;ui<ncols;ui++) {
2679 TString starFormat = Form("*%%%d.%ds",colSizes[ui]+2,colSizes[ui]+2);
2680 onerow += Form(starFormat.Data(),var[ui]->PrintValue(-2));
2681 }
2682 if (fScanRedirect)
2683 out<<onerow.Data()<<"*"<<std::endl;
2684 else
2685 printf("%s*\n",onerow.Data());
2686 onerow = "* Row ";
2687 if (hasArray) onerow += "* Instance ";
2688 for (ui=0;ui<ncols;ui++) {
2689 TString numbFormat = Form("* %%%d.%ds ",colSizes[ui],colSizes[ui]);
2690 onerow += Form(numbFormat.Data(),var[ui]->PrintValue(-1));
2691 }
2692 if (fScanRedirect)
2693 out<<onerow.Data()<<"*"<<std::endl;
2694 else
2695 printf("%s*\n",onerow.Data());
2696 onerow = "***********";
2697 if (hasArray) onerow += "***********";
2698 for (ui=0;ui<ncols;ui++) {
2699 TString starFormat = Form("*%%%d.%ds",colSizes[ui]+2,colSizes[ui]+2);
2700 onerow += Form(starFormat.Data(),var[ui]->PrintValue(-2));
2701 }
2702 if (fScanRedirect)
2703 out<<onerow.Data()<<"*"<<std::endl;
2704 else
2705 printf("%s*\n",onerow.Data());
2706//*-*- loop on all selected entries
2707 fSelectedRows = 0;
2708 Int_t tnumber = -1;
2709 bool exitloop = false;
2710 for (entry=firstentry;
2711 entry<(firstentry+nentries) && !exitloop;
2712 entry++) {
2713 entryNumber = fTree->GetEntryNumber(entry);
2714 if (entryNumber < 0) break;
2715 Long64_t localEntry = fTree->LoadTree(entryNumber);
2716 if (localEntry < 0) break;
2717 if (tnumber != fTree->GetTreeNumber()) {
2718 tnumber = fTree->GetTreeNumber();
2719 if (manager) manager->UpdateFormulaLeaves();
2720 else {
2721 for(i=0;i<=fFormulaList->LastIndex();i++) {
2723 }
2724 }
2725 }
2726
2727 int ndata = 1;
2728 if (forceDim) {
2729
2730 if (manager) {
2731
2732 ndata = manager->GetNdata(true);
2733
2734 } else {
2735
2736 // let's print the max number of column
2737 for (ui=0;ui<ncols;ui++) {
2738 if (ndata < var[ui]->GetNdata() ) {
2739 ndata = var[ui]->GetNdata();
2740 }
2741 }
2742 if (select && select->GetNdata()==0) ndata = 0;
2743 }
2744
2745 }
2746
2747 if (lenmax && ndata>(int)lenmax) ndata = lenmax;
2748 bool loaded = false;
2749 for(int inst=0;inst<ndata;inst++) {
2750 if (select) {
2751 if (select->EvalInstance(inst) == 0) {
2752 continue;
2753 }
2754 }
2755 if (inst==0) loaded = true;
2756 else if (!loaded) {
2757 // EvalInstance(0) always needs to be called so that
2758 // the proper branches are loaded.
2759 for (ui=0;ui<ncols;ui++) {
2760 var[ui]->EvalInstance(0);
2761 }
2762 loaded = true;
2763 }
2764 onerow = Form("* %8lld ",entryNumber);
2765 if (hasArray) {
2766 onerow += Form("* %8d ",inst);
2767 }
2768 for (ui=0;ui<ncols;++ui) {
2769 TString numbFormat = Form("* %%%d.%ds ",colSizes[ui],colSizes[ui]);
2770 if (var[ui]->GetNdim()) onerow += Form(numbFormat.Data(),var[ui]->PrintValue(0,inst,colFormats[ui].Data()));
2771 else {
2772 TString emptyForm = Form("* %%%dc ",colSizes[ui]);
2773 onerow += Form(emptyForm.Data(),' ');
2774 }
2775 }
2776 fSelectedRows++;
2777 if (fScanRedirect)
2778 out<<onerow.Data()<<"*"<<std::endl;
2779 else
2780 printf("%s*\n",onerow.Data());
2781 if (fTree->GetScanField() > 0 && fSelectedRows > 0) {
2782 if (fSelectedRows%fTree->GetScanField() == 0) {
2783 fprintf(stderr,"Type <CR> to continue or q to quit ==> ");
2784 int answer, readch;
2785 readch = getchar();
2786 answer = readch;
2787 while (readch != '\n' && readch != EOF) readch = getchar();
2788 if (answer == 'q' || answer == 'Q') {
2789 exitloop = true;
2790 break;
2791 }
2792 }
2793 }
2794 }
2795 }
2796 onerow = "***********";
2797 if (hasArray) onerow += "***********";
2798 for (ui=0;ui<ncols;ui++) {
2799 TString starFormat = Form("*%%%d.%ds",colSizes[ui]+2,colSizes[ui]+2);
2800 onerow += Form(starFormat.Data(),var[ui]->PrintValue(-2));
2801 }
2802 if (fScanRedirect)
2803 out<<onerow.Data()<<"*"<<std::endl;
2804 else
2805 printf("%s*\n",onerow.Data());
2806 if (select) Printf("==> %lld selected %s", fSelectedRows,
2807 fSelectedRows == 1 ? "entry" : "entries");
2808 if (fScanRedirect) printf("File <%s> created\n", fname);
2809
2810//*-*- delete temporary objects
2812 // The TTreeFormulaManager is deleted by the last TTreeFormula.
2813 delete [] var;
2814 return fSelectedRows;
2815}
2816
2817////////////////////////////////////////////////////////////////////////////////
2818/// Loop on Tree and return TSQLResult object containing entries passing
2819/// selection. If varexp is 0 (or "") then print only first 8 columns.
2820/// If varexp = "*" print all columns. Otherwise a columns selection can
2821/// be made using "var1:var2:var3". In case of error 0 is returned otherwise
2822/// a TSQLResult object which must be deleted by the user.
2823
2824TSQLResult *TTreePlayer::Query(const char *varexp, const char *selection,
2825 Option_t *, Long64_t nentries, Long64_t firstentry)
2826{
2827 TTreeFormula **var;
2828 std::vector<TString> cnames;
2829 TString onerow;
2830 Long64_t entry,entryNumber;
2831 Int_t i,nch;
2832 Int_t ncols = 8; // by default first 8 columns are printed only
2833 TObjArray *leaves = fTree->GetListOfLeaves();
2834 Int_t nleaves = leaves->GetEntriesFast();
2835 if (nleaves < ncols) ncols = nleaves;
2836 nch = varexp ? strlen(varexp) : 0;
2837
2838 nentries = GetEntriesToProcess(firstentry, nentries);
2839
2840 // compile selection expression if there is one
2841 TTreeFormula *select = nullptr;
2842 if (strlen(selection)) {
2843 select = new TTreeFormula("Selection",selection,fTree);
2844 if (!select) return nullptr;
2845 if (!select->GetNdim()) { delete select; return nullptr; }
2846 fFormulaList->Add(select);
2847 }
2848
2849 // if varexp is empty, take first 8 columns by default
2850 int allvar = 0;
2851 if (varexp && !strcmp(varexp, "*")) { ncols = nleaves; allvar = 1; }
2852 if (nch == 0 || allvar) {
2853 for (i=0;i<ncols;i++) {
2854 cnames.push_back( ((TLeaf*)leaves->At(i))->GetName() );
2855 }
2856 } else {
2857 // otherwise select only the specified columns
2858 ncols = fSelector->SplitNames(varexp,cnames);
2859 }
2860 var = new TTreeFormula* [ncols];
2861
2862 // create the TreeFormula objects corresponding to each column
2863 for (i=0;i<ncols;i++) {
2864 var[i] = new TTreeFormula("Var1",cnames[i].Data(),fTree);
2865 fFormulaList->Add(var[i]);
2866 }
2867
2868 // fill header info into result object
2869 TTreeResult *res = new TTreeResult(ncols);
2870 for (i = 0; i < ncols; i++) {
2871 res->AddField(i, var[i]->PrintValue(-1));
2872 }
2873
2874 //*-*- Create a TreeFormulaManager to coordinate the formulas
2875 TTreeFormulaManager *manager=nullptr;
2876 if (fFormulaList->LastIndex()>=0) {
2877 manager = new TTreeFormulaManager;
2878 for(i=0;i<=fFormulaList->LastIndex();i++) {
2879 manager->Add((TTreeFormula*)fFormulaList->At(i));
2880 }
2881 manager->Sync();
2882 }
2883
2884 // loop on all selected entries
2885 const char *aresult;
2886 Int_t len;
2887 char *arow = new char[ncols*50];
2888 fSelectedRows = 0;
2889 Int_t tnumber = -1;
2890 Int_t *fields = new Int_t[ncols];
2891 for (entry=firstentry;entry<firstentry+nentries;entry++) {
2892 entryNumber = fTree->GetEntryNumber(entry);
2893 if (entryNumber < 0) break;
2894 Long64_t localEntry = fTree->LoadTree(entryNumber);
2895 if (localEntry < 0) break;
2896 if (tnumber != fTree->GetTreeNumber()) {
2897 tnumber = fTree->GetTreeNumber();
2898 for (i=0;i<ncols;i++) var[i]->UpdateFormulaLeaves();
2899 }
2900
2901 Int_t ndata = 1;
2902 if (manager && manager->GetMultiplicity()) {
2903 ndata = manager->GetNdata();
2904 }
2905
2906 if (select) {
2907 select->GetNdata();
2908 if (select->EvalInstance(0) == 0) continue;
2909 }
2910
2911 bool loaded = false;
2912 for(int inst=0;inst<ndata;inst++) {
2913 if (select) {
2914 if (select->EvalInstance(inst) == 0) {
2915 continue;
2916 }
2917 }
2918
2919 if (inst==0) loaded = true;
2920 else if (!loaded) {
2921 // EvalInstance(0) always needs to be called so that
2922 // the proper branches are loaded.
2923 for (i=0;i<ncols;i++) {
2924 var[i]->EvalInstance(0);
2925 }
2926 loaded = true;
2927 }
2928 for (i=0;i<ncols;i++) {
2929 aresult = var[i]->PrintValue(0,inst);
2930 len = strlen(aresult)+1;
2931 if (i == 0) {
2932 memcpy(arow,aresult,len);
2933 fields[i] = len;
2934 } else {
2935 memcpy(arow+fields[i-1],aresult,len);
2936 fields[i] = fields[i-1] + len;
2937 }
2938 }
2939 res->AddRow(new TTreeRow(ncols,fields,arow));
2940 fSelectedRows++;
2941 }
2942 }
2943
2944 // delete temporary objects
2946 // The TTreeFormulaManager is deleted by the last TTreeFormula.
2947 delete [] fields;
2948 delete [] arow;
2949 delete [] var;
2950
2951 return res;
2952}
2953
2954////////////////////////////////////////////////////////////////////////////////
2955/// Set number of entries to estimate variable limits.
2956
2958{
2960}
2961
2962////////////////////////////////////////////////////////////////////////////////
2963/// Start the TTreeViewer on this TTree.
2964///
2965/// - ww is the width of the canvas in pixels
2966/// - wh is the height of the canvas in pixels
2967
2969{
2970 // unused variables
2971 (void) ww;
2972 (void) wh;
2973
2974 if (!gApplication)
2976 // make sure that the Gpad and GUI libs are loaded
2977
2978 TString hname = gEnv->GetValue("TreeViewer.Name", "TTreeViewer");
2979
2981 if (gApplication)
2982 gApplication->InitializeGraphics(hname == "RTreeViewer");
2983
2984 if (gROOT->IsBatch()) {
2985 if ((hname != "RTreeViewer") || gROOT->IsWebDisplayBatch()) {
2986 Warning("StartViewer", "The tree viewer cannot run in batch mode");
2987 return;
2988 }
2989 }
2990
2991 if (auto h = gROOT->GetPluginManager()->FindHandler("TVirtualTreeViewer", hname.Data())) {
2992 if (h->LoadPlugin() != -1)
2993 h->ExecPlugin(1, fTree);
2994 }
2995}
2996
2997////////////////////////////////////////////////////////////////////////////////
2998/// Unbinned fit of one or more variable(s) from a Tree.
2999///
3000/// funcname is a TF1 function.
3001///
3002/// See TTree::Draw for explanations of the other parameters.
3003///
3004/// Fit the variable varexp using the function funcname using the
3005/// selection cuts given by selection.
3006///
3007/// The list of fit options is given in parameter option.
3008///
3009/// - option = "Q" Quiet mode (minimum printing)
3010/// - option = "V" Verbose mode (default is between Q and V)
3011/// - option = "E" Perform better Errors estimation using Minos technique
3012/// - option = "M" More. Improve fit results
3013/// - option = "D" Draw the projected histogram with the fitted function
3014/// normalized to the number of selected rows
3015/// and multiplied by the bin width
3016///
3017/// You can specify boundary limits for some or all parameters via
3018/// ~~~{.cpp}
3019/// func->SetParLimits(p_number, parmin, parmax);
3020/// ~~~
3021/// if parmin>=parmax, the parameter is fixed
3022///
3023/// Note that you are not forced to fix the limits for all parameters.
3024/// For example, if you fit a function with 6 parameters, you can do:
3025/// ~~~{.cpp}
3026/// func->SetParameters(0,3.1,1.e-6,0.1,-8,100);
3027/// func->SetParLimits(4,-10,-4);
3028/// func->SetParLimits(5, 1,1);
3029/// ~~~
3030/// With this setup, parameters 0->3 can vary freely
3031/// - Parameter 4 has boundaries [-10,-4] with initial value -8
3032/// - Parameter 5 is fixed to 100.
3033///
3034/// For the fit to be meaningful, the function must be self-normalized.
3035///
3036/// i.e. It must have the same integral regardless of the parameter
3037/// settings. Otherwise the fit will effectively just maximize the
3038/// area.
3039///
3040/// It is mandatory to have a normalization variable
3041/// which is fixed for the fit. e.g.
3042/// ~~~{.cpp}
3043/// TF1* f1 = new TF1("f1", "gaus(0)/sqrt(2*3.14159)/[2]", 0, 5);
3044/// f1->SetParameters(1, 3.1, 0.01);
3045/// f1->SetParLimits(0, 1, 1); // fix the normalization parameter to 1
3046/// data->UnbinnedFit("f1", "jpsimass", "jpsipt>3.0");
3047/// ~~~
3048///
3049/// 1, 2 and 3 Dimensional fits are supported.
3050/// See also TTree::Fit
3051///
3052/// ### Return status
3053///
3054/// The function return the status of the fit in the following form
3055/// ~~~{.cpp}
3056/// fitResult = migradResult + 10*minosResult + 100*hesseResult + 1000*improveResult
3057/// ~~~
3058/// - The fitResult is 0 is the fit is OK.
3059/// - The fitResult is negative in case of an error not connected with the fit.
3060/// - The number of entries used in the fit can be obtained via
3061/// ~~~{.cpp}
3062/// mytree.GetSelectedRows();
3063/// ~~~
3064/// - If the number of selected entries is null the function returns -1
3065///
3066/// new implementation using new Fitter classes
3067
3068Int_t TTreePlayer::UnbinnedFit(const char *funcname ,const char *varexp, const char *selection,Option_t *option ,Long64_t nentries, Long64_t firstentry)
3069{
3070 // function is given by name, find it in gROOT
3071 TF1* fitfunc = (TF1*)gROOT->GetFunction(funcname);
3072 if (!fitfunc) { Error("UnbinnedFit", "Unknown function: %s",funcname); return 0; }
3073
3074 Int_t npar = fitfunc->GetNpar();
3075 if (npar <=0) { Error("UnbinnedFit", "Illegal number of parameters = %d",npar); return 0; }
3076
3077 // Spin through the data to select out the events of interest
3078 // Make sure that the arrays V1,etc are created large enough to accommodate
3079 // all entries
3080 Long64_t oldEstimate = fTree->GetEstimate();
3083
3084 // build FitOptions
3085 TString opt = option;
3086 opt.ToUpper();
3087 Foption_t fitOption;
3088 if (opt.Contains("Q")) fitOption.Quiet = 1;
3089 if (opt.Contains("V")){fitOption.Verbose = 1; fitOption.Quiet = 0;}
3090 if (opt.Contains("E")) fitOption.Errors = 1;
3091 if (opt.Contains("M")) fitOption.More = 1;
3092 if (!opt.Contains("D")) fitOption.Nograph = 1; // what about 0
3093 // could add range and automatic normalization of functions and gradient
3094
3095 TString drawOpt = "goff";
3096 if (!fitOption.Nograph) drawOpt = "";
3097 Long64_t nsel = DrawSelect(varexp, selection,drawOpt, nentries, firstentry);
3098
3099 if (!fitOption.Nograph && GetSelectedRows() <= 0 && GetDimension() > 4) {
3100 Info("UnbinnedFit","Ignore option D with more than 4 variables");
3101 nsel = DrawSelect(varexp, selection,"goff", nentries, firstentry);
3102 }
3103
3104 //if no selected entries return
3105 Long64_t nrows = GetSelectedRows();
3106
3107 if (nrows <= 0) {
3108 Error("UnbinnedFit", "Cannot fit: no entries selected");
3109 return -1;
3110 }
3111
3112 // Check that function has same dimension as number of variables
3113 Int_t ndim = GetDimension();
3114 // do not check with TF1::GetNdim() since it returns 1 for TF1 classes created with
3115 // a C function with larger dimension
3116
3117
3118 // use pointer stored in the tree (not copy the data in)
3119 std::vector<double *> vlist(ndim);
3120 for (int i = 0; i < ndim; ++i)
3121 vlist[i] = fSelector->GetVal(i);
3122
3123 // fill the fit data object
3124 // the object will be then managed by the fitted classes - however it will be invalid when the
3125 // data pointers (given by fSelector->GetVal() ) wil be invalidated
3126 ROOT::Fit::UnBinData * fitdata = new ROOT::Fit::UnBinData(nrows, ndim, vlist.begin());
3127
3128
3129
3131 TFitResultPtr ret = ROOT::Fit::UnBinFit(fitdata,fitfunc, fitOption, minOption);
3132
3133 //reset estimate
3134 fTree->SetEstimate(oldEstimate);
3135
3136 //if option "D" is specified, draw the projected histogram
3137 //with the fitted function normalized to the number of selected rows
3138 //and multiplied by the bin width
3139 if (!fitOption.Nograph && fHistogram) {
3140 if (fHistogram->GetDimension() < 2) {
3141 TH1 *hf = (TH1*)fHistogram->Clone("unbinnedFit");
3142 hf->SetLineWidth(3);
3143 hf->Reset();
3144 Int_t nbins = fHistogram->GetXaxis()->GetNbins();
3145 Double_t norm = ((Double_t)nsel)*fHistogram->GetXaxis()->GetBinWidth(1);
3146 for (Int_t bin=1;bin<=nbins;bin++) {
3147 Double_t func = norm*fitfunc->Eval(hf->GetBinCenter(bin));
3148 hf->SetBinContent(bin,func);
3149 }
3150 fHistogram->GetListOfFunctions()->Add(hf,"lsame");
3151 }
3152 fHistogram->Draw();
3153 }
3154
3155
3156 return int(ret);
3157
3158}
3159
3160////////////////////////////////////////////////////////////////////////////////
3161/// this function is called by TChain::LoadTree when a new Tree is loaded.
3162/// Because Trees in a TChain may have a different list of leaves, one
3163/// must update the leaves numbers in the TTreeFormula used by the TreePlayer.
3164
3166{
3167 if (fSelector) fSelector->Notify();
3168 if (fSelectorUpdate){
3169 //If the selector is writing into a TEntryList, the entry list's
3170 //sublists need to be changed according to the loaded tree
3172 //FIXME: should be more consistent with selector from file
3173 TObject *obj = fSelector->GetObject();
3174 if (obj){
3177 }
3178 }
3179 }
3182 TEntryList *elist=nullptr;
3183 while ((elist=(TEntryList*)next())){
3184 if (elist->InheritsFrom(TEntryList::Class())){
3185 elist->SetTree(fTree->GetTree());
3186 }
3187 }
3188 }
3189 }
3190
3191 if (fFormulaList->GetSize()) {
3193 while (lnk) {
3194 lnk->GetObject()->Notify();
3195 lnk = lnk->Next();
3196 }
3197 }
3198}
#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:124
long long Long64_t
Definition RtypesCore.h:80
const char Option_t
Definition RtypesCore.h:66
#define ClassImp(name)
Definition Rtypes.h:377
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:407
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:555
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:540
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:6685
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:5912
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:4599
Bool_t InheritsFrom(const char *cl) const override
Return kTRUE if this class inherits from a class with name "classname".
Definition TClass.cxx:4874
const char * GetDeclFileName() const
Return name of the file containing the declaration of this class.
Definition TClass.cxx:3463
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:2968
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
A TEventList object is a list of selected events (entries) in a TTree.
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:1441
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:4574
TFileCacheRead * GetCacheRead(const TObject *tree=nullptr) const
Return a pointer to the current read cache.
Definition TFile.cxx:1262
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:9132
@ kNoAxis
NOTE: Must always be 0 !!!
Definition TH1.h:72
virtual Int_t GetDimension() const
Definition TH1.h:283
virtual void Reset(Option_t *option="")
Reset this histogram: contents, errors, etc.
Definition TH1.cxx:7094
TAxis * GetXaxis()
Definition TH1.h:324
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:3898
void Draw(Option_t *option="") override
Draw this histogram with options.
Definition TH1.cxx:3066
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:9213
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:6640
TList * GetListOfFunctions() const
Definition TH1.h:244
virtual void Scale(Double_t c1=1, Option_t *option="")
Multiply this histogram by a constant c1.
Definition TH1.cxx:6595
TObject * Clone(const char *newname="") const override
Make a complete copy of the underlying object.
Definition TH1.cxx:2752
virtual Double_t GetSumOfWeights() const
Return the sum of weights excluding under/overflows.
Definition TH1.cxx:7908
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:5236
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:83
virtual TObjLink * FirstLink() const
Definition TList.h:104
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:593
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:438
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:973
virtual TObject * FindObject(const char *name) const
Must be redefined in derived classes.
Definition TObject.cxx:402
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:780
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:524
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:987
virtual void Draw(Option_t *option="")
Default Draw method for all objects.
Definition TObject.cxx:274
@ 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:961
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:2685
virtual TBranch * GetBranch(const char *name)
Return pointer to the branch with the given name in this tree or its friends.
Definition TTree.cxx:5294
virtual Int_t GetScanField() const
Definition TTree.h:511
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:5638
virtual Long64_t GetEstimate() const
Definition TTree.h:467
virtual TObjArray * GetListOfLeaves()
Definition TTree.h:489
TFile * GetCurrentFile() const
Return pointer to the current file.
Definition TTree.cxx:5479
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:9231
TDirectory * GetDirectory() const
Definition TTree.h:462
virtual TEntryList * GetEntryList()
Returns the entry list assigned to this tree.
Definition TTree.cxx:5854
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:7450
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:9110
virtual Long64_t GetEntryNumber(Long64_t entry) const
Return entry number corresponding to entry.
Definition TTree.cxx:5865
virtual TTree * CloneTree(Long64_t nentries=-1, Option_t *option="")
Create a clone of this tree and copy nentries.
Definition TTree.cxx:3139
virtual TTree * GetTree() const
Definition TTree.h:517
virtual void SetEntryList(TEntryList *list, Option_t *opt="")
Set an EntryList.
Definition TTree.cxx:9046
virtual Long64_t LoadTree(Long64_t entry)
Set current entry.
Definition TTree.cxx:6473
TEventList * GetEventList() const
Definition TTree.h:473
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:5512
virtual Int_t GetTreeNumber() const
Definition TTree.h:519
virtual Int_t GetTimerInterval() const
Definition TTree.h:514
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:651
virtual Long64_t GetCacheSize() const
Definition TTree.h:453
virtual Long64_t GetMaxEntryLoop() const
Definition TTree.h:497
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
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