source: trunk/MagicSoft/Mars/mjobs/MDataSet.cc@ 7388

Last change on this file since 7388 was 7380, checked in by tbretz, 19 years ago
*** empty log message ***
File size: 14.7 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, 1/2005 <mailto:tbretz@astro.uni-wuerzburg.de>
19!
20! Copyright: MAGIC Software Development, 2004-2005
21!
22!
23\* ======================================================================== */
24
25/////////////////////////////////////////////////////////////////////////////
26//
27// MDataSet
28//
29// This class describes a collection of sequences.
30//
31// Such an input file looks like:
32//
33// crab.seq:
34// ---------
35// AnalysisNumber: 1
36//
37// SequencesOn: 35222
38// SequencesOff: 36817
39//
40// Sequence00035222.File: sequences/sequence035222.txt
41// Sequence00036817.File: sequences/sequence036817.txt
42//
43// Sequence00035222.Dir: /data2/wuerzburg/Crab-Analyse/images/035222
44// Sequence00036817.Dir: /data2/wuerzburg/Crab-Analyse/images/036817
45//
46// The analysis number is an artifical number used to name the output
47// files automatically if the names are not overwritten in the corresponding
48// programs.
49//
50// The sequence number are used to concatenate the filenames of the
51// sequences using the file structure used in the datacenter. Each sequence
52// can be added to the on and off data at the same time but only once.
53//
54// If you have different file names you can overwrite the default file names
55// using Sequence%08d.File (make sure you have 8 digits!)
56//
57// In standard coditions (datacenter file system) paths are concatenated
58// by using the information in the sequence files (date, etc). You can
59// overwrite the directories in which the sequence-files (eg I-files) are
60// stored using Sequence%08d.Dir (make sure you have 8 digits!)
61//
62// Resource file entries are case sensitive!
63//
64// IMPORTANT:
65// * Run filenames must begin with a string which allows correct
66// ordering in time, otherwise synchronization might fail.
67// * Sequence filenames should also have names allowing to order them
68// in time, but it is not necessary.
69//
70// MISSING (27/01/04): The default name and paths cannot be used yet, because
71// they have to be defined soon.
72//
73/////////////////////////////////////////////////////////////////////////////
74#include "MDataSet.h"
75
76#include <stdlib.h>
77#include <fstream>
78
79#include <TEnv.h>
80#include <TChain.h>
81#include <TRegexp.h>
82#include <TSystem.h> // TSystem::ExpandPath
83
84#include "MLog.h"
85#include "MLogManip.h"
86
87#include "MRead.h"
88#include "MJob.h"
89#include "MAstro.h"
90#include "MDirIter.h"
91#include "MSequence.h"
92#include "MPointingPos.h"
93
94ClassImp(MDataSet);
95
96using namespace std;
97
98const TString MDataSet::fgCatalog = "/magic/datacenter/setup/magic_favorites.edb";
99const TString MDataSet::fgPathDataFiles = "/magic/data/star";
100const TString MDataSet::fgPathSequences = "/magic/sequences";
101
102// --------------------------------------------------------------------------
103//
104// Copy the sequence numbers from the TString runs into the TArrayI data
105// Sequences which are twice in the list are only added once. In this case
106// a warning is emitted.
107//
108void MDataSet::Split(TString &runs, TArrayI &data) const
109{
110 const TRegexp regexp("[0-9]+");
111
112 data.Set(0);
113 runs = runs.Strip(TString::kTrailing);
114
115 while (!runs.IsNull())
116 {
117 const TString num = runs(regexp);
118
119 if (num.IsNull())
120 {
121 *fLog << warn << "WARNING - Sequence is NaN (not a number): " << runs << endl;
122 break;
123 }
124
125 const Int_t seq = atoi(num.Data());
126 const Int_t n = data.GetSize();
127
128 // skip already existing entries
129 int i;
130 for (i=0; i<n; i++)
131 if (data[i] == seq)
132 break;
133
134 if (i<n)
135 *fLog << warn << "WARNING - Sequence #" << seq << " already in list... skipped." << endl;
136 else
137 {
138 // set new entry
139 data.Set(n+1);
140 data[n] = seq;
141 }
142
143 // remove entry from string
144 runs.Remove(0, runs.First(num)+num.Length());
145 }
146
147 MJob::SortArray(data);
148}
149
150// --------------------------------------------------------------------------
151//
152// After resolving the sequence filename and directory either from the
153// default (/magic/data/sequences/0004/sequence00004000.txt) or from
154// the corresponding entries in the dataset file.
155// The entries are sorted by filename.
156//
157void MDataSet::ResolveSequences(TEnv &env, const TArrayI &num, TList &list, const TString &sequences, const TString &data) const
158{
159 for (int i=0; i<num.GetSize(); i++)
160 {
161 TString name = env.GetValue(Form("Sequence%08d.File", num[i]), "");
162 TString dir = env.GetValue(Form("Sequence%08d.Dir", num[i]), "");
163
164 // Set default sequence file and dir name
165 if (name.IsNull())
166 name = Form("%s%04d/sequence%08d.txt", sequences.Data(), num[i]/10000, num[i]);
167 if (dir.IsNull())
168 dir = Form("%s%04d/%08d", data.Data(), num[i]/10000, num[i]);
169
170 gSystem->ExpandPathName(name);
171 gSystem->ExpandPathName(dir);
172
173 if (gSystem->AccessPathName(name, kFileExists))
174 gLog << warn << "WARNING - Sequence file '" << name << "' doesn't exist." << endl;
175
176 if (gSystem->AccessPathName(dir, kFileExists))
177 gLog << warn << "WARNING - Directory '" << dir << "' doesn't exist." << endl;
178
179 list.Add(new TNamed(name, dir));
180 }
181
182 // For the synchronization we must make sure, that all sequences are
183 // in the correct order...
184 // list.Sort();
185}
186
187// --------------------------------------------------------------------------
188//
189// Read the file fname as setup file for the sequence.
190//
191MDataSet::MDataSet(const char *fname, TString sequences, TString data)
192{
193 fName = fname;
194
195 const char *expname = gSystem->ExpandPathName(fname);
196
197 fTitle = Form("Dataset contained in file %s", expname);
198
199 const Bool_t access = !gSystem->AccessPathName(expname, kFileExists);
200 if (!access)
201 gLog << err << "ERROR - Dataset file " << expname << " not accessible!" << endl;
202
203 TEnv env(expname);
204 delete [] expname;
205
206 fNumAnalysis = env.GetValue("AnalysisNumber", -1);
207
208 TString str;
209 str = env.GetValue("SequencesOn", "");
210 Split(str, fNumSequencesOn);
211 str = env.GetValue("SequencesOff", "");
212 Split(str, fNumSequencesOff);
213
214 SetupDefaultPath(sequences, fgPathSequences);
215 SetupDefaultPath(data, fgPathDataFiles);
216
217 ResolveSequences(env, fNumSequencesOn, fSequencesOn, sequences, data);
218 ResolveSequences(env, fNumSequencesOff, fSequencesOff, sequences, data);
219
220 fNameSource = env.GetValue("SourceName", "");
221 fCatalog = env.GetValue("Catalog", fgCatalog);
222 fIsWobbleMode = env.GetValue("WobbleMode", kFALSE);
223 fComment = env.GetValue("Comment", "");
224}
225
226// --------------------------------------------------------------------------
227//
228// Return '+' if both can be accessed, '-' otherwise.
229//
230void MDataSet::PrintFile(const TObject &obj)
231{
232 const Char_t access =
233 !gSystem->AccessPathName(obj.GetName(), kFileExists) &&
234 !gSystem->AccessPathName(obj.GetTitle(), kFileExists) ? '+' : '-';
235
236 gLog << " " << access << " " << obj.GetName() << " <" << obj.GetTitle() << ">" << endl;
237}
238
239// --------------------------------------------------------------------------
240//
241// Print the contents of the sequence
242//
243void MDataSet::Print(Option_t *o) const
244{
245 gLog << all;
246 if (!IsValid())
247 {
248 gLog << "Dataset: " << fName << " <invalid>" << endl;
249 return;
250 }
251 gLog << "AnalysisNumber: " << fNumAnalysis << endl << endl;
252 gLog << "SequencesOn: ";
253 for (int i=0; i<fNumSequencesOn.GetSize(); i++)
254 gLog << " " << fNumSequencesOn[i];
255 gLog << endl;
256 gLog << "SequencesOff: ";
257 for (int i=0; i<fNumSequencesOff.GetSize(); i++)
258 gLog << " " << fNumSequencesOff[i];
259 gLog << endl << endl;
260
261 gLog << "SourceName: " << fNameSource << endl;
262 gLog << "Catalog: " << fCatalog << endl;
263
264 gLog << "WobbleMode: " << (fIsWobbleMode?"On":"Off") << endl << endl;
265
266 gLog << "Comment: " << fComment << endl;
267
268 if (TString(o).Contains("files", TString::kIgnoreCase))
269 {
270 TObject *obj=0;
271
272 gLog << endl;
273 gLog << "On-Data Files:" << endl;
274 TIter NextOn(&fSequencesOn);
275 while ((obj=NextOn()))
276 PrintFile(*obj);
277
278 gLog << endl;
279 gLog << "Off-Data Files:" << endl;
280 TIter NextOff(&fSequencesOff);
281 while ((obj=NextOff()))
282 PrintFile(*obj);
283
284 return;
285 }
286}
287
288// --------------------------------------------------------------------------
289//
290// Adds all sequences contained in list to the MDirIter. After adding
291// everything MDirIter::Sort is called to sort all entries by name.
292//
293Bool_t MDataSet::AddSequencesFromList(const TList &list, MDirIter &files)
294{
295 TIter Next(const_cast<TList*>(&list));
296 TObject *o=0;
297 while ((o=Next()))
298 {
299 MSequence seq(o->GetName());
300 if (!seq.IsValid())
301 {
302 gLog << warn << "WARNING - Sequence " << o->GetName() << " invalid!" << endl;
303 return kFALSE;
304 }
305
306 const TString dir(o->GetTitle());
307 seq.SetupDatRuns(files, MSequence::kImages, dir.IsNull() ? 0 : dir.Data());
308 }
309
310 // This is important in case of synchronisation, because the
311 // files in the sequences can be interleaved (eg W1, W2)
312 // Filenames MUST begin with an appropriate string which allow
313 // to order them correctly in time!
314 // files.Sort();
315
316 if (gLog.GetDebugLevel()>4)
317 {
318 gLog << dbg << "Files which are searched:" << endl;
319 files.Print();
320 }
321 return kTRUE;
322}
323
324Bool_t MDataSet::AddFilesOn(MRead &read) const
325{
326 MDirIter files;
327 if (!AddSequencesFromList(fSequencesOn, files))
328 return kFALSE;
329 return read.AddFiles(files)>0;
330}
331
332Bool_t MDataSet::AddFilesOff(MRead &read) const
333{
334 MDirIter files;
335 if (!AddSequencesFromList(fSequencesOff, files))
336 return kFALSE;
337 return read.AddFiles(files)>0;
338}
339
340Bool_t MDataSet::AddFiles(MRead &read) const
341{
342 const Bool_t rc1 = AddFilesOff(read);
343 const Bool_t rc2 = AddFilesOn(read);
344 return rc1 && rc2;
345}
346
347Int_t MDataSet::AddFilesToChain(MDirIter &files, TChain &chain)
348{
349 Int_t num=0;
350 while (1)
351 {
352 const TString fname = files.Next();
353 if (fname.IsNull())
354 break;
355
356 const Int_t n = chain.Add(fname);
357 if (n<=0)
358 return kFALSE;
359 num += n;
360 }
361 return num;
362}
363
364Bool_t MDataSet::AddFilesOn(TChain &chain) const
365{
366 MDirIter files;
367 if (!AddSequencesFromList(fSequencesOn, files))
368 return kFALSE;
369 return AddFilesToChain(files, chain)>0;
370}
371
372Bool_t MDataSet::AddFilesOff(TChain &chain) const
373{
374 MDirIter files;
375 if (!AddSequencesFromList(fSequencesOff, files))
376 return kFALSE;
377 return AddFilesToChain(files, chain)>0;
378}
379
380Bool_t MDataSet::AddFiles(TChain &read) const
381{
382 const Bool_t rc1 = AddFilesOff(read);
383 const Bool_t rc2 = AddFilesOn(read);
384 return rc1 && rc2;
385}
386
387Bool_t MDataSet::GetSourcePos(MPointingPos &pos) const
388{
389 if (!HasSource())
390 {
391 gLog << err << "ERROR - MDataSet::GetSourcePos called, but no source available." << endl;
392 return kFALSE;
393 }
394
395 TString catalog(fCatalog);
396 gSystem->ExpandPathName(catalog);
397
398 ifstream fin(catalog);
399 if (!fin)
400 {
401 gLog << err << "Cannot open file " << catalog << ": ";
402 gLog << strerror(errno) << endl;
403 return kFALSE;
404 }
405
406 TString ra, dec, epoch;
407
408 Int_t n = 0;
409 while (1)
410 {
411 TString line;
412 line.ReadLine(fin);
413 if (!fin)
414 break;
415
416 n++;
417
418 // Strip all spaces from line
419 for (int i=0; i<line.Length(); i++)
420 if (line[i]==' ')
421 line.Remove(i--, 1);
422
423 if (fNameSource!=line(0, fNameSource.Length()))
424 continue;
425
426 // CrabNebula,f|L|K0,5:34:32.0,22:0:52,-1.0,2000
427
428 for (int i=0; i<6; i++)
429 {
430 const Ssiz_t p = line.First(',');
431 if (p<0 && i<5)
432 {
433 gLog << err << "ERROR - Not enough arguments in line #" << n << " of " << catalog << endl;
434 return kFALSE;;
435 }
436
437 switch (i)
438 {
439 case 0:
440 case 1:
441 case 4:
442 break;
443 case 2:
444 ra = line(0, p);
445 break;
446 case 3:
447 dec = line(0, p);
448 break;
449 case 5:
450 epoch = line;
451 break;
452 }
453 line.Remove(0, p+1);
454 }
455
456 if (line.First(',')>=0)
457 {
458 gLog << err << "ERROR - Too much arguments in line #" << n << " of " << catalog << endl;
459 return kFALSE;
460 }
461
462 break;
463 }
464
465 if (epoch.IsNull())
466 {
467 gLog << err << "ERROR - No entry " << fNameSource << " in " << catalog << endl;
468 return kFALSE;
469 }
470
471 if (epoch!=(TString)"2000")
472 {
473 gLog << err << "ERROR - Epoch not 2000... not supported." << endl;
474 return kFALSE;
475 }
476
477 Double_t r,d;
478 if (!MAstro::Coordinate2Angle(ra, r))
479 {
480 gLog << err << "ERROR - Interpreting right ascension: " << ra << endl;
481 return kFALSE;
482 }
483 if (!MAstro::Coordinate2Angle(dec, d))
484 {
485 gLog << err << "ERROR - Interpreting declination: " << dec << endl;
486 return kFALSE;
487 }
488
489 pos.SetSkyPosition(r, d);
490 pos.SetTitle(fNameSource);
491
492 return kTRUE;
493}
494
495// --------------------------------------------------------------------------
496//
497// Calls ReplaceAll(old, news) for all Dir-entries
498//
499void MDataSet::ReplaceDir(TList &list, const TString &old, const TString &news) const
500{
501 TIter Next(&list);
502 TNamed *name = 0;
503 while ((name=(TNamed*)Next()))
504 {
505 TString dir = name->GetTitle();
506 dir.ReplaceAll(old, news);
507 name->SetTitle(dir);
508 }
509}
510
511// --------------------------------------------------------------------------
512//
513// Calls ReplaceAll(old, news) for all File-entries
514//
515void MDataSet::ReplaceFile(TList &list, const TString &old, const TString &news) const
516{
517 TIter Next(&list);
518 TNamed *name = 0;
519 while ((name=(TNamed*)Next()))
520 {
521 TString file = name->GetName();
522 file.ReplaceAll(old, news);
523 name->SetName(file);
524 }
525}
Note: See TracBrowser for help on using the repository browser.