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