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

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