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