source: trunk/Mars/mbase/MEvtLoop.cc@ 20042

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