Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TTreePlayer.cxx
Go to the documentation of this file.
1// @(#)root/treeplayer:$Id$
2// Author: Rene Brun 12/01/96
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12/** \class TTreePlayer
13
14Implement some of the functionality of the class TTree requiring access to
15extra libraries (Histogram, display, etc).
16*/
17
18#include "TTreePlayer.h"
19
20#include <cstring>
21#include <cstdio>
22#include <cstdlib>
23#include <iostream>
24#include <fstream>
25
26#include "TROOT.h"
27#include "TApplication.h"
28#include "TSystem.h"
29#include "TFile.h"
30#include "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 = nullptr;
102 fScanFileName = nullptr;
103 fScanRedirect = false;
104 fSelectedRows = 0;
105 fDimension = 0;
106 fHistogram = nullptr;
107 fFormulaList = new TList();
108 fFormulaList->SetOwner(true);
109 fSelector = new TSelectorDraw();
110 fSelectorFromFile = nullptr;
111 fSelectorClass = nullptr;
112 fSelectorUpdate = nullptr;
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 == nullptr) return nullptr;
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 = nullptr; // 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 nullptr;
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 keep = false;
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 }
259 fSelectorFromFile = nullptr;
260 fSelectorClass = nullptr;
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(nullptr);
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, true);
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 optpara = false;
400 bool optcandle = false;
401 bool optgl5d = false;
402 bool optnorm = false;
403 if (opt.Contains("norm")) {optnorm = true; opt.ReplaceAll("norm",""); opt.ReplaceAll(" ","");}
404 if (opt.Contains("para")) optpara = true;
405 if (opt.Contains("candle")) optcandle = true;
406 if (opt.Contains("gl5d")) optgl5d = true;
407 bool pgl = gStyle->GetCanvasPreferGL();
408 if (optgl5d) {
410 if (!gPad) {
411 if (pgl == false) gStyle->SetCanvasPreferGL(true);
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 draw = false;
439 if (!drawflag && !opt.Contains("goff")) draw = true;
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 {
474 bool graph = false;
475 Int_t l = opt.Length();
476 if (l == 0 || opt == "same") graph = true;
477 if (opt.Contains("p") || opt.Contains("*") || opt.Contains("l")) graph = true;
478 if (opt.Contains("surf") || opt.Contains("lego") || opt.Contains("cont")) graph = false;
479 if (opt.Contains("col") || opt.Contains("hist") || opt.Contains("scat")) graph = false;
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(nullptr);
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
639static TString R__GetBranchPointerName(TLeaf *leaf, bool replace = true)
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.
752 bool ischain = fTree->InheritsFrom(TChain::Class());
753 bool 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++/") != nullptr) {
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=nullptr;
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(false);
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," ~%s() override { }\n",classname);
1099 fprintf(fp," Int_t Version() const override { return 2; }\n");
1100 fprintf(fp," void Begin(TTree *tree) override;\n");
1101 fprintf(fp," void SlaveBegin(TTree *tree) override;\n");
1102 fprintf(fp," void Init(TTree *tree) override;\n");
1103 fprintf(fp," bool Notify() override;\n");
1104 fprintf(fp," bool Process(Long64_t entry) override;\n");
1105 fprintf(fp," Int_t GetEntry(Long64_t entry, Int_t getall = 0) override { return fChain ? fChain->GetTree()->GetEntry(entry, getall) : 0; }\n");
1106 fprintf(fp," void SetOption(const char *option) override { fOption = option; }\n");
1107 fprintf(fp," void SetObject(TObject *obj) override { fObject = obj; }\n");
1108 fprintf(fp," void SetInputList(TList *input) override { fInput = input; }\n");
1109 fprintf(fp," TList* GetOutputList() const override { return fOutput; }\n");
1110 fprintf(fp," void SlaveTerminate() override;\n");
1111 fprintf(fp," void Terminate() override;\n\n");
1112 fprintf(fp," ClassDefOverride(%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 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,false).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 %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 true;\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 %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 true;\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 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 h1analysisProxy_Notify();
1882/// - Process -> bool 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==nullptr || 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 Notify()
1957/// - bool 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 = nullptr;
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 = nullptr;
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=nullptr;
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 loaded = false;
2083 if (select) {
2084 if (select->EvalInstance(inst) == 0) {
2085 continue;
2086 }
2087 }
2088
2089 if (inst==0) loaded = true;
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 = true;
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);
2194 TString file(filename);
2195 TSelector *selector = TSelector::GetSelector(file);
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
2244 gMonitoringWriter->SendProcessingStatus("STARTED",true);
2245
2246 bool process = (selector->GetAbort() != TSelector::kAbortProcess &&
2247 (selector->Version() != 0 || selector->GetStatus() != -1)) ? true : false;
2248 if (process) {
2249
2250 Long64_t readbytesatstart = 0;
2251 readbytesatstart = TFile::GetFileBytesRead();
2252
2253 //set the file cache
2254 TTreeCache *tpf = nullptr;
2255 TFile *curfile = fTree->GetCurrentFile();
2256 if (curfile) {
2257 tpf = (TTreeCache*)curfile->GetCacheRead(fTree);
2258 if (tpf)
2259 tpf->SetEntryRange(firstentry,firstentry+nentries);
2260 else {
2261 // Create the TTreeCache with the default size unless the
2262 // user explicitly disabled it.
2263 fTree->EnableCache();
2264 tpf = (TTreeCache*)curfile->GetCacheRead(fTree);
2265 if (tpf) tpf->SetEntryRange(firstentry,firstentry+nentries);
2266 }
2267 }
2268
2269 //Create a timer to get control in the entry loop(s)
2270 TProcessEventTimer *timer = nullptr;
2271 Int_t interval = fTree->GetTimerInterval();
2272 if (!gROOT->IsBatch() && interval)
2273 timer = new TProcessEventTimer(interval);
2274
2275 //loop on entries (elist or all entries)
2276 Long64_t entry, entryNumber, localEntry;
2277
2278 bool useCutFill = selector->Version() == 0;
2279
2280 // force the first monitoring info
2283
2284 //trying to set the first tree, because in the Draw function
2285 //the tree corresponding to firstentry has already been loaded,
2286 //so it is not set in the entry list
2287 fSelectorUpdate = selector;
2289
2290 for (entry=firstentry;entry<firstentry+nentries;entry++) {
2291 entryNumber = fTree->GetEntryNumber(entry);
2292 if (entryNumber < 0) break;
2293 if (timer && timer->ProcessEvents()) break;
2294 if (gROOT->IsInterrupted()) break;
2295 localEntry = fTree->LoadTree(entryNumber);
2296 if (localEntry < 0) break;
2297 if(useCutFill) {
2298 if (selector->ProcessCut(localEntry))
2299 selector->ProcessFill(localEntry); //<==call user analysis function
2300 } else {
2301 selector->Process(localEntry); //<==call user analysis function
2302 }
2304 gMonitoringWriter->SendProcessingProgress((entry-firstentry),TFile::GetFileBytesRead()-readbytesatstart,true);
2305 if (selector->GetAbort() == TSelector::kAbortProcess) break;
2306 if (selector->GetAbort() == TSelector::kAbortFile) {
2307 // Skip to the next file.
2308 entry += fTree->GetTree()->GetEntries() - localEntry;
2309 // Reset the abort status.
2310 selector->ResetAbort();
2311 }
2312 }
2313 delete timer;
2314 //we must reset the cache
2315 {
2316 TFile *curfile2 = fTree->GetCurrentFile();
2317 if (curfile2 && fTree->GetCacheSize() > 0) {
2318 tpf = (TTreeCache*)curfile2->GetCacheRead(fTree);
2319 if (tpf) tpf->SetEntryRange(0,0);
2320 }
2321 }
2322 }
2323
2324 process = (selector->GetAbort() != TSelector::kAbortProcess &&
2325 (selector->Version() != 0 || selector->GetStatus() != -1)) ? true : false;
2326 Long64_t res = (process) ? 0 : -1;
2327 if (process) {
2328 selector->SlaveTerminate(); //<==call user termination function
2329 selector->Terminate(); //<==call user termination function
2330 res = selector->GetStatus();
2331 }
2332 fTree->SetNotify(nullptr); // Detach the selector from the tree.
2333 fSelectorUpdate = nullptr;
2336
2337 return res;
2338}
2339
2340////////////////////////////////////////////////////////////////////////////////
2341/// cleanup pointers in the player pointing to obj
2342
2344{
2345 if (fHistogram == obj) fHistogram = nullptr;
2346}
2347
2348////////////////////////////////////////////////////////////////////////////////
2349/// Loop on Tree and print entries passing selection. If varexp is 0 (or "")
2350/// then print only first 8 columns. If varexp = "*" print all columns.
2351/// Otherwise a columns selection can be made using "var1:var2:var3".
2352/// The function returns the number of entries passing the selection.
2353///
2354/// By default 50 rows are shown and you are asked for `<CR>`
2355/// to see the next 50 rows.
2356///
2357/// You can change the default number of rows to be shown before `<CR>`
2358/// via mytree->SetScanField(maxrows) where maxrows is 50 by default.
2359/// if maxrows is set to 0 all rows of the Tree are shown.
2360///
2361/// This option is interesting when dumping the contents of a Tree to
2362/// an ascii file, eg from the command line.
2363/// ### with ROOT 5
2364/// ~~~{.cpp}
2365/// root [0] tree->SetScanField(0);
2366/// root [1] tree->Scan("*"); >tree.log
2367/// ~~~
2368/// ### with ROOT 6
2369/// ~~~{.cpp}
2370/// root [0] tree->SetScanField(0);
2371/// root [1] .> tree.log
2372/// tree->Scan("*");
2373/// .>
2374/// ~~~
2375/// will create a file tree.log
2376///
2377/// Arrays (within an entry) are printed in their linear forms.
2378/// If several arrays with multiple dimensions are printed together,
2379/// they will NOT be synchronized. For example print
2380/// arr1[4][2] and arr2[2][3] will results in a printing similar to:
2381/// ~~~{.cpp}
2382/// ***********************************************
2383/// * Row * Instance * arr1 * arr2 *
2384/// ***********************************************
2385/// * x * 0 * arr1[0][0]* arr2[0][0]*
2386/// * x * 1 * arr1[0][1]* arr2[0][1]*
2387/// * x * 2 * arr1[1][0]* arr2[0][2]*
2388/// * x * 3 * arr1[1][1]* arr2[1][0]*
2389/// * x * 4 * arr1[2][0]* arr2[1][1]*
2390/// * x * 5 * arr1[2][1]* arr2[1][2]*
2391/// * x * 6 * arr1[3][0]* *
2392/// * x * 7 * arr1[3][1]* *
2393/// ~~~
2394/// However, if there is a selection criterion which is an array, then
2395/// all the formulas will be synchronized with the selection criterion
2396/// (see TTreePlayer::DrawSelect for more information).
2397///
2398/// The options string can contains the following parameters:
2399///
2400/// - lenmax=dd
2401/// Where 'dd' is the maximum number of elements per array that should
2402/// be printed. If 'dd' is 0, all elements are printed (this is the
2403/// default)
2404/// - colsize=ss
2405/// Where 'ss' will be used as the default size for all the column
2406/// If this options is not specified, the default column size is 9
2407/// - precision=pp
2408/// Where 'pp' will be used as the default 'precision' for the
2409/// printing format.
2410/// - col=xxx
2411/// Where 'xxx' is colon (:) delimited list of printing format for
2412/// each column. The format string should follow the printf format
2413/// specification. The value given will be prefixed by % and, if no
2414/// conversion specifier is given, will be suffixed by the letter g.
2415/// before being passed to fprintf. If no format is specified for a
2416/// column, the default is used (aka ${colsize}.${precision}g )
2417///
2418/// For example:
2419/// ~~~{.cpp}
2420/// tree->Scan("a:b:c","","colsize=30 precision=3 col=::20.10:#x:5ld");
2421/// ~~~
2422/// Will print 3 columns, the first 2 columns will be 30 characters long,
2423/// the third columns will be 20 characters long. The printing format used
2424/// for the columns (assuming they are numbers) will be respectively:
2425/// ~~~ {.cpp}
2426/// %30.3g %30.3g %20.10g %#x %5ld
2427/// ~~~
2428
2429Long64_t TTreePlayer::Scan(const char *varexp, const char *selection,
2430 Option_t * option,
2431 Long64_t nentries, Long64_t firstentry)
2432{
2433
2434 TString opt = option;
2435 opt.ToLower();
2436 UInt_t ui;
2437 UInt_t lenmax = 0;
2438 UInt_t colDefaultSize = 9;
2439 UInt_t colPrecision = 9;
2440 std::vector<TString> colFormats;
2441 std::vector<Int_t> colSizes;
2442
2443 if (opt.Contains("lenmax=")) {
2444 int start = opt.Index("lenmax=");
2445 int numpos = start + strlen("lenmax=");
2446 int numlen = 0;
2447 int len = opt.Length();
2448 while( (numpos+numlen<len) && isdigit(opt[numpos+numlen]) ) numlen++;
2449 TString num = opt(numpos,numlen);
2450 opt.Remove(start,strlen("lenmax")+numlen);
2451
2452 lenmax = atoi(num.Data());
2453 }
2454 if (opt.Contains("colsize=")) {
2455 int start = opt.Index("colsize=");
2456 int numpos = start + strlen("colsize=");
2457 int numlen = 0;
2458 int len = opt.Length();
2459 while( (numpos+numlen<len) && isdigit(opt[numpos+numlen]) ) numlen++;
2460 TString num = opt(numpos,numlen);
2461 opt.Remove(start,strlen("size")+numlen);
2462
2463 colDefaultSize = atoi(num.Data());
2464 colPrecision = colDefaultSize;
2465 if (colPrecision>18) colPrecision = 18;
2466 }
2467 if (opt.Contains("precision=")) {
2468 int start = opt.Index("precision=");
2469 int numpos = start + strlen("precision=");
2470 int numlen = 0;
2471 int len = opt.Length();
2472 while( (numpos+numlen<len) && isdigit(opt[numpos+numlen]) ) numlen++;
2473 TString num = opt(numpos,numlen);
2474 opt.Remove(start,strlen("precision")+numlen);
2475
2476 colPrecision = atoi(num.Data());
2477 }
2478 TString defFormat = Form("%d.%d",colDefaultSize,colPrecision);
2479 if (opt.Contains("col=")) {
2480 int start = opt.Index("col=");
2481 int numpos = start + strlen("col=");
2482 int numlen = 0;
2483 int len = opt.Length();
2484 while( (numpos+numlen<len) &&
2485 (isdigit(opt[numpos+numlen])
2486 || opt[numpos+numlen] == 'c'
2487 || opt[numpos+numlen] == 'd'
2488 || opt[numpos+numlen] == 'i'
2489 || opt[numpos+numlen] == 'o'
2490 || opt[numpos+numlen] == 'x'
2491 || opt[numpos+numlen] == 'X'
2492 || opt[numpos+numlen] == 'u'
2493 || opt[numpos+numlen] == 'f'
2494 || opt[numpos+numlen] == 'e'
2495 || opt[numpos+numlen] == 'E'
2496 || opt[numpos+numlen] == 'g'
2497 || opt[numpos+numlen] == 'G'
2498 || opt[numpos+numlen] == 'l'
2499 || opt[numpos+numlen] == 'L'
2500 || opt[numpos+numlen] == 'h'
2501 || opt[numpos+numlen] == 's'
2502 || opt[numpos+numlen] == '#'
2503 || opt[numpos+numlen]=='.'
2504 || opt[numpos+numlen]==':')) numlen++;
2505 TString flist = opt(numpos,numlen);
2506 opt.Remove(start,strlen("col")+numlen);
2507
2508 int i = 0;
2509 while(i<flist.Length() && flist[i]==':') {
2510 colFormats.push_back(defFormat);
2511 colSizes.push_back(colDefaultSize);
2512 ++i;
2513 }
2514 for(; i<flist.Length(); ++i) {
2515 int next = flist.Index(":",i);
2516 if (next==i) {
2517 colFormats.push_back(defFormat);
2518 } else if (next==kNPOS) {
2519 colFormats.push_back(flist(i,flist.Length()-i));
2520 i = flist.Length();
2521 } else {
2522 colFormats.push_back(flist(i,next-i));
2523 i = next;
2524 }
2525 UInt_t siz = atoi(colFormats[colFormats.size()-1].Data());
2526 colSizes.push_back( siz ? siz : colDefaultSize );
2527 }
2528 }
2529
2530 TTreeFormula **var;
2531 std::vector<TString> cnames;
2532 TString onerow;
2533 Long64_t entry,entryNumber;
2534 Int_t i,nch;
2535 UInt_t ncols = 8; // by default first 8 columns are printed only
2536 std::ofstream out;
2537 const char *fname = nullptr;
2538 TString fownname;
2539 if (fScanRedirect) {
2540 fTree->SetScanField(0); // no page break if Scan is redirected
2541 fname = fScanFileName;
2542 if (!fname) fname = "";
2543 Int_t lenfile = strlen(fname);
2544 if (!lenfile) {
2545 fownname = fTree->GetName();
2546 fownname.Append("-scan.dat");
2547 fname = fownname.Data();
2548 }
2549 out.open(fname, std::ios::out);
2550 if (!out.good ()) {
2551 Error("Scan","Can not open file for redirection");
2552 return 0;
2553 }
2554 }
2555 TObjArray *leaves = fTree->GetListOfLeaves();
2556 if (leaves==nullptr) return 0;
2557 UInt_t nleaves = leaves->GetEntriesFast();
2558 if (nleaves < ncols) ncols = nleaves;
2559 nch = varexp ? strlen(varexp) : 0;
2560
2561 nentries = GetEntriesToProcess(firstentry, nentries);
2562
2563//*-*- Compile selection expression if there is one
2564 TTreeFormula *select = nullptr;
2565 if (selection && strlen(selection)) {
2566 select = new TTreeFormula("Selection",selection,fTree);
2567 if (!select) return -1;
2568 if (!select->GetNdim()) { delete select; return -1; }
2569 fFormulaList->Add(select);
2570 }
2571//*-*- if varexp is empty, take first 8 columns by default
2572 int allvar = 0;
2573 if (varexp && !strcmp(varexp, "*")) { ncols = nleaves; allvar = 1; }
2574 if (nch == 0 || allvar) {
2575 UInt_t ncs = ncols;
2576 ncols = 0;
2577 for (ui=0;ui<ncs;++ui) {
2578 TLeaf *lf = (TLeaf*)leaves->At(ui);
2579 if (lf->GetBranch()->GetListOfBranches()->GetEntries() > 0) continue;
2580 cnames.push_back( lf->GetBranch()->GetMother()->GetName() );
2581 if (cnames[ncols] == lf->GetName() ) {
2582 // Already complete, let move on.
2583 } else if (cnames[ncols][cnames[ncols].Length()-1]=='.') {
2584 cnames[ncols] = lf->GetBranch()->GetName(); // name of branch already include mother's name
2585 } else {
2587 TBranchElement *mother = (TBranchElement*)lf->GetBranch()->GetMother();
2588 if (mother->GetType() == 3 || mother->GetType() == 4) {
2589 // The name of the mother branch is embedded in the sub-branch names.
2590 cnames[ncols] = lf->GetBranch()->GetName();
2591 ++ncols;
2592 continue;
2593 }
2594 }
2595 if (!strchr(lf->GetBranch()->GetName() ,'[') ) {
2596 cnames[ncols].Append('.');
2597 cnames[ncols].Append( lf->GetBranch()->GetName() );
2598 }
2599 }
2600 if (lf->GetBranch()->IsA() == TBranch::Class() ||
2601 strcmp( lf->GetBranch()->GetName(), lf->GetName() ) != 0 ) {
2602 cnames[ncols].Append('.');
2603 cnames[ncols].Append( lf->GetName() );
2604 }
2605 ++ncols;
2606 }
2607//*-*- otherwise select only the specified columns
2608 } else {
2609
2610 ncols = fSelector->SplitNames(varexp, cnames);
2611
2612 }
2613 var = new TTreeFormula* [ncols];
2614
2615 for(ui=colFormats.size();ui<ncols;++ui) {
2616 colFormats.push_back(defFormat);
2617 colSizes.push_back(colDefaultSize);
2618 }
2619
2620//*-*- Create the TreeFormula objects corresponding to each column
2621 for (ui=0;ui<ncols;ui++) {
2622 var[ui] = new TTreeFormula("Var1",cnames[ui].Data(),fTree);
2623 fFormulaList->Add(var[ui]);
2624 }
2625
2626//*-*- Create a TreeFormulaManager to coordinate the formulas
2627 TTreeFormulaManager *manager=nullptr;
2628 bool hasArray = false;
2629 bool forceDim = false;
2630 if (fFormulaList->LastIndex()>=0) {
2631 if (select) {
2632 if (select->GetManager()->GetMultiplicity() > 0 ) {
2633 manager = new TTreeFormulaManager;
2634 for(i=0;i<=fFormulaList->LastIndex();i++) {
2635 manager->Add((TTreeFormula*)fFormulaList->At(i));
2636 }
2637 manager->Sync();
2638 }
2639 }
2640 for(i=0;i<=fFormulaList->LastIndex();i++) {
2641 TTreeFormula *form = ((TTreeFormula*)fFormulaList->At(i));
2642 switch( form->GetManager()->GetMultiplicity() ) {
2643 case 1:
2644 case 2:
2645 hasArray = true;
2646 forceDim = true;
2647 break;
2648 case -1:
2649 forceDim = true;
2650 break;
2651 case 0:
2652 break;
2653 }
2654
2655 }
2656 }
2657
2658//*-*- Print header
2659 onerow = "***********";
2660 if (hasArray) onerow += "***********";
2661
2662 for (ui=0;ui<ncols;ui++) {
2663 TString starFormat = Form("*%%%d.%ds",colSizes[ui]+2,colSizes[ui]+2);
2664 onerow += Form(starFormat.Data(),var[ui]->PrintValue(-2));
2665 }
2666 if (fScanRedirect)
2667 out<<onerow.Data()<<"*"<<std::endl;
2668 else
2669 printf("%s*\n",onerow.Data());
2670 onerow = "* Row ";
2671 if (hasArray) onerow += "* Instance ";
2672 for (ui=0;ui<ncols;ui++) {
2673 TString numbFormat = Form("* %%%d.%ds ",colSizes[ui],colSizes[ui]);
2674 onerow += Form(numbFormat.Data(),var[ui]->PrintValue(-1));
2675 }
2676 if (fScanRedirect)
2677 out<<onerow.Data()<<"*"<<std::endl;
2678 else
2679 printf("%s*\n",onerow.Data());
2680 onerow = "***********";
2681 if (hasArray) onerow += "***********";
2682 for (ui=0;ui<ncols;ui++) {
2683 TString starFormat = Form("*%%%d.%ds",colSizes[ui]+2,colSizes[ui]+2);
2684 onerow += Form(starFormat.Data(),var[ui]->PrintValue(-2));
2685 }
2686 if (fScanRedirect)
2687 out<<onerow.Data()<<"*"<<std::endl;
2688 else
2689 printf("%s*\n",onerow.Data());
2690//*-*- loop on all selected entries
2691 fSelectedRows = 0;
2692 Int_t tnumber = -1;
2693 bool exitloop = false;
2694 for (entry=firstentry;
2695 entry<(firstentry+nentries) && !exitloop;
2696 entry++) {
2697 entryNumber = fTree->GetEntryNumber(entry);
2698 if (entryNumber < 0) break;
2699 Long64_t localEntry = fTree->LoadTree(entryNumber);
2700 if (localEntry < 0) break;
2701 if (tnumber != fTree->GetTreeNumber()) {
2702 tnumber = fTree->GetTreeNumber();
2703 if (manager) manager->UpdateFormulaLeaves();
2704 else {
2705 for(i=0;i<=fFormulaList->LastIndex();i++) {
2707 }
2708 }
2709 }
2710
2711 int ndata = 1;
2712 if (forceDim) {
2713
2714 if (manager) {
2715
2716 ndata = manager->GetNdata(true);
2717
2718 } else {
2719
2720 // let's print the max number of column
2721 for (ui=0;ui<ncols;ui++) {
2722 if (ndata < var[ui]->GetNdata() ) {
2723 ndata = var[ui]->GetNdata();
2724 }
2725 }
2726 if (select && select->GetNdata()==0) ndata = 0;
2727 }
2728
2729 }
2730
2731 if (lenmax && ndata>(int)lenmax) ndata = lenmax;
2732 bool loaded = false;
2733 for(int inst=0;inst<ndata;inst++) {
2734 if (select) {
2735 if (select->EvalInstance(inst) == 0) {
2736 continue;
2737 }
2738 }
2739 if (inst==0) loaded = true;
2740 else if (!loaded) {
2741 // EvalInstance(0) always needs to be called so that
2742 // the proper branches are loaded.
2743 for (ui=0;ui<ncols;ui++) {
2744 var[ui]->EvalInstance(0);
2745 }
2746 loaded = true;
2747 }
2748 onerow = Form("* %8lld ",entryNumber);
2749 if (hasArray) {
2750 onerow += Form("* %8d ",inst);
2751 }
2752 for (ui=0;ui<ncols;++ui) {
2753 TString numbFormat = Form("* %%%d.%ds ",colSizes[ui],colSizes[ui]);
2754 if (var[ui]->GetNdim()) onerow += Form(numbFormat.Data(),var[ui]->PrintValue(0,inst,colFormats[ui].Data()));
2755 else {
2756 TString emptyForm = Form("* %%%dc ",colSizes[ui]);
2757 onerow += Form(emptyForm.Data(),' ');
2758 }
2759 }
2760 fSelectedRows++;
2761 if (fScanRedirect)
2762 out<<onerow.Data()<<"*"<<std::endl;
2763 else
2764 printf("%s*\n",onerow.Data());
2765 if (fTree->GetScanField() > 0 && fSelectedRows > 0) {
2766 if (fSelectedRows%fTree->GetScanField() == 0) {
2767 fprintf(stderr,"Type <CR> to continue or q to quit ==> ");
2768 int answer, readch;
2769 readch = getchar();
2770 answer = readch;
2771 while (readch != '\n' && readch != EOF) readch = getchar();
2772 if (answer == 'q' || answer == 'Q') {
2773 exitloop = true;
2774 break;
2775 }
2776 }
2777 }
2778 }
2779 }
2780 onerow = "***********";
2781 if (hasArray) onerow += "***********";
2782 for (ui=0;ui<ncols;ui++) {
2783 TString starFormat = Form("*%%%d.%ds",colSizes[ui]+2,colSizes[ui]+2);
2784 onerow += Form(starFormat.Data(),var[ui]->PrintValue(-2));
2785 }
2786 if (fScanRedirect)
2787 out<<onerow.Data()<<"*"<<std::endl;
2788 else
2789 printf("%s*\n",onerow.Data());
2790 if (select) Printf("==> %lld selected %s", fSelectedRows,
2791 fSelectedRows == 1 ? "entry" : "entries");
2792 if (fScanRedirect) printf("File <%s> created\n", fname);
2793
2794//*-*- delete temporary objects
2796 // The TTreeFormulaManager is deleted by the last TTreeFormula.
2797 delete [] var;
2798 return fSelectedRows;
2799}
2800
2801////////////////////////////////////////////////////////////////////////////////
2802/// Loop on Tree and return TSQLResult object containing entries passing
2803/// selection. If varexp is 0 (or "") then print only first 8 columns.
2804/// If varexp = "*" print all columns. Otherwise a columns selection can
2805/// be made using "var1:var2:var3". In case of error 0 is returned otherwise
2806/// a TSQLResult object which must be deleted by the user.
2807
2808TSQLResult *TTreePlayer::Query(const char *varexp, const char *selection,
2809 Option_t *, Long64_t nentries, Long64_t firstentry)
2810{
2811 TTreeFormula **var;
2812 std::vector<TString> cnames;
2813 TString onerow;
2814 Long64_t entry,entryNumber;
2815 Int_t i,nch;
2816 Int_t ncols = 8; // by default first 8 columns are printed only
2817 TObjArray *leaves = fTree->GetListOfLeaves();
2818 Int_t nleaves = leaves->GetEntriesFast();
2819 if (nleaves < ncols) ncols = nleaves;
2820 nch = varexp ? strlen(varexp) : 0;
2821
2822 nentries = GetEntriesToProcess(firstentry, nentries);
2823
2824 // compile selection expression if there is one
2825 TTreeFormula *select = nullptr;
2826 if (strlen(selection)) {
2827 select = new TTreeFormula("Selection",selection,fTree);
2828 if (!select) return nullptr;
2829 if (!select->GetNdim()) { delete select; return nullptr; }
2830 fFormulaList->Add(select);
2831 }
2832
2833 // if varexp is empty, take first 8 columns by default
2834 int allvar = 0;
2835 if (varexp && !strcmp(varexp, "*")) { ncols = nleaves; allvar = 1; }
2836 if (nch == 0 || allvar) {
2837 for (i=0;i<ncols;i++) {
2838 cnames.push_back( ((TLeaf*)leaves->At(i))->GetName() );
2839 }
2840 } else {
2841 // otherwise select only the specified columns
2842 ncols = fSelector->SplitNames(varexp,cnames);
2843 }
2844 var = new TTreeFormula* [ncols];
2845
2846 // create the TreeFormula objects corresponding to each column
2847 for (i=0;i<ncols;i++) {
2848 var[i] = new TTreeFormula("Var1",cnames[i].Data(),fTree);
2849 fFormulaList->Add(var[i]);
2850 }
2851
2852 // fill header info into result object
2853 TTreeResult *res = new TTreeResult(ncols);
2854 for (i = 0; i < ncols; i++) {
2855 res->AddField(i, var[i]->PrintValue(-1));
2856 }
2857
2858 //*-*- Create a TreeFormulaManager to coordinate the formulas
2859 TTreeFormulaManager *manager=nullptr;
2860 if (fFormulaList->LastIndex()>=0) {
2861 manager = new TTreeFormulaManager;
2862 for(i=0;i<=fFormulaList->LastIndex();i++) {
2863 manager->Add((TTreeFormula*)fFormulaList->At(i));
2864 }
2865 manager->Sync();
2866 }
2867
2868 // loop on all selected entries
2869 const char *aresult;
2870 Int_t len;
2871 char *arow = new char[ncols*50];
2872 fSelectedRows = 0;
2873 Int_t tnumber = -1;
2874 Int_t *fields = new Int_t[ncols];
2875 for (entry=firstentry;entry<firstentry+nentries;entry++) {
2876 entryNumber = fTree->GetEntryNumber(entry);
2877 if (entryNumber < 0) break;
2878 Long64_t localEntry = fTree->LoadTree(entryNumber);
2879 if (localEntry < 0) break;
2880 if (tnumber != fTree->GetTreeNumber()) {
2881 tnumber = fTree->GetTreeNumber();
2882 for (i=0;i<ncols;i++) var[i]->UpdateFormulaLeaves();
2883 }
2884
2885 Int_t ndata = 1;
2886 if (manager && manager->GetMultiplicity()) {
2887 ndata = manager->GetNdata();
2888 }
2889
2890 if (select) {
2891 select->GetNdata();
2892 if (select->EvalInstance(0) == 0) continue;
2893 }
2894
2895 bool loaded = false;
2896 for(int inst=0;inst<ndata;inst++) {
2897 if (select) {
2898 if (select->EvalInstance(inst) == 0) {
2899 continue;
2900 }
2901 }
2902
2903 if (inst==0) loaded = true;
2904 else if (!loaded) {
2905 // EvalInstance(0) always needs to be called so that
2906 // the proper branches are loaded.
2907 for (i=0;i<ncols;i++) {
2908 var[i]->EvalInstance(0);
2909 }
2910 loaded = true;
2911 }
2912 for (i=0;i<ncols;i++) {
2913 aresult = var[i]->PrintValue(0,inst);
2914 len = strlen(aresult)+1;
2915 if (i == 0) {
2916 memcpy(arow,aresult,len);
2917 fields[i] = len;
2918 } else {
2919 memcpy(arow+fields[i-1],aresult,len);
2920 fields[i] = fields[i-1] + len;
2921 }
2922 }
2923 res->AddRow(new TTreeRow(ncols,fields,arow));
2924 fSelectedRows++;
2925 }
2926 }
2927
2928 // delete temporary objects
2930 // The TTreeFormulaManager is deleted by the last TTreeFormula.
2931 delete [] fields;
2932 delete [] arow;
2933 delete [] var;
2934
2935 return res;
2936}
2937
2938////////////////////////////////////////////////////////////////////////////////
2939/// Set number of entries to estimate variable limits.
2940
2942{
2944}
2945
2946////////////////////////////////////////////////////////////////////////////////
2947/// Start the TTreeViewer on this TTree.
2948///
2949/// - ww is the width of the canvas in pixels
2950/// - wh is the height of the canvas in pixels
2951
2953{
2954 // unused variables
2955 (void) ww;
2956 (void) wh;
2957
2958 if (!gApplication)
2960 // make sure that the Gpad and GUI libs are loaded
2961
2962 TString hname = gEnv->GetValue("TreeViewer.Name", "TTreeViewer");
2963
2965 if (gApplication)
2966 gApplication->InitializeGraphics(hname == "RTreeViewer");
2967
2968 if (gROOT->IsBatch()) {
2969 if ((hname != "RTreeViewer") || gROOT->IsWebDisplayBatch()) {
2970 Warning("StartViewer", "The tree viewer cannot run in batch mode");
2971 return;
2972 }
2973 }
2974
2975 if (auto h = gROOT->GetPluginManager()->FindHandler("TVirtualTreeViewer", hname.Data())) {
2976 if (h->LoadPlugin() != -1)
2977 h->ExecPlugin(1, fTree);
2978 }
2979}
2980
2981////////////////////////////////////////////////////////////////////////////////
2982/// Unbinned fit of one or more variable(s) from a Tree.
2983///
2984/// funcname is a TF1 function.
2985///
2986/// See TTree::Draw for explanations of the other parameters.
2987///
2988/// Fit the variable varexp using the function funcname using the
2989/// selection cuts given by selection.
2990///
2991/// The list of fit options is given in parameter option.
2992///
2993/// - option = "Q" Quiet mode (minimum printing)
2994/// - option = "V" Verbose mode (default is between Q and V)
2995/// - option = "E" Perform better Errors estimation using Minos technique
2996/// - option = "M" More. Improve fit results
2997/// - option = "D" Draw the projected histogram with the fitted function
2998/// normalized to the number of selected rows
2999/// and multiplied by the bin width
3000///
3001/// You can specify boundary limits for some or all parameters via
3002/// ~~~{.cpp}
3003/// func->SetParLimits(p_number, parmin, parmax);
3004/// ~~~
3005/// if parmin>=parmax, the parameter is fixed
3006///
3007/// Note that you are not forced to fix the limits for all parameters.
3008/// For example, if you fit a function with 6 parameters, you can do:
3009/// ~~~{.cpp}
3010/// func->SetParameters(0,3.1,1.e-6,0.1,-8,100);
3011/// func->SetParLimits(4,-10,-4);
3012/// func->SetParLimits(5, 1,1);
3013/// ~~~
3014/// With this setup, parameters 0->3 can vary freely
3015/// - Parameter 4 has boundaries [-10,-4] with initial value -8
3016/// - Parameter 5 is fixed to 100.
3017///
3018/// For the fit to be meaningful, the function must be self-normalized.
3019///
3020/// i.e. It must have the same integral regardless of the parameter
3021/// settings. Otherwise the fit will effectively just maximize the
3022/// area.
3023///
3024/// It is mandatory to have a normalization variable
3025/// which is fixed for the fit. e.g.
3026/// ~~~{.cpp}
3027/// TF1* f1 = new TF1("f1", "gaus(0)/sqrt(2*3.14159)/[2]", 0, 5);
3028/// f1->SetParameters(1, 3.1, 0.01);
3029/// f1->SetParLimits(0, 1, 1); // fix the normalization parameter to 1
3030/// data->UnbinnedFit("f1", "jpsimass", "jpsipt>3.0");
3031/// ~~~
3032///
3033/// 1, 2 and 3 Dimensional fits are supported.
3034/// See also TTree::Fit
3035///
3036/// ### Return status
3037///
3038/// The function return the status of the fit in the following form
3039/// ~~~{.cpp}
3040/// fitResult = migradResult + 10*minosResult + 100*hesseResult + 1000*improveResult
3041/// ~~~
3042/// - The fitResult is 0 is the fit is OK.
3043/// - The fitResult is negative in case of an error not connected with the fit.
3044/// - The number of entries used in the fit can be obtained via
3045/// ~~~{.cpp}
3046/// mytree.GetSelectedRows();
3047/// ~~~
3048/// - If the number of selected entries is null the function returns -1
3049///
3050/// new implementation using new Fitter classes
3051
3052Int_t TTreePlayer::UnbinnedFit(const char *funcname ,const char *varexp, const char *selection,Option_t *option ,Long64_t nentries, Long64_t firstentry)
3053{
3054 // function is given by name, find it in gROOT
3055 TF1* fitfunc = (TF1*)gROOT->GetFunction(funcname);
3056 if (!fitfunc) { Error("UnbinnedFit", "Unknown function: %s",funcname); return 0; }
3057
3058 Int_t npar = fitfunc->GetNpar();
3059 if (npar <=0) { Error("UnbinnedFit", "Illegal number of parameters = %d",npar); return 0; }
3060
3061 // Spin through the data to select out the events of interest
3062 // Make sure that the arrays V1,etc are created large enough to accommodate
3063 // all entries
3064 Long64_t oldEstimate = fTree->GetEstimate();
3067
3068 // build FitOptions
3069 TString opt = option;
3070 opt.ToUpper();
3071 Foption_t fitOption;
3072 if (opt.Contains("Q")) fitOption.Quiet = 1;
3073 if (opt.Contains("V")){fitOption.Verbose = 1; fitOption.Quiet = 0;}
3074 if (opt.Contains("E")) fitOption.Errors = 1;
3075 if (opt.Contains("M")) fitOption.More = 1;
3076 if (!opt.Contains("D")) fitOption.Nograph = 1; // what about 0
3077 // could add range and automatic normalization of functions and gradient
3078
3079 TString drawOpt = "goff";
3080 if (!fitOption.Nograph) drawOpt = "";
3081 Long64_t nsel = DrawSelect(varexp, selection,drawOpt, nentries, firstentry);
3082
3083 if (!fitOption.Nograph && GetSelectedRows() <= 0 && GetDimension() > 4) {
3084 Info("UnbinnedFit","Ignore option D with more than 4 variables");
3085 nsel = DrawSelect(varexp, selection,"goff", nentries, firstentry);
3086 }
3087
3088 //if no selected entries return
3089 Long64_t nrows = GetSelectedRows();
3090
3091 if (nrows <= 0) {
3092 Error("UnbinnedFit", "Cannot fit: no entries selected");
3093 return -1;
3094 }
3095
3096 // Check that function has same dimension as number of variables
3097 Int_t ndim = GetDimension();
3098 // do not check with TF1::GetNdim() since it returns 1 for TF1 classes created with
3099 // a C function with larger dimension
3100
3101
3102 // use pointer stored in the tree (not copy the data in)
3103 std::vector<double *> vlist(ndim);
3104 for (int i = 0; i < ndim; ++i)
3105 vlist[i] = fSelector->GetVal(i);
3106
3107 // fill the fit data object
3108 // the object will be then managed by the fitted classes - however it will be invalid when the
3109 // data pointers (given by fSelector->GetVal() ) wil be invalidated
3110 ROOT::Fit::UnBinData * fitdata = new ROOT::Fit::UnBinData(nrows, ndim, vlist.begin());
3111
3112
3113
3115 TFitResultPtr ret = ROOT::Fit::UnBinFit(fitdata,fitfunc, fitOption, minOption);
3116
3117 //reset estimate
3118 fTree->SetEstimate(oldEstimate);
3119
3120 //if option "D" is specified, draw the projected histogram
3121 //with the fitted function normalized to the number of selected rows
3122 //and multiplied by the bin width
3123 if (!fitOption.Nograph && fHistogram) {
3124 if (fHistogram->GetDimension() < 2) {
3125 TH1 *hf = (TH1*)fHistogram->Clone("unbinnedFit");
3126 hf->SetLineWidth(3);
3127 hf->Reset();
3128 Int_t nbins = fHistogram->GetXaxis()->GetNbins();
3129 Double_t norm = ((Double_t)nsel)*fHistogram->GetXaxis()->GetBinWidth(1);
3130 for (Int_t bin=1;bin<=nbins;bin++) {
3131 Double_t func = norm*fitfunc->Eval(hf->GetBinCenter(bin));
3132 hf->SetBinContent(bin,func);
3133 }
3134 fHistogram->GetListOfFunctions()->Add(hf,"lsame");
3135 }
3136 fHistogram->Draw();
3137 }
3138
3139
3140 return int(ret);
3141
3142}
3143
3144////////////////////////////////////////////////////////////////////////////////
3145/// this function is called by TChain::LoadTree when a new Tree is loaded.
3146/// Because Trees in a TChain may have a different list of leaves, one
3147/// must update the leaves numbers in the TTreeFormula used by the TreePlayer.
3148
3150{
3151 if (fSelector) fSelector->Notify();
3152 if (fSelectorUpdate){
3153 //If the selector is writing into a TEntryList, the entry list's
3154 //sublists need to be changed according to the loaded tree
3156 //FIXME: should be more consistent with selector from file
3157 TObject *obj = fSelector->GetObject();
3158 if (obj){
3161 }
3162 }
3163 }
3166 TEntryList *elist=nullptr;
3167 while ((elist=(TEntryList*)next())){
3168 if (elist->InheritsFrom(TEntryList::Class())){
3169 elist->SetTree(fTree->GetTree());
3170 }
3171 }
3172 }
3173 }
3174
3175 if (fFormulaList->GetSize()) {
3177 while (lnk) {
3178 lnk->GetObject()->Notify();
3179 lnk = lnk->Next();
3180 }
3181 }
3182}
#define R__EXTERN
Definition DllImport.h:26
#define h(i)
Definition RSha256.hxx:106
double Double_t
Definition RtypesCore.h:59
constexpr Ssiz_t kNPOS
Definition RtypesCore.h:124
long long Long64_t
Definition RtypesCore.h:80
const char Option_t
Definition RtypesCore.h:66
#define ClassImp(name)
Definition Rtypes.h:377
R__EXTERN TApplication * gApplication
#define gDirectory
Definition TDirectory.h:384
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
R__EXTERN TVirtualMutex * gROOTMutex
Definition TROOT.h:63
#define gROOT
Definition TROOT.h:406
char * Form(const char *fmt,...)
Formats a string in a circular formatting buffer.
Definition TString.cxx:2489
void Printf(const char *fmt,...)
Formats a string in a circular formatting buffer and prints the string.
Definition TString.cxx:2503
R__EXTERN TStyle * gStyle
Definition TStyle.h:433
R__EXTERN TSystem * gSystem
Definition TSystem.h:555
TVirtualFitter * tFitter
R__EXTERN Foption_t Foption
static TString R__GetBranchPointerName(TLeaf *leaf, bool replace=true)
Return the name of the branch pointer needed by MakeClass/MakeSelector.
R__EXTERN TVirtualMonitoringWriter * gMonitoringWriter
#define R__LOCKGUARD(mutex)
#define gPad
#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(Bool_t only_web=kFALSE)
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:125
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.
Int_t GetStreamerType() const
TBranchElement * GetBranchCount2() const
Int_t GetType() const
bool IsBranchFolder() const
static TClass * Class()
A TTree is a list of TBranches.
Definition TBranch.h:93
virtual const char * GetClassName() const
Return the name of the user class whose content is stored in this branch, if any.
Definition TBranch.cxx:1324
static TClass * Class()
TObjArray * GetListOfBranches()
Definition TBranch.h:246
TClass * IsA() const override
Definition TBranch.h:295
Int_t GetNleaves() const
Definition TBranch.h:249
TObjArray * GetListOfLeaves()
Definition TBranch.h:247
TBranch * GetMother() const
Get our top-level parent branch in the tree.
Definition TBranch.cxx:2127
A TChainElement describes a component of a TChain.
A Chain Index.
Definition TChainIndex.h:40
A chain is a collection of files containing TTree objects.
Definition TChain.h:33
static TClass * Class()
Long64_t * GetTreeOffset() const
Definition TChain.h:121
Long64_t LoadTree(Long64_t entry) override
Find the tree which contains entry, and set it as the current tree.
Definition TChain.cxx:1298
Int_t GetNtrees() const
Definition TChain.h:99
TLeaf * GetLeaf(const char *branchname, const char *leafname) override
Return a pointer to the leaf name in the current tree.
Definition TChain.cxx:1052
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:6685
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:5912
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:4599
Bool_t InheritsFrom(const char *cl) const override
Return kTRUE if this class inherits from a class with name "classname".
Definition TClass.cxx:4874
const char * GetDeclFileName() const
Return name of the file containing the declaration of this class.
Definition TClass.cxx:3463
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:2968
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
This class stores the date and time with a precision of one second in an unsigned 32 bit word (950130...
Definition TDatime.h:37
const char * AsString() const
Return the date & time as a string (ctime() format).
Definition TDatime.cxx:102
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.
virtual TFile * GetFile() const
Definition TDirectory.h:220
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:233
virtual Int_t GetNpar() const
Definition TF1.h:507
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:1441
A ROOT file is composed of a header, followed by consecutive data records (TKey instances) with a wel...
Definition TFile.h:53
static Long64_t GetFileBytesRead()
Static function returning the total number of bytes read from all files.
Definition TFile.cxx:4551
TFileCacheRead * GetCacheRead(const TObject *tree=nullptr) const
Return a pointer to the current read cache.
Definition TFile.cxx:1240
Provides an indirection to the TFitResult class and with a semantics identical to a TFitResult pointe...
TH1 is the base class of all histogram classes in ROOT.
Definition TH1.h:59
virtual Double_t GetBinCenter(Int_t bin) const
Return bin center for 1D histogram.
Definition TH1.cxx:9105
@ kNoAxis
NOTE: Must always be 0 !!!
Definition TH1.h:72
virtual Int_t GetDimension() const
Definition TH1.h:283
virtual void Reset(Option_t *option="")
Reset this histogram: contents, errors, etc.
Definition TH1.cxx:7067
TAxis * GetXaxis()
Definition TH1.h:324
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:3062
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:9186
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:6613
TList * GetListOfFunctions() const
Definition TH1.h:244
virtual void Scale(Double_t c1=1, Option_t *option="")
Multiply this histogram by a constant c1.
Definition TH1.cxx:6568
TObject * Clone(const char *newname="") const override
Make a complete copy of the underlying object.
Definition TH1.cxx:2748
virtual Double_t GetSumOfWeights() const
Return the sum of weights excluding under/overflows.
Definition TH1.cxx:7881
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:400
TObject * FindObject(const char *name) const override
Find an object in this list using its name.
Definition TList.cxx:576
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:468
TObject * At(Int_t idx) const override
Returns the object at position idx. Returns 0 if idx is out of range.
Definition TList.cxx:355
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.
TObject * Last() const override
Return the object in the last filled slot. Returns 0 if no entries.
Int_t GetEntries() const override
Return the number of objects in array (i.e.
void Delete(Option_t *option="") override
Remove all objects from the array AND delete all heap based objects.
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.
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 (the base implementation is no-op).
Definition TObject.cxx:594
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:439
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:962
virtual TObject * FindObject(const char *name) const
Must be redefined in derived classes.
Definition TObject.cxx:403
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:780
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:525
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:976
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:950
A 3D polymarker.
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:92
A container proxy, which allows to access references stored in a TRefArray from TTree::Draw.
A specialized TSelector for TTree::Draw.
virtual void SetEstimate(Long64_t n)
Set number of entries to estimate variable limits.
TTreeFormula * GetVar3() const
See TSelectorDraw::GetVar.
virtual Long64_t GetDrawFlag() const
TH1 * GetOldHistogram() const
virtual UInt_t SplitNames(const TString &varexp, std::vector< TString > &names)
Build Index array for names in varexp.
TObject * GetObject() const
TTreeFormula * GetVar2() const
See TSelectorDraw::GetVar.
virtual Int_t GetAction() const
TTreeFormula * GetVar1() const
See TSelectorDraw::GetVar.
virtual Int_t GetDimension() const
virtual Double_t * GetVal(Int_t i) const
Return the last values corresponding to the i-th component of the formula being processed (where the ...
bool Notify() override
This function is called at the first entry of a new tree in a chain.
virtual bool GetCleanElist() const
The class is derived from the ROOT class TSelector.
virtual Long64_t GetSelectedRows() const
A TSelector object is used by the TTree::Draw, TTree::Scan, TTree::Process to navigate in a TTree and...
Definition TSelector.h:31
virtual EAbort GetAbort() const
Definition TSelector.h:73
virtual void ProcessFill(Long64_t)
This method is called for all selected entries.
@ kAbortProcess
Definition TSelector.h:34
virtual void Init(TTree *)
Definition TSelector.h:53
virtual int Version() const
Definition TSelector.h:52
virtual bool ProcessCut(Long64_t)
This method is called before processing entry.
virtual bool Process(Long64_t)
The Process() function is called for each entry in the tree (or possibly keyed object in the case of ...
TClass * IsA() const override
Definition TSelector.h:79
virtual void SlaveBegin(TTree *)
Definition TSelector.h:55
bool Notify() override
This method must be overridden to handle object notification (the base implementation is no-op).
Definition TSelector.h:56
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...
Int_t LastIndex() const
static TClass * Class()
const char * GetTypeName() const
TClass * IsA() const override
Basic string class.
Definition TString.h:139
Ssiz_t Length() const
Definition TString.h:417
void ToLower()
Change string to lower-case.
Definition TString.cxx:1182
const char * Data() const
Definition TString.h:376
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition TString.h:704
Ssiz_t Last(char c) const
Find last occurrence of a character c.
Definition TString.cxx:931
void ToUpper()
Change string to upper case.
Definition TString.cxx:1195
TString & Remove(Ssiz_t pos)
Definition TString.h:685
TString & Append(const char *cs)
Definition TString.h:572
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition TString.cxx:2356
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:632
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:651
Bool_t GetCanvasPreferGL() const
Definition TStyle.h:186
void SetCanvasPreferGL(Bool_t prefer=kTRUE)
Definition TStyle.h:339
Int_t GetNumberOfColors() const
Return number of colors in the color palette.
Definition TStyle.cxx:1171
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:966
virtual TString SplitAclicMode(const char *filename, TString &mode, TString &args, TString &io) const
This method split a filename of the form:
Definition TSystem.cxx:4258
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 forceLoadDim=false)
Return number of available instances in the formulas.
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 bool Sync()
Synchronize all the formulae.
virtual Int_t GetMultiplicity() const
Used to pass a selection expression to the Tree drawing routine.
virtual bool IsInteger(bool fast=true) const
Return TRUE if the formula corresponds to one single Tree leaf and this leaf is short,...
TTreeFormulaManager * GetManager() const
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
Int_t MakeCode(const char *filename) override
Generate skeleton function for this Tree.
TTree * CopyTree(const char *selection, Option_t *option, Long64_t nentries, Long64_t firstentry) override
Copy a Tree with selection, make a clone of this Tree header, then copy the selected entries.
Long64_t DrawSelect(const char *varexp, const char *selection, Option_t *option, Long64_t nentries, Long64_t firstentry) override
Draw expression varexp for specified entries that matches the selection.
TList * fInput
! input list to the selector
Definition TTreePlayer.h:53
void DeleteSelectorFromFile()
Delete any selector created by this object.
void SetEstimate(Long64_t n) override
Set number of entries to estimate variable limits.
Int_t UnbinnedFit(const char *formula, const char *varexp, const char *selection, Option_t *option, Long64_t nentries, Long64_t firstentry) override
Unbinned fit of one or more variable(s) from a Tree.
void RecursiveRemove(TObject *obj) override
cleanup pointers in the player pointing to obj
Long64_t DrawScript(const char *wrapperPrefix, const char *macrofilename, const char *cutfilename, Option_t *option, Long64_t nentries, Long64_t firstentry) override
Draw the result of a C++ script.
TSelectorDraw * fSelector
! Pointer to current selector
Definition TTreePlayer.h:50
void SetTree(TTree *t) override
Long64_t GetSelectedRows() const override
Definition TTreePlayer.h:81
Int_t MakeReader(const char *classname, Option_t *option) override
Generate skeleton selector class for this tree.
const char * GetNameByIndex(TString &varexp, Int_t *index, Int_t colindex)
Return name corresponding to colindex in varexp.
Long64_t fSelectedRows
Number of selected entries.
Definition TTreePlayer.h:48
Long64_t Scan(const char *varexp, const char *selection, Option_t *option, Long64_t nentries, Long64_t firstentry) override
Loop on Tree and print entries passing selection.
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
bool fScanRedirect
Switch to redirect TTree::Scan output to a file.
Definition TTreePlayer.h:45
TTree * fTree
! Pointer to current Tree
Definition TTreePlayer.h:44
void StartViewer(Int_t ww, Int_t wh) override
Start the TTreeViewer on this TTree.
Int_t MakeProxy(const char *classname, const char *macrofilename=nullptr, const char *cutfilename=nullptr, const char *option=nullptr, Int_t maxUnrolling=3) override
Generate a skeleton analysis class for this Tree using TBranchProxy.
Int_t MakeClass(const char *classname, Option_t *option) override
Generate skeleton analysis class for this Tree.
TPrincipal * Principal(const char *varexp, const char *selection, Option_t *option, Long64_t nentries, Long64_t firstentry) override
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
void UpdateFormulaLeaves() override
this function is called by TChain::LoadTree when a new Tree is loaded.
Long64_t Process(const char *filename, Option_t *option, Long64_t nentries, Long64_t firstentry) override
Process this tree executing the TSelector code in the specified filename.
TSQLResult * Query(const char *varexp, const char *selection, Option_t *option, Long64_t nentries, Long64_t firstentry) override
Loop on Tree and return TSQLResult object containing entries passing selection.
TClass * fSelectorClass
! Pointer to the actual class of the TSelectorFromFile
Definition TTreePlayer.h:52
Long64_t GetEntries(const char *selection) override
Return the number of entries matching the selection.
Int_t GetDimension() const override
Definition TTreePlayer.h:74
Int_t fDimension
Dimension of the current expression.
Definition TTreePlayer.h:47
TVirtualIndex * BuildIndex(const TTree *T, const char *majorname, const char *minorname) override
Build the index for the tree (see TTree::BuildIndex)
TTreePlayer()
Default Tree constructor.
~TTreePlayer() override
Tree destructor.
Int_t Fit(const char *formula, const char *varexp, const char *selection, Option_t *option, Option_t *goption, Long64_t nentries, Long64_t firstentry) override
Fit a projected item(s) from a Tree.
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
bool EnableCache()
Enable the TTreeCache unless explicitly disabled for this TTree by a prior call to SetCacheSize(0).
Definition TTree.cxx:2685
virtual TBranch * GetBranch(const char *name)
Return pointer to the branch with the given name in this tree or its friends.
Definition TTree.cxx:5294
virtual Int_t GetScanField() const
Definition TTree.h:511
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:5638
virtual Long64_t GetEstimate() const
Definition TTree.h:467
virtual TObjArray * GetListOfLeaves()
Definition TTree.h:489
TFile * GetCurrentFile() const
Return pointer to the current file.
Definition TTree.cxx:5479
void Draw(Option_t *opt) override
Default Draw method for all objects.
Definition TTree.h:431
virtual void SetNotify(TObject *obj)
Sets the address of the object to be notified when the tree is loaded.
Definition TTree.cxx:9221
TDirectory * GetDirectory() const
Definition TTree.h:462
virtual TEntryList * GetEntryList()
Returns the entry list assigned to this tree.
Definition TTree.cxx:5854
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:7450
virtual Long64_t GetEntries() const
Definition TTree.h:463
virtual void SetEstimate(Long64_t nentries=1000000)
Set number of entries to estimate variable limits.
Definition TTree.cxx:9100
virtual Long64_t GetEntryNumber(Long64_t entry) const
Return entry number corresponding to entry.
Definition TTree.cxx:5865
virtual TTree * CloneTree(Long64_t nentries=-1, Option_t *option="")
Create a clone of this tree and copy nentries.
Definition TTree.cxx:3139
virtual TTree * GetTree() const
Definition TTree.h:517
virtual void SetEntryList(TEntryList *list, Option_t *opt="")
Set an EntryList.
Definition TTree.cxx:9036
virtual Long64_t LoadTree(Long64_t entry)
Set current entry.
Definition TTree.cxx:6473
TEventList * GetEventList() const
Definition TTree.h:473
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:5512
virtual Int_t GetTreeNumber() const
Definition TTree.h:519
virtual Int_t GetTimerInterval() const
Definition TTree.h:514
virtual void SetScanField(Int_t n=50)
Definition TTree.h:645
virtual Long64_t GetCacheSize() const
Definition TTree.h:453
virtual Long64_t GetMaxEntryLoop() const
Definition TTree.h:497
Abstract Base Class for Fitting.
Abstract interface for Tree Index.
virtual Bool_t SendProcessingProgress(Double_t, Double_t, Bool_t=kFALSE)
virtual Bool_t SendProcessingStatus(const char *, Bool_t=kFALSE)
virtual TObjArray * GetElements() const =0
const Int_t n
Definition legend1.C:16
TFitResultPtr UnBinFit(ROOT::Fit::UnBinData *data, TF1 *f1, Foption_t &option, const ROOT::Math::MinimizerOptions &moption)
fit an unbin data set (from tree or from histogram buffer) using a TF1 pointer and fit options.
Definition HFitImpl.cxx:821
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 graph.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