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

Last change on this file since 6084 was 5911, checked in by tbretz, 20 years ago
*** empty log message ***
File size: 31.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@astro.uni-wuerzburg.de>
19!
20! Copyright: MAGIC Software Development, 2000-2003
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 function of the tasks are
41// executed as long as one function returns kSTOP. Only the tasks which
42// are marked as "All" or with a string which matches the MInputStreamID
43// of 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// If you want to display the progress in a gui you can use SetProgressBar
49// and a TGProgressBar or a MProgressBar. If you set a MStatusDisplay
50// using SetDisplay, the Progress bar from this display is used.
51//
52// You can create a macro from a completely setup eventloop by:
53// evtloop.MakeMacro("mymacro.C");
54//
55// You will always need to check the macro, it will not run, but it
56// should have al important information.
57//
58//
59// You can also write all this information to a root file:
60// TFile file("myfile.root");
61// evtloop.Write("MyEvtloopKey");
62//
63// You can afterwards read the information from an open file by:
64// evtloop.Read("MyEvtloopKey");
65//
66// To lookup the information write it to a file using MakeMacro
67//
68//////////////////////////////////////////////////////////////////////////////
69#include "MEvtLoop.h"
70
71#include <time.h> // time_t
72#include <fstream> // ofstream, SavePrimitive
73
74#include <TEnv.h> // TEnv
75#include <TRint.h> // gApplication, TRint::Class()
76#include <TTime.h> // TTime
77#include <TFile.h> // gFile
78#include <TThread.h> // TThread::Self()
79#include <TDatime.h> // TDatime
80#include <TSystem.h> // gSystem
81#include <TStopwatch.h>
82#include <TGProgressBar.h>
83
84#include "MLog.h"
85#include "MLogManip.h"
86
87#include "MParList.h"
88#include "MTaskList.h"
89#ifdef __MARS__
90#include "MRead.h" // for setting progress bar
91#include "MProgressBar.h" // MProgressBar::GetBar
92#include "MStatusDisplay.h" // MStatusDisplay::GetBar
93#endif
94
95ClassImp(MEvtLoop);
96
97using namespace std;
98
99// --------------------------------------------------------------------------
100//
101// default constructor
102//
103MEvtLoop::MEvtLoop(const char *name) : fParList(NULL), fProgress(NULL)
104{
105 fName = name;
106
107 gROOT->GetListOfCleanups()->Add(this); // To remove fDisplay
108 SetBit(kMustCleanup);
109
110 *fLog << inf << underline << "Instantiated MEvtLoop (" << name << "), using ROOT v" << ROOTVER << endl;
111}
112
113// --------------------------------------------------------------------------
114//
115// destructor
116//
117MEvtLoop::~MEvtLoop()
118{
119 if (TestBit(kIsOwner) && fParList)
120 delete fParList;
121}
122
123void MEvtLoop::SetParList(MParList *p)
124{
125 if (!p)
126 return;
127
128 p->SetBit(kMustCleanup);
129 fParList = p;
130}
131
132// --------------------------------------------------------------------------
133//
134// If the evntloop knows its tasklist search for the task there,
135// otherwise return NULL.
136//
137MTask *MEvtLoop::FindTask(const char *name) const
138{
139 return fTaskList ? fTaskList->FindTask(name) : NULL;
140}
141
142// --------------------------------------------------------------------------
143//
144// If the evntloop knows its tasklist search for the task there,
145// otherwise return NULL.
146//
147MTask *MEvtLoop::FindTask(const MTask *obj) const
148{
149 return fTaskList ? fTaskList->FindTask(obj) : NULL;
150}
151
152// --------------------------------------------------------------------------
153//
154// if you set the Eventloop as owner the destructor of the given parameter
155// list is calles by the destructor of MEvtLoop, otherwise not.
156//
157void MEvtLoop::SetOwner(Bool_t enable)
158{
159 enable ? SetBit(kIsOwner) : ResetBit(kIsOwner);
160}
161
162void MEvtLoop::SetProgressBar(TGProgressBar *bar)
163{
164 fProgress = bar;
165 if (fProgress)
166 fProgress->SetBit(kMustCleanup);
167}
168
169#ifdef __MARS__
170// --------------------------------------------------------------------------
171//
172// Specify an existing MProgressBar object. It will display the progress
173// graphically. This will make thing about 1-2% slower.
174//
175void MEvtLoop::SetProgressBar(MProgressBar *bar)
176{
177 SetProgressBar(bar->GetBar());
178}
179#endif
180
181void MEvtLoop::SetDisplay(MStatusDisplay *d)
182{
183 MParContainer::SetDisplay(d);
184 if (!d)
185 fProgress=NULL;
186 else
187 {
188 d->SetBit(kMustCleanup);
189
190 // Get pointer to update Progress bar
191 fProgress = fDisplay->GetBar();
192 }
193
194 if (fParList)
195 fParList->SetDisplay(d);
196}
197
198// --------------------------------------------------------------------------
199//
200// The proprocessing part of the eventloop. Be careful, this is
201// for developers or use in special jobs only!
202//
203Bool_t MEvtLoop::PreProcess(const char *tlist)
204{
205 fTaskList = NULL;
206
207 //
208 // check if the needed parameter list is set.
209 //
210 if (!fParList)
211 {
212 *fLog << err << dbginf << "Parlist not initialized." << endl;
213 return kFALSE;
214 }
215
216 //
217 // check for the existance of the specified task list
218 // the default name is "MTaskList"
219 //
220 fTaskList = (MTaskList*)fParList->FindObject(tlist, "MTaskList");
221 if (!fTaskList)
222 {
223 *fLog << err << dbginf << "Cannot find tasklist '" << tlist << "' in parameter list." << endl;
224 return kFALSE;
225 }
226
227 if (fLog != &gLog)
228 fParList->SetLogStream(fLog);
229
230#ifdef __MARS__
231 //
232 // Check whether display is still existing
233 //
234 if (fDisplay)
235 {
236 // Lock display to prevent user from deleting it
237 fDisplay->Lock();
238 // Don't display context menus
239 fDisplay->SetNoContextMenu();
240 // Set window and icon name
241 fDisplay->SetWindowName(TString("Status Display: ")+fName);
242 fDisplay->SetIconName(fName);
243 // Start automatic update
244 fDisplay->StartUpdate();
245 // Cascade display through childs
246 if (!TestBit(kPrivateDisplay))
247 fParList->SetDisplay(fDisplay);
248 }
249#endif
250
251 //
252 // execute the preprocess of all tasks
253 // connect the different tasks with the right containers in
254 // the parameter list
255 //
256 if (!fTaskList->PreProcess(fParList))
257 {
258 *fLog << err << "Error detected while PreProcessing." << endl;
259 return kFALSE;
260 }
261
262 *fLog << endl;
263
264 return kTRUE;
265}
266
267Bool_t MEvtLoop::ProcessGuiEvents(Int_t num)
268{
269 if (gROOT->IsBatch())
270 return kTRUE;
271
272 //
273 // Check status of display
274 //
275 Bool_t rc = kTRUE;
276
277 if (fDisplay)
278 switch (fDisplay->CheckStatus())
279 {
280 case MStatusDisplay::kLoopNone:
281 break;
282 case MStatusDisplay::kLoopStop:
283 rc = kFALSE;
284 fDisplay->ClearStatus();
285 break;
286 //
287 // If the display is not on the heap (means: not created
288 // with the new operator) the object is deleted somewhere
289 // else in the code. It is the responsibility of the
290 // application which instantiated the object to make
291 // sure that the correct action is taken. This can be
292 // done by calling MStatusDisplay::CheckStatus()
293 //
294 // Because we are synchronous we can safely delete it here!
295 //
296 // Close means: Close the display but leave analysis running
297 // Exit means: Close the display and stop analysis
298 //
299 case MStatusDisplay::kFileClose:
300 case MStatusDisplay::kFileExit:
301 rc = fDisplay->CheckStatus() == MStatusDisplay::kFileClose;
302
303 if (fDisplay->IsOnHeap())
304 delete fDisplay;
305
306 //
307 // This makes the display really disappear physically on
308 // the screen in case of MStatusDisplay::kFileClose
309 //
310 gSystem->ProcessEvents();
311
312 return rc;
313 default:
314 *fLog << warn << "MEvtloop: fDisplay->CheckStatus() has returned unknown status #" << fDisplay->CheckStatus() << "... cleared." << endl;
315 fDisplay->ClearStatus();
316 break;
317 }
318
319 //
320 // Check System time (don't loose too much time by updating the GUI)
321 //
322
323 // FIXME: Not thread safe (if you have more than one eventloop running)
324 static Int_t start = num;
325 static TTime t1 = gSystem->Now();
326 static TTime t2 = t1;
327
328 //
329 // No update < 20ms
330 //
331 const TTime t0 = gSystem->Now();
332 if (t0-t1 < (TTime)20)
333 return rc;
334 t1 = t0;
335
336 //
337 // Update current speed each 1.5 second
338 //
339 if (fDisplay && t0-t2>(TTime)1500)
340 {
341 const Float_t speed = 1000.*(num-start)/(long int)(t0-t2);
342 TString txt = "Processing...";
343 if (speed>0)
344 {
345 txt += " (";
346 txt += (Int_t)speed;
347 txt += "Evts/s";
348 if (fNumEvents>0)
349 {
350 txt += ", est: ";
351 txt += (int)((fNumEvents-num)/speed/60)+1;
352 txt += "min";
353 }
354 //txt += (int)fmod(entries/(1000.*(num-start)/(long int)(t0-t2)), 60);
355 //txt += "s";
356 txt += ")";
357 }
358 fDisplay->SetStatusLine1(txt);
359 start = num;
360 t2 = t0;
361 }
362
363 //
364 // Set new progress bar position
365 //
366 if (fProgress && fNumEvents>0)
367 fProgress->SetPosition((Double_t)num/fNumEvents);
368
369 // FIXME: This is a workaround, because TApplication::Run is not
370 // thread safe against ProcessEvents. We assume, that if
371 // we are not in the Main-Thread ProcessEvents() is
372 // called by the TApplication Event Loop...
373 if (!TThread::Self()/*gApplication->InheritsFrom(TRint::Class())*/)
374 {
375 //
376 // Handle GUI events (display changes)
377 //
378#if ROOT_VERSION_CODE < ROOT_VERSION(3,02,06)
379 gSystem->ProcessEvents();
380#else
381 if (fDisplay)
382 gSystem->ProcessEvents();
383 else
384 if (fProgress)
385 gClient->ProcessEventsFor(fProgress);
386#endif
387 }
388
389 return rc;
390}
391
392// --------------------------------------------------------------------------
393//
394// The processing part of the eventloop. Be careful, this is
395// for developers or use in special jobs only!
396//
397Int_t MEvtLoop::Process(UInt_t maxcnt)
398{
399 if (!fTaskList)
400 return kFALSE;
401
402 //
403 // loop over all events and process all tasks for
404 // each event
405 //
406 *fLog << all <<"Eventloop running (";
407
408 if (maxcnt==0)
409 *fLog << "all";
410 else
411 *fLog << dec << maxcnt;
412
413 *fLog << " events)..." << flush;
414
415 UInt_t entries = kMaxUInt;
416 fNumEvents = 0;
417
418 if (fProgress && !gROOT->IsBatch())
419 {
420 fProgress->Reset();
421 fProgress->SetRange(0, 1);
422
423#ifdef __MARS__
424 MRead *read = (MRead*)fTaskList->FindObject("MRead");
425 if (read && read->GetEntries()>0)
426 entries = read->GetEntries();
427#endif
428
429 if (maxcnt>0)
430 fNumEvents = TMath::Min(maxcnt, entries);
431 else
432 if (entries!=kMaxUInt)
433 fNumEvents = entries;
434 }
435
436 if (fDisplay)
437 {
438 fDisplay->SetStatusLine1("Processing...");
439 fDisplay->SetStatusLine2("");
440 }
441
442 //
443 // start a stopwatch
444 //
445 TStopwatch clock;
446 clock.Start();
447
448 //
449 // This is the MAIN EVENTLOOP which processes the data
450 // if maxcnt==0 the number of processed events is counted
451 // else only maxcnt events are processed
452 //
453 UInt_t numcnts = 0;
454 UInt_t dummy = maxcnt;
455
456 Int_t rc=kTRUE;
457 if (maxcnt==0)
458 // process first and increment if sucessfull
459 while (1)
460 {
461 rc=fTaskList->Process();
462 if (rc!=kTRUE && rc!=kCONTINUE)
463 break;
464
465 numcnts++;
466 if (!ProcessGuiEvents(++dummy))
467 break;
468 }
469 else
470 // check for number and break if unsuccessfull
471 while (dummy--)
472 {
473 rc=fTaskList->Process();
474 if (rc!=kTRUE && rc!=kCONTINUE)
475 break;
476
477 numcnts++;
478 if (!ProcessGuiEvents(maxcnt - dummy))
479 break;
480 }
481
482 //
483 // stop stop-watch, print results
484 //
485 clock.Stop();
486
487 if (fProgress && !gROOT->IsBatch())
488 {
489 //fProgress->SetPosition(maxcnt>0 ? TMath::Min(maxcnt, entries) : entries);
490 fProgress->SetPosition(1);
491
492 // FIXME: This is a workaround, because TApplication::Run is not
493 // thread safe against ProcessEvents. We assume, that if
494 // we are not in the Main-Thread ProcessEvents() is
495 // called by the TApplication Event Loop...
496 if (!TThread::Self()/*gApplication->InheritsFrom(TRint::Class())*/)
497 {
498#if ROOT_VERSION_CODE < ROOT_VERSION(3,02,06)
499 gSystem->ProcessEvents();
500#else
501 gClient->ProcessEventsFor(fDisplay ? fDisplay->GetBar() : fProgress);
502#endif
503 }
504 }
505
506 *fLog << all << "Ready!" << endl << endl;
507
508 *fLog << dec << endl << "CPU - Time: ";
509 *fLog << clock.CpuTime() << "s" << " for " << numcnts << " Events";
510 if (numcnts>0)
511 *fLog << " --> " << numcnts/clock.CpuTime() << " Events/s";
512 *fLog << endl << "Real - Time: ";
513 *fLog << clock.RealTime() << "s" << " for " << numcnts << " Events";
514 if (numcnts>0)
515 *fLog << " --> " << numcnts/clock.RealTime() << " Events/s";
516
517 *fLog << endl << endl;
518
519 return rc!=kERROR;
520}
521
522// --------------------------------------------------------------------------
523//
524// The postprocessing part of the eventloop. Be careful, this is
525// for developers or use in special jobs only!
526//
527Bool_t MEvtLoop::PostProcess() const
528{
529 //
530 // execute the post process of all tasks
531 //
532 return fTaskList ? fTaskList->PostProcess() : kTRUE;
533}
534
535// --------------------------------------------------------------------------
536//
537// See class description above. Returns kTRUE if PreProcessing,
538// Processing and PostProcessing was successfull.
539// kFALSE is retuned if something was not successfull, eg:
540// PreProcess or PostProcess returned kFALSE
541// process returned kERRR
542//
543// maxcnt==0 means: all events
544// tlist is the name of the task-list to be used. Be carefull, this
545// feature is not finally implemented - it will only work if no
546// task will access the tasklist.
547//
548Bool_t MEvtLoop::Eventloop(UInt_t maxcnt, const char *tlist)
549{
550 TDatime d;
551 *fLog << inf << underline << "Eventloop: " << fName << " started at " << d.AsString() << endl;
552
553 Bool_t rc = PreProcess(tlist);
554
555 //
556 // If all Tasks were PreProcesses successfully start Processing.
557 //
558 if (rc)
559 rc = Process(maxcnt);
560
561 //
562 // Now postprocess all tasks. Only successfully preprocessed tasks
563 // are postprocessed. If the Postprocessing of one task fails
564 // return an error.
565 //
566 if (!PostProcess())
567 {
568 *fLog << err << "Error detected while PostProcessing." << endl;
569 rc = kFALSE;
570 }
571
572 if (!fDisplay)
573 return rc;
574
575 // Set status lines
576 fDisplay->SetStatusLine1(fName);
577 fDisplay->SetStatusLine2(rc ? "Done." : "Error!");
578 // Stop automatic update
579 fDisplay->StopUpdate();
580 // Reallow context menus
581 fDisplay->SetNoContextMenu(kFALSE);
582 // Reallow user to exit window by File menu
583 fDisplay->UnLock();
584
585 //
586 // If postprocessing of all preprocessed tasks was sucefully return rc.
587 // This gives an error in case the preprocessing has failed already.
588 // Otherwise the eventloop is considered: successfully.
589 //
590 return rc;
591}
592
593// --------------------------------------------------------------------------
594//
595// After you setup (or read) an Evtloop you can use MakeMacro() to write
596// the eventloop setup as a macro. The default name is "evtloop.C". The
597// default extension is .C If the extension is not given, .C is added.
598// If the last character in the argument is a '+' the file is not closed.
599// This is usefull if you have an eventloop which runs three times and
600// you want to write one macro. If the first character is a '+' no
601// opening is written, eg:
602//
603// MEvtLoop evtloop;
604// // some setup
605// evtloop.MakeMacro("mymacro+");
606// // replace the tasklist the first time
607// evtloop.MakeMacro("+mymacro+");
608// // replace the tasklist the second time
609// evtloop.MakeMacro("+mymacro");
610//
611void MEvtLoop::MakeMacro(const char *filename)
612{
613 TString name(filename);
614
615 name = name.Strip(TString::kBoth);
616
617 Bool_t open = kTRUE;
618 Bool_t close = kTRUE;
619 if (name[0]=='+')
620 {
621 open = kFALSE;
622 name.Remove(0, 1);
623 name = name.Strip(TString::kBoth);
624 }
625
626 if (name[name.Length()-1]=='+')
627 {
628 close = kFALSE;
629 name.Remove(name.Length()-1, 1);
630 name = name.Strip(TString::kBoth);
631 }
632
633 if (!name.EndsWith(".C"))
634 name += ".C";
635
636 ofstream fout;
637
638 if (!open)
639 {
640 fout.open(name, ios::app);
641 fout << endl;
642 fout << " // ----------------------------------------------------------------------" << endl;
643 fout << endl;
644 }
645 else
646 {
647 fout.open(name);
648
649 time_t t = time(NULL);
650 fout <<
651 "/* ======================================================================== *\\" << endl <<
652 "!" << endl <<
653 "! *" << endl <<
654 "! * This file is part of MARS, the MAGIC Analysis and Reconstruction" << endl <<
655 "! * Software. It is distributed to you in the hope that it can be a useful" << endl <<
656 "! * and timesaving tool in analysing Data of imaging Cerenkov telescopes." << endl <<
657 "! * It is distributed WITHOUT ANY WARRANTY." << endl <<
658 "! *" << endl <<
659 "! * Permission to use, copy, modify and distribute this software and its" << endl <<
660 "! * documentation for any purpose is hereby granted without fee," << endl <<
661 "! * provided that the above copyright notice appear in all copies and" << endl <<
662 "! * that both that copyright notice and this permission notice appear" << endl <<
663 "! * in supporting documentation. It is provided \"as is\" without express" << endl <<
664 "! * or implied warranty." << endl <<
665 "! *" << endl <<
666 "!" << endl <<
667 "!" << endl <<
668 "! Author(s): Thomas Bretz et al. <mailto:tbretz@astro.uni-wuerzburg.de>" << endl <<
669 "!" << endl <<
670 "! Copyright: MAGIC Software Development, 2000-2002" << endl <<
671 "!" << endl <<
672 "!" << endl <<
673 "\\* ======================================================================== */" << endl << endl <<
674 "// ------------------------------------------------------------------------" << endl <<
675 "//" << endl <<
676 "// This macro was automatically created on" << endl<<
677 "// " << ctime(&t) <<
678 "// with the MEvtLoop::MakeMacro tool." << endl <<
679 "//" << endl <<
680 "// ------------------------------------------------------------------------" << endl << endl <<
681 "void " << name(0, name.Length()-2) << "()" << endl <<
682 "{" << endl;
683 }
684
685 SavePrimitive(fout, (TString)"" + (open?"open":"") + (close?"close":""));
686
687 if (!close)
688 return;
689
690 fout << "}" << endl;
691
692 *fLog << inf << "Macro '" << name << "' written." << endl;
693}
694
695// --------------------------------------------------------------------------
696//
697// Implementation of SavePrimitive. Used to write the call to a constructor
698// to a macro. In the original root implementation it is used to write
699// gui elements to a macro-file.
700//
701void MEvtLoop::StreamPrimitive(ofstream &out) const
702{
703 out << " MEvtLoop " << GetUniqueName();
704 if (fName!="Evtloop")
705 out << "(\"" << fName << "\")";
706 out << ";" << endl;
707}
708
709// --------------------------------------------------------------------------
710//
711//
712void MEvtLoop::SavePrimitive(ofstream &out, Option_t *opt)
713{
714 TString options = opt;
715 options.ToLower();
716
717 if (HasDuplicateNames("MEvtLoop::SavePrimitive"))
718 {
719 out << " // !" << endl;
720 out << " // ! WARNING - Your eventloop (MParList, MTaskList, ...) contains more than" << endl;
721 out << " // ! one object (MParContainer, MTask, ...) with the same name. The created macro" << endl;
722 out << " // ! may need manual intervention before it can be used." << endl;
723 out << " // !" << endl;
724 out << endl;
725 }
726
727 if (!options.Contains("open"))
728 {
729 if (gListOfPrimitives)
730 {
731 *fLog << err << "MEvtLoop::SavePrimitive - Error: old file not closed." << endl;
732 gListOfPrimitives->ForEach(TObject, ResetBit)(BIT(15));
733 delete gListOfPrimitives;
734 }
735 gListOfPrimitives = new TList;
736 }
737
738 if (fParList)
739 fParList->SavePrimitive(out);
740
741 MParContainer::SavePrimitive(out);
742
743 if (fParList)
744 out << " " << GetUniqueName() << ".SetParList(&" << fParList->GetUniqueName() << ");" << endl;
745 else
746 out << " // fParList empty..." << endl;
747 out << " if (!" << GetUniqueName() << ".Eventloop())" << endl;
748 out << " return;" << endl;
749
750 if (!options.Contains("close"))
751 return;
752
753 gListOfPrimitives->ForEach(TObject, ResetBit)(BIT(15));
754 delete gListOfPrimitives;
755 gListOfPrimitives = 0;
756}
757
758// --------------------------------------------------------------------------
759//
760// Get a list of all conmtainer names which are somehow part of the
761// eventloop. Chack for duplicate members and print a warning if
762// duplicates are found. Return kTRUE if duplicates are found, otherwise
763// kFALSE;
764//
765Bool_t MEvtLoop::HasDuplicateNames(TObjArray &arr, const TString txt) const
766{
767 arr.Sort();
768
769 TIter Next(&arr);
770 TObject *obj;
771 TString name;
772 Bool_t found = kFALSE;
773 while ((obj=Next()))
774 {
775 if (name==obj->GetName())
776 {
777 if (!found)
778 {
779 *fLog << warn << endl;
780 *fLog << " ! WARNING (" << txt << ")" << endl;
781 *fLog << " ! Your eventloop (MParList, MTaskList, ...) contains more than" << endl;
782 *fLog << " ! one object (MParContainer, MTask, ...) with the same name." << endl;
783 *fLog << " ! Creating a macro from it using MEvtLoop::MakeMacro may create" << endl;
784 *fLog << " ! a macro which needs manual intervention before it can be used." << endl;
785 found = kTRUE;
786 }
787 *fLog << " ! Please rename: " << obj->GetName() << endl;
788 }
789 name = obj->GetName();
790 }
791
792 return found;
793}
794
795// --------------------------------------------------------------------------
796//
797// Get a list of all conmtainer names which are somehow part of the
798// eventloop. Chack for duplicate members and print a warning if
799// duplicates are found. Return kTRUE if duplicates are found, otherwise
800// kFALSE;
801//
802Bool_t MEvtLoop::HasDuplicateNames(const TString txt) const
803{
804 if (!fParList)
805 return kFALSE;
806
807 TObjArray list;
808 list.SetOwner();
809
810 fParList->GetNames(list);
811
812 return HasDuplicateNames(list, txt);
813}
814
815// --------------------------------------------------------------------------
816//
817// Reads a saved eventloop from a file. The default name is "Evtloop".
818// Therefor an open file must exist (See TFile for more information)
819//
820// eg:
821// TFile file("myfile.root", "READ");
822// MEvtLoop evtloop;
823// evtloop.Read();
824// evtloop.MakeMacro("mymacro");
825//
826Int_t MEvtLoop::Read(const char *name)
827{
828 if (!gFile)
829 {
830 *fLog << err << "MEvtloop::Read: No file found. Please create a TFile first." << endl;
831 return 0;
832 }
833
834 if (!gFile->IsOpen())
835 {
836 *fLog << err << "MEvtloop::Read: File not open. Please open the TFile first." << endl;
837 return 0;
838 }
839
840 Int_t n = 0;
841 TObjArray list;
842
843 n += TObject::Read(name);
844
845 if (n==0)
846 {
847 *fLog << err << "MEvtloop::Read: No objects read." << endl;
848 return 0;
849 }
850
851 n += list.Read((TString)name+"_names");
852
853 fParList->SetNames(list);
854
855 HasDuplicateNames(list, "MEvtLoop::Read");
856
857 *fLog << inf << "Eventloop '" << name << "' read from file." << endl;
858
859 return n;
860}
861
862// --------------------------------------------------------------------------
863//
864// If available print the contents of the parameter list.
865//
866void MEvtLoop::Print(Option_t *opt) const
867{
868 if (fParList)
869 fParList->Print();
870 else
871 *fLog << all << "MEvtloop: No Parameter List available." << endl;
872}
873
874// --------------------------------------------------------------------------
875//
876// Writes a eventloop to a file. The default name is "Evtloop".
877// Therefor an open file must exist (See TFile for more information)
878//
879// eg:
880// TFile file("myfile.root", "RECREATE");
881// MEvtLoop evtloop;
882// evtloop.Write();
883// file.Close();
884//
885Int_t MEvtLoop::Write(const char *name, Int_t option, Int_t bufsize) const
886{
887 if (!gFile)
888 {
889 *fLog << err << "MEvtloop::Write: No file found. Please create a TFile first." << endl;
890 return 0;
891 }
892
893 if (!gFile->IsOpen())
894 {
895 *fLog << err << "MEvtloop::Write: File not open. Please open the TFile first." << endl;
896 return 0;
897 }
898
899 if (!gFile->IsWritable())
900 {
901 *fLog << err << "MEvtloop::Write: File not writable." << endl;
902 return 0;
903 }
904
905 Int_t n = 0;
906
907 TObjArray list;
908 list.SetOwner();
909
910 fParList->GetNames(list);
911
912#if ROOT_VERSION_CODE < ROOT_VERSION(4,02,00)
913 n += const_cast<MEvtLoop*>(this)->TObject::Write(name, option, bufsize);
914#else
915 n += TObject::Write(name, option, bufsize);
916#endif
917
918 if (n==0)
919 {
920 *fLog << err << "MEvtloop::Read: No objects written." << endl;
921 return 0;
922 }
923
924 n += list.Write((TString)name+"_names", kSingleKey);
925
926 HasDuplicateNames(list, "MEvtLoop::Write");
927
928 *fLog << inf << "Eventloop written to file as " << name << "." << endl;
929
930 return n;
931}
932
933// --------------------------------------------------------------------------
934//
935// Read the contents/setup of a parameter container/task from a TEnv
936// instance (steering card/setup file).
937// The key to search for in the file should be of the syntax:
938// prefix.vname
939// While vname is a name which is specific for a single setup date
940// (variable) of this container and prefix is something like:
941// evtloopname.name
942// While name is the name of the containers/tasks in the parlist/tasklist
943//
944// eg. Job4.MImgCleanStd.CleaningLevel1: 3.0
945// Job4.MImgCleanStd.CleaningLevel2: 2.5
946//
947// If this cannot be found the next step is to search for
948// MImgCleanStd.CleaningLevel1: 3.0
949// And if this doesn't exist, too, we should search for:
950// CleaningLevel1: 3.0
951//
952//
953// With the argument prefix you can overwrite the name of the MEvtLoop object
954// as prefix - use with extreme care! The prifix argument must not end with
955// a dot!
956//
957//
958// Warning: The programmer is responsible for the names to be unique in
959// all Mars classes.
960//
961Int_t MEvtLoop::ReadEnv(const TEnv &env, TString prefix, Bool_t print)
962{
963// if (!prefix.IsNull())
964// *fLog << warn << "WARNING - Second argument in MEvtLoop::ReadEnv has no meaning... ignored." << endl;
965
966 if (prefix.IsNull())
967 prefix = fName;
968 prefix += ".";
969
970 *fLog << inf << "Reading resources for " << prefix /*TEnv::fRcName << " from " << env.GetRcName()*/ << endl;
971
972 fLog->ReadEnv(env, prefix, print);
973
974 if (!fParList)
975 {
976 *fLog << warn << "WARNING - No parameter list to propagate resources to." << endl;
977 return kTRUE;
978 }
979
980 if (fParList->ReadEnv(env, prefix, print)==kERROR)
981 {
982 *fLog << err << "ERROR - Reading Environment file." << endl;
983 return kFALSE;
984 }
985
986 return kTRUE;
987}
988
989// --------------------------------------------------------------------------
990//
991// Calls 'ReadEnv' with a TEnv initialized with the given file name.
992// If 'config=0' kTRUE is returned.
993//
994Bool_t MEvtLoop::ReadEnv(const char *config, Bool_t print)
995{
996 if (!config)
997 return kTRUE;
998
999 const Bool_t fileexist = !gSystem->AccessPathName(config, kFileExists);
1000 if (!fileexist)
1001 {
1002 *fLog << warn << "WARNING - resource file '" << config << "' not found... no resources applied." << endl;
1003 return kFALSE;
1004 }
1005
1006 return ReadEnv(TEnv(config), "", print);
1007}
1008
1009// --------------------------------------------------------------------------
1010//
1011// Write the contents/setup of a parameter container/task to a TEnv
1012// instance (steering card/setup file).
1013// The key to search for in the file should be of the syntax:
1014// prefix.vname
1015// While vname is a name which is specific for a single setup date
1016// (variable) of this container and prefix is something like:
1017// evtloopname.name
1018// While name is the name of the containers/tasks in the parlist/tasklist
1019//
1020// eg. Job4.MImgCleanStd.CleaningLevel1: 3.0
1021// Job4.MImgCleanStd.CleaningLevel2: 2.5
1022//
1023// If this cannot be found the next step is to search for
1024// MImgCleanStd.CleaningLevel1: 3.0
1025// And if this doesn't exist, too, we should search for:
1026// CleaningLevel1: 3.0
1027//
1028// Warning: The programmer is responsible for the names to be unique in
1029// all Mars classes.
1030//
1031Bool_t MEvtLoop::WriteEnv(TEnv &env, TString prefix, Bool_t print) const
1032{
1033 if (!prefix.IsNull())
1034 *fLog << warn << "WARNING - Second argument in MEvtLoop::WriteEnv has no meaning... ignored." << endl;
1035
1036 prefix = fName;
1037 prefix += ".";
1038
1039 *fLog << inf << "Writing resources: " << prefix /*TEnv::fRcName << " to " << env.GetRcName()*/ << endl;
1040
1041 fLog->WriteEnv(env, prefix, print);
1042
1043 if (!fParList)
1044 {
1045 *fLog << warn << "WARNING - No parameter list to get resources from." << endl;
1046 return kTRUE;
1047 }
1048
1049
1050 if (fParList->WriteEnv(env, prefix, print)!=kTRUE)
1051 {
1052 *fLog << err << "ERROR - Writing Environment file." << endl;
1053 return kFALSE;
1054 }
1055
1056 return kTRUE;
1057}
1058
1059void MEvtLoop::RecursiveRemove(TObject *obj)
1060{
1061 if (obj==fParList)
1062 {
1063 fParList=NULL;
1064 fTaskList=NULL;
1065 }
1066
1067 if (obj==fProgress)
1068 fProgress = NULL;
1069
1070 if (obj==fDisplay)
1071 SetDisplay(NULL);
1072
1073 if (obj==fLog)
1074 {
1075 if (fParList)
1076 fParList->SetLogStream(NULL);
1077 SetLogStream(NULL);
1078 }
1079}
Note: See TracBrowser for help on using the repository browser.