source: trunk/MagicSoft/Mars/mjobs/MSequence.cc@ 8996

Last change on this file since 8996 was 8996, checked in by tbretz, 16 years ago
*** empty log message ***
File size: 35.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, 8/2004 <mailto:tbretz@astro.uni-wuerzburg.de>
19!
20! Copyright: MAGIC Software Development, 2004-2008
21!
22!
23\* ======================================================================== */
24
25/////////////////////////////////////////////////////////////////////////////
26//
27// MSequence
28//
29// This class describes a sequence. For sequences see:
30// http://db.astro.uni-wuerzburg.de
31//
32// A sequence is a collection of runs which should be used together.
33// Any run can be contained only once.
34//
35// Here is an example how a file describing a sequence could look like.
36//
37// Reading the file is based on TEnv. For more details see also
38// the class reference of TEnv.
39//
40// ===========================================================================
41//
42// sequence.txt
43// ------------
44//
45// # Sequence number (identifier) - necessary if the path
46// # contains the sequence number, e.g. image files
47// Sequence: 31015
48//
49// # Observation Period (not needed)
50// Period: 18
51//
52// # Date of sunrise of the observation night - necessary if the path
53// # contains the date, e.g. raw data
54// Night: 2004-06-24
55//
56// # Start time of the sequence (first data run, not needed)
57// Start: 2004-06-24 03:12:42
58//
59// # Run number of last data run in sequence (not needed)
60// LastRun: 31032
61//
62// # Project name of data-runs of sequence (not needed)
63// Project: 3EG2033+41
64//
65// # Source name of all runs of sequence (not needed)
66// Source: 3EG2033+41
67//
68// # Trigger table of data-runs of sequence (not needed)
69// TriggerTable: L1_4NN:L2_DEFAULT
70//
71// # HV Setting table of data-runs of sequence (not needed)
72// HvSettings: HVSettings_FF36q
73//
74// # Total number of data-events in sequence (not needed)
75// NumEvents: 250914
76//
77// # Whether this is MC data or not (necessary in case of MCs if
78// # default paths should be used)
79// MonteCarlo: Yes
80//
81// # List of all runs of this sequence (not needed)
82// Runs: 31015:31017 31018 31019.0 31019.3 31019.5:7 31020+ 31021::3
83//
84// # List of all calibration runs of this sequence (necessary if accessed)
85// CalRuns: 31015 31016 31017
86// # List of pedestal runs belonging to the calibration runs of this sequence (necessary if accessed)
87// PedRuns: 31018
88// # List of all data runs belonging to this sequence (necessary)
89// DatRuns: 31019.0 31019.3 31019:5:7 31020+ 31021::3
90//
91// Run00031020: :3 7:9 15
92//
93// # Just for fun ;-) (not needed, but helpful)
94// Comment: This is a template for a sequence file
95//
96// ===========================================================================
97//
98// Runs are devided into file since run 1000000. These Run-/Filenumbers
99// are given by a dot. X.Y means Run X, File Y.
100//
101// In the Runs, CalRuns, PedRuns and DatRuns tag you can use
102// several abbreviationa:
103//
104// 31015:31017 means 31015.0 31016.0 31017.0
105// 31018 means 31018.0
106// 31019.3 means 31019.3
107// 31019.5:7 means 31019.5 31019.6 31019.7
108// 31020+ means file list for run 21020 given below
109// 31021::3 means 31021.0 31021.1 31021.2 31021.3
110//
111// For the run-list defined above (note the number must have 8 digits,
112// for example 'Run00031020') you can also use abbreviations:
113//
114// :3 means 0 1 2 3
115// 7:9 means 7 8 9
116//
117// ===========================================================================
118//
119// For special cases you can also setup a sequence directly from a macro,
120// for example:
121//
122// MDirIter pediter, datiter, caliter;
123//
124// MSequence seq;
125// seq.SetNight("2004-07-06");
126// seq.AddRun(31751, 'P');
127// seq.AddRun(31752, 'C');
128// seq.AddRuns(31753, 31764, 'D');
129// seq.SetupPedRuns(pediter);
130// seq.SetupCalRuns(caliter);
131// seq.SetupDatRuns(datiter);
132//
133// or
134//
135// MDirIter iter;
136//
137// MSequence seq;
138// seq.SetNight("2004-07-06");
139// seq.AddFiles(31753, 0, 120);
140// seq.SetupRuns(iter);
141// seq.SetupPedRuns(iter, "/mypath", "[DPC]");
142//
143//
144// ===========================================================================
145//
146// ToDO:
147// * Default paths could be moved into the global .rootrc
148//
149// ===========================================================================
150//
151//
152// Class Version 2:
153// ----------------
154// + fMonteCarlo
155//
156// Class Version 3:
157// ----------------
158// + fComment
159//
160// Class Version 4:
161// ----------------
162// + fExclRuns
163//
164// Class Version 5:
165// ----------------
166// + fRunsSub
167// + fDatRunsSub
168// + fPedRunsSub
169// + fCalRunsSub
170// + fExclRunsSub
171//
172/////////////////////////////////////////////////////////////////////////////
173#include "MSequenceSQL.h"
174
175#include <stdlib.h>
176#include <errno.h>
177
178#include <fstream>
179
180#include <TEnv.h>
181#include <TPRegexp.h>
182#include <TSystem.h> // TSystem::ExpandPath
183
184#include "MLog.h"
185#include "MLogManip.h"
186
187#include "MEnv.h"
188#include "MJob.h"
189#include "MAstro.h"
190#include "MString.h"
191#include "MDirIter.h"
192
193ClassImp(MSequence);
194
195using namespace std;
196
197// --------------------------------------------------------------------------
198//
199// This adds an run/file entry to the data/sub arrays. If it is already
200// contained a waring is printed.
201//
202void MSequence::AddEntry(Int_t run, Int_t file, TArrayI &data, TArrayI &sub) const
203{
204 const Int_t n = data.GetSize();
205
206 // skip already existing entries
207 if (IsContained(data, sub, run, file))
208 {
209 *fLog << warn << "WARNING - File " << run << "." << file << " already in list... skipped." << endl;
210 return;
211 }
212
213 if (run<1000000 && file>0)
214 *fLog << warn << "WARNING - Run number " << run << "<" << "1,000,000 but file " << file << ">0..." << endl;
215
216 // set new entry
217 data.Set(n+1);
218 sub.Set(n+1);
219
220 data[n] = run;
221 sub[n] = file;
222}
223
224// --------------------------------------------------------------------------
225//
226// Evaluate a token in thr Run string. Add the coresponding run/files
227// with AddEntry
228//
229void MSequence::EvalEntry(const TEnv *env, const TString &prefix, const TString &num, TArrayI &data, TArrayI &sub) const
230{
231 // Split entry into run and file
232 const Int_t run = num.Atoi();
233
234 // Syntax error forbidden by construction
235 const Ssiz_t p1 = num.First('.');
236 const Ssiz_t p2 = num.Last(':');
237
238 // ---------------------------------------------------------------
239
240 const Int_t n1 = atoi(num.Data()+p1+1);
241 const Int_t n2 = atoi(num.Data()+p2+1);
242
243 // ---------------------------------------------------------------
244 // p1>=0 && p2<0 (. but no :) run.n1 run.file1
245 if (p1>=0 && p2<0)
246 {
247 AddEntry(run, n1, data, sub);
248 return;
249 }
250
251 // ---------------------------------------------------------------
252 // p1>=0 && p2>=0 (. and :) run:n1:n2 run.file1-run.file2
253 if (p1>=0 && p2>=0)
254 {
255 if (n2<n1)
256 {
257 *fLog << warn << "WARNING - Invalid range '" << num << "'... ignored." << endl;
258 return;
259 }
260
261 for (int i=n1; i<=n2; i++)
262 AddEntry(run, i, data, sub);
263 return;
264 }
265
266 // ---------------------------------------------------------------
267 // p1<0 && p2>=0 (no . but :) n1:n2 run1-run2
268 if (p1<0 && p2>=0)
269 {
270 if (n2<run)
271 {
272 *fLog << warn << "WARNING - Invalid range in '" << num << "'... ignored." << endl;
273 return;
274 }
275
276 for (int i=run; i<=n2; i++)
277 AddEntry(i, 0, data, sub);
278 return;
279 }
280
281 // ---------------------------------------------------------------
282 // p0<0 and p1<0 (no . and no :) run run
283
284 if (!num.EndsWith("+"))
285 {
286 AddEntry(run, 0, data, sub);
287 return;
288 }
289
290 if (!env)
291 return;
292
293 TPRegexp regexp("([0-9]*:[0-9]+|[0-9]+(:[0-9]*)?)( +|$)");
294
295 TString files = GetEnvValue2(*env, prefix, Form("Run%08d", run), "");
296 if (files.IsNull())
297 {
298 AddEntry(run, 0, data, sub);
299 return;
300 }
301
302 while (!files.IsNull())
303 {
304 const TString num = files(regexp);
305 if (num.IsNull())
306 {
307 *fLog << warn << "WARNING - File in run " << run << " is NaN (not a number): '" << files << "'" << endl;
308 break;
309 }
310
311 const Ssiz_t p1 = num.First(':');
312 if (p1>=0)
313 {
314 const Int_t n1 = atoi(num.Data());
315 const Int_t n2 = atoi(num.Data()+p1+1);
316
317 if (n2<n1)
318 {
319 *fLog << warn << "WARNING - Invalid range in '" << num << "'... ignored." << endl;
320 return;
321 }
322
323 // FIXME: n2==0 || n2<n1
324 for (int i=n1; i<=n2; i++)
325 AddEntry(run, i, data, sub);
326 }
327 else
328 {
329 const Int_t file = atoi(num.Data());
330 AddEntry(run, file, data, sub);
331 }
332
333 files.Remove(0, files.First(num)+num.Length());
334 }
335}
336
337// --------------------------------------------------------------------------
338//
339// Interprete the TString and add the run/files to the arrays.
340// Run/files which are twice in the list are only added once. In this case
341// a warning is emitted.
342//
343void MSequence::Split(TString &runs, TArrayI &data, TArrayI &sub, const TEnv *env, const TString prefix) const
344{
345 TPRegexp regexp("^[0-9]+([+]|(:|[.]([0-9]*:)?)[0-9]+)?( +|$)");
346
347 data.Set(0);
348 sub.Set(0);
349
350 runs.ReplaceAll("\t", " ");
351 runs = runs.Strip(TString::kBoth);
352
353 while (!runs.IsNull())
354 {
355 const TString num = runs(regexp);
356 if (num.IsNull())
357 {
358 *fLog << warn << "WARNING - Run syntax error: '" << runs << "'" << endl;
359 break;
360 }
361
362 EvalEntry(env, prefix, num.Strip(TString::kTrailing), data, sub);
363
364 runs.Remove(0, runs.First(num)+num.Length());
365 }
366
367 SortArrays(data, sub);
368}
369
370// --------------------------------------------------------------------------
371//
372// Get the String from the TEnv file prefixed by prefix-name.
373// Intepret the string using Split which adds the run/files to the arrays.
374//
375void MSequence::Split(const TEnv &env, const TString &prefix, const char *name, TArrayI &data, TArrayI &sub) const
376{
377 TString str = GetEnvValue2(env, prefix, name, "");
378 Split(str, data, sub, &env, prefix);
379}
380
381// --------------------------------------------------------------------------
382//
383// Compile path from the given path name and expand it. If it IsNull()
384// the path is compiled as standard path from tha datacenter). The
385// returned path will end with a "/".
386//
387TString MSequence::GetPathName(TString d, FileType_t type) const
388{
389 // Setup path
390 if (d.IsNull())
391 {
392 d = GetStandardPath();
393 switch (type)
394 {
395 case kRawDat: // rawdata
396 case kRawPed:
397 case kRawCal:
398 case kRawAll:
399 case kRootDat: // mcdata
400 case kRootPed:
401 case kRootCal:
402 case kRootAll:
403 d += "rawfiles/";
404 d += fNight.GetStringFmt("%Y/%m/%d");
405 break;
406 case kCalibrated:
407 d += Form("callisto/%04d/%08d", fSequence/10000, fSequence);
408 break;
409 case kImages:
410 d += Form("star/%04d/%08d", fSequence/10000, fSequence);
411 break;
412 }
413 }
414 else
415 gSystem->ExpandPathName(d);
416
417 if (!d.EndsWith("/"))
418 d += '/';
419
420 return d;
421}
422
423// --------------------------------------------------------------------------
424//
425// Return the expression describing the file-name for the file defined
426// by i-th entry of the the given arrays. The file type identifier is
427// defined by type. The source name is replaced by a wildcard and
428// the extension is defined by the type as well.
429//
430TString MSequence::GetFileName(UInt_t i, const TArrayI &arr, const TArrayI &sub, FileType_t type) const
431{
432 const char *id="_";
433 switch (type)
434 {
435 case kRawDat:
436 case kRootDat:
437 id = "D";
438 break;
439 case kRawPed:
440 case kRootPed:
441 id = "P";
442 break;
443 case kRawCal:
444 case kRootCal:
445 id = "C";
446 break;
447 case kRawAll:
448 case kRootAll:
449 id = "[PCD]";
450 break;
451 case kCalibrated:
452 id = "Y";
453 break;
454 case kImages:
455 id = "I";
456 break;
457 }
458
459 // ------------- Create file name --------------
460 TString n = fNight.GetStringFmt("%Y%m%d_");
461
462 if (arr[i]>999999)
463 n += "M1_";
464
465 // R. DeLosReyes and T. Bretz
466 // Changes to read the DAQ numbering format. Changes takes place
467 // between runs 35487 and 00035488 (2004_08_30)
468 n += Form(arr[i]>35487 || fMonteCarlo ? "%08d" : "%05d", arr[i]);
469
470 if (arr[i]>999999 && sub.GetSize()>0)
471 n += Form(".%05d", sub[i]);
472
473 n += "_";
474 n += id;
475 n += "_*";
476
477 if (arr[i]<1000000)
478 n += "_E";
479
480 switch (type)
481 {
482 case kRawDat:
483 case kRawPed:
484 case kRawCal:
485 case kRawAll:
486 n += ".raw.?g?z?";
487 break;
488 default:
489 n += ".root";
490 }
491
492 return n;
493}
494
495// --------------------------------------------------------------------------
496//
497// Add the entries from the arrays to the MDirIter
498//
499UInt_t MSequence::SetupRuns(MDirIter &iter, const TArrayI &arr, const TArrayI &sub, FileType_t type, const char *path) const
500{
501 TString d(path);
502 if (d.IsNull())
503 d = fDataPath;
504
505 const Bool_t def = d.IsNull();
506
507 d = GetPathName(d, type);
508
509 // For this particular case we assume that the files are added one by
510 // one without wildcards.
511 const Int_t n0 = iter.GetNumEntries();
512
513 Int_t excluded = 0;
514 for (int i=0; i<arr.GetSize(); i++)
515 {
516 if (IsExcluded(arr[i], sub[i]))
517 {
518 excluded++;
519 continue;
520 }
521
522 const TString n = GetFileName(i, arr, sub, type);
523
524 // Check existance and accessibility of file
525 MDirIter file(d, n, 0);
526 TString name = file();
527 gSystem->ExpandPathName(name);
528 if (gSystem->AccessPathName(name, kFileExists))
529 {
530 *fLog << err;
531 *fLog << "ERROR - File " << d << n << " not accessible!" << endl;
532 return 0;
533 }
534 if (!file().IsNull())
535 {
536 *fLog << err;
537 *fLog << "ERROR - Searching for file " << d << n << " gave more than one result!" << endl;
538 return 0;
539 }
540
541 // Add Path/File to TIter
542 iter.AddDirectory(d, n, 0);
543 }
544
545 // n0: The previous contents of the iter
546 // n1: The number of files which have been added to the iter
547 // n2: The number of files which should have been added from the array
548 const Int_t n1 = iter.GetNumEntries()-n0;
549 const Int_t n2 = arr.GetSize()-excluded;
550 if (n1==0)
551 {
552 *fLog << err;
553 *fLog << "ERROR - No input files for sequence #" << GetSequence() << endl;
554 *fLog << " read from " << GetBaseName() << endl;
555 *fLog << " found in" << (def?" default-path ":" ") << d << endl;
556 return 0;
557 }
558
559 if (n1==n2)
560 return n1;
561
562 *fLog << err;
563 *fLog << "ERROR - " << n1 << " input files for sequence #" << GetSequence() << " found in" << endl;
564 *fLog << " " << (def?" default-path ":" ") << d << endl;
565 *fLog << " but " << n2 << " files were defined in sequence file" << endl;
566 *fLog << " " << GetBaseName() << endl;
567 if (fLog->GetDebugLevel()<=4)
568 return 0;
569
570 *fLog << inf << "Files which are searched for this sequence:" << endl;
571 iter.Print();
572 return 0;
573}
574
575// --------------------------------------------------------------------------
576//
577// Get LightCondition from str and convert it to LightCondition_t
578//
579MSequence::LightCondition_t MSequence::GetLightCondition(const TString &str) const
580{
581 if (!str.CompareTo("n/a", TString::kIgnoreCase))
582 return kNA;
583 if (!str.CompareTo("No_Moon", TString::kIgnoreCase))
584 return kNoMoon;
585 if (!str.CompareTo("NoMoon", TString::kIgnoreCase))
586 return kNoMoon;
587 if (!str.CompareTo("Twilight", TString::kIgnoreCase))
588 return kTwilight;
589 if (!str.CompareTo("Moon", TString::kIgnoreCase))
590 return kMoon;
591 if (!str.CompareTo("Day", TString::kIgnoreCase))
592 return kDay;
593
594 gLog << warn;
595 gLog << "WARNING - in " << GetBaseName() << ":" << endl;
596 gLog << " LightCondition-tag is '" << str << "' but must be n/a, no_moon, twilight, moon or day." << endl;
597 return kNA;
598}
599
600// --------------------------------------------------------------------------
601//
602// Read the file fname as setup file for the sequence.
603//
604MSequence::MSequence(const char *fname, const char *path, UInt_t seq)
605{
606 fName = "MSequence";
607 fTitle = "Sequence file";
608
609 fFileName = fname;
610 fDataPath = path;
611
612 gSystem->ExpandPathName(fFileName);
613 gSystem->ExpandPathName(fDataPath);
614
615 const Bool_t rc1 = gSystem->AccessPathName(fFileName, kFileExists);
616 const Bool_t rc2 = !fDataPath.IsNull() && gSystem->AccessPathName(fDataPath, kFileExists);
617
618 if (rc1)
619 gLog << err << "ERROR - Sequence file '" << fname << "' doesn't exist." << endl;
620 if (rc2)
621 gLog << err << "ERROR - Directory '" << path << "' doesn't exist." << endl;
622
623 MEnv env(fFileName);
624
625 fSequence = (UInt_t)env.GetValue("Sequence", (Int_t)seq);
626 if (rc1 || rc2)
627 fSequence = (UInt_t)-1;
628
629 const TString prefix = Form("Sequence%08d", fSequence);
630
631 fLastRun = GetEnvValue2(env, prefix, "LastRun", -1);
632 fNumEvents = GetEnvValue2(env, prefix, "NumEvents", -1);
633 fPeriod = GetEnvValue2(env, prefix, "Period", -1);
634
635 TString str;
636 str = GetEnvValue2(env, prefix, "LightConditions", "n/a");
637 fLightCondition = GetLightCondition(str);
638
639 str = GetEnvValue2(env, prefix, "Start", "");
640 fStart.SetSqlDateTime(str);
641
642 str = GetEnvValue2(env, prefix, "Night", "");
643 str += " 00:00:00";
644 fNight.SetSqlDateTime(str);
645
646 fProject = GetEnvValue2(env, prefix, "Project", "");
647 fSource = GetEnvValue2(env, prefix, "Source", "");
648 fTriggerTable = GetEnvValue2(env, prefix, "TriggerTable", "");
649 fHvSettings = GetEnvValue2(env, prefix, "HvSettings", "");
650 fMonteCarlo = GetEnvValue2(env, prefix, "MonteCarlo", kFALSE);
651 fComment = GetEnvValue2(env, prefix, "Comment", "");
652
653 Split(env, prefix, "Runs", fRuns, fRunsSub);
654 Split(env, prefix, "CalRuns", fCalRuns, fCalRunsSub);
655 Split(env, prefix, "PedRuns", fPedRuns, fPedRunsSub);
656 Split(env, prefix, "DatRuns", fDatRuns, fDatRunsSub);
657 Split(env, prefix, "Exclude", fExclRuns, fExclRunsSub);
658
659 // Dummies:
660 env.Touch("ZdMin");
661 env.Touch("ZdMax");
662 env.Touch("L1TriggerTable");
663 env.Touch("L2TriggerTable");
664
665 if (seq<0 && env.GetNumUntouched()>0)
666 {
667 gLog << warn << "WARNING - At least one resource in the sequence-file has not been touched!" << endl;
668 env.PrintUntouched();
669 }
670}
671
672MSequence::MSequence(const char *fname, UInt_t seq)
673{
674 *this = MSequenceSQL(fname, seq);
675}
676
677//---------------------------------------------------------------------------
678//
679// Make sure that the name used for writing doesn't contain a full path
680//
681const char *MSequence::GetBaseName() const
682{
683 return gSystem->BaseName(fFileName);
684}
685
686//---------------------------------------------------------------------------
687//
688// Make sure that the name used for writing doesn't contain a full path
689//
690const char *MSequence::GetFilePath() const
691{
692 return gSystem->DirName(fFileName);
693}
694
695// --------------------------------------------------------------------------
696//
697// Find a sequence of continous numbers in f starting at pos (looking
698// only at n entries). The output is converted into sequences
699// of X (single r) and X:Y (a sequence between x and r). The function
700// returnes when position pos+n is reached
701//
702TString MSequence::GetNumSequence(Int_t pos, Int_t n, const TArrayI &f) const
703{
704 TString str;
705
706 Int_t p=pos;
707 while (p<pos+n)
708 {
709 str += Form(" %d", f[p]);
710
711 if (p==pos+n-1)
712 break;
713
714 int i=0;
715 while (++i<n)
716 if (f[p+i]-f[p]!=i)
717 break;
718
719 if (i>1)
720 str += Form(":%d", f[p+i-1]);
721
722 p += i;
723 }
724
725 return str;
726}
727
728// --------------------------------------------------------------------------
729//
730// Search for a sequence of continous numbers in r with f==0 starting at p.
731// A new starting p is returned. The output is converted into sequences
732// of X (single r) and X:Y (a sequence between x and r). The function
733// returnes with the next f!=0.
734//
735TString MSequence::GetNumSequence(Int_t &p, const TArrayI &r, const TArrayI &f) const
736{
737 TString str;
738
739 while (p<r.GetSize() && f[p]==0)
740 {
741 // serach for the first entry which doesn't fit
742 // or has a file number which is != 0
743 int i=0;
744 while (p+ ++i<r.GetSize())
745 if (r[p+i]-r[p]!=i || f[p+i]!=0)
746 break;
747
748 // None found (i-1==0)
749 if (i-1==0)
750 return str;
751
752 // The last run found in the sequence (e.g. 5.0) is followed
753 // by an identical run number but file != 0 (e.g. 5.1)
754 if (p+i<f.GetSize() && r[p+i]==r[p] && f[p+i]!=0)
755 i--;
756
757 // Now we have to check again whether found no valid entry
758 if (i-1==0)
759 return str;
760
761 str += Form(" %d", r[p]);
762 // p now points to the last entry which fits and
763 // has a file number == 0
764 p += i-1;
765 // Only one found (i-1==1)
766 // More tahn one found (i-1>1)
767 str += i-1==1 ? " " : ":";
768 str += Form("%d", r[p]);
769
770 // One step forward
771 p++;
772 }
773
774 return str;
775}
776
777// --------------------------------------------------------------------------
778//
779// Print the runs in a compressed wa. Returns the RunXXXXXXX string
780// simplyfing the file setup
781//
782TString MSequence::PrintRuns(ostream &out, const char *pre, const char *name, const TArrayI &r, const TArrayI &f) const
783{
784 if (r.GetSize()==0)
785 return "";
786
787 out << pre << name;
788 if (f.GetSize()==0)
789 const_cast<TArrayI&>(f).Set(r.GetSize());
790
791#ifdef DEBUG
792 for (int i=0; i<r.GetSize(); i++)
793 out << " " << r[i] << "." << f[i];
794 out << endl;
795 return "";
796#endif
797
798 TString str;
799
800 Int_t pos = 0;
801 while (pos<r.GetSize())
802 {
803 TString rc = GetNumSequence(pos, r, f);
804 if (!rc.IsNull())
805 {
806 out << rc;
807 continue;
808 }
809
810 Int_t n = GetSubArray(pos, r.GetSize(), (Int_t*)r.GetArray());
811 // end reached
812 if (n<0)
813 break;
814
815 // This can happen if it is the last entry
816 if (n==1)
817 {
818 out << " " << r[pos];
819 if (f[pos]>0)
820 out << "." << f[pos];
821 }
822 else
823 {
824 // Check for sequence
825 Bool_t isseq = kTRUE;
826 for (int i=1; i<n; i++)
827 if (f[pos+i]-f[pos]!=i)
828 isseq=kFALSE;
829
830 if (isseq)
831 {
832 out << " " << r[pos] << ".";
833 if (f[pos]!=0)
834 out << f[pos];
835 out << ":" << f[pos+n-1];
836 }
837 else
838 {
839 out << " " << r[pos] << "+";
840
841 str += '\n';
842 str += pre;
843 str += Form("Run%08d:", r[pos]);
844 str += GetNumSequence(pos, n, f);
845 }
846 }
847
848 pos += n;
849 }
850
851 out << endl;
852
853 return str;
854}
855
856// --------------------------------------------------------------------------
857//
858// Print the numbers in the classical way (one run after the other)
859//
860void MSequence::PrintRunsClassic(ostream &out, const char *pre, const char *name, const TArrayI &r) const
861{
862 out << pre << name;
863 for (int i=0; i<r.GetSize(); i++)
864 out << " " << r[i];
865 out << endl;
866}
867
868// --------------------------------------------------------------------------
869//
870// Print the contents of the sequence
871//
872void MSequence::Print(ostream &out, Option_t *o) const
873{
874 const TString opt(o);
875
876 const TString pre = opt.Contains("prefixed") ? Form("Sequence%08d.", fSequence) : "";
877
878 if (!IsValid())
879 {
880 out << pre << "Sequence: " << fFileName << " <invalid>" << endl;
881 return;
882 }
883 if (!fFileName.IsNull())
884 out << "# FileName: " << fFileName << endl;
885 if (!fDataPath.IsNull())
886 out << "# DataPath: " << fDataPath << endl;
887 out << endl;
888 if (pre.IsNull())
889 out << "Sequence: " << fSequence << endl;
890 if (fMonteCarlo)
891 out << pre << "MonteCarlo: Yes" << endl;
892 if (fPeriod>=0)
893 out << pre << "Period: " << fPeriod << endl;
894 if (fNight!=MTime())
895 out << pre << "Night: " << fNight.GetStringFmt("%Y-%m-%d") << endl;
896 out << endl;
897 out << pre << "LightCondition: ";
898 switch (fLightCondition)
899 {
900 case kNA: out << "n/a" << endl; break;
901 case kNoMoon: out << "NoMoon" << endl; break;
902 case kTwilight: out << "Twilight" << endl; break;
903 case kMoon: out << "Moon" << endl; break;
904 case kDay: out << "Day" << endl; break;
905 }
906
907 if (fStart!=MTime())
908 out << pre << "Start: " << fStart.GetSqlDateTime() << endl;
909 if (fLastRun>=0)
910 out << pre << "LastRun: " << fLastRun << endl;
911 if (fNumEvents>=0)
912 out << pre << "NumEvents: " << fNumEvents << endl;
913 if (!fProject.IsNull())
914 out << pre << "Project: " << fProject << endl;
915 if (!fSource.IsNull())
916 out << pre << "Source: " << fSource << endl;
917 if (!fTriggerTable.IsNull())
918 out << pre << "TriggerTable: " << fTriggerTable << endl;
919 if (!fHvSettings.IsNull())
920 out << pre << "HvSettings: " << fHvSettings << endl;
921 out << endl;
922
923 TString str;
924 if (!HasSubRuns() && opt.Contains("classic"))
925 {
926 PrintRunsClassic(out, pre, "Runs: ", fRuns);
927 PrintRunsClassic(out, pre, "CalRuns: ", fCalRuns);
928 PrintRunsClassic(out, pre, "PedRuns: ", fPedRuns);
929 PrintRunsClassic(out, pre, "DataRuns: ", fDatRuns);
930 PrintRunsClassic(out, pre, "Exclude: ", fExclRuns);
931 }
932 else
933 {
934 str += PrintRuns(out, pre, "Runs: ", fRuns, fRunsSub);
935 str += PrintRuns(out, pre, "CalRuns: ", fCalRuns, fCalRunsSub);
936 str += PrintRuns(out, pre, "PedRuns: ", fPedRuns, fPedRunsSub);
937 str += PrintRuns(out, pre, "DataRuns: ", fDatRuns, fDatRunsSub);
938 str += PrintRuns(out, pre, "Exclude: ", fExclRuns, fExclRunsSub);
939 }
940
941 if (!fDataPath.IsNull())
942 out << endl << pre << "DataPath: " << fDataPath << endl;
943
944 if (!str.IsNull())
945 out << str << endl;
946
947 out << endl;
948
949 if (!fComment.IsNull())
950 out << pre << "Comment: " << fComment << endl;
951}
952
953// --------------------------------------------------------------------------
954//
955// Print the contents of the sequence to gLog
956//
957void MSequence::Print(Option_t *o) const
958{
959 gLog << all;
960 Print(gLog, o);
961}
962
963// --------------------------------------------------------------------------
964//
965// Print the contents of the sequence to the file with name filename
966//
967void MSequence::WriteFile(const char *name, const Option_t *o) const
968{
969 ofstream fout(name);
970 if (!fout)
971 {
972 gLog << err << "Cannot open file " << name << ": ";
973 gLog << strerror(errno) << endl;
974 return;
975 }
976
977 Print(fout, o);
978}
979
980// --------------------------------------------------------------------------
981//
982// Add all ped runs from the sequence to MDirIter.
983// If path==0 fDataPath is used instead. If it is also empty
984// the standard path of the data-center is assumed.
985// If you have the runs locally use path="."
986// Using raw=kTRUE you get correspodning raw-files setup.
987// Return the number of files added.
988//
989// Runs which are in fExlRuns are ignored.
990//
991UInt_t MSequence::SetupPedRuns(MDirIter &iter, const char *path, Bool_t raw) const
992{
993 return SetupRuns(iter, fPedRuns, fPedRunsSub, raw?kRawPed:kRootPed, path);
994}
995
996// --------------------------------------------------------------------------
997//
998// Add all data runs from the sequence to MDirIter.
999// If path==0 fDataPath is used instead. If it is also empty
1000// the standard path of the data-center is assumed.
1001// If you have the runs locally use path="."
1002// Using raw=kTRUE you get correspodning raw-files setup.
1003// Return the number of files added.
1004//
1005// Runs which are in fExlRuns are ignored.
1006//
1007UInt_t MSequence::SetupDatRuns(MDirIter &iter, const char *path, Bool_t raw) const
1008{
1009 return SetupRuns(iter, fDatRuns, fDatRunsSub, raw?kRawDat:kRootDat, path);
1010}
1011
1012// --------------------------------------------------------------------------
1013//
1014// Add all runs from the sequence to MDirIter.
1015// If path==0 fDataPath is used instead. If it is also empty
1016// the standard path of the data-center is assumed.
1017// If you have the runs locally use path="."
1018// Using raw=kTRUE you get correspodning raw-files setup.
1019// Return the number of files added.
1020//
1021// Runs which are in fExlRuns are ignored.
1022//
1023UInt_t MSequence::SetupAllRuns(MDirIter &iter, const char *path, Bool_t raw) const
1024{
1025 return SetupRuns(iter, fRuns, fRunsSub, raw?kRawAll:kRootAll, path);
1026}
1027
1028// --------------------------------------------------------------------------
1029//
1030// Add all calibration runs from the sequence to MDirIter.
1031// If path==0 fDataPath is used instead. If it is also empty
1032// the standard path of the data-center is assumed.
1033// If you have the runs locally use path="."
1034// Using raw=kTRUE you get correspodning raw-files setup.
1035// Return the number of files added.
1036//
1037// Runs which are in fExlRuns are ignored.
1038//
1039UInt_t MSequence::SetupCalRuns(MDirIter &iter, const char *path, Bool_t raw) const
1040{
1041 return SetupRuns(iter, fCalRuns, fCalRunsSub, raw?kRawCal:kRootCal, path);
1042}
1043
1044// --------------------------------------------------------------------------
1045//
1046// Add all data runs from the sequence to MDirIter.
1047// If path==0 fDataPath is used instead. If it is also empty
1048// the standard path of the data-center is assumed.
1049// If you have the runs locally use path="."
1050// Using raw=kTRUE you get correspodning raw-files setup.
1051// Return the number of files added.
1052//
1053// Runs which are in fExlRuns are ignored.
1054//
1055UInt_t MSequence::SetupDatRuns(MDirIter &iter, FileType_t type, const char *path) const
1056{
1057 return SetupRuns(iter, fDatRuns, fDatRunsSub, type, path);
1058}
1059
1060// --------------------------------------------------------------------------
1061//
1062// check if the run/file is contained in the arrays.
1063//
1064Bool_t MSequence::IsContained(const TArrayI &arr, const TArrayI &sub, UInt_t run, UInt_t file) const
1065{
1066 // Backward compatibilty
1067 if (sub.GetSize()==0)
1068 {
1069 for (int i=0; i<arr.GetSize(); i++)
1070 if (run==(UInt_t)arr[i])
1071 return kTRUE;
1072 }
1073 else
1074 {
1075 for (int i=0; i<arr.GetSize(); i++)
1076 if (run==(UInt_t)arr[i] && file==(UInt_t)sub[i])
1077 return kTRUE;
1078 }
1079 return kFALSE;
1080}
1081
1082// --------------------------------------------------------------------------
1083//
1084// Add a file (run/file) to the arrays defined by type (P, C, D, X)
1085//
1086void MSequence::AddFile(UInt_t run, UInt_t file, char type)
1087{
1088 TArrayI *r=0, *f=0;
1089 switch (type)
1090 {
1091 case 'P':
1092 r = &fPedRuns;
1093 f = &fPedRunsSub;
1094 break;
1095 case 'D':
1096 r = &fDatRuns;
1097 f = &fDatRunsSub;
1098 break;
1099 case 'C':
1100 r = &fCalRuns;
1101 f = &fCalRunsSub;
1102 break;
1103 default:
1104 r = &fRuns;
1105 f = &fRunsSub;
1106 break;
1107 }
1108
1109 AddEntry(run, file, *r, *f);
1110
1111 MJob::SortArray(fExclRuns);
1112}
1113
1114// --------------------------------------------------------------------------
1115//
1116// Exclude this run (i.e. add it to fExclRuns)
1117//
1118void MSequence::ExcludeFile(UInt_t run, UInt_t file/*, Bool_t force*/)
1119{
1120// if (force && IsExcluded(run, file))
1121// return;
1122
1123 AddEntry(run, file, fExclRuns, fExclRunsSub);
1124
1125 MJob::SortArray(fExclRuns);
1126}
1127
1128// --------------------------------------------------------------------------
1129//
1130// Exclude all runs which are found in the list, e.g. "100 102 105"
1131//
1132void MSequence::ExcludeRuns(TString runs)
1133{
1134 // FIXME: Decode stream!!!
1135
1136 TArrayI data, sub;
1137 Split(runs, data, sub);
1138 for (int i=0; i<data.GetSize(); i++)
1139 ExcludeFile(data[i], sub[i]);
1140}
1141
1142// --------------------------------------------------------------------------
1143//
1144// Return the excluded runs (to be more precise:the excluded files)
1145// in a string
1146//
1147const TString MSequence::GetExcludedRuns() const
1148{
1149 TString rc;
1150 for (int i=0; i<fExclRuns.GetSize(); i++)
1151 {
1152 rc += fExclRuns[i];
1153 if (fExclRunsSub.GetSize()>0)
1154 {
1155 rc += ".";
1156 rc += fExclRunsSub[i];
1157 }
1158 rc += " ";
1159 }
1160 return rc(0, rc.Length()-1);
1161}
1162
1163// --------------------------------------------------------------------------
1164//
1165// If you want to change or set the night manually.
1166// The Format is
1167// SetNight("yyyy-mm-dd");
1168//
1169void MSequence::SetNight(const char *txt)
1170{
1171 TString night(txt);
1172 night += " 00:00:00";
1173 fNight.SetSqlDateTime(night);
1174
1175 fPeriod = MAstro::GetMagicPeriod(fNight.GetMjd());
1176}
1177
1178// --------------------------------------------------------------------------
1179//
1180// If the sequence name seq is just a digit it is inflated to a full
1181// path following the datacenter standard.
1182//
1183// Returns if file accessible or not.
1184//
1185Bool_t MSequence::InflatePath(TString &seq, Bool_t ismc)
1186{
1187 if (seq.IsDigit())
1188 {
1189 const Int_t numseq = seq.Atoi();
1190 seq = "/magic/";
1191 if (ismc)
1192 seq += "montecarlo/";
1193 seq += Form("sequences/%04d/sequence%08d.txt", numseq/10000, numseq);
1194 gLog << inf << "Inflated sequence file: " << seq << endl;
1195 }
1196
1197 if (!gSystem->AccessPathName(seq, kFileExists))
1198 return kTRUE;
1199
1200 gLog << err << "Sorry, sequence file '" << seq << "' doesn't exist." << endl;
1201 return kFALSE;
1202}
1203
1204// --------------------------------------------------------------------------
1205//
1206// Search starting at position p in array arr and return the number
1207// of elemets which are identical to the starting entry (the starting entry
1208// is also counted)
1209//
1210Int_t MSequence::GetSubArray(Int_t p, Int_t n, Int_t *arr)
1211{
1212 Int_t *ptr0 = arr+p;
1213
1214 Int_t *ptr = ptr0;
1215 Int_t *end = arr+n;
1216
1217 while (ptr<end && *ptr==*ptr0)
1218 ptr++;
1219
1220 return ptr-ptr0;
1221}
1222
1223// --------------------------------------------------------------------------
1224//
1225// Sort the array arr2 starting at position p for following entries
1226// for which arr1 is equal. If not at least two entries are found which
1227// can be sorted return -1.
1228//
1229// The absolute index of the next entry in arr1 is returned.
1230//
1231Int_t MSequence::SortArraySub(Int_t p, Int_t n, Int_t *arr1, Int_t *arr2)
1232{
1233 Int_t *ptr2 = arr2+p;
1234
1235 Int_t cnt = GetSubArray(p, n, arr1);
1236 if (cnt==0)
1237 return -1;
1238
1239 TArrayI srt(cnt, ptr2);
1240 MJob::SortArray(srt);
1241
1242 memcpy(ptr2, srt.GetArray(), srt.GetSize()*sizeof(Int_t));
1243
1244 return p+srt.GetSize();
1245}
1246
1247void MSequence::SortArrays(TArrayI &arr1, TArrayI &arr2)
1248{
1249 if (arr1.GetSize()!=arr2.GetSize())
1250 return;
1251
1252 TArrayI idx(arr1.GetSize());
1253
1254 TArrayI srt1(arr1);
1255 TArrayI srt2(arr2);
1256
1257 TMath::Sort(arr1.GetSize(), srt1.GetArray(), idx.GetArray(), kFALSE);
1258
1259 for (int i=0; i<arr1.GetSize(); i++)
1260 {
1261 arr1[i] = srt1[idx[i]];
1262 arr2[i] = srt2[idx[i]];
1263 }
1264
1265 Int_t p = 0;
1266 while (p>=0)
1267 p = SortArraySub(p, arr1.GetSize(), arr1.GetArray(), arr2.GetArray());
1268}
Note: See TracBrowser for help on using the repository browser.