source: trunk/MagicSoft/Mars/mbase/MEvtLoop.cc@ 1483

Last change on this file since 1483 was 1483, checked in by tbretz, 22 years ago
*** empty log message ***
File size: 17.5 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@uni-sw.gwdg.de>
19!
20! Copyright: MAGIC Software Development, 2000-2001
21!
22!
23\* ======================================================================== */
24
25
26//////////////////////////////////////////////////////////////////////////////
27// //
28// MEvtLoop //
29// //
30// This class is the core of each event processing. //
31// First you must set the parameter list to use. The parameter list //
32// must contain the task list (MTaskList) to use. The name of the task //
33// list can be specified if you call Eventloop. The standard name is //
34// "MTaskList". The name you specify must match the name of the MTaskList //
35// object. //
36// //
37// If you call Eventloop first all PreProcess functions - with the //
38// parameter list as an argument - of the tasks in the task list are //
39// executed. If one of them returns kFALSE then the execution is stopped. //
40// If the preprocessing was ok. The Process funtion of the tasks are //
41// as long as one function returns kSTOP. Only the tasks which are marked //
42// marked as "All" or with a string which matches the MInputStreamID of //
43// MTaskList are executed. If one tasks returns kCONTINUE the pending //
44// tasks in the list are skipped and the execution in continued with //
45// the first one in the list. //
46// Afterwards the PostProcess functions are executed. //
47// //
48// //
49// Maybe we can add a TProgressMeter sometimes later to be able to show //
50// the progress graphically... //
51// //
52// //
53// You can create a macro from a completely setup eventloop by: //
54// evtloop.MakeMacro("mymacro.C"); //
55// //
56// You will always need to check the macro, it will not run, but it //
57// should have al important information. //
58// //
59// //
60// You can also write all this information to a root file: //
61// TFile file("myfile.root"); //
62// evtloop.Write("MyEvtloopKey"); //
63// //
64// You can afterwards read the information from an open file by: //
65// evtloop.Read("MyEvtloopKey"); //
66// //
67// To lookup the information write it to a file using MakeMacro //
68// //
69//////////////////////////////////////////////////////////////////////////////
70#include "MEvtLoop.h"
71
72#include <time.h> // time_t
73#include <fstream.h> // ofstream, SavePrimitive
74#include <iostream.h>
75
76#include <TFile.h> // gFile
77#include <TSystem.h> // gSystem
78#include <TStopwatch.h>
79#include <TGProgressBar.h>
80
81#include "MLog.h"
82#include "MLogManip.h"
83
84#include "MParList.h"
85#include "MTaskList.h"
86
87ClassImp(MEvtLoop);
88
89
90//!
91//! Maybe we can add a static parameter list to MEvtLoop
92//! Also we can derive MEvtLoop from MTaskList to have a static tasklist, too
93//!
94
95// --------------------------------------------------------------------------
96//
97// default constructor - emty
98//
99MEvtLoop::MEvtLoop() : fParList(NULL), fProgress(NULL)
100{
101}
102
103// --------------------------------------------------------------------------
104//
105// default destructor - emty
106//
107MEvtLoop::~MEvtLoop()
108{
109 if (TestBit(kIsOwner) && fParList)
110 delete fParList;
111}
112
113// --------------------------------------------------------------------------
114//
115// if you set the Eventloop as owner the destructor of the given parameter
116// list is calles by the destructor of MEvtLoop, otherwise not.
117//
118void MEvtLoop::SetOwner(Bool_t enable)
119{
120 enable ? SetBit(kIsOwner) : ResetBit(kIsOwner);
121}
122
123// --------------------------------------------------------------------------
124//
125// The proprocessing part of the eventloop. Be careful, this is
126// for developers or use in special jobs only!
127//
128Bool_t MEvtLoop::PreProcess(const char *tlist)
129{
130 //
131 // check if the needed parameter list is set.
132 //
133 if (!fParList)
134 {
135 *fLog << err << dbginf << "Parlist not initialized." << endl;
136 return kFALSE;
137 }
138
139 //
140 // check for the existance of the specified task list
141 // the default name is "MTaskList"
142 //
143 fTaskList = (MTaskList*)fParList->FindObject(tlist, "MTaskList");
144 if (!fTaskList)
145 {
146 *fLog << err << dbginf << "Cannot find tasklist '" << tlist << "' in parameter list." << endl;
147 return kFALSE;
148 }
149
150 if (fLog != &gLog)
151 fParList->SetLogStream(fLog);
152
153 //
154 // execute the preprocess of all tasks
155 // connect the different tasks with the right containers in
156 // the parameter list
157 //
158 if (!fTaskList->PreProcess(fParList))
159 {
160 *fLog << err << "Error detected while PreProcessing" << endl;
161 return kFALSE;
162 }
163
164 *fLog << endl;
165
166 return kTRUE;
167}
168
169// --------------------------------------------------------------------------
170//
171// The processing part of the eventloop. Be careful, this is
172// for developers or use in special jobs only!
173//
174void MEvtLoop::Process(Int_t maxcnt) const
175{
176 //
177 // loop over all events and process all tasks for
178 // each event
179 //
180 *fLog << all <<"Eventloop running (";
181
182 if (maxcnt<0)
183 *fLog << "all";
184 else
185 *fLog << dec << maxcnt;
186
187 *fLog << " events)..." << flush;
188
189 if (fProgress && maxcnt>0)
190 fProgress->SetRange(0, maxcnt);
191
192 Int_t dummy = maxcnt<0 ? 0 : maxcnt;
193
194 //
195 // start a stopwatch
196 //
197 TStopwatch clock;
198 clock.Start();
199
200 //
201 // This is the MAIN EVENTLOOP which processes the data
202 // if maxcnt<0 the number of processed events is counted
203 // else only maxcnt events are processed
204 //
205 if (maxcnt<0)
206 // process first and increment if sucessfull
207 if (fProgress)
208 while (fTaskList->Process())
209 {
210 fProgress->SetPosition(++dummy);
211#if ROOT_VERSION_CODE < ROOT_VERSION(3,02,06)
212 gSystem->ProcessEvents();
213#else
214 gClient->ProcessEventsFor(fProgress);
215#endif
216 }
217 else
218 while (fTaskList->Process()) dummy++;
219 else
220 // check for number and break if unsuccessfull
221 if (fProgress)
222 while (dummy-- && fTaskList->Process())
223 {
224 fProgress->SetPosition(maxcnt - dummy);
225#if ROOT_VERSION_CODE < ROOT_VERSION(3,02,06)
226 gSystem->ProcessEvents();
227#else
228 gClient->ProcessEventsFor(fProgress);
229#endif
230 }
231 else
232 while (dummy-- && fTaskList->Process());
233
234 //
235 // stop stop-watch, print results
236 //
237 clock.Stop();
238
239 *fLog << all << "Ready!" << endl << endl;
240
241 *fLog << dec << endl << "CPU - "
242 << "Time: " << clock.CpuTime() << "s"
243 << " for " << (maxcnt<0?dummy:maxcnt) << " Events"
244 << " --> " << (maxcnt<0?dummy:maxcnt)/clock.CpuTime() << " Events/s"
245 << endl;
246 *fLog << "Real - "
247 << "Time: " << clock.RealTime() << "s"
248 << " for " << (maxcnt<0?dummy:maxcnt) << " Events"
249 << " --> " << (maxcnt<0?dummy:maxcnt)/clock.RealTime() << " Events/s"
250 << endl << endl;
251}
252
253// --------------------------------------------------------------------------
254//
255// The postprocessing part of the eventloop. Be careful, this is
256// for developers or use in special jobs only!
257//
258Bool_t MEvtLoop::PostProcess() const
259{
260 //
261 // execute the post process of all tasks
262 //
263 return fTaskList->PostProcess();
264}
265
266// --------------------------------------------------------------------------
267//
268// See class description above.
269//
270Bool_t MEvtLoop::Eventloop(Int_t maxcnt, const char *tlist)
271{
272 Bool_t rc = PreProcess();
273
274 //
275 // If all Tasks were PreProcesses successfully start Processing.
276 //
277 if (rc)
278 Process(maxcnt);
279
280 //
281 // Now postprocess all tasks. Only successfully preprocessed tasks are
282 // postprocessed. If the Postprocessing of one task fail return an error.
283 //
284 if (!PostProcess())
285 return kFALSE;
286
287 //
288 // If postprocessing of all preprocessed tasks was sucefully return rc.
289 // This gives an error in case the preprocessing has failed already.
290 // Otherwise the eventloop is considered: successfully.
291 //
292 return rc;
293}
294
295// --------------------------------------------------------------------------
296//
297// After you setup (or read) an Evtloop you can use this to write the
298// eventloop setup as a macro. The default name is "evtloop.C". The default
299// extension is .C If the extension is not given, .C is added.
300//
301void MEvtLoop::MakeMacro(const char *filename)
302{
303 TString name(filename);
304
305 if (!name.EndsWith(".C"))
306 name += ".C";
307
308 time_t t = time(NULL);
309
310 ofstream fout(name);
311 fout <<
312 "/* ======================================================================== *\\" << endl <<
313 "!" << endl <<
314 "! *" << endl <<
315 "! * This file is part of MARS, the MAGIC Analysis and Reconstruction" << endl <<
316 "! * Software. It is distributed to you in the hope that it can be a useful" << endl <<
317 "! * and timesaving tool in analysing Data of imaging Cerenkov telescopes." << endl <<
318 "! * It is distributed WITHOUT ANY WARRANTY." << endl <<
319 "! *" << endl <<
320 "! * Permission to use, copy, modify and distribute this software and its" << endl <<
321 "! * documentation for any purpose is hereby granted without fee," << endl <<
322 "! * provided that the above copyright notice appear in all copies and" << endl <<
323 "! * that both that copyright notice and this permission notice appear" << endl <<
324 "! * in supporting documentation. It is provided \"as is\" without express" << endl <<
325 "! * or implied warranty." << endl <<
326 "! *" << endl <<
327 "!" << endl <<
328 "!" << endl <<
329 "! Author(s): Thomas Bretz et al. <mailto:tbretz@astro.uni-wuerzburg.de>" << endl <<
330 "!" << endl <<
331 "! Copyright: MAGIC Software Development, 2000-2002" << endl <<
332 "!" << endl <<
333 "!" << endl <<
334 "\\* ======================================================================== */" << endl << endl <<
335 "// ------------------------------------------------------------------------" << endl <<
336 "//" << endl <<
337 "// This macro was automatically created on" << endl<<
338 "// " << ctime(&t) <<
339 "// with the MEvtLoop::MakeMacro tool." << endl <<
340 "//" << endl <<
341 "// ------------------------------------------------------------------------" << endl << endl <<
342 "void " << name(0, name.Length()-2) << "()" << endl <<
343 "{" << endl;
344
345 SavePrimitive(fout);
346
347 fout << "}" << endl;
348}
349
350// --------------------------------------------------------------------------
351//
352// Implementation of SavePrimitive. Used to write the call to a constructor
353// to a macro. In the original root implementation it is used to write
354// gui elements to a macro-file.
355//
356void MEvtLoop::SavePrimitive(ofstream &out, Option_t *)
357{
358 if (HasDuplicateNames("MEvtLoop::SavePrimitive"))
359 {
360 out << " // !" << endl;
361 out << " // ! WARNING - Your eventloop (MParList, MTaskList, ...) contains more than" << endl;
362 out << " // ! one object (MParContainer, MTask, ...) with the same name. The created macro" << endl;
363 out << " // ! may need manual intervention before it can be used." << endl;
364 out << " // !" << endl;
365 out << endl;
366 }
367
368 if (fParList)
369 fParList->SavePrimitive(out);
370
371 out << " MEvtLoop evtloop;" << endl;
372 if (fParList)
373 out << " evtloop.SetParList(&" << fParList->GetUniqueName() << ");" << endl;
374 else
375 out << " // fParList empty..." << endl;
376 out << " if (!evtloop.Eventloop())" << endl;
377 out << " return;" << endl;
378}
379
380// --------------------------------------------------------------------------
381//
382// Get a list of all conmtainer names which are somehow part of the
383// eventloop. Chack for duplicate members and print a warning if
384// duplicates are found. Return kTRUE if duplicates are found, otherwise
385// kFALSE;
386//
387Bool_t MEvtLoop::HasDuplicateNames(TObjArray &arr, const TString txt) const
388{
389 arr.Sort();
390
391 TIter Next(&arr);
392 TObject *obj;
393 TString name;
394 Bool_t found = kFALSE;
395 while ((obj=Next()))
396 {
397 if (name==obj->GetName())
398 {
399 if (!found)
400 {
401 *fLog << warn << endl;
402 *fLog << " ! WARNING (" << txt << ")" << endl;
403 *fLog << " ! Your eventloop (MParList, MTaskList, ...) contains more than" << endl;
404 *fLog << " ! one object (MParContainer, MTask, ...) with the same name." << endl;
405 *fLog << " ! Creating a macro from it using MEvtLoop::MakeMacro may create" << endl;
406 *fLog << " ! a macro which needs manual intervention before it can be used." << endl;
407 found = kTRUE;
408 }
409 *fLog << " ! Please rename: " << obj->GetName() << endl;
410 }
411 name = obj->GetName();
412 }
413
414 return found;
415}
416
417// --------------------------------------------------------------------------
418//
419// Get a list of all conmtainer names which are somehow part of the
420// eventloop. Chack for duplicate members and print a warning if
421// duplicates are found. Return kTRUE if duplicates are found, otherwise
422// kFALSE;
423//
424Bool_t MEvtLoop::HasDuplicateNames(const TString txt) const
425{
426 if (!fParList)
427 return kFALSE;
428
429 TObjArray list;
430 list.SetOwner();
431
432 fParList->GetNames(list);
433
434 return HasDuplicateNames(list, txt);
435}
436
437// --------------------------------------------------------------------------
438//
439// Reads a saved eventloop from a file. The default name is "Evtloop".
440// Therefor an open file must exist (See TFile for more information)
441//
442// eg:
443// TFile file("myfile.root", "READ");
444// MEvtLoop evtloop;
445// evtloop.Read();
446// evtloop.MakeMacro("mymacro");
447//
448Int_t MEvtLoop::Read(const char *name)
449{
450 if (!gFile)
451 {
452 *fLog << err << "MEvtloop::Read: No file found. Please create a TFile first." << endl;
453 return 0;
454 }
455
456 if (!gFile->IsOpen())
457 {
458 *fLog << err << "MEvtloop::Read: File not open. Please open the TFile first." << endl;
459 return 0;
460 }
461
462 Int_t n = 0;
463 TObjArray list;
464
465 n += TObject::Read(name);
466
467 if (n==0)
468 {
469 *fLog << err << "MEvtloop::Read: No objects read." << endl;
470 return 0;
471 }
472
473 n += list.Read((TString)name+"_names");
474
475 fParList->SetNames(list);
476
477 HasDuplicateNames(list, "MEvtLoop::Read");
478
479 return n;
480}
481
482// --------------------------------------------------------------------------
483//
484// Writes a eventloop to a file. The default name is "Evtloop".
485// Therefor an open file must exist (See TFile for more information)
486//
487// eg:
488// TFile file("myfile.root", "RECREATE");
489// MEvtLoop evtloop;
490// evtloop.Write();
491// file.Close();
492//
493Int_t MEvtLoop::Write(const char *name, Int_t option, Int_t bufsize)
494{
495 if (!gFile)
496 {
497 *fLog << err << "MEvtloop::Write: No file found. Please create a TFile first." << endl;
498 return 0;
499 }
500
501 if (!gFile->IsOpen())
502 {
503 *fLog << err << "MEvtloop::Write: File not open. Please open the TFile first." << endl;
504 return 0;
505 }
506
507 if (!gFile->IsWritable())
508 {
509 *fLog << err << "MEvtloop::Write: File not writable." << endl;
510 return 0;
511 }
512
513 Int_t n = 0;
514
515 TObjArray list;
516 list.SetOwner();
517
518 fParList->GetNames(list);
519
520 n += TObject::Write(name, option, bufsize);
521
522 if (n==0)
523 {
524 *fLog << err << "MEvtloop::Read: No objects written." << endl;
525 return 0;
526 }
527
528 n += list.Write((TString)name+"_names", kSingleKey);
529
530 HasDuplicateNames(list, "MEvtLoop::Write");
531
532 return n;
533}
Note: See TracBrowser for help on using the repository browser.