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

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