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

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