Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TSelector.cxx
Go to the documentation of this file.
1 // @(#)root/tree:$Id$
2 // Author: Rene Brun 05/02/97
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 /** \class TSelector
13 \ingroup tree
14 
15 A TSelector object is used by the TTree::Draw, TTree::Scan,
16 TTree::Process to navigate in a TTree and make selections.
17 It contains the following main methods:
18 
19 - void TSelector::Init(TTree *t). Called every time a new TTree is
20  attached.
21 
22 - void TSelector::SlaveBegin(). Create e.g. histograms in this method.
23  This method is called (with or without PROOF) before looping on the
24  entries in the Tree. When using PROOF, this method is called on
25  each worker node.
26 
27 - void TSelector::Begin(). Mostly for backward compatibility; use
28  SlaveBegin() instead. Both methods are called before looping on the
29  entries in the Tree. When using PROOF, Begin() is called on the
30  client only.
31 
32 - Bool_t TSelector::Notify(). This method is called at the first entry
33  of a new file in a chain.
34 
35 - Bool_t TSelector::Process(Long64_t entry). This method is called
36  to process an entry. It is the user's responsability to read
37  the corresponding entry in memory (may be just a partial read).
38  Once the entry is in memory one can apply a selection and if the
39  entry is selected histograms can be filled. Processing stops
40  when this function returns kFALSE. This function combines the
41  next two functions in one, avoiding to have to maintain state
42  in the class to communicate between these two functions.
43  See WARNING below about entry.
44  This method is used by PROOF.
45 
46 - Bool_t TSelector::ProcessCut(Long64_t entry). This method is called
47  before processing entry. It is the user's responsability to read
48  the corresponding entry in memory (may be just a partial read).
49  The function returns kTRUE if the entry must be processed,
50  kFALSE otherwise. This method is obsolete, use Process().
51  See WARNING below about entry.
52 
53 - void TSelector::ProcessFill(Long64_t entry). This method is called
54  for all selected entries. User fills histograms in this function.
55  This method is obsolete, use Process().
56  See WARNING below about entry.
57 
58 - void TSelector::SlaveTerminate(). This method is called at the end of
59  the loop on all PROOF worker nodes. In local mode this method is
60  called on the client too.
61 
62 - void TSelector::Terminate(). This method is called at the end of
63  the loop on all entries. When using PROOF Terminate() is call on
64  the client only. Typically one performs the fits on the produced
65  histograms or write the histograms to file in this method.
66 
67 __WARNING when a selector is used with a TChain:__
68 
69 in the Process, ProcessCut, ProcessFill function, you must use
70 the pointer to the current Tree to call `GetEntry(entry)`.
71 entry is always the local entry number in the current tree.
72 Assuming that fChain is the pointer to the TChain being processed,
73 use `fChain->GetTree()->GetEntry(entry);`
74 */
75 
76 #include "TROOT.h"
77 #include "TSystem.h"
78 #include "TTree.h"
79 #include "TError.h"
80 #include "TSelector.h"
81 #include "TClass.h"
82 #include "TInterpreter.h"
83 
84 ClassImp(TSelector);
85 
86 ////////////////////////////////////////////////////////////////////////////////
87 /// Default selector ctor.
88 
89 TSelector::TSelector() : TObject()
90 {
91  fStatus = 0;
92  fAbort = kContinue;
93  fObject = 0;
94  fInput = 0;
95  fOutput = new TSelectorList;
96  fOutput->SetOwner();
97 }
98 
99 ////////////////////////////////////////////////////////////////////////////////
100 /// Selector destructor.
101 
102 TSelector::~TSelector()
103 {
104  delete fOutput;
105 }
106 
107 ////////////////////////////////////////////////////////////////////////////////
108 /// Abort processing. If what = kAbortProcess, the Process() loop will be
109 /// aborted. If what = kAbortFile, the current file in a chain will be
110 /// aborted and the processing will continue with the next file, if there
111 /// is no next file then Process() will be aborted. Abort() can also be
112 /// called from Begin(), SlaveBegin(), Init() and Notify(). After abort
113 /// the SlaveTerminate() and Terminate() are always called. The abort flag
114 /// can be checked in these methods using GetAbort().
115 
116 void TSelector::Abort(const char *why, EAbort what)
117 {
118  fAbort = what;
119  TString mess = "Abort";
120  if (fAbort == kAbortProcess)
121  mess = "AbortProcess";
122  else if (fAbort == kAbortFile)
123  mess = "AbortFile";
124 
125  Info(mess, "%s", why);
126 }
127 
128 ////////////////////////////////////////////////////////////////////////////////
129 /// The code in filename is loaded (interpreted or compiled, see below),
130 /// filename must contain a valid class implementation derived from TSelector.
131 ///
132 /// If filename is of the form file.C, the file will be interpreted.
133 /// If filename is of the form file.C++, the file file.C will be compiled
134 /// and dynamically loaded. The corresponding binary file and shared
135 /// library will be deleted at the end of the function.
136 /// If filename is of the form file.C+, the file file.C will be compiled
137 /// and dynamically loaded. At next call, if file.C is older than file.o
138 /// and file.so, the file.C is not compiled, only file.so is loaded.
139 ///
140 /// The static function returns a pointer to a TSelector object
141 
142 TSelector *TSelector::GetSelector(const char *filename)
143 {
144  // If the filename does not contain "." assume class is compiled in
145  TString localname;
146  Bool_t fromFile = kFALSE;
147  if (strchr(filename, '.') != 0) {
148  //Interpret/compile filename via CINT
149  localname = ".L ";
150  localname += filename;
151  gROOT->ProcessLine(localname);
152  fromFile = kTRUE;
153  }
154 
155  //loop on all classes known to CINT to find the class on filename
156  //that derives from TSelector
157  const char *basename = gSystem->BaseName(filename);
158  if (!basename) {
159  ::Error("TSelector::GetSelector","unable to determine the classname for file %s", filename);
160  return 0;
161  }
162  TString aclicmode,args,io;
163  localname = gSystem->SplitAclicMode(basename,aclicmode,args,io);
164  if (localname.Last('.') != kNPOS)
165  localname.Remove(localname.Last('.'));
166 
167  // if a file was not specified, try to load the class via the interpreter;
168  // this returns 0 (== failure) in the case the class is already in memory
169  // but does not have a dictionary, so we just raise a flag for better
170  // diagnostic in the case the class is not found in the CINT ClassInfo table.
171  Bool_t autoloaderr = kFALSE;
172  if (!fromFile && gCling->AutoLoad(localname) != 1)
173  autoloaderr = kTRUE;
174 
175  TClass *selCl = TClass::GetClass(localname);
176  if (selCl) {
177  // We have all we need.
178  auto offset = selCl->GetBaseClassOffset(TSelector::Class());
179  if (offset == -1) {
180  // TSelector is not a based class.
181  if (fromFile)
182  ::Error("TSelector::GetSelector",
183  "The class %s in file %s does not derive from TSelector.", localname.Data(), filename);
184  else if (autoloaderr)
185  ::Error("TSelector::GetSelector", "class %s could not be loaded", filename);
186  else
187  ::Error("TSelector::GetSelector",
188  "class %s does not exist or does not derive from TSelector", filename);
189  return 0;
190  }
191  char *result = (char*)selCl->New();
192  // By adding offset, we support the case where TSelector is not the
193  // "left-most" base class (i.e. offset != 0)
194  return (TSelector*)(result+offset);
195 
196  } else {
197  ClassInfo_t *cl = gCling->ClassInfo_Factory(localname);
198  Bool_t ok = kFALSE;
199  Bool_t nameFound = kFALSE;
200  if (cl && gCling->ClassInfo_IsValid(cl)) {
201  if (localname == gCling->ClassInfo_FullName(cl)) {
202  nameFound = kTRUE;
203  if (gCling->ClassInfo_IsBase(cl,"TSelector")) ok = kTRUE;
204  }
205  }
206  if (!ok) {
207  if (fromFile) {
208  if (nameFound) {
209  ::Error("TSelector::GetSelector",
210  "The class %s in file %s does not derive from TSelector.", localname.Data(), filename);
211  } else {
212  ::Error("TSelector::GetSelector",
213  "The file %s does not define a class named %s.", filename, localname.Data());
214  }
215  } else {
216  if (autoloaderr)
217  ::Error("TSelector::GetSelector", "class %s could not be loaded", filename);
218  else
219  ::Error("TSelector::GetSelector",
220  "class %s does not exist or does not derive from TSelector", filename);
221  }
222  gCling->ClassInfo_Delete(cl);
223  return 0;
224  }
225 
226  // we can now create an instance of the class
227  TSelector *selector = (TSelector*)gCling->ClassInfo_New(cl);
228  gCling->ClassInfo_Delete(cl);
229  return selector;
230  }
231 }
232 
233 ////////////////////////////////////////////////////////////////////////////////
234 /// Find out if this is a standard selection used for Draw actions
235 /// (either TSelectorDraw, TProofDraw or deriving from them).
236 
237 Bool_t TSelector::IsStandardDraw(const char *selec)
238 {
239  // Make sure we have a name
240  if (!selec) {
241  ::Info("TSelector::IsStandardDraw",
242  "selector name undefined - do nothing");
243  return kFALSE;
244  }
245 
246  Bool_t stdselec = kFALSE;
247  if (!strchr(selec, '.')) {
248  if (strstr(selec, "TSelectorDraw")) {
249  stdselec = kTRUE;
250  } else {
251  TClass *cl = TClass::GetClass(selec);
252  if (cl && (cl->InheritsFrom("TProofDraw") ||
253  cl->InheritsFrom("TSelectorDraw")))
254  stdselec = kTRUE;
255  }
256  }
257 
258  // We are done
259  return stdselec;
260 }
261 
262 ////////////////////////////////////////////////////////////////////////////////
263 /// Imports the content of 'output' in the internal output list. Existing content
264 /// in the output list is discarded (unless found also in 'output').
265 /// In particular, if 'output' is nullptr or empty, reset the internal list.
266 /// On return, the content of 'output' is cleared to avoid double deletion issues.
267 /// (The caller is responsible of 'output' as container: its content is transferred
268 /// under the selector ownership).
269 
270 void TSelector::ImportOutput(TList *output) {
271 
272  // Reset the list, if required
273  if (!output || output->GetSize() <= 0) {
274  fOutput->Delete();
275  return;
276  }
277 
278  TObject *o;
279 
280  // Remove from new list objects already existing locally
281  TIter nxexo(fOutput);
282  while ((o = nxexo())) {
283  if (output->FindObject(o)) output->Remove(o);
284  }
285 
286  // Transfer remaining objects
287  TIter nxo(output);
288  while ((o = nxo())) {
289  fOutput->Add(o);
290  }
291 
292  // Cleanup original list
293  output->SetOwner(kFALSE);
294  output->Clear("nodelete");
295 
296  // Done
297  return;
298 }
299 
300 Bool_t TSelector::ProcessCut(Long64_t /*entry*/)
301 {
302  // This method is called before processing entry. It is the user's responsability to read
303  // the corresponding entry in memory (may be just a partial read).
304  // The function returns kTRUE if the entry must be processed,
305  // kFALSE otherwise. This method is obsolete, use Process().
306  //
307  // WARNING when a selector is used with a TChain:
308  // in the Process, ProcessCut, ProcessFill function, you must use
309  // the pointer to the current Tree to call GetEntry(entry).
310  // entry is always the local entry number in the current tree.
311  // Assuming that fChain is the pointer to the TChain being processed,
312  // use fChain->GetTree()->GetEntry(entry);
313 
314  return kTRUE;
315 }
316 
317 void TSelector::ProcessFill(Long64_t /*entry*/)
318 {
319  // This method is called for all selected entries. User fills histograms
320  // in this function. This method is obsolete, use Process().
321  //
322  // WARNING when a selector is used with a TChain:
323  // in the Process, ProcessCut, ProcessFill function, you must use
324  // the pointer to the current Tree to call GetEntry(entry).
325  // entry is always the local entry number in the current tree.
326  // Assuming that fChain is the pointer to the TChain being processed,
327  // use fChain->GetTree()->GetEntry(entry);
328 }
329 
330 Bool_t TSelector::Process(Long64_t /*entry*/) {
331  // The Process() function is called for each entry in the tree (or possibly
332  // keyed object in the case of PROOF) to be processed. The entry argument
333  // specifies which entry in the currently loaded tree is to be processed.
334  // It can be passed to either t01::GetEntry() or TBranch::GetEntry()
335  // to read either all or the required parts of the data. When processing
336  // keyed objects with PROOF, the object is already loaded and is available
337  // via the fObject pointer.
338  //
339  // This function should contain the "body" of the analysis. It can contain
340  // simple or elaborate selection criteria, run algorithms on the data
341  // of the event and typically fill histograms.
342  //
343  // The processing can be stopped by calling Abort().
344  //
345  // Use fStatus to set the return value of TTree::Process().
346  //
347  // The return value is currently not used.
348 
349  return kFALSE;
350 }
351