9 from PyUtils.fprint
import _formatFloat
10 from typing
import List, Tuple, Callable
14 if not isinstance(x, float):
17 mantissa, exponent = math.frexp(x)
18 sm =
'%.12g' % mantissa
19 return _formatFloat (
float(sm[:precision]) * 2**exponent)
22 if not isinstance(instr, str):
27 for badkey
in (
'fTsumw',
'fTsumwx',
'fTsumw2',
'fTsumwx2',
'fTsumwy',
'fTsumwy2',
'fTsumwxy',
28 'fTsumwz',
'fTsumwz2',
'fTsumwxz',
'fTsumwyz' ):
33 arrkeys: List[Tuple[str,int,Callable]] = [(
'fSumw2', 15, float)]
35 arrkeys += [(
'fBinEntries', 15, float), (
'fBinSumw2', 15, float)]
38 if j[
'_typename']
in (
'TH1F',
'TH2F',
'TH3F'):
39 arrkeys.append((
'fArray', 6, float))
40 elif j[
'_typename']
in (
'TH1C',
'TH1I',
'TH1S',
'TH2C',
'TH2I',
'TH2S',
41 'TH3C',
'TH3I',
'TH3S'):
43 arrkeys.append((
'fArray', 15,
lambda x: x))
45 arrkeys.append((
'fArray', 15, float))
47 arrkeys.append((
'fArray', 15, float))
48 for badkey, precision, func
in arrkeys:
50 j[badkey] = [
fixprecision(func(_), precision)
for _
in j[badkey]]
53 for branch
in j[
'fBranches'][
'arr']:
54 branch[
'fBasketSeek'] = []
57 if 'fXaxis' in j
and 'fLabels' in j[
'fXaxis']
and j[
'fXaxis'][
'fLabels']
is not None and 'opt' in j[
'fXaxis'][
'fLabels']:
58 opt = j[
'fXaxis'][
'fLabels'][
'opt']
59 for i
in range(len(opt)):
60 if opt[i]
is None: opt[i] =
''
61 return json.dumps(j, sort_keys=
True)
63 parser=argparse.ArgumentParser()
64 parser.add_argument(
'filename',
65 help=
'Input HIST file name')
66 parser.add_argument(
'-r',
'--rankorder', default=
'onfile',
67 choices=[
'onfile',
'uncompressed',
'name'],
68 help=
'rankorder is "onfile" (default), "uncompressed" or "name"')
69 parser.add_argument(
'-p',
'--path',
70 help=
'Only look under this directory')
71 parser.add_argument(
'--hash', action=
'store_true',
72 help=
'Print hashes of objects')
73 parser.add_argument(
'--metadata', action=
'store_true',
74 help=
'Include metadata trees')
75 parser.add_argument(
'--no_onfile', action=
'store_true',
76 help=
"Don't show on file size")
77 parser.add_argument(
'--no_inmem', action=
'store_true',
78 help=
"Don't show in memory size")
79 parser.add_argument(
'--tree_entries', action=
'store_true',
80 help=
"Use more robust hash of TTree branches + entries")
81 parser.add_argument(
'--fuzzy_histbins', action=
'store_true',
82 help=
"Allow small variations in histogram bin content")
83 args=parser.parse_args()
85 ordering = args.rankorder
87 accounting = {}; hashes = {}; types = {}
89 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; }")
90 ROOT.gInterpreter.LoadText(
"void* getbuffer(TKey* key) { key->SetBuffer(); key->ReadFile(); return (void*) (key->GetBuffer()+key->GetKeylen()); }")
91 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; }")
92 ROOT.gInterpreter.LoadText(
"UInt_t bufferhash3(TKey* key) { TObject* obj = key->ReadObj(); UInt_t rv = obj->Hash(); delete obj; return rv; }")
93 ROOT.gInterpreter.LoadText(
"TString getjson(TKey* key) { TObject* obj = key->ReadObj(); auto rv = TBufferJSON::ConvertToJSON(obj); delete obj; return rv; }")
95 ROOT.gSystem.Load(
'libDataQualityUtils')
99 rv = zlib.adler32(((
' '.
join(_.GetName()
for _
in t.GetListOfBranches()))
100 + (
' '.
join(_.GetName() + _.GetTypeName()
for _
in t.GetListOfLeaves()))
107 thispath = d.GetPath()
109 thispath = thispath.split(
':', 1)[1]
112 for k
in d.GetListOfKeys():
113 if not args.metadata
and k.GetName() ==
'metadata' and k.GetClassName() ==
'TTree':
115 if k.GetClassName().startswith(
'TDirectory'):
118 if args.tree_entries
and k.GetClassName() ==
'TTree':
121 if k.GetClassName() !=
'TEfficiency':
122 fixedjson =
jsonfixup(ROOT.getjson(k), args.fuzzy_histbins)
124 j0 = json.loads(ROOT.getjson(k).Data())
125 for subh
in (
'fPassedHistogram',
'fTotalHistogram'):
126 j0[subh] = json.loads(
jsonfixup(json.dumps(j0[subh])))
127 fixedjson = json.dumps(j0, sort_keys=
True)
128 lhash = zlib.adler32(fixedjson.encode())
133 idxname = os.path.join(thispath, k.GetName())
134 accounting[idxname] = (k.GetObjlen(), k.GetNbytes()-k.GetKeylen())
135 hashes[idxname] = lhash
136 types[idxname] = k.GetClassName()
140 f = ROOT.TFile.Open(args.filename)
142 d = f.Get(args.path.rstrip(
'/'))
144 print(
"Can't access path", args.path,
"- exiting")
150 if ordering ==
'onfile':
151 def key(x):
return (x[1][1], x[1][0], x[0])
152 elif ordering ==
'uncompressed':
153 def key(x):
return (x[1][0], x[1][1], x[0])
155 def key(x):
return (x[0], x[1][1], x[1][0])
156 sortedl =
sorted(accounting.items(), key=key, reverse=
True)
159 + (
'%d uncompressed' % b
if not args.no_inmem
else '')
160 + (
', %d on file ' % c
if not args.no_onfile
else ' ')
162 % (types[a], a, hashes[a])
for a, (b, c)
in sortedl)
166 + (
'%d uncompressed' % b
if not args.no_inmem
else '')
167 + (
', %d on file' % c
if not args.no_onfile
else ' '))
168 % (types[a], a)
for a, (b, c)
in sortedl)