Logo ROOT  
Reference Guide
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);
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%zx,(TEntryList*)0x%zx)",
526 (size_t)para, (size_t)enlist));
527 }
528 //*-*- 5d with gl
529 } else if (fDimension == 5 && optgl5d) {
530 gROOT->ProcessLineFast(Form("(new TGL5DDataSet((TTree *)0x%zx))->Draw(\"%s\");", (size_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.
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 && fTree->GetCacheSize() > 0) {
2256 tpf = (TTreeCache*)curfile->GetCacheRead(fTree);
2257 if (tpf)
2258 tpf->SetEntryRange(firstentry,firstentry+nentries);
2259 else {
2261 tpf = (TTreeCache*)curfile->GetCacheRead(fTree);
2262 if (tpf) tpf->SetEntryRange(firstentry,firstentry+nentries);
2263 }
2264 }
2265
2266 //Create a timer to get control in the entry loop(s)
2267 TProcessEventTimer *timer = 0;
2268 Int_t interval = fTree->GetTimerInterval();
2269 if (!gROOT->IsBatch() && interval)
2270 timer = new TProcessEventTimer(interval);
2271
2272 //loop on entries (elist or all entries)
2273 Long64_t entry, entryNumber, localEntry;
2274
2275 Bool_t useCutFill = selector->Version() == 0;
2276
2277 // force the first monitoring info
2280
2281 //trying to set the first tree, because in the Draw function
2282 //the tree corresponding to firstentry has already been loaded,
2283 //so it is not set in the entry list
2284 fSelectorUpdate = selector;
2286
2287 for (entry=firstentry;entry<firstentry+nentries;entry++) {
2288 entryNumber = fTree->GetEntryNumber(entry);
2289 if (entryNumber < 0) break;
2290 if (timer && timer->ProcessEvents()) break;
2291 if (gROOT->IsInterrupted()) break;
2292 localEntry = fTree->LoadTree(entryNumber);
2293 if (localEntry < 0) break;
2294 if(useCutFill) {
2295 if (selector->ProcessCut(localEntry))
2296 selector->ProcessFill(localEntry); //<==call user analysis function
2297 } else {
2298 selector->Process(localEntry); //<==call user analysis function
2299 }
2301 gMonitoringWriter->SendProcessingProgress((entry-firstentry),TFile::GetFileBytesRead()-readbytesatstart,kTRUE);
2302 if (selector->GetAbort() == TSelector::kAbortProcess) break;
2303 if (selector->GetAbort() == TSelector::kAbortFile) {
2304 // Skip to the next file.
2305 entry += fTree->GetTree()->GetEntries() - localEntry;
2306 // Reset the abort status.
2307 selector->ResetAbort();
2308 }
2309 }
2310 delete timer;
2311 //we must reset the cache
2312 {
2313 TFile *curfile2 = fTree->GetCurrentFile();
2314 if (curfile2 && fTree->GetCacheSize() > 0) {
2315 tpf = (TTreeCache*)curfile2->GetCacheRead(fTree);
2316 if (tpf) tpf->SetEntryRange(0,0);
2317 }
2318 }
2319 }
2320
2321 process = (selector->GetAbort() != TSelector::kAbortProcess &&
2322 (selector->Version() != 0 || selector->GetStatus() != -1)) ? kTRUE : kFALSE;
2323 Long64_t res = (process) ? 0 : -1;
2324 if (process) {
2325 selector->SlaveTerminate(); //<==call user termination function
2326 selector->Terminate(); //<==call user termination function
2327 res = selector->GetStatus();
2328 }
2329 fTree->SetNotify(0); // Detach the selector from the tree.
2330 fSelectorUpdate = 0;
2333
2334 return res;
2335}
2336
2337////////////////////////////////////////////////////////////////////////////////
2338/// cleanup pointers in the player pointing to obj
2339
2341{
2342 if (fHistogram == obj) fHistogram = 0;
2343}
2344
2345////////////////////////////////////////////////////////////////////////////////
2346/// Loop on Tree and print entries passing selection. If varexp is 0 (or "")
2347/// then print only first 8 columns. If varexp = "*" print all columns.
2348/// Otherwise a columns selection can be made using "var1:var2:var3".
2349/// The function returns the number of entries passing the selection.
2350///
2351/// By default 50 rows are shown and you are asked for `<CR>`
2352/// to see the next 50 rows.
2353///
2354/// You can change the default number of rows to be shown before `<CR>`
2355/// via mytree->SetScanField(maxrows) where maxrows is 50 by default.
2356/// if maxrows is set to 0 all rows of the Tree are shown.
2357///
2358/// This option is interesting when dumping the contents of a Tree to
2359/// an ascii file, eg from the command line.
2360/// ### with ROOT 5
2361/// ~~~{.cpp}
2362/// root [0] tree->SetScanField(0);
2363/// root [1] tree->Scan("*"); >tree.log
2364/// ~~~
2365/// ### with ROOT 6
2366/// ~~~{.cpp}
2367/// root [0] tree->SetScanField(0);
2368/// root [1] .> tree.log
2369/// tree->Scan("*");
2370/// .>
2371/// ~~~
2372/// will create a file tree.log
2373///
2374/// Arrays (within an entry) are printed in their linear forms.
2375/// If several arrays with multiple dimensions are printed together,
2376/// they will NOT be synchronized. For example print
2377/// arr1[4][2] and arr2[2][3] will results in a printing similar to:
2378/// ~~~{.cpp}
2379/// ***********************************************
2380/// * Row * Instance * arr1 * arr2 *
2381/// ***********************************************
2382/// * x * 0 * arr1[0][0]* arr2[0][0]*
2383/// * x * 1 * arr1[0][1]* arr2[0][1]*
2384/// * x * 2 * arr1[1][0]* arr2[0][2]*
2385/// * x * 3 * arr1[1][1]* arr2[1][0]*
2386/// * x * 4 * arr1[2][0]* arr2[1][1]*
2387/// * x * 5 * arr1[2][1]* arr2[1][2]*
2388/// * x * 6 * arr1[3][0]* *
2389/// * x * 7 * arr1[3][1]* *
2390/// ~~~
2391/// However, if there is a selection criterion which is an array, then
2392/// all the formulas will be synchronized with the selection criterion
2393/// (see TTreePlayer::DrawSelect for more information).
2394///
2395/// The options string can contains the following parameters:
2396///
2397/// - lenmax=dd
2398/// Where 'dd' is the maximum number of elements per array that should
2399/// be printed. If 'dd' is 0, all elements are printed (this is the
2400/// default)
2401/// - colsize=ss
2402/// Where 'ss' will be used as the default size for all the column
2403/// If this options is not specified, the default column size is 9
2404/// - precision=pp
2405/// Where 'pp' will be used as the default 'precision' for the
2406/// printing format.
2407/// - col=xxx
2408/// Where 'xxx' is colon (:) delimited list of printing format for
2409/// each column. The format string should follow the printf format
2410/// specification. The value given will be prefixed by % and, if no
2411/// conversion specifier is given, will be suffixed by the letter g.
2412/// before being passed to fprintf. If no format is specified for a
2413/// column, the default is used (aka ${colsize}.${precision}g )
2414///
2415/// For example:
2416/// ~~~{.cpp}
2417/// tree->Scan("a:b:c","","colsize=30 precision=3 col=::20.10:#x:5ld");
2418/// ~~~
2419/// Will print 3 columns, the first 2 columns will be 30 characters long,
2420/// the third columns will be 20 characters long. The printing format used
2421/// for the columns (assuming they are numbers) will be respectively:
2422/// ~~~ {.cpp}
2423/// %30.3g %30.3g %20.10g %#x %5ld
2424/// ~~~
2425
2426Long64_t TTreePlayer::Scan(const char *varexp, const char *selection,
2427 Option_t * option,
2428 Long64_t nentries, Long64_t firstentry)
2429{
2430
2431 TString opt = option;
2432 opt.ToLower();
2433 UInt_t ui;
2434 UInt_t lenmax = 0;
2435 UInt_t colDefaultSize = 9;
2436 UInt_t colPrecision = 9;
2437 std::vector<TString> colFormats;
2438 std::vector<Int_t> colSizes;
2439
2440 if (opt.Contains("lenmax=")) {
2441 int start = opt.Index("lenmax=");
2442 int numpos = start + strlen("lenmax=");
2443 int numlen = 0;
2444 int len = opt.Length();
2445 while( (numpos+numlen<len) && isdigit(opt[numpos+numlen]) ) numlen++;
2446 TString num = opt(numpos,numlen);
2447 opt.Remove(start,strlen("lenmax")+numlen);
2448
2449 lenmax = atoi(num.Data());
2450 }
2451 if (opt.Contains("colsize=")) {
2452 int start = opt.Index("colsize=");
2453 int numpos = start + strlen("colsize=");
2454 int numlen = 0;
2455 int len = opt.Length();
2456 while( (numpos+numlen<len) && isdigit(opt[numpos+numlen]) ) numlen++;
2457 TString num = opt(numpos,numlen);
2458 opt.Remove(start,strlen("size")+numlen);
2459
2460 colDefaultSize = atoi(num.Data());
2461 colPrecision = colDefaultSize;
2462 if (colPrecision>18) colPrecision = 18;
2463 }
2464 if (opt.Contains("precision=")) {
2465 int start = opt.Index("precision=");
2466 int numpos = start + strlen("precision=");
2467 int numlen = 0;
2468 int len = opt.Length();
2469 while( (numpos+numlen<len) && isdigit(opt[numpos+numlen]) ) numlen++;
2470 TString num = opt(numpos,numlen);
2471 opt.Remove(start,strlen("precision")+numlen);
2472
2473 colPrecision = atoi(num.Data());
2474 }
2475 TString defFormat = Form("%d.%d",colDefaultSize,colPrecision);
2476 if (opt.Contains("col=")) {
2477 int start = opt.Index("col=");
2478 int numpos = start + strlen("col=");
2479 int numlen = 0;
2480 int len = opt.Length();
2481 while( (numpos+numlen<len) &&
2482 (isdigit(opt[numpos+numlen])
2483 || opt[numpos+numlen] == 'c'
2484 || opt[numpos+numlen] == 'd'
2485 || opt[numpos+numlen] == 'i'
2486 || opt[numpos+numlen] == 'o'
2487 || opt[numpos+numlen] == 'x'
2488 || opt[numpos+numlen] == 'X'
2489 || opt[numpos+numlen] == 'u'
2490 || opt[numpos+numlen] == 'f'
2491 || opt[numpos+numlen] == 'e'
2492 || opt[numpos+numlen] == 'E'
2493 || opt[numpos+numlen] == 'g'
2494 || opt[numpos+numlen] == 'G'
2495 || opt[numpos+numlen] == 'l'
2496 || opt[numpos+numlen] == 'L'
2497 || opt[numpos+numlen] == 'h'
2498 || opt[numpos+numlen] == 's'
2499 || opt[numpos+numlen] == '#'
2500 || opt[numpos+numlen]=='.'
2501 || opt[numpos+numlen]==':')) numlen++;
2502 TString flist = opt(numpos,numlen);
2503 opt.Remove(start,strlen("col")+numlen);
2504
2505 int i = 0;
2506 while(i<flist.Length() && flist[i]==':') {
2507 colFormats.push_back(defFormat);
2508 colSizes.push_back(colDefaultSize);
2509 ++i;
2510 }
2511 for(; i<flist.Length(); ++i) {
2512 int next = flist.Index(":",i);
2513 if (next==i) {
2514 colFormats.push_back(defFormat);
2515 } else if (next==kNPOS) {
2516 colFormats.push_back(flist(i,flist.Length()-i));
2517 i = flist.Length();
2518 } else {
2519 colFormats.push_back(flist(i,next-i));
2520 i = next;
2521 }
2522 UInt_t siz = atoi(colFormats[colFormats.size()-1].Data());
2523 colSizes.push_back( siz ? siz : colDefaultSize );
2524 }
2525 }
2526
2527 TTreeFormula **var;
2528 std::vector<TString> cnames;
2529 TString onerow;
2530 Long64_t entry,entryNumber;
2531 Int_t i,nch;
2532 UInt_t ncols = 8; // by default first 8 columns are printed only
2533 std::ofstream out;
2534 const char *fname = nullptr;
2535 TString fownname;
2536 if (fScanRedirect) {
2537 fTree->SetScanField(0); // no page break if Scan is redirected
2538 fname = fScanFileName;
2539 if (!fname) fname = "";
2540 Int_t lenfile = strlen(fname);
2541 if (!lenfile) {
2542 fownname = fTree->GetName();
2543 fownname.Append("-scan.dat");
2544 fname = fownname.Data();
2545 }
2546 out.open(fname, std::ios::out);
2547 if (!out.good ()) {
2548 Error("Scan","Can not open file for redirection");
2549 return 0;
2550 }
2551 }
2552 TObjArray *leaves = fTree->GetListOfLeaves();
2553 if (leaves==0) return 0;
2554 UInt_t nleaves = leaves->GetEntriesFast();
2555 if (nleaves < ncols) ncols = nleaves;
2556 nch = varexp ? strlen(varexp) : 0;
2557
2558 nentries = GetEntriesToProcess(firstentry, nentries);
2559
2560//*-*- Compile selection expression if there is one
2561 TTreeFormula *select = 0;
2562 if (selection && strlen(selection)) {
2563 select = new TTreeFormula("Selection",selection,fTree);
2564 if (!select) return -1;
2565 if (!select->GetNdim()) { delete select; return -1; }
2566 fFormulaList->Add(select);
2567 }
2568//*-*- if varexp is empty, take first 8 columns by default
2569 int allvar = 0;
2570 if (varexp && !strcmp(varexp, "*")) { ncols = nleaves; allvar = 1; }
2571 if (nch == 0 || allvar) {
2572 UInt_t ncs = ncols;
2573 ncols = 0;
2574 for (ui=0;ui<ncs;++ui) {
2575 TLeaf *lf = (TLeaf*)leaves->At(ui);
2576 if (lf->GetBranch()->GetListOfBranches()->GetEntries() > 0) continue;
2577 cnames.push_back( lf->GetBranch()->GetMother()->GetName() );
2578 if (cnames[ncols] == lf->GetName() ) {
2579 // Already complete, let move on.
2580 } else if (cnames[ncols][cnames[ncols].Length()-1]=='.') {
2581 cnames[ncols] = lf->GetBranch()->GetName(); // name of branch already include mother's name
2582 } else {
2583 if (lf->GetBranch()->GetMother()->IsA()->InheritsFrom(TBranchElement::Class())) {
2584 TBranchElement *mother = (TBranchElement*)lf->GetBranch()->GetMother();
2585 if (mother->GetType() == 3 || mother->GetType() == 4) {
2586 // The name of the mother branch is embedded in the sub-branch names.
2587 cnames[ncols] = lf->GetBranch()->GetName();
2588 ++ncols;
2589 continue;
2590 }
2591 }
2592 if (!strchr(lf->GetBranch()->GetName() ,'[') ) {
2593 cnames[ncols].Append('.');
2594 cnames[ncols].Append( lf->GetBranch()->GetName() );
2595 }
2596 }
2597 if (lf->GetBranch()->IsA() == TBranch::Class() ||
2598 strcmp( lf->GetBranch()->GetName(), lf->GetName() ) != 0 ) {
2599 cnames[ncols].Append('.');
2600 cnames[ncols].Append( lf->GetName() );
2601 }
2602 ++ncols;
2603 }
2604//*-*- otherwise select only the specified columns
2605 } else {
2606
2607 ncols = fSelector->SplitNames(varexp, cnames);
2608
2609 }
2610 var = new TTreeFormula* [ncols];
2611
2612 for(ui=colFormats.size();ui<ncols;++ui) {
2613 colFormats.push_back(defFormat);
2614 colSizes.push_back(colDefaultSize);
2615 }
2616
2617//*-*- Create the TreeFormula objects corresponding to each column
2618 for (ui=0;ui<ncols;ui++) {
2619 var[ui] = new TTreeFormula("Var1",cnames[ui].Data(),fTree);
2620 fFormulaList->Add(var[ui]);
2621 }
2622
2623//*-*- Create a TreeFormulaManager to coordinate the formulas
2624 TTreeFormulaManager *manager=0;
2625 Bool_t hasArray = kFALSE;
2626 Bool_t forceDim = kFALSE;
2627 if (fFormulaList->LastIndex()>=0) {
2628 if (select) {
2629 if (select->GetManager()->GetMultiplicity() > 0 ) {
2630 manager = new TTreeFormulaManager;
2631 for(i=0;i<=fFormulaList->LastIndex();i++) {
2632 manager->Add((TTreeFormula*)fFormulaList->At(i));
2633 }
2634 manager->Sync();
2635 }
2636 }
2637 for(i=0;i<=fFormulaList->LastIndex();i++) {
2638 TTreeFormula *form = ((TTreeFormula*)fFormulaList->At(i));
2639 switch( form->GetManager()->GetMultiplicity() ) {
2640 case 1:
2641 case 2:
2642 hasArray = kTRUE;
2643 forceDim = kTRUE;
2644 break;
2645 case -1:
2646 forceDim = kTRUE;
2647 break;
2648 case 0:
2649 break;
2650 }
2651
2652 }
2653 }
2654
2655//*-*- Print header
2656 onerow = "***********";
2657 if (hasArray) onerow += "***********";
2658
2659 for (ui=0;ui<ncols;ui++) {
2660 TString starFormat = Form("*%%%d.%ds",colSizes[ui]+2,colSizes[ui]+2);
2661 onerow += Form(starFormat.Data(),var[ui]->PrintValue(-2));
2662 }
2663 if (fScanRedirect)
2664 out<<onerow.Data()<<"*"<<std::endl;
2665 else
2666 printf("%s*\n",onerow.Data());
2667 onerow = "* Row ";
2668 if (hasArray) onerow += "* Instance ";
2669 for (ui=0;ui<ncols;ui++) {
2670 TString numbFormat = Form("* %%%d.%ds ",colSizes[ui],colSizes[ui]);
2671 onerow += Form(numbFormat.Data(),var[ui]->PrintValue(-1));
2672 }
2673 if (fScanRedirect)
2674 out<<onerow.Data()<<"*"<<std::endl;
2675 else
2676 printf("%s*\n",onerow.Data());
2677 onerow = "***********";
2678 if (hasArray) onerow += "***********";
2679 for (ui=0;ui<ncols;ui++) {
2680 TString starFormat = Form("*%%%d.%ds",colSizes[ui]+2,colSizes[ui]+2);
2681 onerow += Form(starFormat.Data(),var[ui]->PrintValue(-2));
2682 }
2683 if (fScanRedirect)
2684 out<<onerow.Data()<<"*"<<std::endl;
2685 else
2686 printf("%s*\n",onerow.Data());
2687//*-*- loop on all selected entries
2688 fSelectedRows = 0;
2689 Int_t tnumber = -1;
2690 Bool_t exitloop = kFALSE;
2691 for (entry=firstentry;
2692 entry<(firstentry+nentries) && !exitloop;
2693 entry++) {
2694 entryNumber = fTree->GetEntryNumber(entry);
2695 if (entryNumber < 0) break;
2696 Long64_t localEntry = fTree->LoadTree(entryNumber);
2697 if (localEntry < 0) break;
2698 if (tnumber != fTree->GetTreeNumber()) {
2699 tnumber = fTree->GetTreeNumber();
2700 if (manager) manager->UpdateFormulaLeaves();
2701 else {
2702 for(i=0;i<=fFormulaList->LastIndex();i++) {
2704 }
2705 }
2706 }
2707
2708 int ndata = 1;
2709 if (forceDim) {
2710
2711 if (manager) {
2712
2713 ndata = manager->GetNdata(kTRUE);
2714
2715 } else {
2716
2717 // let's print the max number of column
2718 for (ui=0;ui<ncols;ui++) {
2719 if (ndata < var[ui]->GetNdata() ) {
2720 ndata = var[ui]->GetNdata();
2721 }
2722 }
2723 if (select && select->GetNdata()==0) ndata = 0;
2724 }
2725
2726 }
2727
2728 if (lenmax && ndata>(int)lenmax) ndata = lenmax;
2729 Bool_t loaded = kFALSE;
2730 for(int inst=0;inst<ndata;inst++) {
2731 if (select) {
2732 if (select->EvalInstance(inst) == 0) {
2733 continue;
2734 }
2735 }
2736 if (inst==0) loaded = kTRUE;
2737 else if (!loaded) {
2738 // EvalInstance(0) always needs to be called so that
2739 // the proper branches are loaded.
2740 for (ui=0;ui<ncols;ui++) {
2741 var[ui]->EvalInstance(0);
2742 }
2743 loaded = kTRUE;
2744 }
2745 onerow = Form("* %8lld ",entryNumber);
2746 if (hasArray) {
2747 onerow += Form("* %8d ",inst);
2748 }
2749 for (ui=0;ui<ncols;++ui) {
2750 TString numbFormat = Form("* %%%d.%ds ",colSizes[ui],colSizes[ui]);
2751 if (var[ui]->GetNdim()) onerow += Form(numbFormat.Data(),var[ui]->PrintValue(0,inst,colFormats[ui].Data()));
2752 else {
2753 TString emptyForm = Form("* %%%dc ",colSizes[ui]);
2754 onerow += Form(emptyForm.Data(),' ');
2755 }
2756 }
2757 fSelectedRows++;
2758 if (fScanRedirect)
2759 out<<onerow.Data()<<"*"<<std::endl;
2760 else
2761 printf("%s*\n",onerow.Data());
2762 if (fTree->GetScanField() > 0 && fSelectedRows > 0) {
2763 if (fSelectedRows%fTree->GetScanField() == 0) {
2764 fprintf(stderr,"Type <CR> to continue or q to quit ==> ");
2765 int answer, readch;
2766 readch = getchar();
2767 answer = readch;
2768 while (readch != '\n' && readch != EOF) readch = getchar();
2769 if (answer == 'q' || answer == 'Q') {
2770 exitloop = kTRUE;
2771 break;
2772 }
2773 }
2774 }
2775 }
2776 }
2777 onerow = "***********";
2778 if (hasArray) onerow += "***********";
2779 for (ui=0;ui<ncols;ui++) {
2780 TString starFormat = Form("*%%%d.%ds",colSizes[ui]+2,colSizes[ui]+2);
2781 onerow += Form(starFormat.Data(),var[ui]->PrintValue(-2));
2782 }
2783 if (fScanRedirect)
2784 out<<onerow.Data()<<"*"<<std::endl;
2785 else
2786 printf("%s*\n",onerow.Data());
2787 if (select) Printf("==> %lld selected %s", fSelectedRows,
2788 fSelectedRows == 1 ? "entry" : "entries");
2789 if (fScanRedirect) printf("File <%s> created\n", fname);
2790
2791//*-*- delete temporary objects
2793 // The TTreeFormulaManager is deleted by the last TTreeFormula.
2794 delete [] var;
2795 return fSelectedRows;
2796}
2797
2798////////////////////////////////////////////////////////////////////////////////
2799/// Loop on Tree and return TSQLResult object containing entries passing
2800/// selection. If varexp is 0 (or "") then print only first 8 columns.
2801/// If varexp = "*" print all columns. Otherwise a columns selection can
2802/// be made using "var1:var2:var3". In case of error 0 is returned otherwise
2803/// a TSQLResult object which must be deleted by the user.
2804
2805TSQLResult *TTreePlayer::Query(const char *varexp, const char *selection,
2806 Option_t *, Long64_t nentries, Long64_t firstentry)
2807{
2808 TTreeFormula **var;
2809 std::vector<TString> cnames;
2810 TString onerow;
2811 Long64_t entry,entryNumber;
2812 Int_t i,nch;
2813 Int_t ncols = 8; // by default first 8 columns are printed only
2814 TObjArray *leaves = fTree->GetListOfLeaves();
2815 Int_t nleaves = leaves->GetEntriesFast();
2816 if (nleaves < ncols) ncols = nleaves;
2817 nch = varexp ? strlen(varexp) : 0;
2818
2819 nentries = GetEntriesToProcess(firstentry, nentries);
2820
2821 // compile selection expression if there is one
2822 TTreeFormula *select = 0;
2823 if (strlen(selection)) {
2824 select = new TTreeFormula("Selection",selection,fTree);
2825 if (!select) return 0;
2826 if (!select->GetNdim()) { delete select; return 0; }
2827 fFormulaList->Add(select);
2828 }
2829
2830 // if varexp is empty, take first 8 columns by default
2831 int allvar = 0;
2832 if (varexp && !strcmp(varexp, "*")) { ncols = nleaves; allvar = 1; }
2833 if (nch == 0 || allvar) {
2834 for (i=0;i<ncols;i++) {
2835 cnames.push_back( ((TLeaf*)leaves->At(i))->GetName() );
2836 }
2837 } else {
2838 // otherwise select only the specified columns
2839 ncols = fSelector->SplitNames(varexp,cnames);
2840 }
2841 var = new TTreeFormula* [ncols];
2842
2843 // create the TreeFormula objects corresponding to each column
2844 for (i=0;i<ncols;i++) {
2845 var[i] = new TTreeFormula("Var1",cnames[i].Data(),fTree);
2846 fFormulaList->Add(var[i]);
2847 }
2848
2849 // fill header info into result object
2850 TTreeResult *res = new TTreeResult(ncols);
2851 for (i = 0; i < ncols; i++) {
2852 res->AddField(i, var[i]->PrintValue(-1));
2853 }
2854
2855 //*-*- Create a TreeFormulaManager to coordinate the formulas
2856 TTreeFormulaManager *manager=0;
2857 if (fFormulaList->LastIndex()>=0) {
2858 manager = new TTreeFormulaManager;
2859 for(i=0;i<=fFormulaList->LastIndex();i++) {
2860 manager->Add((TTreeFormula*)fFormulaList->At(i));
2861 }
2862 manager->Sync();
2863 }
2864
2865 // loop on all selected entries
2866 const char *aresult;
2867 Int_t len;
2868 char *arow = new char[ncols*50];
2869 fSelectedRows = 0;
2870 Int_t tnumber = -1;
2871 Int_t *fields = new Int_t[ncols];
2872 for (entry=firstentry;entry<firstentry+nentries;entry++) {
2873 entryNumber = fTree->GetEntryNumber(entry);
2874 if (entryNumber < 0) break;
2875 Long64_t localEntry = fTree->LoadTree(entryNumber);
2876 if (localEntry < 0) break;
2877 if (tnumber != fTree->GetTreeNumber()) {
2878 tnumber = fTree->GetTreeNumber();
2879 for (i=0;i<ncols;i++) var[i]->UpdateFormulaLeaves();
2880 }
2881
2882 Int_t ndata = 1;
2883 if (manager && manager->GetMultiplicity()) {
2884 ndata = manager->GetNdata();
2885 }
2886
2887 if (select) {
2888 select->GetNdata();
2889 if (select->EvalInstance(0) == 0) continue;
2890 }
2891
2892 Bool_t loaded = kFALSE;
2893 for(int inst=0;inst<ndata;inst++) {
2894 if (select) {
2895 if (select->EvalInstance(inst) == 0) {
2896 continue;
2897 }
2898 }
2899
2900 if (inst==0) loaded = kTRUE;
2901 else if (!loaded) {
2902 // EvalInstance(0) always needs to be called so that
2903 // the proper branches are loaded.
2904 for (i=0;i<ncols;i++) {
2905 var[i]->EvalInstance(0);
2906 }
2907 loaded = kTRUE;
2908 }
2909 for (i=0;i<ncols;i++) {
2910 aresult = var[i]->PrintValue(0,inst);
2911 len = strlen(aresult)+1;
2912 if (i == 0) {
2913 memcpy(arow,aresult,len);
2914 fields[i] = len;
2915 } else {
2916 memcpy(arow+fields[i-1],aresult,len);
2917 fields[i] = fields[i-1] + len;
2918 }
2919 }
2920 res->AddRow(new TTreeRow(ncols,fields,arow));
2921 fSelectedRows++;
2922 }
2923 }
2924
2925 // delete temporary objects
2927 // The TTreeFormulaManager is deleted by the last TTreeFormula.
2928 delete [] fields;
2929 delete [] arow;
2930 delete [] var;
2931
2932 return res;
2933}
2934
2935////////////////////////////////////////////////////////////////////////////////
2936/// Set number of entries to estimate variable limits.
2937
2939{
2941}
2942
2943////////////////////////////////////////////////////////////////////////////////
2944/// Start the TTreeViewer on this TTree.
2945///
2946/// - ww is the width of the canvas in pixels
2947/// - wh is the height of the canvas in pixels
2948
2950{
2951 if (!gApplication)
2953 // make sure that the Gpad and GUI libs are loaded
2955 if (gApplication)
2957 if (gROOT->IsBatch()) {
2958 Warning("StartViewer", "The tree viewer cannot run in batch mode");
2959 return;
2960 }
2961
2962 if (ww || wh) { } // use unused variables
2964 if ((h = gROOT->GetPluginManager()->FindHandler("TVirtualTreeViewer"))) {
2965 if (h->LoadPlugin() == -1)
2966 return;
2967 h->ExecPlugin(1,fTree);
2968 }
2969}
2970
2971////////////////////////////////////////////////////////////////////////////////
2972/// Unbinned fit of one or more variable(s) from a Tree.
2973///
2974/// funcname is a TF1 function.
2975///
2976/// See TTree::Draw for explanations of the other parameters.
2977///
2978/// Fit the variable varexp using the function funcname using the
2979/// selection cuts given by selection.
2980///
2981/// The list of fit options is given in parameter option.
2982///
2983/// - option = "Q" Quiet mode (minimum printing)
2984/// - option = "V" Verbose mode (default is between Q and V)
2985/// - option = "E" Perform better Errors estimation using Minos technique
2986/// - option = "M" More. Improve fit results
2987/// - option = "D" Draw the projected histogram with the fitted function
2988/// normalized to the number of selected rows
2989/// and multiplied by the bin width
2990///
2991/// You can specify boundary limits for some or all parameters via
2992/// ~~~{.cpp}
2993/// func->SetParLimits(p_number, parmin, parmax);
2994/// ~~~
2995/// if parmin>=parmax, the parameter is fixed
2996///
2997/// Note that you are not forced to fix the limits for all parameters.
2998/// For example, if you fit a function with 6 parameters, you can do:
2999/// ~~~{.cpp}
3000/// func->SetParameters(0,3.1,1.e-6,0.1,-8,100);
3001/// func->SetParLimits(4,-10,-4);
3002/// func->SetParLimits(5, 1,1);
3003/// ~~~
3004/// With this setup, parameters 0->3 can vary freely
3005/// - Parameter 4 has boundaries [-10,-4] with initial value -8
3006/// - Parameter 5 is fixed to 100.
3007///
3008/// For the fit to be meaningful, the function must be self-normalized.
3009///
3010/// i.e. It must have the same integral regardless of the parameter
3011/// settings. Otherwise the fit will effectively just maximize the
3012/// area.
3013///
3014/// It is mandatory to have a normalization variable
3015/// which is fixed for the fit. e.g.
3016/// ~~~{.cpp}
3017/// TF1* f1 = new TF1("f1", "gaus(0)/sqrt(2*3.14159)/[2]", 0, 5);
3018/// f1->SetParameters(1, 3.1, 0.01);
3019/// f1->SetParLimits(0, 1, 1); // fix the normalization parameter to 1
3020/// data->UnbinnedFit("f1", "jpsimass", "jpsipt>3.0");
3021/// ~~~
3022///
3023/// 1, 2 and 3 Dimensional fits are supported.
3024/// See also TTree::Fit
3025///
3026/// ### Return status
3027///
3028/// The function return the status of the fit in the following form
3029/// ~~~{.cpp}
3030/// fitResult = migradResult + 10*minosResult + 100*hesseResult + 1000*improveResult
3031/// ~~~
3032/// - The fitResult is 0 is the fit is OK.
3033/// - The fitResult is negative in case of an error not connected with the fit.
3034/// - The number of entries used in the fit can be obtained via
3035/// ~~~{.cpp}
3036/// mytree.GetSelectedRows();
3037/// ~~~
3038/// - If the number of selected entries is null the function returns -1
3039///
3040/// new implementation using new Fitter classes
3041
3042Int_t TTreePlayer::UnbinnedFit(const char *funcname ,const char *varexp, const char *selection,Option_t *option ,Long64_t nentries, Long64_t firstentry)
3043{
3044 // function is given by name, find it in gROOT
3045 TF1* fitfunc = (TF1*)gROOT->GetFunction(funcname);
3046 if (!fitfunc) { Error("UnbinnedFit", "Unknown function: %s",funcname); return 0; }
3047
3048 Int_t npar = fitfunc->GetNpar();
3049 if (npar <=0) { Error("UnbinnedFit", "Illegal number of parameters = %d",npar); return 0; }
3050
3051 // Spin through the data to select out the events of interest
3052 // Make sure that the arrays V1,etc are created large enough to accommodate
3053 // all entries
3054 Long64_t oldEstimate = fTree->GetEstimate();
3057
3058 // build FitOptions
3059 TString opt = option;
3060 opt.ToUpper();
3061 Foption_t fitOption;
3062 if (opt.Contains("Q")) fitOption.Quiet = 1;
3063 if (opt.Contains("V")){fitOption.Verbose = 1; fitOption.Quiet = 0;}
3064 if (opt.Contains("E")) fitOption.Errors = 1;
3065 if (opt.Contains("M")) fitOption.More = 1;
3066 if (!opt.Contains("D")) fitOption.Nograph = 1; // what about 0
3067 // could add range and automatic normalization of functions and gradient
3068
3069 TString drawOpt = "goff";
3070 if (!fitOption.Nograph) drawOpt = "";
3071 Long64_t nsel = DrawSelect(varexp, selection,drawOpt, nentries, firstentry);
3072
3073 if (!fitOption.Nograph && GetSelectedRows() <= 0 && GetDimension() > 4) {
3074 Info("UnbinnedFit","Ignore option D with more than 4 variables");
3075 nsel = DrawSelect(varexp, selection,"goff", nentries, firstentry);
3076 }
3077
3078 //if no selected entries return
3079 Long64_t nrows = GetSelectedRows();
3080
3081 if (nrows <= 0) {
3082 Error("UnbinnedFit", "Cannot fit: no entries selected");
3083 return -1;
3084 }
3085
3086 // Check that function has same dimension as number of variables
3087 Int_t ndim = GetDimension();
3088 // do not check with TF1::GetNdim() since it returns 1 for TF1 classes created with
3089 // a C function with larger dimension
3090
3091
3092 // use pointer stored in the tree (not copy the data in)
3093 std::vector<double *> vlist(ndim);
3094 for (int i = 0; i < ndim; ++i)
3095 vlist[i] = fSelector->GetVal(i);
3096
3097 // fill the fit data object
3098 // the object will be then managed by the fitted classes - however it will be invalid when the
3099 // data pointers (given by fSelector->GetVal() ) wil be invalidated
3100 ROOT::Fit::UnBinData * fitdata = new ROOT::Fit::UnBinData(nrows, ndim, vlist.begin());
3101
3102
3103
3105 TFitResultPtr ret = ROOT::Fit::UnBinFit(fitdata,fitfunc, fitOption, minOption);
3106
3107 //reset estimate
3108 fTree->SetEstimate(oldEstimate);
3109
3110 //if option "D" is specified, draw the projected histogram
3111 //with the fitted function normalized to the number of selected rows
3112 //and multiplied by the bin width
3113 if (!fitOption.Nograph && fHistogram) {
3114 if (fHistogram->GetDimension() < 2) {
3115 TH1 *hf = (TH1*)fHistogram->Clone("unbinnedFit");
3116 hf->SetLineWidth(3);
3117 hf->Reset();
3118 Int_t nbins = fHistogram->GetXaxis()->GetNbins();
3119 Double_t norm = ((Double_t)nsel)*fHistogram->GetXaxis()->GetBinWidth(1);
3120 for (Int_t bin=1;bin<=nbins;bin++) {
3121 Double_t func = norm*fitfunc->Eval(hf->GetBinCenter(bin));
3122 hf->SetBinContent(bin,func);
3123 }
3124 fHistogram->GetListOfFunctions()->Add(hf,"lsame");
3125 }
3126 fHistogram->Draw();
3127 }
3128
3129
3130 return int(ret);
3131
3132}
3133
3134////////////////////////////////////////////////////////////////////////////////
3135/// this function is called by TChain::LoadTree when a new Tree is loaded.
3136/// Because Trees in a TChain may have a different list of leaves, one
3137/// must update the leaves numbers in the TTreeFormula used by the TreePlayer.
3138
3140{
3141 if (fSelector) fSelector->Notify();
3142 if (fSelectorUpdate){
3143 //If the selector is writing into a TEntryList, the entry list's
3144 //sublists need to be changed according to the loaded tree
3146 //FIXME: should be more consistent with selector from file
3147 TObject *obj = fSelector->GetObject();
3148 if (obj){
3151 }
3152 }
3153 }
3156 TEntryList *elist=0;
3157 while ((elist=(TEntryList*)next())){
3158 if (elist->InheritsFrom(TEntryList::Class())){
3159 elist->SetTree(fTree->GetTree());
3160 }
3161 }
3162 }
3163 }
3164
3165 if (fFormulaList->GetSize()) {
3167 while (lnk) {
3168 lnk->GetObject()->Notify();
3169 lnk = lnk->Next();
3170 }
3171 }
3172}
void Class()
Definition: Class.C:29
#define R__EXTERN
Definition: DllImport.h:27
#define h(i)
Definition: RSha256.hxx:106
const Ssiz_t kNPOS
Definition: RtypesCore.h:124
int Int_t
Definition: RtypesCore.h:45
int Ssiz_t
Definition: RtypesCore.h:67
unsigned int UInt_t
Definition: RtypesCore.h:46
const Bool_t kFALSE
Definition: RtypesCore.h:101
bool Bool_t
Definition: RtypesCore.h:63
double Double_t
Definition: RtypesCore.h:59
long long Long64_t
Definition: RtypesCore.h:80
const Bool_t kTRUE
Definition: RtypesCore.h:100
const char Option_t
Definition: RtypesCore.h:66
#define ClassImp(name)
Definition: Rtypes.h:364
R__EXTERN TApplication * gApplication
Definition: TApplication.h:165
#define gDirectory
Definition: TDirectory.h:348
int nentries
Definition: THbookFile.cxx:91
R__EXTERN TVirtualMutex * gROOTMutex
Definition: TROOT.h:61
#define gROOT
Definition: TROOT.h:404
char * Form(const char *fmt,...)
void Printf(const char *fmt,...)
R__EXTERN TStyle * gStyle
Definition: TStyle.h:413
R__EXTERN TSystem * gSystem
Definition: TSystem.h:559
TVirtualFitter * tFitter
Definition: TTreePlayer.cxx:91
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
Definition: TTreePlayer.cxx:89
R__EXTERN TVirtualMonitoringWriter * gMonitoringWriter
#define R__LOCKGUARD(mutex)
#define gPad
Definition: TVirtualPad.h:288
#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
static void CreateApplication()
void InitializeGraphics()
Initialize the graphics 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:1322
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:2044
A TChainElement describes a component of a TChain.
Definition: TChainElement.h:28
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:1314
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:1070
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:6637
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:5905
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:4592
const char * GetDeclFileName() const
Return name of the file containing the declaration of this class.
Definition: TClass.cxx:3416
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:2955
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.
Definition: TCollection.h:184
This class stores the date and time with a precision of one second in an unsigned 32 bit word (950130...
Definition: TDatime.h:37
const char * AsString() const
Return the date & time as a string (ctime() format).
Definition: TDatime.cxx:102
TDirectory::TContext keeps track and restore the current directory.
Definition: TDirectory.h:89
virtual const char * GetPath() const
Returns the full path of the directory.
Definition: TDirectory.cxx:996
virtual TFile * GetFile() const
Definition: TDirectory.h:211
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:77
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:1440
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:4478
TFileCacheRead * GetCacheRead(const TObject *tree=nullptr) const
Return a pointer to the current read cache.
Definition: TFile.cxx:1192
Provides an indirection to the TFitResult class and with a semantics identical to a TFitResult pointe...
Definition: TFitResultPtr.h:32
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:8984
@ kNoAxis
NOTE: Must always be 0 !!!
Definition: TH1.h:71
virtual Int_t GetDimension() const
Definition: TH1.h:282
virtual void Reset(Option_t *option="")
Reset this histogram: contents, errors, etc.
Definition: TH1.cxx:7071
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:2741
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:3893
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:9065
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:6611
TList * GetListOfFunctions() const
Definition: TH1.h:243
virtual void Draw(Option_t *option="")
Draw this histogram with options.
Definition: TH1.cxx:3074
virtual void Scale(Double_t c1=1, Option_t *option="")
Multiply this histogram by a constant c1.
Definition: TH1.cxx:6566
virtual Double_t GetSumOfWeights() const
Return the sum of weights excluding under/overflows.
Definition: TH1.cxx:7805
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:5178
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.
Definition: TObjArray.cxx:506
Int_t GetEntries() const
Return the number of objects in array (i.e.
Definition: TObjArray.cxx:523
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.
Definition: TObjArray.cxx:356
virtual TObject * FindObject(const char *name) const
Find an object in this collection using its name.
Definition: TObjArray.cxx:415
virtual void AddAt(TObject *obj, Int_t idx)
Add object at position ids.
Definition: TObjArray.cxx:254
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
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
A 3D polymarker.
Definition: TPolyMarker3D.h:33
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:91
A container proxy, which allows to access references stored in a TRefArray from TTree::Draw.
A specialized TSelector for TTree::Draw.
Definition: TSelectorDraw.h:33
virtual void SetEstimate(Long64_t n)
Set number of entries to estimate variable limits.
TTreeFormula * GetVar3() const
See TSelectorDraw::GetVar.
Definition: TSelectorDraw.h:97
virtual Long64_t GetDrawFlag() const
Definition: TSelectorDraw.h:83
TH1 * GetOldHistogram() const
Definition: TSelectorDraw.h:87
virtual UInt_t SplitNames(const TString &varexp, std::vector< TString > &names)
Build Index array for names in varexp.
TObject * GetObject() const
Definition: TSelectorDraw.h:84
virtual Bool_t GetCleanElist() const
Definition: TSelectorDraw.h:81
TTreeFormula * GetVar2() const
See TSelectorDraw::GetVar.
Definition: TSelectorDraw.h:95
virtual Int_t GetAction() const
Definition: TSelectorDraw.h:80
TTreeFormula * GetVar1() const
See TSelectorDraw::GetVar.
Definition: TSelectorDraw.h:93
virtual Int_t GetDimension() const
Definition: TSelectorDraw.h:82
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.
A TSelector object is used by the TTree::Draw, TTree::Scan, TTree::Process to navigate in a TTree and...
Definition: TSelector.h:31
virtual EAbort GetAbort() const
Definition: TSelector.h:73
virtual void ProcessFill(Long64_t)
This method is called for all selected entries.
Definition: TSelector.cxx:330
@ kAbortFile
Definition: TSelector.h:34
@ 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)
The Process() function is called for each entry in the tree (or possibly keyed object in the case of ...
Definition: TSelector.cxx:360
virtual void SlaveBegin(TTree *)
Definition: TSelector.h:55
virtual Bool_t ProcessCut(Long64_t)
This method is called before processing entry.
Definition: TSelector.cxx:313
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...
Definition: TSelector.cxx:142
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:1150
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:916
void ToUpper()
Change string to upper case.
Definition: TString.cxx:1163
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:2314
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:967
virtual TString SplitAclicMode(const char *filename, TString &mode, TString &args, TString &io) const
This method split a filename of the form:
Definition: TSystem.cxx:4241
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.
Definition: TTreeFormula.h:58
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
Definition: TTreeFormula.h:189
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
! input list to the selector
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 current selector
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)
Return name corresponding to colindex in varexp.
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
Number of selected entries.
Definition: TTreePlayer.h:48
TSelector * fSelectorFromFile
! Pointer to a user defined selector created by this TTreePlayer object
Definition: TTreePlayer.h:51
const char * fScanFileName
Name of the file where Scan is redirected.
Definition: TTreePlayer.h:46
TList * fFormulaList
! Pointer to a list of coordinated list TTreeFormula (used by Scan and Query)
Definition: TTreePlayer.h:54
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
! Pointer to current Tree
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
! Set to the selector address when it's entry list needs to be updated by the UpdateFormulaLeaves fun...
Definition: TTreePlayer.h:55
TH1 * fHistogram
! Pointer to histogram used for the projection
Definition: TTreePlayer.h:49
virtual void StartViewer(Int_t ww, Int_t wh)
Start the TTreeViewer on this TTree.
Bool_t fScanRedirect
Switch to redirect TTree::Scan output to a file.
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 the actual class of the TSelectorFromFile
Definition: TTreePlayer.h:52
virtual void SetTree(TTree *t)
Definition: TTreePlayer.h:124
virtual TVirtualIndex * BuildIndex(const TTree *T, const char *majorname, const char *minorname)
Build the index for the tree (see TTree::BuildIndex)
Int_t fDimension
Dimension of the current expression.
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.
Definition: TTreePlayer.cxx:98
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:5257
virtual Int_t GetScanField() const
Definition: TTree.h:507
virtual Int_t GetEntry(Long64_t entry, Int_t getall=0)
Read all branches of entry and return total number of bytes read.
Definition: TTree.cxx:5606
virtual Long64_t GetEstimate() const
Definition: TTree.h:463
virtual TObjArray * GetListOfLeaves()
Definition: TTree.h:485
TFile * GetCurrentFile() const
Return pointer to the current file.
Definition: TTree.cxx:5447
TDirectory * GetDirectory() const
Definition: TTree.h:458
virtual TEntryList * GetEntryList()
Returns the entry list assigned to this tree.
Definition: TTree.cxx:5822
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:7418
virtual Long64_t GetEntries() const
Definition: TTree.h:459
virtual void SetEstimate(Long64_t nentries=1000000)
Set number of entries to estimate variable limits.
Definition: TTree.cxx:9060
virtual Long64_t GetEntryNumber(Long64_t entry) const
Return entry number corresponding to entry.
Definition: TTree.cxx:5833
virtual TTree * CloneTree(Long64_t nentries=-1, Option_t *option="")
Create a clone of this tree and copy nentries.
Definition: TTree.cxx:3110
virtual TTree * GetTree() const
Definition: TTree.h:513
virtual void SetEntryList(TEntryList *list, Option_t *opt="")
Set an EntryList.
Definition: TTree.cxx:8996
virtual Long64_t LoadTree(Long64_t entry)
Set current entry.
Definition: TTree.cxx:6441
virtual void SetNotify(TObject *obj)
Sets the address of the object to be notified when the tree is loaded.
Definition: TTree.h:634
TEventList * GetEventList() const
Definition: TTree.h:469
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:5480
virtual Int_t GetTreeNumber() const
Definition: TTree.h:515
virtual void Draw(Option_t *opt)
Default Draw method for all objects.
Definition: TTree.h:428
virtual Int_t GetTimerInterval() const
Definition: TTree.h:510
virtual void SetScanField(Int_t n=50)
Definition: TTree.h:639
virtual Long64_t GetCacheSize() const
Definition: TTree.h:449
virtual Int_t SetCacheSize(Long64_t cachesize=-1)
Set maximum size of the file cache .
Definition: TTree.cxx:8636
virtual Long64_t GetMaxEntryLoop() const
Definition: TTree.h:493
Abstract Base Class for Fitting.
Abstract interface for Tree Index.
Definition: TVirtualIndex.h:30
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
double T(double x)
Definition: ChebyshevPol.h:34
Type GetType(const std::string &Name)
Definition: Systematics.cxx:34
static constexpr double s
Short_t Max(Short_t a, Short_t b)
Definition: TMathBase.h:208
Short_t Min(Short_t a, Short_t b)
Definition: TMathBase.h:176
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