Loading [MathJax]/extensions/tex2jax.js
ATLAS Offline Software
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
hist_file_dump.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 # Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3 from __future__ import print_function
4 
5 import ROOT
6 import sys, os
7 import argparse
8 import zlib
9 import json
10 from PyUtils.fprint import _formatFloat
11 from typing import List, Tuple, Callable
12 
13 def fixprecision(x, precision=15):
14  import math
15  if not isinstance(x, float):
16  return x
17  else:
18  mantissa, exponent = math.frexp(x)
19  sm = '%.12g' % mantissa
20  return _formatFloat (float(sm[:precision]) * 2**exponent)
21 
22 def jsonfixup(instr, fuzzyarray=False):
23  if not isinstance(instr, str):
24  instr = instr.Data()
25  j=json.loads(instr)
26  # the following are very subject to floating point numeric effects
27  # are doubles, keep 15 decimal digits of precision
28  for badkey in ('fTsumw', 'fTsumwx', 'fTsumw2', 'fTsumwx2', 'fTsumwy', 'fTsumwy2', 'fTsumwxy',
29  'fTsumwz', 'fTsumwz2', 'fTsumwxz', 'fTsumwyz' ):
30  if badkey in j:
31  j[badkey] = fixprecision(float(j[badkey]))
32  #print(type(j["fTsumwx"]))
33  # member, digits of precision
34  arrkeys: List[Tuple[str,int,Callable]] = [('fSumw2', 15, float)]
35  if fuzzyarray:
36  arrkeys += [('fBinEntries', 15, float), ('fBinSumw2', 15, float)]
37  # apply different precision for fArray depending on object type
38  if '_typename' in j:
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'):
43  # precision here isn't relevant, *should* be an integer
44  arrkeys.append(('fArray', 15, lambda x: x))
45  else:
46  arrkeys.append(('fArray', 15, float))
47  else:
48  arrkeys.append(('fArray', 15, float))
49  for badkey, precision, func in arrkeys:
50  if badkey in j:
51  j[badkey] = [fixprecision(func(_), precision) for _ in j[badkey]]
52  # the following ignores small layout fluctuations in TTrees
53  if 'fBranches' in j:
54  for branch in j['fBranches']['arr']:
55  branch['fBasketSeek'] = []
56  # The formatting of the opt array changed in newer ROOT versions
57  # to be filled with instances of None rather than empty strings.
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)
63 
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()
85 
86 ordering = args.rankorder
87 
88 accounting = {}; hashes = {}; types = {}
89 
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; }")
95 
96 ROOT.gSystem.Load('libDataQualityUtils')
97 
98 def fuzzytreehash(tkey):
99  t = tkey.ReadObj()
100  rv = zlib.adler32(((' '.join(_.GetName() for _ in t.GetListOfBranches()))
101  + (' '.join(_.GetName() + _.GetTypeName() for _ in t.GetListOfLeaves()))
102  + ' ' + str(t.GetEntries())).encode()
103  )
104  del t
105  return rv
106 
107 def dumpdir(d):
108  thispath = d.GetPath()
109  if ':' in thispath:
110  thispath = thispath.split(':', 1)[1]
111  #print thispath
112  subdirs = []
113  for k in d.GetListOfKeys():
114  if not args.metadata and k.GetName() == 'metadata' and k.GetClassName() == 'TTree':
115  continue
116  if k.GetClassName().startswith('TDirectory'):
117  subdirs.append(k)
118  else:
119  if args.tree_entries and k.GetClassName() == 'TTree':
120  lhash = fuzzytreehash(k)
121  elif args.hash:
122  if k.GetClassName() != 'TEfficiency':
123  fixedjson = jsonfixup(ROOT.getjson(k), args.fuzzy_histbins)
124  else:
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())
130  if lhash < 0:
131  lhash += 2**32
132  else:
133  lhash = 0
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()
138  for k in subdirs:
139  dumpdir(k.ReadObj())
140 
141 f = ROOT.TFile.Open(args.filename)
142 if args.path:
143  d = f.Get(args.path.rstrip('/'))
144  if not d:
145  print("Can't access path", args.path, "- exiting")
146  sys.exit(1)
147 else:
148  d = f
149 dumpdir(d)
150 
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])
155 else:
156  def key(x): return (x[0], x[1][1], x[1][0])
157 sortedl = sorted(accounting.items(), key=key, reverse=True)
158 if args.hash:
159  print('\n'.join(('%s %s: '
160  + ('%d uncompressed' % b if not args.no_inmem else '')
161  + (', %d on file ' % c if not args.no_onfile else ' ')
162  + '(hash %s)')
163  % (types[a], a, hashes[a]) for a, (b, c) in sortedl)
164  )
165 else:
166  print('\n'.join(('%s %s: '
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)
170  )
171 
DerivationFramework::TriggerMatchingUtils::sorted
std::vector< typename R::value_type > sorted(const R &r, PROJ proj={})
Helper function to create a sorted vector from an unsorted range.
hist_file_dump.jsonfixup
def jsonfixup(instr, fuzzyarray=False)
Definition: hist_file_dump.py:22
hist_file_dump.key
def key(x)
Definition: hist_file_dump.py:152
hist_file_dump.dumpdir
def dumpdir(d)
Definition: hist_file_dump.py:107
Data
@ Data
Definition: BaseObject.h:11
AtlasMcWeight::encode
number_type encode(double weight)
Definition: AtlasMcWeight.cxx:65
plotBeamSpotVxVal.range
range
Definition: plotBeamSpotVxVal.py:195
print
void print(char *figname, TCanvas *c1)
Definition: TRTCalib_StrawStatusPlots.cxx:25
TCS::join
std::string join(const std::vector< std::string > &v, const char c=',')
Definition: Trigger/TrigT1/L1Topo/L1TopoCommon/Root/StringUtils.cxx:10
hist_file_dump.fixprecision
def fixprecision(x, precision=15)
Definition: hist_file_dump.py:13
hist_file_dump.fuzzytreehash
def fuzzytreehash(tkey)
Definition: hist_file_dump.py:98
str
Definition: BTagTrackIpAccessor.cxx:11
python.LArMinBiasAlgConfig.float
float
Definition: LArMinBiasAlgConfig.py:65