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