MUSIC unknown
Analysis for the MUSIC active-target ionization chamber
Loading...
Searching...
No Matches
FileSet.cpp
Go to the documentation of this file.
1#include "FileSet.hpp"
2
3std::mutex g_plot_mutex;
4std::mutex g_log_mutex;
5
7 return Constants::cfg.COMPASS_BASE_DIR +
8 Form("run_%d/RAW/DataR_run_%d%s.BIN", s.run, s.run, s.suffix.Data());
9}
10
11TString FileSet::SolBinPath(const FileSpec &s) {
12 // SOLARIS naming: music_exp1915_<RUN3>_00_66222_<SEQ3>.sol; suffix is empty
13 // for _000, else "_1"->_001; chunk "_cNNN"/"_<seq>_cNNN" -> _chunkNNN.sol
14 Int_t cPos = s.suffix.Index("_c");
15 if (cPos >= 0) {
16 TString chunkIdx = s.suffix(cPos + 2, s.suffix.Length() - cPos - 2);
17 Int_t seq = 0;
18 if (cPos > 1) {
19 TString seqStr = s.suffix(1, cPos - 1);
20 seq = seqStr.Atoi();
21 }
22 return Constants::cfg.SOL_SPLIT_DIR +
23 Form("music_exp1915_%03d_00_66222_%03d_chunk%s.sol", s.run, seq,
24 chunkIdx.Data());
25 }
26
27 Int_t seq = 0;
28 if (s.suffix != "" && s.suffix[0] == '_') {
29 TString seq_str = s.suffix(1, s.suffix.Length() - 1);
30 seq = seq_str.Atoi();
31 }
32 return Constants::cfg.SOL_BASE_DIR +
33 Form("music_exp1915_%03d_00_66222_%03d.sol", s.run, seq);
34}
35
36namespace {
37std::vector<TString> DiscoverSuffixesIn(const TString &dir,
38 const TString &prefix,
39 const TString &ext) {
40 std::vector<TString> suffixes;
41 void *dirp = gSystem->OpenDirectory(dir);
42 if (!dirp) {
43 std::cerr << "DiscoverSuffixesIn: cannot open " << dir << std::endl;
44 return suffixes;
45 }
46 const Char_t *name;
47 while ((name = gSystem->GetDirEntry(dirp))) {
48 TString fname(name);
49 if (!fname.BeginsWith(prefix))
50 continue;
51 if (!fname.EndsWith(ext))
52 continue;
53 TString rest =
54 fname(prefix.Length(), fname.Length() - prefix.Length() - ext.Length());
55 if (rest == "") {
56 suffixes.push_back("");
57 continue;
58 }
59 if (rest.Length() < 2 || rest[0] != '_')
60 continue;
61 TString num = rest(1, rest.Length() - 1);
62 if (!num.IsDigit())
63 continue;
64 suffixes.push_back(rest);
65 }
66 gSystem->FreeDirectory(dirp);
67 std::sort(suffixes.begin(), suffixes.end(),
68 [](const TString &a, const TString &b) {
69 if (a == "")
70 return true;
71 if (b == "")
72 return false;
73 return TString(a(1, a.Length() - 1)).Atoi() <
74 TString(b(1, b.Length() - 1)).Atoi();
75 });
76 return suffixes;
77}
78
79std::vector<FileSpec> BuildSpecsImpl(Bool_t processed) {
80 std::vector<FileSpec> specs;
81 const std::vector<Int_t> &runs = Constants::ActiveRunNumbers();
82 for (Int_t r = 0; r < Int_t(runs.size()); r++) {
83 Int_t run = runs[r];
84 std::vector<TString> suffixes;
85 if (processed) {
88 suffixes = FileSet::DiscoverSolRunSuffixes(run);
89 } else {
90 suffixes = FileSet::DiscoverRunSuffixes(run);
91 }
92 Int_t limit = suffixes.size();
93 if (Constants::cfg.N_CHUNKS > 0 && Constants::cfg.N_CHUNKS < limit)
94 limit = Constants::cfg.N_CHUNKS;
95 Int_t epoch_cap = Constants::ActiveMaxFiles();
96 if (epoch_cap > 0 && epoch_cap < limit)
97 limit = epoch_cap;
98 for (Int_t k = 0; k < limit; k++) {
99 FileSpec s;
100 s.run = run;
101 s.suffix = suffixes[k];
102 specs.push_back(s);
103 }
104 }
105 return specs;
106}
107
108// Suffix order: the empty suffix first, then the leading subfile number
109// (_1_c000 -> 1, _c000 -> 0), then lexicographic.
110Bool_t SuffixLess(const TString &a, const TString &b) {
111 if (a == "")
112 return kTRUE;
113 if (b == "")
114 return kFALSE;
115 Int_t na = 0, nb = 0;
116 if (a.Length() > 1 && a[0] == '_') {
117 TString numA = a(1, a.Length() - 1);
118 Int_t dash = numA.Index('_');
119 if (dash > 0)
120 numA = numA(0, dash);
121 if (numA.IsDigit())
122 na = numA.Atoi();
123 }
124 if (b.Length() > 1 && b[0] == '_') {
125 TString numB = b(1, b.Length() - 1);
126 Int_t dash = numB.Index('_');
127 if (dash > 0)
128 numB = numB(0, dash);
129 if (numB.IsDigit())
130 nb = numB.Atoi();
131 }
132 if (na != nb)
133 return na < nb;
134 return a < b;
135}
136} // namespace
137
138std::vector<TString> FileSet::DiscoverRunSuffixes(Int_t run) {
139 return DiscoverSuffixesIn(Constants::cfg.COMPASS_BASE_DIR +
140 Form("run_%d/RAW/", run),
141 Form("DataR_run_%d", run), ".BIN");
142}
143
144std::vector<TString> FileSet::DiscoverSolRunSuffixes(Int_t run) {
145 std::vector<TString> suffixes;
146 TString prefix = Form("music_exp1915_%03d_00_66222_", run);
147
148 // Check for split chunks first, unless splitting is off for the active
149 // epoch; whole files only, so stale chunks cannot be picked up.
150 TString split_dir = Constants::cfg.SOL_SPLIT_DIR;
151 void *dirp = Constants::ActiveSplitChunkSeconds() > 0
152 ? gSystem->OpenDirectory(split_dir)
153 : nullptr;
154 if (dirp) {
155 const Char_t *name;
156 while ((name = gSystem->GetDirEntry(dirp))) {
157 TString fname(name);
158 if (!fname.BeginsWith(prefix))
159 continue;
160 if (!fname.EndsWith(".sol"))
161 continue;
162 if (!fname.Contains("_chunk"))
163 continue;
164
165 Int_t chunkPos = fname.Index("_chunk");
166 if (chunkPos < 0)
167 continue;
168
169 TString seqStr = fname(prefix.Length(), chunkPos - prefix.Length());
170 if (!seqStr.IsDigit())
171 continue;
172 Int_t seq = seqStr.Atoi();
173
174 TString chunkStr = fname(chunkPos + 6, fname.Length() - chunkPos - 6 - 4);
175 if (!chunkStr.IsDigit())
176 continue;
177
178 if (seq == 0) {
179 suffixes.push_back(Form("_c%s", chunkStr.Data()));
180 } else {
181 suffixes.push_back(Form("_%d_c%s", seq, chunkStr.Data()));
182 }
183 }
184 gSystem->FreeDirectory(dirp);
185
186 if (!suffixes.empty()) {
187 std::sort(suffixes.begin(), suffixes.end(),
188 [](const TString &a, const TString &b) { return a < b; });
189 return suffixes;
190 }
191 }
192
193 // Fall back to original files
194 TString sol_dir = Constants::cfg.SOL_BASE_DIR;
195 dirp = gSystem->OpenDirectory(sol_dir);
196 if (!dirp) {
197 std::cerr << "DiscoverSolRunSuffixes: cannot open " << sol_dir << std::endl;
198 return suffixes;
199 }
200
201 const Char_t *name;
202 while ((name = gSystem->GetDirEntry(dirp))) {
203 TString fname(name);
204 if (!fname.BeginsWith(prefix))
205 continue;
206 if (!fname.EndsWith(".sol"))
207 continue;
208
209 TString rest = fname(prefix.Length(), fname.Length() - prefix.Length() - 4);
210 if (!rest.IsDigit())
211 continue;
212
213 Int_t seq = rest.Atoi();
214 if (seq == 0) {
215 suffixes.push_back("");
216 } else {
217 suffixes.push_back(Form("_%d", seq));
218 }
219 }
220 gSystem->FreeDirectory(dirp);
221
222 // Sort by sequence number
223 std::sort(suffixes.begin(), suffixes.end(),
224 [](const TString &a, const TString &b) {
225 if (a == "")
226 return true;
227 if (b == "")
228 return false;
229 return a.Atoi() < b.Atoi();
230 });
231
232 return suffixes;
233}
234
235std::vector<TString> FileSet::DiscoverProcessedRunSuffixes(Int_t run) {
236 std::vector<TString> suffixes;
237 TString dir = IO::GetRootFilesBaseDir();
238 // The same name the pipeline writes (EventsName), tag included, with the
239 // suffix left off: a tagged epoch's files are found only with it active.
240 FileSpec bare;
241 bare.run = run;
242 bare.suffix = "";
243 TString prefix = EventsName(bare);
244 void *dirp = gSystem->OpenDirectory(dir);
245 if (!dirp)
246 return suffixes;
247 const Char_t *name;
248 while ((name = gSystem->GetDirEntry(dirp))) {
249 TString fname(name);
250 if (!fname.BeginsWith(prefix))
251 continue;
252 if (!fname.EndsWith(".root"))
253 continue;
254 TString rest = fname(prefix.Length(), fname.Length() - prefix.Length() - 5);
255 // The suffix is empty or "_<subfile>...": "Events_Run1" must not
256 // collect run 16's files as suffix "6_...".
257 if (rest.Length() > 0 && rest[0] != '_')
258 continue;
259 suffixes.push_back(rest);
260 }
261 gSystem->FreeDirectory(dirp);
262 std::sort(suffixes.begin(), suffixes.end(), SuffixLess);
263 return suffixes;
264}
265
266std::vector<FileSpec> FileSet::BuildFileSpecs() {
267 return BuildSpecsImpl(kFALSE);
268}
269
270std::vector<FileSpec> FileSet::BuildProcessedFileSpecs() {
271 return BuildSpecsImpl(kTRUE);
272}
273
275 std::vector<FileSpec> specs = BuildFileSpecs();
276 std::vector<FileSpec> processed = BuildProcessedFileSpecs();
277 for (Int_t k = 0; k < Int_t(processed.size()); k++) {
278 Bool_t already = kFALSE;
279 for (Int_t j = 0; j < Int_t(specs.size()); j++) {
280 if (specs[j].run == processed[k].run &&
281 specs[j].suffix == processed[k].suffix) {
282 already = kTRUE;
283 break;
284 }
285 }
286 if (!already)
287 specs.push_back(processed[k]);
288 }
289 return specs;
290}
291
292TString FileSet::EventsName(const FileSpec &s) {
293 const TString &tag = Constants::ActiveFileTag();
294 if (tag.Length() > 0)
295 return Form("Events_%s_Run%d%s", tag.Data(), s.run, s.suffix.Data());
296 return Form("Events_Run%d%s", s.run, s.suffix.Data());
297}
298
299TString FileSet::FileLabel(const FileSpec &s) {
300 const TString &tag = Constants::ActiveFileTag();
301 if (tag.Length() > 0)
302 return Form("%s_run%d%s", tag.Data(), s.run, s.suffix.Data());
303 return Form("run%d%s", s.run, s.suffix.Data());
304}
305
307 GateGroups g;
308 std::vector<FileSpec> all_specs = BuildProcessedFileSpecs();
309 const Bool_t per_file = !Constants::ActiveUseSolarisData();
310 Int_t next_key = 0;
311 for (Int_t i = 0; i < Int_t(all_specs.size()); i++) {
312 const FileSpec &s = all_specs[i];
313 const TString name = EventsName(s);
314 TString full = IO::GetRootFilesBaseDir() + "/" + name + ".root";
315 if (gSystem->AccessPathName(full)) {
316 std::cerr << "Missing events file: " << full << std::endl;
317 continue;
318 }
319 // CoMPASS: a fresh key per file; SOLARIS: the run number, shared by its
320 // chunks.
321 const Int_t key = per_file ? next_key++ : s.run;
322 if (g.chain.find(key) == g.chain.end()) {
323 g.chain[key] = new TChain("events");
324 g.order.push_back(key);
325 g.label[key] = per_file ? FileLabel(s) : TString(Form("run%d", s.run));
326 }
327 g.chain[key]->Add(full);
328 g.key_of[name] = key;
329 }
330 return g;
331}
332
333Long64_t FileSet::SampleStride(Long64_t n_total, Long64_t max_points) {
334 Long64_t n_visit =
335 (max_points > 0 && n_total > max_points) ? max_points : n_total;
336 Long64_t stride = (n_visit > 0) ? (n_total / n_visit) : 1;
337 if (stride < 1)
338 stride = 1;
339 return stride;
340}
341
342FileSpec FileSet::ResolveFileSpec(const TString &file_label) {
343 std::vector<FileSpec> specs = BuildFileSpecs();
344 for (Int_t k = 0; k < Int_t(specs.size()); k++) {
345 if (FileLabel(specs[k]) == file_label)
346 return specs[k];
347 }
348 FileSpec s;
349 s.run = -1;
350 s.suffix = "";
351 Int_t i = 0;
352 while (i < file_label.Length() &&
353 !(file_label[i] >= '0' && file_label[i] <= '9'))
354 i++;
355 Int_t j = i;
356 while (j < file_label.Length() &&
357 (file_label[j] >= '0' && file_label[j] <= '9'))
358 j++;
359 if (j > i)
360 s.run = TString(file_label(i, j - i)).Atoi();
361 return s;
362}
std::mutex g_plot_mutex
Serialises all plotting and canvas work.
Definition FileSet.cpp:3
std::mutex g_log_mutex
Serialises multi-line progress logging from worker threads.
Definition FileSet.cpp:4
static TString EventsName(const FileSpec &s)
Filename of the built-events ROOT file for a subfile.
Definition FileSet.cpp:292
static std::vector< FileSpec > BuildFileSpecs()
Every raw input subfile for the configured runs.
Definition FileSet.cpp:266
static std::vector< TString > DiscoverSolRunSuffixes(Int_t run)
Subfile suffixes present on disk for a SOLARIS run.
Definition FileSet.cpp:144
static GateGroups GroupEventsForGating()
Build the gate groups; see GateGroups.
Definition FileSet.cpp:306
static TString FileLabel(const FileSpec &s)
Human-readable label identifying a subfile.
Definition FileSet.cpp:299
static TString CompassBinPath(const FileSpec &s)
Path to a CoMPASS binary subfile.
Definition FileSet.cpp:6
static std::vector< FileSpec > BuildRawOrProcessedFileSpecs()
The union of raw and processed subfiles, without duplicates.
Definition FileSet.cpp:274
static FileSpec ResolveFileSpec(const TString &file_label)
Recover the FileSpec behind a label from FileLabel().
Definition FileSet.cpp:342
static TString SolBinPath(const FileSpec &s)
Path to a SOLARIS .sol subfile.
Definition FileSet.cpp:11
static std::vector< FileSpec > BuildProcessedFileSpecs()
Every subfile that already has processed output.
Definition FileSet.cpp:270
static std::vector< TString > DiscoverRunSuffixes(Int_t run)
Subfile suffixes present on disk for a CoMPASS run.
Definition FileSet.cpp:138
static Long64_t SampleStride(Long64_t n_total, Long64_t max_points)
Stride that visits at most max_points of n_total entries.
Definition FileSet.cpp:333
static std::vector< TString > DiscoverProcessedRunSuffixes(Int_t run)
Subfile suffixes for which processed output already exists.
Definition FileSet.cpp:235
Int_t ActiveMaxFiles()
Cap on subfiles processed per run for the active epoch.
Double_t ActiveSplitChunkSeconds()
Chunk length the active epoch's .sol files are split into, in seconds; non-positive means whole files...
const std::vector< Int_t > & ActiveRunNumbers()
Runs of the active epoch, or the flat RUN_NUMBERS when none is set.
const TString & ActiveFileTag()
Output-name prefix of the active epoch.
const DatasetConfig & cfg
The active dataset's configuration, flat block.
Bool_t ActiveUseSolarisData()
Whether this era's data is SOLARIS rather than CoMPASS.
The events files grouped into the units the beam gates are fitted on.
Definition FileSet.hpp:125
std::map< Int_t, TChain * > chain
Chain per key. Caller owns..
Definition FileSet.hpp:127
std::map< TString, Int_t > key_of
Group key per EventsName().
Definition FileSet.hpp:129
std::map< Int_t, TString > label
Label per key, for logs and plots.
Definition FileSet.hpp:128
std::vector< Int_t > order
Group keys in processing order.
Definition FileSet.hpp:126
One input file: a run number and the subfile suffix within it.
Definition FileSet.hpp:40
TString suffix
Subfile suffix, empty for the first subfile.
Definition FileSet.hpp:42
Int_t run
Run number.
Definition FileSet.hpp:41