source: trunk/Mars/mjobs/MSequence.cc@ 14449

Last change on this file since 14449 was 12795, checked in by tbretz, 13 years ago
implemented more arrays to be able to keep four different types of files; implemented a new keyword to keep the number of a corresponding DRS calibration file
File size: 49.8 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&kRunType)==kDrsFile)
475 {
476 n += night.GetStringFmt("%Y%m%d_");
477 n += MString::Format("%03d", run);
478 n += ".drs.fits.?g?z?";
479 return n;
480 }
481 if ((type&kFileType)==kFits)
482 {
483 n += night.GetStringFmt("%Y%m%d_");
484 n += MString::Format("%03d", run);
485 n += ".fits.?g?z?";
486 return n;
487 }
488
489 const char *id="_";
490 switch ((RunType_t)(type&kRunType))
491 {
492 case kDat:
493 id = "D";
494 break;
495 case kPed:
496 id = "P";
497 break;
498 case kCal:
499 id = "C";
500 break;
501 case kAll:
502 id = "[PCD]";
503 break;
504 case kCalib:
505 id = "Y";
506 break;
507 case kImage:
508 id = "I";
509 break;
510 case kExcl:
511 break;
512 }
513
514 // Is report file?
515 const Bool_t isrep = type&kReport;
516
517 // Calculate limit for transition from 5-digit to 8-digit numbers
518 const Int_t limit = isrep ? 39373 : 35487;
519
520 // ------------- Create file name --------------
521 if (night)
522 n += night.GetStringFmt("%Y%m%d_");
523
524 // This is for MCs (FIXME!!!!)
525 if (run<0)
526 {
527 n += MString::Format("%08d", -run);
528 if (file>=0)
529 n += MString::Format(".%03d", file);
530 }
531 else
532 {
533 if (tel>0)
534 n += MString::Format("M%d_", tel);
535
536 // R. DeLosReyes and T. Bretz
537 // Changes to read the DAQ numbering format. Changes takes place
538 // between runs 35487 and 00035488 (2004_08_30)
539 n += MString::Format(run>limit ? "%08d" : "%05d", run);
540
541 if (tel>0)
542 n += MString::Format(".%03d", file);
543 }
544
545
546 n += "_";
547 n += id;
548 n += "_*";
549
550 if (tel==0 && run>=0)
551 n += isrep ? "_S" : "_E";
552
553 switch (type&kFileType)
554 {
555 case kRaw: // MC // DATA
556 n += run<0 ? ".root" : ".raw.?g?z?"; // TPRegexp: (\.gz)?
557 break;
558 case kReport:
559 n += ".rep"; // TPRegexp: (\.gz)?
560 break;
561 default:
562 n += ".root";
563 break;
564 }
565
566 return n;
567}
568
569// --------------------------------------------------------------------------
570//
571// Return the expression describing the file-name for the file defined
572// by i-th entry of the the given arrays. The file type identifier is
573// defined by type. The source name is replaced by a wildcard and
574// the extension is defined by the type as well.
575//
576TString MSequence::GetFileRegexp(UInt_t i, const TArrayI &arr, const TArrayI &sub, FileType_t type) const
577{
578 // Entry doesn't exist
579 if (i>=(UInt_t)arr.GetSize())
580 return "";
581
582 // This is (so far) well defined for MAGIC data
583 if (!fMonteCarlo)
584 return InflateFileName(fNight, arr[i]>999999?fTelescope:0, arr[i], sub.GetSize()>0?sub[i]:0, type);
585
586 // Monte Carlos
587 return InflateFileName(fNight, fTelescope, -arr[i], sub.GetSize()>0?sub[i]:0, type);
588}
589
590// --------------------------------------------------------------------------
591//
592// Get the filename from the dirctory and the file-regexp.
593// return "" if file is not accessible or the regular expression is not
594// unambiguous.
595//
596TString MSequence::FindFile(const TString &d, const TString &f) const
597{
598 // Check existance and accessibility of file
599 MDirIter file(d, f, 0);
600
601 TString name = file();
602 gSystem->ExpandPathName(name);
603 if (gSystem->AccessPathName(name, kFileExists))
604 {
605 *fLog << err;
606 *fLog << "ERROR - File " << d << f << " not accessible!" << endl;
607 return "";
608 }
609 if (!file().IsNull())
610 {
611 *fLog << err;
612 *fLog << "ERROR - Searching for file " << d << f << " gave more than one result!" << endl;
613 return "";
614 }
615
616 return name;
617}
618
619// --------------------------------------------------------------------------
620//
621// Set the path accoring to type (if fDataPath=path=0), fDataPath
622// (if path=0) or path.
623// Returns accessability of the path.
624//
625Bool_t MSequence::FindPath(TString &path, FileType_t type) const
626{
627 if (path.IsNull())
628 path = fDataPath;
629
630 const Bool_t def = path.IsNull();
631
632 path = GetPathName(path, type);
633
634 return def;
635}
636
637// --------------------------------------------------------------------------
638//
639// Add the entries from the arrays to the MDirIter
640//
641UInt_t MSequence::GetRuns(MDirIter &iter, const TArrayI &arr, const TArrayI &sub, FileType_t type, TString path) const
642{
643 const Bool_t def = FindPath(path, type);
644
645 // For this particular case we assume that the files are added one by
646 // one without wildcards.
647 const Int_t n0 = iter.GetNumEntries();
648
649 Int_t excluded = 0;
650 for (int i=0; i<arr.GetSize(); i++)
651 {
652 if (IsExcluded(arr[i], sub[i]))
653 {
654 excluded++;
655 continue;
656 }
657
658 const TString n = GetFileRegexp(i, arr, sub, type);
659
660 if (FindFile(path, n).IsNull())
661 continue;
662
663 // Add Path/File to TIter
664 iter.AddDirectory(path, n, 0);
665 }
666
667 // n0: The previous contents of the iter
668 // n1: The number of files which have been added to the iter
669 // n2: The number of files which should have been added from the array
670 const Int_t n1 = iter.GetNumEntries()-n0;
671 const Int_t n2 = arr.GetSize()-excluded;
672 if (n1==0)
673 {
674 *fLog << err;
675 *fLog << "ERROR - No input files for sequence #" << GetSequence() << endl;
676 *fLog << " read from " << GetBaseName() << endl;
677 *fLog << " found in" << (def?" default-path ":" ") << path << endl;
678 return 0;
679 }
680
681 if (n1==n2)
682 return n1;
683
684 *fLog << err;
685 *fLog << "ERROR - " << n1 << " input files for sequence #" << GetSequence() << " found in" << endl;
686 *fLog << " " << (def?" default-path ":" ") << path << endl;
687 *fLog << " but " << n2 << " files were defined in sequence file" << endl;
688 *fLog << " " << GetBaseName() << endl;
689 if (fLog->GetDebugLevel()<=4)
690 return 0;
691
692 *fLog << inf << "Files which are searched for this sequence:" << endl;
693 iter.Print();
694 return 0;
695}
696
697UInt_t MSequence::GetDrsFile() const
698{
699 if (fDrsRuns.GetSize()==0)
700 return fDrsFiles[0];
701
702 UInt_t rc = 0;
703 for (int i=0; i<fDrsFiles.GetSize(); i++)
704 {
705 for (int j=0; j<fPedRuns.GetSize(); j++)
706 {
707 if (fDrsFiles[i]==fPedRuns[j])
708 rc = fDrsFiles[i];
709 }
710 }
711
712 return rc;
713}
714
715// --------------------------------------------------------------------------
716//
717// Returns "0" if file at i-th index is excluded. Get the access-path
718// defined by the default or data-path (if path=0) or path.
719// Get the full file-name by accessing the file.
720//
721TString MSequence::GetFileName(UInt_t i, const TArrayI &arr, const TArrayI &sub, FileType_t type, const char *path) const
722{
723 if (i>=(UInt_t)arr.GetSize())
724 return "";
725
726 if (IsExcluded(arr[i], sub[i]))
727 return "0";
728
729 const TString d = FindPath(type, path);
730 const TString n = GetFileRegexp(i, arr, sub, type);
731
732 return FindFile(d, n);
733}
734
735// --------------------------------------------------------------------------
736//
737// Return the pointers to the arrays with the runs/files depending on the
738// given type.
739//
740void MSequence::GetArrays(const TArrayI* &r, const TArrayI* &f, Int_t type) const
741{
742 switch ((RunType_t)(type&(kRunType|kExcl)))
743 {
744 case kDrsRun:
745 r = &fDrsRuns;
746 f = &fDrsRunsSub;
747 break;
748 case kDrsFile:
749 r = &fDrsFiles;
750 f = &fDrsFilesSub;
751 break;
752 case kPed:
753 r = &fPedRuns;
754 f = &fPedRunsSub;
755 break;
756 case kDat:
757 case kImage:
758 case kCalib:
759 r = &fDatRuns;
760 f = &fDatRunsSub;
761 break;
762 case kCal:
763 r = &fCalRuns;
764 f = &fCalRunsSub;
765 break;
766 case kExcl:
767 r = &fExclRuns;
768 f = &fExclRunsSub;
769 break;
770 case kAll:
771 r = &fRuns;
772 f = &fRunsSub;
773 break;
774 }
775}
776
777// --------------------------------------------------------------------------
778//
779// Add runs from the sequence to MDirIter. If path==0 fDataPath is
780// used instead. If it is also empty the standard path of the
781// data-center is assumed. If you have the runs locally use path="."
782//
783// Returns the number of files added.
784//
785// Runs which are in fExlRuns are ignored.
786//
787UInt_t MSequence::GetRuns(MDirIter &iter, FileType_t type, const char *path) const
788{
789 const TArrayI *r=0, *f=0;
790 GetArrays(r, f, type);
791 return r==0 ? 0 : GetRuns(iter, *r, *f, type, path);
792}
793
794// --------------------------------------------------------------------------
795//
796// Returns the num-th entry of FileType_t as regular expression.
797// If the file is excluded return "".
798// To get the number of valid entries use GetNumEntries(FileType_t)
799//
800// e.g.
801// if (GetNumEntries(MSequence::kDat))<5)
802// GetFileRegexp(3, MSequence::kRawDat);
803//
804TString MSequence::GetFileRegexp(UInt_t num, FileType_t type) const
805{
806 const TArrayI *r=0, *f=0;
807 GetArrays(r, f, type);
808
809 TString rc = GetFileRegexp(num, *r, *f, type);
810 rc.ReplaceAll(".", "\\.");
811 rc.ReplaceAll("*", ".*");
812 return rc;
813}
814
815// --------------------------------------------------------------------------
816//
817// Returns the num-th entry of FileType_t as filename. To access the
818// path the default is used if path IsNull, path otherwise.
819// If the file could not be accessed "" is returned, if it is
820// excluded "0".
821// To get the number of valid entries use GetNumEntries(FileType_t)
822//
823// e.g.
824// if (GetNumEntries(MSequence::kDat))<5)
825// GetFileName(3, MSequence::kRawDat);
826//
827TString MSequence::GetFileName(UInt_t num, FileType_t type, const char *path) const
828{
829 const TArrayI *r=0, *f=0;
830 GetArrays(r, f, type);
831 return GetFileName(num, *r, *f, type, path);
832}
833
834// --------------------------------------------------------------------------
835//
836// Returns the num-th entry of FileType_t as filename.
837// If the file could not be accessed or excluded return "".
838// To get the number of valid entries use GetNumEntries(RunType_t)
839//
840UInt_t MSequence::GetNumEntries(RunType_t type) const
841{
842 const TArrayI *r=0, *f=0;
843 GetArrays(r, f, type);
844 return r->GetSize();
845}
846
847// --------------------------------------------------------------------------
848//
849// Returns the num-th entry of RunType_t as run- and file-number.
850// Returns -1 if index is out of range, 0 if file is excluded and
851// 1 in case of success.
852//
853// e.g.
854// UInt_t run, file;
855// GetFile(3, MSequence::kDat, run, file);
856//
857Int_t MSequence::GetFile(UInt_t i, RunType_t type, UInt_t &run, UInt_t &file) const
858{
859 const TArrayI *r=0, *f=0;
860 GetArrays(r, f, type);
861
862 if (i>=(UInt_t)r->GetSize())
863 return -1;
864
865 run = (*r)[i];
866 file = i<(UInt_t)f->GetSize() ? (*f)[i] : 0;
867
868 if (IsExcluded(run, file))
869 return 0;
870
871 return 1;
872}
873
874// --------------------------------------------------------------------------
875//
876// Add a file (run/file) to the arrays defined by RunType_t
877//
878void MSequence::AddFile(UInt_t run, UInt_t file, RunType_t type)
879{
880 const TArrayI *rconst=0, *fconst=0;
881
882 GetArrays(rconst, fconst, type);
883
884 if (!rconst || !fconst)
885 {
886 *fLog << err << "ERROR - Invalid values returned by MSequence::GetArrays... " << run << "." << file << " ignored." << endl;
887 return;
888 }
889
890 TArrayI &r=*const_cast<TArrayI*>(rconst);
891 TArrayI &f=*const_cast<TArrayI*>(fconst);
892
893 AddEntry(run, file, r, f);
894
895 SortArrays(r, f);
896}
897
898// --------------------------------------------------------------------------
899//
900// Get LightCondition from str and convert it to LightCondition_t
901//
902MSequence::LightCondition_t MSequence::GetLightCondition(const TString &str) const
903{
904 if (!str.CompareTo("n/a", TString::kIgnoreCase))
905 return kNA;
906 if (!str.CompareTo("No_Moon", TString::kIgnoreCase))
907 return kNoMoon;
908 if (!str.CompareTo("NoMoon", TString::kIgnoreCase))
909 return kNoMoon;
910 if (!str.CompareTo("Twilight", TString::kIgnoreCase))
911 return kTwilight;
912 if (!str.CompareTo("Moon", TString::kIgnoreCase))
913 return kMoon;
914 if (!str.CompareTo("Day", TString::kIgnoreCase))
915 return kDay;
916
917 gLog << warn;
918 gLog << "WARNING - in " << GetBaseName() << ":" << endl;
919 gLog << " LightCondition-tag is '" << str << "' but must be n/a, no_moon, twilight, moon or day." << endl;
920 return kNA;
921}
922
923// --------------------------------------------------------------------------
924//
925// Set the path to the data. If no path is given the data-center default
926// path is used to access the files.
927//
928// kTRUE is returned if the path is acessible, kFALSE otherwise.
929// (In case of the default path kTRUE is returned in any case)
930//
931Bool_t MSequence::SetDataPath(const char *path)
932{
933 fDataPath = path;
934
935 gSystem->ExpandPathName(fDataPath);
936
937 const Bool_t rc = !fDataPath.IsNull() && gSystem->AccessPathName(fDataPath, kFileExists);
938 if (rc)
939 gLog << err << "ERROR - Directory '" << fDataPath << "' doesn't exist." << endl;
940
941 return !rc;
942}
943
944// --------------------------------------------------------------------------
945//
946// Read a sequence from a file. To set the location of the data (datapath)
947// use SetDataPath. The sequence number given is used if no sequence
948// number is found in the sequence file.
949//
950// If the file could not be found or accesed kFALSE is returned, kTRUE
951// otherwise.
952//
953Bool_t MSequence::ReadFile(const char *filename, UInt_t seq)
954{
955 fFileName = filename;
956
957 gSystem->ExpandPathName(fFileName);
958
959 const Bool_t rc = gSystem->AccessPathName(fFileName, kFileExists);
960 if (rc)
961 gLog << err << "ERROR - Sequence file '" << filename << "' doesn't exist." << endl;
962
963 MEnv env(fFileName);
964
965 fSequence = (UInt_t)env.GetValue("Sequence", (Int_t)seq);
966
967 const TString prefix = MString::Format("Sequence%08d", fSequence);
968
969 fTelescope = GetEnvValue2(env, prefix, "Telescope", 1);
970 fLastRun = GetEnvValue2(env, prefix, "LastRun", -1);
971 fNumEvents = GetEnvValue2(env, prefix, "NumEvents", -1);
972 fDrsSequence = GetEnvValue2(env, prefix, "DrsSequence", 0);
973
974 TString str;
975 str = GetEnvValue2(env, prefix, "LightCondition", "n/a");
976 fLightCondition = GetLightCondition(str);
977
978 str = GetEnvValue2(env, prefix, "Start", "");
979 fStart.SetSqlDateTime(str);
980
981 str = GetEnvValue2(env, prefix, "Night", "");
982 SetNight(str);
983
984 fProject = GetEnvValue2(env, prefix, "Project", "");
985 fSource = GetEnvValue2(env, prefix, "Source", "");
986 fTriggerTable = GetEnvValue2(env, prefix, "TriggerTable", "");
987 fHvSettings = GetEnvValue2(env, prefix, "HvSettings", "");
988 fMonteCarlo = GetEnvValue2(env, prefix, "MonteCarlo", kFALSE);
989 fComment = GetEnvValue2(env, prefix, "Comment", "");
990
991 Split(env, prefix, "Runs", fRuns, fRunsSub);
992 Split(env, prefix, "CalRuns", fCalRuns, fCalRunsSub);
993 Split(env, prefix, "PedRuns", fPedRuns, fPedRunsSub);
994 Split(env, prefix, "DatRuns", fDatRuns, fDatRunsSub);
995 Split(env, prefix, "DrsRuns", fDrsRuns, fDrsRunsSub);
996 Split(env, prefix, "DrsFiles",fDrsFiles, fDrsFilesSub);
997 Split(env, prefix, "Exclude", fExclRuns, fExclRunsSub);
998
999 if (fDrsRuns.GetSize()==0 && fDrsFiles.GetSize()>1)
1000 gLog << warn << "WARNING - In a data sequence only one DrsFiles entry makes sense." << endl;
1001
1002 // Dummies:
1003 env.Touch("Period");
1004 env.Touch("ZdMin");
1005 env.Touch("ZdMax");
1006 env.Touch("L1TriggerTable");
1007 env.Touch("L2TriggerTable");
1008
1009 if (seq==(UInt_t)-1 && env.GetNumUntouched()>0)
1010 {
1011 gLog << warn << "WARNING - At least one resource in the sequence-file has not been touched!" << endl;
1012 env.PrintUntouched();
1013 }
1014
1015 return !rc;
1016}
1017
1018// --------------------------------------------------------------------------
1019//
1020// Instantiate a file from either a file or the database.
1021//
1022// If not valid sequence could be created the sequence is invalidated,
1023// which can be queried with IsValid.
1024//
1025// see ReadFile, ReadDatabase and SetDataPath for more details.
1026//
1027MSequence::MSequence(const char *fname, const char *path, UInt_t seq)
1028 : fTelescope(1), fSequence((UInt_t)-1), fLastRun((UInt_t)-1),
1029 fNumEvents((UInt_t)-1), fPeriod((UInt_t)-1), fLightCondition(kNA),
1030 fMonteCarlo(kFALSE)
1031{
1032 fName = "MSequence";
1033 fTitle = "Sequence file";
1034
1035 if (TString(fname).IsNull() && TString(path).IsNull() && seq==(UInt_t)-1)
1036 return;
1037
1038 // regular expression to distinguish beween a mysql-path and
1039 // a filename from where the sequence should be retrieved
1040 TPRegexp regexp("mysql://[a-zA-Z0-9]+:.+@[a-zA-Z0-9]+/[a-zA-Z0-9]+/([0-9]+:)?[0-9]+");
1041
1042 const TString db = TString(fname)(regexp);
1043
1044 const Bool_t rc1 = db.IsNull() ? ReadFile(fname, seq) : ReadDatabase(fname, seq);
1045 const Bool_t rc2 = SetDataPath(path);
1046
1047 if (!rc1 || !rc2)
1048 fSequence = (UInt_t)-1;
1049}
1050
1051// --------------------------------------------------------------------------
1052//
1053// Read a sequence from the database. Give the path to the database as:
1054// mysql://user:password@name/database
1055// In this case you MUST give a sequence number.
1056//
1057// You can code the telescope and sequence number into the path and
1058// omit the arguments:
1059// mysql://user:password@name/database/[tel:]sequence
1060//
1061// The third option is to give just the sql.rc as string in the argument.
1062// In this case you MUST give a sequence number.
1063//
1064// If the telecope number is omitted as argument, i.e. ==0, or in the
1065// database path, a sequence is read from the database if the sequence
1066// number is unambiguous.
1067//
1068// kFALSE is returned if the final sequence is invalid, kTRUE in case of
1069// success.
1070//
1071Bool_t MSequence::ReadDatabase(TString name, UInt_t seq, UShort_t tel)
1072{
1073 TPRegexp regexp("([0-9]+:)?[0-9]+$");
1074
1075 const TString telseq = name(regexp);
1076
1077 if (!telseq.IsNull())
1078 {
1079 const Ssiz_t p = telseq.First(':');
1080
1081 const TString strtel = p<0 ? TString("") : telseq(0, p);
1082 const TString strseq = telseq(p+1, telseq.Length());
1083
1084 tel = strtel.Atoi();
1085 seq = strseq.Atoi();
1086
1087 name = gSystem->DirName(name);
1088 }
1089
1090 *this = MSequenceSQL(name, seq, tel);
1091
1092 return IsValid();
1093}
1094
1095// --------------------------------------------------------------------------
1096//
1097// Create a sequence from the database, e.g.
1098//
1099// TString mysql = "mysql://MAGIC:password@vela/MyMagic";
1100// Int_t sequence = 100002;
1101// Int_t telescope = 1;
1102//
1103// MSequence seq(mysql, sequence, telescope);
1104//
1105// Is the telescope number is omitted (==0) the database is checked for
1106// an unambiguous sequence.
1107//
1108// For more details see ReadDatabase and MSequenceSQL.
1109//
1110MSequence::MSequence(const char *fname, UInt_t seq, UShort_t tel)
1111{
1112 const Bool_t rc = ReadDatabase(fname, seq, tel);
1113
1114 fName = "MSequence";
1115 fTitle = "Sequence file";
1116
1117 if (!rc)
1118 fSequence = (UInt_t)-1;
1119}
1120
1121// --------------------------------------------------------------------------
1122//
1123// Some helper functions for the comparison functions
1124//
1125static int operator==(const TArrayI &a, const TArrayI &b)
1126{
1127 return a.GetSize()==b.GetSize() &&
1128 memcmp(a.GetArray(), b.GetArray(), a.GetSize()*sizeof(Int_t));
1129}
1130
1131static int IsNull(const TArrayI &a, const TArrayI &b)
1132{
1133 return a==TArrayI(a.GetSize()) && b==TArrayI(b.GetSize());
1134}
1135
1136static int Check(const TArrayI &a, const TArrayI &b)
1137{
1138 return a==b || IsNull(a, b);
1139}
1140
1141// --------------------------------------------------------------------------
1142//
1143// Here we test all things mandatory for a sequence:
1144// fTelescope
1145// fSequence
1146// fNight
1147// fMonteCarlo
1148// fCalRuns
1149// fCalRunsSub
1150// fPedRuns
1151// fPedRunsSub
1152// fDatRuns
1153// fDatRunsSub
1154// fDrsRuns
1155// fDrsRunsSub
1156// fExclRuns
1157// fExclRunsSub
1158//
1159Bool_t MSequence::IsCompatible(const MSequence &s) const
1160{
1161 return // Mandatory
1162 fTelescope == s.fTelescope &&
1163 fSequence == s.fSequence &&
1164 fNight == s.fNight &&
1165
1166 fMonteCarlo == s.fMonteCarlo &&
1167
1168 fCalRuns == s.fCalRuns &&
1169 fPedRuns == s.fPedRuns &&
1170 fDatRuns == s.fDatRuns &&
1171 fDrsRuns == s.fDrsRuns &&
1172 fExclRuns == s.fExclRuns &&
1173
1174 Check(fCalRunsSub, s.fCalRunsSub) &&
1175 Check(fPedRunsSub, s.fPedRunsSub) &&
1176 Check(fDatRunsSub, s.fDatRunsSub) &&
1177 Check(fDrsRunsSub, s.fDrsRunsSub) &&
1178 Check(fExclRunsSub, s.fExclRunsSub);
1179}
1180
1181// --------------------------------------------------------------------------
1182//
1183// Here we test whether all values of a sequence are identical
1184// IsCompaticle(s)
1185// fStart
1186// fLastRun
1187// fNumEvents
1188// fPeriod
1189// fProject
1190// fSource
1191// fRuns
1192// fHvSettings
1193// fTriggerTable
1194// fLightCondition
1195// fRuns
1196// fRunsSub
1197//
1198Bool_t MSequence::operator==(const MSequence &s) const
1199{
1200 return IsCompatible(s) &&
1201 // Unnecessary
1202 fStart == s.fStart &&
1203 fLastRun == s.fLastRun &&
1204 fNumEvents == s.fNumEvents &&
1205 fPeriod == s.fPeriod &&
1206 fProject == s.fProject &&
1207 fSource == s.fSource &&
1208 fRuns == s.fRuns &&
1209 fHvSettings == s.fHvSettings &&
1210 fTriggerTable == s.fTriggerTable &&
1211 fLightCondition == s.fLightCondition &&
1212 Check(fRunsSub, s.fRunsSub);
1213}
1214
1215// --------------------------------------------------------------------------
1216//
1217// Check whether the sequence has also identical source, i.e.
1218// the sequence filepath and the datapath in addition to operator==
1219//
1220Bool_t MSequence::IsIdentical(const MSequence &s) const
1221{
1222 return *this==s &&
1223 // Obsolete
1224 fDataPath==s.fDataPath && fFileName==s.fFileName;
1225}
1226
1227//---------------------------------------------------------------------------
1228//
1229// Make sure that the name used for writing doesn't contain a full path
1230//
1231const char *MSequence::GetBaseName() const
1232{
1233 return gSystem->BaseName(fFileName);
1234}
1235
1236//---------------------------------------------------------------------------
1237//
1238// Make sure that the name used for writing doesn't contain a full path
1239//
1240const char *MSequence::GetFilePath() const
1241{
1242 return gSystem->DirName(fFileName);
1243}
1244
1245// --------------------------------------------------------------------------
1246//
1247// Find a sequence of continous numbers in f starting at pos (looking
1248// only at n entries). The output is converted into sequences
1249// of X (single r) and X:Y (a sequence between x and r). The function
1250// returnes when position pos+n is reached
1251//
1252TString MSequence::GetNumSequence(Int_t pos, Int_t n, const TArrayI &f) const
1253{
1254 TString str;
1255
1256 Int_t p=pos;
1257 while (p<pos+n)
1258 {
1259 str += MString::Format(" %d", f[p]);
1260
1261 if (p==pos+n-1)
1262 break;
1263
1264 int i=0;
1265 while (++i<n)
1266 if (f[p+i]-f[p]!=i)
1267 break;
1268
1269 if (i>1)
1270 str += MString::Format(":%d", f[p+i-1]);
1271
1272 p += i;
1273 }
1274
1275 return str;
1276}
1277
1278// --------------------------------------------------------------------------
1279//
1280// Search for a sequence of continous numbers in r with f==0 starting at p.
1281// A new starting p is returned. The output is converted into sequences
1282// of X (single r) and X:Y (a sequence between x and r). The function
1283// returnes with the next f!=0.
1284//
1285TString MSequence::GetNumSequence(Int_t &p, const TArrayI &r, const TArrayI &f) const
1286{
1287 TString str;
1288
1289 while (p<r.GetSize() && f[p]==0)
1290 {
1291 // serach for the first entry which doesn't fit
1292 // or has a file number which is != 0
1293 int i=0;
1294 while (p+ ++i<r.GetSize())
1295 if (r[p+i]-r[p]!=i || f[p+i]!=0)
1296 break;
1297
1298 // None found (i-1==0)
1299 if (i-1==0)
1300 return str;
1301
1302 // The last run found in the sequence (e.g. 5.0) is followed
1303 // by an identical run number but file != 0 (e.g. 5.1)
1304 if (p+i<f.GetSize() && r[p+i]==r[p] && f[p+i]!=0)
1305 i--;
1306
1307 // Now we have to check again whether found no valid entry
1308 if (i-1==0)
1309 return str;
1310
1311 str += MString::Format(" %d", r[p]);
1312 // p now points to the last entry which fits and
1313 // has a file number == 0
1314 p += i-1;
1315 // Only one found (i-1==1)
1316 // More tahn one found (i-1>1)
1317 str += i-1==1 ? " " : ":";
1318 str += MString::Format("%d", r[p]);
1319
1320 // One step forward
1321 p++;
1322 }
1323
1324 return str;
1325}
1326
1327// --------------------------------------------------------------------------
1328//
1329// Print the runs in a compressed wa. Returns the RunXXXXXXX string
1330// simplyfing the file setup
1331//
1332TString MSequence::PrintRuns(ostream &out, const char *pre, const char *name, const TArrayI &r, const TArrayI &f) const
1333{
1334 if (r.GetSize()==0)
1335 return "";
1336
1337 out << pre << name;
1338 if (f.GetSize()==0)
1339 const_cast<TArrayI&>(f).Set(r.GetSize());
1340
1341#ifdef DEBUG
1342 for (int i=0; i<r.GetSize(); i++)
1343 out << " " << r[i] << "." << f[i];
1344 out << endl;
1345 return "";
1346#endif
1347
1348 TString str;
1349
1350 Int_t pos = 0;
1351 while (pos<r.GetSize())
1352 {
1353 TString rc = GetNumSequence(pos, r, f);
1354 if (!rc.IsNull())
1355 {
1356 out << rc;
1357 continue;
1358 }
1359
1360 Int_t n = GetSubArray(pos, r.GetSize(), (Int_t*)r.GetArray());
1361 // end reached
1362 if (n<0)
1363 break;
1364
1365 // This can happen if it is the last entry
1366 if (n==1)
1367 {
1368 out << " " << r[pos];
1369 if (f[pos]>=0)
1370 out << "." << f[pos];
1371 }
1372 else
1373 {
1374 // Check for sequence
1375 Bool_t isseq = kTRUE;
1376 for (int i=1; i<n; i++)
1377 if (f[pos+i]-f[pos]!=i)
1378 isseq=kFALSE;
1379
1380 if (isseq)
1381 {
1382 out << " " << r[pos] << ".";
1383 if (f[pos]>=0)
1384 out << f[pos];
1385 out << ":" << f[pos+n-1];
1386 }
1387 else
1388 {
1389 out << " " << r[pos] << "+";
1390
1391 str += '\n';
1392 str += pre;
1393 str += MString::Format("Run%08d:", r[pos]);
1394 str += GetNumSequence(pos, n, f);
1395 }
1396 }
1397
1398 pos += n;
1399 }
1400
1401 out << endl;
1402
1403 return str;
1404}
1405
1406// --------------------------------------------------------------------------
1407//
1408// Print the numbers in the classical way (one run after the other)
1409//
1410void MSequence::PrintRunsClassic(ostream &out, const char *pre, const char *name, const TArrayI &r) const
1411{
1412 out << pre << name;
1413 for (int i=0; i<r.GetSize(); i++)
1414 out << " " << r[i];
1415 out << endl;
1416}
1417
1418// --------------------------------------------------------------------------
1419//
1420// Print the contents of the sequence
1421//
1422void MSequence::Print(ostream &out, Option_t *o) const
1423{
1424 const TString opt(o);
1425
1426 const TString pre = opt.Contains("prefixed") ? MString::Format("Sequence%08d.", fSequence) : "";
1427
1428 if (!IsValid())
1429 {
1430 out << pre << "Sequence: " << fFileName << " <invalid>" << endl;
1431 return;
1432 }
1433 if (!fFileName.IsNull())
1434 out << "# FileName: " << fFileName << endl;
1435 if (!fDataPath.IsNull())
1436 out << "# DataPath: " << fDataPath << endl;
1437 out << endl;
1438 if (pre.IsNull())
1439 out << "Sequence: " << fSequence << endl;
1440 if (fTelescope!=1)
1441 out << "Telescope: " << fTelescope << endl;
1442 if (fMonteCarlo)
1443 out << pre << "MonteCarlo: Yes" << endl;
1444 if (fPeriod!=(UInt_t)-1)
1445 out << pre << "Period: " << fPeriod << endl;
1446 if (fNight!=MTime())
1447 out << pre << "Night: " << fNight.GetStringFmt("%Y-%m-%d") << endl;
1448 out << endl;
1449 if (fLightCondition!=kNA)
1450 {
1451 out << pre << "LightCondition: ";
1452 switch (fLightCondition)
1453 {
1454 case kNA: out << "n/a" << endl; break;
1455 case kNoMoon: out << "NoMoon" << endl; break;
1456 case kTwilight: out << "Twilight" << endl; break;
1457 case kMoon: out << "Moon" << endl; break;
1458 case kDay: out << "Day" << endl; break;
1459 }
1460 }
1461
1462 if (fStart!=MTime())
1463 out << pre << "Start: " << fStart.GetSqlDateTime() << endl;
1464 if (fLastRun!=(UInt_t)-1)
1465 out << pre << "LastRun: " << fLastRun << endl;
1466 if (fDrsSequence)
1467 out << pre << "DrsSequence: " << fDrsSequence << endl;
1468 if (fNumEvents!=(UInt_t)-1)
1469 out << pre << "NumEvents: " << fNumEvents << endl;
1470 if (!fProject.IsNull())
1471 out << pre << "Project: " << fProject << endl;
1472 if (!fSource.IsNull())
1473 out << pre << "Source: " << fSource << endl;
1474 if (!fTriggerTable.IsNull())
1475 out << pre << "TriggerTable: " << fTriggerTable << endl;
1476 if (!fHvSettings.IsNull())
1477 out << pre << "HvSettings: " << fHvSettings << endl;
1478 out << endl;
1479
1480 TString str;
1481 if (!HasSubRuns() && opt.Contains("classic"))
1482 {
1483 PrintRunsClassic(out, pre, "Runs: ", fRuns);
1484 PrintRunsClassic(out, pre, "CalRuns: ", fCalRuns);
1485 PrintRunsClassic(out, pre, "PedRuns: ", fPedRuns);
1486 PrintRunsClassic(out, pre, "DataRuns: ", fDatRuns);
1487 PrintRunsClassic(out, pre, "DrsRuns: ", fDrsRuns);
1488 PrintRunsClassic(out, pre, "DrsFiles: ", fDrsFiles);
1489 PrintRunsClassic(out, pre, "Exclude: ", fExclRuns);
1490 }
1491 else
1492 {
1493 // FIXME: This needs more check!
1494 // FORBID the + syntax in "Runs"
1495 // Could we make "Runs" an automatic summary of all runs?
1496 // Should we add a check forbidding the same run in
1497 // Cal/Ped/Data? What about the Exclude?
1498 /*str +=*/ PrintRuns(out, pre, "Runs: ", fRuns, fRunsSub);
1499 str += PrintRuns(out, pre, "CalRuns: ", fCalRuns, fCalRunsSub);
1500 str += PrintRuns(out, pre, "PedRuns: ", fPedRuns, fPedRunsSub);
1501 str += PrintRuns(out, pre, "DatRuns: ", fDatRuns, fDatRunsSub);
1502 str += PrintRuns(out, pre, "DrsRuns: ", fDrsRuns, fDrsRunsSub);
1503 str += PrintRuns(out, pre, "DrsFiles: ", fDrsFiles, fDrsFilesSub);
1504 str += PrintRuns(out, pre, "Exclude: ", fExclRuns, fExclRunsSub);
1505 }
1506
1507// if (!fDataPath.IsNull())
1508// out << endl << pre << "DataPath: " << fDataPath << endl;
1509
1510 if (!str.IsNull())
1511 out << str << endl;
1512
1513 out << endl;
1514
1515 if (!fComment.IsNull())
1516 out << pre << "Comment: " << fComment << endl;
1517
1518 if (GetDrsFile())
1519 out << "# DrsFile: " << GetDrsFile() << endl;
1520}
1521
1522// --------------------------------------------------------------------------
1523//
1524// Print the contents of the sequence to gLog
1525//
1526void MSequence::Print(Option_t *o) const
1527{
1528 gLog << all;
1529 Print(gLog, o);
1530}
1531
1532// --------------------------------------------------------------------------
1533//
1534// Print the contents of the sequence to the file with name filename
1535//
1536Bool_t MSequence::WriteFile(const char *name, const Option_t *o) const
1537{
1538 ofstream fout(name);
1539 if (!fout)
1540 {
1541 gLog << err << "ERROR - Cannot open file " << name << ": ";
1542 gLog << strerror(errno) << endl;
1543 return kFALSE;
1544 }
1545
1546 Print(fout, o);
1547
1548 if (!fout)
1549 {
1550 gLog << err << "ERROR - Writing file " << name << ": ";
1551 gLog << strerror(errno) << endl;
1552 return kFALSE;
1553 }
1554
1555 return kTRUE;
1556}
1557
1558// --------------------------------------------------------------------------
1559//
1560// check if the run/file is contained in the arrays.
1561//
1562Bool_t MSequence::IsContained(const TArrayI &arr, const TArrayI &sub, UInt_t run, UInt_t file) const
1563{
1564 // Backward compatibilty
1565 if (sub.GetSize()==0)
1566 {
1567 for (int i=0; i<arr.GetSize(); i++)
1568 if (run==(UInt_t)arr[i])
1569 return kTRUE;
1570 }
1571 else
1572 {
1573 for (int i=0; i<arr.GetSize(); i++)
1574 if (run==(UInt_t)arr[i] && file==(UInt_t)sub[i])
1575 return kTRUE;
1576 }
1577 return kFALSE;
1578}
1579
1580// --------------------------------------------------------------------------
1581//
1582// Exclude all runs which are found in the list, e.g. "100 102 105"
1583//
1584void MSequence::ExcludeRuns(TString runs)
1585{
1586 // FIXME: Decode stream!!!
1587
1588 TArrayI data, sub;
1589 Split(runs, data, sub);
1590 for (int i=0; i<data.GetSize(); i++)
1591 ExcludeFile(data[i], sub[i]);
1592}
1593
1594// --------------------------------------------------------------------------
1595//
1596// Return the excluded runs (to be more precise:the excluded files)
1597// in a string
1598//
1599const TString MSequence::GetExcludedRuns() const
1600{
1601 TString rc;
1602 for (int i=0; i<fExclRuns.GetSize(); i++)
1603 {
1604 rc += fExclRuns[i];
1605 if (fExclRunsSub.GetSize()>0)
1606 {
1607 rc += ".";
1608 rc += fExclRunsSub[i];
1609 }
1610 rc += " ";
1611 }
1612 return rc(0, rc.Length()-1);
1613}
1614
1615// --------------------------------------------------------------------------
1616//
1617// If you want to change or set the night manually.
1618// The Format is
1619// SetNight("yyyy-mm-dd");
1620//
1621void MSequence::SetNight(const char *txt)
1622{
1623 TString night(txt);
1624
1625 if (night.IsNull())
1626 {
1627 fNight = MTime();
1628 fPeriod = UInt_t(-1);
1629 return;
1630 }
1631
1632 night += " 00:00:00";
1633 fNight.SetSqlDateTime(night);
1634
1635 fPeriod = fNight.GetMagicPeriod();
1636}
1637
1638// --------------------------------------------------------------------------
1639//
1640// Read a sequence from gDirectory. If the default is given we try
1641// to find a sequence with name GetName. If a key with name name
1642// exists in the file read this key. Otherwise loop over all keys
1643// and return the first key matching the TPRegex (regular expression)
1644// matching defined by the argument.
1645//
1646Int_t MSequence::Read(const char *name)
1647{
1648 if (!name || !gDirectory)
1649 return MParContainer::Read(name);
1650
1651 if (gDirectory->GetListOfKeys()->FindObject(name))
1652 return MParContainer::Read(name);
1653
1654 TPRegexp regexp(name);
1655
1656 TIter NextK(gDirectory->GetListOfKeys());
1657 TObject *key = 0;
1658 while ((key=NextK()))
1659 if (TString(key->GetName())(regexp)==key->GetName())
1660 return MParContainer::Read(key->GetName());
1661
1662 *fLog << warn << "WARNING - No key in " << gDirectory->GetName() << " matching " << name << "." << endl;
1663 return 0;
1664}
1665
1666// --------------------------------------------------------------------------
1667//
1668// If the sequence name seq is just a digit it is inflated to a full
1669// path following the datacenter standard.
1670//
1671// Returns if file accessible or not.
1672//
1673Bool_t MSequence::InflateSeq(TString &seq, Bool_t ismc)
1674{
1675 TObjArray *arr = seq.Tokenize(':');
1676 if (arr->GetEntries()<3)
1677 {
1678 TString num1 = (*arr)[0]->GetName();
1679 TString num2 = arr->GetEntries()==2 ? (*arr)[1]->GetName() : "";
1680
1681 if (num1.IsDigit() && num2.IsDigit())
1682 {
1683 gLog << err << "ERROR - InflateSeq 'telescope:sequence' not yet implemented." << endl;
1684 delete arr;
1685 return kFALSE;
1686 }
1687
1688 if (num1.IsDigit() && num2.IsNull())
1689 {
1690 const Int_t numseq = seq.Atoi();
1691 seq = "/magic/";
1692 if (ismc)
1693 seq += "montecarlo/";
1694 seq += MString::Format("sequences/%04d/sequence%08d.txt", numseq/10000, numseq);
1695 gLog << inf << "Inflated sequence file: " << seq << endl;
1696 }
1697 }
1698 delete arr;
1699
1700 if (!gSystem->AccessPathName(seq, kFileExists))
1701 return kTRUE;
1702
1703 gLog << err << "Sorry, sequence file '" << seq << "' doesn't exist." << endl;
1704 return kFALSE;
1705}
1706
1707// --------------------------------------------------------------------------
1708//
1709// Search starting at position p in array arr and return the number
1710// of elemets which are identical to the starting entry (the starting entry
1711// is also counted)
1712//
1713Int_t MSequence::GetSubArray(Int_t p, Int_t n, Int_t *arr)
1714{
1715 Int_t *ptr0 = arr+p;
1716
1717 Int_t *ptr = ptr0;
1718 Int_t *end = arr+n;
1719
1720 while (ptr<end && *ptr==*ptr0)
1721 ptr++;
1722
1723 return ptr-ptr0;
1724}
1725
1726// --------------------------------------------------------------------------
1727//
1728// Sort the array arr2 starting at position p for following entries
1729// for which arr1 is equal. If not at least two entries are found which
1730// can be sorted return -1.
1731//
1732// The absolute index of the next entry in arr1 is returned.
1733//
1734Int_t MSequence::SortArraySub(Int_t p, Int_t n, Int_t *arr1, Int_t *arr2)
1735{
1736 Int_t *ptr2 = arr2+p;
1737
1738 Int_t cnt = GetSubArray(p, n, arr1);
1739 if (cnt==0)
1740 return -1;
1741
1742 TArrayI srt(cnt, ptr2);
1743 MJob::SortArray(srt);
1744
1745 memcpy(ptr2, srt.GetArray(), srt.GetSize()*sizeof(Int_t));
1746
1747 return p+srt.GetSize();
1748}
1749
1750void MSequence::SortArrays(TArrayI &arr1, TArrayI &arr2)
1751{
1752 if (arr1.GetSize()!=arr2.GetSize())
1753 return;
1754
1755 TArrayI idx(arr1.GetSize());
1756
1757 TArrayI srt1(arr1);
1758 TArrayI srt2(arr2);
1759
1760 TMath::Sort(arr1.GetSize(), srt1.GetArray(), idx.GetArray(), kFALSE);
1761
1762 for (int i=0; i<arr1.GetSize(); i++)
1763 {
1764 arr1[i] = srt1[idx[i]];
1765 arr2[i] = srt2[idx[i]];
1766 }
1767
1768 Int_t p = 0;
1769 while (p>=0)
1770 p = SortArraySub(p, arr1.GetSize(), arr1.GetArray(), arr2.GetArray());
1771}
Note: See TracBrowser for help on using the repository browser.