40 TTreeReaderGenerator::TTreeReaderGenerator(TTree* tree,
const char *classname, Option_t *option) :
41 TTreeGeneratorBase(tree, option), fClassname(classname),
42 fIncludeAllLeaves(kFALSE), fIncludeAllTopmost(kFALSE)
52 void TTreeReaderGenerator::AddReader(TTreeReaderDescriptor::ReaderType type, TString dataType, TString name,
53 TString branchName, TBranchDescriptor *parent, Bool_t isLeaf)
55 if(BranchNeedsReader(branchName, parent, isLeaf)) {
57 if (dataType.EqualTo(
"")) {
58 Warning(
"TTreeReaderGenerator::AddReader",
"Ignored branch %s because type is unsupported.", branchName.Data());
62 TIter next(&fListOfReaders);
63 TTreeReaderDescriptor *descriptor;
64 while ( ( descriptor = (TTreeReaderDescriptor*)next() ) ) {
65 if (descriptor->fBranchName.EqualTo(branchName)) {
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());
72 name.ReplaceAll(
'.',
'_');
74 while (name.Index(
'[') >= 0 && name.Index(
']') >= 0 && name.Index(
']') > name.Index(
'[')) {
75 name.Remove(name.Index(
'['), name.Index(
']') - name.Index(
'[') + 1);
77 fListOfReaders.Add(
new TTreeReaderDescriptor(type, dataType, name, branchName) );
84 UInt_t TTreeReaderGenerator::AnalyzeBranches(TBranchDescriptor *desc, TBranchElement *branch, TVirtualStreamerInfo *info)
86 if (info==0) info = branch->GetInfo();
88 TIter branches(branch->GetListOfBranches());
90 return AnalyzeBranches(desc, branches, info);
96 UInt_t TTreeReaderGenerator::AnalyzeBranches(TBranchDescriptor *desc, TIter &branches, TVirtualStreamerInfo *info)
99 ELocation outer_isclones = kOut;
100 TString containerName;
101 TString subBranchPrefix;
102 Bool_t skipped =
false;
106 TIter peek = branches;
107 TBranchElement *branch = (TBranchElement*)peek();
108 if (desc && desc->IsClones()) {
109 outer_isclones = kClones;
110 containerName =
"TClonesArray";
111 }
else if (desc && desc->IsSTL()) {
112 outer_isclones = kSTL;
113 containerName = desc->fContainerName;
114 }
else if (!desc && branch && branch->GetBranchCount() == branch->GetMother()) {
115 if ( ((TBranchElement*)(branch->GetMother()))->GetType()==3) {
116 outer_isclones = kClones;
117 containerName =
"TClonesArray";
119 outer_isclones = kSTL;
120 containerName = branch->GetMother()->GetClassName();
134 subBranchPrefix = desc->fSubBranchPrefix;
136 TBranchElement *mom = (TBranchElement*)branch->GetMother();
137 subBranchPrefix = mom->GetName();
138 if (subBranchPrefix[subBranchPrefix.Length()-1]==
'.') {
139 subBranchPrefix.Remove(subBranchPrefix.Length()-1);
140 }
else if (mom->GetType()!=3 && mom->GetType() != 4) {
141 subBranchPrefix =
"";
151 TIter elements( info->GetElements() );
152 for( TStreamerElement *element = (TStreamerElement*)elements();
154 element = (TStreamerElement*)elements() )
156 Bool_t isBase =
false;
157 Bool_t usedBranch = kTRUE;
158 Bool_t isLeaf =
true;
159 TIter peek = branches;
162 TBranchElement *branch = (TBranchElement*)peek();
166 Error(
"AnalyzeBranches",
"Ran out of branches when looking in branch %s, class %s",
167 desc->fBranchName.Data(), info->GetName());
169 Error(
"AnalyzeBranches",
"Ran out of branches when looking in class %s, element %s",
170 info->GetName(), element->GetName());
175 if (info->GetClass()->GetCollectionProxy() && strcmp(element->GetName(),
"This")==0) {
179 if (element->GetType() == -1) {
184 TString branchname = branch->GetName();
185 TString branchEndName;
187 TLeaf *leaf = (TLeaf*)branch->GetListOfLeaves()->At(0);
188 if (leaf && outer_isclones == kOut
189 && !(branch->GetType() == 3 || branch->GetType() == 4)) branchEndName = leaf->GetName();
190 else branchEndName = branch->GetName();
192 pos = branchEndName.Index(
".");
194 if (subBranchPrefix.Length() && branchEndName.BeginsWith(subBranchPrefix)) {
195 branchEndName.Remove(0, subBranchPrefix.Length() + 1);
201 TTreeReaderDescriptor::ReaderType readerType = TTreeReaderDescriptor::ReaderType::kValue;
202 Bool_t ispointer =
false;
203 ELocation isclones = outer_isclones;
205 switch(element->GetType()) {
207 case TVirtualStreamerInfo::kBool: { dataType =
"Bool_t"; readerType = TTreeReaderDescriptor::ReaderType::kValue;
break; }
208 case TVirtualStreamerInfo::kChar: { dataType =
"Char_t"; readerType = TTreeReaderDescriptor::ReaderType::kValue;
break; }
209 case TVirtualStreamerInfo::kShort: { dataType =
"Short_t"; readerType = TTreeReaderDescriptor::ReaderType::kValue;
break; }
210 case TVirtualStreamerInfo::kInt: { dataType =
"Int_t"; readerType = TTreeReaderDescriptor::ReaderType::kValue;
break; }
211 case TVirtualStreamerInfo::kLong: { dataType =
"Long_t"; readerType = TTreeReaderDescriptor::ReaderType::kValue;
break; }
212 case TVirtualStreamerInfo::kLong64: { dataType =
"Long64_t"; readerType = TTreeReaderDescriptor::ReaderType::kValue;
break; }
213 case TVirtualStreamerInfo::kFloat: { dataType =
"Float_t"; readerType = TTreeReaderDescriptor::ReaderType::kValue;
break; }
214 case TVirtualStreamerInfo::kFloat16: { dataType =
"Float16_t"; readerType = TTreeReaderDescriptor::ReaderType::kValue;
break; }
215 case TVirtualStreamerInfo::kDouble: { dataType =
"Double_t"; readerType = TTreeReaderDescriptor::ReaderType::kValue;
break; }
216 case TVirtualStreamerInfo::kDouble32:{ dataType =
"Double32_t"; readerType = TTreeReaderDescriptor::ReaderType::kValue;
break; }
217 case TVirtualStreamerInfo::kUChar: { dataType =
"UChar_t"; readerType = TTreeReaderDescriptor::ReaderType::kValue;
break; }
218 case TVirtualStreamerInfo::kUShort: { dataType =
"unsigned short"; readerType = TTreeReaderDescriptor::ReaderType::kValue;
break; }
219 case TVirtualStreamerInfo::kUInt: { dataType =
"unsigned int"; readerType = TTreeReaderDescriptor::ReaderType::kValue;
break; }
220 case TVirtualStreamerInfo::kULong: { dataType =
"ULong_t"; readerType = TTreeReaderDescriptor::ReaderType::kValue;
break; }
221 case TVirtualStreamerInfo::kULong64: { dataType =
"ULong64_t"; readerType = TTreeReaderDescriptor::ReaderType::kValue;
break; }
222 case TVirtualStreamerInfo::kBits: { dataType =
"unsigned int"; readerType = TTreeReaderDescriptor::ReaderType::kValue;
break; }
224 case TVirtualStreamerInfo::kCharStar: { dataType =
"Char_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray;
break; }
226 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kBool: { dataType =
"Bool_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray;
break; }
227 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kChar: { dataType =
"Char_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray;
break; }
228 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kShort: { dataType =
"Short_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray;
break; }
229 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kInt: { dataType =
"Int_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray;
break; }
230 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kLong: { dataType =
"Long_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray;
break; }
231 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kLong64: { dataType =
"Long64_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray;
break; }
232 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kFloat: { dataType =
"Float_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray;
break; }
233 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kFloat16: { dataType =
"Float16_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray;
break; }
234 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kDouble: { dataType =
"Double_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray;
break; }
235 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kDouble32:{ dataType =
"Double32_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray;
break; }
236 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kUChar: { dataType =
"UChar_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray;
break; }
237 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kUShort: { dataType =
"unsigned short"; readerType = TTreeReaderDescriptor::ReaderType::kArray;
break; }
238 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kUInt: { dataType =
"unsigned int"; readerType = TTreeReaderDescriptor::ReaderType::kArray;
break; }
239 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kULong: { dataType =
"ULong_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray;
break; }
240 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kULong64: { dataType =
"ULong64_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray;
break; }
241 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kBits: { dataType =
"unsigned int"; readerType = TTreeReaderDescriptor::ReaderType::kArray;
break; }
243 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kBool: { dataType =
"Bool_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray;
break; }
244 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kChar: { dataType =
"Char_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray;
break; }
245 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kShort: { dataType =
"Short_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray;
break; }
246 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kInt: { dataType =
"Int_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray;
break; }
247 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kLong: { dataType =
"Long_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray;
break; }
248 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kLong64: { dataType =
"Long64_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray;
break; }
249 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kFloat: { dataType =
"Float_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray;
break; }
250 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kFloat16: { dataType =
"Float16_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray;
break; }
251 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kDouble: { dataType =
"Double_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray;
break; }
252 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kDouble32:{ dataType =
"Double32_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray;
break; }
253 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kUChar: { dataType =
"UChar_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray;
break; }
254 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kUShort: { dataType =
"unsigned short"; readerType = TTreeReaderDescriptor::ReaderType::kArray;
break; }
255 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kUInt: { dataType =
"unsigned int"; readerType = TTreeReaderDescriptor::ReaderType::kArray;
break; }
256 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kULong: { dataType =
"ULong_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray;
break; }
257 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kULong64: { dataType =
"ULong64_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray;
break; }
258 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kBits: { dataType =
"unsigned int"; readerType = TTreeReaderDescriptor::ReaderType::kArray;
break; }
260 case TVirtualStreamerInfo::kCounter: { dataType =
"Int_t"; readerType = TTreeReaderDescriptor::ReaderType::kArray;
break; }
262 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kObjectp:
263 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kObjectP:
264 case TVirtualStreamerInfo::kObjectp:
265 case TVirtualStreamerInfo::kObjectP:
266 case TVirtualStreamerInfo::kAnyp:
267 case TVirtualStreamerInfo::kAnyP:
268 case TVirtualStreamerInfo::kSTL + TVirtualStreamerInfo::kObjectp:
269 case TVirtualStreamerInfo::kSTL + TVirtualStreamerInfo::kObjectP:
272 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kObject:
274 readerType = TTreeReaderDescriptor::ReaderType::kArray;
275 case TVirtualStreamerInfo::kObject:
276 case TVirtualStreamerInfo::kTString:
277 case TVirtualStreamerInfo::kTNamed:
278 case TVirtualStreamerInfo::kTObject:
279 case TVirtualStreamerInfo::kAny:
280 case TVirtualStreamerInfo::kBase:
281 case TVirtualStreamerInfo::kSTL: {
282 TClass *cl = element->GetClassPointer();
284 dataType = cl->GetName();
286 if (cl == TClonesArray::Class()) {
288 containerName =
"TClonesArray";
289 if (outer_isclones != kOut) {
290 isclones = outer_isclones;
291 dataType =
"TClonesArray";
293 readerType = TTreeReaderDescriptor::ReaderType::kArray;
294 dataType = GetContainedClassName(branch, element, ispointer);
296 }
else if (cl->GetCollectionProxy()) {
298 containerName = cl->GetName();
299 if (outer_isclones != kOut || containerName.EqualTo(
"vector<bool>")) {
305 isclones = outer_isclones;
306 dataType = cl->GetName();
308 readerType = TTreeReaderDescriptor::ReaderType::kArray;
309 TClass *valueClass = cl->GetCollectionProxy()->GetValueClass();
311 dataType = valueClass->GetName();
314 TDataType *valueClassBuiltIn = TDataType::GetDataType(cl->GetCollectionProxy()->GetType());
315 if (valueClassBuiltIn) dataType = valueClassBuiltIn->GetName();
316 else Error(
"AnalyzeBranches",
"Could not get type from collection %s in branch %s", cl->GetName(), branch->GetName());
333 TBranch *parent = branch->GetMother()->GetSubBranch(branch);
334 TVirtualStreamerInfo *objInfo = 0;
335 if (branch->GetListOfBranches()->GetEntries()) {
336 objInfo = ((TBranchElement*)branch->GetListOfBranches()->At(0))->GetInfo();
338 objInfo = branch->GetInfo();
340 if (element->IsBase()) {
342 if (cl == TObject::Class() && info->GetClass()->CanIgnoreTObjectStreamer())
347 TBranchDescriptor *bdesc = 0;
349 if (branchEndName == element->GetName()) {
350 if (branch->GetListOfBranches()->GetEntries() == 0) {
354 Int_t pos = branchname.Last(
'.');
356 branchname.Remove(pos);
358 TString local_prefix = desc ? desc->fSubBranchPrefix : TString(parent->GetName());
359 bdesc =
new TBranchDescriptor(cl->GetName(), objInfo, branchname.Data(), local_prefix.Data(),
360 isclones, containerName, desc);
362 lookedAt += AnalyzeBranches(bdesc, branch, objInfo);
367 Int_t pos = branchname.Last(
'.');
369 branchname.Remove(pos);
371 TString local_prefix = desc ? desc->fSubBranchPrefix : TString(parent->GetName());
372 objInfo = GetBaseClass(element);
376 cl = objInfo->GetClass();
377 bdesc =
new TBranchDescriptor(cl->GetName(), objInfo, branchname.Data(), local_prefix.Data(),
378 isclones, containerName, desc);
381 lookedAt += AnalyzeBranches(bdesc, branches, objInfo);
385 TBranchDescriptor *bdesc = 0;
386 if (branchEndName == element->GetName()) {
387 if (branch->GetListOfBranches()->GetEntries() == 0) {
391 if (isclones != kOut) {
393 cl = TClass::GetClass(dataType);
394 objInfo = GetStreamerInfo(branch, branch->GetListOfBranches(), cl);
396 bdesc =
new TBranchDescriptor(cl->GetName(), objInfo, branch->GetName(), branch->GetName(),
397 isclones, containerName, desc);
399 lookedAt += AnalyzeBranches(bdesc, branch, objInfo);
403 TString local_prefix = desc ? desc->fSubBranchPrefix : TString(parent->GetName());
404 if (local_prefix.Length()) local_prefix +=
".";
405 local_prefix += element->GetName();
406 objInfo = branch->GetInfo();
407 Int_t pos = branchname.Last(
'.');
409 branchname.Remove(pos);
411 if (isclones != kOut) {
413 cl = TClass::GetClass(dataType);
414 objInfo = GetStreamerInfo(branch, branches, cl);
416 bdesc =
new TBranchDescriptor(cl->GetName(), objInfo, branchname.Data(), local_prefix.Data(),
417 isclones, containerName, desc);
421 lookedAt += AnalyzeBranches(bdesc, branches, objInfo);
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;
439 AddReader(readerType, dataType, branch->GetName(), branch->GetName(), desc, isLeaf);
457 UInt_t TTreeReaderGenerator::AnalyzeOldBranch(TBranch *branch)
459 UInt_t extraLookedAt = 0;
462 TString branchName = branch->GetName();
464 TObjArray *leaves = branch->GetListOfLeaves();
465 Int_t nleaves = leaves ? leaves->GetEntriesFast() : 0;
468 for(
int l=0;l<nleaves;l++) {
469 TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(l);
470 extraLookedAt += AnalyzeOldLeaf(leaf, nleaves);
473 return extraLookedAt;
479 UInt_t TTreeReaderGenerator::AnalyzeOldLeaf(TLeaf *leaf, Int_t nleaves)
481 if (leaf->IsA()==TLeafObject::Class()) {
482 Error(
"AnalyzeOldLeaf",
"TLeafObject not supported yet");
486 TString leafTypeName = leaf->GetTypeName();
487 Int_t pos = leafTypeName.Last(
'_');
492 std::vector<Int_t> maxDim;
495 TString temp = leaf->GetName();
496 pos = temp.Index(
"[");
498 if (pos) temp.Remove(0, pos);
499 dimensions.Append(temp);
501 temp = leaf->GetTitle();
502 pos = temp.Index(
"[");
504 if (pos) temp.Remove(0, pos);
505 dimensions.Append(temp);
508 Int_t dimlen = dimensions.Length();
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,
"[" );
532 if (dim == 0 && leaf->IsA() == TLeafC::Class()) {
536 TTreeReaderDescriptor::ReaderType type = TTreeReaderDescriptor::ReaderType::kValue;
540 type = TTreeReaderDescriptor::ReaderType::kValue;
541 dataType = leafTypeName;
545 type = TTreeReaderDescriptor::ReaderType::kArray;
546 dataType = leafTypeName;
573 TString branchName = leaf->GetBranch()->GetName();
575 branchName.Form(
"%s.%s", leaf->GetBranch()->GetName(), leaf->GetName());
578 AddReader(type, dataType, leaf->GetName(), branchName, 0, kTRUE);
587 Bool_t TTreeReaderGenerator::BranchNeedsReader(TString branchName, TBranchDescriptor *parent, Bool_t isLeaf)
591 if (fIncludeAllLeaves)
return kTRUE;
592 if (std::find(fIncludeLeaves.begin(), fIncludeLeaves.end(), branchName) != fIncludeLeaves.end())
return kTRUE;
593 if (std::find(fIncludeStruct.begin(), fIncludeStruct.end(), branchName) != fIncludeStruct.end())
return kTRUE;
595 if (fIncludeAllTopmost)
return kTRUE;
598 if (std::find(fIncludeLeaves.begin(), fIncludeLeaves.end(), parent->fBranchName) != fIncludeLeaves.end()) {
601 parent = parent->fParent;
605 if (std::find(fIncludeStruct.begin(), fIncludeStruct.end(), branchName) != fIncludeStruct.end())
return kTRUE;
607 if (fIncludeAllTopmost)
return kTRUE;
616 void TTreeReaderGenerator::ParseOptions() {
617 if (fOptionStr.EqualTo(
"")) {
618 fIncludeAllLeaves = kTRUE;
619 }
else if (fOptionStr.EqualTo(
"@")) {
620 fIncludeAllTopmost = kTRUE;
622 TObjArray *tokens = fOptionStr.Tokenize(TString(
";"));
623 for (Int_t i = 0; i < tokens->GetEntries(); ++i) {
624 TString token = ((TObjString*)tokens->At(i))->GetString();
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] ==
'@') {
628 token = TString(token.Data()+1);
629 fIncludeStruct.push_back(token);
631 fIncludeLeaves.push_back(token);
633 if (!fTree->GetBranch(token)) {
634 Warning(
"ParseOptions",
"Tree %s does not contain a branch named %s.", fTree->GetName(), token.Data());
644 void TTreeReaderGenerator::AnalyzeTree(TTree *tree)
646 TIter next(tree->GetListOfBranches());
650 while ( (branch = (TBranch*)next()) ) {
651 TVirtualStreamerInfo *info = 0;
653 const char *branchName = branch->GetName();
654 const char *branchClassName = branch->GetClassName();
655 TClass *cl = TClass::GetClass(branchClassName);
658 if (branchClassName && strlen(branchClassName)) {
662 TString type =
"unknown";
663 ELocation isclones = kOut;
664 TString containerName =
"";
665 TBranchDescriptor *desc = 0;
669 if (cl == TClonesArray::Class()) {
671 containerName =
"TClonesArray";
672 if (branch->IsA()==TBranchElement::Class()) {
674 const char *cname = ((TBranchElement*)branch)->GetClonesName();
675 TClass *ncl = TClass::GetClass(cname);
678 info = GetStreamerInfo(branch, branch->GetListOfBranches(), cl);
681 "Introspection of TClonesArray in older file not implemented yet.");
684 TClonesArray **ptr = (TClonesArray**)branch->GetAddress();
685 TClonesArray *clones = 0;
687 clones =
new TClonesArray;
688 branch->SetAddress(&clones);
692 TClass *ncl = *ptr ? (*ptr)->GetClass() : 0;
697 "Introspection of TClonesArray for %s failed.",branch->GetName());
701 }
else if (cl->GetCollectionProxy()) {
703 containerName = cl->GetName();
705 if (cl->GetCollectionProxy()->GetValueClass()) {
706 cl = cl->GetCollectionProxy()->GetValueClass();
712 if (containerName.EqualTo(
"vector<bool>")) {
713 AddReader(TTreeReaderDescriptor::ReaderType::kValue,
715 branch->GetName(), branch->GetName(), 0, kTRUE);
717 AddReader(TTreeReaderDescriptor::ReaderType::kArray,
718 TDataType::GetDataType(cl->GetCollectionProxy()->GetType())->GetName(),
719 branch->GetName(), branch->GetName(), 0, kTRUE);
727 if (cl->TestBit(TClass::kIsEmulation) || branchName[strlen(branchName)-1] ==
'.' || branch->GetSplitLevel()) {
728 TBranchElement *be =
dynamic_cast<TBranchElement*
>(branch);
729 TVirtualStreamerInfo *beinfo = (be && isclones == kOut)
730 ? be->GetInfo() : cl->GetStreamerInfo();
732 desc =
new TBranchDescriptor(cl->GetName(), beinfo, branchName, branchName, isclones, containerName);
736 AddReader(isclones == kOut ?
737 TTreeReaderDescriptor::ReaderType::kValue
738 : TTreeReaderDescriptor::ReaderType::kArray,
739 cl->GetName(), branchName, branchName, 0, kTRUE);
746 if (branch->GetListOfBranches()->GetEntries() == 0) {
750 AddReader(isclones == kOut ?
751 TTreeReaderDescriptor::ReaderType::kValue
752 : TTreeReaderDescriptor::ReaderType::kArray,
753 desc->GetName(), desc->fBranchName, desc->fBranchName, 0, kTRUE);
756 AnalyzeOldBranch(branch);
759 TIter subnext( branch->GetListOfBranches() );
762 TBranchElement *branchElem =
dynamic_cast<TBranchElement*
>(branch);
764 AnalyzeBranches(desc, branchElem, info);
766 Error(
"AnalyzeTree",
"Cannot analyze branch %s because it is not a TBranchElement.", branchName);
769 AddReader(isclones == kOut ?
770 TTreeReaderDescriptor::ReaderType::kValue
771 : TTreeReaderDescriptor::ReaderType::kArray,
772 desc->GetName(), desc->fBranchName, desc->fBranchName, 0, kFALSE);
782 void TTreeReaderGenerator::WriteSelector()
785 if (!fClassname) fClassname = fTree->GetName();
788 if (fTree->GetDirectory() && fTree->GetDirectory()->GetFile()) {
789 treefile = fTree->GetDirectory()->GetFile()->GetName();
791 treefile =
"Memory Directory";
796 Bool_t ischain = fTree->InheritsFrom(TChain::Class());
797 Bool_t isHbook = fTree->InheritsFrom(
"THbookTree");
799 treefile = fTree->GetTitle();
803 thead.Form(
"%s.h", fClassname.Data());
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;
814 ofs <<
"// from TTree " << fTree->GetName() <<
"/" << fTree->GetTitle() << std::endl
815 <<
"// found on file: " << treefile << std::endl;
817 ofs <<
"// from TChain " << fTree->GetName() <<
"/" << fTree->GetTitle() << 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";
825 TIter next(&fListOfHeaders);
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";
835 next = &fListOfReaders;
836 TTreeReaderDescriptor *descriptor;
837 while ( ( descriptor = (TTreeReaderDescriptor*)next() ) ) {
838 ofs <<
" TTreeReader" << (descriptor->fType == TTreeReaderDescriptor::ReaderType::kValue ?
"Value" :
"Array")
839 <<
"<" << descriptor->fDataType
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.SetLocalEntry(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";