ATLAS Offline Software
Loading...
Searching...
No Matches
trfFileUtils.py
Go to the documentation of this file.
1# Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
2
8
9import logging
10msg = logging.getLogger(__name__)
11
12# @note Use the PyUtils forking decorator to ensure that ROOT is run completely within
13# a child process and will not 'pollute' the parent python process with unthread-safe
14# bits of code (otherwise strange hangs are observed on subsequent uses of ROOT)
15import PyUtils.Decorators as _decos
16
17from PyUtils.RootUtils import import_root
18
19# Use a stripped down key list, as we retrieve only 'fast' metadata
20athFileInterestingKeys = ['file_size', 'file_guid', 'file_type', 'nentries']
21
22
23def AthenaLiteFileInfo(filename, filetype, retrieveKeys = athFileInterestingKeys):
24 msg.debug('Calling AthenaLiteFileInfo for {0} (type {1})'.format(filename, filetype))
25 from PyUtils.MetaReader import read_metadata
26
27 metaDict = {}
28 try:
29 meta = read_metadata(filename,None,'lite')[filename]
30 msg.debug('read_metadata came back for {0}'.format(filename))
31 metaDict[filename] = {}
32 for key in retrieveKeys:
33 msg.debug('Looking for key {0}'.format(key))
34 try:
35 metaval = meta[key]
36 metaDict[filename][key] = metaval.lower() if key == 'file_type' else metaval
37 except KeyError:
38 msg.warning('Missing key in athFile info: {0}'.format(key))
39 except (ValueError, AssertionError, ReferenceError):
40 msg.error('Problem in getting metadata for {0}'.format(filename))
41 return None
42 msg.debug('Returning {0}'.format(metaDict))
43 return metaDict
44
45
54@_decos.forking
55def HISTEntries(fileName):
56
57 root = import_root()
58
59 fname = root.TFile.Open(fileName, 'READ')
60
61 if not (isinstance(fname, root.TFile) and fname.IsOpen()):
62 return None
63
64 # HIST_HLTMON case
65 htrig_path = 'HLTFramework/HltEventLoopMgr/TotalTime'
66 htrig = fname.Get(htrig_path)
67 if isinstance( htrig, root.TH1 ):
68 nev_trig = htrig.GetEntries()
69 fname.Close()
70 msg.debug( 'Retrieved %s in file %s, found %i entries', htrig_path, fileName, nev_trig)
71 return nev_trig
72
73 rundir = None
74 keys = fname.GetListOfKeys()
75
76 for key in keys:
77
78 name=key.GetName()
79
80 if name.startswith('run_') and name != 'run_multiple':
81
82 if rundir is not None:
83 msg.warning('Found two run_ directories in HIST file %s: %s and %s', fileName, rundir, name)
84 return None
85 else:
86 rundir = name
87
88 del name
89
90 if rundir is None:
91 msg.warning( 'Unable to find run directory in HIST file %s', fileName )
92 fname.Close()
93 return None
94
95 msg.info( 'Using run directory %s for event counting of HIST file %s. ', rundir, fileName )
96
97 hpath = '%s/GLOBAL/DQTDataFlow/events_lb' % rundir
98 possibleLBs = []
99 if 'tmp.HIST_' in fileName:
100 msg.info( 'Special case for temporary HIST file {0}. '.format( fileName ) )
101 h = fname.Get('{0}'.format(rundir))
102 for directories in h.GetListOfKeys() :
103 if 'lb' in directories.GetName():
104 msg.info( 'Using {0} in tmp HIST file {1}. '.format(directories.GetName(), fileName ) )
105 hpath = rundir+'/'+str(directories.GetName())+'/GLOBAL/DQTDataFlow/events_lb'
106 possibleLBs.append(hpath)
107 else:
108 msg.info( 'Classical case for HIST file {0}. '.format( fileName ) )
109 possibleLBs.append(hpath)
110 nev = 0
111 if len(possibleLBs) == 0:
112 msg.warning( 'Unable to find events_lb histogram in HIST file %s', fileName )
113 fname.Close()
114 return None
115 for hpath in possibleLBs:
116 h = fname.Get(hpath)
117
118 if not isinstance( h, root.TH1 ):
119 msg.warning( 'Unable to retrieve %s in HIST file %s.', hpath, fileName )
120 fname.Close()
121 return None
122
123 nBinsX = h.GetNbinsX()
124 nevLoc = 0
125
126 for i in range(1, nBinsX):
127
128 if h[i] < 0:
129 msg.warning( 'Negative number of events for step %s in HIST file %s.', h.GetXaxis().GetBinLabel(i), fileName )
130 fname.Close()
131 return None
132
133 elif h[i] == 0:
134 continue
135
136 if nevLoc == 0:
137 nevLoc = h[i]
138
139 else:
140 if nevLoc != h[i]:
141 msg.warning( 'Mismatch in events per step in HIST file %s; most recent step seen is %s.', fileName, h.GetXaxis().GetBinLabel(i) )
142 fname.Close()
143 return None
144 nev += nevLoc
145 fname.Close()
146 return nev
147
148
149
150
161@_decos.forking
162def NTUPEntries(fileName, treeNames):
163
164 if not isinstance( treeNames, list ):
165 treeNames=[treeNames]
166
167 root = import_root()
168
169 fname = root.TFile.Open(fileName, 'READ')
170
171 if not (isinstance(fname, root.TFile) and fname.IsOpen()):
172 return None
173
174 prevNum=None
175 prevTree=None
176
177 for treeName in treeNames:
178
179 tree = fname.Get(treeName)
180
181 if not isinstance(tree, root.TTree):
182 return None
183
184 num = tree.GetEntriesFast()
185
186 if not num>=0:
187 msg.warning('GetEntriesFast returned non positive value for tree %s in NTUP file %s.', treeName, fileName )
188 return None
189
190 if prevNum is not None and prevNum != num:
191 msg.warning( "Found diffferent number of entries in tree %s and tree %s of file %s.", treeName, prevTree, fileName )
192 return None
193
194 numberOfEntries=num
195 prevTree=treeName
196 del num
197 del tree
198
199 fname.Close()
200
201 return numberOfEntries
202
203
204
214@_decos.forking
215def PRWEntries(fileName, integral=False):
216
217 root = import_root()
218
219 fname = root.TFile.Open(fileName, 'READ')
220
221 if not (isinstance(fname, root.TFile) and fname.IsOpen()):
222 return None
223
224 rundir = None
225
226 for key in fname.GetListOfKeys():
227 if key.GetName()=='PileupReweighting':
228 rundir = fname.Get('PileupReweighting')
229 break
230 # Not PRW...
231
232 if rundir is None: return None
233
234 total = 0
235 for key in rundir.GetListOfKeys():
236 if 'pileup' in key.GetName():
237 msg.debug('Working on file '+fileName+' histo '+key.GetName())
238 if integral:
239 total += rundir.Get(key.GetName()).Integral()
240 else:
241 total += rundir.Get(key.GetName()).GetEntries()
242 # Was not one of our histograms
243 # Make sure we return an int for the number of events
244 return int(total)
245
246
247
257@_decos.forking
258def PHYSVALEntries(fileName, integral=False):
259
260 root = import_root()
261
262 fname = root.TFile.Open(fileName, 'READ')
263
264 if not (isinstance(fname, root.TFile) and fname.IsOpen()):
265 return None
266
267 aipc = fname.Get("/EventInfo/EventInfo_actualInteractionsPerCrossing")
268
269 if not aipc:
270 # Not PHYSVAL...
271 return None
272
273 # If we want the weights, give us the weights
274 if integral:
275 return aipc.Integral()
276
277 # Otherwise we just want the entries
278 return int(aipc.GetEntries())
279
280
281
290@_decos.forking
291def ROOTGetSize(filename):
292 root = import_root()
293
294 try:
295 msg.debug('Calling TFile.Open for {0}'.format(filename))
296 extraparam = '?filetype=raw'
297 if filename.startswith("https") or filename.startswith("davs"):
298 try:
299 pos = filename.find("?")
300 if pos>=0:
301 extraparam = '&filetype=raw'
302 else:
303 extraparam = '?filetype=raw'
304 except Exception:
305 extraparam = '?filetype=raw'
306 fname = root.TFile.Open(filename + extraparam, 'READ')
307 fsize = fname.GetSize()
308 msg.debug('Got size {0} from TFile.GetSize'.format(fsize))
309 except ReferenceError:
310 msg.error('Failed to get size of {0}'.format(filename))
311 return None
312
313 fname.Close()
314 del root
315 return fsize
316
317
318
322def urlType(filename):
323 if filename.startswith('dcap:'):
324 return 'dcap'
325 if filename.startswith('root:'):
326 return 'root'
327 if filename.startswith('rfio:'):
328 return 'rfio'
329 if filename.startswith('file:'):
330 return 'posix'
331 if filename.startswith('https:'):
332 return 'root'
333 if filename.startswith('davs:'):
334 return 'root'
335 return 'posix'
336
TGraphErrors * GetEntries(TH2F *histo)
NTUPEntries(fileName, treeNames)
Determines number of entries in NTUP file with given tree names.
ROOTGetSize(filename)
Get the size of a file via ROOT's TFile.
AthenaLiteFileInfo(filename, filetype, retrieveKeys=athFileInterestingKeys)
New lightweight interface to getting a single file's metadata.
PRWEntries(fileName, integral=False)
Determines number of entries in PRW file.
PHYSVALEntries(fileName, integral=False)
Determines number of entries in NTUP_PHYSVAL file.
urlType(filename)
Return the LAN access type for a file URL.
HISTEntries(fileName)
Determines number of events in a HIST file.