ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/MitAna/TAM/src/TAModule.cxx
Revision: 1.1
Committed: Tue May 27 19:13:21 2008 UTC (16 years, 11 months ago) by loizides
Content type: text/plain
Branch: MAIN
Log Message:
TAM trunk 5120

File Contents

# User Rev Content
1 loizides 1.1 //
2     // $Id: TAModule.cxx 3999 2007-05-17 17:41:42Z loizides $
3     //
4    
5     #include "TAModule.h"
6    
7    
8     #ifndef ROOT_RVersion
9     #include <RVersion.h>
10     #endif
11     #ifndef ROOT_TError
12     #include "TError.h"
13     #endif
14     #ifndef ROOT_TIterator
15     #include "TIterator.h"
16     #endif
17     #ifndef ROOT_TAMOutput
18     #include "TAMOutput.h"
19     #endif
20    
21    
22     //////////////////////////////////////////////////////////////////////////
23     // //
24     // //
25     // TAModule //
26     // //
27     // Abstract base class for processing trees. This class allows the trees//
28     // to be processed in a modular fashion. All iteraction with the tree //
29     // itself is taken care of by TAMSelector. //
30     // //
31     // //
32     // Usage: //
33     // - Make a class that (publically) derives from TAModule //
34     // - The class should have member variables (pointers) to the //
35     // objects that will be read in and used from the tree. //
36     // For example, if a module will need the event info branch //
37     // from the tree, it could have a member variable such as: //
38     // TEventInfo* fEvtInfo; //
39     // Note: Such pointers should be initialized to null. //
40     // DO NOT assign them to 'new' objects as this will //
41     // result in a memory leak. The TAMSelector will //
42     // automatically make these pointers point to valid //
43     // objects after the corresponding tree branch has been //
44     // read in for the current entry. //
45     // - Override any of the following functions as needed: //
46     // - Begin() //
47     // - In Proof, this function is called by the client. //
48     // For most applications, this function will not be needed. //
49     // - SlaveBegin() //
50     // - In Proof, this function is called by each slave server. //
51     // Histograms should be created by a module here. //
52     // All branches that the module may need during Process //
53     // should be requested here using ReqBranch. //
54     // For the above example, one would call: //
55     // ReqBranch("eventInfo",fEvtInfo); //
56     // - Process() //
57     // - The TAMSelector (fSelector) will call this function //
58     // on the TAModule hierarchy for every entry in the tree. //
59     // Here one should only load branches as needed to first //
60     // perform the event selection. If and only if an event //
61     // passes the selection, one should then load the branches //
62     // needed for analysis. This is why requested branches are //
63     // NOT automatically loaded. //
64     // Continuing the example, to load the event info branch: //
65     // LoadBranch("eventInfo"); //
66     // cout << "Event Num=" << fEvtInfo->fEventNum << endl; //
67     // The module can then perform analysis and/or fill //
68     // histograms. //
69     // - SlaveTerminate() //
70     // - In Proof, this function is called by each slave server //
71     // after the Process loop. //
72     // - Terminate() //
73     // - In Proof, this function is called by the client at the //
74     // end of the analysis. //
75     // Here, a module can save results to a file or present them//
76     // graphically. //
77     // //
78     // A module may be active or inactive (controlled by TTask::SetActive). //
79     // When a module is not active, its sub modules are not executed. //
80     // //
81     // Author : Corey Reed 07/20/2004 //
82     // Author : Constantin Loizides 07/12/2006 //
83     // //
84     //////////////////////////////////////////////////////////////////////////
85    
86     ClassImp(TAModule)
87    
88    
89     #if ROOT_VERSION_CODE <=ROOT_VERSION(5,11,3)
90     #define R__ASSERT(e) \
91     if (!(e)) Fatal("", kAssertMsg, _QUOTE_(e), __LINE__, __FILE__)
92     #endif
93    
94     const Char_t TAModule::kExecBegin = 10;
95     const Char_t TAModule::kExecSlaveBegin = 20;
96     const Char_t TAModule::kExecProcess = 30;
97     const Char_t TAModule::kExecSlaveTerminate = 40;
98     const Char_t TAModule::kExecTerminate = 50;
99    
100    
101     //______________________________________________________________________________
102     TAModule::TAModule() :
103     fSelector(0),
104     fOutput(0),
105     fDefActv(IsActive()), // in principal, no need to initialze fDefActv
106     fVerbose(0),
107     fStopped(kFALSE)
108     {
109     // Default constructor.
110     }
111    
112    
113     //______________________________________________________________________________
114     TAModule::TAModule(const Char_t* name, const Char_t* title) :
115     TTask(name, title),
116     fSelector(0),
117     fOutput(0),
118     fDefActv(IsActive()), // in principal, no need to initialze fDefActv
119     fVerbose(0),
120     fStopped(kFALSE)
121     {
122     // Normal constructor:
123     // Use SetSelector on the top-most module to recursively set
124     // the selector for all mods.
125     }
126    
127    
128     //______________________________________________________________________________
129     TAModule::~TAModule()
130     {
131     // Destructor.
132     }
133    
134    
135     //______________________________________________________________________________
136     void TAModule::AbortAnalysis()
137     {
138     // Abort the analysis
139    
140     SetDefActive(kFALSE);
141     fSelector->AbortAnalysis();
142     }
143    
144    
145     //______________________________________________________________________________
146     void TAModule::AbortEvent()
147     {
148     // Abort this event
149    
150     fSelector->AbortEvent();
151     }
152    
153    
154     //______________________________________________________________________________
155     void TAModule::AbortModule()
156     {
157     // Abort the module and all sub-modules until the next call in TAMSelector.
158    
159     fSelector->AbortModule(this);
160     }
161    
162    
163     //______________________________________________________________________________
164     Bool_t TAModule::AddObjThisEvt(TObject* obj)
165     {
166     // Add this object to the list of objects stored for this event.
167     // See further description below.
168    
169     if(obj)
170     return AddObjThisEvt(obj,obj->GetName());
171     else {
172     Error("AddObjThisEvt",
173     "Can not add null object to event.");
174     return kFALSE;
175     }
176     }
177    
178    
179     //______________________________________________________________________________
180     Bool_t TAModule::AddObjThisEvt(TObject* obj, const char *name)
181     {
182     // Add this object to the list of objects stored for this event.
183     // NOTE:
184     // - The object must have a unique name.
185     // - The object must be on the heap.
186     // - The object will be owned by the selector and deleted at the
187     // end of the processing of the current event.
188     //
189     // Returns true iff the object meets the requirements and is added to
190     // the list successfully.
191    
192     if (fSelector!=0) {
193     return fSelector->AddObjThisEvt(obj,name);
194     } else {
195     Error("AddObjThisEvt",
196     "No selector exists, so there is no list of objects for "
197     "this event. Object named [%s] not added to this event.",
198     name);
199     }
200     return 0;
201     }
202    
203    
204     //______________________________________________________________________________
205     void TAModule::Browse(TBrowser* b)
206     {
207     // Browse this module's (and its sub modules) output if there is any
208     // otherwise just browse the tree of modules.
209    
210     if (fOutput!=0) fOutput->Browse(b);
211     else TTask::Browse(b);
212     }
213    
214    
215     //______________________________________________________________________________
216     Bool_t TAModule::CheckSelectors(const TAMSelector* sel, const Bool_t warn/*=kTRUE*/) const
217     {
218     // Checks the tree of TAModules to be sure that each module has the
219     // specified selector.
220    
221     Bool_t check = (fSelector->IsEqual(sel));
222     if ( warn && (!check) ) {
223     Warning("CheckSelectors",
224     "Selector of module [%s] is different from specified selector.",
225     GetName());
226     }
227     TAModule* obj=0;
228     TIter nextobj(fTasks);
229     while ( (obj = dynamic_cast<TAModule*>(nextobj())) ) {
230     check &= obj->CheckSelectors(sel);
231     }
232     return check;
233     }
234    
235    
236     //______________________________________________________________________________
237     void TAModule::DeactivateAll()
238     {
239     // Recursively sets the active flag of this and all sub modules
240     // to false. Store their former activity flag in fDefActv so that
241     // they can be reset to that state by ResetAllActiveFlags().
242    
243     TTask::SetActive(kFALSE);
244    
245     TAModule* task=0;
246     TIter nextobj(fTasks);
247     while ( (task = dynamic_cast<TAModule*>(nextobj())) ) {
248     task->DeactivateAll();
249     }
250     }
251    
252    
253     //______________________________________________________________________________
254     void TAModule::Exec(Option_t* option)
255     {
256     // Executes the module corresponding to the given option.
257     // To be called only by TAMSelector.
258     // Checks the address of the private static variables
259     // to ensure that the TTask execute functions can not be
260     // called by derived classes.
261     // This function must not be overridden!
262    
263     R__ASSERT(option);
264    
265     if (option == &kExecBegin) {
266     Begin();
267     } else if (option == &kExecSlaveBegin) {
268     SlaveBegin();
269     } else if (option == &kExecProcess) {
270     Process();
271     } else if (option == &kExecSlaveTerminate) {
272     SlaveTerminate();
273     } else if (option == &kExecTerminate) {
274     Terminate();
275     } else {
276     SendError(kAbortAnalysis,
277     "Exec",
278     "Invalid option [%s] at %p. Function must only be called "
279     "by TAMSelector.",
280     option, static_cast<const void*>(option));
281     };
282     }
283    
284    
285     //______________________________________________________________________________
286     TFile* TAModule::GetCurrentFile() const
287     {
288     // Returns the current file that the tree is in.
289    
290     return (fSelector) ? (fSelector->GetCurrentFile()) : 0;
291     }
292    
293    
294     //______________________________________________________________________________
295     TObject* TAModule::FindObjThisEvt(const Char_t* name) const
296     {
297     // Looks for the object with the specified name that was added to
298     // this event. If not found, returns 0.
299    
300     if (fSelector!=0) {
301     return fSelector->FindObjThisEvt(name);
302     } else {
303     Error("FindObjThisEvt",
304     "No selector exists, so there is no list of objects for "
305     "this event. Could not find object named [%s].",
306     name);
307     }
308     return 0;
309     }
310    
311    
312     //______________________________________________________________________________
313     TObject* TAModule::FindPublicObj(const Char_t* name) const {
314     // Looks for the public object with the specified name. If not found,
315     // returns 0.
316     // Note: TAModules are not public objects and will not be found by this
317     // function.
318    
319     if (fSelector!=0) {
320     return fSelector->FindPublicObj(name);
321     } else {
322     Error("FindPublicObj",
323     "No selector exists, so there is no list of public objects. "
324     "Could not find object named [%s].",
325     name);
326     }
327     return 0;
328     }
329    
330    
331     //______________________________________________________________________________
332     void TAModule::LoadBranch(const Char_t* bname)
333     {
334     // Loads the current entry for the specified branch.
335     // This function should be called by specific TAModules (classes that
336     // inherit from this one) to get the current entry from the tree for
337     // the branch of the specified name.
338     // The branch must have already been requested (see
339     // ReqBranch).
340     // The actual entry is gotten from the tree by TAMSelector
341     // to ensure that the same branch is not loaded more than once
342     // for a given event.
343    
344     if (fSelector!=0) {
345     fSelector->LoadBranch(bname);
346     } else {
347     SendError(kAbortAnalysis,
348     "LoadBranch",
349     "fSelector is null in module [%s]",
350     GetName());
351     }
352     }
353    
354    
355     //______________________________________________________________________________
356     void TAModule::NewOutputList(TList* list)
357     {
358     // Make a hierarchy of TAMOutput objects corresponding to this
359     // module and all its sub modules. This must only be called once! Analysis
360     // will abort if this module already has an associated TAMOutput object.
361     // The input list is assumed to be the fOutput member of the TAMSelector
362     // and must never be null.
363    
364     R__ASSERT(list);
365     if (fOutput!=0) {
366     if (GetVerbosity()>0) {
367     SendError(kWarning,
368     "NewOutputList",
369     "New output list requested in module [%s] but one has "
370     "already been made. This should only happen if the module "
371     "has been added to more than one TAMSelector. "
372     "Set verbosity to 0 to remove this message.", GetName());
373     }
374    
375     if (fOutput->GetMod()!=this) {
376     if ((GetVerbosity()>0) && (fOutput->GetMod()!=0)) {
377     Warning("NewOutputList",
378     "Output of [%s] was associated with module at %p. "
379     "Resetting to this (%p).",
380     GetName(), (void*)fOutput->GetMod(), (void*)this);
381     }
382     fOutput->SetMod(this);
383     }
384    
385     if (list->FindObject(fOutput)==0) {
386     list->Add(fOutput);
387     }
388     } else {
389     fOutput = new TAMOutput(this);
390     fOutput->SetOwner();
391     list->Add(fOutput);
392     }
393    
394     TAModule* task=0;
395     TIter nextobj(fTasks);
396     while ( (task = dynamic_cast<TAModule*>(nextobj())) ) {
397     task->NewOutputList(fOutput);
398     }
399     }
400    
401    
402     //______________________________________________________________________________
403     Bool_t TAModule::NotifyAll() {
404     // recursively call Notify
405    
406     Bool_t ret = Notify();
407     TAModule* task=0;
408     TIter nextobj(fTasks);
409     while ( (task = dynamic_cast<TAModule*>(nextobj())) ) {
410     ret &= task->NotifyAll();
411     }
412     return ret;
413     }
414    
415    
416     //______________________________________________________________________________
417     void TAModule::Print(Option_t *option/*=""*/) const
418     {
419     // Print the modules inside this module and its submodules.
420    
421     TTask::ls(option);
422     }
423    
424    
425     //______________________________________________________________________________
426     Bool_t TAModule::PublishObj(TObject* obj)
427     {
428     // Adds an object to a list of objects which is outside the module
429     // hierarchy. This can be used to pass objects (for example, calibrations)
430     // between modules. Objects in this list are available before Begin
431     // until the end of SlaveTerminate. They are not guaranteed to be available
432     // during or after Terminate.
433     // Checks (by name) if the object is already in the list. If it is, returns
434     // kFALSE and does not publish the object.
435     // NOTE: These objects are NOT owned by the list! Whatever creates these
436     // objects must take care to (1) remove the object from the list using
437     // RetractObj() and (2) delete the object.
438     // Also NOTE: will not publish TAModule objects.
439    
440     if (fSelector!=0) {
441     return fSelector->PublishObj(obj);
442     } else {
443     Error("PublishObj",
444     "No selector exists, so there is no list of public objects. "
445     "Object named [%s] not published.",
446     (obj!=0) ? obj->GetName() : "NULL");
447     }
448     return kFALSE;
449     }
450    
451    
452     //______________________________________________________________________________
453     TObject* TAModule::RemoveObjThisEvt(const Char_t* name)
454     {
455     // Finds the object with the specified name and removes it from
456     // the list of objects added to this event.
457     // Returns the object that was removed.
458    
459     if (fSelector!=0) {
460     return fSelector->RemoveObjThisEvt(name);
461     } else {
462     Error("RemoveObjThisEvt",
463     "No selector exists, so there is no list of objects for "
464     "this event. Object named [%s] not removed from this event.",
465     name);
466     }
467     return 0;
468     }
469    
470    
471     //______________________________________________________________________________
472     void TAModule::RemoveOutput(TObject* obj)
473     {
474     // Remove the object from the list of output objects of this module.
475    
476     R__ASSERT(fOutput);
477     fOutput->RemoveOutput(obj);
478     }
479    
480    
481     //______________________________________________________________________________
482     void TAModule::ResetAllActiveFlags()
483     {
484     // Recursively reset the activity flag of this and all sub modules
485     // to their fDefActv values.
486    
487     if(fStopped) // this module is permanently aborted
488     return;
489    
490     SetActive(fDefActv);
491    
492     TAModule* task=0;
493     TIter nextobj(fTasks);
494     while ( (task = dynamic_cast<TAModule*>(nextobj())) ) {
495     task->ResetAllActiveFlags();
496     }
497     }
498    
499    
500     //______________________________________________________________________________
501     TObject* TAModule::RetractObj(const Char_t* name) {
502     // Finds the public object with the specified name and removes it from
503     // the list of public objects. Returns the object that was retracted.
504     // Note: TAModules are not public objects and will not be removed by
505     // this function.
506    
507     if (fSelector!=0) {
508     return fSelector->RetractObj(name);
509     } else {
510     Error("RetractObj",
511     "No selector exists, so there is no list of public objects. "
512     "Object named [%s] not retracted.",
513     name);
514     }
515     return 0;
516     }
517    
518    
519     //______________________________________________________________________________
520     void TAModule::SendError(const EModResult errLevel,
521     const Char_t* location,
522     const Char_t* formattedMsg, ...)
523     {
524     // Sends an error using the TError facility.
525     // If errLevel is kAbortAnalysis or greater, the error is sent
526     // as type 'kBreak'.
527     // If errLevel is kWarning, the error is sent as type 'kWarning'.
528     // Otherwise it is sent as type 'kError'.
529    
530     va_list ap;
531     va_start(ap,va_(formattedMsg));
532     if (errLevel>=kAbortAnalysis) {
533     DoError(kBreak,location, va_(formattedMsg), ap);
534     AbortAnalysis();
535     } else if (errLevel>=kStopModule) {
536     DoError(kError,location, va_(formattedMsg), ap);
537     StopModule();
538     } else if (errLevel>=kAbortEvent) {
539     DoError(kError,location, va_(formattedMsg), ap);
540     AbortEvent();
541     } else if (errLevel>=kAbortModule) {
542     DoError(kError,location, va_(formattedMsg), ap);
543     AbortModule();
544     } else if (errLevel==kWarning) {
545     DoError(kWarning,location, va_(formattedMsg), ap);
546     } else {
547     Error("SendError",
548     "Unhandled error level [%d] specified when trying to send the "
549     "following error:",static_cast<Int_t>(errLevel));
550     DoError(kError,location, va_(formattedMsg), ap);
551     }
552     va_end(ap);
553     }
554    
555    
556     //______________________________________________________________________________
557     void TAModule::SetAllModOutput(TAMOutput* o)
558     {
559     // Recursively set the output objects for this module and its submodules
560     // see SetModOutput().
561    
562     SetModOutput(o);
563    
564     if ( fTasks->IndexOf(fTasks->Last()) == o->IndexOf(o->Last()) ) {
565     TAModule* task=0;
566     TAMOutput* taskOutput=0;
567     TIter nextobj(fTasks);
568     TIter nextout(o);
569     while ( (task = dynamic_cast<TAModule*>(nextobj())) &&
570     (taskOutput = dynamic_cast<TAMOutput*>(nextout())) ) {
571     task->SetAllModOutput(taskOutput);
572     }
573     } else {
574     SendError(kAbortAnalysis,
575     "SetAllModOutput",
576     "Can not set output for submodules of [%s]. Module contains %d "
577     "submodules, different from the Output which contains %d "
578     "suboutputs.",
579     GetName(),
580     fTasks->IndexOf(fTasks->Last())+1,
581     o->IndexOf(o->Last())+1);
582     }
583     }
584    
585    
586     //______________________________________________________________________________
587     void TAModule::SetModOutput(TAMOutput* o)
588     {
589     // Check that the output object has the same name as this module
590     // If so, set 'o' to be this module's output and set o's module to this.
591    
592     if (o!=0) {
593     TString on(o->GetName());
594     if (on.CompareTo(GetName())==0) {
595     fOutput = o;
596     o->SetMod(this);
597     } else {
598     SendError(kAbortAnalysis,
599     "SetModOutput",
600     "Output named [%s] different from module named [%s]."
601     "Can not set mod output to module.",
602     on.Data(), GetName());
603     }
604     } else {
605     SendError(kAbortAnalysis,
606     "SetModOutput",
607     "Can not set mod output to null object.");
608     }
609     }
610    
611    
612     //______________________________________________________________________________
613     void TAModule::SetSelector(TAMSelector* sel)
614     {
615     // Recursively set the selector for this module and all contained
616     // modules to 'sel'.
617    
618     fSelector = sel;
619    
620     TAModule* obj=0;
621     TIter nextobj(fTasks);
622     while ( (obj = dynamic_cast<TAModule*>(nextobj())) ) {
623     obj->SetSelector(sel);
624     }
625     }
626    
627    
628     //______________________________________________________________________________
629     void TAModule::SkipEvent()
630     {
631     // Aborts the processing of the current event by this task (and prevents
632     // its subtasks from processing the event) without sending an error
633     // message.
634     //
635     // It is designed for use by event selection type modules.
636     //
637     // If an error message is desired, use SendError with an error level of
638     // kSkipModule to both print the message and skip the event. There is no
639     // need to call both SendError(kSkipModule,...) and SkipEvent().
640    
641     AbortModule();
642     }
643    
644    
645     //______________________________________________________________________________
646     void TAModule::StopModule()
647     {
648     // Stop the module for the rest of the analysis.
649    
650     fStopped = kTRUE;
651     fSelector->AbortModule(this);
652     }
653    
654     //______________________________________________________________________________
655     const char *TAModule::Version()
656     {
657     // Return a TAM version string.
658    
659     #ifndef TAM_RELEASE
660     #define TAM_RELEASE "Unknown"
661     #endif
662    
663     return TAM_RELEASE;
664     }