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

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