3 from __future__
import print_function
10 from PyUtils.fprint
import _formatFloat
11 from typing
import List, Tuple, Callable
15 if not isinstance(x, float):
18 mantissa, exponent = math.frexp(x)
19 sm =
'%.12g' % mantissa
20 return _formatFloat (
float(sm[:precision]) * 2**exponent)
23 if not isinstance(instr, str):
28 for badkey
in (
'fTsumw',
'fTsumwx',
'fTsumw2',
'fTsumwx2',
'fTsumwy',
'fTsumwy2',
'fTsumwxy',
29 'fTsumwz',
'fTsumwz2',
'fTsumwxz',
'fTsumwyz' ):
34 arrkeys: List[Tuple[str,int,Callable]] = [(
'fSumw2', 15, float)]
36 arrkeys += [(
'fBinEntries', 15, float), (
'fBinSumw2', 15, float)]
39 if j[
'_typename']
in (
'TH1F',
'TH2F',
'TH3F'):
40 arrkeys.append((
'fArray', 6, float))
41 elif j[
'_typename']
in (
'TH1C',
'TH1I',
'TH1S',
'TH2C',
'TH2I',
'TH2S',
42 'TH3C',
'TH3I',
'TH3S'):
44 arrkeys.append((
'fArray', 15,
lambda x: x))
46 arrkeys.append((
'fArray', 15, float))
48 arrkeys.append((
'fArray', 15, float))
49 for badkey, precision, func
in arrkeys:
51 j[badkey] = [
fixprecision(func(_), precision)
for _
in j[badkey]]
54 for branch
in j[
'fBranches'][
'arr']:
55 branch[
'fBasketSeek'] = []
58 if 'fXaxis' in j
and 'fLabels' in j[
'fXaxis']
and j[
'fXaxis'][
'fLabels']
is not None and 'opt' in j[
'fXaxis'][
'fLabels']:
59 opt = j[
'fXaxis'][
'fLabels'][
'opt']
60 for i
in range(len(opt)):
61 if opt[i]
is None: opt[i] =
''
62 return json.dumps(j, sort_keys=
True)
64 parser=argparse.ArgumentParser()
65 parser.add_argument(
'filename',
66 help=
'Input HIST file name')
67 parser.add_argument(
'-r',
'--rankorder', default=
'onfile',
68 choices=[
'onfile',
'uncompressed',
'name'],
69 help=
'rankorder is "onfile" (default), "uncompressed" or "name"')
70 parser.add_argument(
'-p',
'--path',
71 help=
'Only look under this directory')
72 parser.add_argument(
'--hash', action=
'store_true',
73 help=
'Print hashes of objects')
74 parser.add_argument(
'--metadata', action=
'store_true',
75 help=
'Include metadata trees')
76 parser.add_argument(
'--no_onfile', action=
'store_true',
77 help=
"Don't show on file size")
78 parser.add_argument(
'--no_inmem', action=
'store_true',
79 help=
"Don't show in memory size")
80 parser.add_argument(
'--tree_entries', action=
'store_true',
81 help=
"Use more robust hash of TTree branches + entries")
82 parser.add_argument(
'--fuzzy_histbins', action=
'store_true',
83 help=
"Allow small variations in histogram bin content")
84 args=parser.parse_args()
86 ordering = args.rankorder
88 accounting = {}; hashes = {}; types = {}
90 ROOT.gInterpreter.LoadText(
"UInt_t bufferhash(TKey* key) { key->SetBuffer(); key->ReadFile(); UInt_t rv = TString::Hash(key->GetBuffer()+key->GetKeylen(), key->GetNbytes()-key->GetKeylen()); key->DeleteBuffer(); return rv; }")
91 ROOT.gInterpreter.LoadText(
"void* getbuffer(TKey* key) { key->SetBuffer(); key->ReadFile(); return (void*) (key->GetBuffer()+key->GetKeylen()); }")
92 ROOT.gInterpreter.LoadText(
"UInt_t bufferhash2(TKey* key) { TObject* obj = key->ReadObj(); TMessage msg(kMESS_OBJECT); msg.WriteObject(obj); UInt_t rv = TString::Hash(msg.Buffer(), msg.Length()); delete obj; return rv; }")
93 ROOT.gInterpreter.LoadText(
"UInt_t bufferhash3(TKey* key) { TObject* obj = key->ReadObj(); UInt_t rv = obj->Hash(); delete obj; return rv; }")
94 ROOT.gInterpreter.LoadText(
"TString getjson(TKey* key) { TObject* obj = key->ReadObj(); auto rv = TBufferJSON::ConvertToJSON(obj); delete obj; return rv; }")
96 ROOT.gSystem.Load(
'libDataQualityUtils')
100 rv = zlib.adler32(((
' '.
join(_.GetName()
for _
in t.GetListOfBranches()))
101 + (
' '.
join(_.GetName() + _.GetTypeName()
for _
in t.GetListOfLeaves()))
108 thispath = d.GetPath()
110 thispath = thispath.split(
':', 1)[1]
113 for k
in d.GetListOfKeys():
114 if not args.metadata
and k.GetName() ==
'metadata' and k.GetClassName() ==
'TTree':
116 if k.GetClassName().startswith(
'TDirectory'):
119 if args.tree_entries
and k.GetClassName() ==
'TTree':
122 if k.GetClassName() !=
'TEfficiency':
123 fixedjson =
jsonfixup(ROOT.getjson(k), args.fuzzy_histbins)
125 j0 = json.loads(ROOT.getjson(k).
Data())
126 for subh
in (
'fPassedHistogram',
'fTotalHistogram'):
127 j0[subh] = json.loads(
jsonfixup(json.dumps(j0[subh])))
128 fixedjson = json.dumps(j0, sort_keys=
True)
129 lhash = zlib.adler32(fixedjson.encode())
134 idxname = os.path.join(thispath, k.GetName())
135 accounting[idxname] = (k.GetObjlen(), k.GetNbytes()-k.GetKeylen())
136 hashes[idxname] = lhash
137 types[idxname] = k.GetClassName()
141 f = ROOT.TFile.Open(args.filename)
143 d = f.Get(args.path.rstrip(
'/'))
145 print(
"Can't access path", args.path,
"- exiting")
151 if ordering ==
'onfile':
152 def key(x):
return (x[1][1], x[1][0], x[0])
153 elif ordering ==
'uncompressed':
154 def key(x):
return (x[1][0], x[1][1], x[0])
156 def key(x):
return (x[0], x[1][1], x[1][0])
157 sortedl =
sorted(accounting.items(), key=key, reverse=
True)
160 + (
'%d uncompressed' % b
if not args.no_inmem
else '')
161 + (
', %d on file ' % c
if not args.no_onfile
else ' ')
163 % (types[a], a, hashes[a])
for a, (b, c)
in sortedl)
167 + (
'%d uncompressed' % b
if not args.no_inmem
else '')
168 + (
', %d on file' % c
if not args.no_onfile
else ' '))
169 % (types[a], a)
for a, (b, c)
in sortedl)