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