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

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