ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/MitAna/TAM/src/TAModule.cxx
Revision: 1.4
Committed: Thu Dec 4 13:50:56 2008 UTC (16 years, 5 months ago) by loizides
Content type: text/plain
Branch: MAIN
CVS Tags: Mit_009c, Mit_009b, Mit_009a, Mit_009, Mit_008, Mit_008pre2, Mit_008pre1, Mit_006b, Mit_006a
Changes since 1.3: +38 -5 lines
Log Message:
Have TAModule::ls

File Contents

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