source: trunk/MagicSoft/Mars/mbase/MTask.cc@ 2951

Last change on this file since 2951 was 2858, checked in by tbretz, 21 years ago
*** empty log message ***
File size: 12.9 KB
Line 
1/* ======================================================================== *\
2!
3! *
4! * This file is part of MARS, the MAGIC Analysis and Reconstruction
5! * Software. It is distributed to you in the hope that it can be a useful
6! * and timesaving tool in analysing Data of imaging Cerenkov telescopes.
7! * It is distributed WITHOUT ANY WARRANTY.
8! *
9! * Permission to use, copy, modify and distribute this software and its
10! * documentation for any purpose is hereby granted without fee,
11! * provided that the above copyright notice appear in all copies and
12! * that both that copyright notice and this permission notice appear
13! * in supporting documentation. It is provided "as is" without express
14! * or implied warranty.
15! *
16!
17!
18! Author(s): Thomas Bretz, 12/2000 <mailto:tbretz@astro.uni-wuerzburg.de>
19!
20! Copyright: MAGIC Software Development, 2000-2003
21!
22!
23\* ======================================================================== */
24
25/////////////////////////////////////////////////////////////////////////////
26//
27// MTask
28//
29// Base class for all tasks which can perfomed in a tasklist
30// For each event processed in the eventloop all the different
31// tasks in the tasklist will be processed.
32//
33// So all tasks must inherit from this baseclass.
34//
35// The inheritance from MInputStreamID is used to indicate the
36// type of event that this task is for. If it is "All" it is executed
37// independantly of the actual ID of the task list.
38//
39// Inside this abstract class, there are three fundamental function:
40//
41// - PreProcess(): executed before the eventloop starts. Here you
42// can initiate different things, open files, etc.
43// As an argument this function gets a pointer to the
44// parameter list. You can stop the execution by
45// returning kFALSE instead of kTRUE. If an error
46// occured and you return kFALSE make sure, that
47// any action is closed correctly and all newly
48// created object are deleted. The PostProcess in
49// such a case won't be executed by the Tasklist or
50// Eventloop.
51//
52// - Process(): executed for each event in the eventloop. Do it
53// one task after the other (as they occur in the
54// tasklist). Only the tasks with a Stream ID
55// which matches the actual ID of the tasklist
56// are executed. A task can return kFALSE to
57// stop the execuition of the tasklist or
58// kCONTINUE to skip the pending tasks. If you want
59// to stop the eventloop and wants the eventloop to
60// return the status 'failed' return kERROR.
61//
62// - ReInit() The idea is, that
63// a) we have one file per run
64// b) each file contains so called run-headers which
65// stores information 'per run', eg MRawRunHeader
66// or the bad pixels
67// c) this information must be evaluated somehow each
68// time a new file is opened.
69//
70// If you use MReadMarsFile or MCT1ReadPreProc it is
71// called each time a new file has been opened and the
72// new run headers have been read before the first
73// event of these file is preprocessed.
74//
75// - PostProcess(): executed after the eventloop. Here you can close
76// output files, start display of the run parameter,
77// etc. PostProcess is only executed in case of
78// PreProcess was successfull (returned kTRUE)
79//
80// Version 1:
81// ----------
82// - first version
83//
84// Version 2:
85// ----------
86// - added fSerialNumber
87//
88/////////////////////////////////////////////////////////////////////////////
89#include "MTask.h"
90
91#include <fstream>
92#include <TBaseClass.h>
93
94#include "MLog.h"
95#include "MLogManip.h"
96
97#include "MFilter.h"
98#include "MStatusDisplay.h"
99
100ClassImp(MTask);
101
102using namespace std;
103
104MTask::MTask(const char *name, const char *title)
105 : fFilter(NULL), fSerialNumber(0), fIsPreprocessed(kFALSE), fNumExecutions(0)
106{
107 fName = name ? name : "MTask";
108 fTitle = title ? title : "Base class for all tasks (dummy task).";
109
110 fListOfBranches = new TList;
111 fListOfBranches->SetOwner();
112}
113
114MTask::~MTask()
115{
116 delete fListOfBranches;
117}
118
119// --------------------------------------------------------------------------
120//
121// This adds a branch to the list for the auto enabeling schmeme.
122// This makes it possible for MReadTree to decide which branches
123// are really needed for the eventloop. Only the necessary branches
124// are read from disk which speeds up the calculation enormously.
125//
126// You can use TRegExp expressions like "*.fEnergy", but the
127// recommended method is to call this function for exactly all
128// branches you want to have, eg:
129// AddToBranchList("MMcTrig.fNumFirstLevel");
130// AddToBranchList("MMcTrig;1.fNumFirstLevel");
131// AddToBranchList("MMcTrig;2.fNumFirstLevel");
132//
133// We agreed on the convetion, that all branches are stored with
134// a trailing dot '.' so that always the Master Branch name
135// (eg. MMcTrig) is part of the branch name.
136//
137// Remark: The common place to call AddToBranchList is the
138// constructor of the derived classes (tasks)
139//
140void MTask::AddToBranchList(const char *b)
141{
142 if (fListOfBranches->FindObject(b))
143 return;
144
145 fListOfBranches->Add(new TNamed(b, ""));
146}
147
148// --------------------------------------------------------------------------
149//
150// Using this overloaded member function you may cascade several branches
151// in acomma seperated list, eg: "MMcEvt.fTheta,MMcEvt.fEnergy"
152//
153// For moredetailed information see AddToBranchList(const char *b);
154//
155void MTask::AddToBranchList(const TString &str)
156{
157 TString s = str;
158
159 while (!s.IsNull())
160 {
161 Int_t fst = s.First(',');
162
163 if (fst<0)
164 fst = s.Length();
165
166 AddToBranchList((const char*)TString(s(0, fst)));
167
168 s.Remove(0, fst+1);
169 }
170}
171
172// --------------------------------------------------------------------------
173//
174// Copy constructor.
175//
176MTask::MTask(MTask &t)
177{
178 fFilter = t.fFilter;
179 fListOfBranches->AddAll(t.fListOfBranches);
180}
181
182// --------------------------------------------------------------------------
183//
184// Mapper function for PreProcess.
185// Sets the preprocessed flag dependend on the return value of PreProcess.
186//
187Int_t MTask::CallPreProcess(MParList *plist)
188{
189 fNumExecutions = 0;
190
191 *fLog << all << fName << "... " << flush;
192 if (fDisplay)
193 fDisplay->SetStatusLine2(*this);
194
195 switch (PreProcess(plist))
196 {
197 case kFALSE:
198 return kFALSE;
199
200 case kTRUE:
201 fIsPreprocessed = kTRUE;
202 return kTRUE;
203
204 case kSKIP:
205 return kSKIP;
206 }
207
208 *fLog << err << dbginf << "PreProcess of " << GetDescriptor();
209 *fLog << " returned an unknown value... aborting." << endl;
210
211 return kFALSE;
212}
213
214// --------------------------------------------------------------------------
215//
216// Mapper function for Process.
217// Executes Process dependent on the existance of a filter and its possible
218// return value.
219// If Process is executed, the execution counter is increased.
220//
221Int_t MTask::CallProcess()
222{
223 //
224 // Check for the existance of a filter. If a filter is existing
225 // check for its value. If the value is kFALSE don't execute
226 // this task.
227 //
228 const Bool_t exec = fFilter ? fFilter->IsConditionTrue() : kTRUE;
229
230 if (!exec)
231 return kTRUE;
232
233 fNumExecutions++;
234 return Process();
235}
236
237// --------------------------------------------------------------------------
238//
239// Mapper function for PreProcess.
240// Calls Postprocess dependent on the state of the preprocessed flag,
241// resets this flag.
242//
243Int_t MTask::CallPostProcess()
244{
245 if (!fIsPreprocessed)
246 return kTRUE;
247
248 fIsPreprocessed = kFALSE;
249
250 *fLog << all << fName << "... " << flush;
251 if (fDisplay)
252 fDisplay->SetStatusLine2(*this);
253
254 return PostProcess();
255}
256
257// --------------------------------------------------------------------------
258//
259// This is reinit function
260//
261// This function is called asynchronously if the tasks in the tasklist need
262// reinitialization. This for example happens when the eventloop switches
263// from one group of events to another one (eg. switching between events
264// of different runs means reading a new run header and a new run header
265// may mean that some value must be reinitialized)
266//
267// the virtual implementation returns kTRUE
268//
269Bool_t MTask::ReInit(MParList *pList)
270{
271 return kTRUE;
272}
273
274// --------------------------------------------------------------------------
275//
276// This is processed before the eventloop starts
277//
278// It is the job of the PreProcess to connect the tasks
279// with the right container in the parameter list.
280//
281// the virtual implementation returns kTRUE
282//
283Int_t MTask::PreProcess(MParList *pList)
284{
285 return kTRUE;
286}
287
288// --------------------------------------------------------------------------
289//
290// This is processed for every event in the eventloop
291//
292// the virtual implementation returns kTRUE
293//
294Int_t MTask::Process()
295{
296 return kTRUE;
297}
298
299// --------------------------------------------------------------------------
300//
301// This is processed after the eventloop starts
302//
303// the virtual implementation returns kTRUE
304//
305Int_t MTask::PostProcess()
306{
307 return kTRUE;
308}
309
310// --------------------------------------------------------------------------
311//
312// Returns the name of the object. If the name of the object is not the
313// class name it returns the object name and in []-brackets the class name.
314// If a serial number is set (!=0) the serial number is added to the
315// name (eg. ;1)
316//
317const char *MTask::GetDescriptor() const
318{
319 //
320 // Because it returns a (const char*) we cannot return a casted
321 // local TString. The pointer would - immediatly after return -
322 // point to a random memory segment, because the TString has gone.
323 //
324 if (fName==ClassName())
325 return fSerialNumber==0 ? ClassName() : Form("%s;%d", ClassName(), fSerialNumber);
326
327 return fSerialNumber>0 ?
328 Form("%s;%d [%s]", fName.Data(), fSerialNumber, ClassName()) :
329 Form("%s [%s]", fName.Data(), ClassName());
330}
331
332// --------------------------------------------------------------------------
333//
334// Prints the number of times all the tasks in the list has been.
335// For convinience the lvl argument results in a number of spaces at the
336// beginning of the line. So that the structur of a tasklist can be
337// identified. If a Tasklist or task has filter applied the name of the
338// filter is printer in <>-brackets behind the number of executions.
339// Use MTaskList::PrintStatistics without an argument.
340//
341void MTask::PrintStatistics(const Int_t lvl, Bool_t title) const
342{
343 *fLog << all << setfill(' ') << setw(lvl) << " " << GetDescriptor() << "\t";
344 *fLog << dec << fNumExecutions;
345 if (fFilter)
346 *fLog << " <" << fFilter->GetName() << ">";
347 if (title)
348 *fLog << "\t" << fTitle;
349 *fLog << endl;
350}
351
352// --------------------------------------------------------------------------
353//
354// First call MParContainer::SavePrimitive which should stream the primitive
355// to the output stream. Then, if a filter is set, stream first the filter
356// and afterwards set the filter for this task.
357//
358void MTask::SavePrimitive(ofstream &out, Option_t *o)
359{
360 MParContainer::SavePrimitive(out);
361 if (!fFilter)
362 return;
363
364 /*
365 If we don't stream filter which are not in the task list itself
366 (which means: already streamed) we may be able to use
367 SavePrimitive as some kind of validity check for the macros
368
369 fFilter->SavePrimitive(out);
370 */
371 out << " " << GetUniqueName() << ".SetFilter(&" << fFilter->GetUniqueName() <<");" << endl;
372 if (fSerialNumber>0)
373 out << " " << GetUniqueName() << ".SetSerialNumber(" << fSerialNumber <<");" << endl;
374}
375
376// --------------------------------------------------------------------------
377//
378// Check whether the class given in the argument overwrites MTask::Process.
379// This function calls itself recursively. If you want to call it,
380// leave out the argument.
381//
382Bool_t MTask::OverwritesProcess(TClass *cls) const
383{
384 if (!cls)
385 cls = IsA();
386
387 //
388 // Check whether we reached the base class MTask
389 //
390 if (TString(cls->GetName())=="MTask")
391 return kFALSE;
392
393 //
394 // Check whether the class cls overwrites Process
395 //
396 if (cls->GetMethodAny("Process"))
397 return kTRUE;
398
399 //
400 // If the class itself doesn't overload it check all it's base classes
401 //
402 TBaseClass *base=NULL;
403 TIter NextBase(cls->GetListOfBases());
404 while ((base=(TBaseClass*)NextBase()))
405 {
406 if (OverwritesProcess(base->GetClassPointer()))
407 return kTRUE;
408 }
409
410 return kFALSE;
411}
412
413void MTask::SetDisplay(MStatusDisplay *d)
414{
415 if (fFilter)
416 fFilter->SetDisplay(d);
417 MParContainer::SetDisplay(d);
418}
Note: See TracBrowser for help on using the repository browser.