ATLAS Offline Software
Loading...
Searching...
No Matches
merge_scale_histograms.py
Go to the documentation of this file.
1#!/bin/env python
2
3# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
4
5
6from array import array
7import logging
8import ROOT
9doc = """
10This is an utility to merge histograms. The common case is when you have
11old scale factors for the whole calorimeter and new scale factor only for
12a subpart.
13"""
14
15ROOT.PyConfig.IgnoreCommandLineOptions = True
16logging.basicConfig(level=logging.INFO)
17
18
19def merge_histograms(old, new, merge_error=True):
20 print("old binning: " + ", ".join(("%.3f" % old.GetBinLowEdge(ibin))
21 for ibin in range(1, old.GetNbinsX()
22 + 2)))
23 print("new binning: " + ", ".join(("%.3f" % new.GetBinLowEdge(ibin))
24 for ibin in range(1, new.GetNbinsX()
25 + 2)))
26
27 new_binning = []
28 new_values = []
29 new_errors = []
30 UNDERFLOW = 0
31 OVERFLOW = new.GetNbinsX() + 1
32
33 for iold in range(1, old.GetNbinsX()):
34 low = old.GetBinLowEdge(iold)
35 r = low + old.GetBinWidth(iold)
36
37 il_new = new.FindFixBin(low)
38 ir_new = new.FindFixBin(r)
39 remainer = None
40
41 if il_new == UNDERFLOW and ir_new == UNDERFLOW:
42 print("1. adding %.3f - %.3f from old" % (low, r))
43 new_binning.append((low, r))
44 new_values.append(old.GetBinContent(iold))
45 new_errors.append(old.GetBinError(iold))
46
47 elif il_new == UNDERFLOW and ir_new > UNDERFLOW:
48 if abs(new.GetBinLowEdge(1) - low) < 1E-100:
49 continue
50 new_binning.append((low, new.GetBinLowEdge(1)))
51 new_values.append(old.GetBinContent(iold))
52 new_errors.append(old.GetBinError(iold))
53 if ir_new == OVERFLOW:
54 remainer = iold # noqa: F841
55 print("breaking")
56 break
57 last_old = iold
58
59 for inew in range(1, new.GetNbinsX() + 1):
60 low = new.GetBinLowEdge(inew)
61 r = low + new.GetBinWidth(inew)
62 print("2. adding %.3f - %.3f from new" % (low, r))
63 new_binning.append((low, r))
64 new_values.append(new.GetBinContent(inew))
65 new_errors.append(new.GetBinError(inew))
66
67 for iold in range(last_old, old.GetNbinsX() + 1):
68 low = old.GetBinLowEdge(iold)
69 r = low + old.GetBinWidth(iold)
70
71 il_new = new.FindFixBin(low)
72 ir_new = new.FindFixBin(r)
73
74 if il_new == OVERFLOW and ir_new == OVERFLOW:
75 print("4. adding %.3f - %.3f from old" % (low, r))
76 new_binning.append((low, r))
77 new_values.append(old.GetBinContent(iold))
78 new_errors.append(old.GetBinError(iold))
79 elif il_new < OVERFLOW and ir_new == OVERFLOW:
80 if abs(new.GetBinLowEdge(new.GetNbinsX() + 1) - r) < 1E-100:
81 continue
82 new_binning.append((new.GetBinLowEdge(new.GetNbinsX() + 1), r))
83 new_values.append(old.GetBinContent(iold))
84 new_errors.append(old.GetBinError(iold))
85
86 print(new_binning)
87 new_edges = array('f', [x[0] for x in new_binning] + [new_binning[-1][1]])
88 histo_type = type(new)
89 result = histo_type(new.GetName(), new.GetTitle(),
90 len(new_edges) - 1, new_edges)
91 for i, (v, e) in enumerate(zip(new_values, new_errors), 1):
92 result.SetBinContent(i, v)
93 if merge_error:
94 result.SetBinError(i, e)
95
96 print("merged binning: " + ", ".join(("%.3f" % result.GetBinLowEdge(ibin))
97 for ibin in range(1, result.GetNbinsX()
98 + 1)))
99
100 return result
101
102
103if __name__ == "__main__":
104 try:
105 ROOT.gROOT.ProcessLine(".x ~/atlasstyle/AtlasStyle.C")
106 ROOT.SetAtlasStyle()
107 except AttributeError:
108 pass
109
110 import argparse
111
112 parser = argparse.ArgumentParser(description=doc,
113 formatter_class=argparse.RawTextHelpFormatter)
114 parser.add_argument('histo_old')
115 parser.add_argument('histo_new')
116 parser.add_argument('--title', help='title of the new histogram')
117 parser.add_argument('--name', help='name of the new histogram')
118 parser.add_argument(
119 '--recreate', help='create a new file', action='store_true')
120 parser.add_argument('--output-filename', default='output.root')
121
122 args = parser.parse_args()
123
124 file_old = ROOT.TFile.Open(args.histo_old.split(":")[0])
125 file_new = ROOT.TFile.Open(args.histo_new.split(":")[0])
126
127 histo_old = file_old.Get(args.histo_old.split(":")[1])
128 histo_new = file_new.Get(args.histo_new.split(":")[1])
129
130 if not histo_old:
131 raise IOError("cannot find histogram %s" % args.histo_old)
132 if not histo_new:
133 raise IOError("cannot find histogram %s" % args.histo_new)
134
135 logging.info("going to merge %s with %s",
136 histo_old.GetName(), histo_new.GetName())
137 histo_merged = merge_histograms(histo_old, histo_new)
138
139 canvas = ROOT.TCanvas()
140 histo_merged.SetFillColor(ROOT.kBlue)
141 histo_old.SetMarkerColor(ROOT.kRed)
142 histo_new.SetMarkerColor(ROOT.kGreen)
143 for histo in histo_old, histo_new:
144 histo.SetMarkerStyle(20)
145 histo.SetMarkerSize(1)
146 histo_merged.Draw("histo")
147 histo_old.Draw("Psame")
148 histo_new.Draw("Psame")
149
150 legend = ROOT.TLegend(0.6, 0.7, 0.9, 0.9)
151 legend.AddEntry(histo_old, "old")
152 legend.AddEntry(histo_new, "new")
153 legend.SetBorderSize(0)
154 legend.Draw()
155
156 fout = ROOT.TFile.Open(args.output_filename,
157 "recreate" if args.recreate else "update")
158 if args.title is not None:
159 histo_merged.SetTitle(args.title)
160 name = args.name or histo_old.GetName()
161 histo_merged.SetName(name)
162 histo_merged.Write()
163
164 input("press a key")
void print(char *figname, TCanvas *c1)
STL class.
merge_histograms(old, new, merge_error=True)