ATLAS Offline Software
Loading...
Searching...
No Matches
ToolsDiscovery.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7//
8// includes
9//
10
12
24#include <TChain.h>
25#include <TChainElement.h>
26#include <TFile.h>
27#include <TTree.h>
28#include <fstream>
29#include <memory>
30#include <stdexcept>
31
32//
33// method implementations
34//
35
36namespace SH
37{
39 const std::string& pattern,
40 const std::string& samplePattern,
41 const std::string& samplePostfix)
42 {
43 ScanDir()
44 .sampleDepth (0)
45 .minDepth (1)
46 .maxDepth (1)
47 .filePattern (pattern)
48 .samplePattern (samplePattern)
49 .samplePostfix (samplePostfix)
50 .scan (sh, list);
51 }
52
53
54
55 void scanDir (SampleHandler& sh, const std::string& dir)
56 {
57 ScanDir()
58 .sampleDepth (0)
59 .minDepth (1)
60 .maxDepth (1)
61 .scan (sh, dir);
62 }
63
64
65
66 void scanDir (SampleHandler& sh, const std::string& dir,
67 const std::string& prefix)
68 {
69 DiskListLocal list (dir, prefix);
70 ScanDir()
71 .sampleDepth (0)
72 .minDepth (1)
73 .maxDepth (1)
74 .scan (sh, list);
75 }
76
77
78
80 const std::string& pattern)
81 {
82 ScanDir()
83 .sampleDepth (-1)
84 .filePattern (pattern)
85 .samplePostfix (".*")
86 .scan (sh, list);
87 }
88
89
90
91 std::unique_ptr<Sample> makeFromTChainUnique (const std::string& name, const TChain& chain)
92 {
93 auto result = std::make_unique<SampleLocal> (name);
94 result->meta()->setString (MetaFields::treeName, chain.GetName());
95
96 TIter chainIter (chain.GetListOfFiles());
97 TChainElement *chainElement = nullptr;
98 while ((chainElement = dynamic_cast<TChainElement*>(chainIter.Next())) != nullptr)
99 result->add (chainElement->GetTitle());
100 return result;
101 }
102
103
104
105 Sample *makeFromTChain (const std::string& name, const TChain& chain)
106 {
107 return makeFromTChainUnique (name, chain).release();
108 }
109
110
111
112 void scanSingleDir (SampleHandler& sh, const std::string& name,
113 DiskList& list, const std::string& pattern)
114 {
115 ScanDir()
116 .sampleDepth (0)
117 .filePattern (pattern)
118 .sampleRename ("*", name)
119 .scan (sh, list);
120 }
121
122
123
124 void scanDQ2 (SampleHandler& sh, const std::string& pattern)
125 {
126 if (pattern.find ("*") == std::string::npos)
127 {
128 addGrid (sh, pattern);
129 } else
130 {
131 std::set<std::string> types = {"DATASET", "DIDType.DATASET"};
132 if (!pattern.empty() && pattern.back() == '/')
133 types = {"CONTAINER", "DIDType.CONTAINER"};
134
135 auto subresult = rucioListDids (pattern);
136 for (auto& ds : subresult)
137 {
138 if (types.find (ds.type) != types.end())
139 addGrid (sh, ds.scope + ":" + ds.name);
140 }
141 }
142 }
143
144
145
146 void scanRucio (SampleHandler& sh, const std::string& pattern,
147 bool alwaysQuery)
148 {
149 if (pattern.find ("*") == std::string::npos && !alwaysQuery)
150 {
151 addGrid (sh, pattern);
152 } else
153 {
154 auto subresult = rucioListDids (pattern);
155 bool added = false;
156 for (std::string type : {"CONTAINER", "DIDType.CONTAINER", "DATASET", "DIDType.DATASET"})
157 {
158 for (auto& ds : subresult)
159 {
160 if (ds.type == type)
161 {
162 addGrid (sh, ds.scope + ":" + ds.name);
163 added = true;
164 }
165 }
166 if (added)
167 return;
168 }
169 throw std::runtime_error ("failed to find any datasets matching pattern: " + pattern);
170 }
171 }
172
173
174
175 void addGrid (SampleHandler& sh, const std::string& ds)
176 {
177 RCU_ASSERT_SOFT (ds.find ("*") == std::string::npos);
178
179 std::string name;
180 if (!ds.empty() && ds.back() == '/')
181 name = ds.substr (0, ds.size()-1);
182 else
183 name = ds;
184
185 auto sample = std::make_unique<SampleGrid> (name);
186 sample->meta()->setString (MetaFields::gridName, ds);
187 sample->meta()->setString (MetaFields::gridFilter, MetaFields::gridFilter_default);
188 sh.add (std::move (sample));
189 }
190
191
192
193 void addGridCombined (SampleHandler& sh, const std::string& dsName,
194 const std::vector<std::string>& dsList)
195 {
196 std::string name;
197 for (const std::string &ds : dsList)
198 {
199 RCU_ASSERT_SOFT (ds.find ("*") == std::string::npos);
200
201 if (!name.empty())
202 name.append(",");
203
204 if (ds.at(ds.size() - 1) == '/')
205 name.append(ds.substr (0, ds.size() - 1));
206 else
207 name.append(ds);
208 }
209
210 auto sample = std::make_unique<SampleGrid> (dsName);
211 sample->meta()->setString (MetaFields::gridName, name);
212 sample->meta()->setString (MetaFields::gridFilter, MetaFields::gridFilter_default);
213 sh.add (std::move (sample));
214 }
215 void addGridCombinedFromFile (SampleHandler& sh, const std::string& dsName,
216 const std::string& dsFile)
217 {
218 std::ifstream file (dsFile.c_str());
219
220 std::string name;
221 std::string ds;
222 const std::set<char> whitespaces{'\t',' ','\n','\r'};
223 while (std::getline (file, ds))
224 {
225 while ((!ds.empty()) && whitespaces.count(ds.back())) ds.pop_back();
226 if (ds.empty() || ds.at(0) == '#')
227 continue;
228
229 RCU_ASSERT_SOFT (ds.find ("*") == std::string::npos);
230
231 if (!name.empty())
232 name.append(",");
233
234 if (ds.at(ds.size() - 1) == '/')
235 name.append(ds.substr (0, ds.size() - 1));
236 else
237 name.append(ds);
238 }
239 if (!file.eof())
240 throw std::runtime_error ("failed to read file: " + dsFile);
241
242 auto sample = std::make_unique<SampleGrid> (dsName);
243 sample->meta()->setString (MetaFields::gridName, name);
244 sample->meta()->setString (MetaFields::gridFilter, MetaFields::gridFilter_default);
245 sh.add (std::move (sample));
246 }
247
248
249 void makeGridDirect (SampleHandler& sh, const std::string& disk,
250 const std::string& from, const std::string& to,
251 bool allow_partial)
252 {
253 using namespace msgDiscovery;
254
255 SampleHandler mysh;
256
257 for (auto sample : sh.samples())
258 {
259 SampleGrid *grid = dynamic_cast<SampleGrid*>(sample.get());
260
261 if (grid == nullptr)
262 {
263 mysh.add (sample);
264 } else
265 {
266 const std::string ds = grid->meta()->castString (MetaFields::gridName);
267 if (ds.empty())
268 throw std::runtime_error ("no dataset configured for grid sample " + grid->name());
269
271
272 std::set<std::string> knownFiles;
273 std::map<std::string,std::string> usedFiles;
274 for (auto& entry : rucioListFileReplicas (ds))
275 {
276 if (RCU::match_expr (pattern, entry.name))
277 {
278 knownFiles.insert (entry.name);
279 if (entry.disk == disk)
280 {
281 std::string url = entry.replica;
282 const auto split = url.find (from);
283 if (split == std::string::npos)
284 throw std::runtime_error ("prefix \"" + from + "\" not part of replica URL: " + url);
285 url.replace(split, from.size(), to);
286 usedFiles[entry.name] = url;
287 }
288 }
289 }
290
291 if (usedFiles.empty())
292 {
293 if (allow_partial)
294 ANA_MSG_WARNING ("dataset " << ds << " not at " << disk << ", skipped");
295 } else if (knownFiles.size() != usedFiles.size())
296 {
297 if (allow_partial)
298 {
299 ANA_MSG_WARNING ("only incomplete version of dataset " << ds << " at " << disk);
300 } else
301 {
302 usedFiles.clear ();
303 }
304 }
305
306 if (usedFiles.size() == 0)
307 {
308 mysh.add (sample);
309 } else
310 {
311 auto mysample = std::make_unique<SampleLocal> (grid->name());
312 *mysample->meta() = *grid->meta();
313
314 for (const auto& file : usedFiles)
315 {
316 mysample->add (file.second);
317 }
318 mysh.add (std::move (mysample));
319 }
320 }
321 }
322 swap (sh, mysh);
323 }
324
325
326
327 void scanForTrees (SampleHandler& sh, const std::shared_ptr<Sample>& sample,
328 const std::string& pattern)
329 {
330 auto mysample = sample->makeLocal();
331 if (mysample->numFiles() == 0)
332 {
333 sh.add (sample);
334 return;
335 }
336 std::unique_ptr<TFile> file (TFile::Open (mysample->fileName(0).c_str()));
337 if (!file.get())
338 throw std::runtime_error ("could not open file: " + mysample->fileName(0));
339 TObject *object = nullptr;
340 std::regex mypattern (pattern);
341 // rationale: GetListOfKeys() contains one key per tree cycle
342 // (e.g. "physics;1", "physics;2"), all with the same name. we
343 // process each name only once, so that repeated cycles do not
344 // make sh.add throw on a duplicate sample name.
345 std::set<std::string> seenTrees;
346 for (TIter iter (file->GetListOfKeys()); (object = iter.Next()); )
347 {
348 if (RCU::match_expr (mypattern, object->GetName()) &&
349 seenTrees.insert (object->GetName()).second &&
350 dynamic_cast<TTree*>(file->Get(object->GetName())))
351 {
352 std::string newName = sample->name() + "_" + object->GetName();
353 std::unique_ptr<Sample> newSample
354 (dynamic_cast<Sample*>(sample->Clone (newName.c_str())));
355 newSample->name (newName);
356 newSample->meta()->setString (MetaFields::treeName, object->GetName());
357 sh.add (std::move (newSample));
358 }
359 }
360 }
361
362
363
364 void scanForTrees (SampleHandler& sh, const std::string& pattern)
365 {
366 SH::SampleHandler sh_new;
367
368 for (auto sample : sh.samples())
369 {
370 scanForTrees (sh_new, sample, pattern);
371 }
372 swap (sh, sh_new);
373 }
374
375
376
377 void readFileList (SampleHandler& sh, const std::string& name,
378 const std::string& file)
379 {
380 std::ifstream myfile (file.c_str());
381
382 auto sample = std::make_unique<SampleLocal> (name);
383 std::string line;
384 const std::set<char> whitespaces{'\t',' ','\n','\r'};
385 while (std::getline (myfile, line))
386 {
387 while ((!line.empty()) && whitespaces.count(line.back())) line.pop_back();
388 if (!line.empty() && line.at(0) != '#')
389 {
390 sample->add (line);
391 }
392 }
393 if (!myfile.eof())
394 throw std::runtime_error ("failed to read file: " + file);
395 sh.add (std::move (sample));
396 }
397}
#define RCU_ASSERT_SOFT(x)
Definition Assert.h:155
#define ANA_MSG_WARNING(xmsg,...)
Macro printing warning messages.
static const std::vector< std::string > types
a DiskList implementation for local directories
an interface for listing directory contents, locally or on a file server
Definition DiskList.h:25
void swap(MetaObject &a, MetaObject &b)
standard swap
std::string castString(const std::string &name, const std::string &def_val="", CastMode mode=CAST_ERROR_THROW) const
the meta-data string with the given name
This class implements a Sample located on the grid.
Definition SampleGrid.h:36
A class that manages a list of Sample objects.
void add(const Sample &sample)
add a copy of the sample to the handler
a base class that manages a set of files belonging to a particular data set and the associated meta-d...
Definition Sample.h:49
MetaObject * meta()
the meta-information for this sample
const std::string & name() const
the name of the sample we are using
std::vector< std::string > split(const std::string &s, const std::string &t=":")
Definition hcg.cxx:179
bool match_expr(const std::regex &expr, std::string_view str)
returns: whether we can match the entire string with the regular expression guarantee: strong failure...
std::string glob_to_regexp(std::string_view glob)
returns: a string that is the regular expression equivalent of the given glob expression guarantee: s...
This module provides a lot of global definitions, forward declarations and includes that are used by ...
Definition DiskList.cxx:21
void scanSingleDir(SampleHandler &sh, const std::string &name, DiskList &list, const std::string &pattern)
effects: scan the given directory tree and turn it into a single sample of the given name guarantee: ...
void addGrid(SampleHandler &sh, const std::string &ds)
effects: add a grid dataset for dataset ds guarantee: strong failures: out of memory II requires: ds....
void scanDQ2(SampleHandler &sh, const std::string &pattern)
effects: make a list from DQ2 using the given pattern guarantee: basic, may add partially failures: o...
void scanForTrees(SampleHandler &sh, const std::shared_ptr< Sample > &sample, const std::string &pattern)
effects: scan for trees in the given sample (or sample handler), and create a separate sample for eac...
void readFileList(SampleHandler &sh, const std::string &name, const std::string &file)
effects: read a file list from a text file guarantee: strong failures: out of memory III failures: i/...
Sample * makeFromTChain(const std::string &name, const TChain &chain)
effects: create a sample with the given name from the given TChain object guarantee: strong failures:...
void scanFiles(SampleHandler &sh, DiskList &list, const std::string &pattern)
effects: scan the given directory tree and make a separate sample for each file (using the file name ...
std::vector< RucioListFileReplicasEntry > rucioListFileReplicas(const std::string &dataset)
run rucio-list-file-replicas for the given dataset
std::vector< RucioListDidsEntry > rucioListDids(const std::string &dataset)
run rucio-list-dids for the given dataset
void makeGridDirect(SampleHandler &sh, const std::string &disk, const std::string &from, const std::string &to, bool allow_partial)
effects: update all grid samples in the sample handler that are located on the given disk to be opene...
void scanDir(SampleHandler &sh, DiskList &list, const std::string &pattern, const std::string &samplePattern, const std::string &samplePostfix)
effects: scan the given directory and add all subdirectories as samples that contain root files.
void scanRucio(SampleHandler &sh, const std::string &pattern, bool alwaysQuery)
make a list of grid datasets using the given pattern
void addGridCombined(SampleHandler &sh, const std::string &dsName, const std::vector< std::string > &dsList)
effects: add a combined grid dataset with name dsName for dataset list dsList guarantee: strong failu...
void addGridCombinedFromFile(SampleHandler &sh, const std::string &dsName, const std::string &dsFile)
effects: add a combined grid dataset with name dsName for dataset list file dsFile guarantee: strong ...
std::unique_ptr< Sample > makeFromTChainUnique(const std::string &name, const TChain &chain)
effects: create a sample with the given name from the given TChain object guarantee: strong failures:...
static const std::string gridFilter
the field containing the file filter for the dataset on the grid
Definition MetaFields.h:30
static const std::string gridName
the field containing the name of the dataset on the grid
Definition MetaFields.h:26
static const std::string treeName
the name of the tree in the sample
Definition MetaFields.h:44
static const std::string gridFilter_default
the default value for gridFilter
Definition MetaFields.h:33
the class used for scanning local directories and file servers for samples
Definition ScanDir.h:39
ScanDir & samplePattern(const std::string &val_samplePattern)
the pattern for samples to be accepted
Definition ScanDir.cxx:130
const ScanDir & scan(SampleHandler &sh, const std::string &dir) const
scan the given directory and put the created samples into the sample handler
Definition ScanDir.cxx:168
ScanDir & sampleDepth(int val_sampleDepth)
the index of the file hierarchy at which we gather the sample name.
Definition ScanDir.cxx:47
ScanDir & maxDepth(std::size_t val_maxDepth)
the maximum depth for files to make it into the sample
Definition ScanDir.cxx:85
ScanDir & samplePostfix(const std::string &val_samplePostfix)
the pattern for the postfix to be stripped from the sampleName
Definition ScanDir.cxx:139
ScanDir & minDepth(std::size_t val_minDepth)
the minimum depth for files to make it into the sample
Definition ScanDir.cxx:76
ScanDir & sampleRename(const std::string &pattern, const std::string &name)
rename any sample matching pattern to name
Definition ScanDir.cxx:149
ScanDir & filePattern(const std::string &val_filePattern)
the pattern for files to be accepted
Definition ScanDir.cxx:94
TFile * file