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

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