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

Last change on this file since 8791 was 8746, checked in by tbretz, 17 years ago
*** empty log message ***
File size: 32.9 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 //
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 *fLog << inf << endl << underline << "Eventloop: " << fName << " started at " << TDatime().AsString() << endl;
578
579 Bool_t rc = PreProcess();
580
581 //
582 // If all Tasks were PreProcesses successfully start Processing.
583 //
584 if (rc)
585 rc = Process(maxcnt);
586
587 //
588 // Now postprocess all tasks. Only successfully preprocessed tasks
589 // are postprocessed. If the Postprocessing of one task fails
590 // return an error.
591 //
592 if (!PostProcess())
593 {
594 *fLog << err << "Error detected while PostProcessing." << endl;
595 rc = kFALSE;
596 }
597
598 //
599 // If Process has ever been called print statistics
600 //
601 if (fTaskList && fTaskList->GetNumExecutions()>0)
602 switch (printstat)
603 {
604 case kNoStatistics:
605 break;
606 case kStdStatistics:
607 fTaskList->PrintStatistics();
608 break;
609 case kFullStatistics:
610 fTaskList->PrintStatistics(0, kTRUE);
611 break;
612 }
613
614 if (!fDisplay)
615 return rc;
616
617 // Set status lines
618 fDisplay->SetStatusLine1(fName);
619 fDisplay->SetStatusLine2(rc ? "Done." : "Error!");
620 // Stop automatic update
621 fDisplay->StopUpdate();
622 // Reallow context menus
623 fDisplay->SetNoContextMenu(kFALSE);
624 // Reallow user to exit window by File menu
625 fDisplay->UnLock();
626
627 //
628 // If postprocessing of all preprocessed tasks was sucefully return rc.
629 // This gives an error in case the preprocessing has failed already.
630 // Otherwise the eventloop is considered: successfully.
631 //
632 return rc;
633}
634
635// --------------------------------------------------------------------------
636//
637// After you setup (or read) an Evtloop you can use MakeMacro() to write
638// the eventloop setup as a macro. The default name is "evtloop.C". The
639// default extension is .C If the extension is not given, .C is added.
640// If the last character in the argument is a '+' the file is not closed.
641// This is usefull if you have an eventloop which runs three times and
642// you want to write one macro. If the first character is a '+' no
643// opening is written, eg:
644//
645// MEvtLoop evtloop;
646// // some setup
647// evtloop.MakeMacro("mymacro+");
648// // replace the tasklist the first time
649// evtloop.MakeMacro("+mymacro+");
650// // replace the tasklist the second time
651// evtloop.MakeMacro("+mymacro");
652//
653void MEvtLoop::MakeMacro(const char *filename)
654{
655 TString name(filename);
656
657 name = name.Strip(TString::kBoth);
658
659 Bool_t open = kTRUE;
660 Bool_t close = kTRUE;
661 if (name[0]=='+')
662 {
663 open = kFALSE;
664 name.Remove(0, 1);
665 name = name.Strip(TString::kBoth);
666 }
667
668 if (name[name.Length()-1]=='+')
669 {
670 close = kFALSE;
671 name.Remove(name.Length()-1, 1);
672 name = name.Strip(TString::kBoth);
673 }
674
675 if (!name.EndsWith(".C"))
676 name += ".C";
677
678 ofstream fout;
679
680 if (!open)
681 {
682 fout.open(name, ios::app);
683 fout << endl;
684 fout << " // ----------------------------------------------------------------------" << endl;
685 fout << endl;
686 }
687 else
688 {
689 fout.open(name);
690
691 time_t t = time(NULL);
692 fout <<
693 "/* ======================================================================== *\\" << endl <<
694 "!" << endl <<
695 "! *" << endl <<
696 "! * This file is part of MARS, the MAGIC Analysis and Reconstruction" << endl <<
697 "! * Software. It is distributed to you in the hope that it can be a useful" << endl <<
698 "! * and timesaving tool in analysing Data of imaging Cerenkov telescopes." << endl <<
699 "! * It is distributed WITHOUT ANY WARRANTY." << endl <<
700 "! *" << endl <<
701 "! * Permission to use, copy, modify and distribute this software and its" << endl <<
702 "! * documentation for any purpose is hereby granted without fee," << endl <<
703 "! * provided that the above copyright notice appear in all copies and" << endl <<
704 "! * that both that copyright notice and this permission notice appear" << endl <<
705 "! * in supporting documentation. It is provided \"as is\" without express" << endl <<
706 "! * or implied warranty." << endl <<
707 "! *" << endl <<
708 "!" << endl <<
709 "!" << endl <<
710 "! Author(s): Thomas Bretz et al. <mailto:tbretz@astro.uni-wuerzburg.de>" << endl <<
711 "!" << endl <<
712 "! Copyright: MAGIC Software Development, 2000-2005" << endl <<
713 "!" << endl <<
714 "!" << endl <<
715 "\\* ======================================================================== */" << endl << endl <<
716 "// ------------------------------------------------------------------------" << endl <<
717 "//" << endl <<
718 "// This macro was automatically created on" << endl<<
719 "// " << ctime(&t) <<
720 "// with the MEvtLoop::MakeMacro tool." << endl <<
721 "//" << endl <<
722 "// ------------------------------------------------------------------------" << endl << endl <<
723 "void " << name(0, name.Length()-2) << "()" << endl <<
724 "{" << endl;
725 }
726
727 SavePrimitive(fout, (TString)"" + (open?"open":"") + (close?"close":""));
728
729 if (!close)
730 return;
731
732 fout << "}" << endl;
733
734 *fLog << inf << "Macro '" << name << "' written." << endl;
735}
736
737// --------------------------------------------------------------------------
738//
739// Implementation of SavePrimitive. Used to write the call to a constructor
740// to a macro. In the original root implementation it is used to write
741// gui elements to a macro-file.
742//
743void MEvtLoop::StreamPrimitive(ostream &out) const
744{
745 out << " MEvtLoop " << GetUniqueName();
746 if (fName!="Evtloop")
747 out << "(\"" << fName << "\")";
748 out << ";" << endl;
749}
750
751// --------------------------------------------------------------------------
752//
753//
754void MEvtLoop::SavePrimitive(ostream &out, Option_t *opt)
755{
756 TString options = opt;
757 options.ToLower();
758
759 if (HasDuplicateNames("MEvtLoop::SavePrimitive"))
760 {
761 out << " // !" << endl;
762 out << " // ! WARNING - Your eventloop (MParList, MTaskList, ...) contains more than" << endl;
763 out << " // ! one object (MParContainer, MTask, ...) with the same name. The created macro" << endl;
764 out << " // ! may need manual intervention before it can be used." << endl;
765 out << " // !" << endl;
766 out << endl;
767 }
768
769 if (!options.Contains("open"))
770 {
771 if (gListOfPrimitives)
772 {
773 *fLog << err << "MEvtLoop::SavePrimitive - Error: old file not closed." << endl;
774 gListOfPrimitives->R__FOR_EACH(TObject, ResetBit)(BIT(15));
775 delete gListOfPrimitives;
776 }
777 gListOfPrimitives = new TList;
778 }
779
780 if (fParList)
781 fParList->SavePrimitive(out);
782
783 MParContainer::SavePrimitive(out);
784
785 if (fParList)
786 out << " " << GetUniqueName() << ".SetParList(&" << fParList->GetUniqueName() << ");" << endl;
787 else
788 out << " // fParList empty..." << endl;
789 out << " if (!" << GetUniqueName() << ".Eventloop())" << endl;
790 out << " return;" << endl;
791
792 if (!options.Contains("close"))
793 return;
794
795 gListOfPrimitives->R__FOR_EACH(TObject, ResetBit)(BIT(15));
796 delete gListOfPrimitives;
797 gListOfPrimitives = 0;
798}
799
800void MEvtLoop::SavePrimitive(ofstream &out, Option_t *o)
801{
802 SavePrimitive(static_cast<ostream&>(out), o);
803}
804
805// --------------------------------------------------------------------------
806//
807// Get a list of all conmtainer names which are somehow part of the
808// eventloop. Chack for duplicate members and print a warning if
809// duplicates are found. Return kTRUE if duplicates are found, otherwise
810// kFALSE;
811//
812Bool_t MEvtLoop::HasDuplicateNames(TObjArray &arr, const TString txt) const
813{
814 arr.Sort();
815
816 TIter Next(&arr);
817 TObject *obj;
818 TString name;
819 Bool_t found = kFALSE;
820 while ((obj=Next()))
821 {
822 if (name==obj->GetName())
823 {
824 if (!found)
825 {
826 *fLog << warn << endl;
827 *fLog << " ! WARNING (" << txt << ")" << endl;
828 *fLog << " ! Your eventloop (MParList, MTaskList, ...) contains more than" << endl;
829 *fLog << " ! one object (MParContainer, MTask, ...) with the same name." << endl;
830 *fLog << " ! Creating a macro from it using MEvtLoop::MakeMacro may create" << endl;
831 *fLog << " ! a macro which needs manual intervention before it can be used." << endl;
832 found = kTRUE;
833 }
834 *fLog << " ! Please rename: " << obj->GetName() << endl;
835 }
836 name = obj->GetName();
837 }
838
839 return found;
840}
841
842// --------------------------------------------------------------------------
843//
844// Get a list of all conmtainer names which are somehow part of the
845// eventloop. Chack for duplicate members and print a warning if
846// duplicates are found. Return kTRUE if duplicates are found, otherwise
847// kFALSE;
848//
849Bool_t MEvtLoop::HasDuplicateNames(const TString txt) const
850{
851 if (!fParList)
852 return kFALSE;
853
854 TObjArray list;
855 list.SetOwner();
856
857 fParList->GetNames(list);
858
859 return HasDuplicateNames(list, txt);
860}
861
862// --------------------------------------------------------------------------
863//
864// Reads a saved eventloop from a file. The default name is "Evtloop".
865// Therefor an open file must exist (See TFile for more information)
866//
867// eg:
868// TFile file("myfile.root", "READ");
869// MEvtLoop evtloop;
870// evtloop.Read();
871// evtloop.MakeMacro("mymacro");
872//
873Int_t MEvtLoop::Read(const char *name)
874{
875 if (!gFile)
876 {
877 *fLog << err << "MEvtloop::Read: No file found. Please create a TFile first." << endl;
878 return 0;
879 }
880
881 if (!gFile->IsOpen())
882 {
883 *fLog << err << "MEvtloop::Read: File not open. Please open the TFile first." << endl;
884 return 0;
885 }
886
887 Int_t n = 0;
888 TObjArray list;
889
890 n += TObject::Read(name);
891
892 if (n==0)
893 {
894 *fLog << err << "MEvtloop::Read: No objects read." << endl;
895 return 0;
896 }
897
898 n += list.Read((TString)name+"_names");
899
900 fParList->SetNames(list);
901
902 HasDuplicateNames(list, "MEvtLoop::Read");
903
904 *fLog << inf << "Eventloop '" << name << "' read from file." << endl;
905
906 return n;
907}
908
909// --------------------------------------------------------------------------
910//
911// If available print the contents of the parameter list.
912//
913void MEvtLoop::Print(Option_t *) const
914{
915 if (fParList)
916 fParList->Print();
917 else
918 *fLog << all << "MEvtloop: No Parameter List available." << endl;
919}
920
921// --------------------------------------------------------------------------
922//
923// Writes a eventloop to a file. The default name is "Evtloop".
924// Therefor an open file must exist (See TFile for more information)
925//
926// eg:
927// TFile file("myfile.root", "RECREATE");
928// MEvtLoop evtloop;
929// evtloop.Write();
930// file.Close();
931//
932Int_t MEvtLoop::Write(const char *name, Int_t option, Int_t bufsize) const
933{
934 if (!gFile)
935 {
936 *fLog << err << "MEvtloop::Write: No file found. Please create a TFile first." << endl;
937 return 0;
938 }
939
940 if (!gFile->IsOpen())
941 {
942 *fLog << err << "MEvtloop::Write: File not open. Please open the TFile first." << endl;
943 return 0;
944 }
945
946 if (!gFile->IsWritable())
947 {
948 *fLog << err << "MEvtloop::Write: File not writable." << endl;
949 return 0;
950 }
951
952 Int_t n = 0;
953
954 TObjArray list;
955 list.SetOwner();
956
957 fParList->GetNames(list);
958
959#if ROOT_VERSION_CODE < ROOT_VERSION(4,02,00)
960 n += const_cast<MEvtLoop*>(this)->TObject::Write(name, option, bufsize);
961#else
962 n += TObject::Write(name, option, bufsize);
963#endif
964
965 if (n==0)
966 {
967 *fLog << err << "MEvtloop::Read: No objects written." << endl;
968 return 0;
969 }
970
971 n += list.Write((TString)name+"_names", kSingleKey);
972
973 HasDuplicateNames(list, "MEvtLoop::Write");
974
975 *fLog << inf << "Eventloop written to file as " << name << "." << endl;
976
977 return n;
978}
979
980// --------------------------------------------------------------------------
981//
982// Read the contents/setup of a parameter container/task from a TEnv
983// instance (steering card/setup file).
984// The key to search for in the file should be of the syntax:
985// prefix.vname
986// While vname is a name which is specific for a single setup date
987// (variable) of this container and prefix is something like:
988// evtloopname.name
989// While name is the name of the containers/tasks in the parlist/tasklist
990//
991// eg. Job4.MImgCleanStd.CleaningLevel1: 3.0
992// Job4.MImgCleanStd.CleaningLevel2: 2.5
993//
994// If this cannot be found the next step is to search for
995// MImgCleanStd.CleaningLevel1: 3.0
996// And if this doesn't exist, too, we should search for:
997// CleaningLevel1: 3.0
998//
999//
1000// With the argument prefix you can overwrite the name of the MEvtLoop object
1001// as prefix - use with extreme care! The prifix argument must not end with
1002// a dot!
1003//
1004//
1005// Warning: The programmer is responsible for the names to be unique in
1006// all Mars classes.
1007//
1008Int_t MEvtLoop::ReadEnv(const TEnv &env, TString prefix, Bool_t print)
1009{
1010// if (!prefix.IsNull())
1011// *fLog << warn << "WARNING - Second argument in MEvtLoop::ReadEnv has no meaning... ignored." << endl;
1012
1013 if (prefix.IsNull())
1014 prefix = fName;
1015 prefix += ".";
1016
1017 *fLog << inf << "Reading resources for " << prefix /*TEnv::fRcName << " from " << env.GetRcName()*/ << endl;
1018
1019 fLog->ReadEnv(env, prefix, print);
1020
1021 if (!fParList)
1022 {
1023 *fLog << warn << "WARNING - No parameter list to propagate resources to." << endl;
1024 return kTRUE;
1025 }
1026
1027 if (fParList->ReadEnv(env, prefix, print)==kERROR)
1028 {
1029 *fLog << err << "ERROR - Reading Environment file." << endl;
1030 return kFALSE;
1031 }
1032
1033 return kTRUE;
1034}
1035
1036// --------------------------------------------------------------------------
1037//
1038// Calls 'ReadEnv' with a TEnv initialized with the given file name.
1039// If 'config=0' kTRUE is returned.
1040//
1041Bool_t MEvtLoop::ReadEnv(const char *config, Bool_t print)
1042{
1043 if (!config)
1044 return kTRUE;
1045
1046 const Bool_t fileexist = !gSystem->AccessPathName(config, kFileExists);
1047 if (!fileexist)
1048 {
1049 *fLog << warn << "WARNING - resource file '" << config << "' not found... no resources applied." << endl;
1050 return kFALSE;
1051 }
1052
1053 const TEnv env(config);
1054 return ReadEnv(env, "", print);
1055}
1056
1057// --------------------------------------------------------------------------
1058//
1059// Write the contents/setup of a parameter container/task to a TEnv
1060// instance (steering card/setup file).
1061// The key to search for in the file should be of the syntax:
1062// prefix.vname
1063// While vname is a name which is specific for a single setup date
1064// (variable) of this container and prefix is something like:
1065// evtloopname.name
1066// While name is the name of the containers/tasks in the parlist/tasklist
1067//
1068// eg. Job4.MImgCleanStd.CleaningLevel1: 3.0
1069// Job4.MImgCleanStd.CleaningLevel2: 2.5
1070//
1071// If this cannot be found the next step is to search for
1072// MImgCleanStd.CleaningLevel1: 3.0
1073// And if this doesn't exist, too, we should search for:
1074// CleaningLevel1: 3.0
1075//
1076// Warning: The programmer is responsible for the names to be unique in
1077// all Mars classes.
1078//
1079Bool_t MEvtLoop::WriteEnv(TEnv &env, TString prefix, Bool_t print) const
1080{
1081 if (!prefix.IsNull())
1082 *fLog << warn << "WARNING - Second argument in MEvtLoop::WriteEnv has no meaning... ignored." << endl;
1083
1084 prefix = fName;
1085 prefix += ".";
1086
1087 *fLog << inf << "Writing resources: " << prefix /*TEnv::fRcName << " to " << env.GetRcName()*/ << endl;
1088
1089 fLog->WriteEnv(env, prefix, print);
1090
1091 if (!fParList)
1092 {
1093 *fLog << warn << "WARNING - No parameter list to get resources from." << endl;
1094 return kTRUE;
1095 }
1096
1097
1098 if (fParList->WriteEnv(env, prefix, print)!=kTRUE)
1099 {
1100 *fLog << err << "ERROR - Writing Environment file." << endl;
1101 return kFALSE;
1102 }
1103
1104 return kTRUE;
1105}
1106
1107void MEvtLoop::RecursiveRemove(TObject *obj)
1108{
1109 // If the tasklist was deleted... remove it
1110 if (obj==fTaskList)
1111 fTaskList = NULL;
1112
1113 // If the parlist was deleted...invalidate par- and tasklist
1114 if (obj==fParList)
1115 {
1116 fParList=NULL;
1117 fTaskList=NULL;
1118 }
1119
1120 // if the progress bar was deleted...remove it
1121 if (obj==fProgress)
1122 fProgress = NULL;
1123
1124 // If it was something else check par- and tasklist
1125 if (fParList)
1126 fParList->RecursiveRemove(obj);
1127 else
1128 if (fTaskList) // Note that the tasklist is included in the parlist
1129 fTaskList->RecursiveRemove(obj);
1130
1131 // Now check for fDisplay and fLog
1132 MParContainer::RecursiveRemove(obj);
1133}
Note: See TracBrowser for help on using the repository browser.