00001 // @(#)root/tree:$Id: TSelector.cxx 34277 2010-07-01 10:37:08Z rdm $ 00002 // Author: Rene Brun 05/02/97 00003 00004 /************************************************************************* 00005 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * 00006 * All rights reserved. * 00007 * * 00008 * For the licensing terms see $ROOTSYS/LICENSE. * 00009 * For the list of contributors see $ROOTSYS/README/CREDITS. * 00010 *************************************************************************/ 00011 00012 //////////////////////////////////////////////////////////////////////////// 00013 // // 00014 // A TSelector object is used by the TTree::Draw, TTree::Scan, // 00015 // TTree::Process to navigate in a TTree and make selections. // 00016 // It contains the following main methods: // 00017 // // 00018 // void TSelector::Init(TTree *t). Called every time a new TTree is // 00019 // attached. // 00020 // void TSelector::Begin(). This method is called before looping on the // 00021 // events in the Tree. The user can create his histograms in this // 00022 // function. When using PROOF Begin() is called on the client only. // 00023 // Histogram creation should preferable be done in SlaveBegin() in // 00024 // that case. // 00025 // void TSelector::SlaveBegin(). This method is called on each PROOF // 00026 // worker node. The user can create his histograms in this method. // 00027 // In local mode this method is called on the client too. // 00028 // // 00029 // Bool_t TSelector::Notify(). This method is called at the first entry // 00030 // of a new file in a chain. // 00031 // // 00032 // Bool_t TSelector::Process(Long64_t entry). This method is called // 00033 // to process an event. It is the user's responsability to read // 00034 // the corresponding entry in memory (may be just a partial read). // 00035 // Once the entry is in memory one can apply a selection and if the // 00036 // event is selected histograms can be filled. Processing stops // 00037 // when this function returns kFALSE. This function combines the // 00038 // next two functions in one, avoiding to have to maintain state // 00039 // in the class to communicate between these two functions. // 00040 // See WARNING below about entry. // 00041 // This method is used by PROOF. // 00042 // Bool_t TSelector::ProcessCut(Long64_t entry). This method is called // 00043 // before processing entry. It is the user's responsability to read // 00044 // the corresponding entry in memory (may be just a partial read). // 00045 // The function returns kTRUE if the entry must be processed, // 00046 // kFALSE otherwise. This method is obsolete, use Process(). // 00047 // See WARNING below about entry. // 00048 // void TSelector::ProcessFill(Long64_t entry). This method is called // 00049 // for all selected events. User fills histograms in this function. // 00050 // This method is obsolete, use Process(). // 00051 // See WARNING below about entry. // 00052 // void TSelector::SlaveTerminate(). This method is called at the end of // 00053 // the loop on all PROOF worker nodes. In local mode this method is // 00054 // called on the client too. // 00055 // void TSelector::Terminate(). This method is called at the end of // 00056 // the loop on all events. When using PROOF Terminate() is call on // 00057 // the client only. Typically one performs the fits on the produced // 00058 // histograms or write the histograms to file in this method. // 00059 // // 00060 // WARNING when a selector is used with a TChain: // 00061 // in the Process, ProcessCut, ProcessFill function, you must use // 00062 // the pointer to the current Tree to call GetEntry(entry). // 00063 // entry is always the local entry number in the current tree. // 00064 // Assuming that fChain is the pointer to the TChain being processed, // 00065 // use fChain->GetTree()->GetEntry(entry); // 00066 // // 00067 //////////////////////////////////////////////////////////////////////////// 00068 00069 #include "TROOT.h" 00070 #include "TSystem.h" 00071 #include "TTree.h" 00072 #include "TError.h" 00073 #include "TSelectorCint.h" 00074 #include "TClass.h" 00075 #include "TInterpreter.h" 00076 00077 00078 ClassImp(TSelector) 00079 00080 //______________________________________________________________________________ 00081 TSelector::TSelector() : TObject() 00082 { 00083 // Default selector ctor. 00084 00085 fStatus = 0; 00086 fAbort = kContinue; 00087 fObject = 0; 00088 fInput = 0; 00089 fOutput = new TSelectorList; 00090 fOutput->SetOwner(); 00091 } 00092 00093 //______________________________________________________________________________ 00094 TSelector::~TSelector() 00095 { 00096 // Selector destructor. 00097 00098 delete fOutput; 00099 } 00100 00101 //______________________________________________________________________________ 00102 void TSelector::Abort(const char *why, EAbort what) 00103 { 00104 // Abort processing. If what = kAbortProcess, the Process() loop will be 00105 // aborted. If what = kAbortFile, the current file in a chain will be 00106 // aborted and the processing will continue with the next file, if there 00107 // is no next file then Process() will be aborted. Abort() can also be 00108 // called from Begin(), SlaveBegin(), Init() and Notify(). After abort 00109 // the SlaveTerminate() and Terminate() are always called. The abort flag 00110 // can be checked in these methods using GetAbort(). 00111 00112 fAbort = what; 00113 TString mess = "Abort"; 00114 if (fAbort == kAbortProcess) 00115 mess = "AbortProcess"; 00116 else if (fAbort == kAbortFile) 00117 mess = "AbortFile"; 00118 00119 Info(mess, "%s", why); 00120 } 00121 00122 //______________________________________________________________________________ 00123 TSelector *TSelector::GetSelector(const char *filename) 00124 { 00125 // The code in filename is loaded (interpreted or compiled, see below), 00126 // filename must contain a valid class implementation derived from TSelector. 00127 // 00128 // If filename is of the form file.C, the file will be interpreted. 00129 // If filename is of the form file.C++, the file file.C will be compiled 00130 // and dynamically loaded. The corresponding binary file and shared 00131 // library will be deleted at the end of the function. 00132 // If filename is of the form file.C+, the file file.C will be compiled 00133 // and dynamically loaded. At next call, if file.C is older than file.o 00134 // and file.so, the file.C is not compiled, only file.so is loaded. 00135 // 00136 // The static function returns a pointer to a TSelector object 00137 00138 // If the filename does not contain "." assume class is compiled in 00139 TString localname; 00140 Bool_t fromFile = kFALSE; 00141 if (strchr(filename, '.') != 0) { 00142 //Interpret/compile filename via CINT 00143 localname = ".L "; 00144 localname += filename; 00145 gROOT->ProcessLine(localname); 00146 fromFile = kTRUE; 00147 } 00148 00149 //loop on all classes known to CINT to find the class on filename 00150 //that derives from TSelector 00151 const char *basename = gSystem->BaseName(filename); 00152 if (!basename) { 00153 ::Error("TSelector::GetSelector","unable to determine the classname for file %s", filename); 00154 return 0; 00155 } 00156 TString aclicmode,args,io; 00157 localname = gSystem->SplitAclicMode(basename,aclicmode,args,io); 00158 Bool_t isCompiled = !fromFile || aclicmode.Length()>0; 00159 if (localname.Last('.') != kNPOS) 00160 localname.Remove(localname.Last('.')); 00161 00162 // if a file was not specified, try to load the class via the interpreter; 00163 // this returns 0 (== failure) in the case the class is already in memory 00164 // but does not have a dictionary, so we just raise a flag for better 00165 // diagnostic in the case the class is not found in the CINT ClassInfo table. 00166 Bool_t autoloaderr = kFALSE; 00167 if (!fromFile && gCint->AutoLoad(localname) != 1) 00168 autoloaderr = kTRUE; 00169 00170 ClassInfo_t *cl = gCint->ClassInfo_Factory(); 00171 Bool_t ok = kFALSE; 00172 while (gCint->ClassInfo_Next(cl)) { 00173 if (localname == gCint->ClassInfo_FullName(cl)) { 00174 if (gCint->ClassInfo_IsBase(cl,"TSelector")) ok = kTRUE; 00175 break; 00176 } 00177 } 00178 if (!ok) { 00179 if (fromFile) { 00180 ::Error("TSelector::GetSelector", 00181 "file %s does not have a valid class deriving from TSelector", filename); 00182 } else { 00183 if (autoloaderr) 00184 ::Error("TSelector::GetSelector", "class %s could not be loaded", filename); 00185 else 00186 ::Error("TSelector::GetSelector", 00187 "class %s does not exist or does not derive from TSelector", filename); 00188 } 00189 return 0; 00190 } 00191 00192 // we can now create an instance of the class 00193 TSelector *selector = (TSelector*)gCint->ClassInfo_New(cl); 00194 if (!selector || isCompiled) return selector; 00195 00196 //interpreted selector: cannot be used as such 00197 //create a fake selector 00198 TSelectorCint *select = new TSelectorCint(); 00199 select->Build(selector, cl); 00200 gCint->ClassInfo_Delete(cl); 00201 return select; 00202 } 00203 00204 //______________________________________________________________________________ 00205 Bool_t TSelector::IsStandardDraw(const char *selec) 00206 { 00207 // Find out if this is a standard selection used for Draw actions 00208 // (either TSelectorDraw, TProofDraw or deriving from them). 00209 00210 // Make sure we have a name 00211 if (!selec) { 00212 ::Info("TSelector::IsStandardDraw", 00213 "selector name undefined - do nothing"); 00214 return kFALSE; 00215 } 00216 00217 Bool_t stdselec = kFALSE; 00218 if (!strchr(selec, '.')) { 00219 if (strstr(selec, "TSelectorDraw")) { 00220 stdselec = kTRUE; 00221 } else { 00222 TClass *cl = TClass::GetClass(selec); 00223 if (cl && (cl->InheritsFrom("TProofDraw") || 00224 cl->InheritsFrom("TSelectorDraw"))) 00225 stdselec = kTRUE; 00226 } 00227 } 00228 00229 // We are done 00230 return stdselec; 00231 }