source: branches/removing_cpp11_features/mjobs/MSequence.cc@ 18459

Last change on this file since 18459 was 17834, checked in by tbretz, 10 years ago
I wonder how that could ever work... it did not accept fz as extension.
File size: 50.0 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-2010
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// # Telescope number the sequence belongs to (if the resource is omitted
50// # the default is 1)
51// Telescope: 1
52//
53// # Observation Period (not needed, calculated from Night)
54// # Period: 18
55//
56// # Date of sunrise of the observation night - necessary if the path
57// # contains the date, e.g. raw data
58// Night: 2004-06-24
59//
60// # Start time of the sequence (first data run, not needed)
61// Start: 2004-06-24 03:12:42
62//
63// # Run number of last data run in sequence (not needed)
64// LastRun: 31032
65//
66// # Project name of data-runs of sequence (not needed)
67// Project: 3EG2033+41
68//
69// # Source name of all runs of sequence (not needed)
70// Source: 3EG2033+41
71//
72// # Trigger table of data-runs of sequence (not needed)
73// TriggerTable: L1_4NN:L2_DEFAULT
74//
75// # HV Setting table of data-runs of sequence (not needed)
76// HvSettings: HVSettings_FF36q
77//
78// # Total number of data-events in sequence (not needed)
79// NumEvents: 250914
80//
81// # Brightest light condition of the contained runs (not needed)
82// LightCondition: Twilight
83//
84// # Whether this is MC data or not (necessary in case of MCs if
85// # default paths should be used)
86// MonteCarlo: Yes
87//
88// # List of all runs of this sequence (not needed)
89// Runs: 31015:31017 31018 31019.0 31019.3 31019.5:7 31020+ 31021::3
90//
91// # List of all calibration runs of this sequence (necessary if accessed)
92// CalRuns: 31015 31016 31017
93// # List of pedestal runs belonging to the calibration runs of this sequence (necessary if accessed)
94// PedRuns: 31018
95// # List of all data runs belonging to this sequence (necessary)
96// DatRuns: 31019.0 31019.3 31019:5:7 31020+ 31021::3
97//
98// Run00031020: :3 7:9 15
99//
100// # Just for fun ;-) (not needed, but helpful)
101// Comment: This is a template for a sequence file
102//
103// ===========================================================================
104//
105// Runs are devided into file since run 1000000. These Run-/Filenumbers
106// are given by a dot. X.Y means Run X, File Y.
107//
108// In the Runs, CalRuns, PedRuns and DatRuns tag you can use
109// several abbreviationa:
110//
111// 31015:31017 means 31015.0 31016.0 31017.0
112// 31018 means 31018.0
113// 31019.3 means 31019.3
114// 31019.5:7 means 31019.5 31019.6 31019.7
115// 31020+ means file list for run 21020 given below
116// 31021::3 means 31021.0 31021.1 31021.2 31021.3
117//
118// For the run-list defined above (note the number must have 8 digits,
119// for example 'Run00031020') you can also use abbreviations:
120//
121// :3 means 0 1 2 3
122// 7:9 means 7 8 9
123//
124// ===========================================================================
125//
126// For special cases you can also setup a sequence directly from a macro,
127// for example:
128//
129// MDirIter pediter, datiter, caliter;
130//
131// MSequence seq;
132// seq.SetNight("2004-07-06");
133// seq.AddRun(31751, 'P');
134// seq.AddRun(31752, 'C');
135// seq.AddRuns(31753, 31764, 'D');
136// seq.SetupPedRuns(pediter);
137// seq.SetupCalRuns(caliter);
138// seq.SetupDatRuns(datiter);
139//
140// or
141//
142// MDirIter iter;
143//
144// MSequence seq;
145// seq.SetNight("2004-07-06");
146// seq.AddFiles(31753, 0, 120);
147// seq.GetRuns(iter);
148// seq.SetupPedRuns(iter, "/mypath", "[DPC]");
149//
150//
151// ===========================================================================
152//
153// ToDO:
154// * Default paths could be moved into the global .rootrc
155//
156// ===========================================================================
157//
158//
159// Class Version 2:
160// ----------------
161// + fMonteCarlo
162//
163// Class Version 3:
164// ----------------
165// + fComment
166//
167// Class Version 4:
168// ----------------
169// + fExclRuns
170//
171// Class Version 5:
172// ----------------
173// + fRunsSub
174// + fDatRunsSub
175// + fPedRunsSub
176// + fCalRunsSub
177// + fExclRunsSub
178//
179// Class Version 6:
180// ----------------
181// + fTelescope
182//
183// Class Version 7:
184// ----------------
185// + fDrsRuns
186// + fDrsRunsSub
187// + fDrsFiles
188// + fDrsFilesSub
189// + fDrsSequence
190//
191/////////////////////////////////////////////////////////////////////////////
192#include "MSequenceSQL.h"
193
194#include <stdlib.h>
195#include <errno.h>
196
197#include <fstream>
198
199#include <TEnv.h>
200#include <TPRegexp.h>
201#include <TSystem.h> // TSystem::ExpandPath
202
203#include "MLog.h"
204#include "MLogManip.h"
205
206#include "MEnv.h"
207#include "MJob.h"
208#include "MAstro.h"
209#include "MString.h"
210#include "MDirIter.h"
211
212ClassImp(MSequence);
213
214using namespace std;
215
216// --------------------------------------------------------------------------
217//
218// This adds an run/file entry to the data/sub arrays. If it is already
219// contained a waring is printed.
220//
221void MSequence::AddEntry(Int_t run, Int_t file, TArrayI &data, TArrayI &sub) const
222{
223 const Int_t n = data.GetSize();
224
225 // skip already existing entries
226 if (IsContained(data, sub, run, file))
227 {
228 *fLog << warn << "WARNING - File " << run << "." << file << " already in list... skipped." << endl;
229 return;
230 }
231
232 if (!fMonteCarlo && run<1000000 && file>0)
233 *fLog << warn << "WARNING - Run number " << run << "<" << "1,000,000 but file " << file << ">0..." << endl;
234
235 // set new entry
236 data.Set(n+1);
237 sub.Set(n+1);
238
239 data[n] = run;
240 sub[n] = file;
241}
242
243// --------------------------------------------------------------------------
244//
245// Evaluate a token in thr Run string. Add the coresponding run/files
246// with AddEntry
247//
248void MSequence::EvalEntry(const TEnv *env, const TString &prefix, const TString &num, TArrayI &data, TArrayI &sub) const
249{
250 // Split entry into run and file
251 const Int_t run = num.Atoi();
252
253 // Syntax error forbidden by construction
254 const Ssiz_t p1 = num.First('.');
255 const Ssiz_t p2 = num.Last(':');
256
257 // ---------------------------------------------------------------
258
259 const Int_t n1 = atoi(num.Data()+p1+1);
260 const Int_t n2 = atoi(num.Data()+p2+1);
261
262 // ---------------------------------------------------------------
263 // p1>=0 && p2<0 (. but no :) run.n1 run.file1
264 if (p1>=0 && p2<0)
265 {
266 AddEntry(run, n1, data, sub);
267 return;
268 }
269
270 // ---------------------------------------------------------------
271 // p1>=0 && p2>=0 (. and :) run:n1:n2 run.file1-run.file2
272 if (p1>=0 && p2>=0)
273 {
274 if (n2<n1)
275 {
276 *fLog << warn << "WARNING - Invalid range '" << num << "'... ignored." << endl;
277 return;
278 }
279
280 for (int i=n1; i<=n2; i++)
281 AddEntry(run, i, data, sub);
282 return;
283 }
284
285 // ---------------------------------------------------------------
286 // p1<0 && p2>=0 (no . but :) n1:n2 run1-run2
287 if (p1<0 && p2>=0)
288 {
289 if (n2<run)
290 {
291 *fLog << warn << "WARNING - Invalid range in '" << num << "'... ignored." << endl;
292 return;
293 }
294
295 for (int i=run; i<=n2; i++)
296 AddEntry(i, 0, data, sub);
297 return;
298 }
299
300 // ---------------------------------------------------------------
301 // p0<0 and p1<0 (no . and no :) run run
302
303 if (!num.EndsWith("+"))
304 {
305 AddEntry(run, 0, data, sub);
306 return;
307 }
308
309 if (!env)
310 return;
311
312 TPRegexp regexp("([0-9]*:[0-9]+|[0-9]+(:[0-9]*)?)( +|$)");
313
314 TString files = GetEnvValue3(*env, prefix, "Run%d", run);
315 if (files.IsNull())
316 {
317 AddEntry(run, 0, data, sub);
318 return;
319 }
320
321 while (!files.IsNull())
322 {
323 const TString num = files(regexp);
324 if (num.IsNull())
325 {
326 *fLog << warn << "WARNING - File in run " << run << " is NaN (not a number): '" << files << "'" << endl;
327 break;
328 }
329
330 const Ssiz_t p1 = num.First(':');
331 if (p1>=0)
332 {
333 const Int_t n1 = atoi(num.Data());
334 const Int_t n2 = atoi(num.Data()+p1+1);
335
336 if (n2<n1)
337 {
338 *fLog << warn << "WARNING - Invalid range in '" << num << "'... ignored." << endl;
339 return;
340 }
341
342 // FIXME: n2==0 || n2<n1
343 for (int i=n1; i<=n2; i++)
344 AddEntry(run, i, data, sub);
345 }
346 else
347 {
348 const Int_t file = atoi(num.Data());
349 AddEntry(run, file, data, sub);
350 }
351
352 files.Remove(0, files.First(num)+num.Length());
353 }
354}
355
356// --------------------------------------------------------------------------
357//
358// Interprete the TString and add the run/files to the arrays.
359// Run/files which are twice in the list are only added once. In this case
360// a warning is emitted.
361//
362void MSequence::Split(TString &runs, TArrayI &data, TArrayI &sub, const TEnv *env, const TString prefix) const
363{
364 TPRegexp regexp("^[0-9]+([+]|(:|[.]([0-9]*:)?)[0-9]+)?( +|$)");
365
366 data.Set(0);
367 sub.Set(0);
368
369 runs.ReplaceAll("\t", " ");
370 runs = runs.Strip(TString::kBoth);
371
372 while (!runs.IsNull())
373 {
374 const TString num = runs(regexp);
375 if (num.IsNull())
376 {
377 *fLog << warn << "WARNING - Run syntax error: '" << runs << "'" << endl;
378 break;
379 }
380
381 EvalEntry(env, prefix, num.Strip(TString::kTrailing), data, sub);
382
383 runs.Remove(0, runs.First(num)+num.Length());
384 }
385
386 SortArrays(data, sub);
387}
388
389// --------------------------------------------------------------------------
390//
391// Get the String from the TEnv file prefixed by prefix-name.
392// Intepret the string using Split which adds the run/files to the arrays.
393//
394void MSequence::Split(const TEnv &env, const TString &prefix, const char *name, TArrayI &data, TArrayI &sub) const
395{
396 TString str = GetEnvValue2(env, prefix, name, "");
397 Split(str, data, sub, &env, prefix);
398}
399
400TString MSequence::InflateFilePath(const MTime &night, Bool_t mc)
401{
402 TString rc = GetStandardPath(mc);
403 rc += "rawfiles/";
404 rc += night.GetStringFmt("%Y/%m/%d/");
405 return rc;
406}
407
408TString MSequence::InflateFilePath(const MTime &night, UShort_t tel, Int_t run, Int_t file, Int_t type)
409{
410 return InflateFilePath(night)+InflateFileName(night, tel, run, file, type);
411}
412
413// --------------------------------------------------------------------------
414//
415// Compile path from the given path name and expand it. If it IsNull()
416// the path is compiled as standard path from tha datacenter). The
417// returned path will end with a "/".
418//
419TString MSequence::GetPathName(TString d, FileType_t type) const
420{
421 // Setup path
422 if (d.IsNull())
423 {
424 d = GetStandardPath();
425 switch (type&kFilePaths)
426 {
427 case kDrs:
428 case kFits:
429 d += "raw/";
430 d += fNight.GetStringFmt("%Y/%m/%d");
431 break;
432 case kRaw: // rawdata
433 case kRoot: // mcdata
434 d += "rawfiles/";
435 if (!fNight)
436 *fLog << "WARNING - No Night-resource... path not supported." << endl;
437 d += fNight.GetStringFmt("%Y/%m/%d");
438 break;
439 case kReport:
440 d += "../subsystemdata/cc/";
441 d += fNight.GetStringFmt("%Y/%m/%d");
442 break;
443 case kCalibrated:
444 d += MString::Format("callisto/%04d/%08d", fSequence/10000, fSequence);
445 break;
446 case kImages:
447 d += MString::Format("star/%04d/%08d", fSequence/10000, fSequence);
448 break;
449 }
450 }
451 else
452 gSystem->ExpandPathName(d);
453
454 if (!d.EndsWith("/"))
455 d += '/';
456
457 return d;
458}
459
460// --------------------------------------------------------------------------
461//
462// Compile FileName according to night, tel, run, file and type.
463//
464TString MSequence::InflateFileName(const MTime &night, UShort_t tel, Int_t run, Int_t file, Int_t type)
465{
466 if (!night && type==kCorsika)
467 {
468 // /magic/simulated/ceres/001/000/0001/cer123456
469 return MString::Format("cer%06d", -run);
470 }
471
472 TString n;
473
474 if (type&kDrsFile)
475 {
476 n += night.GetStringFmt("%Y%m%d_");
477 n += MString::Format("%03d", run);
478 n += ".drs.fits.?[fg]?z?";
479 return n;
480 }
481 if (type&(kFits|kFact))
482 {
483 n += night.GetStringFmt("%Y%m%d_");
484 n += MString::Format("%03d", run);
485
486 if (type==kFactCal)
487 n += "_C.root";
488 else if (type==kFactImg)
489 n += "_I.root";
490 else
491 n += ".fits.?[fg]?z?";
492 return n;
493 }
494
495 const char *id="_";
496 switch ((RunType_t)(type&kRunType))
497 {
498 case kDat:
499 id = "D";
500 break;
501 case kPed:
502 id = "P";
503 break;
504 case kCal:
505 id = "C";
506 break;
507 case kAll:
508 id = "[PCD]";
509 break;
510 case kCalib:
511 id = "Y";
512 break;
513 case kImage:
514 id = "I";
515 break;
516 case kExcl:
517 break;
518 }
519
520 // Is report file?
521 const Bool_t isrep = type&kReport;
522
523 // Calculate limit for transition from 5-digit to 8-digit numbers
524 const Int_t limit = isrep ? 39373 : 35487;
525
526 // ------------- Create file name --------------
527 if (night)
528 n += night.GetStringFmt("%Y%m%d_");
529
530 // This is for MCs (FIXME!!!!)
531 if (run<0)
532 {
533 n += MString::Format("%08d", -run);
534 if (file>=0)
535 n += MString::Format(".%03d", file);
536 }
537 else
538 {
539 if (tel>0)
540 n += MString::Format("M%d_", tel);
541
542 // R. DeLosReyes and T. Bretz
543 // Changes to read the DAQ numbering format. Changes takes place
544 // between runs 35487 and 00035488 (2004_08_30)
545 n += MString::Format(run>limit ? "%08d" : "%05d", run);
546
547 if (tel>0)
548 n += MString::Format(".%03d", file);
549 }
550
551
552 n += "_";
553 n += id;
554 n += "_*";
555
556 if (tel==0 && run>=0)
557 n += isrep ? "_S" : "_E";
558
559 switch (type&kFileType)
560 {
561 case kRaw: // MC // DATA
562 n += run<0 ? ".root" : ".raw.?[fg]?z?"; // TPRegexp: (\.gz)?
563 break;
564 case kReport:
565 n += ".rep"; // TPRegexp: (\.gz)?
566 break;
567 default:
568 n += ".root";
569 break;
570 }
571
572 return n;
573}
574
575// --------------------------------------------------------------------------
576//
577// Return the expression describing the file-name for the file defined
578// by i-th entry of the the given arrays. The file type identifier is
579// defined by type. The source name is replaced by a wildcard and
580// the extension is defined by the type as well.
581//
582TString MSequence::GetFileRegexp(UInt_t i, const TArrayI &arr, const TArrayI &sub, FileType_t type) const
583{
584 // Entry doesn't exist
585 if (i>=(UInt_t)arr.GetSize())
586 return "";
587
588 // This is (so far) well defined for MAGIC data
589 if (!fMonteCarlo)
590 return InflateFileName(fNight, arr[i]>999999?fTelescope:0, arr[i], sub.GetSize()>0?sub[i]:0, type);
591
592 // Monte Carlos
593 return InflateFileName(fNight, fTelescope, -arr[i], sub.GetSize()>0?sub[i]:0, type);
594}
595
596// --------------------------------------------------------------------------
597//
598// Get the filename from the dirctory and the file-regexp.
599// return "" if file is not accessible or the regular expression is not
600// unambiguous.
601//
602TString MSequence::FindFile(const TString &d, const TString &f) const
603{
604 // Check existance and accessibility of file
605 MDirIter file(d, f, 0);
606
607 TString name = file();
608 gSystem->ExpandPathName(name);
609 if (gSystem->AccessPathName(name, kFileExists))
610 {
611 *fLog << err;
612 *fLog << "ERROR - File " << d << f << " not accessible!" << endl;
613 return "";
614 }
615 if (!file().IsNull())
616 {
617 *fLog << err;
618 *fLog << "ERROR - Searching for file " << d << f << " gave more than one result!" << endl;
619 return "";
620 }
621
622 return name;
623}
624
625// --------------------------------------------------------------------------
626//
627// Set the path accoring to type (if fDataPath=path=0), fDataPath
628// (if path=0) or path.
629// Returns accessability of the path.
630//
631Bool_t MSequence::FindPath(TString &path, FileType_t type) const
632{
633 if (path.IsNull())
634 path = fDataPath;
635
636 const Bool_t def = path.IsNull();
637
638 path = GetPathName(path, type);
639
640 return def;
641}
642
643// --------------------------------------------------------------------------
644//
645// Add the entries from the arrays to the MDirIter
646//
647UInt_t MSequence::GetRuns(MDirIter &iter, const TArrayI &arr, const TArrayI &sub, FileType_t type, TString path) const
648{
649 const Bool_t def = FindPath(path, type);
650
651 // For this particular case we assume that the files are added one by
652 // one without wildcards.
653 const Int_t n0 = iter.GetNumEntries();
654
655 Int_t excluded = 0;
656 for (int i=0; i<arr.GetSize(); i++)
657 {
658 if (IsExcluded(arr[i], sub[i]))
659 {
660 excluded++;
661 continue;
662 }
663
664 const TString n = GetFileRegexp(i, arr, sub, type);
665
666 if (FindFile(path, n).IsNull())
667 continue;
668
669 // Add Path/File to TIter
670 iter.AddDirectory(path, n, 0);
671 }
672
673 // n0: The previous contents of the iter
674 // n1: The number of files which have been added to the iter
675 // n2: The number of files which should have been added from the array
676 const Int_t n1 = iter.GetNumEntries()-n0;
677 const Int_t n2 = arr.GetSize()-excluded;
678 if (n1==0)
679 {
680 *fLog << err;
681 *fLog << "ERROR - No input files for sequence #" << GetSequence() << endl;
682 *fLog << " read from " << GetBaseName() << endl;
683 *fLog << " found in" << (def?" default-path ":" ") << path << endl;
684 return 0;
685 }
686
687 if (n1==n2)
688 return n1;
689
690 *fLog << err;
691 *fLog << "ERROR - " << n1 << " input files for sequence #" << GetSequence() << " found in" << endl;
692 *fLog << " " << (def?" default-path ":" ") << path << endl;
693 *fLog << " but " << n2 << " files were defined in sequence file" << endl;
694 *fLog << " " << GetBaseName() << endl;
695 if (fLog->GetDebugLevel()<=4)
696 return 0;
697
698 *fLog << inf << "Files which are searched for this sequence:" << endl;
699 iter.Print();
700 return 0;
701}
702
703UInt_t MSequence::GetDrsFile() const
704{
705 if (fDrsRuns.GetSize()==0)
706 return fDrsFiles.GetSize()==0 ? 0 : fDrsFiles[0];
707
708 UInt_t rc = 0;
709 for (int i=0; i<fDrsFiles.GetSize(); i++)
710 {
711 for (int j=0; j<fPedRuns.GetSize(); j++)
712 {
713 if (fDrsFiles[i]==fPedRuns[j])
714 rc = fDrsFiles[i];
715 }
716 }
717
718 return rc;
719}
720
721// --------------------------------------------------------------------------
722//
723// Returns "0" if file at i-th index is excluded. Get the access-path
724// defined by the default or data-path (if path=0) or path.
725// Get the full file-name by accessing the file.
726//
727TString MSequence::GetFileName(UInt_t i, const TArrayI &arr, const TArrayI &sub, FileType_t type, const char *path) const
728{
729 if (i>=(UInt_t)arr.GetSize())
730 return "";
731
732 if (IsExcluded(arr[i], sub[i]))
733 return "0";
734
735 const TString d = FindPath(type, path);
736 const TString n = GetFileRegexp(i, arr, sub, type);
737
738 return FindFile(d, n);
739}
740
741// --------------------------------------------------------------------------
742//
743// Return the pointers to the arrays with the runs/files depending on the
744// given type.
745//
746void MSequence::GetArrays(const TArrayI* &r, const TArrayI* &f, Int_t type) const
747{
748 switch ((RunType_t)(type&(kRunType|kExcl)))
749 {
750 case kDrsRun:
751 r = &fDrsRuns;
752 f = &fDrsRunsSub;
753 break;
754 case kDrsFile:
755 r = &fDrsFiles;
756 f = &fDrsFilesSub;
757 break;
758 case kPed:
759 r = &fPedRuns;
760 f = &fPedRunsSub;
761 break;
762 case kDat:
763 case kImage:
764 case kCalib:
765 r = &fDatRuns;
766 f = &fDatRunsSub;
767 break;
768 case kCal:
769 r = &fCalRuns;
770 f = &fCalRunsSub;
771 break;
772 case kExcl:
773 r = &fExclRuns;
774 f = &fExclRunsSub;
775 break;
776 case kAll:
777 r = &fRuns;
778 f = &fRunsSub;
779 break;
780 }
781}
782
783// --------------------------------------------------------------------------
784//
785// Add runs from the sequence to MDirIter. If path==0 fDataPath is
786// used instead. If it is also empty the standard path of the
787// data-center is assumed. If you have the runs locally use path="."
788//
789// Returns the number of files added.
790//
791// Runs which are in fExlRuns are ignored.
792//
793UInt_t MSequence::GetRuns(MDirIter &iter, FileType_t type, const char *path) const
794{
795 const TArrayI *r=0, *f=0;
796 GetArrays(r, f, type);
797 return r==0 ? 0 : GetRuns(iter, *r, *f, type, path);
798}
799
800// --------------------------------------------------------------------------
801//
802// Returns the num-th entry of FileType_t as regular expression.
803// If the file is excluded return "".
804// To get the number of valid entries use GetNumEntries(FileType_t)
805//
806// e.g.
807// if (GetNumEntries(MSequence::kDat))<5)
808// GetFileRegexp(3, MSequence::kRawDat);
809//
810TString MSequence::GetFileRegexp(UInt_t num, FileType_t type) const
811{
812 const TArrayI *r=0, *f=0;
813 GetArrays(r, f, type);
814
815 TString rc = GetFileRegexp(num, *r, *f, type);
816 rc.ReplaceAll(".", "\\.");
817 rc.ReplaceAll("*", ".*");
818 return rc;
819}
820
821// --------------------------------------------------------------------------
822//
823// Returns the num-th entry of FileType_t as filename. To access the
824// path the default is used if path IsNull, path otherwise.
825// If the file could not be accessed "" is returned, if it is
826// excluded "0".
827// To get the number of valid entries use GetNumEntries(FileType_t)
828//
829// e.g.
830// if (GetNumEntries(MSequence::kDat))<5)
831// GetFileName(3, MSequence::kRawDat);
832//
833TString MSequence::GetFileName(UInt_t num, FileType_t type, const char *path) const
834{
835 const TArrayI *r=0, *f=0;
836 GetArrays(r, f, type);
837 return GetFileName(num, *r, *f, type, path);
838}
839
840// --------------------------------------------------------------------------
841//
842// Returns the num-th entry of FileType_t as filename.
843// If the file could not be accessed or excluded return "".
844// To get the number of valid entries use GetNumEntries(RunType_t)
845//
846UInt_t MSequence::GetNumEntries(RunType_t type) const
847{
848 const TArrayI *r=0, *f=0;
849 GetArrays(r, f, type);
850 return r->GetSize();
851}
852
853// --------------------------------------------------------------------------
854//
855// Returns the num-th entry of RunType_t as run- and file-number.
856// Returns -1 if index is out of range, 0 if file is excluded and
857// 1 in case of success.
858//
859// e.g.
860// UInt_t run, file;
861// GetFile(3, MSequence::kDat, run, file);
862//
863Int_t MSequence::GetFile(UInt_t i, RunType_t type, UInt_t &run, UInt_t &file) const
864{
865 const TArrayI *r=0, *f=0;
866 GetArrays(r, f, type);
867
868 if (i>=(UInt_t)r->GetSize())
869 return -1;
870
871 run = (*r)[i];
872 file = i<(UInt_t)f->GetSize() ? (*f)[i] : 0;
873
874 if (IsExcluded(run, file))
875 return 0;
876
877 return 1;
878}
879
880// --------------------------------------------------------------------------
881//
882// Add a file (run/file) to the arrays defined by RunType_t
883//
884void MSequence::AddFile(UInt_t run, UInt_t file, RunType_t type)
885{
886 const TArrayI *rconst=0, *fconst=0;
887
888 GetArrays(rconst, fconst, type);
889
890 if (!rconst || !fconst)
891 {
892 *fLog << err << "ERROR - Invalid values returned by MSequence::GetArrays... " << run << "." << file << " ignored." << endl;
893 return;
894 }
895
896 TArrayI &r=*const_cast<TArrayI*>(rconst);
897 TArrayI &f=*const_cast<TArrayI*>(fconst);
898
899 AddEntry(run, file, r, f);
900
901 SortArrays(r, f);
902}
903
904// --------------------------------------------------------------------------
905//
906// Get LightCondition from str and convert it to LightCondition_t
907//
908MSequence::LightCondition_t MSequence::GetLightCondition(const TString &str) const
909{
910 if (!str.CompareTo("n/a", TString::kIgnoreCase))
911 return kNA;
912 if (!str.CompareTo("No_Moon", TString::kIgnoreCase))
913 return kNoMoon;
914 if (!str.CompareTo("NoMoon", TString::kIgnoreCase))
915 return kNoMoon;
916 if (!str.CompareTo("Twilight", TString::kIgnoreCase))
917 return kTwilight;
918 if (!str.CompareTo("Moon", TString::kIgnoreCase))
919 return kMoon;
920 if (!str.CompareTo("Day", TString::kIgnoreCase))
921 return kDay;
922
923 gLog << warn;
924 gLog << "WARNING - in " << GetBaseName() << ":" << endl;
925 gLog << " LightCondition-tag is '" << str << "' but must be n/a, no_moon, twilight, moon or day." << endl;
926 return kNA;
927}
928
929// --------------------------------------------------------------------------
930//
931// Set the path to the data. If no path is given the data-center default
932// path is used to access the files.
933//
934// kTRUE is returned if the path is acessible, kFALSE otherwise.
935// (In case of the default path kTRUE is returned in any case)
936//
937Bool_t MSequence::SetDataPath(const char *path)
938{
939 fDataPath = path;
940
941 gSystem->ExpandPathName(fDataPath);
942
943 const Bool_t rc = !fDataPath.IsNull() && gSystem->AccessPathName(fDataPath, kFileExists);
944 if (rc)
945 gLog << err << "ERROR - Directory '" << fDataPath << "' doesn't exist." << endl;
946
947 return !rc;
948}
949
950// --------------------------------------------------------------------------
951//
952// Read a sequence from a file. To set the location of the data (datapath)
953// use SetDataPath. The sequence number given is used if no sequence
954// number is found in the sequence file.
955//
956// If the file could not be found or accesed kFALSE is returned, kTRUE
957// otherwise.
958//
959Bool_t MSequence::ReadFile(const char *filename, UInt_t seq)
960{
961 fFileName = filename;
962
963 gSystem->ExpandPathName(fFileName);
964
965 const Bool_t rc = gSystem->AccessPathName(fFileName, kFileExists);
966 if (rc)
967 gLog << err << "ERROR - Sequence file '" << filename << "' doesn't exist." << endl;
968
969 MEnv env(fFileName);
970
971 fSequence = (UInt_t)env.GetValue("Sequence", (Int_t)seq);
972
973 const TString prefix = MString::Format("Sequence%08d", fSequence);
974
975 fTelescope = GetEnvValue2(env, prefix, "Telescope", 1);
976 fLastRun = GetEnvValue2(env, prefix, "LastRun", -1);
977 fNumEvents = GetEnvValue2(env, prefix, "NumEvents", -1);
978 fDrsSequence = GetEnvValue2(env, prefix, "DrsSequence", 0);
979
980 TString str;
981 str = GetEnvValue2(env, prefix, "LightCondition", "n/a");
982 fLightCondition = GetLightCondition(str);
983
984 str = GetEnvValue2(env, prefix, "Start", "");
985 fStart.SetSqlDateTime(str);
986
987 str = GetEnvValue2(env, prefix, "Night", "");
988 SetNight(str);
989
990 fProject = GetEnvValue2(env, prefix, "Project", "");
991 fSource = GetEnvValue2(env, prefix, "Source", "");
992 fTriggerTable = GetEnvValue2(env, prefix, "TriggerTable", "");
993 fHvSettings = GetEnvValue2(env, prefix, "HvSettings", "");
994 fMonteCarlo = GetEnvValue2(env, prefix, "MonteCarlo", kFALSE);
995 fComment = GetEnvValue2(env, prefix, "Comment", "");
996
997 Split(env, prefix, "Runs", fRuns, fRunsSub);
998 Split(env, prefix, "CalRuns", fCalRuns, fCalRunsSub);
999 Split(env, prefix, "PedRuns", fPedRuns, fPedRunsSub);
1000 Split(env, prefix, "DatRuns", fDatRuns, fDatRunsSub);
1001 Split(env, prefix, "DrsRuns", fDrsRuns, fDrsRunsSub);
1002 Split(env, prefix, "DrsFiles",fDrsFiles, fDrsFilesSub);
1003 Split(env, prefix, "Exclude", fExclRuns, fExclRunsSub);
1004
1005 if (fDrsRuns.GetSize()==0 && fDrsFiles.GetSize()>1)
1006 gLog << warn << "WARNING - In a data sequence only one DrsFiles entry makes sense." << endl;
1007
1008 // Dummies:
1009 env.Touch("Period");
1010 env.Touch("ZdMin");
1011 env.Touch("ZdMax");
1012 env.Touch("L1TriggerTable");
1013 env.Touch("L2TriggerTable");
1014
1015 if (seq==(UInt_t)-1 && env.GetNumUntouched()>0)
1016 {
1017 gLog << warn << "WARNING - At least one resource in the sequence-file has not been touched!" << endl;
1018 env.PrintUntouched();
1019 }
1020
1021 return !rc;
1022}
1023
1024// --------------------------------------------------------------------------
1025//
1026// Instantiate a file from either a file or the database.
1027//
1028// If not valid sequence could be created the sequence is invalidated,
1029// which can be queried with IsValid.
1030//
1031// see ReadFile, ReadDatabase and SetDataPath for more details.
1032//
1033MSequence::MSequence(const char *fname, const char *path, UInt_t seq)
1034 : fTelescope(1), fSequence((UInt_t)-1), fLastRun((UInt_t)-1),
1035 fNumEvents((UInt_t)-1), fPeriod((UInt_t)-1), fLightCondition(kNA),
1036 fMonteCarlo(kFALSE)
1037{
1038 fName = "MSequence";
1039 fTitle = "Sequence file";
1040
1041 if (TString(fname).IsNull() && TString(path).IsNull() && seq==(UInt_t)-1)
1042 return;
1043
1044 // regular expression to distinguish beween a mysql-path and
1045 // a filename from where the sequence should be retrieved
1046 TPRegexp regexp("mysql://[a-zA-Z0-9]+:.+@[a-zA-Z0-9]+/[a-zA-Z0-9]+/([0-9]+:)?[0-9]+");
1047
1048 const TString db = TString(fname)(regexp);
1049
1050 const Bool_t rc1 = db.IsNull() ? ReadFile(fname, seq) : ReadDatabase(fname, seq);
1051 const Bool_t rc2 = SetDataPath(path);
1052
1053 if (!rc1 || !rc2)
1054 fSequence = (UInt_t)-1;
1055}
1056
1057// --------------------------------------------------------------------------
1058//
1059// Read a sequence from the database. Give the path to the database as:
1060// mysql://user:password@name/database
1061// In this case you MUST give a sequence number.
1062//
1063// You can code the telescope and sequence number into the path and
1064// omit the arguments:
1065// mysql://user:password@name/database/[tel:]sequence
1066//
1067// The third option is to give just the sql.rc as string in the argument.
1068// In this case you MUST give a sequence number.
1069//
1070// If the telecope number is omitted as argument, i.e. ==0, or in the
1071// database path, a sequence is read from the database if the sequence
1072// number is unambiguous.
1073//
1074// kFALSE is returned if the final sequence is invalid, kTRUE in case of
1075// success.
1076//
1077Bool_t MSequence::ReadDatabase(TString name, UInt_t seq, UShort_t tel)
1078{
1079 TPRegexp regexp("([0-9]+:)?[0-9]+$");
1080
1081 const TString telseq = name(regexp);
1082
1083 if (!telseq.IsNull())
1084 {
1085 const Ssiz_t p = telseq.First(':');
1086
1087 const TString strtel = p<0 ? TString("") : telseq(0, p);
1088 const TString strseq = telseq(p+1, telseq.Length());
1089
1090 tel = strtel.Atoi();
1091 seq = strseq.Atoi();
1092
1093 name = gSystem->DirName(name);
1094 }
1095
1096 *this = MSequenceSQL(name, seq, tel);
1097
1098 return IsValid();
1099}
1100
1101// --------------------------------------------------------------------------
1102//
1103// Create a sequence from the database, e.g.
1104//
1105// TString mysql = "mysql://MAGIC:password@vela/MyMagic";
1106// Int_t sequence = 100002;
1107// Int_t telescope = 1;
1108//
1109// MSequence seq(mysql, sequence, telescope);
1110//
1111// Is the telescope number is omitted (==0) the database is checked for
1112// an unambiguous sequence.
1113//
1114// For more details see ReadDatabase and MSequenceSQL.
1115//
1116MSequence::MSequence(const char *fname, UInt_t seq, UShort_t tel)
1117{
1118 const Bool_t rc = ReadDatabase(fname, seq, tel);
1119
1120 fName = "MSequence";
1121 fTitle = "Sequence file";
1122
1123 if (!rc)
1124 fSequence = (UInt_t)-1;
1125}
1126
1127// --------------------------------------------------------------------------
1128//
1129// Some helper functions for the comparison functions
1130//
1131static int operator==(const TArrayI &a, const TArrayI &b)
1132{
1133 return a.GetSize()==b.GetSize() &&
1134 memcmp(a.GetArray(), b.GetArray(), a.GetSize()*sizeof(Int_t));
1135}
1136
1137static int IsNull(const TArrayI &a, const TArrayI &b)
1138{
1139 return a==TArrayI(a.GetSize()) && b==TArrayI(b.GetSize());
1140}
1141
1142static int Check(const TArrayI &a, const TArrayI &b)
1143{
1144 return a==b || IsNull(a, b);
1145}
1146
1147// --------------------------------------------------------------------------
1148//
1149// Here we test all things mandatory for a sequence:
1150// fTelescope
1151// fSequence
1152// fNight
1153// fMonteCarlo
1154// fCalRuns
1155// fCalRunsSub
1156// fPedRuns
1157// fPedRunsSub
1158// fDatRuns
1159// fDatRunsSub
1160// fDrsRuns
1161// fDrsRunsSub
1162// fExclRuns
1163// fExclRunsSub
1164//
1165Bool_t MSequence::IsCompatible(const MSequence &s) const
1166{
1167 return // Mandatory
1168 fTelescope == s.fTelescope &&
1169 fSequence == s.fSequence &&
1170 fNight == s.fNight &&
1171
1172 fMonteCarlo == s.fMonteCarlo &&
1173
1174 fCalRuns == s.fCalRuns &&
1175 fPedRuns == s.fPedRuns &&
1176 fDatRuns == s.fDatRuns &&
1177 fDrsRuns == s.fDrsRuns &&
1178 fExclRuns == s.fExclRuns &&
1179
1180 Check(fCalRunsSub, s.fCalRunsSub) &&
1181 Check(fPedRunsSub, s.fPedRunsSub) &&
1182 Check(fDatRunsSub, s.fDatRunsSub) &&
1183 Check(fDrsRunsSub, s.fDrsRunsSub) &&
1184 Check(fExclRunsSub, s.fExclRunsSub);
1185}
1186
1187// --------------------------------------------------------------------------
1188//
1189// Here we test whether all values of a sequence are identical
1190// IsCompaticle(s)
1191// fStart
1192// fLastRun
1193// fNumEvents
1194// fPeriod
1195// fProject
1196// fSource
1197// fRuns
1198// fHvSettings
1199// fTriggerTable
1200// fLightCondition
1201// fRuns
1202// fRunsSub
1203//
1204Bool_t MSequence::operator==(const MSequence &s) const
1205{
1206 return IsCompatible(s) &&
1207 // Unnecessary
1208 fStart == s.fStart &&
1209 fLastRun == s.fLastRun &&
1210 fNumEvents == s.fNumEvents &&
1211 fPeriod == s.fPeriod &&
1212 fProject == s.fProject &&
1213 fSource == s.fSource &&
1214 fRuns == s.fRuns &&
1215 fHvSettings == s.fHvSettings &&
1216 fTriggerTable == s.fTriggerTable &&
1217 fLightCondition == s.fLightCondition &&
1218 Check(fRunsSub, s.fRunsSub);
1219}
1220
1221// --------------------------------------------------------------------------
1222//
1223// Check whether the sequence has also identical source, i.e.
1224// the sequence filepath and the datapath in addition to operator==
1225//
1226Bool_t MSequence::IsIdentical(const MSequence &s) const
1227{
1228 return *this==s &&
1229 // Obsolete
1230 fDataPath==s.fDataPath && fFileName==s.fFileName;
1231}
1232
1233//---------------------------------------------------------------------------
1234//
1235// Make sure that the name used for writing doesn't contain a full path
1236//
1237const char *MSequence::GetBaseName() const
1238{
1239 return gSystem->BaseName(fFileName);
1240}
1241
1242//---------------------------------------------------------------------------
1243//
1244// Make sure that the name used for writing doesn't contain a full path
1245//
1246const char *MSequence::GetFilePath() const
1247{
1248 return gSystem->DirName(fFileName);
1249}
1250
1251// --------------------------------------------------------------------------
1252//
1253// Find a sequence of continous numbers in f starting at pos (looking
1254// only at n entries). The output is converted into sequences
1255// of X (single r) and X:Y (a sequence between x and r). The function
1256// returnes when position pos+n is reached
1257//
1258TString MSequence::GetNumSequence(Int_t pos, Int_t n, const TArrayI &f) const
1259{
1260 TString str;
1261
1262 Int_t p=pos;
1263 while (p<pos+n)
1264 {
1265 str += MString::Format(" %d", f[p]);
1266
1267 if (p==pos+n-1)
1268 break;
1269
1270 int i=0;
1271 while (++i<n)
1272 if (f[p+i]-f[p]!=i)
1273 break;
1274
1275 if (i>1)
1276 str += MString::Format(":%d", f[p+i-1]);
1277
1278 p += i;
1279 }
1280
1281 return str;
1282}
1283
1284// --------------------------------------------------------------------------
1285//
1286// Search for a sequence of continous numbers in r with f==0 starting at p.
1287// A new starting p is returned. The output is converted into sequences
1288// of X (single r) and X:Y (a sequence between x and r). The function
1289// returnes with the next f!=0.
1290//
1291TString MSequence::GetNumSequence(Int_t &p, const TArrayI &r, const TArrayI &f) const
1292{
1293 TString str;
1294
1295 while (p<r.GetSize() && f[p]==0)
1296 {
1297 // serach for the first entry which doesn't fit
1298 // or has a file number which is != 0
1299 int i=0;
1300 while (p+ ++i<r.GetSize())
1301 if (r[p+i]-r[p]!=i || f[p+i]!=0)
1302 break;
1303
1304 // None found (i-1==0)
1305 if (i-1==0)
1306 return str;
1307
1308 // The last run found in the sequence (e.g. 5.0) is followed
1309 // by an identical run number but file != 0 (e.g. 5.1)
1310 if (p+i<f.GetSize() && r[p+i]==r[p] && f[p+i]!=0)
1311 i--;
1312
1313 // Now we have to check again whether found no valid entry
1314 if (i-1==0)
1315 return str;
1316
1317 str += MString::Format(" %d", r[p]);
1318 // p now points to the last entry which fits and
1319 // has a file number == 0
1320 p += i-1;
1321 // Only one found (i-1==1)
1322 // More tahn one found (i-1>1)
1323 str += i-1==1 ? " " : ":";
1324 str += MString::Format("%d", r[p]);
1325
1326 // One step forward
1327 p++;
1328 }
1329
1330 return str;
1331}
1332
1333// --------------------------------------------------------------------------
1334//
1335// Print the runs in a compressed wa. Returns the RunXXXXXXX string
1336// simplyfing the file setup
1337//
1338TString MSequence::PrintRuns(ostream &out, const char *pre, const char *name, const TArrayI &r, const TArrayI &f) const
1339{
1340 if (r.GetSize()==0)
1341 return "";
1342
1343 out << pre << name;
1344 if (f.GetSize()==0)
1345 const_cast<TArrayI&>(f).Set(r.GetSize());
1346
1347#ifdef DEBUG
1348 for (int i=0; i<r.GetSize(); i++)
1349 out << " " << r[i] << "." << f[i];
1350 out << endl;
1351 return "";
1352#endif
1353
1354 TString str;
1355
1356 Int_t pos = 0;
1357 while (pos<r.GetSize())
1358 {
1359 TString rc = GetNumSequence(pos, r, f);
1360 if (!rc.IsNull())
1361 {
1362 out << rc;
1363 continue;
1364 }
1365
1366 Int_t n = GetSubArray(pos, r.GetSize(), (Int_t*)r.GetArray());
1367 // end reached
1368 if (n<0)
1369 break;
1370
1371 // This can happen if it is the last entry
1372 if (n==1)
1373 {
1374 out << " " << r[pos];
1375 if (f[pos]>=0)
1376 out << "." << f[pos];
1377 }
1378 else
1379 {
1380 // Check for sequence
1381 Bool_t isseq = kTRUE;
1382 for (int i=1; i<n; i++)
1383 if (f[pos+i]-f[pos]!=i)
1384 isseq=kFALSE;
1385
1386 if (isseq)
1387 {
1388 out << " " << r[pos] << ".";
1389 if (f[pos]>=0)
1390 out << f[pos];
1391 out << ":" << f[pos+n-1];
1392 }
1393 else
1394 {
1395 out << " " << r[pos] << "+";
1396
1397 str += '\n';
1398 str += pre;
1399 str += MString::Format("Run%08d:", r[pos]);
1400 str += GetNumSequence(pos, n, f);
1401 }
1402 }
1403
1404 pos += n;
1405 }
1406
1407 out << endl;
1408
1409 return str;
1410}
1411
1412// --------------------------------------------------------------------------
1413//
1414// Print the numbers in the classical way (one run after the other)
1415//
1416void MSequence::PrintRunsClassic(ostream &out, const char *pre, const char *name, const TArrayI &r) const
1417{
1418 out << pre << name;
1419 for (int i=0; i<r.GetSize(); i++)
1420 out << " " << r[i];
1421 out << endl;
1422}
1423
1424// --------------------------------------------------------------------------
1425//
1426// Print the contents of the sequence
1427//
1428void MSequence::Print(ostream &out, Option_t *o) const
1429{
1430 const TString opt(o);
1431
1432 const TString pre = opt.Contains("prefixed") ? MString::Format("Sequence%08d.", fSequence) : "";
1433
1434 if (!IsValid())
1435 {
1436 out << pre << "Sequence: " << fFileName << " <invalid>" << endl;
1437 return;
1438 }
1439 if (!fFileName.IsNull())
1440 out << "# FileName: " << fFileName << endl;
1441 if (!fDataPath.IsNull())
1442 out << "# DataPath: " << fDataPath << endl;
1443 out << endl;
1444 if (pre.IsNull())
1445 out << "Sequence: " << fSequence << endl;
1446 if (fTelescope!=1)
1447 out << "Telescope: " << fTelescope << endl;
1448 if (fMonteCarlo)
1449 out << pre << "MonteCarlo: Yes" << endl;
1450 if (fPeriod!=(UInt_t)-1)
1451 out << pre << "Period: " << fPeriod << endl;
1452 if (fNight!=MTime())
1453 out << pre << "Night: " << fNight.GetStringFmt("%Y-%m-%d") << endl;
1454 out << endl;
1455 if (fLightCondition!=kNA)
1456 {
1457 out << pre << "LightCondition: ";
1458 switch (fLightCondition)
1459 {
1460 case kNA: out << "n/a" << endl; break;
1461 case kNoMoon: out << "NoMoon" << endl; break;
1462 case kTwilight: out << "Twilight" << endl; break;
1463 case kMoon: out << "Moon" << endl; break;
1464 case kDay: out << "Day" << endl; break;
1465 }
1466 }
1467
1468 if (fStart!=MTime())
1469 out << pre << "Start: " << fStart.GetSqlDateTime() << endl;
1470 if (fLastRun!=(UInt_t)-1)
1471 out << pre << "LastRun: " << fLastRun << endl;
1472 if (fDrsSequence)
1473 out << pre << "DrsSequence: " << fDrsSequence << endl;
1474 if (fNumEvents!=(UInt_t)-1)
1475 out << pre << "NumEvents: " << fNumEvents << endl;
1476 if (!fProject.IsNull())
1477 out << pre << "Project: " << fProject << endl;
1478 if (!fSource.IsNull())
1479 out << pre << "Source: " << fSource << endl;
1480 if (!fTriggerTable.IsNull())
1481 out << pre << "TriggerTable: " << fTriggerTable << endl;
1482 if (!fHvSettings.IsNull())
1483 out << pre << "HvSettings: " << fHvSettings << endl;
1484 out << endl;
1485
1486 TString str;
1487 if (!HasSubRuns() && opt.Contains("classic"))
1488 {
1489 PrintRunsClassic(out, pre, "Runs: ", fRuns);
1490 PrintRunsClassic(out, pre, "CalRuns: ", fCalRuns);
1491 PrintRunsClassic(out, pre, "PedRuns: ", fPedRuns);
1492 PrintRunsClassic(out, pre, "DataRuns: ", fDatRuns);
1493 PrintRunsClassic(out, pre, "DrsRuns: ", fDrsRuns);
1494 PrintRunsClassic(out, pre, "DrsFiles: ", fDrsFiles);
1495 PrintRunsClassic(out, pre, "Exclude: ", fExclRuns);
1496 }
1497 else
1498 {
1499 // FIXME: This needs more check!
1500 // FORBID the + syntax in "Runs"
1501 // Could we make "Runs" an automatic summary of all runs?
1502 // Should we add a check forbidding the same run in
1503 // Cal/Ped/Data? What about the Exclude?
1504 /*str +=*/ PrintRuns(out, pre, "Runs: ", fRuns, fRunsSub);
1505 str += PrintRuns(out, pre, "CalRuns: ", fCalRuns, fCalRunsSub);
1506 str += PrintRuns(out, pre, "PedRuns: ", fPedRuns, fPedRunsSub);
1507 str += PrintRuns(out, pre, "DatRuns: ", fDatRuns, fDatRunsSub);
1508 str += PrintRuns(out, pre, "DrsRuns: ", fDrsRuns, fDrsRunsSub);
1509 str += PrintRuns(out, pre, "DrsFiles: ", fDrsFiles, fDrsFilesSub);
1510 str += PrintRuns(out, pre, "Exclude: ", fExclRuns, fExclRunsSub);
1511 }
1512
1513// if (!fDataPath.IsNull())
1514// out << endl << pre << "DataPath: " << fDataPath << endl;
1515
1516 if (!str.IsNull())
1517 out << str << endl;
1518
1519 out << endl;
1520
1521 if (!fComment.IsNull())
1522 out << pre << "Comment: " << fComment << endl;
1523
1524 if (GetDrsFile())
1525 out << "# DrsFile: " << GetDrsFile() << endl;
1526}
1527
1528// --------------------------------------------------------------------------
1529//
1530// Print the contents of the sequence to gLog
1531//
1532void MSequence::Print(Option_t *o) const
1533{
1534 gLog << all;
1535 Print(gLog, o);
1536}
1537
1538// --------------------------------------------------------------------------
1539//
1540// Print the contents of the sequence to the file with name filename
1541//
1542Bool_t MSequence::WriteFile(const char *name, const Option_t *o) const
1543{
1544 ofstream fout(name);
1545 if (!fout)
1546 {
1547 gLog << err << "ERROR - Cannot open file " << name << ": ";
1548 gLog << strerror(errno) << endl;
1549 return kFALSE;
1550 }
1551
1552 Print(fout, o);
1553
1554 if (!fout)
1555 {
1556 gLog << err << "ERROR - Writing file " << name << ": ";
1557 gLog << strerror(errno) << endl;
1558 return kFALSE;
1559 }
1560
1561 return kTRUE;
1562}
1563
1564// --------------------------------------------------------------------------
1565//
1566// check if the run/file is contained in the arrays.
1567//
1568Bool_t MSequence::IsContained(const TArrayI &arr, const TArrayI &sub, UInt_t run, UInt_t file) const
1569{
1570 // Backward compatibilty
1571 if (sub.GetSize()==0)
1572 {
1573 for (int i=0; i<arr.GetSize(); i++)
1574 if (run==(UInt_t)arr[i])
1575 return kTRUE;
1576 }
1577 else
1578 {
1579 for (int i=0; i<arr.GetSize(); i++)
1580 if (run==(UInt_t)arr[i] && file==(UInt_t)sub[i])
1581 return kTRUE;
1582 }
1583 return kFALSE;
1584}
1585
1586// --------------------------------------------------------------------------
1587//
1588// Exclude all runs which are found in the list, e.g. "100 102 105"
1589//
1590void MSequence::ExcludeRuns(TString runs)
1591{
1592 // FIXME: Decode stream!!!
1593
1594 TArrayI data, sub;
1595 Split(runs, data, sub);
1596 for (int i=0; i<data.GetSize(); i++)
1597 ExcludeFile(data[i], sub[i]);
1598}
1599
1600// --------------------------------------------------------------------------
1601//
1602// Return the excluded runs (to be more precise:the excluded files)
1603// in a string
1604//
1605const TString MSequence::GetExcludedRuns() const
1606{
1607 TString rc;
1608 for (int i=0; i<fExclRuns.GetSize(); i++)
1609 {
1610 rc += fExclRuns[i];
1611 if (fExclRunsSub.GetSize()>0)
1612 {
1613 rc += ".";
1614 rc += fExclRunsSub[i];
1615 }
1616 rc += " ";
1617 }
1618 return rc(0, rc.Length()-1);
1619}
1620
1621// --------------------------------------------------------------------------
1622//
1623// If you want to change or set the night manually.
1624// The Format is
1625// SetNight("yyyy-mm-dd");
1626//
1627void MSequence::SetNight(const char *txt)
1628{
1629 TString night(txt);
1630
1631 if (night.IsNull())
1632 {
1633 fNight = MTime();
1634 fPeriod = UInt_t(-1);
1635 return;
1636 }
1637
1638 night += " 00:00:00";
1639 fNight.SetSqlDateTime(night);
1640
1641 fPeriod = fNight.GetMagicPeriod();
1642}
1643
1644// --------------------------------------------------------------------------
1645//
1646// Read a sequence from gDirectory. If the default is given we try
1647// to find a sequence with name GetName. If a key with name name
1648// exists in the file read this key. Otherwise loop over all keys
1649// and return the first key matching the TPRegex (regular expression)
1650// matching defined by the argument.
1651//
1652Int_t MSequence::Read(const char *name)
1653{
1654 if (!name || !gDirectory)
1655 return MParContainer::Read(name);
1656
1657 if (gDirectory->GetListOfKeys()->FindObject(name))
1658 return MParContainer::Read(name);
1659
1660 TPRegexp regexp(name);
1661
1662 TIter NextK(gDirectory->GetListOfKeys());
1663 TObject *key = 0;
1664 while ((key=NextK()))
1665 if (TString(key->GetName())(regexp)==key->GetName())
1666 return MParContainer::Read(key->GetName());
1667
1668 *fLog << warn << "WARNING - No key in " << gDirectory->GetName() << " matching " << name << "." << endl;
1669 return 0;
1670}
1671
1672// --------------------------------------------------------------------------
1673//
1674// If the sequence name seq is just a digit it is inflated to a full
1675// path following the datacenter standard.
1676//
1677// Returns if file accessible or not.
1678//
1679Bool_t MSequence::InflateSeq(TString &seq, Bool_t ismc)
1680{
1681 TObjArray *arr = seq.Tokenize(':');
1682 if (arr->GetEntries()<3)
1683 {
1684 TString num1 = (*arr)[0]->GetName();
1685 TString num2 = arr->GetEntries()==2 ? (*arr)[1]->GetName() : "";
1686
1687 if (num1.IsDigit() && num2.IsDigit())
1688 {
1689 gLog << err << "ERROR - InflateSeq 'telescope:sequence' not yet implemented." << endl;
1690 delete arr;
1691 return kFALSE;
1692 }
1693
1694 if (num1.IsDigit() && num2.IsNull())
1695 {
1696 const Int_t numseq = seq.Atoi();
1697 seq = "/magic/";
1698 if (ismc)
1699 seq += "montecarlo/";
1700 seq += MString::Format("sequences/%04d/sequence%08d.txt", numseq/10000, numseq);
1701 gLog << inf << "Inflated sequence file: " << seq << endl;
1702 }
1703 }
1704 delete arr;
1705
1706 if (!gSystem->AccessPathName(seq, kFileExists))
1707 return kTRUE;
1708
1709 gLog << err << "Sorry, sequence file '" << seq << "' doesn't exist." << endl;
1710 return kFALSE;
1711}
1712
1713// --------------------------------------------------------------------------
1714//
1715// Search starting at position p in array arr and return the number
1716// of elemets which are identical to the starting entry (the starting entry
1717// is also counted)
1718//
1719Int_t MSequence::GetSubArray(Int_t p, Int_t n, Int_t *arr)
1720{
1721 Int_t *ptr0 = arr+p;
1722
1723 Int_t *ptr = ptr0;
1724 Int_t *end = arr+n;
1725
1726 while (ptr<end && *ptr==*ptr0)
1727 ptr++;
1728
1729 return ptr-ptr0;
1730}
1731
1732// --------------------------------------------------------------------------
1733//
1734// Sort the array arr2 starting at position p for following entries
1735// for which arr1 is equal. If not at least two entries are found which
1736// can be sorted return -1.
1737//
1738// The absolute index of the next entry in arr1 is returned.
1739//
1740Int_t MSequence::SortArraySub(Int_t p, Int_t n, Int_t *arr1, Int_t *arr2)
1741{
1742 Int_t *ptr2 = arr2+p;
1743
1744 Int_t cnt = GetSubArray(p, n, arr1);
1745 if (cnt==0)
1746 return -1;
1747
1748 TArrayI srt(cnt, ptr2);
1749 MJob::SortArray(srt);
1750
1751 memcpy(ptr2, srt.GetArray(), srt.GetSize()*sizeof(Int_t));
1752
1753 return p+srt.GetSize();
1754}
1755
1756void MSequence::SortArrays(TArrayI &arr1, TArrayI &arr2)
1757{
1758 if (arr1.GetSize()!=arr2.GetSize())
1759 return;
1760
1761 TArrayI idx(arr1.GetSize());
1762
1763 TArrayI srt1(arr1);
1764 TArrayI srt2(arr2);
1765
1766 TMath::Sort(arr1.GetSize(), srt1.GetArray(), idx.GetArray(), kFALSE);
1767
1768 for (int i=0; i<arr1.GetSize(); i++)
1769 {
1770 arr1[i] = srt1[idx[i]];
1771 arr2[i] = srt2[idx[i]];
1772 }
1773
1774 Int_t p = 0;
1775 while (p>=0)
1776 p = SortArraySub(p, arr1.GetSize(), arr1.GetArray(), arr2.GetArray());
1777}
Note: See TracBrowser for help on using the repository browser.