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