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

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