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

Last change on this file since 9244 was 9244, checked in by tbretz, 16 years ago
*** empty log message ***
File size: 15.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, 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//
276Bool_t MJob::InitRandomNumberGenerator() const
277{
278 const TString rng = GetEnv("RandomNumberGenerator", "");
279 if (!rng.IsNull())
280 {
281 TClass *cls = MParContainer::GetClass(rng, &gLog);
282 if (!cls)
283 return kFALSE;
284
285 if (!cls->InheritsFrom(TRandom::Class()))
286 {
287 *fLog << err << "ERROR - RandomNumberGenerator " << rng << " doesn't inherit from TRandom." << endl;
288 return kFALSE;
289 }
290
291 delete gRandom;
292 gRandom = static_cast<TRandom*>(cls->New());
293
294 *fLog << inf << "Random number generator " << rng << " initialized." << endl;
295 }
296
297 // Nothing: Keep seed value, 0 set time as seed value, val set seed
298 const TString seed = GetEnv("RandomNumberSeedNumber", "");
299 if (!seed.IsNull())
300 {
301 gRandom->SetSeed(seed.Atoi());
302 *fLog << inf << "Random number seed value set to " << seed.Atoi() << endl;
303 }
304
305 return kTRUE;
306}
307
308//------------------------------------------------------------------------
309//
310// Check the resource file for
311// PathOut
312// PathIn
313// MaxEvents
314// Overwrite
315// EnvDebug
316// RandomNumberGenerator
317// RandomNumberSeedValue
318//
319// and call the virtual function CheckEnvLocal
320//
321Bool_t MJob::CheckEnv()
322{
323 if (!fEnv)
324 return kTRUE;
325
326 if (!InitRandomNumberGenerator())
327 return kFALSE;
328
329 TString p;
330 p = GetEnv("PathOut", "");
331 if (!p.IsNull())
332 SetPathOut(p);
333
334 p = GetEnv("PathIn", "");
335 if (!p.IsNull())
336 SetPathIn(p);
337
338 SetMaxEvents(GetEnv("MaxEvents", fMaxEvents));
339 SetOverwrite(GetEnv("Overwrite", fOverwrite));
340 SetEnvDebug( GetEnv("EnvDebug", fEnvDebug));
341
342 return CheckEnvLocal();
343}
344
345//------------------------------------------------------------------------
346//
347// Returns the result of c.ReadEnv(*fEnv, fEnvPrefix, fEnvDebug>2)
348// By adding the container first to a MParList it is ensured that
349// all levels are checked.
350//
351Bool_t MJob::CheckEnv(MParContainer &c) const
352{
353 if (!fEnv)
354 return kTRUE;
355
356 // Make sure that all levels are checked
357 MParList l;
358 l.AddToList(&c);
359 return l.ReadEnv(*fEnv, fEnvPrefix+".", fEnvDebug>2);
360}
361
362//------------------------------------------------------------------------
363//
364// Call the eventsloops ReadEnv and print untouched resources afterwards
365// if fEnvDebug>1
366//
367Bool_t MJob::SetupEnv(MEvtLoop &loop) const
368{
369 if (!fEnv)
370 return kTRUE;
371
372 if (!loop.ReadEnv(*fEnv, fEnvPrefix, fEnvDebug>2))
373 return kFALSE;
374
375 if (fEnvDebug>1)
376 fEnv->PrintUntouched();
377
378 return kTRUE;
379}
380
381//------------------------------------------------------------------------
382//
383// Checks whether write permissions to fname exists including
384// the fOverwrite data member. Empty file names return kTRUE
385//
386Bool_t MJob::HasWritePermission(TString fname) const
387{
388 gSystem->ExpandPathName(fname);
389
390 const Bool_t exists = !gSystem->AccessPathName(fname, kFileExists);
391 if (!exists)
392 return kTRUE;
393
394 const Bool_t write = !gSystem->AccessPathName(fname, kWritePermission);
395 if (!write)
396 {
397 *fLog << err << "ERROR - No permission to write to " << fname << endl;
398 return kFALSE;
399 }
400
401 if (fOverwrite)
402 return kTRUE;
403
404 *fLog << err;
405 *fLog << "ERROR - File " << fname << " already exists and overwrite not allowed." << endl;
406
407 return kFALSE;
408}
409
410//------------------------------------------------------------------------
411//
412// Write containers in list to gFile. Returns kFALSE if no gFile or any
413// container couldn't be written. kTRUE otherwise.
414//
415Bool_t MJob::WriteContainer(TCollection &list) const
416{
417 if (!gFile)
418 {
419 *fLog << err << dbginf << "ERROR - No file open (gFile==0)" << endl;
420 return kFALSE;
421 }
422
423 TIter Next(&list);
424 TObject *o=0;
425 while ((o=Next()))
426 {
427 *fLog << inf << " - Writing " << MParContainer::GetDescriptor(*o) << "..." << flush;
428 if (o->Write(o->GetName())<=0)
429 {
430 *fLog << err << dbginf << "ERROR - Writing " << MParContainer::GetDescriptor(*o) << " to file " << gFile->GetName() << endl;
431 return kFALSE;
432 }
433 *fLog << "ok." << endl;
434 }
435 return kTRUE;
436}
437
438//------------------------------------------------------------------------
439//
440// Read containers in list into list from gFile
441// Returns kFALSE if no gFile or any container couldn't be read.
442//
443Bool_t MJob::ReadContainer(TCollection &list) const
444{
445 if (!gFile)
446 {
447 *fLog << err << dbginf << "ERROR - No file open (gFile==0)" << endl;
448 return kFALSE;
449 }
450
451 MIter Next(&list);
452 MParContainer *o=0;
453 while ((o=Next()))
454 {
455 *fLog << inf << " - Reading " << o->GetDescriptor() << "..." << flush;
456 if (o->Read(o->GetName())<=0)
457 {
458 *fLog << err << dbginf << "ERROR - Reading " << o->GetDescriptor() << " from file " << gFile->GetName() << endl;
459 return kFALSE;
460 }
461 *fLog << "ok." << endl;
462 }
463 return kTRUE;
464}
465
466//------------------------------------------------------------------------
467//
468// Write containers in cont to fPathOut+"/"+name, or fPathOut only
469// if name is empty.
470//
471Bool_t MJob::WriteContainer(TCollection &cont, const char *name, const char *option, const int compr) const
472{
473 if (fPathOut.IsNull())
474 {
475 *fLog << inf << "No output path specified via SetPathOut - no output written." << endl;
476 return kTRUE;
477 }
478
479 const TString oname = CombinePath(fPathOut, name);
480
481 *fLog << inf << "Writing to file: " << oname << endl;
482
483 TString title("File written by ");
484 title += fName;
485
486 // In case the update-option is selected check whether
487 // the file is already open
488 if (TString(option).Contains("update", TString::kIgnoreCase))
489 {
490 TFile *file = dynamic_cast<TFile*>(gROOT->GetListOfFiles()->FindObject(oname));
491 if (file && file->IsOpen() && !file->IsZombie())
492 {
493 *fLog << inf << "Open file found." << endl;
494 file->cd();
495 return WriteContainer(cont);
496 }
497 }
498
499 // Open a new file with the defined option for writing
500 TFile file(oname, option, title, compr);
501 if (!file.IsOpen() || file.IsZombie())
502 {
503 *fLog << err << "ERROR - Couldn't open file " << oname << " for writing..." << endl;
504 return kFALSE;
505 }
506
507 return WriteContainer(cont);
508}
509
510//------------------------------------------------------------------------
511//
512// return kTRUE if no display is set.
513//
514// Write the display to the TFile with name name, options option and
515// compression level comp.
516//
517// If name IsNull fPathOut is assumed to contain the name, otherwise
518// name is appended to fPathOut. fPathOut might be null.
519//
520Bool_t MJob::WriteDisplay(const char *name, const char *option, const int compr) const
521{
522 if (!fDisplay)
523 return kTRUE;
524
525 TObjArray arr;
526 arr.Add((TObject*)(fDisplay));
527 return WriteContainer(arr, name, option, compr);
528}
529
530TString MJob::ExpandPath(TString fname)
531{
532 // empty
533 if (fname.IsNull())
534 return "";
535
536 // Expand path using environment
537 gSystem->ExpandPathName(fname);
538
539 // Absolute path
540 if (fname[0]=='/')
541 {
542 gLog << dbg << "MJob::ExpandPath - Path " << fname << " is absolute." << endl;
543 return fname;
544 }
545
546 // relative path to file and file could be found
547 if (!gSystem->AccessPathName(fname, kFileExists))
548 {
549 gLog << dbg << "MJob::ExpandPath - Relative path " << fname << " found..." << endl;
550 return fname;
551 }
552
553 // Now check gEnv and MARSSYS. gEnv can overwrite MARSSYS
554 TString path(gEnv ? gEnv->GetValue("Mars.Path", "$MARSSYS") : "$MARSSYS");
555
556 // Expand path using environment
557 gSystem->ExpandPathName(path);
558
559 // check if path ends with a slash
560 path = CombinePath(path, fname);
561
562 gLog << dbg << "MJob::ExpandPath - Filename expanded to " << path << endl;
563
564 // return new path
565 return path;
566}
567
568//------------------------------------------------------------------------
569//
570// Sorts the array.
571//
572void MJob::SortArray(TArrayI &arr)
573{
574 TArrayI idx(arr.GetSize());
575 TArrayI srt(arr);
576
577 TMath::Sort(arr.GetSize(), srt.GetArray(), idx.GetArray(), kFALSE);
578
579 for (int i=0; i<arr.GetSize(); i++)
580 arr[i] = srt[idx[i]];
581}
Note: See TracBrowser for help on using the repository browser.