for h in hists: ratio_hists.append(plot.MakeRatioHist(h, hists[0], False, False)) for tgt in targets: ratio_hists[tgt[0]].Draw('HISTSAME') plot.SetupTwoPadSplitAsRatio( pads, plot.GetAxisHist( pads[0]), plot.GetAxisHist(pads[1]), 'Ratio to SM', True, 0.0, 5.0) # Go back and tidy up the axes and frame pads[0].cd() pads[0].GetFrame().Draw() pads[0].RedrawAxis() # CMS logo plot.DrawCMSLogo(pads[0], 'Les Houches', '2019', 11, 0.045, 0.05, 1.0, '', 1.0) plot.DrawTitle(pads[0], 'pp #rightarrow H / Hj', 1) plot.DrawTitle(pads[0], 'SMEFT', 3) canv.Print('.png') canv.Print('.pdf') for ib in xrange(1, h_nominal.GetNbinsX() + 1): line = 'xsec / SM for bin %i [%g, %g] = 1.0' % (ib, h_nominal.GetXaxis().GetBinLowEdge(ib), h_nominal.GetXaxis().GetBinUpEdge(ib)) for tgt in targets: x_tot = hists[tgt[0]].GetBinContent(ib) x_sm = h_nominal.GetBinContent(ib) ci = tgt[2] x_int = (x_tot - x_sm) / ci x_int = x_int / x_sm
pads[1].SetGrid(0, 1) h_axes[1].Draw() r_data = plot.MakeRatioHist(h_data, h_tot, True, False) r_tot = plot.MakeRatioHist(h_tot, h_tot, True, False) r_tot.Draw('E2SAME') r_data.Draw('SAME') plot.SetupTwoPadSplitAsRatio(pads, plot.GetAxisHist(pads[0]), plot.GetAxisHist(pads[1]), 'Obs/Exp', True, 0.61, 1.39) # Go back and tidy up the axes and frame pads[0].cd() pads[0].GetFrame().Draw() pads[0].RedrawAxis() # CMS logo plot.DrawCMSLogo(pads[0], 'CMS', 'Preliminary', 11, 0.045, 0.05, 1.0, '', 1.0) plot.DrawTitle(pads[0], '%.1f pb^{-1} (13 TeV)' % intLumiData, 3) # latex = ROOT.TLatex() # plot.Set(latex, NDC=None, TextFont=42, TextSize=0.08) # latex.DrawLatex(0.67, 0.57, CHANNELS[args.channel]) plot.DrawTitle(pads[0], CHANNELS[args.channel], 1) # ... and we're done canv.Print('.png') canv.Print('.pdf') canv.Print('.root')
else: lo = math.sqrt(v_lo[i] * v_lo[i] - v_lo[i + 1] * v_lo[i + 1]) else: hi = v_hi[i] lo = v_lo[i] textfit += '{}^{#plus %.3f}_{#minus %.3f}(%s)' % (hi, abs(lo), br) pt.AddText(textfit) pt.SetTextAlign(11) pt.SetTextFont(42) pt.Draw() plot.DrawCMSLogo(pads[0], args.logo, args.logo_sub, 11, 0.045, 0.035, 1.2, cmsTextSize=1.) legend_l = 0.69 if len(other_scans) > 0: legend_l = legend_l - len(other_scans) * 0.04 legend = ROOT.TLegend(0.15, legend_l, 0.45, 0.78, '', 'NBNDC') if len(other_scans) >= 3: legend = ROOT.TLegend(0.46, 0.83, 0.95, 0.93, '', 'NBNDC') legend.SetNColumns(2) legend.AddEntry(main_scan['func'], args.main_label, 'L') for i, other in enumerate(other_scans): legend.AddEntry(other['func'], other_scans_opts[i][1], 'L')
ratio_graphs = [] pads[0].cd() if legend.GetNRows() == 1: legend.SetY1(legend.GetY2() - 0.5 * (legend.GetY2() - legend.GetY1())) legend.Draw() box = ROOT.TPave(pads[0].GetLeftMargin(), 0.81, 1 - pads[0].GetRightMargin(), 1 - pads[0].GetTopMargin(), 1, 'NDC') box.Draw() legend.Draw() plot.DrawCMSLogo(pads[0], 'CMS', args.cms_sub, 11, 0.045, 0.035, 1.2, '', 0.8) plot.DrawTitle(pads[0], args.title_right, 3) plot.DrawTitle(pads[0], title, 1) textlabel = ROOT.TPaveText(0.68, 0.88, 0.80, 0.92, "NDC") textlabel.SetBorderSize(0) textlabel.SetFillStyle(0) textlabel.SetTextAlign(32) textlabel.SetTextSize(0.04) textlabel.SetTextColor(1) textlabel.SetTextFont(62) textlabel.AddText(args.statistic + ", %s Toys" % (toy_graph.GetN())) textlabel.Draw() pvalue = ROOT.TPaveText(0.68, 0.83, 0.80, 0.87, "NDC") pvalue.SetBorderSize(0)
def main(): parser = argparse.ArgumentParser() parser.add_argument('main', help='Main input file for the scan') parser.add_argument('--y-cut', type=float, default=7., help='Remove points with y > y-cut') parser.add_argument('--y-max', type=float, default=8., help='y-axis maximum') parser.add_argument('--output', '-o', help='output name without file extension', default='scan') parser.add_argument('--POI', help='use this parameter of interest', default='r') parser.add_argument('--translate', default=None, help='json file with POI name translation') parser.add_argument('--main-label', default='Observed', type=str, help='legend label for the main scan') parser.add_argument('--main-color', default=1, type=int, help='line and marker color for main scan') parser.add_argument( '--others', nargs='*', help='add secondary scans processed as main: FILE:LABEL:COLOR') parser.add_argument('--breakdown', help='do quadratic error subtraction using --others') parser.add_argument('--logo', default='CMS') parser.add_argument('--logo-sub', default='Internal') args = parser.parse_args() # print '--------------------------------------' # print args.output # print '--------------------------------------' fixed_name = args.POI xaxis_name = fixed_name label_name = fixed_name unit = "" if args.translate is not None: with open(args.translate) as jsonfile: name_translate = json.load(jsonfile) if args.POI in name_translate: fixed_name = name_translate[args.POI] # yvals = [1., 3.84] yvals = [1., 4.0] scalePOI = 9.2 xaxis_name = "#sigma [fb]" label_name = "#sigma" unit = "fb" main_scan = BuildScan(args.output, "{0}*{1}".format(scalePOI, args.POI), [args.main], args.main_color, yvals, args.y_cut) other_scans = [] other_scans_opts = [] if args.others is not None: for oargs in args.others: splitargs = oargs.split(':') other_scans_opts.append(splitargs) other_scans.append( BuildScan(args.output, args.POI, [splitargs[0]], int(splitargs[2]), yvals, args.y_cut)) canv = ROOT.TCanvas(args.output, args.output) pads = plot.OnePad() main_scan['graph'].SetMarkerColor(1) main_scan['graph'].Draw('AP') axishist = plot.GetAxisHist(pads[0]) axishist.SetMaximum(args.y_max) axishist.GetYaxis().SetTitle("- 2 #Delta ln L") axishist.GetXaxis().SetTitle("%s" % xaxis_name) new_min = axishist.GetXaxis().GetXmin() new_max = axishist.GetXaxis().GetXmax() mins = [] maxs = [] for other in other_scans: mins.append(other['graph'].GetX()[0]) maxs.append(other['graph'].GetX()[other['graph'].GetN() - 1]) if len(other_scans) > 0: if min(mins) < main_scan['graph'].GetX()[0]: new_min = min(mins) - (main_scan['graph'].GetX()[0] - new_min) if max(maxs) > main_scan['graph'].GetX()[main_scan['graph'].GetN() - 1]: new_max = max(maxs) + ( new_max - main_scan['graph'].GetX()[main_scan['graph'].GetN() - 1]) axishist.GetXaxis().SetLimits(new_min, new_max) for other in other_scans: if args.breakdown is not None: other['graph'].SetMarkerSize(0.4) other['graph'].Draw('PSAME') line = ROOT.TLine() line.SetLineColor(16) # line.SetLineStyle(7) for yval in yvals: plot.DrawHorizontalLine(pads[0], line, yval) if (len(other_scans) == 0): for cr in main_scan['crossings'][yval]: if cr['valid_lo']: line.DrawLine(cr['lo'], 0, cr['lo'], yval) if cr['valid_hi']: line.DrawLine(cr['hi'], 0, cr['hi'], yval) main_scan['func'].Draw('same') for other in other_scans: if args.breakdown is not None: other['func'].SetLineStyle(2) other['func'].SetLineWidth(2) other['func'].Draw('SAME') box = ROOT.TBox(axishist.GetXaxis().GetXmin(), 0.625 * args.y_max, axishist.GetXaxis().GetXmax(), args.y_max) box.Draw() pads[0].GetFrame().Draw() pads[0].RedrawAxis() crossings = main_scan['crossings'] val_nom = main_scan['val'] val_2sig = main_scan['val_2sig'] textfit = '%s = %.1f{}^{#plus %.1f}_{#minus %.1f} %s' % ( label_name, val_nom[0], val_nom[1], abs(val_nom[2]), unit) pt = ROOT.TPaveText(0.59, 0.82 - len(other_scans) * 0.08, 0.95, 0.91, 'NDCNB') pt.AddText(textfit) if args.breakdown is None: for i, other in enumerate(other_scans): textfit = '#color[%s]{%s = %.3f{}^{#plus %.3f}_{#minus %.3f}}' % ( other_scans_opts[i][2], fixed_name, other['val'][0], other['val'][1], abs(other['val'][2])) pt.AddText(textfit) if args.breakdown is not None: pt.SetX1(0.50) if len(other_scans) >= 3: pt.SetX1(0.19) pt.SetX2(0.88) pt.SetY1(0.66) pt.SetY2(0.82) breakdown = args.breakdown.split(',') v_hi = [val_nom[1]] v_lo = [val_nom[2]] for other in other_scans: v_hi.append(other['val'][1]) v_lo.append(other['val'][2]) assert (len(v_hi) == len(breakdown)) textfit = '%s = %.2f' % (label_name, val_nom[0]) for i, br in enumerate(breakdown): if i < (len(breakdown) - 1): if (abs(v_hi[i + 1]) > abs(v_hi[i])): print 'ERROR SUBTRACTION IS NEGATIVE FOR %s HI' % br hi = 0. else: hi = math.sqrt(v_hi[i] * v_hi[i] - v_hi[i + 1] * v_hi[i + 1]) if (abs(v_lo[i + 1]) > abs(v_lo[i])): print 'ERROR SUBTRACTION IS NEGATIVE FOR %s LO' % br lo = 0. else: lo = math.sqrt(v_lo[i] * v_lo[i] - v_lo[i + 1] * v_lo[i + 1]) else: hi = v_hi[i] lo = v_lo[i] textfit += '{}^{#plus %.2f}_{#minus %.2f}(%s)' % (hi, abs(lo), br) pt.AddText(textfit) pt.SetTextAlign(11) pt.SetTextFont(42) pt.Draw() plot.DrawCMSLogo(pads[0], args.logo, args.logo_sub, 11, 0.045, 0.035, 1.2, cmsTextSize=1.) legend_l = 0.69 if len(other_scans) > 0: legend_l = legend_l - len(other_scans) * 0.04 legend = ROOT.TLegend(0.15, legend_l, 0.45, 0.78, '', 'NBNDC') if len(other_scans) >= 3: legend = ROOT.TLegend(0.46, 0.83, 0.95, 0.93, '', 'NBNDC') legend.SetNColumns(2) legend.AddEntry(main_scan['func'], args.main_label, 'L') for i, other in enumerate(other_scans): legend.AddEntry(other['func'], other_scans_opts[i][1], 'L') legend.Draw() save_graph = main_scan['graph'].Clone() save_graph.GetXaxis().SetTitle( '%s = %.2f %+.2f/%+.2f' % (label_name, val_nom[0], val_nom[2], val_nom[1])) outfile = ROOT.TFile(args.output + '.root', 'RECREATE') outfile.WriteTObject(save_graph) outfile.Close() canv.Print('.pdf') canv.Print('.png') canv.Print('.C')