source: trunk/MagicSoft/Mars/mjobs/MJob.cc@ 9251

Last change on this file since 9251 was 9246, checked in by tbretz, 18 years ago
*** empty log message ***
File size: 15.6 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, 8/2004 <mailto:tbretz@astro.uni-wuerzburg.de>
19!
20! Copyright: MAGIC Software Development, 2000-2007
21!
22!
23\* ======================================================================== */
24
25/////////////////////////////////////////////////////////////////////////////
26//
27// MJob
28//
29// A base class for jobs
30//
31// SetDebugEnv(0) // switch off debugging
32// SetDebugEnv(1) // reserved
33// SetDebugEnv(2) // print untouched resources after evtloop resources setup
34// SetDebugEnv(3) // do 2) and debug setting env completely
35//
36// To allow overwriting the output files call SetOverwrite()
37//
38/////////////////////////////////////////////////////////////////////////////
39#include "MJob.h"
40
41#include "MEnv.h"
42
43#include <TFile.h>
44#include <TSystem.h>
45#include <TRandom.h>
46#include <TObjArray.h>
47
48#include "MIter.h"
49
50#include "MLog.h"
51#include "MLogManip.h"
52
53#include "MParList.h"
54#include "MEvtLoop.h"
55
56ClassImp(MJob);
57
58using namespace std;
59
60// --------------------------------------------------------------------------
61//
62// Default constructor.
63//
64// Sets fDataFlag to 0
65//
66MJob::MJob(const char *name, const char *title) : fEnv(0), fEnvDebug(0), fOverwrite(kFALSE), fMaxEvents(0)
67{
68 fName = name ? name : "MJob";
69 fTitle = title ? title : "Base class for jobs";
70}
71
72//------------------------------------------------------------------------
73//
74// If MJob is the owner of fEnv delete fEnv.
75//
76// Reset the owenership bit.
77//
78// Set fEnv to NULL.
79//
80void MJob::ClearEnv()
81{
82 if (fEnv && TestBit(kIsOwner))
83 delete fEnv;
84 ResetBit(kIsOwner);
85 fEnv=0;
86}
87
88//------------------------------------------------------------------------
89//
90// ClearEnv()
91//
92MJob::~MJob()
93{
94 ClearEnv();
95}
96
97//------------------------------------------------------------------------
98//
99// If prefix==0 the prefix is taken from fName up to the first
100// whitespace.
101//
102// A trailing dot is removed.void MJob::SetPrefix(const char *prefix)
103void MJob::SetPrefix(const char *prefix)
104{
105 fEnvPrefix = prefix;
106
107 if (!prefix)
108 fEnvPrefix = fName.First(' ')>0 ? fName(0, fName.First(' ')) : fName;
109
110 if (fEnvPrefix.EndsWith("."))
111 fEnvPrefix.Remove(fEnvPrefix.Length()-1);
112}
113
114//------------------------------------------------------------------------
115//
116// Create a new MEnv from the file env. MJob takes of course the
117// ownership of the newly created MEnv.
118//
119// SetPrefix(prefix)
120//
121// return kFALSE if MEnv is invalid
122//
123Bool_t MJob::SetEnv(const char *env, const char *prefix)
124{
125 SetEnv(new MEnv(env), prefix);
126
127 // Take the owenership of the MEnv instance
128 SetBit(kIsOwner);
129
130 return fEnv->IsValid();
131}
132
133//------------------------------------------------------------------------
134//
135// Set a new fEnv and a new general prefix.
136//
137// Calls SetPrefix(prefix)
138//
139// MJob does not take the owenership of the MEnv instance.
140//
141void MJob::SetEnv(MEnv *env, const char *prefix)
142{
143 ClearEnv();
144
145 fEnv = env;
146
147 SetPrefix(prefix);
148}
149
150//------------------------------------------------------------------------
151//
152// Removes LF's from the path (necessary if the resource file was written
153// with a different operating system than Linux.
154//
155// Removes a trailing slash if the path is not the root-path.
156//
157// Adds fname to the path if given.
158//
159void MJob::FixPath(TString &path)
160{
161 path.ReplaceAll("\015", "");
162
163 if (path==(TString)"/")
164 return;
165
166 if (path.EndsWith("/"))
167 path.Remove(path.Length()-1);
168}
169
170//------------------------------------------------------------------------
171//
172// Calls FixPath
173//
174// Adds fname to the path if given.
175//
176TString MJob::CombinePath(TString path, TString fname)
177{
178 FixPath(path);
179
180 if (fname.IsNull())
181 return path;
182
183 if (path!=(TString)"/")
184 path += "/";
185
186 path += fname;
187
188 return path;
189}
190
191//------------------------------------------------------------------------
192//
193// Sets the output path. The exact meaning (could also be a file) is
194// deined by the derived class.
195//
196void MJob::SetPathOut(const char *path)
197{
198 fPathOut = path;
199 FixPath(fPathOut);
200}
201
202//------------------------------------------------------------------------
203//
204// Sets the input path. The exact meaning (could also be a file) is
205// deined by the derived class.
206//
207void MJob::SetPathIn(const char *path)
208{
209 fPathIn = path;
210 FixPath(fPathIn);
211}
212
213//------------------------------------------------------------------------
214//
215// Returns the TEnv
216//
217const TEnv *MJob::GetEnv() const
218{
219 return static_cast<const TEnv *const>(fEnv);
220}
221
222//------------------------------------------------------------------------
223//
224// Checks GetEnvValue(*fEnv, fEnvPrefix, name, dftl)
225// For details see MParContainer
226//
227Int_t MJob::GetEnv(const char *name, Int_t dflt) const
228{
229 return GetEnvValue2(*fEnv, fEnvPrefix, name, dflt); // return fEnv->GetValue(Form("%s%s", fEnvPrefix.Data(), name), dflt);
230}
231
232//------------------------------------------------------------------------
233//
234// Checks GetEnvValue(*fEnv, fEnvPrefix, name, dftl)
235// For details see MParContainer
236//
237Double_t MJob::GetEnv(const char *name, Double_t dflt) const
238{
239 return GetEnvValue2(*fEnv, fEnvPrefix, name, dflt); // return fEnv->GetValue(Form("%s%s", fEnvPrefix.Data(), name), dflt);
240}
241
242//------------------------------------------------------------------------
243//
244// Checks GetEnvValue(*fEnv, fEnvPrefix, name, dftl)
245// For details see MParContainer
246//
247const char *MJob::GetEnv(const char *name, const char *dflt) const
248{
249 return GetEnvValue2(*fEnv, fEnvPrefix, name, dflt); //fEnv->GetValue(Form("%s%s", fEnvPrefix.Data(), name), dflt);
250}
251
252//------------------------------------------------------------------------
253//
254// Checks IsEnvDefined(*fEnv, fEnvPrefix, name, fEnvDebug>2)
255// For details see MParContainer
256//
257Bool_t MJob::HasEnv(const char *name) const
258{
259 return IsEnvDefined(*fEnv, fEnvPrefix, name, fEnvDebug>2);//fEnv->Lookup(Form("%s%s", fEnvPrefix.Data(), name));
260}
261
262//------------------------------------------------------------------------
263//
264// Check fEnv for RadnomNumberGenerator. If it is empty or the
265// corresponding class does either not exist or not inherit from TRandom,
266// gRandom remains unchanged. Otherwise gRandom is set to a newly created
267// instance of this class.
268//
269// The second resource which is checked is RandomNumberSeedValue. If it
270// is empty (not given) the seed keeps unchanged. If a number is given
271// the seed value of gRandom is set accordingly. (0 means that
272// the seed value is set accoring to the time, see TRandom::SetSeed())
273//
274// If an error occured kFALSE is returned, kTRUE otherwise.
275//
276// For exmaple:
277// RandomNumberGenerator: TRandom3
278// RandomNumberSeeValue: 0
279//
280Bool_t MJob::InitRandomNumberGenerator() const
281{
282 const TString rng = GetEnv("RandomNumberGenerator", "");
283 if (!rng.IsNull())
284 {
285 TClass *cls = MParContainer::GetClass(rng, &gLog);
286 if (!cls)
287 return kFALSE;
288
289 if (!cls->InheritsFrom(TRandom::Class()))
290 {
291 *fLog << err << "ERROR - RandomNumberGenerator " << rng << " doesn't inherit from TRandom." << endl;
292 return kFALSE;
293 }
294
295 delete gRandom;
296 gRandom = static_cast<TRandom*>(cls->New());
297
298 *fLog << inf << "Random number generator " << rng << " initialized." << endl;
299 }
300
301 // Nothing: Keep seed value, 0 set time as seed value, val set seed
302 const TString seed = GetEnv("RandomNumberSeedNumber", "");
303 if (!seed.IsNull())
304 {
305 if (!seed.IsAlnum())
306 {
307 *fLog << err << "ERROR - RandomNumberSeedValue not an integer: " << seed << endl;
308 return kFALSE;
309 }
310
311 gRandom->SetSeed(seed.Atoi());
312 *fLog << inf << "Random number seed value set to " << seed.Atoi() << endl;
313 }
314
315 return kTRUE;
316}
317
318//------------------------------------------------------------------------
319//
320// Check the resource file for
321// PathOut
322// PathIn
323// MaxEvents
324// Overwrite
325// EnvDebug
326// RandomNumberGenerator
327// RandomNumberSeedValue
328//
329// and call the virtual function CheckEnvLocal
330//
331Bool_t MJob::CheckEnv()
332{
333 if (!fEnv)
334 return kTRUE;
335
336 if (!InitRandomNumberGenerator())
337 return kFALSE;
338
339 TString p;
340 p = GetEnv("PathOut", "");
341 if (!p.IsNull())
342 SetPathOut(p);
343
344 p = GetEnv("PathIn", "");
345 if (!p.IsNull())
346 SetPathIn(p);
347
348 SetMaxEvents(GetEnv("MaxEvents", fMaxEvents));
349 SetOverwrite(GetEnv("Overwrite", fOverwrite));
350 SetEnvDebug( GetEnv("EnvDebug", fEnvDebug));
351
352 return CheckEnvLocal();
353}
354
355//------------------------------------------------------------------------
356//
357// Returns the result of c.ReadEnv(*fEnv, fEnvPrefix, fEnvDebug>2)
358// By adding the container first to a MParList it is ensured that
359// all levels are checked.
360//
361Bool_t MJob::CheckEnv(MParContainer &c) const
362{
363 if (!fEnv)
364 return kTRUE;
365
366 // Make sure that all levels are checked
367 MParList l;
368 l.AddToList(&c);
369 return l.ReadEnv(*fEnv, fEnvPrefix+".", fEnvDebug>2);
370}
371
372//------------------------------------------------------------------------
373//
374// Call the eventsloops ReadEnv and print untouched resources afterwards
375// if fEnvDebug>1
376//
377Bool_t MJob::SetupEnv(MEvtLoop &loop) const
378{
379 if (!fEnv)
380 return kTRUE;
381
382 if (!loop.ReadEnv(*fEnv, fEnvPrefix, fEnvDebug>2))
383 return kFALSE;
384
385 if (fEnvDebug>1)
386 fEnv->PrintUntouched();
387
388 return kTRUE;
389}
390
391//------------------------------------------------------------------------
392//
393// Checks whether write permissions to fname exists including
394// the fOverwrite data member. Empty file names return kTRUE
395//
396Bool_t MJob::HasWritePermission(TString fname) const
397{
398 gSystem->ExpandPathName(fname);
399
400 const Bool_t exists = !gSystem->AccessPathName(fname, kFileExists);
401 if (!exists)
402 return kTRUE;
403
404 const Bool_t write = !gSystem->AccessPathName(fname, kWritePermission);
405 if (!write)
406 {
407 *fLog << err << "ERROR - No permission to write to " << fname << endl;
408 return kFALSE;
409 }
410
411 if (fOverwrite)
412 return kTRUE;
413
414 *fLog << err;
415 *fLog << "ERROR - File " << fname << " already exists and overwrite not allowed." << endl;
416
417 return kFALSE;
418}
419
420//------------------------------------------------------------------------
421//
422// Write containers in list to gFile. Returns kFALSE if no gFile or any
423// container couldn't be written. kTRUE otherwise.
424//
425Bool_t MJob::WriteContainer(TCollection &list) const
426{
427 if (!gFile)
428 {
429 *fLog << err << dbginf << "ERROR - No file open (gFile==0)" << endl;
430 return kFALSE;
431 }
432
433 TIter Next(&list);
434 TObject *o=0;
435 while ((o=Next()))
436 {
437 *fLog << inf << " - Writing " << MParContainer::GetDescriptor(*o) << "..." << flush;
438 if (o->Write(o->GetName())<=0)
439 {
440 *fLog << err << dbginf << "ERROR - Writing " << MParContainer::GetDescriptor(*o) << " to file " << gFile->GetName() << endl;
441 return kFALSE;
442 }
443 *fLog << "ok." << endl;
444 }
445 return kTRUE;
446}
447
448//------------------------------------------------------------------------
449//
450// Read containers in list into list from gFile
451// Returns kFALSE if no gFile or any container couldn't be read.
452//
453Bool_t MJob::ReadContainer(TCollection &list) const
454{
455 if (!gFile)
456 {
457 *fLog << err << dbginf << "ERROR - No file open (gFile==0)" << endl;
458 return kFALSE;
459 }
460
461 MIter Next(&list);
462 MParContainer *o=0;
463 while ((o=Next()))
464 {
465 *fLog << inf << " - Reading " << o->GetDescriptor() << "..." << flush;
466 if (o->Read(o->GetName())<=0)
467 {
468 *fLog << err << dbginf << "ERROR - Reading " << o->GetDescriptor() << " from file " << gFile->GetName() << endl;
469 return kFALSE;
470 }
471 *fLog << "ok." << endl;
472 }
473 return kTRUE;
474}
475
476//------------------------------------------------------------------------
477//
478// Write containers in cont to fPathOut+"/"+name, or fPathOut only
479// if name is empty.
480//
481Bool_t MJob::WriteContainer(TCollection &cont, const char *name, const char *option, const int compr) const
482{
483 if (fPathOut.IsNull())
484 {
485 *fLog << inf << "No output path specified via SetPathOut - no output written." << endl;
486 return kTRUE;
487 }
488
489 const TString oname = CombinePath(fPathOut, name);
490
491 *fLog << inf << "Writing to file: " << oname << endl;
492
493 TString title("File written by ");
494 title += fName;
495
496 // In case the update-option is selected check whether
497 // the file is already open
498 if (TString(option).Contains("update", TString::kIgnoreCase))
499 {
500 TFile *file = dynamic_cast<TFile*>(gROOT->GetListOfFiles()->FindObject(oname));
501 if (file && file->IsOpen() && !file->IsZombie())
502 {
503 *fLog << inf << "Open file found." << endl;
504 file->cd();
505 return WriteContainer(cont);
506 }
507 }
508
509 // Open a new file with the defined option for writing
510 TFile file(oname, option, title, compr);
511 if (!file.IsOpen() || file.IsZombie())
512 {
513 *fLog << err << "ERROR - Couldn't open file " << oname << " for writing..." << endl;
514 return kFALSE;
515 }
516
517 return WriteContainer(cont);
518}
519
520//------------------------------------------------------------------------
521//
522// return kTRUE if no display is set.
523//
524// Write the display to the TFile with name name, options option and
525// compression level comp.
526//
527// If name IsNull fPathOut is assumed to contain the name, otherwise
528// name is appended to fPathOut. fPathOut might be null.
529//
530Bool_t MJob::WriteDisplay(const char *name, const char *option, const int compr) const
531{
532 if (!fDisplay)
533 return kTRUE;
534
535 TObjArray arr;
536 arr.Add((TObject*)(fDisplay));
537 return WriteContainer(arr, name, option, compr);
538}
539
540TString MJob::ExpandPath(TString fname)
541{
542 // empty
543 if (fname.IsNull())
544 return "";
545
546 // Expand path using environment
547 gSystem->ExpandPathName(fname);
548
549 // Absolute path
550 if (fname[0]=='/')
551 {
552 gLog << dbg << "MJob::ExpandPath - Path " << fname << " is absolute." << endl;
553 return fname;
554 }
555
556 // relative path to file and file could be found
557 if (!gSystem->AccessPathName(fname, kFileExists))
558 {
559 gLog << dbg << "MJob::ExpandPath - Relative path " << fname << " found..." << endl;
560 return fname;
561 }
562
563 // Now check gEnv and MARSSYS. gEnv can overwrite MARSSYS
564 TString path(gEnv ? gEnv->GetValue("Mars.Path", "$MARSSYS") : "$MARSSYS");
565
566 // Expand path using environment
567 gSystem->ExpandPathName(path);
568
569 // check if path ends with a slash
570 path = CombinePath(path, fname);
571
572 gLog << dbg << "MJob::ExpandPath - Filename expanded to " << path << endl;
573
574 // return new path
575 return path;
576}
577
578//------------------------------------------------------------------------
579//
580// Sorts the array.
581//
582void MJob::SortArray(TArrayI &arr)
583{
584 TArrayI idx(arr.GetSize());
585 TArrayI srt(arr);
586
587 TMath::Sort(arr.GetSize(), srt.GetArray(), idx.GetArray(), kFALSE);
588
589 for (int i=0; i<arr.GetSize(); i++)
590 arr[i] = srt[idx[i]];
591}
Note: See TracBrowser for help on using the repository browser.