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

Last change on this file since 1525 was 1525, checked in by tbretz, 22 years ago
*** empty log message ***
File size: 20.2 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
95TList *gListOfPrimitives; // forard declaration in MParContainer.h
96
97// --------------------------------------------------------------------------
98//
99// default constructor - emty
100//
101MEvtLoop::MEvtLoop() : fParList(NULL), fProgress(NULL)
102{
103 fName = "Evtloop";
104}
105
106// --------------------------------------------------------------------------
107//
108// default destructor - emty
109//
110MEvtLoop::~MEvtLoop()
111{
112 if (TestBit(kIsOwner) && fParList)
113 delete fParList;
114}
115
116// --------------------------------------------------------------------------
117//
118// if you set the Eventloop as owner the destructor of the given parameter
119// list is calles by the destructor of MEvtLoop, otherwise not.
120//
121void MEvtLoop::SetOwner(Bool_t enable)
122{
123 enable ? SetBit(kIsOwner) : ResetBit(kIsOwner);
124}
125
126// --------------------------------------------------------------------------
127//
128// The proprocessing part of the eventloop. Be careful, this is
129// for developers or use in special jobs only!
130//
131Bool_t MEvtLoop::PreProcess(const char *tlist)
132{
133 //
134 // check if the needed parameter list is set.
135 //
136 if (!fParList)
137 {
138 *fLog << err << dbginf << "Parlist not initialized." << endl;
139 return kFALSE;
140 }
141
142 //
143 // check for the existance of the specified task list
144 // the default name is "MTaskList"
145 //
146 fTaskList = (MTaskList*)fParList->FindObject(tlist, "MTaskList");
147 if (!fTaskList)
148 {
149 *fLog << err << dbginf << "Cannot find tasklist '" << tlist << "' in parameter list." << endl;
150 return kFALSE;
151 }
152
153 if (fLog != &gLog)
154 fParList->SetLogStream(fLog);
155
156 //
157 // execute the preprocess of all tasks
158 // connect the different tasks with the right containers in
159 // the parameter list
160 //
161 if (!fTaskList->PreProcess(fParList))
162 {
163 *fLog << err << "Error detected while PreProcessing" << endl;
164 return kFALSE;
165 }
166
167 *fLog << endl;
168
169 return kTRUE;
170}
171
172// --------------------------------------------------------------------------
173//
174// The processing part of the eventloop. Be careful, this is
175// for developers or use in special jobs only!
176//
177void MEvtLoop::Process(Int_t maxcnt) const
178{
179 //
180 // loop over all events and process all tasks for
181 // each event
182 //
183 *fLog << all <<"Eventloop running (";
184
185 if (maxcnt<0)
186 *fLog << "all";
187 else
188 *fLog << dec << maxcnt;
189
190 *fLog << " events)..." << flush;
191
192 if (fProgress && maxcnt>0)
193 fProgress->SetRange(0, maxcnt);
194
195 Int_t dummy = maxcnt<0 ? 0 : maxcnt;
196
197 //
198 // start a stopwatch
199 //
200 TStopwatch clock;
201 clock.Start();
202
203 //
204 // This is the MAIN EVENTLOOP which processes the data
205 // if maxcnt<0 the number of processed events is counted
206 // else only maxcnt events are processed
207 //
208 if (maxcnt<0)
209 // process first and increment if sucessfull
210 if (fProgress)
211 while (fTaskList->Process())
212 {
213 fProgress->SetPosition(++dummy);
214#if ROOT_VERSION_CODE < ROOT_VERSION(3,02,06)
215 gSystem->ProcessEvents();
216#else
217 gClient->ProcessEventsFor(fProgress);
218#endif
219 }
220 else
221 while (fTaskList->Process()) dummy++;
222 else
223 // check for number and break if unsuccessfull
224 if (fProgress)
225 while (dummy-- && fTaskList->Process())
226 {
227 fProgress->SetPosition(maxcnt - dummy);
228#if ROOT_VERSION_CODE < ROOT_VERSION(3,02,06)
229 gSystem->ProcessEvents();
230#else
231 gClient->ProcessEventsFor(fProgress);
232#endif
233 }
234 else
235 while (dummy-- && fTaskList->Process());
236
237 //
238 // stop stop-watch, print results
239 //
240 clock.Stop();
241
242 *fLog << all << "Ready!" << endl << endl;
243
244 *fLog << dec << endl << "CPU - "
245 << "Time: " << clock.CpuTime() << "s"
246 << " for " << (maxcnt<0?dummy:maxcnt) << " Events"
247 << " --> " << (maxcnt<0?dummy:maxcnt)/clock.CpuTime() << " Events/s"
248 << endl;
249 *fLog << "Real - "
250 << "Time: " << clock.RealTime() << "s"
251 << " for " << (maxcnt<0?dummy:maxcnt) << " Events"
252 << " --> " << (maxcnt<0?dummy:maxcnt)/clock.RealTime() << " Events/s"
253 << endl << endl;
254}
255
256// --------------------------------------------------------------------------
257//
258// The postprocessing part of the eventloop. Be careful, this is
259// for developers or use in special jobs only!
260//
261Bool_t MEvtLoop::PostProcess() const
262{
263 //
264 // execute the post process of all tasks
265 //
266 return fTaskList->PostProcess();
267}
268
269// --------------------------------------------------------------------------
270//
271// See class description above.
272//
273Bool_t MEvtLoop::Eventloop(Int_t maxcnt, const char *tlist)
274{
275 Bool_t rc = PreProcess();
276
277 //
278 // If all Tasks were PreProcesses successfully start Processing.
279 //
280 if (rc)
281 Process(maxcnt);
282
283 //
284 // Now postprocess all tasks. Only successfully preprocessed tasks are
285 // postprocessed. If the Postprocessing of one task fail return an error.
286 //
287 if (!PostProcess())
288 return kFALSE;
289
290 //
291 // If postprocessing of all preprocessed tasks was sucefully return rc.
292 // This gives an error in case the preprocessing has failed already.
293 // Otherwise the eventloop is considered: successfully.
294 //
295 return rc;
296}
297
298// --------------------------------------------------------------------------
299//
300// After you setup (or read) an Evtloop you can use this to write the
301// eventloop setup as a macro. The default name is "evtloop.C". The default
302// extension is .C If the extension is not given, .C is added.
303// I the last character in the argument is a '+' the file is not closed.
304// This is usefull if you have an eventloop which runs three times and
305// you want to write one macro. If the first character is a '+' no
306// opening is written, eg:
307//
308// MEvtLoop evtloop;
309// // some setup
310// evtloop.MakeMacro("mymacro+");
311// // replace the tasklist the first time
312// evtloop.MakeMacro("+mymacro+");
313// // replace the tasklist the second time
314// evtloop.MakeMacro("+mymacro");
315//
316void MEvtLoop::MakeMacro(const char *filename)
317{
318 TString name(filename);
319
320 name = name.Strip(TString::kBoth);
321
322 Bool_t open = kTRUE;
323 Bool_t close = kTRUE;
324 if (name[0]=='+')
325 {
326 open = kFALSE;
327 name.Remove(0, 1);
328 name = name.Strip(TString::kBoth);
329 }
330
331 if (name[name.Length()-1]=='+')
332 {
333 close = kFALSE;
334 name.Remove(name.Length()-1, 1);
335 name = name.Strip(TString::kBoth);
336 }
337
338 if (!name.EndsWith(".C"))
339 name += ".C";
340
341 ofstream fout;
342
343 if (!open)
344 {
345 fout.open(name, ios::app);
346 fout << endl;
347 fout << " // ----------------------------------------------------------------------" << endl;
348 fout << endl;
349 }
350 else
351 {
352 fout.open(name);
353
354 time_t t = time(NULL);
355 fout <<
356 "/* ======================================================================== *\\" << endl <<
357 "!" << endl <<
358 "! *" << endl <<
359 "! * This file is part of MARS, the MAGIC Analysis and Reconstruction" << endl <<
360 "! * Software. It is distributed to you in the hope that it can be a useful" << endl <<
361 "! * and timesaving tool in analysing Data of imaging Cerenkov telescopes." << endl <<
362 "! * It is distributed WITHOUT ANY WARRANTY." << endl <<
363 "! *" << endl <<
364 "! * Permission to use, copy, modify and distribute this software and its" << endl <<
365 "! * documentation for any purpose is hereby granted without fee," << endl <<
366 "! * provided that the above copyright notice appear in all copies and" << endl <<
367 "! * that both that copyright notice and this permission notice appear" << endl <<
368 "! * in supporting documentation. It is provided \"as is\" without express" << endl <<
369 "! * or implied warranty." << endl <<
370 "! *" << endl <<
371 "!" << endl <<
372 "!" << endl <<
373 "! Author(s): Thomas Bretz et al. <mailto:tbretz@astro.uni-wuerzburg.de>" << endl <<
374 "!" << endl <<
375 "! Copyright: MAGIC Software Development, 2000-2002" << endl <<
376 "!" << endl <<
377 "!" << endl <<
378 "\\* ======================================================================== */" << endl << endl <<
379 "// ------------------------------------------------------------------------" << endl <<
380 "//" << endl <<
381 "// This macro was automatically created on" << endl<<
382 "// " << ctime(&t) <<
383 "// with the MEvtLoop::MakeMacro tool." << endl <<
384 "//" << endl <<
385 "// ------------------------------------------------------------------------" << endl << endl <<
386 "void " << name(0, name.Length()-2) << "()" << endl <<
387 "{" << endl;
388 }
389
390 SavePrimitive(fout, (TString)"" + (open?"open":"") + (close?"close":""));
391
392 if (!close)
393 return;
394
395 fout << "}" << endl;
396
397 *fLog << inf << "Macro '" << name << "' written." << endl;
398}
399
400// --------------------------------------------------------------------------
401//
402// Implementation of SavePrimitive. Used to write the call to a constructor
403// to a macro. In the original root implementation it is used to write
404// gui elements to a macro-file.
405//
406
407void MEvtLoop::StreamPrimitive(ofstream &out) const
408{
409 out << " MEvtLoop " << GetUniqueName() << ";" << endl;
410}
411
412void MEvtLoop::SavePrimitive(ofstream &out, Option_t *opt)
413{
414 TString options = opt;
415 options.ToLower();
416
417 if (HasDuplicateNames("MEvtLoop::SavePrimitive"))
418 {
419 out << " // !" << endl;
420 out << " // ! WARNING - Your eventloop (MParList, MTaskList, ...) contains more than" << endl;
421 out << " // ! one object (MParContainer, MTask, ...) with the same name. The created macro" << endl;
422 out << " // ! may need manual intervention before it can be used." << endl;
423 out << " // !" << endl;
424 out << endl;
425 }
426
427 if (!options.Contains("open"))
428 {
429 if (gListOfPrimitives)
430 {
431 *fLog << err << "MEvtLoop::SavePrimitive - Error: old file not closed." << endl;
432 gListOfPrimitives->ForEach(TObject, ResetBit)(BIT(15));
433 delete gListOfPrimitives;
434 }
435 gListOfPrimitives = new TList;
436 }
437
438 if (fParList)
439 fParList->SavePrimitive(out);
440
441 MParContainer::SavePrimitive(out);
442
443 if (fParList)
444 out << " " << GetUniqueName() << ".SetParList(&" << fParList->GetUniqueName() << ");" << endl;
445 else
446 out << " // fParList empty..." << endl;
447 out << " if (!" << GetUniqueName() << ".Eventloop())" << endl;
448 out << " return;" << endl;
449
450 if (!options.Contains("close"))
451 return;
452
453 gListOfPrimitives->ForEach(TObject, ResetBit)(BIT(15));
454 delete gListOfPrimitives;
455 gListOfPrimitives = 0;
456}
457
458// --------------------------------------------------------------------------
459//
460// Get a list of all conmtainer names which are somehow part of the
461// eventloop. Chack for duplicate members and print a warning if
462// duplicates are found. Return kTRUE if duplicates are found, otherwise
463// kFALSE;
464//
465Bool_t MEvtLoop::HasDuplicateNames(TObjArray &arr, const TString txt) const
466{
467 arr.Sort();
468
469 TIter Next(&arr);
470 TObject *obj;
471 TString name;
472 Bool_t found = kFALSE;
473 while ((obj=Next()))
474 {
475 if (name==obj->GetName())
476 {
477 if (!found)
478 {
479 *fLog << warn << endl;
480 *fLog << " ! WARNING (" << txt << ")" << endl;
481 *fLog << " ! Your eventloop (MParList, MTaskList, ...) contains more than" << endl;
482 *fLog << " ! one object (MParContainer, MTask, ...) with the same name." << endl;
483 *fLog << " ! Creating a macro from it using MEvtLoop::MakeMacro may create" << endl;
484 *fLog << " ! a macro which needs manual intervention before it can be used." << endl;
485 found = kTRUE;
486 }
487 *fLog << " ! Please rename: " << obj->GetName() << endl;
488 }
489 name = obj->GetName();
490 }
491
492 return found;
493}
494
495// --------------------------------------------------------------------------
496//
497// Get a list of all conmtainer names which are somehow part of the
498// eventloop. Chack for duplicate members and print a warning if
499// duplicates are found. Return kTRUE if duplicates are found, otherwise
500// kFALSE;
501//
502Bool_t MEvtLoop::HasDuplicateNames(const TString txt) const
503{
504 if (!fParList)
505 return kFALSE;
506
507 TObjArray list;
508 list.SetOwner();
509
510 fParList->GetNames(list);
511
512 return HasDuplicateNames(list, txt);
513}
514
515// --------------------------------------------------------------------------
516//
517// Reads a saved eventloop from a file. The default name is "Evtloop".
518// Therefor an open file must exist (See TFile for more information)
519//
520// eg:
521// TFile file("myfile.root", "READ");
522// MEvtLoop evtloop;
523// evtloop.Read();
524// evtloop.MakeMacro("mymacro");
525//
526Int_t MEvtLoop::Read(const char *name)
527{
528 if (!gFile)
529 {
530 *fLog << err << "MEvtloop::Read: No file found. Please create a TFile first." << endl;
531 return 0;
532 }
533
534 if (!gFile->IsOpen())
535 {
536 *fLog << err << "MEvtloop::Read: File not open. Please open the TFile first." << endl;
537 return 0;
538 }
539
540 Int_t n = 0;
541 TObjArray list;
542
543 n += TObject::Read(name);
544
545 if (n==0)
546 {
547 *fLog << err << "MEvtloop::Read: No objects read." << endl;
548 return 0;
549 }
550
551 n += list.Read((TString)name+"_names");
552
553 fParList->SetNames(list);
554
555 HasDuplicateNames(list, "MEvtLoop::Read");
556
557 *fLog << inf << "Eventloop '" << name << "' read from file." << endl;
558
559 return n;
560}
561
562// --------------------------------------------------------------------------
563//
564// If available print the contents of the parameter list.
565//
566void MEvtLoop::Print(Option_t *opt) const
567{
568 if (fParList)
569 fParList->Print();
570 else
571 *fLog << all << "MEvtloop: No Parameter List available." << endl;
572}
573
574// --------------------------------------------------------------------------
575//
576// Writes a eventloop to a file. The default name is "Evtloop".
577// Therefor an open file must exist (See TFile for more information)
578//
579// eg:
580// TFile file("myfile.root", "RECREATE");
581// MEvtLoop evtloop;
582// evtloop.Write();
583// file.Close();
584//
585Int_t MEvtLoop::Write(const char *name, Int_t option, Int_t bufsize)
586{
587 if (!gFile)
588 {
589 *fLog << err << "MEvtloop::Write: No file found. Please create a TFile first." << endl;
590 return 0;
591 }
592
593 if (!gFile->IsOpen())
594 {
595 *fLog << err << "MEvtloop::Write: File not open. Please open the TFile first." << endl;
596 return 0;
597 }
598
599 if (!gFile->IsWritable())
600 {
601 *fLog << err << "MEvtloop::Write: File not writable." << endl;
602 return 0;
603 }
604
605 Int_t n = 0;
606
607 TObjArray list;
608 list.SetOwner();
609
610 fParList->GetNames(list);
611
612 n += TObject::Write(name, option, bufsize);
613
614 if (n==0)
615 {
616 *fLog << err << "MEvtloop::Read: No objects written." << endl;
617 return 0;
618 }
619
620 n += list.Write((TString)name+"_names", kSingleKey);
621
622 HasDuplicateNames(list, "MEvtLoop::Write");
623
624 *fLog << inf << "Eventloop written to file as " << name << "." << endl;
625
626 return n;
627}
Note: See TracBrowser for help on using the repository browser.