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

Last change on this file since 9029 was 9028, checked in by tbretz, 16 years ago
*** empty log message ***
File size: 45.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 = GetEnvValue2(*env, prefix, Form("Run%08d", 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 str += " 00:00:00";
893 fNight.SetSqlDateTime(str);
894
895 fPeriod = fNight.GetMagicPeriod();
896
897 fProject = GetEnvValue2(env, prefix, "Project", "");
898 fSource = GetEnvValue2(env, prefix, "Source", "");
899 fTriggerTable = GetEnvValue2(env, prefix, "TriggerTable", "");
900 fHvSettings = GetEnvValue2(env, prefix, "HvSettings", "");
901 fMonteCarlo = GetEnvValue2(env, prefix, "MonteCarlo", kFALSE);
902 fComment = GetEnvValue2(env, prefix, "Comment", "");
903
904 Split(env, prefix, "Runs", fRuns, fRunsSub);
905 Split(env, prefix, "CalRuns", fCalRuns, fCalRunsSub);
906 Split(env, prefix, "PedRuns", fPedRuns, fPedRunsSub);
907 Split(env, prefix, "DatRuns", fDatRuns, fDatRunsSub);
908 Split(env, prefix, "Exclude", fExclRuns, fExclRunsSub);
909
910 // Dummies:
911 env.Touch("Period");
912 env.Touch("ZdMin");
913 env.Touch("ZdMax");
914 env.Touch("L1TriggerTable");
915 env.Touch("L2TriggerTable");
916
917 if (seq<0 && env.GetNumUntouched()>0)
918 {
919 gLog << warn << "WARNING - At least one resource in the sequence-file has not been touched!" << endl;
920 env.PrintUntouched();
921 }
922
923 return !rc;
924}
925
926// --------------------------------------------------------------------------
927//
928// Instantiate a file from either a file or the database.
929//
930// If not valid sequence could be created the sequence is invalidated,
931// which can be queried with IsValid.
932//
933// see ReadFile, ReadDatabase and SetDataPath for more details.
934//
935MSequence::MSequence(const char *fname, const char *path, UInt_t seq)
936{
937 // regular expression to distinguish beween a mysql-path and
938 // a filename from where the sequence should be retrieved
939 TPRegexp regexp("mysql://[a-zA-Z0-9]+:.+@[a-zA-Z0-9]+/[a-zA-Z0-9]+/([0-9]+:)?[0-9]+");
940
941 const TString db = TString(fname)(regexp);
942
943 const Bool_t rc1 = db.IsNull() ? ReadFile(fname, seq) : ReadDatabase(fname, seq);
944 const Bool_t rc2 = SetDataPath(path);
945
946 fName = "MSequence";
947 fTitle = "Sequence file";
948
949 if (!rc1 || !rc2)
950 fSequence = (UInt_t)-1;
951}
952
953// --------------------------------------------------------------------------
954//
955// Read a sequence from the database. Give the path to the database as:
956// mysql://user:password@name/database
957// In this case you MUST give a sequence number.
958//
959// You can code the telescope and sequence number into the path and
960// omit the arguments:
961// mysql://user:password@name/database/[tel:]sequence
962//
963// The third option is to give just the sql.rc as string in the argument.
964// In this case you MUST give a sequence number.
965//
966// If the telecope number is omitted as argument, i.e. ==0, or in the
967// database path, a sequence is read from the database if the sequence
968// number is unambiguous.
969//
970// kFALSE is returned if the final sequence is invalid, kTRUE in case of
971// success.
972//
973Bool_t MSequence::ReadDatabase(TString name, UInt_t seq, UShort_t tel)
974{
975 TPRegexp regexp("([0-9]+:)?[0-9]+$");
976
977 const TString telseq = name(regexp);
978
979 if (!telseq.IsNull())
980 {
981 const Ssiz_t p = telseq.First(':');
982
983 const TString strtel = p<0 ? TString("") : telseq(0, p);
984 const TString strseq = telseq(p+1, telseq.Length());
985
986 tel = strtel.Atoi();
987 seq = strseq.Atoi();
988
989 name = gSystem->DirName(name);
990 }
991
992 *this = MSequenceSQL(name, seq, tel);
993
994 return IsValid();
995}
996
997// --------------------------------------------------------------------------
998//
999// Create a sequence from the database, e.g.
1000//
1001// TString mysql = "mysql://MAGIC:password@vela/MyMagic";
1002// Int_t sequence = 100002;
1003// Int_t telescope = 1;
1004//
1005// MSequence seq(mysql, sequence, telescope);
1006//
1007// Is the telescope number is omitted (==0) the database is checked for
1008// an unambiguous sequence.
1009//
1010// For more details see ReadDatabase and MSequenceSQL.
1011//
1012MSequence::MSequence(const char *fname, UInt_t seq, UShort_t tel)
1013{
1014 const Bool_t rc = ReadDatabase(fname, seq, tel);
1015
1016 fName = "MSequence";
1017 fTitle = "Sequence file";
1018
1019 if (!rc)
1020 fSequence = (UInt_t)-1;
1021}
1022
1023// --------------------------------------------------------------------------
1024//
1025// Some helper functions for the comparison functions
1026//
1027static int operator==(const TArrayI &a, const TArrayI &b)
1028{
1029 return a.GetSize()==b.GetSize() &&
1030 memcmp(a.GetArray(), b.GetArray(), a.GetSize()*sizeof(Int_t));
1031}
1032
1033static int IsNull(const TArrayI &a, const TArrayI &b)
1034{
1035 return a==TArrayI(a.GetSize()) && b==TArrayI(b.GetSize());
1036}
1037
1038static int Check(const TArrayI &a, const TArrayI &b)
1039{
1040 return a==b || IsNull(a, b);
1041}
1042
1043// --------------------------------------------------------------------------
1044//
1045// Here we test all things mandatory for a sequence:
1046// fTelescope
1047// fSequence
1048// fNight
1049// fMonteCarlo
1050// fCalRuns
1051// fCalRunsSub
1052// fPedRuns
1053// fPedRunsSub
1054// fDatRuns
1055// fDatRunsSub
1056// fExclRuns
1057// fExclRunsSub
1058//
1059Bool_t MSequence::IsCompatible(const MSequence &s) const
1060{
1061 return // Mandatory
1062 fTelescope == s.fTelescope &&
1063 fSequence == s.fSequence &&
1064 fNight == s.fNight &&
1065
1066 fMonteCarlo == s.fMonteCarlo &&
1067
1068 fCalRuns == s.fCalRuns &&
1069 fPedRuns == s.fPedRuns &&
1070 fDatRuns == s.fDatRuns &&
1071 fExclRuns == s.fExclRuns &&
1072
1073 Check(fCalRunsSub, s.fCalRunsSub) &&
1074 Check(fPedRunsSub, s.fPedRunsSub) &&
1075 Check(fDatRunsSub, s.fDatRunsSub) &&
1076 Check(fExclRunsSub, s.fExclRunsSub);
1077}
1078
1079// --------------------------------------------------------------------------
1080//
1081// Here we test whether all values of a sequence are identical
1082// IsCompaticle(s)
1083// fStart
1084// fLastRun
1085// fNumEvents
1086// fPeriod
1087// fProject
1088// fSource
1089// fRuns
1090// fHvSettings
1091// fTriggerTable
1092// fLightCondition
1093// fRuns
1094// fRunsSub
1095//
1096Bool_t MSequence::operator==(const MSequence &s) const
1097{
1098 return IsCompatible(s) &&
1099 // Unnecessary
1100 fStart == s.fStart &&
1101 fLastRun == s.fLastRun &&
1102 fNumEvents == s.fNumEvents &&
1103 fPeriod == s.fPeriod &&
1104 fProject == s.fProject &&
1105 fSource == s.fSource &&
1106 fRuns == s.fRuns &&
1107 fHvSettings == s.fHvSettings &&
1108 fTriggerTable == s.fTriggerTable &&
1109 fLightCondition == s.fLightCondition &&
1110 Check(fRunsSub, s.fRunsSub);
1111}
1112
1113// --------------------------------------------------------------------------
1114//
1115// Check whether the sequence has also identical source, i.e.
1116// the sequence filepath and the datapath in addition to operator==
1117//
1118Bool_t MSequence::IsIdentical(const MSequence &s) const
1119{
1120 return *this==s &&
1121 // Obsolete
1122 fDataPath==s.fDataPath && fFileName==s.fFileName;
1123}
1124
1125//---------------------------------------------------------------------------
1126//
1127// Make sure that the name used for writing doesn't contain a full path
1128//
1129const char *MSequence::GetBaseName() const
1130{
1131 return gSystem->BaseName(fFileName);
1132}
1133
1134//---------------------------------------------------------------------------
1135//
1136// Make sure that the name used for writing doesn't contain a full path
1137//
1138const char *MSequence::GetFilePath() const
1139{
1140 return gSystem->DirName(fFileName);
1141}
1142
1143// --------------------------------------------------------------------------
1144//
1145// Find a sequence of continous numbers in f starting at pos (looking
1146// only at n entries). The output is converted into sequences
1147// of X (single r) and X:Y (a sequence between x and r). The function
1148// returnes when position pos+n is reached
1149//
1150TString MSequence::GetNumSequence(Int_t pos, Int_t n, const TArrayI &f) const
1151{
1152 TString str;
1153
1154 Int_t p=pos;
1155 while (p<pos+n)
1156 {
1157 str += Form(" %d", f[p]);
1158
1159 if (p==pos+n-1)
1160 break;
1161
1162 int i=0;
1163 while (++i<n)
1164 if (f[p+i]-f[p]!=i)
1165 break;
1166
1167 if (i>1)
1168 str += Form(":%d", f[p+i-1]);
1169
1170 p += i;
1171 }
1172
1173 return str;
1174}
1175
1176// --------------------------------------------------------------------------
1177//
1178// Search for a sequence of continous numbers in r with f==0 starting at p.
1179// A new starting p is returned. The output is converted into sequences
1180// of X (single r) and X:Y (a sequence between x and r). The function
1181// returnes with the next f!=0.
1182//
1183TString MSequence::GetNumSequence(Int_t &p, const TArrayI &r, const TArrayI &f) const
1184{
1185 TString str;
1186
1187 while (p<r.GetSize() && f[p]==0)
1188 {
1189 // serach for the first entry which doesn't fit
1190 // or has a file number which is != 0
1191 int i=0;
1192 while (p+ ++i<r.GetSize())
1193 if (r[p+i]-r[p]!=i || f[p+i]!=0)
1194 break;
1195
1196 // None found (i-1==0)
1197 if (i-1==0)
1198 return str;
1199
1200 // The last run found in the sequence (e.g. 5.0) is followed
1201 // by an identical run number but file != 0 (e.g. 5.1)
1202 if (p+i<f.GetSize() && r[p+i]==r[p] && f[p+i]!=0)
1203 i--;
1204
1205 // Now we have to check again whether found no valid entry
1206 if (i-1==0)
1207 return str;
1208
1209 str += Form(" %d", r[p]);
1210 // p now points to the last entry which fits and
1211 // has a file number == 0
1212 p += i-1;
1213 // Only one found (i-1==1)
1214 // More tahn one found (i-1>1)
1215 str += i-1==1 ? " " : ":";
1216 str += Form("%d", r[p]);
1217
1218 // One step forward
1219 p++;
1220 }
1221
1222 return str;
1223}
1224
1225// --------------------------------------------------------------------------
1226//
1227// Print the runs in a compressed wa. Returns the RunXXXXXXX string
1228// simplyfing the file setup
1229//
1230TString MSequence::PrintRuns(ostream &out, const char *pre, const char *name, const TArrayI &r, const TArrayI &f) const
1231{
1232 if (r.GetSize()==0)
1233 return "";
1234
1235 out << pre << name;
1236 if (f.GetSize()==0)
1237 const_cast<TArrayI&>(f).Set(r.GetSize());
1238
1239#ifdef DEBUG
1240 for (int i=0; i<r.GetSize(); i++)
1241 out << " " << r[i] << "." << f[i];
1242 out << endl;
1243 return "";
1244#endif
1245
1246 TString str;
1247
1248 Int_t pos = 0;
1249 while (pos<r.GetSize())
1250 {
1251 TString rc = GetNumSequence(pos, r, f);
1252 if (!rc.IsNull())
1253 {
1254 out << rc;
1255 continue;
1256 }
1257
1258 Int_t n = GetSubArray(pos, r.GetSize(), (Int_t*)r.GetArray());
1259 // end reached
1260 if (n<0)
1261 break;
1262
1263 // This can happen if it is the last entry
1264 if (n==1)
1265 {
1266 out << " " << r[pos];
1267 if (f[pos]>0)
1268 out << "." << f[pos];
1269 }
1270 else
1271 {
1272 // Check for sequence
1273 Bool_t isseq = kTRUE;
1274 for (int i=1; i<n; i++)
1275 if (f[pos+i]-f[pos]!=i)
1276 isseq=kFALSE;
1277
1278 if (isseq)
1279 {
1280 out << " " << r[pos] << ".";
1281 if (f[pos]!=0)
1282 out << f[pos];
1283 out << ":" << f[pos+n-1];
1284 }
1285 else
1286 {
1287 out << " " << r[pos] << "+";
1288
1289 str += '\n';
1290 str += pre;
1291 str += Form("Run%08d:", r[pos]);
1292 str += GetNumSequence(pos, n, f);
1293 }
1294 }
1295
1296 pos += n;
1297 }
1298
1299 out << endl;
1300
1301 return str;
1302}
1303
1304// --------------------------------------------------------------------------
1305//
1306// Print the numbers in the classical way (one run after the other)
1307//
1308void MSequence::PrintRunsClassic(ostream &out, const char *pre, const char *name, const TArrayI &r) const
1309{
1310 out << pre << name;
1311 for (int i=0; i<r.GetSize(); i++)
1312 out << " " << r[i];
1313 out << endl;
1314}
1315
1316// --------------------------------------------------------------------------
1317//
1318// Print the contents of the sequence
1319//
1320void MSequence::Print(ostream &out, Option_t *o) const
1321{
1322 const TString opt(o);
1323
1324 const TString pre = opt.Contains("prefixed") ? Form("Sequence%08d.", fSequence) : "";
1325
1326 if (!IsValid())
1327 {
1328 out << pre << "Sequence: " << fFileName << " <invalid>" << endl;
1329 return;
1330 }
1331 if (!fFileName.IsNull())
1332 out << "# FileName: " << fFileName << endl;
1333 if (!fDataPath.IsNull())
1334 out << "# DataPath: " << fDataPath << endl;
1335 out << endl;
1336 if (pre.IsNull())
1337 out << "Sequence: " << fSequence << endl;
1338 if (fTelescope!=1)
1339 out << "Telescope: " << fTelescope << endl;
1340 if (fMonteCarlo)
1341 out << pre << "MonteCarlo: Yes" << endl;
1342 if (fPeriod>=0)
1343 out << pre << "Period: " << fPeriod << endl;
1344 if (fNight!=MTime())
1345 out << pre << "Night: " << fNight.GetStringFmt("%Y-%m-%d") << endl;
1346 out << endl;
1347 out << pre << "LightCondition: ";
1348 switch (fLightCondition)
1349 {
1350 case kNA: out << "n/a" << endl; break;
1351 case kNoMoon: out << "NoMoon" << endl; break;
1352 case kTwilight: out << "Twilight" << endl; break;
1353 case kMoon: out << "Moon" << endl; break;
1354 case kDay: out << "Day" << endl; break;
1355 }
1356
1357 if (fStart!=MTime())
1358 out << pre << "Start: " << fStart.GetSqlDateTime() << endl;
1359 if (fLastRun>=0)
1360 out << pre << "LastRun: " << fLastRun << endl;
1361 if (fNumEvents>=0)
1362 out << pre << "NumEvents: " << fNumEvents << endl;
1363 if (!fProject.IsNull())
1364 out << pre << "Project: " << fProject << endl;
1365 if (!fSource.IsNull())
1366 out << pre << "Source: " << fSource << endl;
1367 if (!fTriggerTable.IsNull())
1368 out << pre << "TriggerTable: " << fTriggerTable << endl;
1369 if (!fHvSettings.IsNull())
1370 out << pre << "HvSettings: " << fHvSettings << endl;
1371 out << endl;
1372
1373 TString str;
1374 if (!HasSubRuns() && opt.Contains("classic"))
1375 {
1376 PrintRunsClassic(out, pre, "Runs: ", fRuns);
1377 PrintRunsClassic(out, pre, "CalRuns: ", fCalRuns);
1378 PrintRunsClassic(out, pre, "PedRuns: ", fPedRuns);
1379 PrintRunsClassic(out, pre, "DataRuns: ", fDatRuns);
1380 PrintRunsClassic(out, pre, "Exclude: ", fExclRuns);
1381 }
1382 else
1383 {
1384 // FIXME: This needs more check!
1385 // FORBID the + syntax in "Runs"
1386 // Could we make "Runs" an automatic summary of all runs?
1387 // Should we add a check forbidding the same run in
1388 // Cal/Ped/Data? What about the Exclude?
1389 /*str +=*/ PrintRuns(out, pre, "Runs: ", fRuns, fRunsSub);
1390 str += PrintRuns(out, pre, "CalRuns: ", fCalRuns, fCalRunsSub);
1391 str += PrintRuns(out, pre, "PedRuns: ", fPedRuns, fPedRunsSub);
1392 str += PrintRuns(out, pre, "DatRuns: ", fDatRuns, fDatRunsSub);
1393 str += PrintRuns(out, pre, "Exclude: ", fExclRuns, fExclRunsSub);
1394 }
1395
1396 if (!fDataPath.IsNull())
1397 out << endl << pre << "DataPath: " << fDataPath << endl;
1398
1399 if (!str.IsNull())
1400 out << str << endl;
1401
1402 out << endl;
1403
1404 if (!fComment.IsNull())
1405 out << pre << "Comment: " << fComment << endl;
1406}
1407
1408// --------------------------------------------------------------------------
1409//
1410// Print the contents of the sequence to gLog
1411//
1412void MSequence::Print(Option_t *o) const
1413{
1414 gLog << all;
1415 Print(gLog, o);
1416}
1417
1418// --------------------------------------------------------------------------
1419//
1420// Print the contents of the sequence to the file with name filename
1421//
1422Bool_t MSequence::WriteFile(const char *name, const Option_t *o) const
1423{
1424 ofstream fout(name);
1425 if (!fout)
1426 {
1427 gLog << err << "ERROR - Cannot open file " << name << ": ";
1428 gLog << strerror(errno) << endl;
1429 return kFALSE;
1430 }
1431
1432 Print(fout, o);
1433
1434 if (!fout)
1435 {
1436 gLog << err << "ERROR - Writing file " << name << ": ";
1437 gLog << strerror(errno) << endl;
1438 return kFALSE;
1439 }
1440
1441 return kTRUE;
1442}
1443
1444// --------------------------------------------------------------------------
1445//
1446// check if the run/file is contained in the arrays.
1447//
1448Bool_t MSequence::IsContained(const TArrayI &arr, const TArrayI &sub, UInt_t run, UInt_t file) const
1449{
1450 // Backward compatibilty
1451 if (sub.GetSize()==0)
1452 {
1453 for (int i=0; i<arr.GetSize(); i++)
1454 if (run==(UInt_t)arr[i])
1455 return kTRUE;
1456 }
1457 else
1458 {
1459 for (int i=0; i<arr.GetSize(); i++)
1460 if (run==(UInt_t)arr[i] && file==(UInt_t)sub[i])
1461 return kTRUE;
1462 }
1463 return kFALSE;
1464}
1465
1466// --------------------------------------------------------------------------
1467//
1468// Exclude all runs which are found in the list, e.g. "100 102 105"
1469//
1470void MSequence::ExcludeRuns(TString runs)
1471{
1472 // FIXME: Decode stream!!!
1473
1474 TArrayI data, sub;
1475 Split(runs, data, sub);
1476 for (int i=0; i<data.GetSize(); i++)
1477 ExcludeFile(data[i], sub[i]);
1478}
1479
1480// --------------------------------------------------------------------------
1481//
1482// Return the excluded runs (to be more precise:the excluded files)
1483// in a string
1484//
1485const TString MSequence::GetExcludedRuns() const
1486{
1487 TString rc;
1488 for (int i=0; i<fExclRuns.GetSize(); i++)
1489 {
1490 rc += fExclRuns[i];
1491 if (fExclRunsSub.GetSize()>0)
1492 {
1493 rc += ".";
1494 rc += fExclRunsSub[i];
1495 }
1496 rc += " ";
1497 }
1498 return rc(0, rc.Length()-1);
1499}
1500
1501// --------------------------------------------------------------------------
1502//
1503// If you want to change or set the night manually.
1504// The Format is
1505// SetNight("yyyy-mm-dd");
1506//
1507void MSequence::SetNight(const char *txt)
1508{
1509 TString night(txt);
1510 night += " 00:00:00";
1511 fNight.SetSqlDateTime(night);
1512
1513 fPeriod = fNight.GetMagicPeriod();
1514}
1515
1516// --------------------------------------------------------------------------
1517//
1518// If the sequence name seq is just a digit it is inflated to a full
1519// path following the datacenter standard.
1520//
1521// Returns if file accessible or not.
1522//
1523Bool_t MSequence::InflateSeq(TString &seq, Bool_t ismc)
1524{
1525 TObjArray *arr = seq.Tokenize(':');
1526 if (arr->GetEntries()<3)
1527 {
1528 TString num1 = (*arr)[0]->GetName();
1529 TString num2 = arr->GetEntries()==2 ? (*arr)[1]->GetName() : "";
1530
1531 if (num1.IsDigit() && num2.IsDigit())
1532 {
1533 gLog << err << "ERROR - InflateSeq 'telescope:sequence' not yet implemented." << endl;
1534 delete arr;
1535 return kFALSE;
1536 }
1537
1538 if (num1.IsDigit() && num2.IsNull())
1539 {
1540 const Int_t numseq = seq.Atoi();
1541 seq = "/magic/";
1542 if (ismc)
1543 seq += "montecarlo/";
1544 seq += Form("sequences/%04d/sequence%08d.txt", numseq/10000, numseq);
1545 gLog << inf << "Inflated sequence file: " << seq << endl;
1546 }
1547 }
1548 delete arr;
1549
1550 if (!gSystem->AccessPathName(seq, kFileExists))
1551 return kTRUE;
1552
1553 gLog << err << "Sorry, sequence file '" << seq << "' doesn't exist." << endl;
1554 return kFALSE;
1555}
1556
1557// --------------------------------------------------------------------------
1558//
1559// Search starting at position p in array arr and return the number
1560// of elemets which are identical to the starting entry (the starting entry
1561// is also counted)
1562//
1563Int_t MSequence::GetSubArray(Int_t p, Int_t n, Int_t *arr)
1564{
1565 Int_t *ptr0 = arr+p;
1566
1567 Int_t *ptr = ptr0;
1568 Int_t *end = arr+n;
1569
1570 while (ptr<end && *ptr==*ptr0)
1571 ptr++;
1572
1573 return ptr-ptr0;
1574}
1575
1576// --------------------------------------------------------------------------
1577//
1578// Sort the array arr2 starting at position p for following entries
1579// for which arr1 is equal. If not at least two entries are found which
1580// can be sorted return -1.
1581//
1582// The absolute index of the next entry in arr1 is returned.
1583//
1584Int_t MSequence::SortArraySub(Int_t p, Int_t n, Int_t *arr1, Int_t *arr2)
1585{
1586 Int_t *ptr2 = arr2+p;
1587
1588 Int_t cnt = GetSubArray(p, n, arr1);
1589 if (cnt==0)
1590 return -1;
1591
1592 TArrayI srt(cnt, ptr2);
1593 MJob::SortArray(srt);
1594
1595 memcpy(ptr2, srt.GetArray(), srt.GetSize()*sizeof(Int_t));
1596
1597 return p+srt.GetSize();
1598}
1599
1600void MSequence::SortArrays(TArrayI &arr1, TArrayI &arr2)
1601{
1602 if (arr1.GetSize()!=arr2.GetSize())
1603 return;
1604
1605 TArrayI idx(arr1.GetSize());
1606
1607 TArrayI srt1(arr1);
1608 TArrayI srt2(arr2);
1609
1610 TMath::Sort(arr1.GetSize(), srt1.GetArray(), idx.GetArray(), kFALSE);
1611
1612 for (int i=0; i<arr1.GetSize(); i++)
1613 {
1614 arr1[i] = srt1[idx[i]];
1615 arr2[i] = srt2[idx[i]];
1616 }
1617
1618 Int_t p = 0;
1619 while (p>=0)
1620 p = SortArraySub(p, arr1.GetSize(), arr1.GetArray(), arr2.GetArray());
1621}
Note: See TracBrowser for help on using the repository browser.