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

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