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