ATLAS Offline Software
Toggle main menu visibility
Loading...
Searching...
No Matches
Tools
PyJobTransforms
python
trfValidateRootFile.py
Go to the documentation of this file.
1
#!/usr/bin/env python
2
3
# Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
4
5
9
10
11
import
sys, os
12
import
logging
13
14
from
PyUtils
import
RootUtils
15
ROOT = RootUtils.import_root()
16
from
ROOT
import
TFile, TTree, TDirectory, TStopwatch
17
from
ROOT
import
RNTupleReader
18
from
PyUtils.PoolFile
import
isRNTuple
19
20
msg = logging.getLogger(__name__)
21
22
def
checkBranch
(branch):
23
24
msg.debug(
'Checking branch %s ...'
, branch.GetName())
25
26
nBaskets=branch.GetWriteBasket()
27
28
msg.debug(
'Checking %s baskets ...'
, nBaskets)
29
30
for
iBasket
in
range(nBaskets):
31
basket=branch.GetBasket(iBasket)
32
if
not
basket:
33
msg.warning(
'Basket %s of branch %s is corrupted.'
, iBasket, branch.GetName() )
34
return
1
35
36
listOfSubBranches=branch.GetListOfBranches()
37
msg.debug(
'Checking %s subbranches ...'
, listOfSubBranches.GetEntries())
38
for
subBranch
in
listOfSubBranches:
39
if
checkBranch
(subBranch)==1:
40
return
1
41
42
msg.debug(
'Branch %s looks ok.'
, branch.GetName())
43
return
0
44
45
46
def
checkTreeBasketWise
(tree):
47
48
listOfBranches=tree.GetListOfBranches()
49
50
msg.debug(
'Checking %s branches ...'
, listOfBranches.GetEntries())
51
52
for
branch
in
listOfBranches:
53
if
checkBranch
(branch)==1:
54
msg.warning(
'Tree %s is corrupted (branch %s ).'
, tree.GetName(), branch.GetName())
55
return
1
56
57
return
0
58
59
60
def
checkTreeEventWise
(tree, printInterval = 150000):
61
62
nEntries=tree.GetEntries()
63
64
msg.debug(
'Checking %s entries ...'
, nEntries)
65
66
for
i
in
range(nEntries):
67
if
tree.GetEntry(i)<0:
68
msg.warning(
'Event %s of tree %s is corrupted.'
, i, tree.GetName())
69
return
1
70
71
# Show a sign of life for long validation jobs: ATLASJT-433
72
if
(i%printInterval)==0
and
i>0:
73
msg.info(
'Validated %s events so far ...'
, i)
74
75
return
0
76
77
def
checkNTupleEventWise
(ntuple, printInterval = 150000):
78
79
try
:
80
reader=RNTupleReader.Open(ntuple)
81
except
Exception
as
err:
82
msg.warning(
'Could not open ntuple %s: %s'
, ntuple, err)
83
return
1
84
85
nEntries=reader.GetNEntries()
86
87
msg.debug(
'Checking %s entries ...'
, nEntries)
88
89
entry = reader.CreateEntry()
90
for
i
in
range(nEntries):
91
try
:
92
reader.LoadEntry(i, entry)
93
except
Exception
as
err:
94
msg.warning(
'Event %s of ntuple %s is corrupted: %s'
, i, reader.GetDescriptor().GetName(), err)
95
return
1
96
97
# Show a sign of life for long validation jobs: ATLASJT-433
98
if
(i%printInterval)==0
and
i>0:
99
msg.info(
'Validated %s events so far ...'
, i)
100
101
return
0
102
103
def
checkNTupleFieldWise
(ntuple):
104
"""For each cluster, bulk read each top level field.
105
"""
106
from
ROOT
import
RException
107
108
try
:
109
reader=RNTupleReader.Open(ntuple)
110
except
Exception
as
err:
111
msg.warning(
'Could not open ntuple %r: %r'
, ntuple, err)
112
return
1
113
114
try
:
115
descriptor = reader.GetDescriptor()
116
msg.debug(f
"ntupleName={descriptor.GetName()}"
)
117
118
model = reader.GetModel()
119
fieldZero = model.GetConstFieldZero()
120
subFields = fieldZero.GetConstSubfields()
121
msg.debug(f
"Top level fields number {subFields.size()}"
)
122
for
clusterDescriptor
in
descriptor.GetClusterIterable():
123
size = int(clusterDescriptor.GetNEntries())
124
if
msg.isEnabledFor(logging.DEBUG):
125
msg.debug(f
" cluster #{clusterDescriptor.GetId()}"
126
f
" firstEntryIndex={clusterDescriptor.GetFirstEntryIndex()}"
127
f
" nEntries={size}"
)
128
clusterRange = ROOT.RNTupleLocalRange(clusterDescriptor.GetId(), 0, size)
129
for
field
in
subFields:
130
if
msg.isEnabledFor(logging.DEBUG):
131
msg.debug(f
"fieldName={field.GetFieldName()} typeName={field.GetTypeName()}"
)
132
bulk = model.CreateBulk(field.GetFieldName())
133
values = bulk.ReadBulk(clusterRange)
134
if
msg.isEnabledFor(logging.DEBUG):
135
msg.debug(f
" values array at {values}"
)
136
# Be sure that this gets destroyed before field.
137
del bulk
138
139
except
RException
as
err:
140
from
traceback
import
format_exception
141
msg.error(
"Exception reading ntuple %r\n%s"
, ntuple,
""
.join(format_exception(err)))
142
return
1
143
144
return
0
145
146
def
checkDirectory
(directory, the_type, requireTree, depth):
147
148
from
PyUtils
import
PoolFile
149
nentries =
None
150
hasMetadata =
False
151
152
msg.debug(
'Checking directory %s ...'
, directory.GetName())
153
154
listOfKeys=directory.GetListOfKeys()
155
156
msg.debug(
'Checking %s keys ... '
, listOfKeys.GetEntries())
157
158
for
key
in
listOfKeys:
159
160
msg.debug(
'Looking at key %s ...'
, key.GetName())
161
msg.debug(
'Key is of class %s.'
, key.GetClassName())
162
163
the_object=directory.Get(key.GetName())
164
if
not
the_object:
165
msg.warning(
"Can't get object of key %s."
, key.GetName())
166
return
1
167
168
if
requireTree
and
not
isinstance(the_object, TTree):
169
msg.warning(
"Object of key %s is not of class TTree!"
, key.GetName())
170
return
1
171
172
if
isinstance(the_object,TTree):
173
174
msg.debug(
'Checking tree %s ...'
, the_object.GetName())
175
176
if
depth == 0:
177
if
PoolFile.PoolOpts.TTreeNames.EventData == the_object.GetName():
178
nentries = the_object.GetEntries()
179
msg.debug(f
' contains {nentries} events'
)
180
elif
PoolFile.PoolOpts.TTreeNames.MetaData == the_object.GetName():
181
hasMetadata =
True
182
msg.debug(
' contains MetaData'
)
183
184
if
the_type==
'event'
:
185
if
checkTreeEventWise
(the_object)==1:
186
return
1
187
elif
the_type==
'basket'
:
188
if
checkTreeBasketWise
(the_object)==1:
189
return
1
190
191
msg.debug(
'Tree %s looks ok.'
, the_object.GetName())
192
193
if
isRNTuple(the_object):
194
195
msg.debug(
'Checking ntuple of key %s ...'
, key.GetName())
196
197
try
:
198
reader=RNTupleReader.Open(the_object)
199
except
Exception
as
err:
200
msg.warning(
'Could not open ntuple %s: %s'
, the_object, err)
201
return
1
202
203
if
depth == 0:
204
if
PoolFile.PoolOpts.RNTupleNames.EventData == reader.GetDescriptor().GetName():
205
nentries = reader.GetNEntries()
206
msg.debug(f
' contains {nentries} events'
)
207
elif
PoolFile.PoolOpts.RNTupleNames.MetaData == reader.GetDescriptor().GetName():
208
hasMetadata =
True
209
msg.debug(
' contains MetaData'
)
210
211
if
the_type==
'event'
:
212
if
checkNTupleEventWise
(the_object)==1:
213
return
1
214
elif
the_type==
'basket'
:
215
if
checkNTupleFieldWise
(the_object)==1:
216
return
1
217
218
msg.debug(
'NTuple of key %s looks ok.'
, key.GetName())
219
220
if
isinstance(the_object, TDirectory):
221
if
checkDirectory
(the_object, the_type, requireTree, depth + 1)==1:
222
return
1
223
224
# Only check if metadata object is available as in standard POOL files
225
if
depth == 0
and
hasMetadata
and
checkNEvents
(directory.GetName(), nentries)==1:
226
return
1
227
else
:
228
msg.debug(
'Directory %s looks ok.'
, directory.GetName())
229
return
0
230
231
232
def
checkFile
(fileName, the_type, requireTree):
233
234
msg.info(
'Checking file %s ...'
, fileName)
235
236
enabledIMT =
False
237
if
not
ROOT.ROOT.IsImplicitMTEnabled()
and
os.environ.keys() >= {
'TRF_MULTITHREADED_VALIDATION'
,
'ATHENA_CORE_NUMBER'
}:
238
if
(nThreads := int(os.environ[
'ATHENA_CORE_NUMBER'
])) >= 0:
239
msg.info(f
"Setting the number of implicit ROOT threads to {nThreads}"
)
240
ROOT.ROOT.EnableImplicitMT(nThreads)
241
enabledIMT =
True
242
else
:
243
msg.warning(f
"Ignored negative ATHENA_CORE_NUMBER ({nThreads})"
)
244
245
try
:
246
file_handle=TFile.Open(fileName)
247
except
OSError
as
err:
248
msg.error(
'Could not open file %s: %s'
, fileName, err)
249
return
1
250
251
if
not
file_handle:
252
msg.warning(
"Can't access file %s."
, fileName)
253
return
1
254
255
if
not
file_handle.IsOpen():
256
msg.warning(
"Can't open file %s."
, fileName)
257
return
1
258
259
if
file_handle.IsZombie():
260
msg.warning(
"File %s is a zombie."
, fileName)
261
file_handle.Close()
262
return
1
263
264
if
file_handle.TestBit(TFile.kRecovered):
265
msg.warning(
"File %s needed to be recovered."
, fileName)
266
file_handle.Close()
267
return
1
268
269
if
checkDirectory
(file_handle, the_type, requireTree, 0)==1:
270
msg.warning(
"File %s is corrupted."
, fileName)
271
file_handle.Close()
272
return
1
273
274
file_handle.Close()
275
msg.info(
"File %s looks ok."
, fileName)
276
277
if
enabledIMT:
278
ROOT.ROOT.DisableImplicitMT()
279
280
return
0
281
282
283
def
checkNEvents
(fileName, nEntries):
284
"""Check consistency of number of events in file with metadata.
285
286
fileName name of file to check consistency of
287
nEntries number of events in fileName (e.g., obtained by examining event data object)
288
return 0 in case of consistency, 1 otherwise
289
"""
290
from
PyUtils.MetaReader
import
read_metadata
291
292
msg.debug(
'Checking number of events in file %s ...'
, fileName)
293
294
meta = read_metadata(fileName, mode=
'lite'
)[fileName]
295
msg.debug(
' according to metadata: {0}'
.format(meta[
"nentries"
]))
296
msg.debug(
' according to event data: {0}'
.format(nEntries))
297
if
meta[
"nentries"
]
and
nEntries
and
meta[
"nentries"
] != nEntries \
298
or
meta[
"nentries"
]
and
not
nEntries \
299
or
not
meta[
"nentries"
]
and
nEntries:
300
msg.warning(f
' number of events ({nEntries}) inconsistent with metadata ({meta["nentries"]}) in file {fileName!r}.'
)
301
return
1
302
else
:
303
msg.debug(
" looks ok."
)
304
return
0
305
306
def
usage
():
307
print
(
"Usage: validate filename type requireTree verbosity"
)
308
print
(
"'type' must be either 'event' or 'basket'"
)
309
print
(
"'requireTree' must be either 'true' or 'false'"
)
310
print
(
"'verbosity' must be either 'on' or 'off'"
)
311
312
return
2
313
314
315
def
main(argv):
316
317
clock=TStopwatch()
318
319
argc=len(argv)
320
321
if
(argc!=5):
322
return
usage
()
323
324
fileName=argv[1]
325
the_type=argv[2]
326
requireTree=argv[3]
327
verbosity=argv[4]
328
329
330
if
the_type!=
"event"
and
the_type!=
"basket"
:
331
return
usage
()
332
333
if
requireTree==
"true"
:
334
requireTree=
True
335
elif
requireTree==
"false"
:
336
requireTree=
False
337
else
:
338
return
usage
()
339
340
if
verbosity==
"on"
:
341
msg.setLevel(logging.DEBUG)
342
elif
verbosity==
"off"
:
343
msg.setLevel(logging.INFO)
344
else
:
345
return
usage
()
346
347
rc=
checkFile
(fileName,the_type, requireTree)
348
msg.debug(
'Returning %s'
, rc)
349
350
clock.Stop()
351
clock.Print()
352
353
return
rc
354
355
356
if
__name__ ==
'__main__'
:
357
358
ch=logging.StreamHandler(sys.stdout)
359
formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
360
ch.setFormatter(formatter)
361
msg.addHandler(ch)
362
363
rc=main(sys.argv)
364
sys.exit(rc)
365
print
void print(char *figname, TCanvas *c1)
Definition
TRTCalib_StrawStatusPlots.cxx:26
checkFile
Definition
checkFile.py:1
python.trfValidateRootFile.checkTreeEventWise
checkTreeEventWise(tree, printInterval=150000)
Definition
trfValidateRootFile.py:60
python.trfValidateRootFile.checkDirectory
checkDirectory(directory, the_type, requireTree, depth)
Definition
trfValidateRootFile.py:146
python.trfValidateRootFile.checkNEvents
checkNEvents(fileName, nEntries)
Definition
trfValidateRootFile.py:283
python.trfValidateRootFile.checkTreeBasketWise
checkTreeBasketWise(tree)
Definition
trfValidateRootFile.py:46
python.trfValidateRootFile.checkNTupleEventWise
checkNTupleEventWise(ntuple, printInterval=150000)
Definition
trfValidateRootFile.py:77
python.trfValidateRootFile.checkBranch
checkBranch(branch)
Definition
trfValidateRootFile.py:22
python.trfValidateRootFile.checkNTupleFieldWise
checkNTupleFieldWise(ntuple)
Definition
trfValidateRootFile.py:103
python.trfValidateRootFile.usage
usage()
Definition
trfValidateRootFile.py:306
Generated on
for ATLAS Offline Software by
1.17.0