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

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