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

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