6 from array 
import array
 
   10 This is an utility to merge histograms. The common case is when you have 
   11 old scale factors for the whole calorimeter and new scale factor only for 
   15 ROOT.PyConfig.IgnoreCommandLineOptions = 
True 
   16 logging.basicConfig(level=logging.INFO)
 
   20     print(
"old binning: " + 
", ".
join((
"%.3f" % old.GetBinLowEdge(ibin))
 
   21                                       for ibin 
in range(1, old.GetNbinsX()
 
   23     print(
"new binning: " + 
", ".
join((
"%.3f" % new.GetBinLowEdge(ibin))
 
   24                                       for ibin 
in range(1, new.GetNbinsX()
 
   31     OVERFLOW = new.GetNbinsX() + 1
 
   33     for iold 
in range(1, old.GetNbinsX()):
 
   34         low = old.GetBinLowEdge(iold)
 
   35         r = low + old.GetBinWidth(iold)
 
   37         il_new = new.FindFixBin(low)
 
   38         ir_new = new.FindFixBin(r)
 
   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))
 
   47         elif il_new == UNDERFLOW 
and ir_new > UNDERFLOW:
 
   48             if abs(new.GetBinLowEdge(1) - low) < 1E-100:
 
   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:
 
   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))
 
   67     for iold 
in range(last_old, old.GetNbinsX() + 1):
 
   68         low = old.GetBinLowEdge(iold)
 
   69         r = low + old.GetBinWidth(iold)
 
   71         il_new = new.FindFixBin(low)
 
   72         ir_new = new.FindFixBin(r)
 
   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:
 
   82             new_binning.append((new.GetBinLowEdge(new.GetNbinsX() + 1), r))
 
   83             new_values.append(old.GetBinContent(iold))
 
   84             new_errors.append(old.GetBinError(iold))
 
   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)
 
   94             result.SetBinError(i, e)
 
   96     print(
"merged binning: " + 
", ".
join((
"%.3f" % result.GetBinLowEdge(ibin))
 
   97                                          for ibin 
in range(1, result.GetNbinsX()
 
  103 if __name__ == 
"__main__":
 
  105         ROOT.gROOT.ProcessLine(
".x ~/atlasstyle/AtlasStyle.C")
 
  107     except AttributeError:
 
  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')
 
  119         '--recreate', help=
'create a new file', action=
'store_true')
 
  120     parser.add_argument(
'--output-filename', default=
'output.root')
 
  122     args = parser.parse_args()
 
  124     file_old = ROOT.TFile.Open(args.histo_old.split(
":")[0])
 
  125     file_new = ROOT.TFile.Open(args.histo_new.split(
":")[0])
 
  127     histo_old = file_old.Get(args.histo_old.split(
":")[1])
 
  128     histo_new = file_new.Get(args.histo_new.split(
":")[1])
 
  131         raise IOError(
"cannot find histogram %s" % args.histo_old)
 
  133         raise IOError(
"cannot find histogram %s" % args.histo_new)
 
  135     logging.info(
"going to merge %s with %s",
 
  136                  histo_old.GetName(), histo_new.GetName())
 
  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")
 
  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)
 
  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)