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

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