20 #include "TClassEdit.h"
58 Warning(
"AddReader",
"Ingored branch %s because type is unknown.", branchName.
Data());
66 Warning(
"AddReader",
"Ignored branch %s because a branch with the same name already exists. "
67 "TTreeReader requires an unique name for the branches. You may need to "
68 "put a dot at the end of the name of top-level branches.", branchName.
Data());
86 if (info==0) info = branch->
GetInfo();
110 containerName =
"TClonesArray";
111 }
else if (desc && desc->
IsSTL()) {
112 outer_isclones =
kSTL;
117 containerName =
"TClonesArray";
119 outer_isclones =
kSTL;
137 subBranchPrefix = mom->
GetName();
138 if (subBranchPrefix[subBranchPrefix.
Length()-1]==
'.') {
141 subBranchPrefix =
"";
166 Error(
"AnalyzeBranches",
"Ran out of branches when looking in branch %s, class %s",
169 Error(
"AnalyzeBranches",
"Ran out of branches when looking in class %s, element %s",
170 info->
GetName(), element->GetName());
179 if (element->GetType() == -1) {
188 if (leaf && outer_isclones ==
kOut
190 else branchEndName = branch->
GetName();
192 pos = branchEndName.
Index(
".");
194 if (subBranchPrefix.
Length() && branchEndName.
BeginsWith(subBranchPrefix)) {
205 switch(element->GetType()) {
274 readerType = TTreeReaderDescriptor::ReaderType::kArray;
282 TClass *cl = element->GetClassPointer();
288 containerName =
"TClonesArray";
289 if (outer_isclones !=
kOut) {
290 isclones = outer_isclones;
291 dataType =
"TClonesArray";
293 readerType = TTreeReaderDescriptor::ReaderType::kArray;
299 if (outer_isclones !=
kOut || containerName.
EqualTo(
"vector<bool>")) {
305 isclones = outer_isclones;
308 readerType = TTreeReaderDescriptor::ReaderType::kArray;
311 dataType = valueClass->
GetName();
315 if (valueClassBuiltIn) dataType = valueClassBuiltIn->
GetName();
316 else Error(
"AnalyzeBranches",
"Could not get type from collection %s in branch %s", cl->
GetName(), branch->
GetName());
340 if (element->IsBase()) {
349 if (branchEndName == element->GetName()) {
360 isclones, containerName, desc);
376 cl = objInfo->GetClass();
378 isclones, containerName, desc);
386 if (branchEndName == element->GetName()) {
391 if (isclones !=
kOut) {
397 isclones, containerName, desc);
404 if (local_prefix.
Length()) local_prefix +=
".";
405 local_prefix += element->GetName();
411 if (isclones !=
kOut) {
417 isclones, containerName, desc);
429 Error(
"AnalyzeBranch",
"Unsupported type for %s (%d).", branch->
GetName(), element->GetType());
432 if (!isBase && !skipped) {
433 if (outer_isclones !=
kOut && readerType == TTreeReaderDescriptor::ReaderType::kArray) {
434 Error(
"AnalyzeBranch",
"Arrays inside collections are not supported yet (branch: %s).", branch->
GetName());
436 if (outer_isclones !=
kOut || isclones !=
kOut) {
437 readerType = TTreeReaderDescriptor::ReaderType::kArray;
468 for(
int l=0;
l<nleaves;
l++) {
473 return extraLookedAt;
482 Error(
"AnalyzeOldLeaf",
"TLeafObject not supported yet");
492 std::vector<Int_t> maxDim;
496 pos = temp.
Index(
"[");
498 if (pos) temp.
Remove(0, pos);
502 pos = temp.
Index(
"[");
504 if (pos) temp.
Remove(0, pos);
511 const char *current = dimensions.
Data();
517 if (current[0] ==
']') {
518 maxDim.push_back(-1);
520 scanindex = sscanf(current,
"%d",&index);
522 maxDim.push_back(index);
524 maxDim.push_back(-2);
528 current = (
char*)strstr( current,
"[" );
540 type = TTreeReaderDescriptor::ReaderType::kValue;
541 dataType = leafTypeName;
545 type = TTreeReaderDescriptor::ReaderType::kArray;
546 dataType = leafTypeName;
625 if ( token.
Length() == 0 || (token.
Length() == 1 && token[0] ==
'@') ) {
626 Warning(
"ParseOptions",
"Ignored empty branch name in option string.");
627 }
else if (token[0] ==
'@') {
650 while ( (branch = (
TBranch*)next()) ) {
654 const char *branchClassName = branch->GetClassName();
658 if (branchClassName && strlen(branchClassName)) {
671 containerName =
"TClonesArray";
681 "Introspection of TClonesArray in older file not implemented yet.");
688 branch->SetAddress(&clones);
697 "Introspection of TClonesArray for %s failed.",branch->GetName());
712 if (containerName.
EqualTo(
"vector<bool>")) {
713 AddReader(TTreeReaderDescriptor::ReaderType::kValue,
715 branch->GetName(), branch->GetName(), 0,
kTRUE);
717 AddReader(TTreeReaderDescriptor::ReaderType::kArray,
719 branch->GetName(), branch->GetName(), 0,
kTRUE);
737 TTreeReaderDescriptor::ReaderType::kValue
738 : TTreeReaderDescriptor::ReaderType::kArray,
746 if (branch->GetListOfBranches()->GetEntries() == 0) {
751 TTreeReaderDescriptor::ReaderType::kValue
752 : TTreeReaderDescriptor::ReaderType::kArray,
759 TIter subnext( branch->GetListOfBranches() );
766 Error(
"AnalyzeTree",
"Cannot analyze branch %s because it is not a TBranchElement.", branchName);
770 TTreeReaderDescriptor::ReaderType::kValue
771 : TTreeReaderDescriptor::ReaderType::kArray,
791 treefile =
"Memory Directory";
804 std::ofstream ofs (thead, std::ofstream::out);
806 Error(
"WriteSelector",
"cannot open output file %s", thead.
Data());
812 R
"CODE(//////////////////////////////////////////////////////////
// This class has been automatically generated on
// )CODE" << td.AsString() << R"CODE( by ROOT version )CODE" << gROOT->GetVersion() << std::endl;
815 <<
"// found on file: " << treefile << std::endl;
820 R
"CODE(//////////////////////////////////////////////////////////
#ifndef )CODE" << fClassname << R"CODE(_h
#define )CODE" << fClassname << R"CODE(_h
#include <TROOT.h>
#include <TChain.h>
#include <TFile.h>
)CODE";
821 if (isHbook) ofs <<
"#include <THbookFile.h>" << std::endl;
823 R
"CODE(#include <TSelector.h>
#include <TTreeReader.h>
#include <TTreeReaderValue.h>
#include <TTreeReaderArray.h>
// Headers needed by this particular selector
)CODE";
827 while ( (header = next()) ) {
828 ofs << header->
GetTitle() << std::endl;
830 ofs << std::endl << std::endl;
834 R
"CODE(class )CODE" << fClassname << R"CODE( : public TSelector {
public :
TTreeReader fReader; //!the tree reader
TTree *fChain = 0; //!pointer to the analyzed TTree or TChain
// Readers to access the data (delete the ones you do not need).
)CODE";
838 ofs <<
" TTreeReader" << (descriptor->
fType == TTreeReaderDescriptor::ReaderType::kValue ?
"Value" :
"Array")
840 <<
"> " << descriptor->
fName
841 <<
" = {fReader, \"" << descriptor->
fBranchName <<
"\"};" << std::endl;
845 R
"CODE(
)CODE" << fClassname << R"CODE((TTree * /*tree*/ =0) { }
virtual ~)CODE" << fClassname << R"CODE(() { }
virtual Int_t Version() const { return 2; }
virtual void Begin(TTree *tree);
virtual void SlaveBegin(TTree *tree);
virtual void Init(TTree *tree);
virtual Bool_t Notify();
virtual Bool_t Process(Long64_t entry);
virtual Int_t GetEntry(Long64_t entry, Int_t getall = 0) { return fChain ? fChain->GetTree()->GetEntry(entry, getall) : 0; }
virtual void SetOption(const char *option) { fOption = option; }
virtual void SetObject(TObject *obj) { fObject = obj; }
virtual void SetInputList(TList *input) { fInput = input; }
virtual TList *GetOutputList() const { return fOutput; }
virtual void SlaveTerminate();
virtual void Terminate();
ClassDef()CODE" << fClassname << R"CODE(,0);
};
#endif
#ifdef )CODE" << fClassname << R"CODE(_cxx
void )CODE" << fClassname << R"CODE(::Init(TTree *tree)
{
// The Init() function is called when the selector needs to initialize
// a new tree or chain. Typically here the reader is initialized.
// It is normally not necessary to make changes to the generated
// code, but the routine can be extended by the user if needed.
// Init() will be called many times when running on PROOF
// (once per file to be processed).
fReader.SetTree(tree);
}
Bool_t )CODE" << fClassname << R"CODE(::Notify()
{
// The Notify() function is called when a new file is opened. This
// can be either for a new TTree in a TChain or when when a new TTree
// is started when using PROOF. It is normally not necessary to make changes
// to the generated code, but the routine can be extended by the
// user if needed. The return value is currently not used.
return kTRUE;
}
#endif // #ifdef )CODE" << fClassname << R"CODE(_cxx
)CODE";
850 tcimp.
Form(
"%s.C", fClassname.Data());
851 std::ofstream ofsc (tcimp, std::ofstream::out);
853 Error(
"WriteSelector",
"cannot open output file %s", tcimp.
Data());
858 R
"CODE(#define )CODE" << fClassname << R"CODE(_cxx
// The class definition in )CODE" << fClassname << R"CODE(.h has been generated automatically
// by the ROOT utility TTree::MakeSelector(). This class is derived
// from the ROOT class TSelector. For more information on the TSelector
// framework see $ROOTSYS/README/README.SELECTOR or the ROOT User Manual.
// The following methods are defined in this file:
// Begin(): called every time a loop on the tree starts,
// a convenient place to create your histograms.
// SlaveBegin(): called after Begin(), when on PROOF called only on the
// slave servers.
// Process(): called for each event, in this function you decide what
// to read and fill your histograms.
// SlaveTerminate: called at the end of the loop on the tree, when on PROOF
// called only on the slave servers.
// Terminate(): called at the end of the loop on the tree,
// a convenient place to draw/fit your histograms.
//
// To use this file, try the following session on your Tree T:
//
// root> T->Process(")CODE" << fClassname << R"CODE(.C")
// root> T->Process(")CODE" << fClassname << R"CODE(.C","some options")
// root> T->Process(")CODE" << fClassname << R"CODE(.C+")
//
#include ")CODE" << thead << R"CODE("
#include <TH2.h>
#include <TStyle.h>
void )CODE" << fClassname << R"CODE(::Begin(TTree * /*tree*/)
{
// The Begin() function is called at the start of the query.
// When running with PROOF Begin() is only called on the client.
// The tree argument is deprecated (on PROOF 0 is passed).
TString option = GetOption();
}
void )CODE" << fClassname << R"CODE(::SlaveBegin(TTree * /*tree*/)
{
// The SlaveBegin() function is called after the Begin() function.
// When running with PROOF SlaveBegin() is called on each slave server.
// The tree argument is deprecated (on PROOF 0 is passed).
TString option = GetOption();
}
Bool_t )CODE" << fClassname << R"CODE(::Process(Long64_t entry)
{
// The Process() function is called for each entry in the tree (or possibly
// keyed object in the case of PROOF) to be processed. The entry argument
// specifies which entry in the currently loaded tree is to be processed.
// When processing keyed objects with PROOF, the object is already loaded
// and is available via the fObject pointer.
//
// This function should contain the \"body\" of the analysis. It can contain
// simple or elaborate selection criteria, run algorithms on the data
// of the event and typically fill histograms.
//
// The processing can be stopped by calling Abort().
//
// Use fStatus to set the return value of TTree::Process().
//
// The return value is currently not used.
fReader.SetEntry(entry);
return kTRUE;
}
void )CODE" << fClassname << R"CODE(::SlaveTerminate()
{
// The SlaveTerminate() function is called after all entries or objects
// have been processed. When running with PROOF SlaveTerminate() is called
// on each slave server.
}
void )CODE" << fClassname << R"CODE(::Terminate()
{
// The Terminate() function is the last function to be called during
// a query. It always runs on the client, it can be used to present
// the results graphically or save the results to file.
})CODE";
864 virtual const char * GetTitle() const
Returns title of object.
std::string GetName(const std::string &scope_name)
A TLeaf describes individual elements of a TBranch See TBranch structure in TTree.
Ssiz_t Last(char c) const
Find last occurrence of a character c.
static TDataType * GetDataType(EDataType type)
Given a EDataType type, get the TDataType* that represents it.
UInt_t AnalyzeOldLeaf(TLeaf *leaf, Int_t nleaves)
Analyze the leaf and add the variables found.
std::vector< TString > fIncludeStruct
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
virtual TClass * GetClass() const =0
Collectable string class.
virtual TClass * GetValueClass() const =0
TString & ReplaceAll(const TString &s1, const TString &s2)
void AnalyzeTree(TTree *tree)
Analyze tree and extract readers.
void AddHeader(TClass *cl)
Add a header inclusion request.
TTreeReaderGenerator(TTree *tree, const char *classname, Option_t *option)
Constructor. Analyzes the tree and writes selector.
TBranchDescriptor * fParent
TBranch * GetBranch() const
std::vector< TString > fIncludeLeaves
Int_t GetEntriesFast() const
virtual EDataType GetType() const =0
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
TString GetContainedClassName(TBranchElement *branch, TStreamerElement *element, Bool_t ispointer)
Get name of class inside a container.
UInt_t AnalyzeBranches(TBranchDescriptor *desc, TBranchElement *branch, TVirtualStreamerInfo *info)
Analyse sub-branches of 'branch' recursively and extract readers.
TBranchElement * GetBranchCount() const
const char * Data() const
void WriteSelector()
Generate code for selector class.
virtual TObjArray * GetListOfBranches()
TStreamerInfo * GetInfo() const
Get streamer info for the branch class.
TString & Append(const char *cs)
TObjArray * GetListOfBranches()
virtual TBranch * GetBranch(const char *name)
Return pointer to the branch with the given name in this tree or its friends.
virtual TFile * GetFile() const
TObject * UncheckedAt(Int_t i) const
virtual const char * GetTypeName() const
TVirtualStreamerInfo * GetStreamerInfo(Int_t version=0) const
returns a pointer to the TVirtualStreamerInfo object for version If the object does not exist...
Bool_t EqualTo(const char *cs, ECaseCompare cmp=kExact) const
Basic data type descriptor (datatype information is obtained from CINT).
TDirectory * GetDirectory() const
TBranch * GetMother() const
Get our top-level parent branch in the tree.
TVirtualStreamerInfo * GetStreamerInfo(TBranch *branch, TIter current, TClass *cl)
Return the correct TStreamerInfo of class 'cl' in the list of branches (current) [Assuming these bran...
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Bool_t TestBit(UInt_t f) const
Bool_t fIncludeAllTopmost
Bool_t CanIgnoreTObjectStreamer()
virtual const char * GetName() const
Returns name of object.
The ROOT global object gROOT contains a list of all defined classes.
TBranch * GetSubBranch(const TBranch *br) const
Find the parent branch of child.
void Warning(const char *location, const char *msgfmt,...)
TObjArray * Tokenize(const TString &delim) const
This function is used to isolate sequential tokens in a TString.
A Branch for the case of an object.
TString & Remove(Ssiz_t pos)
virtual TObjArray * GetElements() const =0
TClass * GetClass() const
void ParseOptions()
Parse the user options.
TObjArray * GetListOfLeaves()
Int_t GetEntries() const
Return the number of objects in array (i.e.
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.
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Mother of all ROOT objects.
An array of clone (identical) objects.
virtual void Add(TObject *obj)
Bool_t BranchNeedsReader(TString branchName, TBranchDescriptor *parent, Bool_t isLeaf)
Check whether a branch should have a corresponding reader added, depending on the options provided by...
A TTree object has a header with a name and a title.
void AddReader(TTreeReaderDescriptor::ReaderType type, TString dataType, TString name, TString branchName, TBranchDescriptor *parent=0, Bool_t isLeaf=kTRUE)
Add a reader to the generated code.
UInt_t AnalyzeOldBranch(TBranch *branch)
Analyze branch and add the variables found.
TObject * At(Int_t idx) const
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
A TTree is a list of TBranches.
Abstract Interface class describing Streamer information for one class.
virtual const char * GetClassName() const
Return the name of the user class whose content is stored in this branch, if any. ...
const char * AsString() const
Return the date & time as a string (ctime() format).
virtual const char * GetTitle() const
Returns title of object.
TVirtualStreamerInfo * GetBaseClass(TStreamerElement *element)
Check if element is a base class and if yes, return the base class.
void Error(ErrorHandler_t func, int code, const char *va_(fmt),...)
Write error message and call a handler, if required.
This class stores the date and time with a precision of one second in an unsigned 32 bit word (950130...