Logo ROOT  
Reference Guide
TTreePlayer.cxx
Go to the documentation of this file.
1// @(#)root/treeplayer:$Id$
2// Author: Rene Brun 12/01/96
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12/** \class TTreePlayer
13
14Implement some of the functionality of the class TTree requiring access to
15extra libraries (Histogram, display, etc).
16*/
17
18#include "TTreePlayer.h"
19
20#include <cstring>
21#include <cstdio>
22#include <cstdlib>
23#include <iostream>
24#include <fstream>
25
26#include "TROOT.h"
27#include "TApplication.h"
28#include "TSystem.h"
29#include "TFile.h"
30#include "TEnv.h"
31#include "TEventList.h"
32#include "TEntryList.h"
33#include "TBranchObject.h"
34#include "TBranchElement.h"
35#include "TStreamerInfo.h"
36#include "TStreamerElement.h"
37#include "TLeafObject.h"
38#include "TLeafF.h"
39#include "TLeafD.h"
40#include "TLeafC.h"
41#include "TLeafB.h"
42#include "TLeafI.h"
43#include "TLeafS.h"
44#include "TMath.h"
45#include "TH1.h"
46#include "TPolyMarker.h"
47#include "TPolyMarker3D.h"
48#include "TText.h"
49#include "TDirectory.h"
50#include "TClonesArray.h"
51#include "TClass.h"
52#include "TVirtualPad.h"
53#include "TProfile.h"
54#include "TProfile2D.h"
55#include "TTreeFormula.h"
56#include "TTreeFormulaManager.h"
57#include "TStyle.h"
58#include "Foption.h"
59#include "TTreeResult.h"
60#include "TTreeRow.h"
61#include "TPrincipal.h"
62#include "TChain.h"
63#include "TChainElement.h"
64#include "TF1.h"
65#include "TVirtualFitter.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 "TVirtualMutex.h"
80#include "ThreadLocalStorage.h"
81#include "strlcpy.h"
82#include "snprintf.h"
83
84#include "HFitInterface.h"
85#include "Fit/BinData.h"
86#include "Fit/UnBinData.h"
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{
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,
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%zx,(TEntryList*)0x%zx)",
527 (size_t)para, (size_t)enlist));
528 }
529 //*-*- 5d with gl
530 } else if (fDimension == 5 && optgl5d) {
531 gROOT->ProcessLineFast(Form("(new TGL5DDataSet((TTree *)0x%zx))->Draw(\"%s\");", (size_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
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/// ~~~
1976{
1977 if (!classname) classname = fTree->GetName();
1978
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
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);
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 const char *fname = nullptr;
2536 TString fownname;
2537 if (fScanRedirect) {
2538 fTree->SetScanField(0); // no page break if Scan is redirected
2539 fname = fScanFileName;
2540 if (!fname) fname = "";
2541 Int_t lenfile = strlen(fname);
2542 if (!lenfile) {
2543 fownname = fTree->GetName();
2544 fownname.Append("-scan.dat");
2545 fname = fownname.Data();
2546 }
2547 out.open(fname, std::ios::out);
2548 if (!out.good ()) {
2549 Error("Scan","Can not open file for redirection");
2550 return 0;
2551 }
2552 }
2553 TObjArray *leaves = fTree->GetListOfLeaves();
2554 if (leaves==0) return 0;
2555 UInt_t nleaves = leaves->GetEntriesFast();
2556 if (nleaves < ncols) ncols = nleaves;
2557 nch = varexp ? strlen(varexp) : 0;
2558
2559 nentries = GetEntriesToProcess(firstentry, nentries);
2560
2561//*-*- Compile selection expression if there is one
2562 TTreeFormula *select = 0;
2563 if (selection && strlen(selection)) {
2564 select = new TTreeFormula("Selection",selection,fTree);
2565 if (!select) return -1;
2566 if (!select->GetNdim()) { delete select; return -1; }
2567 fFormulaList->Add(select);
2568 }
2569//*-*- if varexp is empty, take first 8 columns by default
2570 int allvar = 0;
2571 if (varexp && !strcmp(varexp, "*")) { ncols = nleaves; allvar = 1; }
2572 if (nch == 0 || allvar) {
2573 UInt_t ncs = ncols;
2574 ncols = 0;
2575 for (ui=0;ui<ncs;++ui) {
2576 TLeaf *lf = (TLeaf*)leaves->At(ui);
2577 if (lf->GetBranch()->GetListOfBranches()->GetEntries() > 0) continue;
2578 cnames.push_back( lf->GetBranch()->GetMother()->GetName() );
2579 if (cnames[ncols] == lf->GetName() ) {
2580 // Already complete, let move on.
2581 } else if (cnames[ncols][cnames[ncols].Length()-1]=='.') {
2582 cnames[ncols] = lf->GetBranch()->GetName(); // name of branch already include mother's name
2583 } else {
2585 TBranchElement *mother = (TBranchElement*)lf->GetBranch()->GetMother();
2586 if (mother->GetType() == 3 || mother->GetType() == 4) {
2587 // The name of the mother branch is embedded in the sub-branch names.
2588 cnames[ncols] = lf->GetBranch()->GetName();
2589 ++ncols;
2590 continue;
2591 }
2592 }
2593 if (!strchr(lf->GetBranch()->GetName() ,'[') ) {
2594 cnames[ncols].Append('.');
2595 cnames[ncols].Append( lf->GetBranch()->GetName() );
2596 }
2597 }
2598 if (lf->GetBranch()->IsA() == TBranch::Class() ||
2599 strcmp( lf->GetBranch()->GetName(), lf->GetName() ) != 0 ) {
2600 cnames[ncols].Append('.');
2601 cnames[ncols].Append( lf->GetName() );
2602 }
2603 ++ncols;
2604 }
2605//*-*- otherwise select only the specified columns
2606 } else {
2607
2608 ncols = fSelector->SplitNames(varexp, cnames);
2609
2610 }
2611 var = new TTreeFormula* [ncols];
2612
2613 for(ui=colFormats.size();ui<ncols;++ui) {
2614 colFormats.push_back(defFormat);
2615 colSizes.push_back(colDefaultSize);
2616 }
2617
2618//*-*- Create the TreeFormula objects corresponding to each column
2619 for (ui=0;ui<ncols;ui++) {
2620 var[ui] = new TTreeFormula("Var1",cnames[ui].Data(),fTree);
2621 fFormulaList->Add(var[ui]);
2622 }
2623
2624//*-*- Create a TreeFormulaManager to coordinate the formulas
2625 TTreeFormulaManager *manager=0;
2626 Bool_t hasArray = kFALSE;
2627 Bool_t forceDim = kFALSE;
2628 if (fFormulaList->LastIndex()>=0) {
2629 if (select) {
2630 if (select->GetManager()->GetMultiplicity() > 0 ) {
2631 manager = new TTreeFormulaManager;
2632 for(i=0;i<=fFormulaList->LastIndex();i++) {
2633 manager->Add((TTreeFormula*)fFormulaList->At(i));
2634 }
2635 manager->Sync();
2636 }
2637 }
2638 for(i=0;i<=fFormulaList->LastIndex();i++) {
2639 TTreeFormula *form = ((TTreeFormula*)fFormulaList->At(i));
2640 switch( form->GetManager()->GetMultiplicity() ) {
2641 case 1:
2642 case 2:
2643 hasArray = kTRUE;
2644 forceDim = kTRUE;
2645 break;
2646 case -1:
2647 forceDim = kTRUE;
2648 break;
2649 case 0:
2650 break;
2651 }
2652
2653 }
2654 }
2655
2656//*-*- Print header
2657 onerow = "***********";
2658 if (hasArray) onerow += "***********";
2659
2660 for (ui=0;ui<ncols;ui++) {
2661 TString starFormat = Form("*%%%d.%ds",colSizes[ui]+2,colSizes[ui]+2);
2662 onerow += Form(starFormat.Data(),var[ui]->PrintValue(-2));
2663 }
2664 if (fScanRedirect)
2665 out<<onerow.Data()<<"*"<<std::endl;
2666 else
2667 printf("%s*\n",onerow.Data());
2668 onerow = "* Row ";
2669 if (hasArray) onerow += "* Instance ";
2670 for (ui=0;ui<ncols;ui++) {
2671 TString numbFormat = Form("* %%%d.%ds ",colSizes[ui],colSizes[ui]);
2672 onerow += Form(numbFormat.Data(),var[ui]->PrintValue(-1));
2673 }
2674 if (fScanRedirect)
2675 out<<onerow.Data()<<"*"<<std::endl;
2676 else
2677 printf("%s*\n",onerow.Data());
2678 onerow = "***********";
2679 if (hasArray) onerow += "***********";
2680 for (ui=0;ui<ncols;ui++) {
2681 TString starFormat = Form("*%%%d.%ds",colSizes[ui]+2,colSizes[ui]+2);
2682 onerow += Form(starFormat.Data(),var[ui]->PrintValue(-2));
2683 }
2684 if (fScanRedirect)
2685 out<<onerow.Data()<<"*"<<std::endl;
2686 else
2687 printf("%s*\n",onerow.Data());
2688//*-*- loop on all selected entries
2689 fSelectedRows = 0;
2690 Int_t tnumber = -1;
2691 Bool_t exitloop = kFALSE;
2692 for (entry=firstentry;
2693 entry<(firstentry+nentries) && !exitloop;
2694 entry++) {
2695 entryNumber = fTree->GetEntryNumber(entry);
2696 if (entryNumber < 0) break;
2697 Long64_t localEntry = fTree->LoadTree(entryNumber);
2698 if (localEntry < 0) break;
2699 if (tnumber != fTree->GetTreeNumber()) {
2700 tnumber = fTree->GetTreeNumber();
2701 if (manager) manager->UpdateFormulaLeaves();
2702 else {
2703 for(i=0;i<=fFormulaList->LastIndex();i++) {
2705 }
2706 }
2707 }
2708
2709 int ndata = 1;
2710 if (forceDim) {
2711
2712 if (manager) {
2713
2714 ndata = manager->GetNdata(kTRUE);
2715
2716 } else {
2717
2718 // let's print the max number of column
2719 for (ui=0;ui<ncols;ui++) {
2720 if (ndata < var[ui]->GetNdata() ) {
2721 ndata = var[ui]->GetNdata();
2722 }
2723 }
2724 if (select && select->GetNdata()==0) ndata = 0;
2725 }
2726
2727 }
2728
2729 if (lenmax && ndata>(int)lenmax) ndata = lenmax;
2730 Bool_t loaded = kFALSE;
2731 for(int inst=0;inst<ndata;inst++) {
2732 if (select) {
2733 if (select->EvalInstance(inst) == 0) {
2734 continue;
2735 }
2736 }
2737 if (inst==0) loaded = kTRUE;
2738 else if (!loaded) {
2739 // EvalInstance(0) always needs to be called so that
2740 // the proper branches are loaded.
2741 for (ui=0;ui<ncols;ui++) {
2742 var[ui]->EvalInstance(0);
2743 }
2744 loaded = kTRUE;
2745 }
2746 onerow = Form("* %8lld ",entryNumber);
2747 if (hasArray) {
2748 onerow += Form("* %8d ",inst);
2749 }
2750 for (ui=0;ui<ncols;++ui) {
2751 TString numbFormat = Form("* %%%d.%ds ",colSizes[ui],colSizes[ui]);
2752 if (var[ui]->GetNdim()) onerow += Form(numbFormat.Data(),var[ui]->PrintValue(0,inst,colFormats[ui].Data()));
2753 else {
2754 TString emptyForm = Form("* %%%dc ",colSizes[ui]);
2755 onerow += Form(emptyForm.Data(),' ');
2756 }
2757 }
2758 fSelectedRows++;
2759 if (fScanRedirect)
2760 out<<onerow.Data()<<"*"<<std::endl;
2761 else
2762 printf("%s*\n",onerow.Data());
2763 if (fTree->GetScanField() > 0 && fSelectedRows > 0) {
2764 if (fSelectedRows%fTree->GetScanField() == 0) {
2765 fprintf(stderr,"Type <CR> to continue or q to quit ==> ");
2766 int answer, readch;
2767 readch = getchar();
2768 answer = readch;
2769 while (readch != '\n' && readch != EOF) readch = getchar();
2770 if (answer == 'q' || answer == 'Q') {
2771 exitloop = kTRUE;
2772 break;
2773 }
2774 }
2775 }
2776 }
2777 }
2778 onerow = "***********";
2779 if (hasArray) onerow += "***********";
2780 for (ui=0;ui<ncols;ui++) {
2781 TString starFormat = Form("*%%%d.%ds",colSizes[ui]+2,colSizes[ui]+2);
2782 onerow += Form(starFormat.Data(),var[ui]->PrintValue(-2));
2783 }
2784 if (fScanRedirect)
2785 out<<onerow.Data()<<"*"<<std::endl;
2786 else
2787 printf("%s*\n",onerow.Data());
2788 if (select) Printf("==> %lld selected %s", fSelectedRows,
2789 fSelectedRows == 1 ? "entry" : "entries");
2790 if (fScanRedirect) printf("File <%s> created\n", fname);
2791
2792//*-*- delete temporary objects
2794 // The TTreeFormulaManager is deleted by the last TTreeFormula.
2795 delete [] var;
2796 return fSelectedRows;
2797}
2798
2799////////////////////////////////////////////////////////////////////////////////
2800/// Loop on Tree and return TSQLResult object containing entries passing
2801/// selection. If varexp is 0 (or "") then print only first 8 columns.
2802/// If varexp = "*" print all columns. Otherwise a columns selection can
2803/// be made using "var1:var2:var3". In case of error 0 is returned otherwise
2804/// a TSQLResult object which must be deleted by the user.
2805
2806TSQLResult *TTreePlayer::Query(const char *varexp, const char *selection,
2807 Option_t *, Long64_t nentries, Long64_t firstentry)
2808{
2809 TTreeFormula **var;
2810 std::vector<TString> cnames;
2811 TString onerow;
2812 Long64_t entry,entryNumber;
2813 Int_t i,nch;
2814 Int_t ncols = 8; // by default first 8 columns are printed only
2815 TObjArray *leaves = fTree->GetListOfLeaves();
2816 Int_t nleaves = leaves->GetEntriesFast();
2817 if (nleaves < ncols) ncols = nleaves;
2818 nch = varexp ? strlen(varexp) : 0;
2819
2820 nentries = GetEntriesToProcess(firstentry, nentries);
2821
2822 // compile selection expression if there is one
2823 TTreeFormula *select = 0;
2824 if (strlen(selection)) {
2825 select = new TTreeFormula("Selection",selection,fTree);
2826 if (!select) return 0;
2827 if (!select->GetNdim()) { delete select; return 0; }
2828 fFormulaList->Add(select);
2829 }
2830
2831 // if varexp is empty, take first 8 columns by default
2832 int allvar = 0;
2833 if (varexp && !strcmp(varexp, "*")) { ncols = nleaves; allvar = 1; }
2834 if (nch == 0 || allvar) {
2835 for (i=0;i<ncols;i++) {
2836 cnames.push_back( ((TLeaf*)leaves->At(i))->GetName() );
2837 }
2838 } else {
2839 // otherwise select only the specified columns
2840 ncols = fSelector->SplitNames(varexp,cnames);
2841 }
2842 var = new TTreeFormula* [ncols];
2843
2844 // create the TreeFormula objects corresponding to each column
2845 for (i=0;i<ncols;i++) {
2846 var[i] = new TTreeFormula("Var1",cnames[i].Data(),fTree);
2847 fFormulaList->Add(var[i]);
2848 }
2849
2850 // fill header info into result object
2851 TTreeResult *res = new TTreeResult(ncols);
2852 for (i = 0; i < ncols; i++) {
2853 res->AddField(i, var[i]->PrintValue(-1));
2854 }
2855
2856 //*-*- Create a TreeFormulaManager to coordinate the formulas
2857 TTreeFormulaManager *manager=0;
2858 if (fFormulaList->LastIndex()>=0) {
2859 manager = new TTreeFormulaManager;
2860 for(i=0;i<=fFormulaList->LastIndex();i++) {
2861 manager->Add((TTreeFormula*)fFormulaList->At(i));
2862 }
2863 manager->Sync();
2864 }
2865
2866 // loop on all selected entries
2867 const char *aresult;
2868 Int_t len;
2869 char *arow = new char[ncols*50];
2870 fSelectedRows = 0;
2871 Int_t tnumber = -1;
2872 Int_t *fields = new Int_t[ncols];
2873 for (entry=firstentry;entry<firstentry+nentries;entry++) {
2874 entryNumber = fTree->GetEntryNumber(entry);
2875 if (entryNumber < 0) break;
2876 Long64_t localEntry = fTree->LoadTree(entryNumber);
2877 if (localEntry < 0) break;
2878 if (tnumber != fTree->GetTreeNumber()) {
2879 tnumber = fTree->GetTreeNumber();
2880 for (i=0;i<ncols;i++) var[i]->UpdateFormulaLeaves();
2881 }
2882
2883 Int_t ndata = 1;
2884 if (manager && manager->GetMultiplicity()) {
2885 ndata = manager->GetNdata();
2886 }
2887
2888 if (select) {
2889 select->GetNdata();
2890 if (select->EvalInstance(0) == 0) continue;
2891 }
2892
2893 Bool_t loaded = kFALSE;
2894 for(int inst=0;inst<ndata;inst++) {
2895 if (select) {
2896 if (select->EvalInstance(inst) == 0) {
2897 continue;
2898 }
2899 }
2900
2901 if (inst==0) loaded = kTRUE;
2902 else if (!loaded) {
2903 // EvalInstance(0) always needs to be called so that
2904 // the proper branches are loaded.
2905 for (i=0;i<ncols;i++) {
2906 var[i]->EvalInstance(0);
2907 }
2908 loaded = kTRUE;
2909 }
2910 for (i=0;i<ncols;i++) {
2911 aresult = var[i]->PrintValue(0,inst);
2912 len = strlen(aresult)+1;
2913 if (i == 0) {
2914 memcpy(arow,aresult,len);
2915 fields[i] = len;
2916 } else {
2917 memcpy(arow+fields[i-1],aresult,len);
2918 fields[i] = fields[i-1] + len;
2919 }
2920 }
2921 res->AddRow(new TTreeRow(ncols,fields,arow));
2922 fSelectedRows++;
2923 }
2924 }
2925
2926 // delete temporary objects
2928 // The TTreeFormulaManager is deleted by the last TTreeFormula.
2929 delete [] fields;
2930 delete [] arow;
2931 delete [] var;
2932
2933 return res;
2934}
2935
2936////////////////////////////////////////////////////////////////////////////////
2937/// Set number of entries to estimate variable limits.
2938
2940{
2942}
2943
2944////////////////////////////////////////////////////////////////////////////////
2945/// Start the TTreeViewer on this TTree.
2946///
2947/// - ww is the width of the canvas in pixels
2948/// - wh is the height of the canvas in pixels
2949
2951{
2952 // unused variables
2953 (void) ww;
2954 (void) wh;
2955
2956 if (!gApplication)
2958 // make sure that the Gpad and GUI libs are loaded
2960 if (gApplication)
2962
2963 TString hname = gEnv->GetValue("TreeViewer.Name", "TTreeViewer");
2964
2965 if (gROOT->IsBatch()) {
2966 if ((hname != "RTreeViewer") || (gROOT->GetWebDisplay() != "server")) {
2967 Warning("StartViewer", "The tree viewer cannot run in batch mode");
2968 return;
2969 }
2970 }
2971
2972 if (auto h = gROOT->GetPluginManager()->FindHandler("TVirtualTreeViewer", hname.Data())) {
2973 if (h->LoadPlugin() != -1)
2974 h->ExecPlugin(1, fTree);
2975 }
2976}
2977
2978////////////////////////////////////////////////////////////////////////////////
2979/// Unbinned fit of one or more variable(s) from a Tree.
2980///
2981/// funcname is a TF1 function.
2982///
2983/// See TTree::Draw for explanations of the other parameters.
2984///
2985/// Fit the variable varexp using the function funcname using the
2986/// selection cuts given by selection.
2987///
2988/// The list of fit options is given in parameter option.
2989///
2990/// - option = "Q" Quiet mode (minimum printing)
2991/// - option = "V" Verbose mode (default is between Q and V)
2992/// - option = "E" Perform better Errors estimation using Minos technique
2993/// - option = "M" More. Improve fit results
2994/// - option = "D" Draw the projected histogram with the fitted function
2995/// normalized to the number of selected rows
2996/// and multiplied by the bin width
2997///
2998/// You can specify boundary limits for some or all parameters via
2999/// ~~~{.cpp}
3000/// func->SetParLimits(p_number, parmin, parmax);
3001/// ~~~
3002/// if parmin>=parmax, the parameter is fixed
3003///
3004/// Note that you are not forced to fix the limits for all parameters.
3005/// For example, if you fit a function with 6 parameters, you can do:
3006/// ~~~{.cpp}
3007/// func->SetParameters(0,3.1,1.e-6,0.1,-8,100);
3008/// func->SetParLimits(4,-10,-4);
3009/// func->SetParLimits(5, 1,1);
3010/// ~~~
3011/// With this setup, parameters 0->3 can vary freely
3012/// - Parameter 4 has boundaries [-10,-4] with initial value -8
3013/// - Parameter 5 is fixed to 100.
3014///
3015/// For the fit to be meaningful, the function must be self-normalized.
3016///
3017/// i.e. It must have the same integral regardless of the parameter
3018/// settings. Otherwise the fit will effectively just maximize the
3019/// area.
3020///
3021/// It is mandatory to have a normalization variable
3022/// which is fixed for the fit. e.g.
3023/// ~~~{.cpp}
3024/// TF1* f1 = new TF1("f1", "gaus(0)/sqrt(2*3.14159)/[2]", 0, 5);
3025/// f1->SetParameters(1, 3.1, 0.01);
3026/// f1->SetParLimits(0, 1, 1); // fix the normalization parameter to 1
3027/// data->UnbinnedFit("f1", "jpsimass", "jpsipt>3.0");
3028/// ~~~
3029///
3030/// 1, 2 and 3 Dimensional fits are supported.
3031/// See also TTree::Fit
3032///
3033/// ### Return status
3034///
3035/// The function return the status of the fit in the following form
3036/// ~~~{.cpp}
3037/// fitResult = migradResult + 10*minosResult + 100*hesseResult + 1000*improveResult
3038/// ~~~
3039/// - The fitResult is 0 is the fit is OK.
3040/// - The fitResult is negative in case of an error not connected with the fit.
3041/// - The number of entries used in the fit can be obtained via
3042/// ~~~{.cpp}
3043/// mytree.GetSelectedRows();
3044/// ~~~
3045/// - If the number of selected entries is null the function returns -1
3046///
3047/// new implementation using new Fitter classes
3048
3049Int_t TTreePlayer::UnbinnedFit(const char *funcname ,const char *varexp, const char *selection,Option_t *option ,Long64_t nentries, Long64_t firstentry)
3050{
3051 // function is given by name, find it in gROOT
3052 TF1* fitfunc = (TF1*)gROOT->GetFunction(funcname);
3053 if (!fitfunc) { Error("UnbinnedFit", "Unknown function: %s",funcname); return 0; }
3054
3055 Int_t npar = fitfunc->GetNpar();
3056 if (npar <=0) { Error("UnbinnedFit", "Illegal number of parameters = %d",npar); return 0; }
3057
3058 // Spin through the data to select out the events of interest
3059 // Make sure that the arrays V1,etc are created large enough to accommodate
3060 // all entries
3061 Long64_t oldEstimate = fTree->GetEstimate();
3064
3065 // build FitOptions
3066 TString opt = option;
3067 opt.ToUpper();
3068 Foption_t fitOption;
3069 if (opt.Contains("Q")) fitOption.Quiet = 1;
3070 if (opt.Contains("V")){fitOption.Verbose = 1; fitOption.Quiet = 0;}
3071 if (opt.Contains("E")) fitOption.Errors = 1;
3072 if (opt.Contains("M")) fitOption.More = 1;
3073 if (!opt.Contains("D")) fitOption.Nograph = 1; // what about 0
3074 // could add range and automatic normalization of functions and gradient
3075
3076 TString drawOpt = "goff";
3077 if (!fitOption.Nograph) drawOpt = "";
3078 Long64_t nsel = DrawSelect(varexp, selection,drawOpt, nentries, firstentry);
3079
3080 if (!fitOption.Nograph && GetSelectedRows() <= 0 && GetDimension() > 4) {
3081 Info("UnbinnedFit","Ignore option D with more than 4 variables");
3082 nsel = DrawSelect(varexp, selection,"goff", nentries, firstentry);
3083 }
3084
3085 //if no selected entries return
3086 Long64_t nrows = GetSelectedRows();
3087
3088 if (nrows <= 0) {
3089 Error("UnbinnedFit", "Cannot fit: no entries selected");
3090 return -1;
3091 }
3092
3093 // Check that function has same dimension as number of variables
3094 Int_t ndim = GetDimension();
3095 // do not check with TF1::GetNdim() since it returns 1 for TF1 classes created with
3096 // a C function with larger dimension
3097
3098
3099 // use pointer stored in the tree (not copy the data in)
3100 std::vector<double *> vlist(ndim);
3101 for (int i = 0; i < ndim; ++i)
3102 vlist[i] = fSelector->GetVal(i);
3103
3104 // fill the fit data object
3105 // the object will be then managed by the fitted classes - however it will be invalid when the
3106 // data pointers (given by fSelector->GetVal() ) wil be invalidated
3107 ROOT::Fit::UnBinData * fitdata = new ROOT::Fit::UnBinData(nrows, ndim, vlist.begin());
3108
3109
3110
3112 TFitResultPtr ret = ROOT::Fit::UnBinFit(fitdata,fitfunc, fitOption, minOption);
3113
3114 //reset estimate
3115 fTree->SetEstimate(oldEstimate);
3116
3117 //if option "D" is specified, draw the projected histogram
3118 //with the fitted function normalized to the number of selected rows
3119 //and multiplied by the bin width
3120 if (!fitOption.Nograph && fHistogram) {
3121 if (fHistogram->GetDimension() < 2) {
3122 TH1 *hf = (TH1*)fHistogram->Clone("unbinnedFit");
3123 hf->SetLineWidth(3);
3124 hf->Reset();
3125 Int_t nbins = fHistogram->GetXaxis()->GetNbins();
3126 Double_t norm = ((Double_t)nsel)*fHistogram->GetXaxis()->GetBinWidth(1);
3127 for (Int_t bin=1;bin<=nbins;bin++) {
3128 Double_t func = norm*fitfunc->Eval(hf->GetBinCenter(bin));
3129 hf->SetBinContent(bin,func);
3130 }
3131 fHistogram->GetListOfFunctions()->Add(hf,"lsame");
3132 }
3133 fHistogram->Draw();
3134 }
3135
3136
3137 return int(ret);
3138
3139}
3140
3141////////////////////////////////////////////////////////////////////////////////
3142/// this function is called by TChain::LoadTree when a new Tree is loaded.
3143/// Because Trees in a TChain may have a different list of leaves, one
3144/// must update the leaves numbers in the TTreeFormula used by the TreePlayer.
3145
3147{
3148 if (fSelector) fSelector->Notify();
3149 if (fSelectorUpdate){
3150 //If the selector is writing into a TEntryList, the entry list's
3151 //sublists need to be changed according to the loaded tree
3153 //FIXME: should be more consistent with selector from file
3154 TObject *obj = fSelector->GetObject();
3155 if (obj){
3158 }
3159 }
3160 }
3163 TEntryList *elist=0;
3164 while ((elist=(TEntryList*)next())){
3165 if (elist->InheritsFrom(TEntryList::Class())){
3166 elist->SetTree(fTree->GetTree());
3167 }
3168 }
3169 }
3170 }
3171
3172 if (fFormulaList->GetSize()) {
3174 while (lnk) {
3175 lnk->GetObject()->Notify();
3176 lnk = lnk->Next();
3177 }
3178 }
3179}
#define R__EXTERN
Definition: DllImport.h:27
#define h(i)
Definition: RSha256.hxx:106
bool Bool_t
Definition: RtypesCore.h:63
const Ssiz_t kNPOS
Definition: RtypesCore.h:124
const Bool_t kFALSE
Definition: RtypesCore.h:101
double Double_t
Definition: RtypesCore.h:59
long long Long64_t
Definition: RtypesCore.h:80
const Bool_t kTRUE
Definition: RtypesCore.h:100
const char Option_t
Definition: RtypesCore.h:66
#define ClassImp(name)
Definition: Rtypes.h:375
R__EXTERN TApplication * gApplication
Definition: TApplication.h:165
#define gDirectory
Definition: TDirectory.h:348
R__EXTERN TEnv * gEnv
Definition: TEnv.h:170
Option_t Option_t option
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char filename
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t UChar_t len
int nentries
Definition: THbookFile.cxx:91
R__EXTERN TVirtualMutex * gROOTMutex
Definition: TROOT.h:63
#define gROOT
Definition: TROOT.h:404
char * Form(const char *fmt,...)
Formats a string in a circular formatting buffer.
Definition: TString.cxx:2456
void Printf(const char *fmt,...)
Formats a string in a circular formatting buffer and prints the string.
Definition: TString.cxx:2470
R__EXTERN TStyle * gStyle
Definition: TStyle.h:414
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:288
#define snprintf
Definition: civetweb.c:1540
Class describing the un-binned data sets (just x coordinates values) of any dimensions.
Definition: UnBinData.h:46
virtual Int_t GetNdim() const
Definition: TFormula.h:237
void InitializeGraphics()
Initialize the graphics environment.
static void CreateApplication()
Static function used to create a default application environment.
static void NeedGraphicsLibs()
Static method.
virtual void SetLineWidth(Width_t lwidth)
Set the line width.
Definition: TAttLine.h:43
virtual void SetTextAlign(Short_t align=11)
Set the text alignment.
Definition: TAttText.h:42
virtual void SetTextColor(Color_t tcolor=1)
Set the text color.
Definition: TAttText.h:44
virtual void SetTextFont(Font_t tfont=62)
Set the text font.
Definition: TAttText.h:46
virtual void SetTextSize(Float_t tsize=1)
Set the text size.
Definition: TAttText.h:47
Int_t GetNbins() const
Definition: TAxis.h:121
virtual Double_t GetBinWidth(Int_t bin) const
Return bin width.
Definition: TAxis.cxx:540
A Branch for the case of an object.
static TClass * Class()
const char * GetClassName() const override
Return the name of the user class whose content is stored in this branch, if any.
Bool_t IsBranchFolder() const
Int_t GetStreamerType() const
TBranchElement * GetBranchCount2() const
Int_t GetType() const
static TClass * Class()
A TTree is a list of TBranches.
Definition: TBranch.h:89
virtual const char * GetClassName() const
Return the name of the user class whose content is stored in this branch, if any.
Definition: TBranch.cxx:1322
static TClass * Class()
TObjArray * GetListOfBranches()
Definition: TBranch.h:242
TClass * IsA() const override
Definition: TBranch.h:291
Int_t GetNleaves() const
Definition: TBranch.h:245
TObjArray * GetListOfLeaves()
Definition: TBranch.h:243
TBranch * GetMother() const
Get our top-level parent branch in the tree.
Definition: TBranch.cxx:2065
A TChainElement describes a component of a TChain.
Definition: TChainElement.h:28
A Chain Index.
Definition: TChainIndex.h:40
A chain is a collection of files containing TTree objects.
Definition: TChain.h:33
virtual Long64_t LoadTree(Long64_t entry)
Find the tree which contains entry, and set it as the current tree.
Definition: TChain.cxx:1302
static TClass * Class()
Long64_t * GetTreeOffset() const
Definition: TChain.h:120
virtual TLeaf * GetLeaf(const char *branchname, const char *leafname)
Return a pointer to the leaf name in the current tree.
Definition: TChain.cxx:1058
Int_t GetNtrees() const
Definition: TChain.h:98
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition: TClass.h:81
void AdoptReferenceProxy(TVirtualRefProxy *proxy)
Adopt the Reference proxy pointer to indicate that this class represents a reference.
Definition: TClass.cxx:6674
Bool_t HasInterpreterInfo() const
Definition: TClass.h:408
Bool_t IsLoaded() const
Return true if the shared library of this class is currently in the a process's memory.
Definition: TClass.cxx:5901
TVirtualStreamerInfo * GetStreamerInfo(Int_t version=0, Bool_t isTransient=kFALSE) const
returns a pointer to the TVirtualStreamerInfo object for version If the object does not exist,...
Definition: TClass.cxx:4588
Bool_t InheritsFrom(const char *cl) const override
Return kTRUE if this class inherits from a class with name "classname".
Definition: TClass.cxx:4863
const char * GetDeclFileName() const
Return name of the file containing the declaration of this class.
Definition: TClass.cxx:3452
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:2969
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
Definition: TCollection.h:184
This class stores the date and time with a precision of one second in an unsigned 32 bit word (950130...
Definition: TDatime.h:37
const char * AsString() const
Return the date & time as a string (ctime() format).
Definition: TDatime.cxx:102
TDirectory::TContext keeps track and restore the current directory.
Definition: TDirectory.h:89
virtual const char * GetPath() const
Returns the full path of the directory.
Definition: TDirectory.cxx:996
virtual TFile * GetFile() const
Definition: TDirectory.h:211
A List of entry numbers in a TTree or TChain.
Definition: TEntryList.h:26
static TClass * Class()
virtual void SetTree(const TTree *tree)
If a list for a tree with such name and filename exists, sets it as the current sublist If not,...
virtual Long64_t GetN() const
Definition: TEntryList.h:78
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition: TEnv.cxx:491
A TEventList object is a list of selected events (entries) in a TTree.
Definition: TEventList.h:31
1-Dim function class
Definition: TF1.h:213
virtual Int_t GetNpar() const
Definition: TF1.h:486
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:1455
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format.
Definition: TFile.h:54
static Long64_t GetFileBytesRead()
Static function returning the total number of bytes read from all files.
Definition: TFile.cxx:4543
TFileCacheRead * GetCacheRead(const TObject *tree=nullptr) const
Return a pointer to the current read cache.
Definition: TFile.cxx:1228
Provides an indirection to the TFitResult class and with a semantics identical to a TFitResult pointe...
Definition: TFitResultPtr.h:32
TH1 is the base class of all histogram classes in ROOT.
Definition: TH1.h:58
virtual Double_t GetBinCenter(Int_t bin) const
Return bin center for 1D histogram.
Definition: TH1.cxx:9008
virtual Int_t GetDimension() const
Definition: TH1.h:281
virtual void Reset(Option_t *option="")
Reset this histogram: contents, errors, etc.
Definition: TH1.cxx:7091
TAxis * GetXaxis()
Definition: TH1.h:322
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:3894
void Draw(Option_t *option="") override
Draw this histogram with options.
Definition: TH1.cxx:3060
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:9089
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:6631
TList * GetListOfFunctions() const
Definition: TH1.h:242
@ kNoAxis
NOTE: Must always be 0 !!!
Definition: TH1.h:71
virtual void Scale(Double_t c1=1, Option_t *option="")
Multiply this histogram by a constant c1.
Definition: TH1.cxx:6586
TObject * Clone(const char *newname="") const override
Make a complete copy of the underlying object.
Definition: TH1.cxx:2727
virtual Double_t GetSumOfWeights() const
Return the sum of weights excluding under/overflows.
Definition: TH1.cxx:7828
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:5209
A TLeaf for a general object derived from TObject.
Definition: TLeafObject.h:31
TClass * GetClass() const
Definition: TLeafObject.h:59
const char * GetTypeName() const override
Returns name of leaf type.
A TLeaf describes individual elements of a TBranch See TBranch structure in TTree.
Definition: TLeaf.h:57
virtual Int_t GetMaximum() const
Definition: TLeaf.h:134
virtual const char * GetTypeName() const
Definition: TLeaf.h:139
virtual Int_t GetLen() const
Return the number of effective elements of this leaf, for the current entry.
Definition: TLeaf.cxx:404
virtual TLeaf * GetLeafCount() const
If this leaf stores a variable-sized array or a multi-dimensional array whose last dimension has vari...
Definition: TLeaf.h:121
TBranch * GetBranch() const
Definition: TLeaf.h:116
static TClass * Class()
A doubly linked list.
Definition: TList.h:38
void Clear(Option_t *option="") override
Remove all objects from the list.
Definition: TList.cxx:402
TObject * FindObject(const char *name) const override
Find an object in this list using its name.
Definition: TList.cxx:578
void Add(TObject *obj) override
Definition: TList.h:81
virtual TObjLink * FirstLink() const
Definition: TList.h:102
void Delete(Option_t *option="") override
Remove all objects from the list AND delete all heap based objects.
Definition: TList.cxx:470
TObject * At(Int_t idx) const override
Returns the object at position idx. Returns 0 if idx is out of range.
Definition: TList.cxx:357
The TNamed class is the base class for all named ROOT classes.
Definition: TNamed.h:29
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition: TNamed.cxx:164
const char * GetName() const override
Returns name of object.
Definition: TNamed.h:47
const char * GetTitle() const override
Returns title of object.
Definition: TNamed.h:48
An array of TObjects.
Definition: TObjArray.h:31
Int_t GetEntriesFast() const
Definition: TObjArray.h:58
void AddAt(TObject *obj, Int_t idx) override
Add object at position ids.
Definition: TObjArray.cxx:254
TObject * Last() const override
Return the object in the last filled slot. Returns 0 if no entries.
Definition: TObjArray.cxx:506
Int_t GetEntries() const override
Return the number of objects in array (i.e.
Definition: TObjArray.cxx:523
void Delete(Option_t *option="") override
Remove all objects from the array AND delete all heap based objects.
Definition: TObjArray.cxx:356
TObject * At(Int_t idx) const override
Definition: TObjArray.h:164
TObject * UncheckedAt(Int_t i) const
Definition: TObjArray.h:84
TObject * FindObject(const char *name) const override
Find an object in this collection using its name.
Definition: TObjArray.cxx:415
void Add(TObject *obj) override
Definition: TObjArray.h:68
Collectable string class.
Definition: TObjString.h:28
const char * GetName() const override
Returns name of object.
Definition: TObjString.h:38
Mother of all ROOT objects.
Definition: TObject.h:41
virtual Bool_t Notify()
This method must be overridden to handle object notification.
Definition: TObject.cxx:589
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:440
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:956
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:775
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:526
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:970
virtual void Draw(Option_t *option="")
Default Draw method for all objects.
Definition: TObject.cxx:274
@ kCanDelete
if object in a list can be deleted
Definition: TObject.h:62
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:944
A 3D polymarker.
Definition: TPolyMarker3D.h:33
void Draw(Option_t *option="") override
Draws 3-D polymarker with its current attributes.
Principal Components Analysis (PCA)
Definition: TPrincipal.h:21
Bool_t ProcessEvents()
Process events if timer did time out.
Definition: TSystem.cxx:91
A container proxy, which allows to access references stored in a TRefArray from TTree::Draw.
A specialized TSelector for TTree::Draw.
Definition: TSelectorDraw.h:33
virtual void SetEstimate(Long64_t n)
Set number of entries to estimate variable limits.
TTreeFormula * GetVar3() const
See TSelectorDraw::GetVar.
Definition: TSelectorDraw.h:97
virtual Long64_t GetDrawFlag() const
Definition: TSelectorDraw.h:83
TH1 * GetOldHistogram() const
Definition: TSelectorDraw.h:87
virtual UInt_t SplitNames(const TString &varexp, std::vector< TString > &names)
Build Index array for names in varexp.
TObject * GetObject() const
Definition: TSelectorDraw.h:84
virtual Bool_t GetCleanElist() const
Definition: TSelectorDraw.h:81
TTreeFormula * GetVar2() const
See TSelectorDraw::GetVar.
Definition: TSelectorDraw.h:95
virtual Int_t GetAction() const
Definition: TSelectorDraw.h:80
TTreeFormula * GetVar1() const
See TSelectorDraw::GetVar.
Definition: TSelectorDraw.h:93
virtual Int_t GetDimension() const
Definition: TSelectorDraw.h:82
virtual Double_t * GetVal(Int_t i) const
Return the last values corresponding to the i-th component of the formula being processed (where the ...
virtual Bool_t Notify()
This function is called at the first entry of a new tree in a chain.
The class is derived from the ROOT class TSelector.
A TSelector object is used by the TTree::Draw, TTree::Scan, TTree::Process to navigate in a TTree and...
Definition: TSelector.h:31
virtual EAbort GetAbort() const
Definition: TSelector.h:73
Bool_t Notify() override
This method must be overridden to handle object notification.
Definition: TSelector.h:56
virtual void ProcessFill(Long64_t)
This method is called for all selected entries.
Definition: TSelector.cxx:330
@ kAbortFile
Definition: TSelector.h:34
@ kAbortProcess
Definition: TSelector.h:34
virtual void Init(TTree *)
Definition: TSelector.h:53
virtual int Version() const
Definition: TSelector.h:52
virtual Bool_t Process(Long64_t)
The Process() function is called for each entry in the tree (or possibly keyed object in the case of ...
Definition: TSelector.cxx:360
TClass * IsA() const override
Definition: TSelector.h:79
virtual void SlaveBegin(TTree *)
Definition: TSelector.h:55
virtual Bool_t ProcessCut(Long64_t)
This method is called before processing entry.
Definition: TSelector.cxx:313
virtual void SetOption(const char *option)
Definition: TSelector.h:64
virtual Long64_t GetStatus() const
Definition: TSelector.h:58
virtual void SetInputList(TList *input)
Definition: TSelector.h:66
virtual TList * GetOutputList() const
Definition: TSelector.h:69
virtual void SlaveTerminate()
Definition: TSelector.h:70
virtual void ResetAbort()
Definition: TSelector.h:74
virtual void Begin(TTree *)
Definition: TSelector.h:54
virtual void Terminate()
Definition: TSelector.h:71
static TSelector * GetSelector(const char *filename)
The code in filename is loaded (interpreted or compiled, see below), filename must contain a valid cl...
Definition: TSelector.cxx:142
Int_t LastIndex() const
static TClass * Class()
const char * GetTypeName() const
TClass * IsA() const override
Basic string class.
Definition: TString.h:136
Ssiz_t Length() const
Definition: TString.h:410
void ToLower()
Change string to lower-case.
Definition: TString.cxx:1159
const char * Data() const
Definition: TString.h:369
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition: TString.h:692
Ssiz_t Last(char c) const
Find last occurrence of a character c.
Definition: TString.cxx:925
void ToUpper()
Change string to upper case.
Definition: TString.cxx:1172
TString & Remove(Ssiz_t pos)
Definition: TString.h:673
TString & Append(const char *cs)
Definition: TString.h:564
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2323
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:624
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:639
Bool_t GetCanvasPreferGL() const
Definition: TStyle.h:180
void SetCanvasPreferGL(Bool_t prefer=kTRUE)
Definition: TStyle.h:326
Int_t GetNumberOfColors() const
Return number of colors in the color palette.
Definition: TStyle.cxx:1123
virtual Bool_t IsFileInIncludePath(const char *name, char **fullpath=nullptr)
Return true if 'name' is a file that can be found in the ROOT include path or the current directory.
Definition: TSystem.cxx:969
virtual TString SplitAclicMode(const char *filename, TString &mode, TString &args, TString &io) const
This method split a filename of the form:
Definition: TSystem.cxx:4259
Base class for several text objects.
Definition: TText.h:22
A cache to speed-up the reading of ROOT datasets.
Definition: TTreeCache.h:32
virtual void SetEntryRange(Long64_t emin, Long64_t emax)
Set the minimum and maximum entry number to be processed this information helps to optimize the numbe...
Used to coordinate one or more TTreeFormula objects.
virtual void UpdateFormulaLeaves()
This function could be called TTreePlayer::UpdateFormulaLeaves, itself called by TChain::LoadTree whe...
virtual Int_t GetNdata(Bool_t forceLoadDim=kFALSE)
Return number of available instances in the formulas.
virtual Bool_t Sync()
Synchronize all the formulae.
virtual void Add(TTreeFormula *)
Add a new formula to the list of formulas managed The manager of the formula will be changed and the ...
virtual Int_t GetMultiplicity() const
Used to pass a selection expression to the Tree drawing routine.
Definition: TTreeFormula.h:58
virtual Bool_t IsInteger(Bool_t fast=kTRUE) const
Return TRUE if the formula corresponds to one single Tree leaf and this leaf is short,...
TTreeFormulaManager * GetManager() const
Definition: TTreeFormula.h:189
virtual char * PrintValue(Int_t mode=0) const
Return value of variable as a string.
T EvalInstance(Int_t i=0, const char *stringStack[]=nullptr)
Evaluate this treeformula.
virtual void UpdateFormulaLeaves()
This function is called TTreePlayer::UpdateFormulaLeaves, itself called by TChain::LoadTree when a ne...
virtual Int_t GetNdata()
Return number of available instances in the formula.
A Tree Index with majorname and minorname.
Definition: TTreeIndex.h:29
Implement some of the functionality of the class TTree requiring access to extra libraries (Histogram...
Definition: TTreePlayer.h:37
virtual void UpdateFormulaLeaves()
this function is called by TChain::LoadTree when a new Tree is loaded.
TList * fInput
! input list to the selector
Definition: TTreePlayer.h:53
void DeleteSelectorFromFile()
Delete any selector created by this object.
virtual Long64_t DrawSelect(const char *varexp, const char *selection, Option_t *option, Long64_t nentries, Long64_t firstentry)
Draw expression varexp for specified entries that matches the selection.
virtual Long64_t GetSelectedRows() const
Definition: TTreePlayer.h:81
virtual Long64_t GetEntries(const char *selection)
Return the number of entries matching the selection.
TSelectorDraw * fSelector
! Pointer to current selector
Definition: TTreePlayer.h:50
virtual Int_t UnbinnedFit(const char *formula, const char *varexp, const char *selection, Option_t *option, Long64_t nentries, Long64_t firstentry)
Unbinned fit of one or more variable(s) from a Tree.
const char * GetNameByIndex(TString &varexp, Int_t *index, Int_t colindex)
Return name corresponding to colindex in varexp.
virtual ~TTreePlayer()
Tree destructor.
virtual Int_t Fit(const char *formula, const char *varexp, const char *selection, Option_t *option, Option_t *goption, Long64_t nentries, Long64_t firstentry)
Fit a projected item(s) from a Tree.
Long64_t fSelectedRows
Number of selected entries.
Definition: TTreePlayer.h:48
TSelector * fSelectorFromFile
! Pointer to a user defined selector created by this TTreePlayer object
Definition: TTreePlayer.h:51
const char * fScanFileName
Name of the file where Scan is redirected.
Definition: TTreePlayer.h:46
TList * fFormulaList
! Pointer to a list of coordinated list TTreeFormula (used by Scan and Query)
Definition: TTreePlayer.h:54
virtual TTree * CopyTree(const char *selection, Option_t *option, Long64_t nentries, Long64_t firstentry)
Copy a Tree with selection, make a clone of this Tree header, then copy the selected entries.
virtual Int_t MakeCode(const char *filename)
Generate skeleton function for this Tree.
TTree * fTree
! Pointer to current Tree
Definition: TTreePlayer.h:44
virtual Int_t MakeClass(const char *classname, Option_t *option)
Generate skeleton analysis class for this Tree.
virtual void SetEstimate(Long64_t n)
Set number of entries to estimate variable limits.
virtual Long64_t DrawScript(const char *wrapperPrefix, const char *macrofilename, const char *cutfilename, Option_t *option, Long64_t nentries, Long64_t firstentry)
Draw the result of a C++ script.
virtual Long64_t Scan(const char *varexp, const char *selection, Option_t *option, Long64_t nentries, Long64_t firstentry)
Loop on Tree and print entries passing selection.
virtual Int_t MakeProxy(const char *classname, const char *macrofilename=nullptr, const char *cutfilename=nullptr, const char *option=nullptr, Int_t maxUnrolling=3)
Generate a skeleton analysis class for this Tree using TBranchProxy.
TPrincipal * Principal(const char *varexp, const char *selection, Option_t *option, Long64_t nentries, Long64_t firstentry)
Interface to the Principal Components Analysis class.
TSelector * fSelectorUpdate
! Set to the selector address when it's entry list needs to be updated by the UpdateFormulaLeaves fun...
Definition: TTreePlayer.h:55
TH1 * fHistogram
! Pointer to histogram used for the projection
Definition: TTreePlayer.h:49
virtual void StartViewer(Int_t ww, Int_t wh)
Start the TTreeViewer on this TTree.
Bool_t fScanRedirect
Switch to redirect TTree::Scan output to a file.
Definition: TTreePlayer.h:45
virtual TSQLResult * Query(const char *varexp, const char *selection, Option_t *option, Long64_t nentries, Long64_t firstentry)
Loop on Tree and return TSQLResult object containing entries passing selection.
virtual Int_t GetDimension() const
Definition: TTreePlayer.h:74
TClass * fSelectorClass
! Pointer to the actual class of the TSelectorFromFile
Definition: TTreePlayer.h:52
virtual void SetTree(TTree *t)
Definition: TTreePlayer.h:124
virtual TVirtualIndex * BuildIndex(const TTree *T, const char *majorname, const char *minorname)
Build the index for the tree (see TTree::BuildIndex)
Int_t fDimension
Dimension of the current expression.
Definition: TTreePlayer.h:47
virtual Long64_t Process(const char *filename, Option_t *option, Long64_t nentries, Long64_t firstentry)
Process this tree executing the TSelector code in the specified filename.
TTreePlayer()
Default Tree constructor.
Definition: TTreePlayer.cxx: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:79
virtual TBranch * GetBranch(const char *name)
Return pointer to the branch with the given name in this tree or its friends.
Definition: TTree.cxx:5262
virtual Int_t GetScanField() const
Definition: TTree.h:507
virtual Int_t GetEntry(Long64_t entry, Int_t getall=0)
Read all branches of entry and return total number of bytes read.
Definition: TTree.cxx:5612
virtual Long64_t GetEstimate() const
Definition: TTree.h:463
virtual TObjArray * GetListOfLeaves()
Definition: TTree.h:485
TFile * GetCurrentFile() const
Return pointer to the current file.
Definition: TTree.cxx:5453
void Draw(Option_t *opt) override
Default Draw method for all objects.
Definition: TTree.h:428
TDirectory * GetDirectory() const
Definition: TTree.h:458
virtual TEntryList * GetEntryList()
Returns the entry list assigned to this tree.
Definition: TTree.cxx:5828
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:7424
virtual Long64_t GetEntries() const
Definition: TTree.h:459
virtual void SetEstimate(Long64_t nentries=1000000)
Set number of entries to estimate variable limits.
Definition: TTree.cxx:9074
virtual Long64_t GetEntryNumber(Long64_t entry) const
Return entry number corresponding to entry.
Definition: TTree.cxx:5839
virtual TTree * CloneTree(Long64_t nentries=-1, Option_t *option="")
Create a clone of this tree and copy nentries.
Definition: TTree.cxx:3110
virtual TTree * GetTree() const
Definition: TTree.h:513
virtual void SetEntryList(TEntryList *list, Option_t *opt="")
Set an EntryList.
Definition: TTree.cxx:9010
virtual Long64_t LoadTree(Long64_t entry)
Set current entry.
Definition: TTree.cxx:6447
virtual void SetNotify(TObject *obj)
Sets the address of the object to be notified when the tree is loaded.
Definition: TTree.h:634
TEventList * GetEventList() const
Definition: TTree.h:469
virtual Long64_t GetEntriesFriend() const
Return pointer to the 1st Leaf named name in any Branch of this Tree or any branch in the list of fri...
Definition: TTree.cxx:5486
virtual Int_t GetTreeNumber() const
Definition: TTree.h:515
virtual Int_t GetTimerInterval() const
Definition: TTree.h:510
virtual void SetScanField(Int_t n=50)
Definition: TTree.h:639
virtual Long64_t GetCacheSize() const
Definition: TTree.h:449
virtual Int_t SetCacheSize(Long64_t cachesize=-1)
Set maximum size of the file cache .
Definition: TTree.cxx:8650
virtual Long64_t GetMaxEntryLoop() const
Definition: TTree.h:493
Abstract Base Class for Fitting.
Abstract interface for Tree Index.
Definition: TVirtualIndex.h:30
virtual Bool_t SendProcessingProgress(Double_t, Double_t, Bool_t=kFALSE)
virtual Bool_t SendProcessingStatus(const char *, Bool_t=kFALSE)
virtual TObjArray * GetElements() const =0
const Int_t n
Definition: legend1.C:16
TFitResultPtr UnBinFit(ROOT::Fit::UnBinData *data, TF1 *f1, Foption_t &option, const ROOT::Math::MinimizerOptions &moption)
fit an unbin data set (from tree or from histogram buffer) using a TF1 pointer and fit options.
Definition: HFitImpl.cxx:810
void(off) SmallVectorTemplateBase< T
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)
Returns the largest of a and b.
Definition: TMathBase.h:250
Short_t Min(Short_t a, Short_t b)
Returns the smallest of a and b.
Definition: TMathBase.h:198
Definition: 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
TLine l
Definition: textangle.C:4