ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/MitAna/TAM/src/TAMSelector.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: TAMSelector.cxx 4001 2007-05-17 22:14:23Z loizides $
3     //
4    
5     #include "TAMSelector.h"
6    
7    
8     #ifndef ROOT_RVersion
9     #include <RVersion.h>
10     #endif
11     #ifndef ROOT_TFile
12     #include "TFile.h"
13     #endif
14     #ifndef ROOT_TTree
15     #include "TTree.h"
16     #endif
17     #ifndef ROOT_TError
18     #include "TError.h"
19     #endif
20     #ifndef ROOT_TROOT
21     #include "TROOT.h"
22     #endif
23     #ifndef ROOT_TList
24     #include "TList.h"
25     #endif
26     #ifndef ROOT_TClass
27     #include "TClass.h"
28     #endif
29     #ifndef ROOT_TProcessID
30     #include "TProcessID.h"
31     #endif
32     #if ROOT_VERSION_CODE >= ROOT_VERSION(5,0,0) && \
33     ROOT_VERSION_CODE < ROOT_VERSION(5,11,2)
34     #ifndef ROOT_TUrl
35     #include "TUrl.h"
36     #endif
37     #endif
38     #ifndef TAM_TAModule
39     #include "TAModule.h"
40     #endif
41     #ifndef TAM_TAMOutput
42     #include "TAMOutput.h"
43     #endif
44     #ifndef TAM_TAMVirtualLoader
45     #include "TAMVirtualLoader.h"
46     #endif
47     #ifndef TAM_TAMVirtualBranchLoader
48     #include "TAMVirtualBranchLoader.h"
49     #endif
50     #ifndef TAM_TAMTreeLoader
51     #include "TAMTreeLoader.h"
52     #endif
53    
54    
55     //////////////////////////////////////////////////////////////////////////
56     // //
57     // TAMSelector //
58     // //
59     // A selector class for modular processing of a tree (or chain). //
60     // Processing is done by TAModule(s). //
61     // //
62     // Each TAModule contains pointers to the objects that will be read //
63     // in from the tree. For each such pointer, it will call //
64     // ReqBranch(name, pointer) to request that the branch be available for //
65     // processing by the module. The module's pointer would then be //
66     // automatically set to point to the object for the current event by //
67     // the TAMSelector, whenever the module calls LoadBranch. //
68     // //
69     // TAMSelector provides (and hides) all interaction with the tree //
70     // for the TAModule(s). //
71     // //
72     // Author : Corey Reed 07/20/2004 //
73     // Maarten Ballintijn 12/06/2005 //
74     // Constantin Loizides 12/06/2005 //
75     // //
76     //////////////////////////////////////////////////////////////////////////
77    
78     ClassImp(TAMSelector)
79    
80    
81     #if ROOT_VERSION_CODE < ROOT_VERSION(5,11,3)
82     #define R__ASSERT(e) \
83     if (!(e)) Fatal("", kAssertMsg, _QUOTE_(e), __LINE__, __FILE__)
84     #endif
85    
86    
87     //______________________________________________________________________________
88     TAMSelector::TAMSelector() :
89     fTree(0),
90     fBranchTable(),
91     fEventObjs(),
92     fAModules(new TAModule("TAMTopModule",
93     "Top-most module containing all other modules.")),
94     fCurEvt(-1),
95     fOwnInput(0),
96     fAnalysisAborted(kFALSE),
97     fModAborted(kFALSE),
98     fEventAborted(kFALSE),
99     fActNotify(kFALSE),
100     fObjCounter(0),
101     fVerbosity(0),
102     fLoaders()
103     {
104     // Default constructor.
105    
106     fBranchTable.SetOwner(kTRUE);
107     fEventObjs.SetOwner(kTRUE);
108     gROOT->GetListOfBrowsables()->Add(fAModules,"Analysis Modules");
109     fLoaders.SetName("TAM_LOADERS");
110     }
111    
112    
113     //______________________________________________________________________________
114     TAMSelector::~TAMSelector()
115     {
116     // Destructor.
117    
118     gROOT->GetListOfBrowsables()->Remove(fAModules);
119     TList *submods = fAModules->GetListOfTasks();
120     if (submods!=0) submods->Clear("nodelete");
121     delete fAModules;
122     delete fOwnInput;
123     }
124    
125    
126     //______________________________________________________________________________
127     void TAMSelector::AbortAnalysis()
128     {
129     // Aborts the analysis by aborting all modules and never executing
130     // further module funtions.
131    
132     // no way known to propagate the stop of analysis in PROOF from
133     // one slave to the other slaves (and master).
134     Fatal("AbortAnalysis", "Analysis aborted!");
135    
136     fAModules->DeactivateAll();
137     fAnalysisAborted = kTRUE;
138     }
139    
140    
141     //______________________________________________________________________________
142     void TAMSelector::AbortEvent()
143     {
144     // Aborts the current event by setting all modules inactive.
145    
146     fAModules->DeactivateAll();
147     fEventAborted = kTRUE;
148     }
149    
150    
151     //______________________________________________________________________________
152     void TAMSelector::AbortModule(TAModule *mod)
153     {
154     // Abort the specified module by setting it (and its sub modules) inactive.
155    
156     mod->DeactivateAll();
157     fModAborted = kTRUE;
158     }
159    
160    
161     //______________________________________________________________________________
162     void TAMSelector::AddInput(TAModule *mod)
163     {
164     // Adds the module to the top-most module in the hierarchy.
165     // The "misnomer" on the function name is intentional:
166     // This allows users to call gProof->AddInput(myMod) when
167     // using proof and mySelector->AddInput(myMod) when not
168     // using proof.
169    
170     fAModules->Add(mod);
171     }
172    
173     //______________________________________________________________________________
174     Bool_t TAMSelector::AddObjThisEvt(TObject *obj)
175     {
176     // Add this object to the list of objects stored for this event.
177     // See further description below.
178    
179     if(obj)
180     return AddObjThisEvt(obj,obj->GetName());
181     else {
182     Error("AddObjThisEvt",
183     "Can not add null object to event.");
184     return kFALSE;
185     }
186     }
187    
188    
189     //______________________________________________________________________________
190     Bool_t TAMSelector::AddObjThisEvt(TObject *obj, const char *name)
191     {
192     // Add this object to the list of objects stored for this event.
193     // NOTE:
194     // - The object must have a unique name.
195     // - The object must be on the heap.
196     // - The object will be owned by the selector and deleted at the
197     // end of the processing of the current event.
198     //
199     // Returns true iff the object meets the requirements and is added to
200     // the list successfully.
201    
202     if (obj!=0) {
203     if (FindObjThisEvt(name)==0) {
204     if (obj->IsOnHeap()) {
205     fEventObjs.Add(new TAMEvtObj(obj,name));
206     } else {
207     Error("AddObjThisEvt",
208     "Object [%s] does not appear to be on heap. "
209     "Can not add object.",
210     name);
211     }
212     } else {
213     Error("AddObjThisEvt",
214     "Object with name [%s] already added to this event.",
215     name);
216     }
217     } else {
218     Error("AddObjThisEvt",
219     "Can not add null object to event.");
220     }
221     return kFALSE;
222     }
223    
224    
225     //______________________________________________________________________________
226     void TAMSelector::AddNewOutputLists()
227     {
228     // Make a new hierarchy of TAMOutput objects and add it to
229     // the output of this selector. Note that this should only be called
230     // ONCE (by SlaveBegin())!!
231    
232     fAModules->NewOutputList(GetOutputList());
233     }
234    
235    
236     //______________________________________________________________________________
237     void TAMSelector::Begin(TTree */*tree*/)
238     {
239     // The Begin() function is called at the start of the query.
240     // When running with PROOF Begin() is only called on the client.
241     // The tree argument is deprecated (on PROOF 0 is passed).
242     // It checks the tree of modules to be sure each module is set
243     // up to use this selector.
244     // Adds the tree of modules to the input list of this selector.
245     // Builds the hierarchy of TAMOutput objects in the output list.
246     // Then calls Begin() on the TAModule(s). At the end, it adds the
247     // list of loaders to the input list.
248    
249     if (fAnalysisAborted) {
250     return;
251     } else {
252     if (fInput==0) {
253     fOwnInput = new TList;
254     SetInputList(fOwnInput);
255     }
256     CopyModsFromInput();
257     fAModules->SetSelector(this);
258     if (fAModules->CheckSelectors(this)) {
259     if (fModAborted) {
260     fAModules->ResetAllActiveFlags();
261     fModAborted = kFALSE;
262     }
263     fAModules->ExecuteTask(&TAModule::kExecBegin);
264     if (fEventObjs.IsEmpty()==kFALSE) fEventObjs.Delete();
265     } else {
266     Error("Begin",
267     "One or more module is not set up to use this selector.");
268     R__ASSERT(0);
269     }
270     }
271    
272     fInput->AddLast(&fLoaders);
273     }
274    
275    
276     //______________________________________________________________________________
277     void TAMSelector::ClearAllLoaders()
278     {
279     // Go through the list of requested branches and clear the
280     // loaders that were used.
281    
282     TIter nextBr(fBranchTable.MakeIterator());
283     while ( TAMBranchInfo *br = dynamic_cast<TAMBranchInfo*>(nextBr())) {
284    
285     if (!br->fIsLoaded) continue;
286     // don't bother with branches that weren't loaded
287    
288     TAMVirtualBranchLoader *l = br->GetLoader();
289     if (l) {
290     l->Clear();
291     } else {
292     Error("ClearAllLoaders",
293     "Could not get loader for [%s]. Unable to "
294     "try to clear loader for this branch.",
295     br->GetName());
296     }
297     }
298     }
299    
300    
301     //______________________________________________________________________________
302     void TAMSelector::CopyModsFromInput()
303     {
304     // Find all TAModules in the input list and copy them to fAModules.
305    
306     R__ASSERT(fInput!=0);
307    
308     if (fInput->IsEmpty()) return;
309    
310     TObject *obj=fInput->First(), *tobj=0;
311     while (obj!=0) {
312     tobj = fInput->After(obj);
313     if (obj->InheritsFrom(TAModule::Class())) {
314     AddInput(dynamic_cast<TAModule*>(obj));
315     }
316     obj = tobj;
317     }
318     }
319    
320    
321     //______________________________________________________________________________
322     Bool_t TAMSelector::FindLoader(TAMBranchInfo *brInfo)
323     {
324     // Find the loader responsible for the given branch info. Return kFALSE
325     // if none could be found in the list of loaders.
326    
327     const char *bname = brInfo->GetName();
328     TIter next(&fLoaders);
329    
330     while( TAMVirtualLoader *l = dynamic_cast<TAMVirtualLoader*>(next()) ) {
331     TAMVirtualBranchLoader *bl = l->CreateBranchLoader(fTree, brInfo);
332     if (bl != 0) {
333     Info("FindLoader","branch '%s' use loader %s",
334     bname, bl->IsA()->GetName());
335     brInfo->SetLoader(bl);
336     return kTRUE;
337     }
338     }
339    
340     Error("FindLoader","No loader found for branch '%s'", bname);
341     return kFALSE;
342     }
343    
344    
345     //______________________________________________________________________________
346     TAMOutput *TAMSelector::FindModOutput(const TAModule *mod)
347     {
348     // Find the TAMOutput object corresponding to the given module.
349    
350     TAMOutput *obj=0, *tobj=0;
351     TIter nextObj(GetOutputList());
352     while ( (obj = dynamic_cast<TAMOutput*>(nextObj())) ) {
353     tobj = obj->FindModOutput(mod); // search mod and sub mods
354     if (tobj!=0) return tobj;
355     }
356     return 0;
357     }
358    
359    
360     //______________________________________________________________________________
361     TObject *TAMSelector::FindObjThisEvt(const Char_t *name) const
362     {
363     // Looks for the object with the specified name that was added to
364     // this event. If not found, returns zero.
365    
366     TAMEvtObj *eo = dynamic_cast<TAMEvtObj*>(fEventObjs.FindObject(name));
367     if (eo!=0) {
368     return eo->fObj;
369     }
370     return 0;
371     }
372    
373    
374     //______________________________________________________________________________
375     TObject *TAMSelector::FindPublicObj(const Char_t *name) const
376     {
377     // Looks for the public object with the specified name. If not found,
378     // returns zero.
379     // Note: TAModules are not public objects and will not be found by this
380     // function.
381    
382     if (fInput!=0) {
383     TIter nextObj(fInput);
384     TObject *obj=0;
385     TString nm(name);
386     while ( (obj = nextObj()) ) {
387     if ( (nm.CompareTo(obj->GetName())==0) &&
388     (obj->InheritsFrom(TAModule::Class())==kFALSE) ) {
389     return obj;
390     }
391     }
392     } else {
393     Error("FindPublicObj",
394     "Input list is null. No public objects exist.");
395     }
396     return 0;
397     }
398    
399    
400     //______________________________________________________________________________
401     TFile *TAMSelector::GetCurrentFile() const
402     {
403     // Returns the current file that the tree is in.
404    
405     return (fTree) ? (fTree->GetCurrentFile()) : 0;
406     }
407    
408    
409     //______________________________________________________________________________
410     const TAMOutput *TAMSelector::GetModOutput() const
411     {
412     // Return the top-most module output object.
413    
414     return fAModules->GetModOutput();
415     }
416    
417    
418     //______________________________________________________________________________
419     TAMOutput *TAMSelector::GetModOutput()
420     {
421     // Return the top-most module output object.
422    
423     return fAModules->GetModOutput();
424     }
425    
426    
427     //______________________________________________________________________________
428     void TAMSelector::Init(TTree *tree) {
429     // Set the tree for this selector. The Init() function is called
430     // when the selector needs to initialize a new tree (or chain).
431     // It will be called many times when running with PROOF. The
432     // list of requested branches must been constructed
433     // already.
434    
435     if (tree==0) {
436     Error("Init", "Specified tree is null.");
437     AbortAnalysis();
438     }
439    
440     fTree = tree;
441    
442     TIter nextBranch(fBranchTable.MakeIterator());
443     while ( TAMBranchInfo *brInfo =
444     dynamic_cast<TAMBranchInfo*>(nextBranch()) ) {
445     brInfo->Init();
446     }
447     }
448    
449    
450     //______________________________________________________________________________
451     void TAMSelector::LoadBranch(const Char_t *bname)
452     {
453     // Loads the selected branch and get the current entry (number fCurEvt)
454     // if the branch has not yet been loaded for this event. It then makes
455     // sure each module's pointer to the branch object point to the address
456     // of this branch.
457    
458     if(fCurEvt==-1) {
459     Error("LoadBranch",
460     "Can not load branch with name [%s] at this point (fCurEvt==1).",
461     bname);
462     AbortAnalysis();
463     }
464    
465     TAMBranchInfo *brInfo =
466     dynamic_cast<TAMBranchInfo*>( fBranchTable.FindObject(bname) );
467    
468     if (brInfo==0) {
469     Error("LoadBranch",
470     "Could not find branch with name [%s] in requested branch list.",
471     bname);
472     AbortAnalysis();
473     }
474    
475     if (brInfo->IsLoaded() )
476     return;
477    
478     // find loader for branch info if needed and notify
479     if (brInfo->GetLoader() == 0) {
480    
481     if ( !FindLoader(brInfo) ) {
482     Error("LoadBranch","Branch [%s] FindLoader() failed in file [%s].",
483     brInfo->GetName(),
484     (GetCurrentFile()!=0) ? (GetCurrentFile()->GetName()) : "null");
485    
486     AbortAnalysis();
487     }
488    
489     if ( !brInfo->Notify(fTree) )
490     Error("LoadBranch","Branch [%s] Notify() failed in file [%s].",
491     brInfo->GetName(),
492     (GetCurrentFile()!=0) ? (GetCurrentFile()->GetName()) : "null");
493    
494     // have to reset our object counter to take care of objects
495     // created in the notify of the loader
496     fObjCounter=TProcessID::GetObjectCount();
497    
498     }
499    
500     // load the entry
501     Int_t ret = brInfo->GetEntry(fCurEvt);
502     if(ret<0) {
503     Error("LoadBranch",
504     "Error in file [%s] when accessing branch with name [%s] in "
505     "requested branch list.",
506     (GetCurrentFile()!=0) ? (GetCurrentFile()->GetName())
507     : "null", bname);
508    
509     AbortAnalysis();
510     }
511     }
512    
513    
514     //______________________________________________________________________________
515     Bool_t TAMSelector::Notify()
516     {
517     // Sets the branch pointers, checks that the types of the module's
518     // pointers correspond to what is in the tree and calls SetBranchAddress
519     // if necessary. Finally, it also notifies the modules.
520     // The Notify() function is called when a new file is opened. This
521     // can be either for a new TTree in a TChain or when a new TTree
522     // is started when using PROOF.
523    
524     //we are just in Notify(), therefore we ignore this call
525     if(fActNotify) return kTRUE;
526     fActNotify = kTRUE; //"lock" to protect for recursive calls
527    
528     #if ROOT_VERSION_CODE >= ROOT_VERSION(5,0,0) && \
529     ROOT_VERSION_CODE < ROOT_VERSION(5,11,2)
530    
531     // Workaround for older ROOT: give file name to
532     // TFile that accidentally stripped the protocol
533    
534     const TUrl *url = (GetCurrentFile()!=0)
535     ? GetCurrentFile()->GetEndpointUrl() : 0;
536    
537     if (url==0) {
538     Warning("Notify","Could not get URL for file [%s].",
539     (GetCurrentFile()!=0) ? (GetCurrentFile()->GetName())
540     : "null");
541     } else {
542    
543     if(GetCurrentFile()!=0)
544     GetCurrentFile()->SetName((const_cast<TUrl*>(url)->GetUrl()));
545     // the const_cast is for some version of
546     // 5.08.00 that didn't have GetUrl const.
547     }
548     #endif
549    
550     if (fVerbosity>0) {
551     Info("Notify","Opening file [%s] at current event [%d].",
552     (GetCurrentFile()!=0) ? (GetCurrentFile()->GetName()) : "null",
553     fCurEvt);
554     }
555    
556    
557     Bool_t notifyStat = kTRUE;
558    
559     // no event yet processed eg, no loaders assigned,
560     // so that the notify is being delayed to LoadBranch()
561     if(fCurEvt>=0) {
562    
563     TIter nextBranch(fBranchTable.MakeIterator());
564    
565     while ( TAMBranchInfo *brInfo =
566     dynamic_cast<TAMBranchInfo*>(nextBranch()) ) {
567    
568     // notify the branchinfo and its corresponding loader
569     notifyStat &= brInfo->Notify(fTree);
570    
571     // have to reset our object counter to take care of objects
572     // created in the notify of the loader
573     fObjCounter=TProcessID::GetObjectCount();;
574    
575     if (notifyStat==kFALSE) {
576     Error("Notify","Branch [%s] Notify() failed in file [%s].",
577     brInfo->GetName(),
578     (GetCurrentFile()!=0) ? (GetCurrentFile()->GetName())
579     : "null");
580    
581     AbortAnalysis();
582     }
583     }
584    
585     }
586    
587     if (notifyStat && (fAnalysisAborted==kFALSE)) {
588     notifyStat &= fAModules->NotifyAll();
589     }
590    
591     //release "lock" on notify
592     fActNotify = kFALSE;
593    
594     return notifyStat;
595     }
596    
597    
598     //______________________________________________________________________________
599     Bool_t TAMSelector::Process(Long64_t entry)
600     {
601     // Zero's all TAModule(s)'s branch addresses and calls Process()
602     // on the TAModule(s). Then clear any requested clones arrays and
603     // clear the list of event-stored objects.
604     //
605     // The Process() function is called for each entry in the tree (or possibly
606     // keyed object in the case of PROOF) to be processed.
607    
608     if (fAnalysisAborted) {
609     // There is currently no reliable way to exit cleanly back to the
610     // interpreter, so simply return immediately.
611     return kFALSE;
612    
613     } else {
614    
615     // Store object counter
616     fObjCounter=TProcessID::GetObjectCount();;
617    
618     fCurEvt = entry;
619     ZeroAllBranches();
620     if (fModAborted) {
621     fAModules->ResetAllActiveFlags();
622     fModAborted = kFALSE;
623     } else if (fEventAborted) {
624     fAModules->ResetAllActiveFlags();
625     fEventAborted = kFALSE;
626     }
627    
628     if (fVerbosity>9) {
629     if ((entry % 100)==0) {
630     fprintf(stderr,"Processing entry %lld... \r",
631     entry);
632     }
633     }
634     fAModules->ExecuteTask(&TAModule::kExecProcess);
635    
636     ClearAllLoaders();
637     if (fEventObjs.IsEmpty()==kFALSE) fEventObjs.Delete();
638    
639     // Restore object counter
640     TProcessID::SetObjectCount(fObjCounter);
641     }
642    
643     return kTRUE;
644     }
645    
646    
647     //______________________________________________________________________________
648     Bool_t TAMSelector::PublishObj(TObject *obj)
649     {
650     // Adds an object to a list of objects which is outside the module
651     // hierarchy. This can be used to pass objects (for example, calibrations)
652     // between modules. Objects in this list are available before Begin
653     // until the end of SlaveTerminate. They are not guaranteed to be available
654     // during or after Terminate.
655     // Checks (by name) if the object is already in the list. If it is, returns
656     // kFALSE and does not publish the object.
657     // NOTE: These objects are NOT owned by the list! Whatever creates these
658     // objects must take care to (1) remove the object from the list using
659     // RetractObj() and (2) delete the object.
660     // Also NOTE: This will not publish TAModule objects.
661    
662     if (obj!=0) {
663     TObject *ob = FindPublicObj(obj->GetName());
664     if (ob==0) {
665     if (obj->InheritsFrom(TAModule::Class())) {
666     // Disallow publishing of TAModules since it breaks the assumption
667     // that all TAModules in the input list were added by AddInput and
668     // are intended to be executed. (Such modules would be found by
669     // TakeModsFromInput and CopyModsFromInput.)
670     Warning("PublishObj",
671     "Can not publish a TAModule. Object named [%s] not "
672     "published.",
673     obj->GetName());
674     } else {
675     if (fInput!=0) {
676     fInput->Add(obj);
677     return kTRUE;
678     } else {
679     Error("PublishObj",
680     "Input list is null. Could not publish object named [%s].",
681     obj->GetName());
682     }
683     }
684     } else {
685     Warning("PublishObj",
686     "Public object named [%s] already exists.",
687     obj->GetName());
688     }
689     } else {
690     Error("PublishObj",
691     "Can not publish null object.");
692     }
693     return kFALSE;
694     }
695    
696    
697     //______________________________________________________________________________
698     TObject *TAMSelector::RemoveObjThisEvt(const Char_t *name)
699     {
700     // Finds the object with the specified name and removes it from
701     // the list of objects added to this event.
702     // Returns the object that was removed.
703    
704     TAMEvtObj *eo = dynamic_cast<TAMEvtObj*>(fEventObjs.FindObject(name));
705     if (eo!=0) {
706     fEventObjs.Remove(eo);
707     TObject *obj = eo->fObj;
708     eo->fObj = 0; // so it won't delete the object
709     delete eo;
710     return obj;
711     }
712     return 0;
713     }
714    
715    
716     //______________________________________________________________________________
717     TObject *TAMSelector::RetractObj(const Char_t *name)
718     {
719     // Finds the public object with the specified name and removes it from
720     // the list of public objects.
721     // Returns the object that was retracted.
722     // Note: TAmodules are not public objects and will not be removed by this
723     // function.
724    
725     TObject *obj = FindPublicObj(name);
726     if (obj!=0) {
727     return fInput->Remove(obj);
728     }
729     return 0;
730     }
731    
732    
733     //______________________________________________________________________________
734     void TAMSelector::SlaveBegin(TTree *tree)
735     {
736     // Inits the tree and calls SlaveBegin() on the TAModule(s)
737     //
738     // The SlaveBegin() function is called after the Begin() function.
739     // When running with PROOF SlaveBegin() is called on each slave server.
740     // The tree argument is deprecated (on PROOF 0 is passed).
741    
742     if (fAnalysisAborted) {
743     return;
744     } else {
745     // call SlaveBegin first so the modules can call ReqBranch and
746     // build the fBranchTable
747     if (fModAborted) {
748     fAModules->ResetAllActiveFlags();
749     fModAborted = kFALSE;
750     }
751     // remove the modules from the input list and put them in the top-most
752     // module of this selector. make sure they use this selector
753     TakeLoadersFromInput();
754     TakeModsFromInput();
755     fAModules->SetSelector(this);
756     if (fAModules->CheckSelectors(this)) {
757     // build the module output hierarchy
758     AddNewOutputLists();
759     // set up the module's output members
760     if (fAModules->fOutput != 0) {
761     fAModules->fOutput->SetAllOutputMembers(kFALSE);
762     }
763    
764     fAModules->ExecuteTask(&TAModule::kExecSlaveBegin);
765     } else {
766     Error("SlaveBegin",
767     "One or more module is not set up to use this selector.");
768     R__ASSERT(0);
769     }
770    
771     // init requires fBranchTable to be built already
772     // in Proof, this is called automatically when a new tree is loaded
773     if (tree) Init(tree);
774     if (fEventObjs.IsEmpty()==kFALSE) fEventObjs.Delete();
775     }
776     }
777    
778    
779     //______________________________________________________________________________
780     void TAMSelector::SlaveTerminate()
781     {
782     // Calls SlaveTerminate() on the TAModule(s)
783     // The SlaveTerminate() function is called after all entries or objects
784     // have been processed. When running with PROOF SlaveTerminate() is called
785     // on each slave server.
786    
787     if (fAnalysisAborted) {
788     return;
789     } else {
790     if (fModAborted) {
791     fAModules->ResetAllActiveFlags();
792     fModAborted = kFALSE;
793     }
794     fAModules->ExecuteTask(&TAModule::kExecSlaveTerminate);
795     if (fEventObjs.IsEmpty()==kFALSE) fEventObjs.Delete();
796     }
797     }
798    
799    
800     //______________________________________________________________________________
801     void TAMSelector::TakeModsFromInput()
802     {
803     // Find all TAModules in the input list and move them to fAModules.
804    
805     R__ASSERT(fInput!=0);
806    
807     if (fInput->IsEmpty()==kFALSE) {
808     TObject *obj=fInput->First(), *tobj=0;
809     while (obj!=0) {
810     tobj = fInput->After(obj);
811     if (obj->InheritsFrom(TAModule::Class())) {
812     AddInput(dynamic_cast<TAModule*>(obj));
813     fInput->Remove(obj);
814     }
815     obj = tobj;
816     }
817     }
818     }
819    
820    
821     //______________________________________________________________________________
822     void TAMSelector::TakeLoadersFromInput()
823     {
824     // Find all TAModules in the input list and copy them to fAModules.
825    
826     R__ASSERT(fInput!=0);
827    
828     TList *loaders = dynamic_cast<TList*>(fInput->FindObject("TAM_LOADERS"));
829     if (loaders != 0) {
830     TIter next(loaders);
831     while ( TAMVirtualLoader *l =
832     dynamic_cast<TAMVirtualLoader*>(next()) ) {
833     if (loaders != &fLoaders) fLoaders.AddLast(l);
834     }
835     }
836    
837     fLoaders.AddLast(new TAMTreeLoader());
838     }
839    
840    
841     //______________________________________________________________________________
842     void TAMSelector::Terminate()
843     {
844     // Calls Terminate() on the TAModule(s).
845     // When running under Proof, will copy the TAMOutput object
846     // from the fOutput list to the top most TAModule object. Assumes
847     // that the only TAMOutput object in fOutput is the one belonging
848     // to the top most module.
849     // The Terminate() function is the last function to be called during
850     // a query. It always runs on the client, it can be used to present
851     // the results graphically or save the results to file.
852    
853     if (fAnalysisAborted) {
854     return;
855     }
856    
857     if (fModAborted) {
858     fAModules->ResetAllActiveFlags();
859     fModAborted = kFALSE;
860     }
861    
862     if (fAModules->GetModOutput()==0) {
863     // When running under Proof, copy the module output hierarchy to
864     // this selector's top most module.
865     TIter nextObj(GetOutputList());
866     TAMOutput *tout=0;
867     TObject *obj=0;
868     Bool_t alreadySet=kFALSE;
869     while ( (obj = nextObj()) ) {
870     if (obj->InheritsFrom(TAMOutput::Class())) {
871     tout = dynamic_cast<TAMOutput*>(obj);
872     if (alreadySet) {
873     Warning("Terminate",
874     "Found more than one TAMOutput object in the "
875     "output list. Assuming the first one is from the "
876     "top-most module. The output list contains:");
877     GetOutputList()->ls();
878     } else {
879     // copy module output hierarchy
880     fAModules->SetAllModOutput(tout);
881     // try to set module's pointers to their output objects
882     tout->SetAllOutputMembers(kTRUE);
883     alreadySet=kTRUE;
884     }
885     }
886     }
887     if (alreadySet==kFALSE) {
888     Error("Terminate",
889     "Did not find TAMOutput object in the output list! "
890     "The output list contains:");
891     GetOutputList()->ls();
892     }
893     }
894    
895     // move output objs from current objects to stored objects
896     // incase the module wants to write output to a file
897     if (fAModules->GetModOutput()!=0) {
898     fAModules->GetModOutput()->StoreAllOutputObjs();
899     } else {
900     Error("Terminate",
901     "Could not store output objects from this process run.");
902     }
903    
904     fAModules->ExecuteTask(&TAModule::kExecTerminate);
905     if (fEventObjs.IsEmpty()==kFALSE) fEventObjs.Delete();
906    
907     // store output objects again, in case a module added any output
908     // objects during terminate
909     if (fAModules->GetModOutput()!=0) {
910     fAModules->GetModOutput()->StoreAllOutputObjs();
911     } else {
912     Error("Terminate",
913     "Could not store output objects after terminate.");
914     }
915     }
916    
917    
918     //______________________________________________________________________________
919     void TAMSelector::ZeroAllBranches()
920     {
921     // Loops through all branches in fBranchTable and sets all user addresses
922     // for each branch to zero.
923    
924     TIter nextBranch(fBranchTable.MakeIterator());
925     while ( TAMBranchInfo *brInfo =
926     dynamic_cast<TAMBranchInfo*>(nextBranch()) ) {
927     brInfo->ZeroUsrAddrs();
928     }
929     }