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