Advertisement
Guest User

Ntuple Tools

a guest
Aug 29th, 2014
308
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 17.85 KB | None | 0 0
  1. //---NtupleTools----------
  2. //   Version 2.0
  3. //   15.07.2010
  4. //   19.11.2010 duplicate check in AllRootFilesNoDup
  5. //   29.11.2010 clash removed in case of multiple opened EasyChains
  6. //   15.02.2011 conditionals for pure header use if __NTHEADER___ defined.
  7. //              This aproach allows the use of NtupleTools2.h with command line macros
  8. //              since the complete implementation is in one file
  9. //     2.5.2011 - Improved performance in case of multiple acces of a branch for same entry
  10. //              - new dcache door
  11. //     8.6.2013 - simple TClonesArray to vector interface
  12. //              - no duplicates default -> false
  13. //              - unique name base argument
  14. //   dirk.kruecker@desy.de
  15.  
  16. #ifndef NtupleTools3_h
  17. #define NtupleTools3_h
  18.  
  19. #ifdef __GNUC__
  20. // only visible for the gnu pre-compiler
  21. //#warning __GNUC__
  22. #pragma GCC diagnostic ignored "-Wunused-parameter"
  23. #pragma GCC diagnostic ignored "-Wuninitialized"
  24. #endif
  25.  
  26. #include <iostream>
  27. #include <sstream>
  28. #include <iomanip>
  29. #include <string>
  30. #include <map>
  31. #include <vector>
  32. #include <cstdlib>
  33. #include <algorithm>
  34. #include "TTree.h"
  35. #include "TFile.h"
  36. #include "TChain.h"
  37. #include "TChainElement.h"
  38. #include "TSystem.h"
  39. #include "TROOT.h"
  40. #include "TString.h"
  41. #include "TObjArray.h"
  42. #include "TClonesArray.h"
  43. #include "TStopwatch.h"
  44. #include "Math/LorentzVector.h"
  45. #include "Math/DisplacementVector3D.h"
  46. #include "Math/GenVector/PositionVector3D.h"
  47. #include "Math/GenVector/PxPyPzE4D.h"
  48. #include "Math/GenVector/PtEtaPhiE4D.h"
  49. #include "Math/GenVector/PxPyPzM4D.h"
  50. #include "Math/GenVector/PtEtaPhiM4D.h"
  51.  
  52. using namespace std;
  53.  
  54. typedef ROOT::Math::LorentzVector<ROOT::Math::PxPyPzE4D<double> >            LorentzV;
  55. typedef ROOT::Math::LorentzVector<ROOT::Math::PtEtaPhiM4D<float> >          LorentzM;
  56. typedef ROOT::Math::LorentzVector<ROOT::Math::PtEtaPhiE4D<float> >          LorentzE;
  57. typedef ROOT::Math::LorentzVector<ROOT::Math::PtEtaPhiM4D<double> >          LorentzMD;
  58. typedef ROOT::Math::LorentzVector<ROOT::Math::PtEtaPhiE4D<double> >          LorentzED;
  59. typedef ROOT::Math::DisplacementVector3D<ROOT::Math::Cartesian3D<double> > XYZVectorD;
  60. typedef ROOT::Math::PositionVector3D<ROOT::Math::Cartesian3D<double>  >     XYZPointD;
  61. typedef ROOT::Math::DisplacementVector3D<ROOT::Math::Cartesian3D<float> > XYZVectorF;
  62. typedef ROOT::Math::PositionVector3D<ROOT::Math::Cartesian3D<float>  >     XYZPointF;
  63.  
  64.  
  65. #ifdef __CINT__
  66. // for the command line ACLIC macro
  67. // compiled during rootcint
  68. //#warning __CINT__
  69. #pragma link C++ class vector<LorentzV>+;
  70. #pragma link C++ class vector<LorentzM>+;
  71. #pragma link C++ class vector<XYZVectorD>+;
  72. #pragma link C++ class vector<XYZPointD>+;
  73. #pragma link C++ class vector<XYZVectorF>+;
  74. #pragma link C++ class vector<XYZPointF>+;
  75. #pragma link C++ class map<string,bool>+;
  76. #pragma link C++ class map<string,string>+;
  77. //
  78. #pragma link C++ class pair<string,bool>+;
  79. #pragma link C++ class pair<string,string>+;
  80. #pragma link C++ class map<string,int>+;
  81. #pragma link C++ class map<string,string>+;
  82. //
  83. #pragma link C++ class ROOT::Math::Cartesian3D<float>+;
  84. #pragma link C++ class ROOT::Math::LorentzVector<ROOT::Math::PxPyPzE4D<float> >+;
  85. #pragma link C++ class ROOT::Math::PositionVector3D<ROOT::Math::Cartesian3D<float>  >+;
  86. #pragma link C++ class ROOT::Math::DisplacementVector3D<ROOT::Math::Cartesian3D<float> >+;
  87. #pragma link C++ class ROOT::Math::LorentzVector<ROOT::Math::PtEtaPhiM4D<float> >+;
  88. #pragma link C++ class ROOT::Math::LorentzVector<ROOT::Math::PtEtaPhiE4D<float> >+;
  89. #pragma link C++ class ROOT::Math::PtEtaPhiM4D<float>+;
  90. #endif
  91.  
  92. //namespace ROOT {
  93. #ifndef __CINT__
  94. // following functions should not be processed by rootcint
  95. //---------- simple progress counter and timer -----------------------------
  96. void progress(ostream& os=cout,const TString& pref="",const TString& postf="")
  97. #ifndef __NTHEADER___
  98. {
  99.         static int cnt(0),step(1),next(1);
  100.         cnt++;
  101.         if(cnt==next){
  102.                 os<<pref<<cnt<<postf<<endl;
  103.                 next+=step;
  104.         }
  105.         if((cnt+1)/step==10)step*=10;
  106. }
  107. #endif
  108. ;
  109. void progressT(int flush=0,ostream& os=cout)
  110. #ifndef __NTHEADER___
  111. {
  112.     static TStopwatch timer;
  113.         static int cnt(0),step(1),next(1);
  114.     if(cnt==0) timer.Start();
  115.         cnt++;
  116.         if(cnt==next||flush==1){
  117.             timer.Stop();
  118.                 os<<setw(10)<<left<<cnt
  119.                   <<" time (time/evt) - real: "
  120.                   <<setw(10)<<timer.RealTime()
  121.                   <<"("<<setw(10)<<timer.RealTime()/step
  122.                   <<"), \tCPU: "<<setw(10)<<timer.CpuTime()
  123.                   <<"("<<setw(10)<<timer.CpuTime()/step<<")"<<endl;
  124.                 timer.Start(false);
  125.                 next+=step;
  126.         }
  127.         if((cnt+1)/step==10)step*=10;
  128. }
  129. #endif
  130. ;
  131. void timer(ostream& os=cout,int stp=10)
  132. #ifndef __NTHEADER___
  133. {
  134.     static TStopwatch timer;
  135.         static int cnt(0),step(stp),next(stp);
  136.     if(cnt==0) timer.Start();
  137.         cnt++;
  138.         if(cnt==next){
  139.             timer.Stop();
  140.                 os<<"Evts: "<<setw(10)<<right<<cnt
  141.                   <<" | time [sec] - real: "
  142.                   <<left<<setprecision(4)<<setw(10)<<timer.RealTime()
  143.                   <<" \tCPU: "<<setw(10)<<left<<setprecision(4)<<timer.CpuTime()<<endl;
  144.                 timer.Start(false);
  145.                 next+=step;
  146.         }
  147.         if((cnt+1)/step==10)step*=10;
  148. }
  149. #endif
  150. ;
  151.  
  152. //---------- file handling -----------------------------
  153. int GetResult(vector<string>& out, const TString& command,bool nodup)
  154. #ifndef __NTHEADER___
  155. {
  156.     TString line;
  157.     FILE* pipe= gSystem->OpenPipe(command,"r");
  158.     if(!pipe){
  159.         cerr<<"Did not work: "<<command<<endl;
  160.     } else {
  161.         while (line.Gets(pipe)) if(line!="") {
  162.             out.push_back(string(line));
  163.         }
  164.         gSystem->ClosePipe(pipe);
  165.     }
  166.     if(nodup){
  167.         map<string, pair<unsigned,string> > singleOut;
  168.         map<string, pair<unsigned,string> >::iterator it;
  169.         unsigned i;
  170.         for(i=0;i<out.size();i++){
  171.             //check format
  172.             if(count(out[i].begin(),out[i].end(),'_') < 3) break;
  173.             //let's hope it fits
  174.             unsigned pos =out[i].rfind("_");
  175.             unsigned pos2=out[i].substr(0,pos).rfind("_")+1;
  176.             unsigned n=atoi(out[i].substr(pos2,pos-pos2).c_str());
  177.             it = singleOut.find(out[i].substr(0,pos2));
  178.             if(it!=singleOut.end()) {
  179.                 if(it->second.first<n) {
  180.                     it->second.first=n;
  181.                     it->second.second=out[i].substr(pos2);
  182.                 }
  183.             } else singleOut[out[i].substr(0,pos2)]=pair<unsigned,string>(n,out[i].substr(pos2));
  184.         }
  185.         if(i==out.size()){
  186.             if (out.size()!=singleOut.size()) cout<< out.size()-singleOut.size() <<" duplicates ignored!"<<endl;;
  187.             out.clear();
  188.             for(it = singleOut.begin();it!=singleOut.end();it++)
  189.                     out.push_back(it->first+it->second.second);
  190.         } else cout<<"File name format not appropriate for duplicate check!"<<endl;
  191.     }
  192.     return out.size();
  193. }
  194. #endif
  195. ;
  196. //AllRootFilesIn(dir,tree)           // any 'ls'-able directory
  197. //AllRootFilesIn(dir,tree,10)        // any 'ls'-able directory, first 10 files
  198. //AllRootFilesIn(dir,tree,"dcls")    // dcache -  needs proxy & dctools !
  199. //AllRootFilesIn(dir,tree,"dcls",10) //first 10 files in dir
  200. int AllRootFilesIn(const TString& dir,TChain* chain,const TString& LScommand,int max,bool nodup=false)
  201. #ifndef __NTHEADER___
  202. {
  203.     vector<string> files;
  204.     int n=0;
  205.     if(LScommand=="dcls"){
  206.         n=GetResult(files,"dcls "+dir+" | grep \"\\.root\" ",nodup);
  207.         n=n>max?max:n;
  208. //old       const string dcache_gate="dcap://dcache-ses-cms.desy.de:22125/";
  209.         const string dcache_gate="dcap://dcache-cms-dcap.desy.de:22125/";
  210.         for(int i=0;i<n;++i) chain->Add((dcache_gate+dir+"/"+files[i]));
  211.     } else if(LScommand=="rfdir") {
  212.         n=GetResult(files,LScommand+" "+dir+" | grep \"\\.root\" | awk \'{print $9}\' ",nodup);
  213.         n=n>max?max:n;
  214.         for(int i=0;i<n;++i) chain->Add(("rfio:"+dir+"/"+files[i]));
  215.     } else {
  216.         n=GetResult(files,LScommand+" "+dir+" | grep \"\\.root\"",nodup);
  217.         n=n>max?max:n;
  218.         for(int i=0;i<n;++i) chain->Add((dir+"/"+files[i]));
  219.     }
  220.     return n;
  221. }
  222. #endif
  223. ;
  224. // no duplicate check
  225. int AllRootFilesIn(const TString& dir,TChain* chain)
  226. #ifndef __NTHEADER___
  227. {
  228.     return AllRootFilesIn(dir,chain,"ls",1000,false);
  229. }
  230. #endif
  231. ;
  232. int AllRootFilesIn(const TString& dir,TChain* chain,const TString& LScommand)
  233. #ifndef __NTHEADER___
  234. {
  235.     return AllRootFilesIn(dir,chain,LScommand,1000,false);
  236. }
  237. #endif
  238. ;
  239. int AllRootFilesIn(const TString& dir,TChain* chain,int max)
  240. #ifndef __NTHEADER___
  241. {
  242.     return AllRootFilesIn(dir,chain,"ls",max,false);
  243. }
  244. #endif
  245. ;
  246. // duplicate check
  247. int AllRootFilesNoDup(const TString& dir,TChain* chain)
  248. #ifndef __NTHEADER___
  249. {
  250.     return AllRootFilesIn(dir,chain,"ls",1000,true);
  251. }
  252. #endif
  253. ;
  254. int AllRootFilesNoDup(const TString& dir,TChain* chain,const TString& LScommand)
  255. #ifndef __NTHEADER___
  256. {
  257.     return AllRootFilesIn(dir,chain,LScommand,1000,true);
  258. }
  259. #endif
  260. ;
  261. int AllRootFilesNoDup(const TString& dir,TChain* chain,int max)
  262. #ifndef __NTHEADER___
  263. {
  264.     return AllRootFilesIn(dir,chain,"ls",max,true);
  265. }
  266. #endif
  267. ;
  268. string file_base(const string& nam)
  269. #ifndef __NTHEADER___
  270. {
  271.     int dot=nam.rfind(".");
  272.     int slash=nam.rfind("/")+1;
  273.     return nam.substr(slash,dot-slash);
  274. }
  275. #endif
  276. ;
  277. TString file_base(const TString& nam)
  278. #ifndef __NTHEADER___
  279. {
  280.     const string namstr(nam.Data());
  281.     return file_base(namstr).c_str();
  282. }
  283. #endif
  284. ;
  285. #endif
  286. //---------- chain and tree handling -----------------------------
  287. // inline is redundant since this is a header files
  288. class EasyChain: public TChain {
  289. public:
  290.     EasyChain(const char* tname) : TChain(tname), localEntry(0), localMax(0), off(0), dcache(false) {
  291.         fileWeight=0;
  292.     };
  293.  
  294.     // here all kinds of variables can be load from the chain
  295.     // e.g.: vector<LorentzV>* electrons = tree->Get(&electrons,"electronP4Pat");
  296.     //       electron->size()
  297.     template<typename T>
  298.     inline T* Get(T** ppt, const char* name){
  299.         TBranch* branch;
  300.         // This increases the performance since GetBranch searches the full tree
  301.         // byNames.find only the used names
  302.         if( localByName.find(name)==localByName.end() ) {
  303.             branch = byName[name] = GetBranch( name );
  304.             localByName[name].second = 0;
  305.             localByName[name].first = -1;
  306.         }
  307.         else branch=byName[name];
  308.         if(branch==0) {
  309.             cerr<<"Branch "<<name<<" is undefined in tree: "<<GetName()<<endl;
  310.             exit(0);
  311.         }
  312.         if(localByName[name].first==localEntry && localByName[name].second!=0)
  313.             return static_cast<T*>(localByName[name].second);
  314.         if(localByName[name].second!=0){
  315.             T* toDelete = static_cast<T*>(localByName[name].second);
  316.             delete toDelete;
  317.             localByName[name].first=-1;
  318.         }
  319.         *ppt=0;
  320.         branch->SetAddress( ppt );
  321.         branch->GetEntry(localEntry,1);
  322.         localByName[name].second=*ppt;
  323.         localByName[name].first=localEntry;
  324.         return *ppt;
  325.     };
  326.     template<typename T>
  327.     inline T* Get(T** ppt, const TString& name){
  328.         return Get(ppt,name.Data());
  329.     }
  330.     // the same as above but the return type is a reference (same performance)
  331.     // e.g.: vector<LorentzV>& electrons = tree->Get(&electrons,"electronP4Pat");
  332.     //       Electron.size()
  333.     template<typename T>
  334.     inline T& Get(T* leaf,const char* name) {
  335.         leaf=leaf;//just to get rid of the  unused warning
  336.         TBranch* branch;
  337.         if( localByName.find(name)==localByName.end() ) {
  338.             branch = byName[name] = GetBranch( name );
  339.             localByName[name].second = 0;
  340.             localByName[name].first = -1;
  341.         }
  342.         else branch=byName[name];
  343.         if(branch==0) {
  344.             cerr<<"Branch "<<name<<" is undefined in tree: "<<GetName()<<endl;
  345.             exit(0);
  346.         }
  347.         if(localByName[name].first==localEntry && localByName[name].second!=0) return *static_cast<T*>(localByName[name].second);
  348.         if(localByName[name].second!=0) {
  349.             T* toDelete = static_cast<T*>(localByName[name].second);
  350.             delete toDelete;
  351.             localByName[name].first=-1;
  352.         }
  353.         T* pt=0;
  354.         branch->SetAddress( &pt );
  355.         branch->GetEntry(localEntry,1);
  356.         localByName[name].second=pt;
  357.         localByName[name].first=localEntry;
  358.         return *pt;
  359.     };
  360.     template<typename T>
  361.     inline T& Get(T* leaf, const TString& name) {
  362.         return Get(leaf,name.Data());
  363.     }
  364.     // this is meant for simple data types as int,float,double i.e. splitlevel 0
  365.     // e.g.: unsigned run = tree->Get(run,"run");
  366.     //                          note: ^ no &
  367.     template<typename T>
  368.     inline T Get(T& leaf,const char* name) {
  369.         TBranch* branch;
  370.         if( byName.find(name)==byName.end() ) branch=byName[name] = GetBranch( name );
  371.         else branch=byName[name];
  372.         if(branch==0) {
  373.             cerr<<"Branch "<<name<<" is undefined in tree: "<<GetName()<<endl;
  374.             exit(0);
  375.         }
  376.         branch->SetAddress(&leaf);
  377.         branch->GetEntry(localEntry,1);
  378.         return leaf;
  379.     };
  380.     template<typename T>
  381.     inline T Get(T& leaf, const TString& name) {
  382.         return Get(leaf,name.Data() ) ;
  383.     }
  384.  
  385.     template<typename T>
  386.     inline void GetCA(vector<T*>& some ,int N, const char* name){ // not optimal efficient but simple syntax
  387.         TClonesArray* ar = Get(&ar,name);
  388.         some.clear();
  389.         for(int i = 0;i < N;i++) {
  390.             some.push_back( (T*)ar->At(i) );
  391.         }
  392.     };
  393.     template<typename T>
  394.     inline void GetCA(vector<T*>& some ,int N,const TString& name){
  395.         GetCA(some,N,name.Data());
  396.     };
  397.  
  398.     template<typename T>
  399.     inline void Get4(vector<T*>& some ,int N, const char* name){ // not optimal efficient but simple syntax
  400.         TClonesArray* ar = Get(&ar,name);
  401.         some.clear();
  402.         for(int i = 0;i < N;i++) {
  403.             ((T*)(ar->At(i)))->Fill4();
  404.             some.push_back( (T*)ar->At(i) );
  405.         }
  406.     };
  407.     template<typename T>
  408.     inline void Get4(vector<T*>& some ,int N,const TString& name){
  409.         Get4(some,N,name.Data());
  410.     };
  411.  
  412. private:
  413.     void FillBranchAddresses(TTree* t){
  414.         for(map<const string,TBranch*>::iterator it=byName.begin();it!=byName.end();++it)
  415.             it->second = t->GetBranch(  it->first.c_str() );
  416.     }
  417.  
  418. public:
  419.     // get entry and check for new tree
  420.     // sequential gives best performance
  421.     virtual inline Int_t GetEntry(Long64_t  entry, Int_t getall = 0){
  422.         getall=getall;//just to get rid of unused warning
  423.         localEntry=entry-off;
  424.         if(localEntry>=localMax||localEntry<0){
  425.             localEntry=LoadTree(entry);
  426.             if(fTree) localMax=fTree->GetEntries();
  427.             else cout<<"hmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm"<<endl;
  428.             off=fTreeOffset[fTreeNumber];
  429.             FillBranchAddresses(fTree);
  430.         }
  431.         return localEntry>=0;
  432.     }
  433.     // get entry and check for new tree + weight
  434.     // sequential gives best performance
  435.     inline double GetEntryW(Long64_t  entry, Int_t getall = 0){
  436.         getall=getall;//just to get rid of unused warning
  437.         localEntry=entry-off;
  438.         if(localEntry>=localMax||localEntry<0){
  439.             localEntry=LoadTree(entry);
  440.             if(fTree) localMax=fTree->GetEntries();
  441.             else cout<<"hmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm"<<endl;
  442.             off=fTreeOffset[fTreeNumber];
  443.             FillBranchAddresses(fTree);
  444.             TString filename = GetFile()->GetName();
  445.             filename.ReplaceAll("//","/");
  446.             TString nam( filename(0,filename.Last('/')+1) );
  447.             nam.ReplaceAll("//","/");
  448.             if( weights.find(nam)==weights.end() ) {
  449.                 cout<<"NtupleTools3:GetEntry don't find a weight for "<<filename<<" "<<nam<<endl;
  450.                 exit(0);
  451.             }
  452.             fileWeight=weights[nam];
  453.         }
  454.         return fileWeight;
  455.     }
  456.     // helper function for AddSmart below
  457.     int AddSmartSingle(const TString& name,int max,bool nodup){
  458.         string dcache_gate="dcap://dcache-cms-dcap.desy.de:22125/";
  459.         vector<string> files;
  460.         int n=1;
  461.         if (name.Index("/pnfs/")==0 || name.Index("/store/")==0){
  462.             if(name.Index("/store/")==0) dcache_gate+="/pnfs/desy.de/cms/tier2/";
  463.             if(name.EndsWith("/")){
  464.                 n=GetResult(files,"dcls "+name+" | grep \"\\.root$\" ",nodup);
  465.                 n=n>max?max:n;
  466.                 for(int i=0;i<n;++i) Add((dcache_gate+name+"/"+files[i]));
  467.             } else  Add(dcache_gate+name);
  468.             dcache=true;
  469.         } else {
  470.             if(name.EndsWith("/")){
  471.                 n=GetResult(files,"ls "+name+" | grep \"\\.root$\"",nodup);
  472.                 n=n>max?max:n;
  473.                 for(int i=0;i<n;++i) Add((name+"/"+files[i]));
  474.             } else Add(name);
  475.         }
  476.         return n;
  477.     }
  478.     // Add single file or all files in directory to this tree
  479.     // assumes /pnfs or /store indicates dcache
  480.     // takes trailing / as directory
  481.     // checks for dir on normal filesystem
  482.     // if name contains ' ' or ',' assume a list of filenames
  483.     int AddSmart(const TString& longname,int max=10000,bool nodup=false){
  484.         // check if name contains ' ' or ','
  485.         TObjArray*  arr = longname.Tokenize(',');
  486.         if(arr->GetEntries()==1) arr = longname.Tokenize(' ');
  487.         if(arr->GetEntries()==1)
  488.             // just one name
  489.             return  AddSmartSingle(longname,max,nodup);
  490.         int k=0;
  491.         for(int idx=0;idx<arr->GetEntries();idx++){
  492.             TObjString* tok = (TObjString*) (*arr)[idx];
  493.                 k+=AddSmartSingle(tok->GetName(),max,nodup);
  494.                 max-=k;
  495.         }
  496.         return k;
  497.     }
  498.     int AddSmartW(const TString& longname,double w,int max=10000,bool nodup=false){
  499.         TString nam=longname;
  500.         nam.ReplaceAll("//","/");
  501.         weights[nam]=w;
  502.         return AddSmart(longname,max,nodup);
  503.     }
  504.     // return an (almost) unique file name depending on all files added to this chain
  505.     // if only 1 file use basename
  506.     string GetUniqeName(const char* base="SusyCAF_Tree"){
  507.         stringstream sstr;
  508.         sstr<<base;
  509.         TObjArray* trees = GetListOfFiles();
  510.         if(trees==0) {
  511.             cout<<"EasyChain::GetUniqeName no files in tree"<<endl;
  512.             exit(0);
  513.         } else if(trees->GetEntries()==1) {
  514.             string s((*trees)[0]->GetTitle());
  515.             return file_base(s)+"_out.root";
  516.         } else {
  517.             // we create a hash number depending on all names
  518.             sstr<<"_n"<<trees->GetEntries();
  519.             TString longname;
  520.             TIter next(trees);
  521.             TChainElement *chEl=0;
  522.             while (( chEl=(TChainElement*)next() )) longname.Append(chEl->GetTitle());
  523.             sstr<<"_"<<longname.Hash()<<"_out.root";
  524.             return sstr.str();
  525.         }
  526.     };
  527.     void GetAll(){
  528.         cout<<"EasyChain::GetAll not implemented"<<endl;
  529.     }
  530.     double fileWeight;
  531. private:
  532.     int localEntry;
  533.     int localMax;
  534.     int off;
  535.     // files are from dcache
  536.     bool dcache;
  537.     // acts as booster for tree with many branches
  538.     map<const string,TBranch*> byName;
  539.     map<string, pair<int,void*> > localByName; // a pointer to the branch and the localEntry number for which it had been read
  540.     map<TString,double>  weights;// weights depending on filename or dirname in AddSmartW
  541. #ifdef  __NTHEADER___
  542.     ClassDef(EasyChain, 1);
  543. #endif
  544. };
  545. //}
  546. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement