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

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