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

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