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

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