00001
00002
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00038
00039 #include <stdio.h>
00040 #include <stdlib.h>
00041 #include <string.h>
00042 #include <assert.h>
00043
00044 #include "TROOT.h"
00045
00046 #if ROOT_VERSION_CODE < ROOT_VERSION(3,00,0)
00047 #define __OLDROOT__
00048 #endif
00049
00050 #include "TFile.h"
00051 #include "TKey.h"
00052 #include "TTree.h"
00053 #include "TChain.h"
00054 #include "TBranch.h"
00055 #ifndef __OLDROOT__
00056 #include "TBranchElement.h"
00057 #include "TFriendElement.h"
00058 #endif
00059 #include "TLeaf.h"
00060 #include "TStreamerInfo.h"
00061 #include "TStreamerElement.h"
00062 #include "TTreeIter.h"
00063 #include "TList.h"
00064 #include "TObjArray.h"
00065 #include "TNamed.h"
00066 #include "TSystem.h"
00067 #include "TRegexp.h"
00068 #include "TError.h"
00069 #include "TDirIter.h"
00070
00071 enum ETTI { kUnknown=0
00072 ,kChar = 1, kShort = 2, kInt = 3, kLong = 4, kFloat = 5, kDouble = 8,kDouble32 = 9
00073 ,kUChar = 11, kUShort = 12, kUInt = 13, kULong = 14};
00074
00075 const char* NTTI[] = {"Unknown"
00076 ,"Char_t" ,"Short_t" ,"Int_t" ,"Long_t" ,"Float_t"
00077 ,"_______" ,"_______" ,"Double_t" ,"Double32_t" ,"_______"
00078 ,"UChar_t" ,"UShort_t" ,"UInt_t" ,"ULong_t" ,"_______"
00079 ,"_______" ,"_______" ,"_______" ,"_______" ,"_______"
00080 ,"Char_t*" ,"Short_t*" ,"Int_t*" ,"Long_*t" ,"Float_t*"
00081 ,"_______*" ,"_______*" ,"Double_t*" ,"_______*" ,"_______*"
00082 ,"UChar_t*" ,"UShort_t*" ,"UInt_t*" ,"ULong_t*" ,"_______*"
00083 ,"_______" ,"_______" ,"_______" ,"_______" ,"_______"
00084 ,"char" ,"short" ,"int" ,"long" ,"float"
00085 ,"_____" ,"_____" ,"double" ,"_____" ,"_____"
00086 ,"uchar" ,"ushort" ,"uint" ,"ulong" ,"_____"
00087 ,"_____" ,"_____" ,"_____" ,"_____" ,"_____"
00088 ,"char*" ,"short*" ,"int*" ,"long_*t" ,"float*"
00089 ,"_____*" ,"_____*" ,"double*" ,"_____*" ,"_____*"
00090 ,"uchar*" ,"ushort*" ,"uint*" ,"ulong*" ,"_____*"
00091 ,"_____" ,"_____" ,"_____" ,"_____" ,"_____"
00092 ,"char" ,"short" ,"int" ,"long" ,"float"
00093 ,"_____" ,"_____" ,"double" ,"_____" ,"_____"
00094 ,"unsigned char" ,"unsigned short" ,"unsigned int" ,"unsigned long" ,"_____"
00095 ,"_____" ,"_____" ,"_____" ,"_____" ,"_____"
00096 ,"char*" ,"short*" ,"int*" ,"long_*t" ,"float*"
00097 ,"_____*" ,"_____*" ,"double*" ,"_____*" ,"_____*"
00098 ,"unsigned char*","unsigned short*","unsigned int*","unsigned long*","_____*"
00099 ,"_____" ,"_____" ,"_____" ,"_____" ,"_____"
00100 ,0};
00101
00102
00103
00104
00105 void TTreeIterCast::Set(void* v,Int_t t,const char* name)
00106 {
00107 if (t==kDouble32 ) t = kDouble;
00108 if (t==kDouble32+20) t = kDouble+20;
00109 fV=v;fT=t;fN=name;
00110 }
00111
00112 void *TTreeIterCast::Addr(Int_t outType)
00113 {
00114 void *v = (outType>20) ? fV: *((void**)fV);
00115 if (fT+20 == outType) {
00116 Warning("Addr","*** Possible wrong cast:variable %s %s to %s ACCEPTED ***",
00117 TTreeIter::TypeName(fT),fN,TTreeIter::TypeName(outType));
00118 }
00119 else if (fT != outType) {
00120 Error("Addr","*** Wrong cast:variable %s %s to %s IGNORED ***",
00121 TTreeIter::TypeName(fT),fN,TTreeIter::TypeName(outType));
00122 v = 0;
00123 }
00124 if (!v) fE[0]++;
00125
00126 return v;
00127 }
00128
00129
00130 TTreeIterCast::operator const Char_t &()
00131 {return *((const Char_t*)Addr(kChar));}
00132
00133 TTreeIterCast::operator const Short_t &()
00134 {return *((const Short_t*)Addr(kShort));}
00135
00136 TTreeIterCast::operator const Int_t &()
00137 {return *((const Int_t*)Addr(kInt));}
00138
00139 TTreeIterCast::operator const Long_t &()
00140 {return *((const Long_t*)Addr(kLong));}
00141
00142 TTreeIterCast::operator const Float_t &()
00143 {return *((const Float_t*)Addr(kFloat));}
00144
00145 TTreeIterCast::operator const Double_t &()
00146 {return *((const Double_t*)Addr(kDouble));}
00147
00148
00149 TTreeIterCast::operator const UChar_t &()
00150 {return *((const UChar_t*)Addr(kUChar));}
00151
00152 TTreeIterCast::operator const UShort_t &()
00153 {return *((const UShort_t*)Addr(kUShort));}
00154
00155 TTreeIterCast::operator const UInt_t &()
00156 {return *((const UInt_t*)Addr(kUInt));}
00157
00158 TTreeIterCast::operator const ULong_t &()
00159 {return *((const ULong_t*)Addr(kULong));}
00160
00161
00162 TTreeIterCast::operator const Char_t *&()
00163 {return *((const Char_t**)Addr(kChar+20));}
00164
00165 TTreeIterCast::operator const Short_t *&()
00166 {return *((const Short_t**)Addr(kShort+20));}
00167
00168 TTreeIterCast::operator const Int_t *&()
00169 {return *((const Int_t**)Addr(kInt+20));}
00170
00171 TTreeIterCast::operator const Long_t *&()
00172 {return *((const Long_t**)Addr(kLong+20));}
00173
00174 TTreeIterCast::operator const Float_t *&()
00175 {return *((const Float_t**)Addr(kFloat+20));}
00176
00177 TTreeIterCast::operator const Double_t *&()
00178 {return *((const Double_t**)Addr(kDouble+20));}
00179
00180
00181 TTreeIterCast::operator const UChar_t *&()
00182 {return *((const UChar_t**)Addr(kUChar+20));}
00183
00184 TTreeIterCast::operator const UShort_t *&()
00185 {return *((const UShort_t**)Addr(kUShort+20));}
00186
00187 TTreeIterCast::operator const UInt_t *&()
00188 {return *((const UInt_t**)Addr(kUInt+20));}
00189
00190 TTreeIterCast::operator const ULong_t *&()
00191 {return *((const ULong_t**)Addr(kULong+20));}
00192
00193
00194
00195
00196
00197 class TTreeIterMem : public TNamed {
00198 public:
00199 Int_t fType;
00200 Int_t fUnits;
00201 Int_t fSize;
00202 TString fTyName;
00203 Char_t *fMem;
00204
00205 public:
00206 TTreeIterMem(const char *name,Int_t type,Int_t units,const char *tyName);
00207 ~TTreeIterMem(){ delete [] fMem;}
00208 void **Alloc(int units=-1);
00209 void **GetMem(){return (void**)&fMem;}
00210 };
00211
00212 TTreeIterMem::TTreeIterMem(const char *name,Int_t type,Int_t units,const char *tyName)
00213 :TNamed(name,"")
00214 {
00215 fType = type;
00216 fTyName = tyName;
00217 fUnits = units;
00218 fSize = 0;
00219 fMem = 0;
00220 Alloc();
00221 }
00222
00223
00224 void **TTreeIterMem::Alloc(int units)
00225 {
00226 if (units>-1) fUnits = units;
00227 if (!fUnits) fUnits=1;
00228 delete [] fMem; fMem=0;
00229 TClass *kl = 0;
00230 int uSize = sizeof(void*);
00231 if (fType) {
00232 fSize = TTreeIter::TypeSize(fType)*fUnits;
00233 } else {
00234 if (fTyName[fTyName.Length()-1]!='*') {
00235 kl = gROOT->GetClass(fTyName);
00236 if (!kl) {
00237 Warning("Alloc","No dictionary for class %s",fTyName.Data());
00238 return 0;}
00239 uSize = kl->Size();
00240 }
00241 fSize = uSize*fUnits;
00242 }
00243 fMem = new char[fSize+8];
00244 memset(fMem,0,fSize);
00245 if (kl){for (char *cc=fMem; cc < fMem+fSize; cc+=uSize){kl->New((void*)cc);}}
00246 strcpy(fMem+fSize,"Perev");
00247 return (void**)&fMem;
00248 }
00249
00250
00251 ClassImp(TTreeIter)
00252
00253
00254 TTreeIter::TTreeIter(TTree *tree):fCast(&fNErr)
00255 {
00256 fNFiles = 0;
00257 fTree = 0;
00258 if (tree) {
00259 fTree = new TChain(tree->GetName());
00260 if (tree->IsA() == TChain::Class()) fTree->Add((TChain*)tree);
00261 }
00262 Init();
00263 }
00264
00265
00266 TTreeIter::TTreeIter(const char *treeName):fCast(&fNErr)
00267 {
00268 fTree = 0;
00269 fNFiles = 0;
00270 if (treeName && treeName[0] && treeName[0]!=' ') fTree = new TChain(treeName);
00271 Init();
00272 }
00273
00274
00275 void TTreeIter::Init()
00276 {
00277 fCint = 0;
00278 fNErr = 0;
00279 fEntry = 0;
00280 fUnits = 0;
00281 if (fTree==0) return;
00282 #ifndef __OLDROOT__
00283 fTree->SetMakeClass(1);
00284 #endif
00285 fTree->SetBranchStatus("*",0);
00286 fTree->SetNotify(this);
00287
00288 }
00289
00290 TTreeIter::~TTreeIter()
00291 {
00292 fEntry = 0;
00293 delete fTree;
00294 fMemList.Delete();
00295
00296 }
00297
00298
00299 void TTreeIter::GetInfo(const TBranch *tbp, const char *&tyName
00300 ,Int_t &units,void *&add, Int_t &brType)
00301 {
00302 tyName = 0;
00303 brType = 0;
00304 TBranch *tb = (TBranch*)tbp;
00305 add = tb->GetAddress();
00306 units = 0;
00307 char *nxt=0;
00308 const char *des = strchr(tb->GetName(),'[');
00309 if (des) {
00310 units = 1;
00311 while(des){
00312 int ii = strtol(des+1,&nxt,10);
00313 if (des+1 != nxt) units *=ii;
00314 if ( !*nxt) break;
00315 des = nxt;
00316 } }
00317
00318 int max = 0;
00319 int kase = 0;
00320 if (strcmp(tb->ClassName(),"TBranchElement")==0) kase = 1;
00321 if (strcmp(tb->ClassName(),"TBranchClones" )==0) kase = 2;
00322 switch (kase) {
00323 #ifndef __OLDROOT__
00324 case 1: {TBranchElement *te = (TBranchElement*)tb;
00325 max = te->GetMaximum();
00326 brType = te->GetType();
00327 TString ts(te->GetName());
00328 int i = 0;
00329 while ((i=ts.Index("."))>=0) { ts.Replace(0,i+1,"");}
00330 i=ts.Index("["); if (i>=0) ts.Replace(i,9999,"");
00331 TStreamerInfo *si = te->GetInfo();
00332 assert(si);
00333 TStreamerElement *se = si->GetStreamerElement(ts.Data(),i);
00334 if (!se) { tyName = si->GetName(); }
00335 else { tyName = se->GetTypeName();}
00336 }
00337 if (strcmp("TClonesArray",tyName)==0 && tb->GetSplitLevel()) tyName=0;
00338 break;
00339 #endif
00340 case 2: max = 0; tyName = "Int_t"; return;
00341
00342 case 0:
00343 TLeaf *lf = (TLeaf*)tb->GetListOfLeaves()->First();
00344 TLeaf *lc = 0;
00345 if (lf) lc = lf->GetLeafCount();
00346 if (lc) max = lc->GetMaximum();
00347
00348 }
00349 if (max) {if (!units) units = 1; units *= max;}
00350 if (brType==3) units=0;
00351 if (tyName) return;
00352
00353 TObjArray *lfList = tb->GetListOfLeaves();
00354 TLeaf *tl = (lfList) ? (TLeaf*)lfList->UncheckedAt(0):0;
00355 tyName= (tl) ? tl->GetTypeName():0;
00356 }
00357
00358 TBranch *TTreeIter::GetBranch(int idx) const
00359 {
00360 TObjArray *ll = fTree->GetListOfLeaves();
00361 if (!ll) return 0;
00362 if (idx>ll->GetLast()) return 0;
00363
00364 return ((TLeaf*)ll->At(idx))->GetBranch();
00365 }
00366
00367
00368 void **TTreeIter::Void(const TString varname)
00369 {
00370 fCint = 1;
00371 return Void(varname.Data());
00372 }
00373
00374 void **TTreeIter::Void(const char *varname)
00375 {
00376 fCast.Set(0,0,varname);
00377
00378 TBranch *br = fTree->GetBranch(varname);
00379 if (br && strcmp(br->ClassName(),"TBranchClones")==0) {
00380 TString ts(varname); ts+="_";
00381 br = fTree->GetBranch(ts.Data());
00382 }
00383 if (!br) {
00384 Warning("operator()","Branch %s NOT FOUND",varname);
00385 return 0;
00386 }
00387
00388 void *addr,**pddr;
00389 const char *tyName;
00390 Int_t brType;
00391 GetInfo(br,tyName,fUnits,addr,brType);
00392
00393 int tyCode = TypeCode(tyName);
00394 if (!tyCode) {
00395
00396 }
00397 TTreeIterMem *mem;
00398 mem = (TTreeIterMem*)fMemList.FindObject(br->GetName());
00399 if (!mem) {
00400 mem = new TTreeIterMem(br->GetName(),tyCode,fUnits,tyName);
00401 fMemList.Add(mem);
00402 pddr = mem->GetMem();
00403 fTree->SetBranchStatus(br->GetName(),1);
00404 br->SetBit(1);
00405 fTree->SetBranchAddress(br->GetName(),*pddr);
00406 fBraList.Add(br);
00407 } else {
00408 pddr = mem->GetMem();
00409 }
00410
00411
00412
00413 if (fUnits) { if(tyCode) tyCode+=20;}
00414 fCast.Set(pddr,tyCode,varname);
00415
00416 return pddr;
00417 }
00418
00419 TTreeIterCast &TTreeIter::operator() (const TString varname)
00420 {
00421 fCint = 1;
00422 return operator() (varname.Data());
00423 }
00424
00425 TTreeIterCast &TTreeIter::operator() (const char *varname)
00426 {
00427 Void(varname);
00428 void *addr = fCast.Addr();
00429 if (fCint) {
00430 fCint = 0;
00431 TTreeIterCast *v =(TTreeIterCast*)addr;
00432
00433 return *v;
00434 }
00435 return fCast;
00436 }
00437
00438 Int_t TTreeIter::Next(Int_t entry)
00439 {
00440 if (fNErr) {
00441 Warning("Next","It was %d errors in Init. Loop ignored",fNErr);
00442 fEntry=0; return 0;}
00443 if (!TestBit(1)) { SetBit(1); Notify();}
00444
00445 int ientry = (entry >= 0) ? entry:fEntry++;
00446
00447 Int_t ans = 0;
00448
00449 ans = fTree->GetEntry(ientry);
00450 #if 0
00451 int n = fBraList.GetEntriesFast();
00452 for (int i=0;i<n;i++) {
00453 TBranch *b = (TBranch*)fBraList.UncheckedAt(i);
00454 ans +=b->GetEntry(ientry);
00455 }
00456 #endif //0
00457 assert(!IsCorrupted());
00458 if (ans) return ans;
00459 fEntry=0;
00460 return 0;
00461
00462 }
00463
00464 Bool_t TTreeIter::Notify()
00465 {
00466 const char *tyName;
00467 Int_t units,brType;
00468 void *add;
00469 assert(!IsCorrupted());
00470 fTree->SetBranchStatus("*",0);
00471 fBraList.Clear();
00472 int n = fMemList.GetEntriesFast();
00473 for (int i=0;i<n;i++) {
00474 TTreeIterMem *t = (TTreeIterMem*)fMemList.UncheckedAt(i);
00475 fTree->SetBranchStatus(t->GetName(),1);
00476 TBranch *b = fTree->GetBranch(t->GetName());
00477 assert(b);
00478 GetInfo(b,tyName,units,add,brType);
00479 void **pddr = t->GetMem();
00480 if (units > t->fUnits) {
00481 pddr = t->Alloc(units);
00482 }
00483 fTree->SetBranchAddress(t->GetName(),*pddr);
00484 }
00485
00486 TBranch *br=0;
00487 int added = 1;
00488 while(added) {
00489 added = 0;
00490 for (int idx=0;(br=GetBranch(idx));idx++) {
00491 if (br->TestBit(kDoNotProcess)) continue;
00492 if (fMemList.FindObject(br->GetName())) continue;
00493 added++;
00494
00495 GetInfo(br,tyName,units,add,brType);
00496 if (brType==3 || brType==4 ) {
00497 (*this)(br->GetName());
00498 printf("Branch %s activated\n",br->GetName());
00499 continue;
00500 }
00501 TObjArray *brl = br->GetListOfBranches();
00502 if (brl && brl->GetEntriesFast()) {
00503 printf("Node Branch %s ignored\n",br->GetName());
00504 added--;
00505 continue;
00506 }
00507
00508 {
00509 fTree->SetBranchStatus(br->GetName(),0);
00510 br->SetBit(kDoNotProcess);
00511 printf("Branch %s desactivated\n",br->GetName());
00512 continue;
00513 }
00514 }
00515 }
00516 fMemList.Sort();
00517 n = fMemList.GetEntriesFast();
00518 for (int i=0;i<n;i++) {
00519 TTreeIterMem *t = (TTreeIterMem*)fMemList.UncheckedAt(i);
00520 TBranch *b = fTree->GetBranch(t->GetName());
00521 assert(b);
00522 fBraList.Add(b);
00523 }
00524 return 0;
00525 }
00526
00527 const char *TTreeIter::IsCorrupted() const
00528 {
00529
00530 int n = fMemList.GetEntriesFast();
00531 assert(n>=0 && n<10000);
00532 for (int i=0;i<n;i++) {
00533 TTreeIterMem *t = (TTreeIterMem*)fMemList.UncheckedAt(i);
00534 assert(t);
00535 assert(t->fMem);
00536 assert(t->fSize>0);
00537
00538 char *perev = t->fMem+t->fSize;
00539 if (strcmp(perev,"Perev") ==0 ) continue;
00540 Error("IsCorrupted","Branch=%s Units=%d Mem=%p ***\n",t->GetName(),fUnits,perev);
00541 return t->GetName();
00542 }
00543 return 0;
00544 }
00545
00546 void TTreeIter::ls(const TObjArray *brList,Int_t lvl,Option_t* option)
00547 {
00548 TBranch *branch;
00549 if (!brList) return;
00550
00551 Int_t nb = brList->GetEntriesFast();
00552 for (int iBr=0;iBr<nb;iBr++) {
00553 branch = (TBranch*)brList->UncheckedAt(iBr);
00554 if (!branch) continue;
00555 Print(branch,lvl,option);
00556 ls(branch->GetListOfBranches(),lvl+1,option);
00557 }
00558 }
00559
00560 void TTreeIter::ls(const TTree *ttp, Option_t* option)
00561 {
00562 TTree *tt = (TTree *)ttp;
00563 if (!tt) return;
00564 ls(tt->GetListOfBranches(),0,option);
00565 }
00566
00567 void TTreeIter::ls(Option_t* option) const
00568 {
00569 if(option && strstr(option,"fil")) {
00570 if(!fTree) return;
00571 if(!fTree->GetListOfFiles()) return;
00572 fTree->GetListOfFiles()->ls();
00573 return;
00574 }
00575 ls(fTree,option);
00576 }
00577
00578 void TTreeIter::Print(Option_t* option) const
00579 {
00580 ls(fTree,option);
00581 }
00582
00583 void TTreeIter::Print(const TBranch *tb,Int_t lvl, Option_t* option)
00584 {
00585 const char *tyName;
00586 Int_t units,brType;
00587 char active[2]={0,0};
00588 void *add;
00589
00590 GetInfo(tb,tyName,units,add,brType);
00591 active[0]='*';
00592 if (tb->TestBit(kDoNotProcess)) active[0]=0;
00593
00594 printf("%10p(%10p) - ",(void*)tb,(void*)add);
00595 for (int i=0;i<lvl;i++){printf(" ");}
00596
00597 printf("%s%s(%s)",active,tb->GetName(),tb->ClassName());
00598
00599 printf("\t // Max=%d Type=%s,brType=%d",units,tyName,brType);
00600 printf("\n");
00601 }
00602
00603 const char* TTreeIter::TypeName(Int_t ity)
00604 {
00605 return NTTI[ity];
00606 }
00607
00608 Int_t TTreeIter::TypeSize(Int_t ity)
00609 {
00610 int t = ity%10;
00611 switch(t) {
00612 case kChar:; case kShort:; return t;
00613 case kInt: return sizeof(Int_t);
00614 case kLong: return sizeof(Long_t);
00615 case kFloat: return sizeof(Float_t);
00616 case kDouble: return sizeof(Double_t);
00617 case kDouble32: return sizeof(Double_t);
00618 default: return 0;
00619 }
00620 }
00621
00622
00623 Int_t TTreeIter::TypeCode(const char *typeName)
00624 {
00625 for (int i=1; NTTI[i]; i++) {if (strcmp(typeName,NTTI[i])==0) return i%20;}
00626
00627 return 0;
00628 }
00629
00630 void TTreeIter::Streamer(TBuffer &) {assert(0);}
00631
00632 Int_t TTreeIter::AddFile(const Char_t *file)
00633 {
00634 const char* fullname;
00635 int num = 0;
00636 TDirIter dirIter(file);
00637 while((fullname=dirIter.NextFile())) {
00638 fNFiles++; num++;
00639 printf("%04d - TTreeIter::AddFile %s\n",fNFiles,fullname);
00640 if (fTree == 0) WhichTree(fullname);
00641 if (fTree) fTree->Add(fullname);
00642 }
00643
00644 Init();
00645 return num;
00646 }
00647
00648 void TTreeIter::WhichTree(const char *fileName)
00649 {
00650 TString fileNameS = fileName;
00651 gSystem->ExpandPathName(fileNameS);
00652
00653
00654
00655
00656 TFile *tfile = TFile::Open(fileNameS.Data());
00657 if (! tfile || tfile->IsZombie()) {
00658 printf("*** Can NOT open %s ***\n",fileNameS.Data());
00659 return;}
00660
00661 TList *keyList = tfile->GetListOfKeys();
00662 TListIter NextKey(keyList);
00663 TKey *key; const char *ttName=0;
00664 while ( (key = (TKey*)NextKey()) )
00665 {
00666 if (strcmp("TTree" ,key->GetClassName())!=0
00667 && strcmp("TNtuple",key->GetClassName())!=0) continue;
00668 ttName = key->GetName(); break;
00669 }
00670 printf(" Got TTree = %s\n",ttName);
00671 if (ttName==0) return;
00672
00673 fTree = new TChain(ttName);
00674 delete tfile;
00675 Init();
00676 }
00677
00678
00679