3 from __future__
import print_function
13 from functools
import wraps
17 def wrapper(*args, **kwargs):
18 print(
'WARNING: [InDetBeamSpotExample.DiskUtils]',
19 '{}() is deprecated and will be removed'.
format( fn.__name__),
21 print(
'WARNING: ', message,
23 return fn(*args, **kwargs)
28 from collections
import namedtuple
29 StorageManager = namedtuple(
'StorageManager', [
'name',
'prefix',
'cp',
'ls',
'longls'])
30 CastorMgr =
StorageManager(name=
'castor', prefix=
'root://castoratlas/', cp=
'xrdcp', ls=
'nsls %s', longls=
'nsls -l %s')
31 RFIOMgr =
StorageManager(name=
'rfio', prefix=
'rfio:', cp=
'rfcp', ls=
'rfdir %s', longls=
'rfdir %s')
32 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"')
33 UnixMgr =
StorageManager(name=
'unix', prefix=
'', cp=
'cp', ls=
'ls %s', longls=
'ls -l %s')
37 Rationalise a path, removing prefix and esuring single leading slash
39 for p
in (
'root://castoratlas/',
'root://eosatlas.cern.ch/',
'rfio:',
'castor:'):
40 if path.startswith(p):
42 if path.startswith(
'//'):
44 if not path.startswith(
'/'):
50 @
deprecated(
"EOS is mounted on /eos with fuse, so you probably don't need this abstraction")
53 Return SotrageManager to deal with listing, copying and reading files from various storage systems
56 if name.startswith(
'/castor/'):
58 elif name.startswith(
'/eos/'):
63 @
deprecated(
"DiskUtils.FileSet replaces this functionality")
66 lists CASTOR/EOS name server directory/file entries.
67 If path is a directory, filelist lists the entries in the directory;
68 they are sorted alphabetically.
70 `files` specifies the CASTOR/EOS pathname.
71 `prefix` specifies the prefix one wants to prepend to the path found.
72 (e.g. prefix='root://castoratlas/' or 'root://eosatlas.cern.ch//')
73 if prefix=True it will determin the prefix based on the pathname
76 filelist('/castor/cern.ch/atlas/*')
77 filelist('/castor/cern.ch/atl*/foo?[bar]/*.pool.root.?')
78 filelist('/eos/atlas/*', prefix='root://eosatlas.cern.ch/')
79 filelist('/castor/cern.ch/atlas/*', prefix=True)
82 path, fname = os.path.split(files)
85 if ( path.count(
'*') > 0
or path.count(
'?') > 0
or
86 path.count(
'[') > 0
or path.count(
']') > 0 ) :
88 return sum([
ls(os.path.join(p,fname))
94 flist = subprocess.check_output(mgr.ls % path, shell=
True).
split()
95 except subprocess.CalledProcessError
as err:
99 if not (os.path.basename(files)
in [
'',
'*']):
100 pattern = fnmatch.translate(os.path.basename(files))
101 flist =
filter(
lambda x: re.search(pattern, x), flist)
104 if isinstance(prefix, str):
105 return [os.path.join(prefix+path, p)
for p
in flist]
107 return [os.path.join(mgr.prefix+path, p)
for p
in flist]
109 return [os.path.join(path, p)
for p
in flist]
111 @
deprecated(
"EOS is mounted on /eos with fuse, so you probably don't need this abstraction")
112 def ls(path, longls=False):
116 `longls` specifies long listing format
123 return subprocess.check_output(mgr.longls % path, shell=
True)
125 return subprocess.check_output(mgr.ls % path, shell=
True)
127 @
deprecated(
"EOS is mounted on /eos with fuse, so you probably don't need this abstraction")
128 def cp(src, dest='.'):
135 if srcmgr.cp ==
'xrdcp' or destmgr.cp ==
'xrdcp': cp =
'xrdcp'
137 return os.system(
'%s %s%s %s%s' %(cp, srcmgr.prefix, src, destmgr.prefix, dest))
146 from PyUtils.RootUtils
import import_root
148 f = root.TFile.Open(root_file,
'READ')
150 meta = f.Get(
'MetaData' )
152 raise Exception(
'No metadata')
157 esiTypeName =
'EventStreamInfo'
158 for l
in meta.GetListOfLeaves():
159 if l.GetTypeName().startswith(esiTypeName):
160 esiTypeName = l.GetTypeName()
161 esiName = l.GetName()
164 if esiTypeName !=
'EventStreamInfo_p3':
165 raise Exception(
"old schema is not supported:", esiTypeName)
169 esic = cppyy.gbl.EventStreamInfoPTCnv_p3()
170 esi = getattr (meta, esiName)
171 if esiName.startswith(esiTypeName):
172 esiName = esiName[len(esiTypeName)+1:]
174 return(
list(esic.lumiBlockNumbers(esi)) )
176 except Exception
as e:
177 print(
"Failed to read MetaData will fall back to looping ",
repr(e))
182 from PyUtils.RootUtils
import import_root
184 f = root.TFile.Open(root_file,
'READ')
186 metadata= f.Get(
'CollectionMetadata')
if f
else None
190 key_name =
str(ctypes.c_char_p(metadata.Key).value)
191 assert key_name ==
'POOLCollectionID'
193 coll_tree = f.Get(
'POOLCollectionTree')
if f
else None
195 evtmax = coll_tree.GetEntries()
196 if evtmax
in (-1,
None):
199 for row
in range(evtmax):
200 if coll_tree.GetEntry(row) < 0:
202 lbn = coll_tree.LumiBlockN
205 return list( lumiblocks )
210 with open(path,
'w')
as mapfile:
211 for f, lbs
in file_set.with_lumi_blocks():
213 mapfile.write(
'{} {}\n'.
format(
215 ','.
join(
str(x)
for x
in lbs)))
219 def exists(self, path):
raise NotImplementedError
220 def is_file(self, path):
raise NotImplementedError
222 def children(self, path):
raise NotImplementedError
223 def glob(self, pattern):
raise NotImplementedError
224 def wrap(self, path):
return path
227 def exists(self, path):
return os.path.exists(path)
229 def is_file(self, path):
return os.path.isfile(path)
233 for dir_name, dirs, files
in os.walk(p):
235 yield os.path.join(dir_name, f)
239 return glob.glob(pattern)
242 """ Accesses EOS using the command line interface.
243 NB: when EOS is fuse-mounted on /eos this class is not really necessary.
246 def __init__(self, prefix='root://eosatlas.cern.ch/
'):
250 if path.startswith(
'/'):
255 if path.startswith(self.
prefix):
256 path = path[len(self.
prefix):]
260 return self.
_call(
'eos',
'-b',
'ls',
'-s', self.
unwrap(path)) == 0
263 return self.
_call(
'eos',
'-b',
'sat',
'-f', self.
unwrap(path)) == 0
266 return self.
_call(
'eos',
'-b',
'sat',
'-d', self.
unwrap(path)) == 0
269 with open(os.devnull,
'w')
as null:
270 output = subprocess.check_output([
'eos',
'-b',
'find',
'-f',
271 self.
unwrap(path)], stderr=null)
272 return [l.strip()
for l
in output.split(
'\n')]
275 with open(os.devnull,
'w')
as null:
276 retcode = subprocess.call(args, stderr=null)
282 """ Represents a list of input files.
283 This class abstracts over the different ways files can be specified, and
284 the different storage backends/protocols on which they reside. It is an
285 iterator, and provides some methods for filtering the file set. E.g.:
287 fs = FileSet.from_input('/eos/atlas/path/to/dataset/')
288 for f in fs.matching(r'.*AOD.*').only_existing():
307 return cls(iter([path]), backend
or Local())
311 be = backend
or Local()
312 return cls(be.children(path), be)
316 with open(path)
as lf:
317 listtoiter = [l.strip()
for l
in lf.readlines()]
318 iterator = iter(listtoiter)
319 return cls(iterator, backend
or Local())
323 be = backend
or Local()
324 return cls(be.glob(pattern), be)
328 path = os.path.join(base, project, stream,
329 '{:0{digits}d}'.
format(
int(run), digits=8))
334 ''' Guess what kind of input file specification was provided. '''
335 be = backend
or Local()
336 if be.is_directory(input_string):
338 elif Local().is_file(input_string)
and not (
339 input_string.endswith(
'.root')
or
340 input_string[-7:-2] ==
'.root'):
342 elif be.is_file(input_string):
344 elif '*' in input_string
or '?' in input_string
or '[' in input_string:
369 name = os.path.basename(f)
374 raise FilterError(
'Not all explicit files were found.')
378 name, ext = os.path.splitext(f)
385 for name, ext
in em.items():
386 yield '.'.
join([name, ext])
387 it =
generator(functools.reduce(fn, self, {}))
392 ds =
'.'.
join(f.split(
'.')[0:3])
399 "Files found from more than one dataset: '{}' != '{}'"
402 it = map(
lambda x: self.
backend.wrap(x), it)
406 """ When strict, errors are raised in the following cases (which
407 otherwise cause the corresponding files to be silently skipped):
409 * When LB info is requested but cannot be found for a file (because
410 it was not in the map file, or we couldn't open the ROOT file).
411 * When `only_existing` is set and a file is missing.
412 * When a file list is provided and not all of the files it mentions
413 were encountered by the end of iteration.
419 ''' Only accept filenames matching the provided regular expression. '''
424 ''' Skip filenames matching the provided regular expression. '''
429 ''' Use specific filenames from within the provided dataset. '''
431 with open(path)
as lf:
432 self.
_explicit = [l.strip()
for l
in lf.readlines()]
438 ''' Only use existing files. '''
443 ''' Keep only the latest retry from sets like `*.1`, `*.2`. '''
448 ''' Require all files to be from the same dataset. '''
453 """ Lookup the luminosity blocks contained in each file.
454 If a map file is provided it will be queried for the LB mapping,
455 otherwise each file will be opened and accessed using AthenaROOTAccess
456 which can be a little slow.
464 with open(map_file)
as mf:
467 fname = line.split(
' ')[0]
468 print(line.split(
' ')[0])
469 print(line.split(
' ')[1])
470 lbs =
set(
int(l)
for l
in line.split(
' ')[1].
split(
','))
475 yield f, s.lb_map[os.path.basename(f)]