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