12 from functools
import wraps
16 def wrapper(*args, **kwargs):
17 print(
'WARNING: [InDetBeamSpotExample.DiskUtils]',
18 '{}() is deprecated and will be removed'.
format( fn.__name__),
20 print(
'WARNING: ', message,
22 return fn(*args, **kwargs)
27 from collections
import namedtuple
28 StorageManager = namedtuple(
'StorageManager', [
'name',
'prefix',
'cp',
'ls',
'longls'])
29 CastorMgr =
StorageManager(name=
'castor', prefix=
'root://castoratlas/', cp=
'xrdcp', ls=
'nsls %s', longls=
'nsls -l %s')
30 RFIOMgr =
StorageManager(name=
'rfio', prefix=
'rfio:', cp=
'rfcp', ls=
'rfdir %s', longls=
'rfdir %s')
31 EOSMgr =
StorageManager(name=
'eos', prefix=
'root://eosatlas.cern.ch/', cp=
'xrdcp', ls=
'/bin/sh -l -c "LD_LIBRARY_PATH=/usr/lib64/ eos ls %s"', longls=
'/bin/sh -l -c "LD_LIBRARY_PATH=/usr/lib64/ eos ls -l %s"')
32 UnixMgr =
StorageManager(name=
'unix', prefix=
'', cp=
'cp', ls=
'ls %s', longls=
'ls -l %s')
36 Rationalise a path, removing prefix and esuring single leading slash
38 for p
in (
'root://castoratlas/',
'root://eosatlas.cern.ch/',
'rfio:',
'castor:'):
39 if path.startswith(p):
41 if path.startswith(
'//'):
43 if not path.startswith(
'/'):
49 @
deprecated(
"EOS is mounted on /eos with fuse, so you probably don't need this abstraction")
52 Return SotrageManager to deal with listing, copying and reading files from various storage systems
55 if name.startswith(
'/castor/'):
57 elif name.startswith(
'/eos/'):
62 @
deprecated(
"DiskUtils.FileSet replaces this functionality")
65 lists CASTOR/EOS name server directory/file entries.
66 If path is a directory, filelist lists the entries in the directory;
67 they are sorted alphabetically.
69 `files` specifies the CASTOR/EOS pathname.
70 `prefix` specifies the prefix one wants to prepend to the path found.
71 (e.g. prefix='root://castoratlas/' or 'root://eosatlas.cern.ch//')
72 if prefix=True it will determin the prefix based on the pathname
75 filelist('/castor/cern.ch/atlas/*')
76 filelist('/castor/cern.ch/atl*/foo?[bar]/*.pool.root.?')
77 filelist('/eos/atlas/*', prefix='root://eosatlas.cern.ch/')
78 filelist('/castor/cern.ch/atlas/*', prefix=True)
81 path, fname = os.path.split(files)
84 if ( path.count(
'*') > 0
or path.count(
'?') > 0
or
85 path.count(
'[') > 0
or path.count(
']') > 0 ) :
87 return sum([
ls(os.path.join(p,fname))
93 flist = subprocess.check_output(mgr.ls % path, shell=
True).
split()
94 except subprocess.CalledProcessError
as err:
98 if not (os.path.basename(files)
in [
'',
'*']):
99 pattern = fnmatch.translate(os.path.basename(files))
100 flist =
filter(
lambda x: re.search(pattern, x), flist)
103 if isinstance(prefix, str):
104 return [os.path.join(prefix+path, p)
for p
in flist]
106 return [os.path.join(mgr.prefix+path, p)
for p
in flist]
108 return [os.path.join(path, p)
for p
in flist]
110 @
deprecated(
"EOS is mounted on /eos with fuse, so you probably don't need this abstraction")
111 def ls(path, longls=False):
115 `longls` specifies long listing format
122 return subprocess.check_output(mgr.longls % path, shell=
True)
124 return subprocess.check_output(mgr.ls % path, shell=
True)
126 @
deprecated(
"EOS is mounted on /eos with fuse, so you probably don't need this abstraction")
127 def cp(src, dest='.'):
134 if srcmgr.cp ==
'xrdcp' or destmgr.cp ==
'xrdcp': cp =
'xrdcp'
136 return os.system(
'%s %s%s %s%s' %(cp, srcmgr.prefix, src, destmgr.prefix, dest))
145 from PyUtils.RootUtils
import import_root
147 f = root.TFile.Open(root_file,
'READ')
149 meta = f.Get(
'MetaData' )
151 raise Exception(
'No metadata')
156 esiTypeName =
'EventStreamInfo'
157 for l
in meta.GetListOfLeaves():
158 if l.GetTypeName().startswith(esiTypeName):
159 esiTypeName = l.GetTypeName()
160 esiName = l.GetName()
163 if esiTypeName !=
'EventStreamInfo_p3':
164 raise Exception(
"old schema is not supported:", esiTypeName)
168 esic = cppyy.gbl.EventStreamInfoPTCnv_p3()
169 esi = getattr (meta, esiName)
170 if esiName.startswith(esiTypeName):
171 esiName = esiName[len(esiTypeName)+1:]
173 return(
list(esic.lumiBlockNumbers(esi)) )
175 except Exception
as e:
176 print(
"Failed to read MetaData will fall back to looping ",
repr(e))
181 from PyUtils.RootUtils
import import_root
183 f = root.TFile.Open(root_file,
'READ')
185 metadata= f.Get(
'CollectionMetadata')
if f
else None
189 key_name =
str(ctypes.c_char_p(metadata.Key).value)
190 assert key_name ==
'POOLCollectionID'
192 coll_tree = f.Get(
'POOLCollectionTree')
if f
else None
194 evtmax = coll_tree.GetEntries()
195 if evtmax
in (-1,
None):
198 for row
in range(evtmax):
199 if coll_tree.GetEntry(row) < 0:
201 lbn = coll_tree.LumiBlockN
204 return list( lumiblocks )
209 with open(path,
'w')
as mapfile:
210 for f, lbs
in file_set.with_lumi_blocks():
212 mapfile.write(
'{} {}\n'.
format(
214 ','.
join(
str(x)
for x
in lbs)))
218 def exists(self, path):
raise NotImplementedError
219 def is_file(self, path):
raise NotImplementedError
221 def children(self, path):
raise NotImplementedError
222 def glob(self, pattern):
raise NotImplementedError
223 def wrap(self, path):
return path
226 def exists(self, path):
return os.path.exists(path)
228 def is_file(self, path):
return os.path.isfile(path)
232 for dir_name, dirs, files
in os.walk(p):
234 yield os.path.join(dir_name, f)
238 return glob.glob(pattern)
241 """ Accesses EOS using the command line interface.
242 NB: when EOS is fuse-mounted on /eos this class is not really necessary.
245 def __init__(self, prefix='root://eosatlas.cern.ch/
'):
249 if path.startswith(
'/'):
254 if path.startswith(self.
prefix):
255 path = path[len(self.
prefix):]
259 return self.
_call(
'eos',
'-b',
'ls',
'-s', self.
unwrap(path)) == 0
262 return self.
_call(
'eos',
'-b',
'sat',
'-f', self.
unwrap(path)) == 0
265 return self.
_call(
'eos',
'-b',
'sat',
'-d', self.
unwrap(path)) == 0
268 with open(os.devnull,
'w')
as null:
269 output = subprocess.check_output([
'eos',
'-b',
'find',
'-f',
270 self.
unwrap(path)], stderr=null)
271 return [l.strip()
for l
in output.split(
'\n')]
274 with open(os.devnull,
'w')
as null:
275 retcode = subprocess.call(args, stderr=null)
281 """ Represents a list of input files.
282 This class abstracts over the different ways files can be specified, and
283 the different storage backends/protocols on which they reside. It is an
284 iterator, and provides some methods for filtering the file set. E.g.:
286 fs = FileSet.from_input('/eos/atlas/path/to/dataset/')
287 for f in fs.matching(r'.*AOD.*').only_existing():
310 be = backend
or Local()
311 return cls(be.children(path), be)
315 with open(path)
as lf:
316 listtoiter = [l.strip()
for l
in lf.readlines()]
317 iterator =
iter(listtoiter)
318 return cls(iterator, backend
or Local())
322 be = backend
or Local()
323 return cls(be.glob(pattern), be)
327 path = os.path.join(base, project, stream,
328 '{:0{digits}d}'.
format(
int(run), digits=8))
333 ''' Guess what kind of input file specification was provided. '''
334 be = backend
or Local()
335 if be.is_directory(input_string):
337 elif Local().is_file(input_string)
and not (
338 input_string.endswith(
'.root')
or
339 input_string[-7:-2] ==
'.root'):
341 elif be.is_file(input_string):
343 elif '*' in input_string
or '?' in input_string
or '[' in input_string:
368 name = os.path.basename(f)
373 raise FilterError(
'Not all explicit files were found.')
377 name, ext = os.path.splitext(f)
384 for name, ext
in em.items():
385 yield '.'.
join([name, ext])
386 it =
generator(functools.reduce(fn, self, {}))
391 ds =
'.'.
join(f.split(
'.')[0:3])
398 "Files found from more than one dataset: '{}' != '{}'"
401 it = map(
lambda x: self.
backend.wrap(x), it)
405 """ When strict, errors are raised in the following cases (which
406 otherwise cause the corresponding files to be silently skipped):
408 * When LB info is requested but cannot be found for a file (because
409 it was not in the map file, or we couldn't open the ROOT file).
410 * When `only_existing` is set and a file is missing.
411 * When a file list is provided and not all of the files it mentions
412 were encountered by the end of iteration.
418 ''' Only accept filenames matching the provided regular expression. '''
423 ''' Skip filenames matching the provided regular expression. '''
428 ''' Use specific filenames from within the provided dataset. '''
430 with open(path)
as lf:
431 self.
_explicit = [l.strip()
for l
in lf.readlines()]
437 ''' Only use existing files. '''
442 ''' Keep only the latest retry from sets like `*.1`, `*.2`. '''
447 ''' Require all files to be from the same dataset. '''
452 """ Lookup the luminosity blocks contained in each file.
453 If a map file is provided it will be queried for the LB mapping,
454 otherwise each file will be opened and accessed using AthenaROOTAccess
455 which can be a little slow.
463 with open(map_file)
as mf:
466 fname = line.split(
' ')[0]
467 print(line.split(
' ')[0])
468 print(line.split(
' ')[1])
469 lbs =
set(
int(l)
for l
in line.split(
' ')[1].
split(
','))
474 yield f, s.lb_map[os.path.basename(f)]