def main(args): if args.gof_variable != None: channel_categories = { "et": ["100"], "mt": ["100"], "tt": ["100"], "em": ["100"] } else: channel_categories = { #"et": ["ztt", "zll", "w", "tt", "ss", "misc"], "et": ["12", "15", "11", "13", "14", "16"], #"mt": ["ztt", "zll", "w", "tt", "ss", "misc"], "mt": ["12", "15", "11", "13", "14", "16"], #"tt": ["ztt", "noniso", "misc"] "tt": ["12", "17", "16"], "em": ["12", "13", "14", "16", "18", "19"] } if args.categories == "stxs_stage0": for channel in ["et", "mt", "tt", "em"]: channel_categories[channel] += [ "1_A", "1_B", "1_C", "2_A", "2_B" ] elif args.categories == "stxs_stage1": for channel in ["et", "mt", "tt", "em"]: channel_categories[channel] += [ "1_A", "1_B", "1_C", "2_A", "2_B" ] else: logger.critical("Selected unkown STXS categorization {}", args.categories) raise Exception channel_dict = { "ee": "ee", "em": "e#mu", "et": "e#tau_{h}", "mm": "#mu#mu", "mt": "#mu#tau_{h}", "tt": "#tau_{h}#tau_{h}" } if args.gof_variable != None: category_dict = {"100": "inclusive"} else: category_dict = { "1": "ggH", "2": "qqH", "3": "ggH, unrolled", "4": "qqH, unrolled", "12": "ztt", "15": "zll", "11": "wjets", "13": "tt", "14": "qcd", "16": "misc", "17": "qcd", "18": "single top", "19": "diboson" } if args.linear == True: split_value = 0 else: if args.normalize_by_bin_width: split_value = 10001 else: split_value = 101 split_dict = {c: split_value for c in ["et", "mt", "tt", "em"]} bkg_processes = ["VVL", "TTL", "ZL", "jetFakes", "EMB"] if not args.fake_factor and args.embedding: bkg_processes = ["QCD", "VVJ", "W", "TTJ", "ZJ", "ZL", "EMB"] if not args.embedding and args.fake_factor: bkg_processes = [ "VVT", "VVJ", "TTT", "TTJ", "ZJ", "ZL", "jetFakes", "ZTT" ] if not args.embedding and not args.fake_factor: bkg_processes = [ "QCD", "VVT", "VVL", "VVJ", "W", "TTT", "TTL", "TTJ", "ZJ", "ZL", "ZTT" ] all_bkg_processes = [b for b in bkg_processes] legend_bkg_processes = copy.deepcopy(bkg_processes) legend_bkg_processes.reverse() if "2016" in args.era: era = "Run2016" elif "2017" in args.era: era = "Run2017" else: logger.critical("Era {} is not implemented.".format(args.era)) raise Exception plots = [] for channel in args.channels: for category in channel_categories[channel]: rootfile = rootfile_parser.Rootfile_parser(args.input) tranche = None if "_" in category: tranche = category.split("_")[1] category = category.split("_")[0] if channel == "tt" and category == "2": bkg_processes = [b for b in all_bkg_processes] elif channel == "em" and args.embedding: bkg_processes = ["ST", "VV", "W", "TT", "ZL", "QCD", "EMB"] elif channel == "em" and not args.embedding: bkg_processes = ["ST", "VV", "W", "TT", "ZL", "QCD", "ZTT"] else: bkg_processes = [b for b in all_bkg_processes] legend_bkg_processes = copy.deepcopy(bkg_processes) legend_bkg_processes.reverse() # create plot width = 600 if args.categories == "stxs_stage1": if category == "2" or (category == "1" and tranche != "A"): width = 1200 if args.linear == True: plot = dd.Plot([0.3, [0.3, 0.28]], "ModTDR", r=0.04, l=0.14, width=width) else: plot = dd.Plot([0.5, [0.3, 0.28]], "ModTDR", r=0.04, l=0.14, width=width) # get background histograms for process in bkg_processes: plot.add_hist(rootfile.get(era, channel, category, process), process, "bkg") plot.setGraphStyle(process, "hist", fillcolor=styles.color_dict[process]) # get signal histograms plot_idx_to_add_signal = [0, 2] if args.linear else [1, 2] for i in plot_idx_to_add_signal: plot.subplot(i).add_hist( rootfile.get(era, channel, category, "ggH"), "ggH") plot.subplot(i).add_hist( rootfile.get(era, channel, category, "ggH"), "ggH_top") plot.subplot(i).add_hist( rootfile.get(era, channel, category, "qqH"), "qqH") plot.subplot(i).add_hist( rootfile.get(era, channel, category, "qqH"), "qqH_top") VHhist = rootfile.get(era, channel, category, "ZH125").Clone("VH") VHhist.Add(rootfile.get(era, channel, category, "WH125")) plot.subplot(i).add_hist(VHhist, "VH") plot.subplot(i).add_hist(VHhist, "VH_top") # get observed data and total background histograms # NOTE: With CMSSW_8_1_0 the TotalBkg definition has changed. plot.add_hist(rootfile.get(era, channel, category, "data_obs"), "data_obs") total_bkg = rootfile.get(era, channel, category, "TotalBkg") ggHHist = rootfile.get(era, channel, category, "ggH") qqHHist = rootfile.get(era, channel, category, "qqH") total_bkg.Add(ggHHist, -1) total_bkg.Add(qqHHist, -1) plot.add_hist(total_bkg, "total_bkg") plot.subplot(0).setGraphStyle("data_obs", "e0") plot.subplot(0 if args.linear else 1).setGraphStyle( "ggH", "hist", linecolor=styles.color_dict["ggH"], linewidth=3) plot.subplot(0 if args.linear else 1).setGraphStyle("ggH_top", "hist", linecolor=0) plot.subplot(0 if args.linear else 1).setGraphStyle( "qqH", "hist", linecolor=styles.color_dict["qqH"], linewidth=3) plot.subplot(0 if args.linear else 1).setGraphStyle("qqH_top", "hist", linecolor=0) plot.subplot(0 if args.linear else 1).setGraphStyle( "VH", "hist", linecolor=styles.color_dict["VH"], linewidth=3) plot.subplot(0 if args.linear else 1).setGraphStyle("VH_top", "hist", linecolor=0) plot.setGraphStyle("total_bkg", "e2", markersize=0, fillcolor=styles.color_dict["unc"], linecolor=0) # assemble ratio bkg_ggH = plot.subplot(2).get_hist("ggH") bkg_qqH = plot.subplot(2).get_hist("qqH") bkg_VH = plot.subplot(2).get_hist("VH") bkg_ggH.Add(plot.subplot(2).get_hist("total_bkg")) bkg_qqH.Add(plot.subplot(2).get_hist("total_bkg")) bkg_VH.Add(plot.subplot(2).get_hist("total_bkg")) plot.subplot(2).add_hist(bkg_ggH, "bkg_ggH") plot.subplot(2).add_hist(bkg_ggH, "bkg_ggH_top") plot.subplot(2).add_hist(bkg_qqH, "bkg_qqH") plot.subplot(2).add_hist(bkg_qqH, "bkg_qqH_top") plot.subplot(2).add_hist(bkg_VH, "bkg_VH") plot.subplot(2).add_hist(bkg_VH, "bkg_VH_top") plot.subplot(2).setGraphStyle("bkg_ggH", "hist", linecolor=styles.color_dict["ggH"], linewidth=3) plot.subplot(2).setGraphStyle("bkg_ggH_top", "hist", linecolor=0) plot.subplot(2).setGraphStyle("bkg_qqH", "hist", linecolor=styles.color_dict["qqH"], linewidth=3) plot.subplot(2).setGraphStyle("bkg_qqH_top", "hist", linecolor=0) plot.subplot(2).setGraphStyle("bkg_VH", "hist", linecolor=styles.color_dict["VH"], linewidth=3) plot.subplot(2).setGraphStyle("bkg_VH_top", "hist", linecolor=0) plot.subplot(2).normalize([ "total_bkg", "bkg_ggH", "bkg_ggH_top", "bkg_qqH", "bkg_qqH_top", "bkg_VH", "bkg_VH_top", "data_obs" ], "total_bkg") # stack background processes plot.create_stack(bkg_processes, "stack") # normalize stacks by bin-width if args.normalize_by_bin_width: plot.subplot(0).normalizeByBinWidth() plot.subplot(1).normalizeByBinWidth() # set axes limits and labels plot.subplot(0).setYlims( split_dict[channel], max(2 * plot.subplot(0).get_hist("total_bkg").GetMaximum(), split_dict[channel] * 2)) plot.subplot(2).setYlims(0.75, 1.45) if category in ["2"]: plot.subplot(2).setYlims(0.55, 2.05) if category in ["1", "2"]: plot.subplot(0).setLogY() plot.subplot(0).setYlims( 0.1, 15000000 if channel in ["et", "mt"] and category == "1" and tranche == "A" else 150000) if channel == "em": plot.subplot(0).setYlims(1, 15000000) if args.linear != True: plot.subplot(1).setYlims(0.1, split_dict[channel]) plot.subplot(1).setLogY() plot.subplot(1).setYlabel( "") # otherwise number labels are not drawn on axis if args.gof_variable != None: if args.gof_variable in styles.x_label_dict[args.channels[0]]: x_label = styles.x_label_dict[args.channels[0]][ args.gof_variable] else: x_label = args.gof_variable plot.subplot(2).setXlabel(x_label) else: plot.subplot(2).setXlabel("NN output") if args.normalize_by_bin_width: plot.subplot(0).setYlabel("dN/d(NN output)") else: plot.subplot(0).setYlabel("N_{events}") plot.subplot(2).setYlabel("") #plot.scaleXTitleSize(0.8) #plot.scaleXLabelSize(0.8) #plot.scaleYTitleSize(0.8) plot.scaleYLabelSize(0.8) #plot.scaleXLabelOffset(2.0) plot.scaleYTitleOffset(1.1) #plot.subplot(2).setNYdivisions(3, 5) if args.categories == "stxs_stage1": if not channel == "tt": plot.subplot(2).changeXLabels( [" ", "0.25", " ", "0.50", " ", "0.75", " ", " "]) if category in ["1"]: selection = None if tranche == "A": selection = [0] elif tranche == "B": selection = [1, 2, 3, 4] elif tranche == "C": selection = [5, 6, 7, 8] if not channel == "tt": plot.setNXdivisions(7, 0, 4, False) #else: # plot.setNXdivisions(4, 0, 0, False) #plot.scaleXLabelSize(0.5) plot.unroll([ "0J", "1J_PTH_0_60", "1J_PTH_60_120", "1J_PTH_120_200", "1J_PTH_GT200", "GE2J_PTH_0_60", "GE2J_PTH_60_120", "GE2J_PTH_120_200", "GE2J_PTH_GT200" ], ur_label_size=0.5, pads_to_print_labels=[], selection=selection) if category in ["2"]: selection = None if tranche == "A": selection = [0, 1] elif tranche == "B": selection = [2, 3, 4] if not channel == "tt": plot.setNXdivisions(7, 0, 4, False) plot.unroll([ "VBFTOPO_JET3VETO", "VBFTOPO_JET3", "VH2JET", "REST", "PTJET1_GT200" ], ur_label_size=0.9, pads_to_print_labels=[], selection=selection) if not channel == "tt" and category in [ "11", "12", "13", "14", "15", "16" ]: plot.subplot(2).changeXLabels( ["0.2", "0.4", "0.6", "0.8", "1.0"]) # draw subplots. Argument contains names of objects to be drawn in corresponding order. procs_to_draw = [ "stack", "total_bkg", "ggH", "ggH_top", "qqH", "qqH_top", "VH", "VH_top", "data_obs" ] if args.linear else ["stack", "total_bkg", "data_obs"] plot.subplot(0).Draw(procs_to_draw) if args.linear != True: plot.subplot(1).Draw([ "stack", "total_bkg", "ggH", "ggH_top", "qqH", "qqH_top", "VH", "VH_top", "data_obs" ]) plot.subplot(2).Draw([ "total_bkg", "bkg_ggH", "bkg_ggH_top", "bkg_qqH", "bkg_qqH_top", "data_obs" ]) # create legends suffix = ["", "_top"] for i in range(2): plot.add_legend( width=0.3 if args.categories == "stxs_stage1" and (category == "2" or (category == "1" and tranche != "A")) else 0.6, height=0.15) for process in legend_bkg_processes: plot.legend(i).add_entry( 0, process, styles.legend_label_dict[process.replace( "TTL", "TT").replace("VVL", "VV")], 'f') plot.legend(i).add_entry(0, "total_bkg", "Bkg. unc.", 'f') plot.legend(i).add_entry(0 if args.linear else 1, "ggH%s" % suffix[i], "gg#rightarrowH", 'l') plot.legend(i).add_entry(0 if args.linear else 1, "qqH%s" % suffix[i], "qq#rightarrowH", 'l') plot.legend(i).add_entry(0 if args.linear else 1, "VH%s" % suffix[i], "qq#rightarrowVH", 'l') plot.legend(i).add_entry(0, "data_obs", "Data", 'PE') plot.legend(i).setNColumns(3) plot.legend(0).Draw() plot.legend(1).setAlpha(0.0) plot.legend(1).Draw() if args.chi2test: import ROOT as r f = r.TFile(args.input, "read") background = f.Get("htt_{}_{}_Run{}_{}/TotalBkg".format( channel, category, args.era, "prefit" if "prefit" in args.input else "postfit")) data = f.Get("htt_{}_{}_Run{}_{}/data_obs".format( channel, category, args.era, "prefit" if "prefit" in args.input else "postfit")) chi2 = data.Chi2Test(background, "UW CHI2/NDF") plot.DrawText(0.7, 0.3, "\chi^{2}/ndf = " + str(round(chi2, 3))) for i in range(2): plot.add_legend(reference_subplot=2, pos=1, width=0.5, height=0.03) plot.legend(i + 2).add_entry(0, "data_obs", "Data", 'PE') plot.legend(i + 2).add_entry(0 if args.linear else 1, "ggH%s" % suffix[i], "ggH+bkg.", 'l') plot.legend(i + 2).add_entry(0 if args.linear else 1, "qqH%s" % suffix[i], "qqH+bkg.", 'l') plot.legend(i + 2).add_entry(0, "total_bkg", "Bkg. unc.", 'f') plot.legend(i + 2).setNColumns(4) plot.legend(2).Draw() plot.legend(3).setAlpha(0.0) plot.legend(3).Draw() # draw additional labels plot.DrawCMS() if "2016" in args.era: plot.DrawLumi("35.9 fb^{-1} (2016, 13 TeV)") elif "2017" in args.era: plot.DrawLumi("41.5 fb^{-1} (2017, 13 TeV)") else: logger.critical("Era {} is not implemented.".format(args.era)) raise Exception posChannelCategoryLabelLeft = None if args.categories == "stxs_stage1": if category in ["1", "2"]: posChannelCategoryLabelLeft = 0.075 plot.DrawChannelCategoryLabel( "%s, %s" % (channel_dict[channel], category_dict[category]), begin_left=posChannelCategoryLabelLeft) # save plot postfix = "prefit" if "prefit" in args.input else "postfit" if "postfit" in args.input else "undefined" plot.save("%s_plots/%s_%s_%s_%s.%s" % (args.era, args.era, channel, args.gof_variable if args.gof_variable is not None else category if tranche == None else "_".join([category, tranche]), postfix, "png" if args.png else "pdf")) plots.append( plot ) # work around to have clean up seg faults only at the end of the script
def main(args): channel_categories = { "mt": ["0"], } channel_dict = { "ee": "ee", "em": "e#mu", "et": "e#tau_{h}", "mm": "#mu#mu", "mt": "#mu#tau_{h}", "tt": "#tau_{h}#tau_{h}" } category_dict = {"0": "nll"} bkg_processes = [ "QCD", "VVT", "VVL", "VVJ", "W", "TTT", "TTL", "TTJ", "ZJ", "ZL", "ZTT"] all_bkg_processes = [b for b in bkg_processes] legend_bkg_processes = copy.deepcopy(bkg_processes) legend_bkg_processes.reverse() era = 2018 plots = [] channel = "mt" for category in channel_categories[channel]: linear = False if category == "0" else True normalize_by_bin_width = False if linear: split_value = 0 else: split_value = 101 rootfile = rootfile_parser.Rootfile_parser(os.path.join(args.workdir, "shapes_{}.root".format(args.fittype))) bkg_processes = [b for b in all_bkg_processes] legend_bkg_processes = copy.deepcopy(bkg_processes) legend_bkg_processes.reverse() # create plot width = 600 if linear: plot = dd.Plot( [0.3, [0.3, 0.28]], "ModTDR", r=0.04, l=0.14, width=width) else: plot = dd.Plot( [0.5, [0.3, 0.28]], "ModTDR", r=0.04, l=0.14, width=width) # get background histograms for process in bkg_processes: try: plot.add_hist( rootfile.get( era, channel, category, process), process, "bkg") plot.setGraphStyle( process, "hist", fillcolor=styles.color_dict[process]) except BaseException: pass # get signal histograms plot_idx_to_add_signal = [0, 2] if linear else [1, 2] for i in plot_idx_to_add_signal: plot.subplot(i).add_hist( rootfile.get(era, channel, category, "ggH"), "ggH") plot.subplot(i).add_hist( rootfile.get(era, channel, category, "ggH"), "ggH_top") plot.subplot(i).add_hist( rootfile.get(era, channel, category, "qqH"), "qqH") plot.subplot(i).add_hist( rootfile.get(era, channel, category, "qqH"), "qqH_top") # get observed data and total background histograms # NOTE: With CMSSW_8_1_0 the TotalBkg definition has changed. plot.add_hist( rootfile.get(era, channel, category, "data_obs"), "data_obs") total_bkg = rootfile.get(era, channel, category, "TotalBkg") #ggHHist = rootfile.get(era, channel, category, "ggH") #qqHHist = rootfile.get(era, channel, category, "qqH") #total_bkg.Add(ggHHist, -1) # if qqHHist: # total_bkg.Add(qqHHist, -1) plot.add_hist(total_bkg, "total_bkg") plot.subplot(0).setGraphStyle("data_obs", "e0") plot.subplot(0 if linear else 1).setGraphStyle( "ggH", "hist", linecolor=styles.color_dict["ggH"], linewidth=3) plot.subplot( 0 if linear else 1).setGraphStyle( "ggH_top", "hist", linecolor=0) plot.subplot(0 if linear else 1).setGraphStyle( "qqH", "hist", linecolor=styles.color_dict["qqH"], linewidth=3) plot.subplot( 0 if linear else 1).setGraphStyle( "qqH_top", "hist", linecolor=0) plot.subplot(0 if linear else 1).setGraphStyle( "VH", "hist", linecolor=styles.color_dict["VH"], linewidth=3) plot.subplot( 0 if linear else 1).setGraphStyle( "VH_top", "hist", linecolor=0) plot.subplot(0 if linear else 1).setGraphStyle( "ttH", "hist", linecolor=styles.color_dict["ttH"], linewidth=3) plot.subplot( 0 if linear else 1).setGraphStyle( "ttH_top", "hist", linecolor=0) plot.subplot(0 if linear else 1).setGraphStyle( "HWW", "hist", linecolor=styles.color_dict["HWW"], linewidth=3) plot.subplot( 0 if linear else 1).setGraphStyle( "HWW_top", "hist", linecolor=0) plot.setGraphStyle( "total_bkg", "e2", markersize=0, fillcolor=styles.color_dict["unc"], linecolor=0) # assemble ratio bkg_ggH = plot.subplot(2).get_hist("ggH") bkg_qqH = plot.subplot(2).get_hist("qqH") bkg_ggH.Add(plot.subplot(2).get_hist("total_bkg")) if bkg_qqH: bkg_qqH.Add(plot.subplot(2).get_hist("total_bkg")) plot.subplot(2).add_hist(bkg_ggH, "bkg_ggH") plot.subplot(2).add_hist(bkg_ggH, "bkg_ggH_top") plot.subplot(2).add_hist(bkg_qqH, "bkg_qqH") plot.subplot(2).add_hist(bkg_qqH, "bkg_qqH_top") plot.subplot(2).setGraphStyle( "bkg_ggH", "hist", linecolor=styles.color_dict["ggH"], linewidth=3) plot.subplot(2).setGraphStyle("bkg_ggH_top", "hist", linecolor=0) plot.subplot(2).setGraphStyle( "bkg_qqH", "hist", linecolor=styles.color_dict["qqH"], linewidth=3) plot.subplot(2).setGraphStyle("bkg_qqH_top", "hist", linecolor=0) plot.subplot(2).normalize([ "total_bkg", "bkg_ggH", "bkg_ggH_top", "bkg_qqH", "bkg_qqH_top", "data_obs" ], "total_bkg") # stack background processes plot.create_stack(bkg_processes, "stack") # normalize stacks by bin-width if normalize_by_bin_width: plot.subplot(0).normalizeByBinWidth() plot.subplot(1).normalizeByBinWidth() # set axes limits and labels plot.subplot(0).setYlims( split_value, max(2 * plot.subplot(0).get_hist("total_bkg").GetMaximum(), split_value * 2)) plot.subplot(2).setYlims(0.75, 1.35) if not linear: plot.subplot(1).setYlims(0.1, split_value) plot.subplot(1).setLogY() plot.subplot(1).setYlabel( "") # otherwise number labels are not drawn on axis plot.subplot(2).setXlabel(styles.x_label_dict[channel][cfg.analysis_variable]) if normalize_by_bin_width: plot.subplot(0).setYlabel("dN/d(NN output)") else: plot.subplot(0).setYlabel("N_{events}") plot.subplot(2).setYlabel("") # plot.scaleXTitleSize(0.8) # plot.scaleXLabelSize(0.8) # plot.scaleYTitleSize(0.8) plot.scaleYLabelSize(0.8) # plot.scaleXLabelOffset(2.0) plot.scaleYTitleOffset(1.1) #plot.subplot(2).setNYdivisions(3, 5) # if not channel == "tt" and category in ["11", "12", "13", "14", "15", "16"]: # plot.subplot(2).changeXLabels(["0.2", "0.4", "0.6", "0.8", "1.0"]) # draw subplots. Argument contains names of objects to be drawn in # corresponding order. procs_to_draw = [ "stack", "total_bkg", "ggH", "ggH_top", "qqH", "qqH_top", "data_obs"] if linear else [ "stack", "total_bkg", "data_obs"] plot.subplot(0).Draw(procs_to_draw) if not linear: plot.subplot(1).Draw( ["stack", "total_bkg", "ggH", "ggH_top", "qqH", "qqH_top", "data_obs"]) plot.subplot(2).Draw([ "total_bkg", "bkg_ggH", "bkg_ggH_top", "bkg_qqH", "bkg_qqH_top", "data_obs" ]) # create legends suffix = ["", "_top"] for i in range(2): plot.add_legend(width=0.6, height=0.15) for process in legend_bkg_processes: try: plot.legend(i).add_entry( 0, process, styles.legend_label_dict [process.replace("TTL", "TT").replace( "VVL", "VV")], 'f') except BaseException: pass plot.legend(i).add_entry(0, "total_bkg", "Bkg. unc.", 'f') plot.legend(i).add_entry( 0 if linear else 1, "ggH%s" % suffix[i], "gg#rightarrowH", 'l') plot.legend(i).add_entry( 0 if linear else 1, "qqH%s" % suffix[i], "qq#rightarrowH", 'l') plot.legend(i).add_entry(0, "data_obs", "Data", 'PE') plot.legend(i).setNColumns(3) plot.legend(0).Draw() plot.legend(1).setAlpha(0.0) plot.legend(1).Draw() for i in range(2): plot.add_legend( reference_subplot=2, pos=1, width=0.5, height=0.03) plot.legend(i + 2).add_entry(0, "data_obs", "Data", 'PE') plot.legend( i + 2).add_entry( 0 if linear else 1, "ggH%s" % suffix[i], "ggH+bkg.", 'l') plot.legend( i + 2).add_entry( 0 if linear else 1, "qqH%s" % suffix[i], "qqH+bkg.", 'l') plot.legend(i + 2).add_entry(0, "total_bkg", "Bkg. unc.", 'f') plot.legend(i + 2).setNColumns(4) plot.legend(2).Draw() plot.legend(3).setAlpha(0.0) plot.legend(3).Draw() # draw additional labels #plot.DrawCMS() plot.DrawLumi("59.7 fb^{-1} (2018, 13 TeV)") plot.DrawChannelCategoryLabel( "%s, %s" % (channel_dict[channel], category_dict[category]), begin_left=None) # save plot for filetype in ["png", "pdf"]: plot.save( "%s/%s_%s_%s_%s.%s" % (args.workdir, "2018", channel, category, args.fittype, filetype)) # work around to have clean up seg faults only at the end of the # script plots.append(plot)
def main(args): if args.gof_variable != None: channel_categories = {c: [args.gof_variable] for c in args.channels} else: channel_categories = { "et": ["ggh", "qqh", "ztt", "zll", "w", "tt", "ss", "misc"], "mt": ["ggh", "qqh", "ztt", "zll", "w", "tt", "ss", "misc"], "tt": ["ggh", "qqh", "ztt", "noniso", "misc"] } channel_dict = { "ee": "ee", "em": "e#mu", "et": "e#tau_{h}", "mm": "#mu#mu", "mt": "#mu#tau_{h}", "tt": "#tau_{h}#tau_{h}" } if args.gof_variable != None: category_dict = {args.gof_variable: "inclusive"} else: category_dict = { "ggh": "ggH", "qqh": "VBF", "ztt": "Z#rightarrow#tau#tau", "zll": "Z#rightarrowll", "w": "W+jets", "tt": "t#bar{t}", "ss": "same sign", "misc": "misc", "noniso": "noniso" } if args.linear == True: split_value = 0 else: if args.normalize_by_bin_width: split_value = 10001 else: split_value = 101 split_dict = {c: split_value for c in ["et", "mt", "tt"]} bkg_processes = ["EWK", "QCD", "VV", "W", "TTT", "TTJ", "ZJ", "ZL", "ZTT"] legend_bkg_processes = copy.deepcopy(bkg_processes) legend_bkg_processes.reverse() rootfile = rootfile_parser.Rootfile_parser(args.input) plots = [] for channel in args.channels: for category in channel_categories[channel]: # create plot if args.linear == True: plot = plot = dd.Plot([0.3, [0.3, 0.28]], "ModTDR", r=0.04, l=0.14) else: plot = dd.Plot([0.5, [0.3, 0.28]], "ModTDR", r=0.04, l=0.14) # get background histograms for process in bkg_processes: plot.add_hist(rootfile.get(channel, category, process), process, "bkg") plot.setGraphStyle(process, "hist", fillcolor=styles.color_dict[process]) # get signal histograms for i in range(2): plot.subplot(i + 1).add_hist( rootfile.get(channel, category, "ggH"), "ggH") plot.subplot(i + 1).add_hist( rootfile.get(channel, category, "ggH"), "ggH_top") plot.subplot(i + 1).add_hist( rootfile.get(channel, category, "qqH"), "qqH") plot.subplot(i + 1).add_hist( rootfile.get(channel, category, "qqH"), "qqH_top") # get observed data and total background histograms plot.add_hist(rootfile.get(channel, category, "data_obs"), "data_obs") plot.add_hist(rootfile.get(channel, category, "TotalBkg"), "total_bkg") plot.subplot(0).setGraphStyle("data_obs", "e0") plot.subplot(1).setGraphStyle("ggH", "hist", linecolor=styles.color_dict["ggH"], linewidth=3) plot.subplot(1).setGraphStyle("ggH_top", "hist", linecolor=0) plot.subplot(1).setGraphStyle("qqH", "hist", linecolor=styles.color_dict["qqH"], linewidth=3) plot.subplot(1).setGraphStyle("qqH_top", "hist", linecolor=0) plot.setGraphStyle("total_bkg", "e2", markersize=0, fillcolor=styles.color_dict["unc"], linecolor=0) # assemble ratio bkg_ggH = plot.subplot(2).get_hist("ggH") bkg_qqH = plot.subplot(2).get_hist("qqH") bkg_ggH.Add(plot.subplot(2).get_hist("total_bkg")) bkg_qqH.Add(plot.subplot(2).get_hist("total_bkg")) plot.subplot(2).add_hist(bkg_ggH, "bkg_ggH") plot.subplot(2).add_hist(bkg_ggH, "bkg_ggH_top") plot.subplot(2).add_hist(bkg_qqH, "bkg_qqH") plot.subplot(2).add_hist(bkg_qqH, "bkg_qqH_top") plot.subplot(2).setGraphStyle("bkg_ggH", "hist", linecolor=styles.color_dict["ggH"], linewidth=3) plot.subplot(2).setGraphStyle("bkg_ggH_top", "hist", linecolor=0) plot.subplot(2).setGraphStyle("bkg_qqH", "hist", linecolor=styles.color_dict["qqH"], linewidth=3) plot.subplot(2).setGraphStyle("bkg_qqH_top", "hist", linecolor=0) plot.subplot(2).normalize([ "total_bkg", "bkg_ggH", "bkg_ggH_top", "bkg_qqH", "bkg_qqH_top", "data_obs" ], "total_bkg") # stack background processes plot.create_stack(bkg_processes, "stack") # normalize stacks by bin-width if args.normalize_by_bin_width: plot.subplot(0).normalizeByBinWidth() plot.subplot(1).normalizeByBinWidth() # set axes limits and labels plot.subplot(0).setYlims( split_dict[channel], max(2 * plot.subplot(0).get_hist("total_bkg").GetMaximum(), split_dict[channel] * 2)) plot.subplot(2).setYlims(0.75, 1.45) if channel == "tt" and category == "qqh": plot.subplot(2).setYlims(0.75, 2.65) if args.linear != True: plot.subplot(1).setYlims(0.1, split_dict[channel]) plot.subplot(1).setLogY() plot.subplot(1).setYlabel( "") # otherwise number labels are not drawn on axis if args.gof_variable != None: plot.subplot(2).setXlabel( styles.x_label_dict[args.channels[0]][args.gof_variable]) else: plot.subplot(2).setXlabel("NN score") if args.normalize_by_bin_width: plot.subplot(0).setYlabel("N_{events}/bin width") else: plot.subplot(0).setYlabel("N_{events}") plot.subplot(2).setYlabel("Ratio to Bkg.") #plot.scaleXTitleSize(0.8) #plot.scaleXLabelSize(0.8) #plot.scaleYTitleSize(0.8) plot.scaleYLabelSize(0.8) #plot.scaleXLabelOffset(2.0) plot.scaleYTitleOffset(1.1) #plot.subplot(2).setNYdivisions(3, 5) # draw subplots. Argument contains names of objects to be drawn in corresponding order. plot.subplot(0).Draw(["stack", "total_bkg", "data_obs"]) if args.linear != True: plot.subplot(1).Draw([ "stack", "total_bkg", "ggH", "ggH_top", "qqH", "qqH_top", "data_obs" ]) plot.subplot(2).Draw([ "total_bkg", "bkg_ggH", "bkg_ggH_top", "bkg_qqH", "bkg_qqH_top", "data_obs" ]) # create legends suffix = ["", "_top"] for i in range(2): plot.add_legend(width=0.48, height=0.15) for process in legend_bkg_processes: plot.legend(i).add_entry( 0, process, styles.legend_label_dict[process.replace( "EWK", "EWKZ")], 'f') plot.legend(i).add_entry(0, "total_bkg", "Bkg. unc.", 'f') plot.legend(i).add_entry(1, "ggH%s" % suffix[i], "ggH", 'l') plot.legend(i).add_entry(1, "qqH%s" % suffix[i], "qqH", 'l') plot.legend(i).add_entry(0, "data_obs", "Data", 'PE') plot.legend(i).setNColumns(3) plot.legend(0).Draw() plot.legend(1).setAlpha(0.0) plot.legend(1).Draw() for i in range(2): plot.add_legend(reference_subplot=2, pos=1, width=0.5, height=0.03) plot.legend(i + 2).add_entry(0, "data_obs", "Data", 'PE') plot.legend(i + 2).add_entry(1, "ggH%s" % suffix[i], "ggH+bkg.", 'l') plot.legend(i + 2).add_entry(1, "qqH%s" % suffix[i], "qqH+bkg.", 'l') plot.legend(i + 2).add_entry(0, "total_bkg", "Bkg. unc.", 'f') plot.legend(i + 2).setNColumns(4) plot.legend(2).Draw() plot.legend(3).setAlpha(0.0) plot.legend(3).Draw() # draw additional labels plot.DrawCMS() plot.DrawLumi("35.9 fb^{-1} (13 TeV)") plot.DrawChannelCategoryLabel( "%s, %s" % (channel_dict[channel], category_dict[category])) # save plot postfix = "prefit" if "prefit" in args.input else "postfit" if "postfit" in args.input else "undefined" plot.save( "plots/%s_%s_%s.%s" % (channel, category, postfix, "png" if args.png else "pdf")) plots.append( plot ) # work around to have clean up seg faults only at the end of the script
def main(args): channel_dict = { "mm": "#mu#mu", } category_dict = { "mm_0jet": "0-jet", "mm_1jet": "1-jet", "mm_ge2jet": "#geq 2-jet", } processes = [ "QCD", "VVT", "VVL", "W", "TTT", "TTL", "ZTT", "ZL" ] legend_processes = copy.deepcopy(processes) legend_processes.reverse() if "2016" in args.era: era = "Run2016" elif "2017" in args.era: era = "Run2017" elif "2018" in args.era: era = "Run2018" else: logger.critical("Era {} is not implemented.".format(args.era)) raise Exception plots = [] for plottype in ["prefit", "postfit"]: for category in category_dict: filename = args.input_dir+ "/" + category + "/postfit_shapes.root" rootfile = rootfile_parser.Rootfile_parser(filename) rootfile._hist_hash = "{category}{plottype}/{process}" rootfile._type = plottype # create plot width = 600 plot = dd.Plot( [0.3, [0.3, 0.28]], "ModTDR", r=0.04, l=0.14, width=width) # get background histograms print "Getting shapes" for process in processes: plot.add_hist( rootfile.get(era, "mm", category, process), process, "procs") plot.setGraphStyle( process, "hist", fillcolor=styles.color_dict[process]) print "Finished getting shapes" # get observed data and total processes histograms plot.add_hist(rootfile.get(era, "mm", category, "data_obs"), "data_obs") plot.add_hist(rootfile.get(era, "mm", category, "TotalProcs"), "total_procs") plot.subplot(0).setGraphStyle("data_obs", "e0") plot.setGraphStyle( "total_procs", "e2", markersize=0, fillcolor=styles.color_dict["unc"], linecolor=0) # assemble ratio plot.subplot(2).normalize(["data_obs", "total_procs"], "total_procs") # stack background processes plot.create_stack(processes, "stack") # set axes limits and labels plot.subplot(0).setYlims(1.0, float(10**10)) plot.subplot(2).setYlims(0.45, 2.05) plot.subplot(0).setLogY() plot.subplot(2).setXlabel("MET #parallel Z") plot.subplot(0).setYlabel("N_{events}") plot.subplot(2).setYlabel("") #plot.scaleXTitleSize(0.8) #plot.scaleXLabelSize(0.8) #plot.scaleYTitleSize(0.8) plot.scaleYLabelSize(0.8) #plot.scaleXLabelOffset(2.0) plot.scaleYTitleOffset(1.1) # draw subplots. Argument contains names of objects to be drawn in corresponding order. procs_to_draw = ["stack", "total_procs", "data_obs"] plot.subplot(0).Draw(procs_to_draw) plot.subplot(2).Draw(["total_procs", "data_obs"]) # create legends for i in range(2): plot.add_legend(width=0.6, height=0.15) for process in legend_processes: plot.legend(i).add_entry( 0, process, styles.legend_label_dict[process.replace("TTL", "TT").replace("VVL", "VV")], 'f') plot.legend(i).add_entry(0, "data_obs", "Data", 'PE') plot.legend(i).add_entry(0, "total_procs", "Total unc.", 'f') plot.legend(i).setNColumns(3) plot.legend(0).Draw() plot.legend(1).setAlpha(0.0) plot.legend(1).Draw() for i in range(2): plot.add_legend(reference_subplot=2, pos=1, width=0.5, height=0.03) plot.legend(i + 2).add_entry(0, "data_obs", "Data", 'PE') plot.legend(i + 2).add_entry(0, "total_procs", "Total unc.", 'f') plot.legend(i + 2).setNColumns(4) plot.legend(2).Draw() plot.legend(3).setAlpha(0.0) plot.legend(3).Draw() # draw additional labels plot.DrawCMS() if "2016" in args.era: plot.DrawLumi("35.9 fb^{-1} (2016, 13 TeV)") elif "2017" in args.era: plot.DrawLumi("41.5 fb^{-1} (2017, 13 TeV)") elif "2018" in args.era: plot.DrawLumi("59.7 fb^{-1} (2018, 13 TeV)") else: logger.critical("Era {} is not implemented.".format(args.era)) raise Exception plot.DrawChannelCategoryLabel( "%s, %s" % (channel_dict["mm"], category_dict[category]), begin_left=None) # save plot plot.save("%s_plots_metrecoilfit/%s_%s_%s_%s.%s" % (args.era, args.variable, "mm", category, plottype, "png")) plot.save("%s_plots_metrecoilfit/%s_%s_%s_%s.%s" % (args.era, args.variable, "mm", category, plottype, "pdf")) plots.append(plot) # work around to have clean up seg faults only at the end of the script
def main(args): #### plot signals if args.background_only: stxs_stage1p1_cats = [] else: stxs_stage1p1_cats = [str(100 + i) for i in range(5) ] + [str(200 + i) for i in range(4)] print(args) if args.gof_variable != None: channel_categories = { "et": ["300"], "mt": ["300"], "tt": ["300"], "em": ["300"] } else: channel_categories = { #"et": ["ztt", "zll", "w", "tt", "ss", "misc"], "et": ["12", "15", "11", "13", "14", "16"], #"mt": ["ztt", "zll", "w", "tt", "ss", "misc"], "mt": ["12", "15", "11", "13", "14", "16"], #"tt": ["ztt", "noniso", "misc"] "tt": ["12", "17", "16"], #"em": ["ztt", "tt", "ss", "misc", "db"] "em": ["12", "13", "14", "16", "19"] } if args.train_emb: #swap ztt for embedding for chn in ["em", "mt", "et", "tt"]: channel_categories[chn].remove("12") channel_categories[chn].append("20") if args.train_ff: for chn in ["mt", "et", "tt"]: # no change for em if chn == "tt": channel_categories[chn].remove("17") else: channel_categories[chn].remove("11") channel_categories[chn].remove("14") channel_categories[chn].append("21") # add ff if args.categories == "stxs_stage0": for channel in ["et", "mt", "tt", "em"]: channel_categories[channel] += ["1", "2"] elif args.categories == "stxs_stage1p1": for channel in ["et", "mt", "tt", "em"]: channel_categories[channel] += stxs_stage1p1_cats elif args.categories == "backgrounds": pass else: logger.critical("Selected unkown STXS categorization {}", args.categories) raise Exception channel_dict = { "ee": "ee", "em": "e#mu", "et": "e#tau_{h}", "mm": "#mu#mu", "mt": "#mu#tau_{h}", "tt": "#tau_{h}#tau_{h}" } if args.gof_variable != None: category_dict = {"300": "inclusive"} else: category_dict = { "1": "ggh", "100": "ggh 0-jet", "101": "ggh 1-jet p_{T}^{H} [0,120]", "102": "ggh 1-jet p_{T}^{H} [120,200]", "103": "ggh #geq 2-jet", "104": "ggh p_{T}^{H}>200", "2": "qqh", "200": "qqh 2J low mjj", "201": "qqh p_{T}^{H}>200", "202": "qqh vbftopo mjj>700", "203": "qqh vbftopo mjj [350,700]", "12": "ztt", "15": "zll", "11": "wjets", "13": "tt", "14": "qcd", "16": "misc", "17": "qcd", "19": "diboson", "20": "Genuine #tau", "21": "Jet #rightarrow #tau_{h}" } if args.linear == True: split_value = 0 else: if args.normalize_by_bin_width: split_value = 10001 else: split_value = 101 split_dict = {c: split_value for c in ["et", "mt", "tt", "em"]} bkg_processes = ["VVL", "TTL", "ZL", "jetFakes", "EMB"] if not args.fake_factor and args.embedding: bkg_processes = ["QCD", "VVJ", "W", "TTJ", "ZJ", "ZL", "EMB"] if not args.embedding and args.fake_factor: bkg_processes = ["VVT", "VVL", "TTT", "TTL", "ZL", "jetFakes", "ZTT"] if not args.embedding and not args.fake_factor: bkg_processes = [ "QCD", "VVT", "VVL", "VVJ", "W", "TTT", "TTL", "TTJ", "ZJ", "ZL", "ZTT" ] all_bkg_processes = [b for b in bkg_processes] legend_bkg_processes = copy.deepcopy(bkg_processes) legend_bkg_processes.reverse() if "2016" in args.era: era = "2016" elif "2017" in args.era: era = "2017" elif "2018" in args.era: era = "2018" else: logger.critical("Era {} is not implemented.".format(args.era)) raise Exception print(channel_categories) plots = [] for channel in args.channels: for category in channel_categories[channel]: print "Plot for category: ", category rootfile = rootfile_parser.Rootfile_parser(args.input) if channel == "em" and args.embedding: bkg_processes = ["VVL", "W", "TTL", "ZL", "QCD", "EMB"] elif channel == "em" and not args.embedding: bkg_processes = ["VVL", "W", "TTL", "ZL", "QCD", "ZTT"] else: bkg_processes = [b for b in all_bkg_processes] legend_bkg_processes = copy.deepcopy(bkg_processes) legend_bkg_processes.reverse() # create plot width = 600 if args.linear == True: plot = dd.Plot([0.3, [0.3, 0.28]], "ModTDR", r=0.04, l=0.14, width=width) else: plot = dd.Plot([0.5, [0.3, 0.28]], "ModTDR", r=0.04, l=0.14, width=width) # get background histograms for process in bkg_processes: try: if channel == "tt" and process == "jetFakes": jetfakes = rootfile.get(era, channel, category, process).Clone() jetfakes.Add( rootfile.get(era, channel, category, "wFakes")) plot.add_hist(jetfakes, process, "bkg") else: plot.add_hist( rootfile.get(era, channel, category, process), process, "bkg") plot.setGraphStyle(process, "hist", fillcolor=styles.color_dict[process]) except: pass # get signal histograms plot_idx_to_add_signal = [0, 2] if args.linear else [1, 2] for i in plot_idx_to_add_signal: try: plot.subplot(i).add_hist( check_for_zero_bins( rootfile.get(era, channel, category, "ggH125")), "ggH") plot.subplot(i).add_hist( check_for_zero_bins( rootfile.get(era, channel, category, "ggH125")), "ggH_top") plot.subplot(i).add_hist( check_for_zero_bins( rootfile.get(era, channel, category, "qqH125")), "qqH") plot.subplot(i).add_hist( check_for_zero_bins( rootfile.get(era, channel, category, "qqH125")), "qqH_top") if not args.plot_restricted_signals: if isinstance( rootfile.get(era, channel, category, "ZH125"), ROOT.TH1): VHhist = rootfile.get(era, channel, category, "ZH125").Clone("VH") WHhist = rootfile.get(era, channel, category, "WH125") if isinstance(WHhist, ROOT.TH1) and VHhist: VHhist.Add(WHhist) elif WHhist: VHhist = WHhist plot.subplot(i).add_hist(VHhist, "VH") plot.subplot(i).add_hist(VHhist, "VH_top") if isinstance( rootfile.get(era, channel, category, "ttH125"), ROOT.TH1): plot.subplot(i).add_hist( rootfile.get(era, channel, category, "ttH125"), "ttH") plot.subplot(i).add_hist( rootfile.get(era, channel, category, "ttH125"), "ttH_top") HWWhist = rootfile.get(era, channel, category, "ggHWW125") if isinstance( rootfile.get(era, channel, category, "ggHWW125"), ROOT.TH1): HWWhist = rootfile.get( era, channel, category, "ggHWW125").Clone("ggHWW125") qqHWWhist = rootfile.get(era, channel, category, "qqHWW125") if isinstance(qqHWWhist, ROOT.TH1) and HWWhist: HWWhist.Add(qqHWWhist) elif qqHWWhist: HWWhist = qqHWWhist plot.subplot(i).add_hist(HWWhist, "HWW") plot.subplot(i).add_hist(HWWhist, "HWW_top") except: pass # get observed data and total background histograms # NOTE: With CMSSW_8_1_0 the TotalBkg definition has changed. print("plot.add_hist(rootfile.get(" + era + ", " + channel + ", " + category + ', "data_obs")') plot.add_hist(rootfile.get(era, channel, category, "data_obs"), "data_obs") total_bkg = check_for_zero_bins( rootfile.get(era, channel, category, "TotalBkg")) #ggHHist = rootfile.get(era, channel, category, "ggH") #qqHHist = rootfile.get(era, channel, category, "qqH") #total_bkg.Add(ggHHist, -1) #if qqHHist: # total_bkg.Add(qqHHist, -1) plot.add_hist(total_bkg, "total_bkg") plot.subplot(0).setGraphStyle("data_obs", "e0") plot.subplot(0 if args.linear else 1).setGraphStyle( "ggH", "hist", linecolor=styles.color_dict["ggH"], linewidth=3) plot.subplot(0 if args.linear else 1).setGraphStyle("ggH_top", "hist", linecolor=0) plot.subplot(0 if args.linear else 1).setGraphStyle( "qqH", "hist", linecolor=styles.color_dict["qqH"], linewidth=3) plot.subplot(0 if args.linear else 1).setGraphStyle("qqH_top", "hist", linecolor=0) if not args.plot_restricted_signals: plot.subplot(0 if args.linear else 1).setGraphStyle( "VH", "hist", linecolor=styles.color_dict["VH"], linewidth=3) plot.subplot(0 if args.linear else 1).setGraphStyle( "VH_top", "hist", linecolor=0) plot.subplot(0 if args.linear else 1).setGraphStyle( "ttH", "hist", linecolor=styles.color_dict["ttH"], linewidth=3) plot.subplot(0 if args.linear else 1).setGraphStyle( "ttH_top", "hist", linecolor=0) plot.subplot(0 if args.linear else 1).setGraphStyle( "HWW", "hist", linecolor=styles.color_dict["HWW"], linewidth=3) plot.subplot(0 if args.linear else 1).setGraphStyle( "HWW_top", "hist", linecolor=0) plot.setGraphStyle("total_bkg", "e2", markersize=0, fillcolor=styles.color_dict["unc"], linecolor=0) # assemble ratio bkg_ggH = plot.subplot(2).get_hist("ggH") bkg_qqH = plot.subplot(2).get_hist("qqH") bkg_ggH.Add(plot.subplot(2).get_hist("total_bkg")) if bkg_qqH: bkg_qqH.Add(plot.subplot(2).get_hist("total_bkg")) plot.subplot(2).add_hist(bkg_ggH, "bkg_ggH") plot.subplot(2).add_hist(bkg_ggH, "bkg_ggH_top") plot.subplot(2).add_hist(bkg_qqH, "bkg_qqH") plot.subplot(2).add_hist(bkg_qqH, "bkg_qqH_top") plot.subplot(2).setGraphStyle("bkg_ggH", "hist", linecolor=styles.color_dict["ggH"], linewidth=3) plot.subplot(2).setGraphStyle("bkg_ggH_top", "hist", linecolor=0) plot.subplot(2).setGraphStyle("bkg_qqH", "hist", linecolor=styles.color_dict["qqH"], linewidth=3) plot.subplot(2).setGraphStyle("bkg_qqH_top", "hist", linecolor=0) plot.subplot(2).normalize([ "total_bkg", "bkg_ggH", "bkg_ggH_top", "bkg_qqH", "bkg_qqH_top", "data_obs" ], "total_bkg") # stack background processes plot.create_stack(bkg_processes, "stack") # normalize stacks by bin-width if args.normalize_by_bin_width: plot.subplot(0).normalizeByBinWidth() plot.subplot(1).normalizeByBinWidth() # set axes limits and labels plot.subplot(0).setYlims( split_dict[channel], max(2 * plot.subplot(0).get_hist("data_obs").GetMaximum(), split_dict[channel] * 2)) if args.gof_variable is None: plot.subplot(2).setYlims(0.45, 2.05) else: plot.subplot(2).setYlims(0.85, 1.25) if category in ["1", "2"] + stxs_stage1p1_cats: plot.subplot(0).setLogY() plot.subplot(0).setYlims(0.1, 150000000) if channel == "em": plot.subplot(0).setYlims(1, 150000000) if not args.linear: plot.subplot(1).setYlims(0.1, split_dict[channel]) plot.subplot(1).setLogY() plot.subplot(1).setYlabel( "") # otherwise number labels are not drawn on axis if args.gof_variable != None: gof_log_vars = [] if args.gof_variable in gof_log_vars: plot.subplot(0).setLogX() plot.subplot(1).setLogX() plot.subplot(2).setLogX() elif args.gof_variable in ["njets_red", "nbtag_red"]: bins = plot.subplot(2).get_hist("data_obs").GetNbinsX() bin_labels = map(str, range(bins - 1)) bin_labels.append("#geq%i" % (bins - 1)) plot.subplot(2).setNXdivisions(bins, 0, 2) plot.subplot(2).changeXLabels(bin_labels) if args.gof_variable in styles.x_label_dict[args.channels[0]]: x_label = styles.x_label_dict[args.channels[0]][ args.gof_variable] else: x_label = args.gof_variable plot.subplot(2).setXlabel(x_label) elif args.gof_variable != None and args.linear: if args.gof_variable in styles.x_label_dict[args.channels[0]]: x_label = styles.x_label_dict[args.channels[0]][ args.gof_variable] else: x_label = args.gof_variable plot.subplot(2).setXlabel(x_label) else: plot.subplot(2).setXlabel("NN output") if args.normalize_by_bin_width: plot.subplot(0).setYlabel("dN/d(%s)" % args.gof_variable) else: plot.subplot(0).setYlabel("N_{events}") plot.subplot(2).setYlabel("") #plot.scaleXTitleSize(0.8) #plot.scaleXLabelSize(0.8) #plot.scaleYTitleSize(0.8) plot.scaleYLabelSize(0.8) #plot.scaleXLabelOffset(2.0) plot.scaleYTitleOffset(1.1) #plot.subplot(2).setNYdivisions(3, 5) #if not channel == "tt" and category in ["11", "12", "13", "14", "15", "16"]: # plot.subplot(2).changeXLabels(["0.2", "0.4", "0.6", "0.8", "1.0"]) # draw subplots. Argument contains names of objects to be drawn in corresponding order. if args.plot_restricted_signals: procs_to_draw = [ "stack", "total_bkg", "ggH", "ggH_top", "qqH", "qqH_top", "data_obs" ] if args.linear else ["stack", "total_bkg", "data_obs"] else: procs_to_draw = [ "stack", "total_bkg", "ggH", "ggH_top", "qqH", "qqH_top", "VH", "VH_top", "ttH", "ttH_top", "HWW", "HWW_top", "data_obs" ] if args.linear else ["stack", "total_bkg", "data_obs"] plot.subplot(0).Draw(procs_to_draw) if args.linear != True: if args.plot_restricted_signals: plot.subplot(1).Draw([ "stack", "total_bkg", "ggH", "ggH_top", "qqH", "qqH_top", "data_obs" ]) else: plot.subplot(1).Draw([ "stack", "total_bkg", "ggH", "ggH_top", "qqH", "qqH_top", "VH", "VH_top", "ttH", "ttH_top", "HWW", "HWW_top", "data_obs" ]) plot.subplot(2).Draw([ "total_bkg", "bkg_ggH", "bkg_ggH_top", "bkg_qqH", "bkg_qqH_top", "data_obs" ]) # create legends suffix = ["", "_top"] for i in range(2): plot.add_legend(width=0.6, height=0.15) for process in legend_bkg_processes: try: plot.legend(i).add_entry( 0, process, styles.legend_label_dict[process.replace( "TTL", "TT").replace("VVL", "VV")], 'f') except: pass plot.legend(i).add_entry(0, "total_bkg", "Bkg. unc.", 'f') plot.legend(i).add_entry(0 if args.linear else 1, "ggH%s" % suffix[i], "gg#rightarrowH", 'l') plot.legend(i).add_entry(0 if args.linear else 1, "qqH%s" % suffix[i], "qq#rightarrowH", 'l') if not args.plot_restricted_signals: plot.legend(i).add_entry(0 if args.linear else 1, "VH%s" % suffix[i], "qq#rightarrowVH", 'l') try: plot.legend(i).add_entry(0 if args.linear else 1, "ttH%s" % suffix[i], "ttH", 'l') plot.legend(i).add_entry(0 if args.linear else 1, "HWW%s" % suffix[i], "H#rightarrowWW", 'l') except: pass plot.legend(i).add_entry(0, "data_obs", "Data", 'PE') plot.legend(i).setNColumns(3) plot.legend(0).Draw() plot.legend(1).setAlpha(0.0) plot.legend(1).Draw() if args.chi2test: import ROOT as r f = r.TFile(args.input, "read") background = f.Get("htt_{}_{}_Run{}_{}/TotalBkg".format( channel, category, args.era, "prefit" if "prefit" in args.input else "postfit")) data = f.Get("htt_{}_{}_Run{}_{}/data_obs".format( channel, category, args.era, "prefit" if "prefit" in args.input else "postfit")) chi2 = data.Chi2Test(background, "UW CHI2/NDF") plot.DrawText(0.7, 0.3, "\chi^{2}/ndf = " + str(round(chi2, 3))) for i in range(2): plot.add_legend(reference_subplot=2, pos=1, width=0.5, height=0.03) plot.legend(i + 2).add_entry(0, "data_obs", "Data", 'PE') plot.legend(i + 2).add_entry(0 if args.linear else 1, "ggH%s" % suffix[i], "ggH+bkg.", 'l') plot.legend(i + 2).add_entry(0 if args.linear else 1, "qqH%s" % suffix[i], "qqH+bkg.", 'l') plot.legend(i + 2).add_entry(0, "total_bkg", "Bkg. unc.", 'f') plot.legend(i + 2).setNColumns(4) plot.legend(2).Draw() plot.legend(3).setAlpha(0.0) plot.legend(3).Draw() # draw additional labels plot.DrawCMS() if "2016" in args.era: plot.DrawLumi("35.9 fb^{-1} (2016, 13 TeV)") elif "2017" in args.era: plot.DrawLumi("41.5 fb^{-1} (2017, 13 TeV)") elif "2018" in args.era: plot.DrawLumi("59.7 fb^{-1} (2018, 13 TeV)") else: logger.critical("Era {} is not implemented.".format(args.era)) raise Exception plot.DrawChannelCategoryLabel( "%s, %s" % (channel_dict[channel], category_dict[category]), begin_left=None) # save plot postfix = "prefit" if "prefit" in args.input else "postfit" if "postfit" in args.input else "undefined" plot.save("%s/%s_%s_%s_%s.%s" % (args.outputfolder, args.era, channel, args.gof_variable if args.gof_variable is not None else category, postfix, "png" if args.png else "pdf")) plots.append( plot ) # work around to have clean up seg faults only at the end of the script
def main(args): if args.control_variable is None: channel_categories = { #"et": ["nobtag_tight", "btag_tight", "nobtag_loosemt", "nobtag_tight"] "et": ["10", "11", "12", "13", "14", "15", "16", "17", "18", "32", "33", "35", "36"], #"mt": ["nobtag_tight", "btag_tight", "nobtag_loosemt", "nobtag_tight"] "mt": ["10", "11", "12", "13", "14", "15", "16", "17", "18", "32", "33", "35", "36"], #"tt": ["nobtag", "btag"] "tt": ["10", "11", "12", "13", "14", "15", "16", "17", "32", "35"], "em": ["2", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "32", "33", "34", "35", "36", "37"] } if args.model_independent: channel_categories = { #"et": ["nobtag_tight", "btag_tight", "nobtag_loosemt", "nobtag_tight"] "et": ["32", "33", "35", "36"], #"mt": ["nobtag_tight", "btag_tight", "nobtag_loosemt", "nobtag_tight"] "mt": ["32", "33", "35", "36"], #"tt": ["nobtag", "btag"] "tt": ["32", "35"], "em": ["2", "32", "33", "34", "35", "36", "37"] } else: channel_categories = { "et": ["100"], "mt": ["100"], "tt": ["100"], "em": ["100"] } channel_dict = { "ee": "ee", "em": "e#mu", "et": "e#tau_{h}", "mm": "#mu#mu", "mt": "#mu#tau_{h}", "tt": "#tau_{h}#tau_{h}" } if args.control_variable != None: category_dict = {"100": "inclusive"} else: category_dict = { "et": { "10": "N_{jets} = 0, m_{T} (e) < 40 GeV", "11": "N_{jets} = 0, 40 GeV < m_{T} (e) < 70 GeV", "12": "N_{jets} = 0, #Delta R #geq 2.5", "13": "n_{jets} = 1, p_{T}(H) < 120 GeV", "14": "n_{jets} = 1, 120 GeV < p_{T}(H) < 200 GeV", "15": "n_{jets} = 1, p_{T}(H) > 200 GeV", "16": "N_{jets} #geq 2, m_{jj} < 350 GeV", "17": "N_{jets} #geq 2, 350 GeV < m_{jj} < 1000 GeV", "18": "N_{jets} #geq 2, m_{jj} > 1000 GeV", "32": "No B-tag Tight-m_{T}", "33": "No B-tag Loose-m_{T}", "35": "B-tag Tight-m_{T}", "36": "B-tag Loose-m_{T}", }, "mt": { "10": "N_{jets} = 0, m_{T} (e) < 40 GeV", "11": "N_{jets} = 0, 40 GeV < m_{T} (e) < 70 GeV", "12": "N_{jets} = 0, #Delta R #geq 2.5", "13": "n_{jets} = 1, p_{T}(H) < 120 GeV", "14": "n_{jets} = 1, 120 GeV < p_{T}(H) < 200 GeV", "15": "n_{jets} = 1, p_{T}(H) > 200 GeV", "16": "N_{jets} #geq 2, m_{jj} < 350 GeV", "17": "N_{jets} #geq 2, 350 GeV < m_{jj} < 1000 GeV", "18": "N_{jets} #geq 2, m_{jj} > 1000 GeV", "32": "No B-tag Tight-m_{T}", "33": "No B-tag Loose-m_{T}", "35": "B-tag Tight-m_{T}", "36": "B-tag Loose-m_{T}", }, "tt": { "10": "10", "11": "11", "12": "12", "13": "13", "14": "14", "15": "15", "16": "16", "17": "17", "32": "No B-tag", "35": "B-tag", }, "em": { "2": "d_{#zeta} < -35 GeV", "10": "10", "11": "11", "12": "12", "13": "13", "14": "14", "15": "15", "16": "16", "17": "17", "18": "18", "19": "19", "32": "No B-tag, high d_{#zeta}", "33": "No B-tag, medium d_{#zeta}", "34": "No B-tag, low d_{#zeta}", "35": "B-tag, high d_{#zeta}", "36": "B-tag, medium d_{#zeta}", "37": "B-tag, low d_{#zeta}", }, } if args.linear == True: split_value = 0 else: if args.normalize_by_bin_width: split_value = 1 else: split_value = 101 split_dict = {c: split_value for c in ["et", "mt", "tt", "em"]} bkg_processes = [ "VVL", "TTL", "ZL", "jetFakes", "EMB" ] if not args.fake_factor and args.embedding: bkg_processes = [ "QCD", "VVJ", "VVL", "W", "TTJ", "TTL", "ZJ", "ZL", "EMB" ] if not args.embedding and args.fake_factor: bkg_processes = [ "VVT", "VVJ", "TTT", "TTJ", "ZJ", "ZL", "jetFakes", "ZTT" ] if not args.embedding and not args.fake_factor: bkg_processes = [ "QCD", "W", "VVJ", "VVL", "VVT", "TTJ", "TTL", "TTT", "ZJ", "ZL", "ZTT" # "QCD", "VVT", "VVJ", "W", "TTT", "TTJ", "ZJ", "ZL", "ZTT" ] all_bkg_processes = [b for b in bkg_processes] legend_bkg_processes = copy.deepcopy(bkg_processes) legend_bkg_processes.reverse() if "2016" in args.era: era = "2016" elif "2017" in args.era: era = "2017" elif "2018" in args.era: era = "2018" else: logger.critical("Era {} is not implemented.".format(args.era)) raise Exception plots = [] for channel in args.channels: if "em" in channel: if not args.embedding: bkg_processes = [ "QCDMC", "VVT", "VVL", "W", "TTT", "TTL", "ZL", "ZTT" ] if args.embedding: bkg_processes = [ "QCD", "VVL", "W", "TTL", "ZL", "EMB" ] for category in channel_categories[channel]: if args.control_region and category != "2": continue rootfile = rootfile_parser.Rootfile_parser(args.input) legend_bkg_processes = copy.deepcopy(bkg_processes) legend_bkg_processes.reverse() # create plot if args.linear == True: plot = dd.Plot( [0.3, [0.3, 0.28]], "ModTDR", r=0.04, l=0.14, width=600) else: plot = dd.Plot( [0.5, [0.3, 0.28]], "ModTDR", r=0.04, l=0.14, width=600) # get background histograms for process in bkg_processes: if process in ["jetFakes", "jetFakesEMB"] and channel == "tt": jetfakes_hist = rootfile.get(era, channel, category, process) jetfakes_hist.Add(rootfile.get(era, channel, category, "wFakes")) plot.add_hist(jetfakes_hist, process, "bkg") else: plot.add_hist( rootfile.get(era, channel, category, process), process, "bkg") plot.setGraphStyle( process, "hist", fillcolor=styles.color_dict[process]) # get signal histograms plot_idx_to_add_signal = [0,2] if args.linear else [1,2] for i in plot_idx_to_add_signal: if args.model_independent: ggH_hist = rootfile.get(era, channel, category, "ggh_t").Clone() ggH_hist.Add(rootfile.get(era, channel, category, "ggh_i")) ggH_hist.Add(rootfile.get(era, channel, category, "ggh_b")) plot.subplot(i).add_hist( ggH_hist, "ggH") plot.subplot(i).add_hist( ggH_hist, "ggH_top") plot.subplot(i).add_hist( rootfile.get(era, channel, category, "bbh"), "bbH") plot.subplot(i).add_hist( rootfile.get(era, channel, category, "bbh"), "bbH_top") else: plot.subplot(i).add_hist( rootfile.get(era, channel, category, "TotalSig"), "mssm_sig") plot.subplot(i).add_hist( rootfile.get(era, channel, category, "TotalSig"), "mssm_sig_top") # get observed data and total background histograms plot.add_hist( rootfile.get(era, channel, category, "data_obs"), "data_obs") plot.add_hist( rootfile.get(era, channel, category, "TotalBkg"), "total_bkg") plot.subplot(0).setGraphStyle("data_obs", "e0") if args.model_independent: plot.subplot(0 if args.linear else 1).setGraphStyle( "ggH", "hist", linecolor=styles.color_dict["ggH"], linewidth=3) plot.subplot(0 if args.linear else 1).setGraphStyle( "ggH_top", "hist", linecolor=0) plot.subplot(0 if args.linear else 1).setGraphStyle( "bbH", "hist", linecolor=styles.color_dict["bbH"], linewidth=3) plot.subplot(0 if args.linear else 1).setGraphStyle( "bbH_top", "hist", linecolor=0) else: plot.subplot(0 if args.linear else 1).setGraphStyle( "mssm_sig", "hist", linecolor=styles.color_dict["bbH"], linewidth=3) plot.subplot(0 if args.linear else 1).setGraphStyle( "mssm_sig_top", "hist", linecolor=0) plot.setGraphStyle( "total_bkg", "e2", markersize=0, fillcolor=styles.color_dict["unc"], linecolor=0) # assemble ratio if args.model_independent: bkg_ggH = plot.subplot(2).get_hist("ggH") bkg_bbH = plot.subplot(2).get_hist("bbH") bkg_ggH.Add(plot.subplot(2).get_hist("total_bkg")) bkg_bbH.Add(plot.subplot(2).get_hist("total_bkg")) plot.subplot(2).add_hist(bkg_ggH, "bkg_ggH") plot.subplot(2).add_hist(bkg_ggH, "bkg_ggH_top") plot.subplot(2).add_hist(bkg_bbH, "bkg_bbH") plot.subplot(2).add_hist(bkg_bbH, "bkg_bbH_top") plot.subplot(2).setGraphStyle( "bkg_ggH", "hist", linecolor=styles.color_dict["ggH"], linewidth=3) plot.subplot(2).setGraphStyle( "bkg_ggH_top", "hist", linecolor=0) plot.subplot(2).setGraphStyle( "bkg_bbH", "hist", linecolor=styles.color_dict["bbH"], linewidth=3) plot.subplot(2).setGraphStyle( "bkg_bbH_top", "hist", linecolor=0) plot.subplot(2).normalize([ "total_bkg", "bkg_ggH", "bkg_ggH_top", "bkg_bbH", "bkg_bbH_top", "data_obs" ], "total_bkg") else: bkg_sig = plot.subplot(2).get_hist("mssm_sig") bkg_sig.Add(plot.subplot(2).get_hist("total_bkg")) plot.subplot(2).add_hist(bkg_sig, "bkg_mssm_sig") plot.subplot(2).add_hist(bkg_sig, "bkg_mssm_sig_top") plot.subplot(2).setGraphStyle( "bkg_mssm_sig", "hist", linecolor=styles.color_dict["bbH"], linewidth=3) plot.subplot(2).setGraphStyle( "bkg_mssm_sig_top", "hist", linecolor=0) plot.subplot(2).normalize([ "total_bkg", "bkg_mssm_sig", "bkg_mssm_sig_top", "data_obs" ], "total_bkg") # stack background processes plot.create_stack(bkg_processes, "stack") # normalize stacks by bin-width if args.normalize_by_bin_width: plot.subplot(0).normalizeByBinWidth() plot.subplot(1).normalizeByBinWidth() # set axes limits and labels plot.subplot(0).setYlims( split_dict[channel], # max(2 * plot.subplot(0).get_hist("total_bkg").GetMaximum(), # split_dict[channel] * 2)) max(1.3 * plot.subplot(0).get_hist("total_bkg").GetMaximum(), split_dict[channel] * 2)) plot.subplot(2).setYlims(0.75, 1.8) if args.linear != True: # plot.subplot(1).setYlims(1.e-4, split_dict[channel]) plot.subplot(1).setYlims(1.e-3, split_dict[channel]) plot.subplot(1).setLogY() if int(category) > 30 or int(category) == 1: plot.subplot(1).setLogX() plot.subplot(1).setYlabel( "") # otherwise number labels are not drawn on axis if args.control_variable != None: if args.control_variable in styles.x_label_dict[args.channels[0]]: x_label = styles.x_label_dict[args.channels[0]][ args.control_variable] else: x_label = args.control_variable plot.subplot(2).setXlabel(x_label) else: if int(category) > 30 or int(category) == 1: plot.subplot(2).setXlabel("m_{T}^{tot} (Puppi) [GeV]") else: plot.subplot(2).setXlabel("SVFit m_{#tau#tau} (Puppi) [GeV]") if args.normalize_by_bin_width: if int(category) > 30 or int(category) == 1: plot.subplot(0).setYlabel("dN/dm_{T}^{tot} [1/GeV]") else: plot.subplot(0).setYlabel("dN/dm_{#tau#tau} [1/GeV]") else: plot.subplot(0).setYlabel("N_{events}") plot.subplot(2).setYlabel("") if int(category) > 30 or int(category) == 1: low_edge = max(10, rootfile.get(era, channel, category, "TotalSig").GetBinLowEdge(2)) plot.setXlims(low_edge, 3890) plot.subplot(0).setLogX() plot.subplot(2).setLogX() #plot.scaleXTitleSize(0.8) #plot.scaleXLabelSize(0.8) #plot.scaleYTitleSize(0.8) plot.scaleYLabelSize(0.8) #plot.scaleXLabelOffset(2.0) plot.scaleYTitleOffset(1.05) #plot.subplot(2).setNYdivisions(3, 5) # draw subplots. Argument contains names of objects to be drawn in corresponding order. # procs_to_draw = ["stack", "total_bkg", "ggH", "ggH_top", "bbH", "bbH_top", "data_obs"] if args.linear else ["stack", "total_bkg", "data_obs"] if category == "1" and args.control_region: procs_to_draw = ["stack", "total_bkg", "data_obs"] if args.linear else ["stack", "total_bkg", "data_obs"] else: if args.model_independent: procs_to_draw = ["stack", "total_bkg", "ggH", "ggH_top", "bbH", "bbH_top", "data_obs"] if args.linear else ["stack", "total_bkg", "data_obs"] else: procs_to_draw = ["stack", "total_bkg", "mssm_sig", "mssm_sig_top", "data_obs"] if args.linear else ["stack", "total_bkg", "data_obs"] if args.blinded: procs_to_draw.remove("data_obs") plot.subplot(0).Draw(procs_to_draw) if args.linear != True: # plot.subplot(1).Draw([ # "stack", "total_bkg", "ggH", "bbH", # "ggH_top", "bbH_top", # "data_obs" # ]) if category == "1" and args.control_region: plot.subplot(1).Draw([ "stack", "total_bkg", "data_obs" ]) else: if args.model_independent: procs_to_draw = ["stack", "total_bkg", "ggH", "bbH", "ggH_top", "bbH_top", "data_obs"] else: procs_to_draw = ["stack", "total_bkg", "mssm_sig", "mssm_sig_top", "data_obs"] if args.blinded: procs_to_draw.remove("data_obs") plot.subplot(1).Draw(procs_to_draw) if category == "1" and args.control_region: plot.subplot(2).Draw([ "total_bkg", "data_obs" ]) else: if args.model_independent: procs_to_draw = ["total_bkg", "bkg_ggH", "bkg_bbH", "bkg_ggH_top", "bkg_bbH_top", "data_obs"] else: procs_to_draw = ["total_bkg", "bkg_mssm_sig", "bkg_mssm_sig_top", "data_obs"] if args.blinded: procs_to_draw.remove("data_obs") plot.subplot(2).Draw(procs_to_draw) # create legends suffix = ["", "_top"] for i in range(2): if int(category) < 30 and int(category) > 1: plot.add_legend(width=0.38, height=0.30) else: plot.add_legend(width=0.40, height=0.30) # plot.add_legend(width=0.6, height=0.15) for process in legend_bkg_processes: plot.legend(i).add_entry( 0, process, styles.legend_label_dict[process.replace("TTL", "TT").replace("VVL", "VV")], 'f') plot.legend(i).add_entry(0, "total_bkg", "Bkg. unc.", 'f') if args.control_region and category == "1": # plot.legend(i).add_entry(0 if args.linear else 1, "mssm_sig%s" % suffix[i], "#splitline{H #rightarrow #tau#tau}{(m_{H}=1200 GeV)}", 'l') pass else: if args.model_independent: plot.legend(i).add_entry(0 if args.linear else 1, "ggH%s" % suffix[i], "#splitline{ggH}{(m_{H} = 2600 GeV)}", 'l') plot.legend(i).add_entry(0 if args.linear else 1, "bbH%s" % suffix[i], "#splitline{bbH}{(m_{H} = 2600 GeV)}", 'l') else: plot.legend(i).add_entry(0 if args.linear else 1, "mssm_sig%s" % suffix[i], "#splitline{H #rightarrow #tau#tau}{#splitline{(m_{A}=1200 GeV,}{ tan #beta = 10)}}", 'l') if not args.blinded: plot.legend(i).add_entry(0, "data_obs", "Data", 'PE') plot.legend(i).setNColumns(2) plot.legend(0).Draw() plot.legend(1).setAlpha(0.0) plot.legend(1).Draw() if args.chi2test: import ROOT as r f = r.TFile(args.input, "read") background = f.Get("htt_{}_{}_Run{}_{}/TotalBkg".format( channel, category, args.era, "prefit" if "prefit" in args.input else "postfit")) data = f.Get("htt_{}_{}_Run{}_{}/data_obs".format( channel, category, args.era, "prefit" if "prefit" in args.input else "postfit")) chi2 = data.Chi2Test(background, "UW CHI2/NDF") plot.DrawText(0.7, 0.3, "\chi^{2}/ndf = " + str(round(chi2, 3))) for i in range(2): plot.add_legend( reference_subplot=2, pos=1, width=0.5, height=0.06) if not args.blinded: plot.legend(i + 2).add_entry(0, "data_obs", "Data", 'PE') if args.control_region and category == "1": pass else: if args.model_independent: plot.legend(i + 2).add_entry(0 if args.linear else 1, "ggH%s" % suffix[i], "ggH+bkg.", 'l') plot.legend(i + 2).add_entry(0 if args.linear else 1, "bbH%s" % suffix[i], "bbH+bkg.", 'l') else: plot.legend(i + 2).add_entry(0 if args.linear else 1, "mssm_sig%s" % suffix[i], "H+bkg.", 'l') plot.legend(i + 2).add_entry(0, "total_bkg", "Bkg. unc.", 'f') plot.legend(i + 2).setNColumns(3) plot.legend(2).Draw() plot.legend(3).setAlpha(0.0) plot.legend(3).Draw() # draw additional labels # plot.DrawCMS() if "2016" in args.era: plot.DrawLumi("35.9 fb^{-1} (2016, 13 TeV)") elif "2017" in args.era: plot.DrawLumi("41.5 fb^{-1} (2017, 13 TeV)") elif "2018" in args.era: plot.DrawLumi("59.7 fb^{-1} (2018, 13 TeV)") else: logger.critical("Era {} is not implemented.".format(args.era)) raise Exception posChannelCategoryLabelLeft = None plot.DrawChannelCategoryLabel( "%s, %s" % (channel_dict[channel], category_dict[channel][category]), begin_left=posChannelCategoryLabelLeft) # save plot postfix = "prefit" if "prefit" in args.input else "postfit" if "postfit" in args.input else "undefined" plot.save("%s/%s_%s_%s_%s.%s" % (args.output_dir, args.era, channel, args.control_variable if args.control_variable is not None else category, postfix, "png" if args.png else "pdf")) plots.append( plot ) # work around to have clean up seg faults only at the end of the script
def main(args): channel_categories = { #"et": ["ztt", "zll", "w", "tt", "ss", "misc"], "et": ["12", "15", "11", "13", "14", "16"], #"mt": ["ztt", "zll", "w", "tt", "ss", "misc"], "mt": ["12", "15", "11", "13", "14", "16"], #"tt": ["ztt", "noniso", "misc"] "tt": ["12", "17", "16"] } if args.categories == "stxs_stage0": for channel in ["et", "mt", "tt"]: channel_categories[channel] += ["1", "2"] elif args.categories == "stxs_stage1": for channel in ["et", "mt", "tt"]: channel_categories[channel] += ["1", "2"] else: logger.critical("Selected unkown STXS categorization {}", args.categories) raise Exception if args.stxs_signals == "stxs_stage0": signals = ["ggH", "qqH"] signal_linestlyes = [1, 1] elif args.stxs_signals == "stxs_stage1": signals = [ "qqH_VBFTOPO_JET3VETO", "qqH_VBFTOPO_JET3", "qqH_REST", "qqH_PTJET1_GT200", "qqH_VH2JET", "ggH_0J", "ggH_1J_PTH_0_60", "ggH_1J_PTH_60_120", "ggH_1J_PTH_120_200", "ggH_1J_PTH_GT200", "ggH_GE2J_PTH_0_60", "ggH_GE2J_PTH_60_120", "ggH_GE2J_PTH_120_200", "ggH_GE2J_PTH_GT200", "ggH_VBFTOPO_JET3VETO", "ggH_VBFTOPO_JET3" ] signal_linestlyes = [1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] else: logger.critical("Selected unkown STXS signals {}", args.stxs_signals) raise Exception signal_names = [signal.replace("125", "") for signal in signals] channel_dict = { "ee": "ee", "em": "e#mu", "et": "e#tau_{h}", "mm": "#mu#mu", "mt": "#mu#tau_{h}", "tt": "#tau_{h}#tau_{h}" } category_dict = { "1": "ggH", "2": "VBF", "12": "Z#rightarrow#tau#tau", "15": "Z#rightarrowll", "11": "W+jets", "13": "t#bar{t}", "14": "same sign", "16": "misc", "17": "noniso" } rootfile = rootfile_parser.Rootfile_parser(args.input) plots = [] for channel in args.channels: for category in channel_categories[channel]: # Create plot width = 600 if args.categories == "stxs_stage1": if category in ["1", "2"]: width = 1200 plot = dd.Plot([], "ModTDR", r=0.04, l=0.14, width=width) # Plot signals for i, (signal, name) in enumerate(zip(signals, signal_names)): plot.subplot(0).add_hist( rootfile.get(channel, category, signal), name) plot.subplot(0).setGraphStyle( name, "hist", linecolor=styles.color_dict[name.split("_")[0]], linewidth=5) plot.subplot(0).get_hist(name).SetLineStyle( signal_linestlyes[i]) # Normalize by bin-width if args.normalize_by_bin_width: plot.subplot(0).normalizeByBinWidth() # Define axes plot.subplot(0).setXlabel("NN score") if args.normalize_by_bin_width: plot.subplot(0).setYlabel("N_{events}/bin width") else: plot.subplot(0).setYlabel("N_{events}") # Draw signals plot.subplot(0).setLogY() plot.subplot(0).setYlims(1e-3, 1e5) plot.subplot(0).Draw(signal_names) # Draw additional labels plot.DrawCMS() if "2016" in args.era: plot.DrawLumi("35.9 fb^{-1} (2016, 13 TeV)") elif "2017" in args.era: plot.DrawLumi("41.5 fb^{-1} (2017, 13 TeV)") else: logger.critical("Era {} is not implemented.".format(args.era)) raise Exception posChannelCategoryLabelLeft = None if args.categories == "stxs_stage1": if category in ["1", "2"]: posChannelCategoryLabelLeft = 0.075 plot.DrawChannelCategoryLabel( "%s, %s" % (channel_dict[channel], category_dict[category]), begin_left=posChannelCategoryLabelLeft) # Create legends plot.add_legend(width=0.40, height=0.30) plot.legend(0).setNColumns(1) for i, name in enumerate(signal_names): plot.legend(0).add_entry(0, name, name, 'l') plot.legend(0).Draw() # Save plot postfix = "signals_{}".format(args.stxs_signals) plot.save("plots/%s_%s_%s_%s.%s" % (args.era, channel, category, postfix, "png" if args.png else "pdf")) plots.append( plot ) # work around to have clean up seg faults only at the end of the script
def main(): rootfile = rootfile_parser.Rootfile_parser("datacard_shapes_prefit.root") # create canvas: # First argument defines subplot structure: List of splits from top to bottom (max. 1.0 to min. 0.0). A split can be a single position or a pair resulting in gap. # Further arguments set general style. plot = dd.Plot([0.65, [0.47, 0.45], [0.22, 0.20]], "ModTDR", r=0.04, l=0.14) bkg_processes = ["EWK", "QCD", "VV", "W", "TTT", "TTJ", "ZJ", "ZL", "ZTT"] # register histograms in the subplots (can be done globally or for specific subplots). regustered histograms are not necessarily plotted later. for process in bkg_processes: plot.add_hist( rootfile.get("mt", "qqh", process), process, "bkg" ) # get(channel, category, process) and assign specific name and group name to histogram. The group name is optional. plot.setGraphStyle(process, "hist", fillcolor=styles.color_dict[process]) for i in range(2): plot.subplot(i + 1).add_hist( rootfile.get("mt", "qqh", "ggH"), "ggH" ) # signal histograms are used twice in order to realize a two color line style plot.subplot(i + 1).add_hist(rootfile.get("mt", "qqh", "ggH"), "ggH_top") plot.subplot(i + 1).add_hist(rootfile.get("mt", "qqh", "qqH"), "qqH") plot.subplot(i + 1).add_hist(rootfile.get("mt", "qqh", "qqH"), "qqH_top") plot.add_hist(rootfile.get("mt", "qqh", "data_obs"), "data_obs") plot.add_hist(rootfile.get("mt", "qqh", "TotalBkg"), "unc_band") # set some graph styles plot.subplot(1).setGraphStyle("ggH", "hist", linecolor=styles.color_dict["ggH"], linewidth=3) plot.subplot(1).setGraphStyle("ggH_top", "hist", linecolor=0) plot.subplot(1).setGraphStyle("qqH", "hist", linecolor=styles.color_dict["qqH"], linewidth=3) plot.subplot(1).setGraphStyle("qqH_top", "hist", linecolor=0) plot.setGraphStyle("unc_band", "e2", markersize=0, fillcolor=styles.color_dict["unc"], linecolor=0) # in order to show S+B in the ratio plot, add total background to signal hists (get_hist returns a copy) and register the results bkg_ggH = plot.subplot(2).get_hist("ggH") bkg_qqH = plot.subplot(2).get_hist("qqH") bkg_ggH.Add(plot.subplot(2).get_hist("unc_band")) bkg_qqH.Add(plot.subplot(2).get_hist("unc_band")) plot.subplot(2).add_hist(bkg_ggH, "bkg_ggH") plot.subplot(2).add_hist(bkg_ggH, "bkg_ggH_top") plot.subplot(2).add_hist(bkg_qqH, "bkg_qqH") plot.subplot(2).add_hist(bkg_qqH, "bkg_qqH_top") plot.subplot(2).setGraphStyle("bkg_ggH", "hist", linecolor=styles.color_dict["ggH"], linewidth=3) plot.subplot(2).setGraphStyle("bkg_ggH_top", "hist", linecolor=0) plot.subplot(2).setGraphStyle("bkg_qqH", "hist", linecolor=styles.color_dict["qqH"], linewidth=3) plot.subplot(2).setGraphStyle("bkg_qqH_top", "hist", linecolor=0) # apply normalizations for the ratio and the background fractions plot: # First argument: Name of a single histogram or list of names / group names that shall be normalized # Second argument: Name of a single histogram or list of names / group names that shall be contained in the denominator plot.subplot(2).normalize([ "unc_band", "bkg_ggH", "bkg_ggH_top", "bkg_qqH", "bkg_qqH_top", "data_obs" ], "unc_band") #plot.subplot(2).normalize(["unc_band", "bkg_ggH", "bkg_ggH_top", "bkg_qqH", "bkg_qqH_top", "data_obs"], "bkg") # would also work but add up the single bkg histograms in the background plot.subplot(3).normalize("bkg", "bkg") # stack background histograms for all subplots and assign a name plot.create_stack(bkg_processes, "stack") # set some axis options plot.subplot(0).setYlims(100, 2000) plot.subplot(1).setYlims(0.1, 100) plot.subplot(2).setYlims(0.81, 1.39) plot.subplot(3).setYlims(0.0, 1.0) plot.subplot(1).setLogY() plot.subplot(3).setXlabel("NN score") plot.subplot(0).setYlabel("N_{events}") plot.subplot(1).setYlabel( "") # otherwise number labels are not drawn on axis plot.subplot(2).setYlabel("ratio to bkg") plot.subplot(3).setYlabel("bkg frac.") plot.scaleXTitleSize(0.8) plot.scaleXLabelSize(0.8) plot.scaleYTitleSize(0.8) plot.scaleYLabelSize(0.8) plot.scaleXLabelOffset(2.0) plot.scaleYTitleOffset(1.1) plot.subplot(2).setNYdivisions(3, 5) # draw subplots. Argument contains names of objects to be drawn in corresponding order. plot.subplot(0).Draw(["stack", "unc_band", "data_obs"]) plot.subplot(1).Draw( ["stack", "unc_band", "ggH", "ggH_top", "qqH", "qqH_top", "data_obs"]) plot.subplot(2).Draw([ "unc_band", "bkg_ggH", "bkg_ggH_top", "bkg_qqH", "bkg_qqH_top", "data_obs" ]) plot.subplot(3).Draw("stack") # create legends bkg_processes.reverse() suffix = ["", "_top"] for i in range(2): plot.add_legend(width=0.48, height=0.15) for process in bkg_processes: plot.legend(i).add_entry( 0, process, styles.label_dict[process.replace("EWK", "EWKZ")], 'f') plot.legend(i).add_entry(0, "unc_band", "Bkg. unc.", 'f') plot.legend(i).add_entry(1, "ggH%s" % suffix[i], "ggH", 'l') plot.legend(i).add_entry(1, "qqH%s" % suffix[i], "qqH", 'l') plot.legend(i).add_entry(0, "data_obs", "Data", 'PE') plot.legend(i).setNColumns(3) plot.legend(0).Draw() plot.legend(1).setAlpha(0.0) plot.legend(1).Draw() for i in range(2): plot.add_legend(reference_subplot=2, pos=1, width=0.4, height=0.03) plot.legend(i + 2).add_entry(0, "data_obs", "Data", 'PE') plot.legend(i + 2).add_entry(1, "ggH%s" % suffix[i], "ggH+bkg.", 'l') plot.legend(i + 2).add_entry(1, "qqH%s" % suffix[i], "qqH+bkg.", 'l') plot.legend(i + 2).setNColumns(3) plot.legend(2).Draw() plot.legend(3).setAlpha(0.0) plot.legend(3).Draw() # draw additional labels plot.DrawCMS() plot.DrawLumi("35.9 fb^{-1} (13 TeV)") plot.DrawChannelCategoryLabel("#mu#tau_{h}, VBF") # save plot plot.save("testoutput.pdf")
def main(args): channel_categories = { "et": ["ggh", "qqh", "ztt", "zll", "w", "tt", "ss", "misc"], "mt": ["ggh", "qqh", "ztt", "zll", "w", "tt", "ss", "misc"], "tt": ["ggh", "qqh", "ztt", "noniso", "misc"] } channel_dict = { "ee": "ee", "em": "e#mu", "et": "e#tau_{h}", "mm": "#mu#mu", "mt": "#mu#tau_{h}", "tt": "#tau_{h}#tau_{h}" } category_dict = { "ggh": "ggH", "qqh": "VBF", "ztt": "Z#rightarrow#tau#tau", "zll": "Z#rightarrowll", "w": "W+jets", "tt": "t#bar{t}", "ss": "same sign", "misc": "misc", "noniso": "noniso" } split_dict = {"et": 50, "mt": 200, "tt": 20} bkg_processes = ["EWK", "QCD", "VV", "W", "TTT", "TTJ", "ZJ", "ZL", "ZTT"] legend_bkg_processes = copy.deepcopy(bkg_processes) legend_bkg_processes.reverse() rootfile_unc = rootfile_parser.Rootfile_parser(args.input) rootfile_prefit = rootfile_parser.Rootfile_parser( args.input.replace(".root", "_prefit.root")) #for process in bkg_processes: # if rootfile.get('mt', 'ztt', process, 'CMS_htt_dyShapeUp') != None: # print process plots = [] for channel in args.channels: for category in channel_categories[channel]: plot = dd.Plot([[0.4, 0.38]], "ModTDR", r=0.04, l=0.14) for process in bkg_processes: plot.add_hist(rootfile_prefit.get(channel, category, process), process, "bkg") plot.setGraphStyle(process, "hist", fillcolor=styles.color_dict[process]) plot.add_hist(rootfile_prefit.get(channel, category, "ggH"), "ggH", "signal") plot.add_hist(rootfile_prefit.get(channel, category, "ggH"), "ggH_top") plot.add_hist(rootfile_prefit.get(channel, category, "qqH"), "qqH", "signal") plot.add_hist(rootfile_prefit.get(channel, category, "qqH"), "qqH_top") plot.add_hist(rootfile_prefit.get(channel, category, "data_obs"), "data_obs") plot.add_hist(rootfile_prefit.get(channel, category, "TotalBkg"), "total_bkg") for index, uncertainty in enumerate(args.uncertainties): for shift in ["Up", "Down"]: for process in bkg_processes + ["ggH125", "qqH125"]: hist = rootfile_unc.get(channel, category, process, uncertainty + shift) if hist != None: plot.subplot(0).add_hist( hist, process + uncertainty + shift, uncertainty + shift) else: plot.subplot(0).add_hist( rootfile_unc.get(channel, category, process), process + uncertainty + shift, uncertainty + shift) sighist = plot.subplot(0).get_hist("signal") sighist.Scale(-1) plot.subplot(0).add_hist(sighist, "signal" + uncertainty + shift, uncertainty + shift) plot.add_hist( plot.subplot(0).get_hist(uncertainty + shift), "total_" + uncertainty + shift, "uncertainties") plot.setGraphStyle("total_" + uncertainty + shift, "hist", linecolor=4 + index, linewidth=3) plot.subplot(0).setGraphStyle("ggH", "hist", linecolor=styles.color_dict["ggH"], linewidth=3) plot.subplot(0).setGraphStyle("ggH_top", "hist", linecolor=0) plot.subplot(0).setGraphStyle("qqH", "hist", linecolor=styles.color_dict["qqH"], linewidth=3) plot.subplot(0).setGraphStyle("qqH_top", "hist", linecolor=0) plot.setGraphStyle("total_bkg", "e2", markersize=0, fillcolor=styles.color_dict["unc"], linecolor=0, fillstyle=3001 if args.png else 1001) bkg_ggH = plot.subplot(1).get_hist("ggH") bkg_qqH = plot.subplot(1).get_hist("qqH") bkg_ggH.Add(plot.subplot(1).get_hist("total_bkg")) bkg_qqH.Add(plot.subplot(1).get_hist("total_bkg")) plot.subplot(1).add_hist(bkg_ggH, "bkg_ggH") plot.subplot(1).add_hist(bkg_ggH, "bkg_ggH_top") plot.subplot(1).add_hist(bkg_qqH, "bkg_qqH") plot.subplot(1).add_hist(bkg_qqH, "bkg_qqH_top") plot.subplot(1).setGraphStyle("bkg_ggH", "hist", linecolor=styles.color_dict["ggH"], linewidth=3) plot.subplot(1).setGraphStyle("bkg_ggH_top", "hist", linecolor=0) plot.subplot(1).setGraphStyle("bkg_qqH", "hist", linecolor=styles.color_dict["qqH"], linewidth=3) plot.subplot(1).setGraphStyle("bkg_qqH_top", "hist", linecolor=0) plot.subplot(1).normalize([ "total_bkg", "bkg_ggH", "bkg_ggH_top", "bkg_qqH", "bkg_qqH_top", "data_obs", "uncertainties" ], "total_bkg") plot.create_stack(bkg_processes, "stack") plot.subplot(0).setYlims( 0, 1.7 * plot.subplot(0).get_hist("total_bkg").GetMaximum()) plot.subplot(1).setYlims(0.85, 1.35) if channel == "tt" and category == "qqh": plot.subplot(1).setYlims(0.75, 2.15) plot.subplot(1).setXlabel(args.x_label) plot.subplot(0).setYlabel("N_{events}") plot.subplot(1).setYlabel("Ratio to Bkg.") #plot.scaleXTitleSize(0.8) #plot.scaleXLabelSize(0.8) #plot.scaleYTitleSize(0.8) plot.scaleYLabelSize(0.8) #plot.scaleXLabelOffset(2.0) plot.scaleYTitleOffset(1.1) #plot.subplot(1).setNYdivisions(3, 5) # draw subplots. Argument contains names of objects to be drawn in corresponding order. plot.subplot(0).Draw([ "stack", "total_bkg", "uncertainties", "ggH", "ggH_top", "qqH", "qqH_top", "data_obs" ]) plot.subplot(1).Draw([ "total_bkg", "uncertainties", "bkg_ggH", "bkg_ggH_top", "bkg_qqH", "bkg_qqH_top", "data_obs" ]) # create legends suffix = ["", "_top"] for i in range(2): plot.add_legend(width=0.48, height=0.15) for process in legend_bkg_processes: plot.legend(i).add_entry( 0, process, styles.label_dict[process.replace("EWK", "EWKZ")], 'f') plot.legend(i).add_entry(0, "total_bkg", "Bkg. unc.", 'f') plot.legend(i).add_entry(0, "ggH%s" % suffix[i], "ggH", 'l') plot.legend(i).add_entry(0, "qqH%s" % suffix[i], "qqH", 'l') plot.legend(i).add_entry(0, "data_obs", "Data", 'PE') for uncertainty in args.uncertainties: plot.legend(i).add_entry( 1, "total_" + uncertainty + "Up", uncertainty.replace("CMS_htt_", ""), 'l') plot.legend(i).setNColumns(3) plot.legend(0).Draw() plot.legend(1).setAlpha(0.0) plot.legend(1).Draw() for i in range(2): plot.add_legend(reference_subplot=1, pos=1, width=0.5, height=0.06) plot.legend(i + 2).add_entry(0, "data_obs", "Data", 'PE') plot.legend(i + 2).add_entry(0, "ggH%s" % suffix[i], "ggH+bkg.", 'l') plot.legend(i + 2).add_entry(0, "qqH%s" % suffix[i], "qqH+bkg.", 'l') plot.legend(i + 2).add_entry(0, "total_bkg", "Bkg. unc.", 'f') for uncertainty in args.uncertainties: plot.legend(i + 2).add_entry( 1, "total_" + uncertainty + "Up", uncertainty.replace("CMS_htt_", ""), 'l') plot.legend(i + 2).setNColumns(4) plot.legend(2).Draw() plot.legend(3).setAlpha(0.0) plot.legend(3).Draw() # draw additional labels plot.DrawCMS() plot.DrawLumi("35.9 fb^{-1} (13 TeV)") plot.DrawChannelCategoryLabel( "%s, %s" % (channel_dict[channel], category_dict[category])) # save plot plot.save("plots/unc_%s_%s.%s" % (channel, category, 'png' if args.png else 'pdf')) plots.append( plot ) # work around to have clean up seg faults only at the end of the script
def main(args): if args.gof_variable != None: channel_categories = { "et": ["100"], "mt": ["100"], "tt": ["100"], "em": ["100"], "mm": ["100"], } channel_categories = { "mt": [args.bin], "mm": ["100"], } channel_dict = { "ee": "ee", "em": "e#mu", "et": "e#tau_{h}", "mm": "#mu#mu", "mt": "#mu#tau_{h}", "tt": "#tau_{h}#tau_{h}" } if args.gof_variable != None: category_dict = {"100": "inclusive"} elif args.categories == "inclusive": category_dict = { "1": "inclusive", "100": "cr", } elif args.categories == "pt_binned": category_dict = { "1": "[20,25]", "2": "[25,30]", "3": "[30,35]", "4": "[35,40]", "5": "[40,50]", "6": "[50,70]", "7": "[70,]", "100": "cr", } elif args.categories == "dm_binned": category_dict = { "1": "DM0", "2": "DM1", "3": "DM10", "4": "DM11", "100": "cr", } elif args.categories == "ptdm_binned": category_dict = { "1": "[20,25], DM0", "2": "[20,25], DM1", "3": "[20,25], DM10", "4": "[25,30], DM0", "5": "[25,30], DM1", "6": "[25,30], DM10", "7": "[30,35], DM0", "8": "[30,35], DM1", "9": "[30,35], DM10", "10": "[35,40], DM0", "11": "[35,40], DM1", "12": "[35,40], DM10", "13": "[40,50], DM0", "14": "[40,50], DM1", "15": "[40,50], DM10", "16": "[50,70], DM0", "17": "[50,70], DM1", "18": "[50,70], DM10", "19": "[70,], DM0", "20": "[70,], DM1", "21": "[70,], DM10", "100": "cr", } else: logger.fatal( "Neither gof variable nor valid categorisation specified.") raise Exception if args.linear == True: split_value = 0 else: if args.normalize_by_bin_width: split_value = 10001 else: split_value = 101 split_dict = {c: split_value for c in ["et", "mt", "tt", "em", "mm"]} bkg_processes = { "mt": ["VVL", "TTL", "ZL", "jetFakes", "EMB"], "mm": ["VV", "TT", "jetFakes", "EMB"] } if not args.fake_factor and args.embedding: bkg_processes = { "mt": ["QCDEMB", "VVJ", "VVL", "W", "TTJ", "TTL", "ZJ", "ZL", "EMB"], "mm": ["QCDEMB", "W", "MMEMB"] } if not args.embedding and args.fake_factor: bkg_processes = { "mt": ["VVT", "VVJ", "TTT", "TTJ", "ZJ", "ZL", "jetFakes", "ZTT"], "mm": ["VV", "TT", "jetFakes", "ZLL"] } if not args.embedding and not args.fake_factor: bkg_processes = { "mt": [ "QCD", "VVT", "VVL", "VVJ", "W", "TTT", "TTL", "TTJ", "ZJ", "ZL", "ZTT" ], "mm": ["VV", "W", "TT", "ZLL"] } legend_bkg_processes = copy.deepcopy(bkg_processes) for chn_bkg_processes in legend_bkg_processes.itervalues(): chn_bkg_processes.reverse() if "2016" in args.era: era = "Run2016" elif "2017" in args.era: era = "Run2017" elif "2018" in args.era: era = "Run2018" else: logger.critical("Era {} is not implemented.".format(args.era)) raise Exception plots = [] for channel in args.channels: for category in channel_categories[channel]: rootfile = rootfile_parser.Rootfile_parser(args.input) tranche = None if "_" in category: tranche = category.split("_")[1] category = category.split("_")[0] # create plot width = 600 if args.linear == True: plot = dd.Plot([0.3, [0.3, 0.28]], "ModTDR", r=0.04, l=0.14, width=width) else: plot = dd.Plot([0.5, [0.3, 0.28]], "ModTDR", r=0.04, l=0.14, width=width) # get background histograms for process in bkg_processes[channel]: plot.add_hist(rootfile.get(era, channel, category, process), process, "bkg") plot.setGraphStyle(process, "hist", fillcolor=styles.color_dict[process]) # get observed data and total background histograms # NOTE: With CMSSW_8_1_0 the TotalBkg definition has changed. plot.add_hist(rootfile.get(era, channel, category, "data_obs"), "data_obs") total_bkg = rootfile.get(era, channel, category, "TotalBkg") if args.embedding: total_bkg.Add(rootfile.get(era, channel, category, "EMB")) else: total_bkg.Add(rootfile.get(era, channel, category, "ZTT")) plot.add_hist(total_bkg, "total_bkg") plot.subplot(0).setGraphStyle("data_obs", "e0") plot.setGraphStyle("total_bkg", "e2", markersize=0, fillcolor=styles.color_dict["unc"], linecolor=0) plot.subplot(2).normalize(["total_bkg", "data_obs"], "total_bkg") # stack background processes plot.create_stack(bkg_processes[channel], "stack") # normalize stacks by bin-width if args.normalize_by_bin_width: plot.subplot(0).normalizeByBinWidth() plot.subplot(1).normalizeByBinWidth() # # set axes limits and labels plot.subplot(0).setYlims( split_dict[channel], max(2 * plot.subplot(0).get_hist("total_bkg").GetMaximum(), split_dict[channel] * 2)) plot.subplot(2).setYlims(0.5, 1.5) if args.linear != True: plot.subplot(1).setYlims(0.1, split_dict[channel]) plot.subplot(1).setLogY() plot.subplot(1).setYlabel( "") # otherwise number labels are not drawn on axis if args.gof_variable != None: if args.gof_variable in styles.x_label_dict[args.channels[0]]: x_label = styles.x_label_dict[args.channels[0]][ args.gof_variable] else: x_label = args.gof_variable plot.subplot(2).setXlabel(x_label) else: plot.subplot(2).setXlabel("m_{vis} / GeV") if args.normalize_by_bin_width: plot.subplot(0).setYlabel("dN/d(NN output)") else: plot.subplot(0).setYlabel("N_{events}") plot.subplot(2).setYlabel("") #plot.scaleXTitleSize(0.8) #plot.scaleXLabelSize(0.8) #plot.scaleYTitleSize(0.8) plot.scaleYLabelSize(0.8) #plot.scaleXLabelOffset(2.0) plot.scaleYTitleOffset(1.1) #plot.subplot(2).setNYdivisions(3, 5) # draw subplots. Argument contains names of objects to be drawn in corresponding order. procs_to_draw = ["stack", "data_obs" ] if args.linear else ["stack", "data_obs"] plot.subplot(0).Draw(procs_to_draw) if args.linear != True: plot.subplot(1).Draw(["stack", "data_obs"]) plot.subplot(2).Draw(["total_bkg", "data_obs"]) # create legends suffix = ["", "_top"] for i in range(2): plot.add_legend(width=0.6, height=0.2) for process in legend_bkg_processes[channel]: plot.legend(i).add_entry( 0, process, styles.legend_label_dict[process.replace( "TTL", "TT").replace("VVL", "VV")], 'f') plot.legend(i).add_entry(0, "data_obs", "Data", 'PE') plot.legend(i).setNColumns(3) plot.legend(0).Draw() plot.legend(1).setAlpha(0.0) plot.legend(1).Draw() if args.chi2test: import ROOT as r f = r.TFile(args.input, "read") background = f.Get("htt_{}_{}_Run{}_{}/TotalBkg".format( channel, category, args.era, "prefit" if "prefit" in args.input else "postfit")) data = f.Get("htt_{}_{}_Run{}_{}/data_obs".format( channel, category, args.era, "prefit" if "prefit" in args.input else "postfit")) chi2 = data.Chi2Test(background, "UW CHI2/NDF") plot.DrawText(0.7, 0.3, "\chi^{2}/ndf = " + str(round(chi2, 3))) for i in range(2): plot.add_legend(reference_subplot=2, pos=1, width=0.5, height=0.03) plot.legend(i + 2).add_entry(0, "data_obs", "Data", 'PE') plot.legend(i + 2).setNColumns(4) plot.legend(2).Draw() plot.legend(3).setAlpha(0.0) plot.legend(3).Draw() # draw additional labels plot.DrawCMS() if "2016" in args.era: plot.DrawLumi("35.9 fb^{-1} (2016, 13 TeV)") elif "2017" in args.era: plot.DrawLumi("41.5 fb^{-1} (2017, 13 TeV)") elif "2018" in args.era: plot.DrawLumi("57.9 fb^{-1} (2018, 13 TeV)") else: logger.critical("Era {} is not implemented.".format(args.era)) raise Exception posChannelCategoryLabelLeft = None plot.DrawChannelCategoryLabel( "%s, %s" % (channel_dict[channel], category_dict[category]), begin_left=posChannelCategoryLabelLeft) # save plot postfix = "prefit" if "prefit" in args.input else "postfit" if "postfit" in args.input else "undefined" plot.save("%s_plots/%s_%s_%s_%s.%s" % (args.era, args.era, channel, args.gof_variable if args.gof_variable is not None else category if tranche == None else "_".join([category, tranche]), postfix, "png" if args.png else "pdf")) plots.append( plot ) # work around to have clean up seg faults only at the end of the script
def main(args): channel_categories = { "et": ["0jet", "boosted", "vbf"], "mt": ["0jet", "boosted", "vbf"], "tt": ["0jet", "boosted", "vbf"] } channel_dict = { "ee": "ee", "em": "e#mu", "et": "e#tau_{h}", "mm": "#mu#mu", "mt": "#mu#tau_{h}", "tt": "#tau_{h}#tau_{h}" } category_dict = {"0jet": "0 Jet", "boosted": "Boosted", "vbf": "VBF"} bkg_processes = ["EWK", "QCD", "VV", "W", "TTT", "TTJ", "ZJ", "ZL", "ZTT"] sig_processes = ["ggH", "qqH"] legend_bkg_processes = copy.deepcopy(bkg_processes) legend_bkg_processes.reverse() rootfile = rootfile_parser.Rootfile_parser(args.input) plots = [] for channel in args.channels: for category in channel_categories[channel]: plot = dd.Plot([], "ModTDR", r=0.04, l=0.14, width=1200, height=600) for process in bkg_processes: plot.add_hist(rootfile.get(channel, category, process), process) plot.setGraphStyle(process, "hist", fillcolor=styles.color_dict[process]) for process in sig_processes: plot.add_hist(rootfile.get(channel, category, process), process) plot.setGraphStyle(process, "hist", fillcolor=styles.color_dict[process]) plot.add_hist(rootfile.get(channel, category, process), process + "_line") plot.setGraphStyle(process + "_line", "hist", linecolor=styles.color_dict[process], linewidth=3) plot.add_hist(rootfile.get(channel, category, "data_obs"), "data_obs") plot.setGraphStyle("data_obs", "e0") plot.add_hist(rootfile.get(channel, category, "TotalBkg"), "total_bkg") plot.setGraphStyle("total_bkg", "e2", markersize=0, fillcolor=styles.color_dict["unc"], linecolor=0, fillstyle=3001 if args.png else 1001) plot.create_stack(bkg_processes + sig_processes, "stack") plot.subplot(0).setYlims( 0.1, 10 * plot.subplot(0).get_hist("total_bkg").GetMaximum()) plot.subplot(0).setXlabel(args.x_label) plot.subplot(0).setYlabel("N_{events}") plot.subplot(0).setLogY() plot.subplot(0).Draw( ["stack", "qqH_line", "ggH_line", "total_bkg", "data_obs"]) plot.DrawCMS() plot.DrawLumi("35.9 fb^{-1} (13 TeV)") plot.DrawChannelCategoryLabel( "%s, %s" % (channel_dict[channel], category_dict[category])) prefix = "prefit" if "prefit" in args.input else "postfit" if "postfit" in args.input else "undefined" plot.save( "plots/%s_%s_%s.%s" % (prefix, channel, category, 'png' if args.png else 'pdf')) plots.append( plot ) # work around to have clean up seg faults only at the end of the script
def main(args): if args.control_variable is None: channel_categories = { #"et": ["nobtag_tight", "btag_tight", "nobtag_loosemt", "nobtag_tight"] "et": ["10", "11", "12", "13", "14", "15", "16", "17", "18", "32", "33", "35", "36"], #"mt": ["nobtag_tight", "btag_tight", "nobtag_loosemt", "nobtag_tight"] "mt": ["10", "11", "12", "13", "14", "15", "16", "17", "18", "32", "33", "35", "36"], #"tt": ["nobtag", "btag"] "tt": ["10", "11", "12", "13", "14", "15", "16", "17", "32", "35"], "em": ["2", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "32", "33", "34", "35", "36", "37"] } if args.model_independent: channel_categories = { #"et": ["nobtag_tight", "btag_tight", "nobtag_loosemt", "nobtag_tight"] "et": ["32", "33", "35", "36"], #"mt": ["nobtag_tight", "btag_tight", "nobtag_loosemt", "nobtag_tight"] "mt": ["32", "33", "35", "36"], #"tt": ["nobtag", "btag"] "tt": ["32", "35"], "em": ["2","32", "33", "34", "35", "36", "37"] } channel_categories = { "et": ["32", "35"], "mt": ["32", "35"], "tt": ["32", "35"], # "em": ["32", "33", "35", "36"], "em": ["33", "36"], "lt": ["32", "35"], } else: channel_categories = { "et": ["100"], "mt": ["100"], "tt": ["100"], "em": ["100"] } channel_dict = { "ee": "ee", "em": "e#mu", "et": "e#tau_{h}", "mm": "#mu#mu", "mt": "#mu#tau_{h}", "lt": "#mu_{}#tau_{h}+e_{}#tau_{h}", # "lt": "#ell#tau_{h}", "tt": "#tau_{h}#tau_{h}" } if args.control_variable != None: category_dict = {"100": "inclusive"} else: category_dict = { "et": { "1": "2D ggH/qqH category", "13": "tt", "15": "zll", "16": "misc", "20": "Genuine #tau", "21": "Jet #rightarrow #tau_{h}", "32": "No b tag Tight-m_{T}", "33": "No b tag Loose-m_{T}", "35": "b tag Tight-m_{T}", "36": "b tag Loose-m_{T}", }, "mt": { "1": "2D ggH/qqH category", "13": "tt", "15": "zll", "16": "misc", "20": "Genuine #tau", "21": "Jet #rightarrow #tau_{h}", "32": "No b tag Tight-m_{T}", "33": "No b tag Loose-m_{T}", "35": "b tag Tight-m_{T}", "36": "b tag Loose-m_{T}", }, "lt": { "1": "2D ggH/qqH category", "13": "tt", "15": "zll", "16": "misc", "20": "Genuine #tau", "21": "Jet #rightarrow #tau_{h}", "32": "No b tag Tight-m_{T}", "33": "No b tag Loose-m_{T}", "35": "b tag Tight-m_{T}", "36": "b tag Loose-m_{T}", }, "tt": { "1": "2D ggH/qqH category", "16": "misc", "20": "Genuine #tau", "21": "Jet #rightarrow #tau_{h}", "32": "No b tag", "35": "b tag", }, "em": { "1": "2D ggH/qqH category", "2": "D_{#lower[-0.2]{#zeta}} < -35 GeV", "13": "tt", "14": "qcd", "16": "misc", "19": "diboson", "20": "Genuine #tau", "32": "No b tag, High-D_{#lower[-0.2]{#zeta}}", "33": "No b tag, Medium-D_{#lower[-0.2]{#zeta}}", "34": "No b tag, Low-D_{#lower[-0.2]{#zeta}}", "35": "b tag, High-D_{#lower[-0.2]{#zeta}}", "36": "b tag, Medium-D_{#lower[-0.2]{#zeta}}", "37": "b tag, Low-D_{#lower[-0.2]{#zeta}}", }, } if args.linear == True: split_value = 0 else: if args.normalize_by_bin_width: split_value = 1 else: split_value = 101 split_dict = {c: split_value for c in ["et", "mt", "tt", "em", "lt"]} bkg_processes = [ "HSM", "VVL", "TTL", "ZL", "jetFakes", "EMB" ] if args.combine_backgrounds: bkg_processes = [ "other", "TTL", "jetFakes", "EMB" ] if not args.fake_factor and args.embedding: bkg_processes = [ "QCD", "VVJ", "VVL", "W", "TTJ", "TTL", "ZJ", "ZL", "EMB" ] if not args.embedding and args.fake_factor: bkg_processes = [ "VVT", "VVJ", "TTT", "TTJ", "ZJ", "ZL", "jetFakes", "ZTT" ] if not args.embedding and not args.fake_factor: bkg_processes = [ "QCD", "W", "VVJ", "VVL", "VVT", "TTJ", "TTL", "TTT", "ZJ", "ZL", "ZTT" # "QCD", "VVT", "VVJ", "W", "TTT", "TTJ", "ZJ", "ZL", "ZTT" ] all_bkg_processes = [b for b in bkg_processes] legend_bkg_processes = copy.deepcopy(bkg_processes) legend_bkg_processes.reverse() if "2016" in args.era: era = "_2016" elif "2017" in args.era: era = "_2017" elif "2018" in args.era: era = "_2018" elif "combined" in args.era: era = "" else: logger.critical("Era {} is not implemented.".format(args.era)) raise Exception plots = [] for channel in args.channels: if "em" in channel: if not args.embedding: bkg_processes = [ "HSM", "QCDMC", "VVT", "VVL", "W", "TTT", "TTL", "ZL", "ZTT" ] else: bkg_processes = [ "HSM", "QCD", "EWK", "TTL", "ZL", "EMB" ] if args.combine_backgrounds: bkg_processes = [ "other", "QCD", "TTL", "EMB" ] for category in channel_categories[channel]: # Set split value to 101 for no b-tag categories to make # transition between scales smoother if int(category) < 35 and int(category) > 10: split_dict[channel] += 100 if args.control_region and category != "2": continue rootfile = rootfile_parser.Rootfile_parser(args.input, mode="CombineHarvesterMerged") legend_bkg_processes = copy.deepcopy(bkg_processes) legend_bkg_processes.reverse() # create plot if args.linear == True: plot = dd.Plot( [0.3, [0.3, 0.28]], "ModTDR", r=0.04, l=0.14, width=600) else: plot = dd.Plot( [0.55, [0.3, 0.28]], style="ModTDR", invert_pad_creation=True, r=0.04, l=0.14, width=600) # get background histograms for process in bkg_processes: if process in ["jetFakes", "jetFakesEMB"] and channel == "tt": jetfakes_hist = rebin_hist_for_logX(rootfile.get(era, channel, category, process).Clone(), xlow=30.) jetfakes_hist.Add(rebin_hist_for_logX(rootfile.get(era, channel, category, "wFakes"), xlow=30.)) plot.add_hist(jetfakes_hist, process, "bkg") elif process in ["HSM"]: if channel == "em": hsm_hist = rebin_hist_for_logX(rootfile.get(era, channel, category, "ggH125").Clone(), xlow=30.) hsm_hist.Add(rebin_hist_for_logX(rootfile.get(era, channel, category, "qqH125"), xlow=30.)) hsm_hist.Add(rebin_hist_for_logX(rootfile.get(era, channel, category, "bbH125"), xlow=30.)) hsm_hist.Add(rebin_hist_for_logX(rootfile.get(era, channel, category, "ggHWW125"), xlow=30.)) hsm_hist.Add(rebin_hist_for_logX(rootfile.get(era, channel, category, "qqHWW125"), xlow=30.)) hsm_hist.Add(rebin_hist_for_logX(rootfile.get(era, channel, category, "ZHWW125"), xlow=30.)) hsm_hist.Add(rebin_hist_for_logX(rootfile.get(era, channel, category, "WHWW125"), xlow=30.)) plot.add_hist(hsm_hist, process, "bkg") else: hsm_hist = rebin_hist_for_logX(rootfile.get(era, channel, category, "ggH125").Clone(), xlow=30.) hsm_hist.Add(rebin_hist_for_logX(rootfile.get(era, channel, category, "qqH125"), xlow=30.)) hsm_hist.Add(rebin_hist_for_logX(rootfile.get(era, channel, category, "bbH125"), xlow=30.)) plot.add_hist(hsm_hist, process, "bkg") elif process == "EWK" and channel == "em": ewk_hist = rebin_hist_for_logX(rootfile.get(era, channel, category, "W").Clone(), xlow=30.) ewk_hist.Add(rebin_hist_for_logX(rootfile.get(era, channel, category, "VVL"), xlow=30.)) plot.add_hist(ewk_hist, process, "bkg") elif process in ["HWW"]: hww_hist = rebin_hist_for_logX(rootfile.get(era, channel, category, "ggHWW125").Clone(), xlow=30.) hww_hist.Add(rebin_hist_for_logX(rootfile.get(era, channel, category, "qqHWW125"), xlow=30.)) hww_hist.Add(rebin_hist_for_logX(rootfile.get(era, channel, category, "ZHWW125"), xlow=30.)) hww_hist.Add(rebin_hist_for_logX(rootfile.get(era, channel, category, "WHWW125"), xlow=30.)) plot.add_hist(hww_hist, process, "bkg") elif process == "other": if channel == "em": other_hist = rebin_hist_for_logX(rootfile.get(era, channel, category, "W").Clone(), xlow=30.) other_hist.Add(rebin_hist_for_logX(rootfile.get(era, channel, category, "VVL"), xlow=30.)) other_hist.Add(rebin_hist_for_logX(rootfile.get(era, channel, category, "ZL"), xlow=30.)) other_hist.Add(rebin_hist_for_logX(rootfile.get(era, channel, category, "ggH125"), xlow=30.)) other_hist.Add(rebin_hist_for_logX(rootfile.get(era, channel, category, "qqH125"), xlow=30.)) other_hist.Add(rebin_hist_for_logX(rootfile.get(era, channel, category, "bbH125"), xlow=30.)) other_hist.Add(rebin_hist_for_logX(rootfile.get(era, channel, category, "ggHWW125"), xlow=30.)) other_hist.Add(rebin_hist_for_logX(rootfile.get(era, channel, category, "qqHWW125"), xlow=30.)) other_hist.Add(rebin_hist_for_logX(rootfile.get(era, channel, category, "ZHWW125"), xlow=30.)) other_hist.Add(rebin_hist_for_logX(rootfile.get(era, channel, category, "WHWW125"), xlow=30.)) plot.add_hist(other_hist, process, "bkg") elif channel in ["et", "mt", "lt", "tt"]: other_hist = rebin_hist_for_logX(rootfile.get(era, channel, category, "VVL").Clone(), xlow=30.) other_hist.Add(rebin_hist_for_logX(rootfile.get(era, channel, category, "ZL"), xlow=30.)) other_hist.Add(rebin_hist_for_logX(rootfile.get(era, channel, category, "ggH125"), xlow=30.)) other_hist.Add(rebin_hist_for_logX(rootfile.get(era, channel, category, "qqH125"), xlow=30.)) other_hist.Add(rebin_hist_for_logX(rootfile.get(era, channel, category, "bbH125"), xlow=30.)) plot.add_hist(other_hist, process, "bkg") else: #print era, channel, category, process plot.add_hist( rebin_hist_for_logX(rootfile.get(era, channel, category, process), xlow=30.), process, "bkg") plot.setGraphStyle( process, "hist", fillcolor=styles.color_dict[process]) # get signal histograms if int(category) > 30: plot_idx_to_add_signal = [0,2] if args.linear else [1,2] for i in plot_idx_to_add_signal: if args.model_independent: ggH_hist = rebin_hist_for_logX(rootfile.get(era, channel, category, "ggh_t"), xlow=30.).Clone() ggH_hist.Add(rebin_hist_for_logX(rootfile.get(era, channel, category, "ggh_i"), xlow=30.)) ggH_hist.Add(rebin_hist_for_logX(rootfile.get(era, channel, category, "ggh_b"), xlow=30.)) plot.subplot(i).add_hist(ggH_hist, "ggH") # bbH signal bbH_hist = rebin_hist_for_logX(rootfile.get(era, channel, category, "bbh"), xlow=30.) # if args.cross_section_bbh != args.cross_section_ggh: # print("Scaling bbH by {}".format(float(args.cross_section_bbh)/float(args.cross_section_ggh))) # bbH_hist.Scale(float(args.cross_section_bbh)/float(args.cross_section_ggh)) if args.cross_section_bbh != args.cross_section_ggh: print("Scaling bbH by {}".format(float(args.cross_section_bbh)/0.0030584)) bbH_hist.Scale(float(args.cross_section_bbh)/0.0030584) plot.subplot(i).add_hist(bbH_hist, "bbH") # vector leptoquark signal VLQ_hist = rebin_hist_for_logX(rootfile.get(era, channel, category, "VLQ_s"), xlow=30.).Clone() VLQ_hist.Add(rebin_hist_for_logX(rootfile.get(era, channel, category, "VLQ_i"), xlow=30.)) plot.subplot(i).add_hist( VLQ_hist, "VLQ") else: plot.subplot(i).add_hist( rebin_hist_for_logX(rootfile.get(era, channel, category, "TotalSig"), xlow=30.), "mssm_sig") # get observed data and total background histograms plot.add_hist( rebin_hist_for_logX(rootfile.get(era, channel, category, "data_obs"), xlow=30.), "data_obs") plot.add_hist( rebin_hist_for_logX(rootfile.get(era, channel, category, "TotalBkg"), xlow=30.), "total_bkg") plot.subplot(0).setGraphStyle("data_obs", "e0") if args.model_independent: if int(category) > 30: plot.subplot(0 if args.linear else 1).setGraphStyle( "ggH", "hist", linecolor=styles.color_dict["ggH"], linewidth=2) plot.subplot(0 if args.linear else 1).setGraphStyle( "bbH", "hist", linecolor=styles.color_dict["bbH"], linewidth=2) plot.subplot(0 if args.linear else 1).setGraphStyle( "VLQ", "hist", linecolor=styles.color_dict["VLQ"], linewidth=2) else: plot.subplot(0 if args.linear else 1).setGraphStyle( "mssm_sig", "hist", linecolor=styles.color_dict["bbH"], linewidth=2) plot.setGraphStyle( "total_bkg", "e2", markersize=0, fillcolor=styles.color_dict["unc"], linecolor=0) # assemble ratio if args.model_independent: if args.b_only_fit is not None: rootfile_b_only = rootfile_parser.Rootfile_parser(args.b_only_fit, mode="CombineHarvesterMerged") plot.subplot(2).add_hist( rebin_hist_for_logX(rootfile_b_only.get(era, channel, category, "TotalBkg"), xlow=30.), "total_bkg_b_only") plot.subplot(2).setGraphStyle( "total_bkg_b_only", "hist", linecolor=ROOT.kBlue, linewidth=2, linestyle=2) if int(category) > 30: bkg_ggH = plot.subplot(2).get_hist("ggH") bkg_bbH = plot.subplot(2).get_hist("bbH") bkg_VLQ = plot.subplot(2).get_hist("VLQ") bkg_ggH.Add(plot.subplot(2).get_hist("total_bkg")) bkg_bbH.Add(plot.subplot(2).get_hist("total_bkg")) bkg_VLQ.Add(plot.subplot(2).get_hist("total_bkg")) plot.subplot(2).add_hist(bkg_ggH, "bkg_ggH") plot.subplot(2).add_hist(bkg_bbH, "bkg_bbH") plot.subplot(2).add_hist(bkg_VLQ, "bkg_VLQ") plot.subplot(2).setGraphStyle( "bkg_ggH", "hist", linecolor=styles.color_dict["ggH"], linewidth=2) plot.subplot(2).setGraphStyle( "bkg_bbH", "hist", linecolor=styles.color_dict["bbH"], linewidth=2) plot.subplot(2).setGraphStyle( "bkg_VLQ", "hist", linecolor=styles.color_dict["VLQ"], linewidth=2) to_normalize = ["total_bkg", "bkg_ggH", "bkg_bbH", "bkg_VLQ", "data_obs" ] if args.b_only_fit is not None: to_normalize.append("total_bkg_b_only") plot.subplot(2).normalize(to_normalize, "total_bkg") else: to_normalize = ["total_bkg", "data_obs" ] if args.b_only_fit is not None: to_normalize.append("total_bkg_b_only") plot.subplot(2).normalize(to_normalize, "total_bkg") else: bkg_sig = plot.subplot(2).get_hist("mssm_sig") bkg_sig.Add(plot.subplot(2).get_hist("total_bkg")) plot.subplot(2).add_hist(bkg_sig, "bkg_mssm_sig") plot.subplot(2).add_hist(bkg_sig, "bkg_mssm_sig_top") plot.subplot(2).setGraphStyle( "bkg_mssm_sig", "hist", linecolor=styles.color_dict["bbH"], linewidth=3) plot.subplot(2).setGraphStyle( "bkg_mssm_sig_top", "hist", linecolor=0) plot.subplot(2).normalize([ "total_bkg", "bkg_mssm_sig", "bkg_mssm_sig_top", "data_obs" ], "total_bkg") # stack background processes plot.create_stack(bkg_processes, "stack") # Use binning from data histogram to get bin widths for the normalization. hist_for_rebinning = rootfile.get(era, channel, category, "data_obs") widths = [] for i in range(hist_for_rebinning.GetNbinsX()): widths.append(hist_for_rebinning.GetBinWidth(i+1)) # normalize stacks by bin-width if args.normalize_by_bin_width: plot.subplot(0).normalizeByBinWidth(widths=widths) plot.subplot(1).normalizeByBinWidth(widths=widths) if args.x_range is not None: for i in range(3): plot.subplot(i).setXlims(*args.x_range) # set axes limits and labels if args.x_range is not None: range_hist = plot.subplot(0).get_hist("data_obs").Clone() range_hist.GetXaxis().SetRangeUser(*args.x_range) plot.subplot(0).setYlims( split_dict[channel], max(1.8 * range_hist.GetMaximum(), split_dict[channel] * 2)) # max(1, # split_dict[channel] * 2)) else: plot.subplot(0).setYlims( split_dict[channel], max(1.4 * plot.subplot(0).get_hist("data_obs").GetMaximum(), split_dict[channel] * 2)) if channel == "em": if int(category) == 36: plot.subplot(2).setYlims(0.2, 2.5) else: plot.subplot(2).setYlims(0.5, 2.0) elif channel == "tt": plot.subplot(2).setYlims(0.7, 2.5) else: if int(category) == 35: plot.subplot(2).setYlims(0.5, 2.2) else: plot.subplot(2).setYlims(0.7, 2.2) ROOT.TGaxis.SetMaxDigits(4) if args.linear != True: # plot.subplot(1).setYlims(1.e-4, split_dict[channel]) plot.subplot(1).setYlims(min(1.e-3, plot.subplot(1).get_hist("data_obs").GetMinimum()/10., plot.subplot(1).get_hist("total_bkg").GetMinimum()/10.), split_dict[channel]) plot.subplot(1).setLogY() if int(category) > 30 or int(category) == 2: plot.subplot(1).setLogX() plot.subplot(1).setYlabel( "") # otherwise number labels are not drawn on axis if args.control_variable != None: if args.control_variable in styles.x_label_dict[args.channels[0]]: x_label = styles.x_label_dict[args.channels[0]][ args.control_variable] else: x_label = args.control_variable plot.subplot(2).setXlabel(x_label) else: if int(category) > 30 or int(category) == 2: plot.subplot(2).setXlabel("m_{T}^{tot} (GeV)") else: plot.subplot(2).setXlabel("SVFit m_{#tau#tau} (GeV)") if args.normalize_by_bin_width: if int(category) > 30 or int(category) == 2: plot.subplot(0).setYlabel("dN/dm_{T}^{tot} (1/GeV)") # plot.subplot(0).setYlabel("< Events / GeV >") else: plot.subplot(0).setYlabel("dN/dm_{#tau#tau} (1/GeV)") else: plot.subplot(0).setYlabel("Events / {} GeV".format(plot.subplot(0).get_hist("total_bkg").GetBinWidth(1))) plot.subplot(2).setYlabel("Obs./Exp.") if (int(category) > 30 or int(category) == 2) and args.x_range is None: plot.subplot(0).setLogX() plot.subplot(2).setLogX() #plot.scaleXTitleSize(0.8) #plot.scaleXLabelSize(0.8) #plot.scaleYTitleSize(0.8) plot.scaleYLabelSize(0.8) #plot.scaleXLabelOffset(2.0) plot.scaleYTitleOffset(1.05) if channel == "em": if category == "32": plot.subplot(0).setNYdivisions(3, 5) elif category == "33": plot.subplot(0).setNYdivisions(4, 5) if int(category) < 35 and int(category) > 10: plot.subplot(1).setNYdivisions(3, 5) plot.subplot(2).setNYdivisions(3, 5) # draw subplots. Argument contains names of objects to be drawn in corresponding order. # procs_to_draw = ["stack", "total_bkg", "ggH", "ggH_top", "bbH", "bbH_top", "data_obs"] if args.linear else ["stack", "total_bkg", "data_obs"] if category == "2": procs_to_draw = ["stack", "total_bkg", "data_obs"] if args.linear else ["stack", "total_bkg", "data_obs"] else: if args.model_independent: procs_to_draw = ["stack", "total_bkg", "ggH", "bbH", "data_obs"] if args.linear else ["stack", "total_bkg", "data_obs"] else: procs_to_draw = ["stack", "total_bkg", "mssm_sig", "data_obs"] if args.linear else ["stack", "total_bkg", "data_obs"] if args.blinded: procs_to_draw.remove("data_obs") plot.subplot(0).Draw(procs_to_draw) if not args.linear: # plot.subplot(1).Draw([ # "stack", "total_bkg", "ggH", "bbH", # "ggH_top", "bbH_top", # "data_obs" # ]) if category == "2": plot.subplot(1).Draw([ "stack", "total_bkg", "data_obs" ]) else: if args.model_independent: procs_to_draw = ["stack", "total_bkg", "ggH", "bbH", "VLQ", "data_obs"] else: procs_to_draw = ["stack", "total_bkg", "mssm_sig", "data_obs"] if args.blinded: procs_to_draw.remove("data_obs") plot.subplot(1).Draw(procs_to_draw) plot.subplot(0).remove_lower_x_ticks() plot.subplot(1)._pad.SetTickx(0) plot.add_line(0, 30, split_dict[channel], 6000, split_dict[channel], linestyle=1, color=ROOT.kGray+2) for line in plot._lines: line.Draw() label2 = ROOT.TLatex() label2.SetNDC() label2.SetTextAngle(270) label2.SetTextColor(ROOT.kGray+2) label2.SetTextSize(0.030) label2.DrawLatex(0.97, 0.54, "log scale") label2.DrawLatex(0.97, 0.75, "linear scale") # Redraw upper x axis to have good looking plot plot.subplot(0)._pad.cd() y_max = 1.4 * plot.subplot(0).get_hist("data_obs").GetMaximum() axis = ROOT.TGaxis(30., y_max, 5000., y_max, 30., 5000., 510, "GBSU-") axis.SetTickLength(0.02) axis.SetTickSize(0.02) axis.Draw() # Draw upper panel after lower panel of split to ensure full # display of the data points if category == "2": plot.subplot(2).Draw([ "total_bkg", "data_obs" ]) else: if args.model_independent: if args.b_only_fit is not None: if int(category) > 30: procs_to_draw = ["total_bkg_b_only", "total_bkg", "bkg_ggH", "bkg_bbH", "bkg_VLQ", "data_obs"] else: procs_to_draw = ["total_bkg_b_only", "total_bkg", "data_obs"] else: if int(category) > 30: procs_to_draw = ["total_bkg", "bkg_ggH", "bkg_bbH", "bkg_VLQ", "data_obs"] else: procs_to_draw = ["total_bkg", "data_obs"] else: procs_to_draw = ["total_bkg", "bkg_mssm_sig", "data_obs"] if args.blinded: procs_to_draw.remove("data_obs") plot.subplot(2).Draw(procs_to_draw) # create legends if int(category) < 30 and int(category) > 2: plot.add_legend(width=0.38, height=0.30) else: # plot.add_legend(width=0.60, height=0.20, pos=1) plot.add_legend(width=0.40, height=0.33, pos=3) # plot.add_legend(width=0.6, height=0.15) for process in legend_bkg_processes: if process == "HSM" and channel == "em": plot.legend(0).add_entry( 0, process, "H(125 GeV)", "f") else: plot.legend(0).add_entry( 0, process, styles.legend_label_dict[process.replace("TTL", "TT").replace("VVL", "VV")], 'f') if not args.blinded: plot.legend(0).add_entry(0, "data_obs", "Observed", 'PE') plot.legend(0).add_entry(0, "total_bkg", "Bkg. unc.", 'f') if args.control_region and category == "2": pass else: if args.model_independent: if int(category) > 30: mass_str = "%s GeV" % args.mass if float(args.mass) < 1000 else "{:.1f} TeV".format(float(args.mass) / 1000) ggH_xs_str = "%s pb" % args.cross_section_ggh if float(args.cross_section_ggh) > 1e-2 else "{} fb".format(float(args.cross_section_ggh) * 1000) bbH_xs_str = "%s pb" % args.cross_section_bbh if float(args.cross_section_bbh) > 1e-2 else "{} fb".format(float(args.cross_section_bbh) * 1000) plot.legend(0).add_entry(0 if args.linear else 1, "ggH", "#splitline{gg#phi @ %s}{(m_{#phi} = %s)}" % (ggH_xs_str, mass_str), 'l') plot.legend(0).add_entry(0 if args.linear else 1, "bbH", "#splitline{bb#phi @ %s}{(m_{#phi} = %s)}" % (bbH_xs_str, mass_str), 'l') plot.legend(0).add_entry(0 if args.linear else 1, "", "", '') plot.legend(0).add_entry(0 if args.linear else 1, "VLQ", "#splitline{VLQ, g_{U} = %s}{(m_{U} = %s TeV)}" % (1.2, 1), 'l') else: plot.legend(0).add_entry(0 if args.linear else 1, "mssm_sig", "#splitline{H #rightarrow #tau#tau}{#splitline{(m_{A}= %s GeV,}{ tan #beta = %s)}}" %(args.mass, args.tanbeta), 'l') plot.legend(0).setNColumns(2) # plot.legend(0).scaleTextSize(1.05) plot.legend(0).Draw() # FIXME: Legend for ratio plot temporarily disabled. if channel != "em": plot.add_legend( reference_subplot=2, pos=1, width=0.45, height=0.10) else: plot.add_legend( reference_subplot=2, pos=1, width=0.75, height=0.05) if not args.blinded: plot.legend(1).add_entry(0, "data_obs", "Observed", 'PE') plot.legend(1).add_entry(0, "total_bkg", "Bkg. unc.", 'f') if args.b_only_fit: plot.legend(1).add_entry(2, "total_bkg_b_only", "Bkg. only fit", "l") if args.control_region and category == "2": pass else: if args.model_independent: if int(category) > 30: plot.legend(1).add_entry(0 if args.linear else 1, "ggH", "gg#phi", 'l') plot.legend(1).add_entry(0 if args.linear else 1, "bbH", "bb#phi", 'l') plot.legend(1).add_entry(0 if args.linear else 1, "VLQ", "VLQ", 'l') else: plot.legend(1).add_entry(0 if args.linear else 1, "mssm_sig", "H+bkg.", 'l') if channel != "em": if not args.blinded: plot.legend(1).add_entry(0, "data_obs", "Observed", 'PE') plot.legend(1).add_entry(0, "total_bkg", "Bkg. unc.", 'f') if args.b_only_fit is not None: plot.legend(1).add_entry(2, "total_bkg_b_only", "Bkg. only fit", "l") plot.legend(1).setNColumns(3) else: plot.legend(1).setNColumns(5) if args.b_only_fit is not None: plot.legend(1).setNColumns(6) # plot.legend(1).scaleTextSize(1.05) plot.legend(1).Draw() # draw additional labels plot.DrawCMS(cms_sub="") if "2016" in args.era: plot.DrawLumi("36.3 fb^{-1} (2016, 13 TeV)") elif "2017" in args.era: plot.DrawLumi("41.5 fb^{-1} (2017, 13 TeV)") elif "2018" in args.era: plot.DrawLumi("59.7 fb^{-1} (2018, 13 TeV)") elif "combined" in args.era: plot.DrawLumi("138 fb^{-1} (13 TeV)") else: logger.critical("Era {} is not implemented.".format(args.era)) raise Exception posChannelCategoryLabelLeft = None plot.DrawChannelCategoryLabel( "#font[42]{%s, %s}" % (channel_dict[channel], category_dict[channel][category]), begin_left=posChannelCategoryLabelLeft) # save plot if not os.path.exists(args.output_dir): os.makedirs(args.output_dir) postfix = "prefit" if "prefit" in args.input else "postfit" if "postfit" in args.input else "undefined" plot.save("%s/%s_%s_%s_%s.%s" % (args.output_dir, args.era, channel, args.control_variable if args.control_variable is not None else category, postfix, "png" if args.png else "pdf")) # Undo switch of split value if int(category) < 35 and int(category) > 10: split_dict[channel] -= 100 plots.append( plot ) # work around to have clean up seg faults only at the end of the script
def main(args): channel_dict = { "em": "e#mu", "et": "e#tau_{h}", "mt": "#mu#tau_{h}", "tt": "#tau_{h}#tau_{h}" } signal_categories = { "2": "#leq 1 jet p_{T}^{H} [200,#infty)", "3": "0 jet p_{T}^{H} [0,200)", "4": "1 jet p_{T}^{H} [0,120)", "5": "1 jet p_{T}^{H} [120,200)", "6": "#geq 2 jet m_{jj} [0,350)", "7": "#geq 2 jet m_{jj} [350,#infty) p_{T}^{H} [0,200)", "8": "#geq 2 jet m_{jj} [350,#infty) p_{T}^{H} [200,#infty)", } category_dict = { "em": signal_categories.copy(), "et": signal_categories.copy(), "mt": signal_categories.copy(), "tt": signal_categories.copy(), } category_dict["em"].update({"1" : "t#bar{t} control"}) category_dict["et"].update({"1" : "W + jets control"}) category_dict["mt"].update({"1" : "W + jets control"}) bkg_processes = ["VVL", "TTL", "ZL", "jetFakes", "EMB"] bkg_processes_em = ["VVL", "TTL", "ZL", "W", "QCD", "EMB"] if "2016" in args.era: era = "Run2016" elif "2017" in args.era: era = "Run2017" elif "2018" in args.era: era = "Run2018" else: logger.critical("Era {} is not implemented.".format(args.era)) raise Exception plots = [] for channel in sorted(channel_dict): for category in sorted(category_dict[channel]): print "channel, category",channel,category rootfile = rootfile_parser.Rootfile_parser(args.input) rootfile._type = args.shape_type if channel == "em": bkgs = bkg_processes_em else: bkgs = bkg_processes legend_bkg_processes = copy.deepcopy(bkgs) legend_bkg_processes.reverse() # create plot width = 600 plot = dd.Plot([0.3, [0.3, 0.28]], "ModTDR", r=0.04, l=0.14, width=width) print "plot created" # get background histograms for process in bkgs: try: bg = rootfile.get(era, channel, category, process) if isinstance(bg,ROOT.TH1): plot.add_hist(bg, process, "bkg") plot.setGraphStyle(process, "hist", fillcolor=styles.color_dict[process]) except: pass print "got bgs" # get signal histograms plot_idx_to_add_signal = [0,2] for i in plot_idx_to_add_signal: try: plot.subplot(i).add_hist(rootfile.get(era, channel, category, "ggH125"), "ggH") plot.subplot(i).add_hist(rootfile.get(era, channel, category, "ggH125"), "ggH_top") plot.subplot(i).add_hist(rootfile.get(era, channel, category, "qqH125"), "qqH") plot.subplot(i).add_hist(rootfile.get(era, channel, category, "qqH125"), "qqH_top") if isinstance(rootfile.get(era, channel, category, "ZH125"), ROOT.TH1): VHhist = rootfile.get(era, channel, category, "ZH125").Clone("VH") WHhist = rootfile.get(era, channel, category, "WH125") if isinstance(WHhist,ROOT.TH1) and VHhist: VHhist.Add(WHhist) elif WHhist: VHhist = WHhist plot.subplot(i).add_hist(VHhist, "VH") plot.subplot(i).add_hist(VHhist, "VH_top") if isinstance(rootfile.get(era, channel, category, "ttH125"), ROOT.TH1): plot.subplot(i).add_hist(rootfile.get(era, channel, category, "ttH125"), "ttH") plot.subplot(i).add_hist(rootfile.get(era, channel, category, "ttH125"), "ttH_top") ggHWWhist = rootfile.get(era, channel, category, "ggHWW125") qqHWWhist = rootfile.get(era, channel, category, "qqHWW125") if isinstance(ggHWWhist, ROOT.TH1): HWWhist = rootfile.get(era, channel, category, "ggHWW125").Clone("ggHWW125") if isinstance(qqHWWhist,ROOT.TH1) and isinstance(HWWhist,ROOT.TH1): HWWhist.Add(qqHWWhist) elif isinstance(qqHWWhist,ROOT.TH1): HWWhist = qqHWWhist if isinstance(HWWhist,ROOT.TH1): plot.subplot(i).add_hist(HWWhist, "HWW") plot.subplot(i).add_hist(HWWhist, "HWW_top") except: pass print "got signals" # get observed data and total background histograms plot.add_hist(rootfile.get(era, channel, category, "data_obs"), "data_obs") total_bkg = rootfile.get(era, channel, category, "TotalBkg") ggHHist = rootfile.get(era, channel, category, "ggH125") qqHHist = rootfile.get(era, channel, category, "qqH125") plot.add_hist(total_bkg, "total_bkg") plot.subplot(0).setGraphStyle("data_obs", "e0") plot.subplot(0).setGraphStyle("ggH", "hist", linecolor=styles.color_dict["ggH"], linewidth=3) plot.subplot(0).setGraphStyle("ggH_top", "hist", linecolor=0) plot.subplot(0).setGraphStyle("qqH", "hist", linecolor=styles.color_dict["qqH"], linewidth=3) plot.subplot(0).setGraphStyle("qqH_top", "hist", linecolor=0) plot.subplot(0).setGraphStyle("VH", "hist", linecolor=styles.color_dict["VH"], linewidth=3) plot.subplot(0).setGraphStyle("VH_top", "hist", linecolor=0) plot.subplot(0).setGraphStyle("ttH", "hist", linecolor=styles.color_dict["ttH"], linewidth=3) plot.subplot(0).setGraphStyle("ttH_top", "hist", linecolor=0) plot.subplot(0).setGraphStyle("HWW", "hist", linecolor=styles.color_dict["HWW"], linewidth=3) plot.subplot(0).setGraphStyle("HWW_top", "hist", linecolor=0) plot.setGraphStyle("total_bkg", "e2", markersize=0, fillcolor=styles.color_dict["unc"], linecolor=0) print "data + signal bg" # assemble ratio bkg_ggH = plot.subplot(2).get_hist("ggH") bkg_qqH = plot.subplot(2).get_hist("qqH") bkg_ggH.Add(plot.subplot(2).get_hist("total_bkg")) if bkg_qqH: bkg_qqH.Add(plot.subplot(2).get_hist("total_bkg")) plot.subplot(2).add_hist(bkg_ggH, "bkg_ggH") plot.subplot(2).add_hist(bkg_ggH, "bkg_ggH_top") plot.subplot(2).add_hist(bkg_qqH, "bkg_qqH") plot.subplot(2).add_hist(bkg_qqH, "bkg_qqH_top") plot.subplot(2).setGraphStyle("bkg_ggH", "hist", linecolor=styles.color_dict["ggH"], linewidth=3) plot.subplot(2).setGraphStyle("bkg_ggH_top", "hist", linecolor=0) plot.subplot(2).setGraphStyle("bkg_qqH", "hist", linecolor=styles.color_dict["qqH"], linewidth=3) plot.subplot(2).setGraphStyle("bkg_qqH_top", "hist", linecolor=0) plot.subplot(2).normalize([ "total_bkg", "bkg_ggH", "bkg_ggH_top", "bkg_qqH", "bkg_qqH_top", "data_obs"], "total_bkg") print "made ratio" # stack background processes plot.create_stack(bkgs, "stack") print "created stack" # normalize stacks by bin-width if args.normalize_by_bin_width: plot.subplot(0).normalizeByBinWidth() plot.subplot(1).normalizeByBinWidth() print "normalized by bin width" # set axes limits and labels plot.subplot(0).setYlims(0.0, 2 * plot.subplot(0).get_hist("total_bkg").GetMaximum()) plot.subplot(2).setYlims(0.45, 2.05) plot.subplot(2).setXlabel(styles.x_label_dict[channel][args.variable]) if args.normalize_by_bin_width: plot.subplot(0).setYlabel("dN/d(%s)"%styles.x_label_dict[channel][args.variable]) else: plot.subplot(0).setYlabel("N_{events}") plot.subplot(2).setYlabel("") plot.scaleYLabelSize(0.8) plot.scaleYTitleOffset(1.1) print "labels & limits" # draw subplots. Argument contains names of objects to be drawn in corresponding order. procs_to_draw = ["stack", "total_bkg", "ggH", "ggH_top", "qqH", "qqH_top", "VH", "VH_top", "ttH", "ttH_top", "HWW", "HWW_top", "data_obs"] plot.subplot(0).Draw(procs_to_draw) plot.subplot(2).Draw(["total_bkg", "bkg_ggH", "bkg_ggH_top", "bkg_qqH", "bkg_qqH_top", "data_obs"]) print "hists drawn" # create legends suffix = ["", "_top"] for i in range(2): plot.add_legend(width=0.6, height=0.15) for process in legend_bkg_processes: try: plot.legend(i).add_entry(0, process, styles.legend_label_dict[process.replace("TTL", "TT").replace("VVL", "VV")], 'f') except: pass plot.legend(i).add_entry(0, "total_bkg", "Bkg. unc.", 'f') plot.legend(i).add_entry(0, "ggH%s" % suffix[i], "gg#rightarrowH", 'l') plot.legend(i).add_entry(0, "qqH%s" % suffix[i], "qq#rightarrowH", 'l') plot.legend(i).add_entry(0, "VH%s" % suffix[i], "qq#rightarrowVH", 'l') try: plot.legend(i).add_entry(0, "ttH%s" % suffix[i], "ttH", 'l') plot.legend(i).add_entry(0, "HWW%s" % suffix[i], "H#rightarrowWW", 'l') except: pass plot.legend(i).add_entry(0, "data_obs", "Data", 'PE') plot.legend(i).setNColumns(3) plot.legend(0).Draw() plot.legend(1).setAlpha(0.0) plot.legend(1).Draw() for i in range(2): plot.add_legend( reference_subplot=2, pos=1, width=0.5, height=0.03) plot.legend(i + 2).add_entry(0, "data_obs", "Data", 'PE') plot.legend(i + 2).add_entry(0, "ggH%s" % suffix[i], "ggH+bkg.", 'l') plot.legend(i + 2).add_entry(0, "qqH%s" % suffix[i], "qqH+bkg.", 'l') plot.legend(i + 2).add_entry(0, "total_bkg", "Bkg. unc.", 'f') plot.legend(i + 2).setNColumns(4) plot.legend(2).Draw() plot.legend(3).setAlpha(0.0) plot.legend(3).Draw() print "legends created" # draw additional labels plot.DrawCMS() if "2016" in args.era: plot.DrawLumi("35.9 fb^{-1} (2016, 13 TeV)") elif "2017" in args.era: plot.DrawLumi("41.5 fb^{-1} (2017, 13 TeV)") elif "2018" in args.era: plot.DrawLumi("59.7 fb^{-1} (2018, 13 TeV)") else: logger.critical("Era {} is not implemented.".format(args.era)) raise Exception plot.DrawChannelCategoryLabel("%s, %s" % (channel_dict[channel], category_dict[channel][category]), begin_left=None) print "additional labes drawn" # save plot postfix = args.shape_type plot.save("%s_plots_cutbased/%s_%s_%s_%s.%s" % (args.era, args.era, channel, category, postfix, "pdf")) plot.save("%s_plots_cutbased/%s_%s_%s_%s.%s" % (args.era, args.era, channel, category, postfix, "png")) plots.append(plot) # work around to have clean up seg faults only at the end of the script
def main(args): if args.gof_variable != None: channel_categories = {c: [args.gof_variable] for c in args.channels} else: channel_categories = { #"et": ["ztt", "zll", "w", "tt", "ss", "misc"], "et": ["12", "15", "11", "13", "14", "16"], #"mt": ["ztt", "zll", "w", "tt", "ss", "misc"], "mt": ["12", "15", "11", "13", "14", "16"], #"tt": ["ztt", "noniso", "misc"] "tt": ["12", "17", "16"] } if args.stxs_categories == 0: for channel in ["et", "mt", "tt"]: channel_categories[channel] += ["1", "2"] elif args.stxs_categories == 1: for channel in ["et", "mt", "tt"]: channel_categories[channel] += ["1", "2"] else: logger.critical("Selected unkown STXS categorization {}", args.stxs_categories) raise Exception channel_dict = { "ee": "ee", "em": "e#mu", "et": "e#tau_{h}", "mm": "#mu#mu", "mt": "#mu#tau_{h}", "tt": "#tau_{h}#tau_{h}" } if args.gof_variable != None: category_dict = {args.gof_variable: "inclusive"} else: category_dict = { "1": "ggH", "2": "VBF", "3": "ggH, unrolled", "4": "VBF, unrolled", "12": "Z#rightarrow#tau#tau", "15": "Z#rightarrowll", "11": "W+jets", "13": "t#bar{t}", "14": "same sign", "16": "misc", "17": "noniso" } if args.linear == True: split_value = 0 else: if args.normalize_by_bin_width: split_value = 10001 else: split_value = 101 split_dict = {c: split_value for c in ["et", "mt", "tt"]} bkg_processes = [ "EWKZ", "QCD", "VVT", "VVJ", "W", "TTT", "TTJ", "ZJ", "ZL", "ZTT" ] if args.fake_factor: bkg_processes = [ b for b in bkg_processes if b not in ["QCD", "VVJ", "TTJ", "W", "ZJ"] ] + ["jetFakes"] if args.embedding: bkg_processes = [b for b in bkg_processes if b not in ["ZTT", "TTT"]] + ["TTL", "EMB"] else: #keep ordering consistent bkg_processes.remove("ZTT") bkg_processes.remove("TTT") bkg_processes.append("TTT") bkg_processes.append("ZTT") all_bkg_processes = [b for b in bkg_processes] legend_bkg_processes = copy.deepcopy(bkg_processes) legend_bkg_processes.reverse() rootfile = rootfile_parser.Rootfile_parser(args.input) plots = [] for channel in args.channels: if channel == "tt": if args.embedding: bkg_processes = [ b for b in all_bkg_processes if b is not "TTL" ] else: bkg_processes = [b for b in all_bkg_processes] else: bkg_processes = [b for b in all_bkg_processes] legend_bkg_processes = copy.deepcopy(bkg_processes) legend_bkg_processes.reverse() for category in channel_categories[channel]: # create plot width = 600 if args.stxs_categories == 1: if category in ["1", "2"]: width = 1200 if args.linear == True: plot = dd.Plot( [0.3, [0.3, 0.28]], "ModTDR", r=0.04, l=0.14, width=width) else: plot = dd.Plot( [0.5, [0.3, 0.28]], "ModTDR", r=0.04, l=0.14, width=width) # get background histograms for process in bkg_processes: plot.add_hist( rootfile.get(channel, category, process), process, "bkg") plot.setGraphStyle( process, "hist", fillcolor=styles.color_dict[process]) # get signal histograms for i in range(2): plot.subplot(i + 1).add_hist( rootfile.get(channel, category, "ggH"), "ggH") plot.subplot(i + 1).add_hist( rootfile.get(channel, category, "ggH"), "ggH_top") plot.subplot(i + 1).add_hist( rootfile.get(channel, category, "qqH"), "qqH") plot.subplot(i + 1).add_hist( rootfile.get(channel, category, "qqH"), "qqH_top") # get observed data and total background histograms plot.add_hist( rootfile.get(channel, category, "data_obs"), "data_obs") plot.add_hist( rootfile.get(channel, category, "TotalBkg"), "total_bkg") plot.subplot(0).setGraphStyle("data_obs", "e0") plot.subplot(1).setGraphStyle( "ggH", "hist", linecolor=styles.color_dict["ggH"], linewidth=3) plot.subplot(1).setGraphStyle("ggH_top", "hist", linecolor=0) plot.subplot(1).setGraphStyle( "qqH", "hist", linecolor=styles.color_dict["qqH"], linewidth=3) plot.subplot(1).setGraphStyle("qqH_top", "hist", linecolor=0) plot.setGraphStyle( "total_bkg", "e2", markersize=0, fillcolor=styles.color_dict["unc"], linecolor=0) # assemble ratio bkg_ggH = plot.subplot(2).get_hist("ggH") bkg_qqH = plot.subplot(2).get_hist("qqH") bkg_ggH.Add(plot.subplot(2).get_hist("total_bkg")) bkg_qqH.Add(plot.subplot(2).get_hist("total_bkg")) plot.subplot(2).add_hist(bkg_ggH, "bkg_ggH") plot.subplot(2).add_hist(bkg_ggH, "bkg_ggH_top") plot.subplot(2).add_hist(bkg_qqH, "bkg_qqH") plot.subplot(2).add_hist(bkg_qqH, "bkg_qqH_top") plot.subplot(2).setGraphStyle( "bkg_ggH", "hist", linecolor=styles.color_dict["ggH"], linewidth=3) plot.subplot(2).setGraphStyle("bkg_ggH_top", "hist", linecolor=0) plot.subplot(2).setGraphStyle( "bkg_qqH", "hist", linecolor=styles.color_dict["qqH"], linewidth=3) plot.subplot(2).setGraphStyle("bkg_qqH_top", "hist", linecolor=0) plot.subplot(2).normalize([ "total_bkg", "bkg_ggH", "bkg_ggH_top", "bkg_qqH", "bkg_qqH_top", "data_obs" ], "total_bkg") # stack background processes plot.create_stack(bkg_processes, "stack") # normalize stacks by bin-width if args.normalize_by_bin_width: plot.subplot(0).normalizeByBinWidth() plot.subplot(1).normalizeByBinWidth() # set axes limits and labels plot.subplot(0).setYlims( split_dict[channel], max(2 * plot.subplot(0).get_hist("total_bkg").GetMaximum(), split_dict[channel] * 2)) plot.subplot(2).setYlims(0.75, 1.45) if int(category) < 10: plot.subplot(2).setYlims(0.55, 2.05) if args.linear != True: plot.subplot(1).setYlims(0.1, split_dict[channel]) plot.subplot(1).setLogY() plot.subplot(1).setYlabel( "") # otherwise number labels are not drawn on axis if args.gof_variable != None: if args.gof_variable in styles.x_label_dict[args.channels[0]]: x_label = styles.x_label_dict[args.channels[0]][ args.gof_variable] else: x_label = args.gof_variable plot.subplot(2).setXlabel(x_label) else: plot.subplot(2).setXlabel("NN score") if args.normalize_by_bin_width: plot.subplot(0).setYlabel("N_{events}/bin width") else: plot.subplot(0).setYlabel("N_{events}") plot.subplot(2).setYlabel("Ratio to Bkg.") #plot.scaleXTitleSize(0.8) #plot.scaleXLabelSize(0.8) #plot.scaleYTitleSize(0.8) plot.scaleYLabelSize(0.8) #plot.scaleXLabelOffset(2.0) plot.scaleYTitleOffset(1.1) #plot.subplot(2).setNYdivisions(3, 5) # draw subplots. Argument contains names of objects to be drawn in corresponding order. plot.subplot(0).Draw(["stack", "total_bkg", "data_obs"]) if args.linear != True: plot.subplot(1).Draw([ "stack", "total_bkg", "ggH", "ggH_top", "qqH", "qqH_top", "data_obs" ]) plot.subplot(2).Draw([ "total_bkg", "bkg_ggH", "bkg_ggH_top", "bkg_qqH", "bkg_qqH_top", "data_obs" ]) # create legends suffix = ["", "_top"] for i in range(2): plot.add_legend(width=0.6, height=0.15) for process in legend_bkg_processes: plot.legend(i).add_entry( 0, process, styles.legend_label_dict[process], 'f') plot.legend(i).add_entry(0, "total_bkg", "Bkg. unc.", 'f') plot.legend(i).add_entry(1, "ggH%s" % suffix[i], "ggH", 'l') plot.legend(i).add_entry(1, "qqH%s" % suffix[i], "qqH", 'l') plot.legend(i).add_entry(0, "data_obs", "Data", 'PE') plot.legend(i).setNColumns(3) plot.legend(0).Draw() plot.legend(1).setAlpha(0.0) plot.legend(1).Draw() if args.chi2test: import ROOT as r f = r.TFile(args.input, "read") background = f.Get("htt_{}_{}_13TeV_{}/TotalBkg".format( channel, category, "prefit" if "prefit" in args.input else "postfit")) data = f.Get("htt_{}_{}_13TeV_{}/data_obs".format( channel, category, "prefit" if "prefit" in args.input else "postfit")) chi2 = data.Chi2Test(background, "UW CHI2/NDF") plot.DrawText(0.7, 0.3, "\chi^{2}/ndf = " + str(round(chi2, 3))) for i in range(2): plot.add_legend( reference_subplot=2, pos=1, width=0.5, height=0.03) plot.legend(i + 2).add_entry(0, "data_obs", "Data", 'PE') plot.legend(i + 2).add_entry(1, "ggH%s" % suffix[i], "ggH+bkg.", 'l') plot.legend(i + 2).add_entry(1, "qqH%s" % suffix[i], "qqH+bkg.", 'l') plot.legend(i + 2).add_entry(0, "total_bkg", "Bkg. unc.", 'f') plot.legend(i + 2).setNColumns(4) plot.legend(2).Draw() plot.legend(3).setAlpha(0.0) plot.legend(3).Draw() # draw additional labels plot.DrawCMS() if "2016" in args.era: plot.DrawLumi("35.9 fb^{-1} (13 TeV)") elif "2017" in args.era: plot.DrawLumi("41.3 fb^{-1} (13 TeV)") else: logger.critical("Era {} is not implemented.".format(args.era)) raise Exception posChannelCategoryLabelLeft = None if args.stxs_categories == 1: if category in ["1", "2"]: posChannelCategoryLabelLeft = 0.075 plot.DrawChannelCategoryLabel( "%s, %s" % (channel_dict[channel], category_dict[category]), begin_left=posChannelCategoryLabelLeft) # save plot postfix = "prefit" if "prefit" in args.input else "postfit" if "postfit" in args.input else "undefined" plot.save("plots/%s_%s_%s_%s.%s" % (args.era, channel, category, postfix, "png" if args.png else "pdf")) plots.append( plot ) # work around to have clean up seg faults only at the end of the script
def main(args): #### plot signals print(args) if args.gof_variable != None: channel_categories = { "et": ["300"], "mt": ["301", "302"], "tt": ["300"], "em": ["301", "302"], } if args.era == "combined": if "prefit" in args.input: channel_categories = { "et": ["300"], "mt": ["300", "301", "302"], "tt": ["300"], "em": ["300", "301", "302"], } else: if "301" in args.input: channel_categories["mt"] = ["301"] channel_categories["em"] = ["301"] elif "302" in args.input: channel_categories["mt"] = ["302"] channel_categories["em"] = ["302"] else: channel_categories = { "et": ["300"], "mt": ["300"], "tt": ["300"], "em": ["300"], } else: channel_categories = { #"et": ["ztt", "zll", "w", "tt", "ss", "misc"], "et": ["12", "15", "11", "13", "14", "16"], #"mt": ["ztt", "zll", "w", "tt", "ss", "misc"], "mt": ["12", "15", "11", "13", "14", "16"], #"tt": ["ztt", "noniso", "misc"] "tt": ["12", "17", "16"], #"em": ["ztt", "tt", "ss", "misc", "db"] "em": ["12", "13", "14", "16", "19"] } channel_dict = { "ee": "ee", "em": "e#mu", "et": "e#tau_{h}", "mm": "#mu#mu", "mt": "#mu#tau_{h}", "tt": "#tau_{h}#tau_{h}" } if args.gof_variable != None: category_dict = { "300": "inclusive", "301": "No b tag", "302": "b tag", } else: category_dict = { "1": "ggh", "100": "ggh 0-jet", "101": "ggh 1-jet p_{T}^{H} [0,120]", "102": "ggh 1-jet p_{T}^{H} [120,200]", "103": "ggh #geq 2-jet", "104": "ggh p_{T}^{H}>200", "2": "qqh", "200": "qqh 2J low mjj", "201": "qqh p_{T}^{H}>200", "202": "qqh vbftopo mjj>700", "203": "qqh vbftopo mjj [350,700]", "12": "ztt", "15": "zll", "11": "wjets", "13": "tt", "14": "qcd", "16": "misc", "17": "qcd", "19": "diboson", "20": "Genuine #tau", "21": "Jet #rightarrow #tau_{h}" } if args.linear == True: split_value = 0 else: if args.normalize_by_bin_width: split_value = 10001 else: split_value = 101 split_dict = {c: split_value for c in ["et", "mt", "tt", "em"]} bkg_processes = ["EWK", "ZL", "TTL", "jetFakes", "EMB"] if not args.fake_factor and args.embedding: bkg_processes = ["QCD", "VVJ", "W", "TTJ", "ZJ", "ZL", "EMB"] if not args.embedding and args.fake_factor: bkg_processes = ["VVT", "VVL", "TTT", "TTL", "ZL", "jetFakes", "ZTT"] if not args.embedding and not args.fake_factor: bkg_processes = [ "QCD", "VVT", "VVL", "VVJ", "W", "TTT", "TTL", "TTJ", "ZJ", "ZL", "ZTT" ] all_bkg_processes = [b for b in bkg_processes] legend_bkg_processes = copy.deepcopy(bkg_processes) legend_bkg_processes.reverse() if "2016" in args.era: era = "2016" elif "2017" in args.era: era = "2017" elif "2018" in args.era: era = "2018" elif "combined" in args.era: era = "combined" else: logger.critical("Era {} is not implemented.".format(args.era)) raise Exception print(channel_categories) plots = [] for channel in args.channels: for category in channel_categories[channel]: print "Plot for category: ", category rootfile = rootfile_parser.Rootfile_parser(args.input) if channel == "em" and args.embedding: bkg_processes = ["EWK", "ZL", "TTL", "QCD", "EMB"] elif channel == "em" and not args.embedding: bkg_processes = ["VVL", "W", "TTL", "ZL", "QCD", "ZTT"] else: bkg_processes = [b for b in all_bkg_processes] legend_bkg_processes = copy.deepcopy(bkg_processes) legend_bkg_processes.reverse() # create plot width = 600 if args.linear == True: plot = dd.Plot([0.25, [0.25, 0.23]], "ModTDR", r=0.04, l=0.14, width=width) else: plot = dd.Plot([0.5, [0.3, 0.28]], "ModTDR", r=0.04, l=0.14, width=width) # get background histograms for process in bkg_processes: try: plot.add_hist( get_histogram(rootfile, era, channel, category, process), process, "bkg") plot.setGraphStyle(process, "hist", fillcolor=styles.color_dict[process]) except: pass # get observed data and total background histograms # NOTE: With CMSSW_8_1_0 the TotalBkg definition has changed. print("plot.add_hist(rootfile.get(" + era + ", " + channel + ", " + category + ', "data_obs")') plot.add_hist( get_histogram(rootfile, era, channel, category, "data_obs"), "data_obs") total_bkg = check_for_zero_bins( get_histogram(rootfile, era, channel, category, "TotalBkg")) #ggHHist = rootfile.get(era, channel, category, "ggH") #qqHHist = rootfile.get(era, channel, category, "qqH") #total_bkg.Add(ggHHist, -1) #if qqHHist: # total_bkg.Add(qqHHist, -1) plot.add_hist(total_bkg, "total_bkg") plot.subplot(0).setGraphStyle("data_obs", "e0") plot.setGraphStyle("total_bkg", "e2", markersize=0, fillcolor=styles.color_dict["unc"], linecolor=0) plot.subplot(2).normalize(["total_bkg", "data_obs"], "total_bkg") # stack background processes plot.create_stack(bkg_processes, "stack") # normalize stacks by bin-width if args.normalize_by_bin_width: plot.subplot(0).normalizeByBinWidth() plot.subplot(1).normalizeByBinWidth() # set axes limits and labels if channel == "em": # plot.setXlims(-200.,150.) if category in ["300", "301"]: plot.setXlims(-70., 100.) plot.subplot(0).setYlims( split_dict[channel], max( 1.40 * plot.subplot(0).get_hist("data_obs").GetMaximum(), split_dict[channel] * 2)) elif category == "302": plot.setXlims(-140., 140) plot.subplot(0).setYlims( split_dict[channel], max( 1.40 * plot.subplot(0).get_hist("data_obs").GetMaximum(), split_dict[channel] * 2)) elif channel in ["et", "mt"]: if category in ["300", "301"]: plot.subplot(0).setYlims( split_dict[channel], max( 1.25 * plot.subplot(0).get_hist("data_obs").GetMaximum(), split_dict[channel] * 2)) elif category in ["302"]: plot.subplot(0).setYlims( split_dict[channel], max( 2.00 * plot.subplot(0).get_hist("data_obs").GetMaximum(), split_dict[channel] * 2)) if args.gof_variable is None: plot.subplot(2).setYlims(0.45, 2.05) else: plot.subplot(2).setYlims(0.85, 1.15) if not args.linear: plot.subplot(1).setYlims(0.1, split_dict[channel]) plot.subplot(1).setLogY() plot.subplot(1).setYlabel( "") # otherwise number labels are not drawn on axis if args.gof_variable != None: gof_log_vars = [] if args.gof_variable in gof_log_vars: plot.subplot(0).setLogX() plot.subplot(1).setLogX() plot.subplot(2).setLogX() elif args.gof_variable in ["njets_red", "nbtag_red"]: bins = plot.subplot(2).get_hist("data_obs").GetNbinsX() bin_labels = map(str, range(bins - 1)) bin_labels.append("#geq%i" % (bins - 1)) plot.subplot(2).setNXdivisions(bins, 0, 2) plot.subplot(2).changeXLabels(bin_labels) if args.gof_variable in styles.x_label_dict[args.channels[0]]: x_label = styles.x_label_dict[args.channels[0]][ args.gof_variable] else: x_label = args.gof_variable plot.subplot(2).setXlabel(x_label) elif args.gof_variable != None and args.linear: if args.gof_variable in styles.x_label_dict[args.channels[0]]: x_label = styles.x_label_dict[args.channels[0]][ args.gof_variable] else: x_label = args.gof_variable plot.subplot(2).setXlabel(x_label) else: plot.subplot(2).setXlabel("NN output") if args.normalize_by_bin_width: plot.subplot(0).setYlabel("dN/d(%s)" % args.gof_variable) else: if channel == "em": plot.subplot(0).setYlabel("Events / 5 GeV") else: plot.subplot(0).setYlabel("Events / 5 GeV") plot.subplot(2).setYlabel("Obs./Exp.") plot.subplot(2).setGrid() #plot.scaleXTitleSize(0.8) #plot.scaleXLabelSize(0.8) #plot.scaleYTitleSize(0.8) plot.scaleYLabelSize(0.8) #plot.scaleXLabelOffset(2.0) plot.scaleYTitleOffset(1.1) plot.subplot(2).setNYdivisions(3, 0) #if not channel == "tt" and category in ["11", "12", "13", "14", "15", "16"]: # plot.subplot(2).changeXLabels(["0.2", "0.4", "0.6", "0.8", "1.0"]) # draw subplots. Argument contains names of objects to be drawn in corresponding order. procs_to_draw = [ "stack", "total_bkg", "data_obs" ] if args.linear else ["stack", "total_bkg", "data_obs"] plot.subplot(0).Draw(procs_to_draw) if args.linear != True: plot.subplot(1).Draw(["stack", "total_bkg", "data_obs"]) plot.subplot(2).Draw(["total_bkg", "data_obs"]) # create legends if channel == "mt" and category in ["302"]: plot.add_legend(width=0.5, height=0.20) plot.legend(0).setNColumns(2) elif channel == "em" and category in ["302"]: plot.add_legend(width=0.25, height=0.35) plot.legend(0).setNColumns(1) else: plot.add_legend(width=0.25, height=0.35) plot.legend(0).setNColumns(1) plot.legend(0).add_entry(0, "data_obs", "Observed", 'PE') for process in legend_bkg_processes: try: plot.legend(0).add_entry( 0, process, styles.legend_label_dict[process.replace( "TTL", "TT").replace("VVL", "VV").replace("EMB", "EMBFull")], 'f') except: pass plot.legend(0).add_entry(0, "total_bkg", "Bkg. unc.", 'f') # plot.legend(0).add_entry(0, "total_bkg", "Background uncertainty", 'f') plot.legend(0).scaleTextSize(1.175) plot.legend(0).Draw() if channel == "em": if category in ["300", "301"]: _ymax_low = max( 1.05 * plot.subplot(0).get_hist("data_obs").GetMaximum(), split_dict[channel] * 2) _ymax_high = max( 0.6 * plot.subplot(0).get_hist("data_obs").GetMaximum(), split_dict[channel] * 2) plot.add_line(xmin=-35, xmax=-35, ymin=0, ymax=_ymax_low, linestyle=7, color=ROOT.kBlack) plot.add_line(xmin=-10, xmax=-10, ymin=0, ymax=_ymax_low, linestyle=7, color=ROOT.kBlack) plot.add_line(xmin=30, xmax=30, ymin=0, ymax=_ymax_low, linestyle=7, color=ROOT.kBlack) # plot.DrawText(0.335, 0.80, "Low-D_{#zeta}", textsize=0.030) # plot.DrawText(0.465, 0.80, "Medium-D_{#zeta}", textsize=0.025) label2 = ROOT.TLatex() plot.subplot(0)._pad.cd() label2.SetNDC(False) label2.SetTextAngle(0) label2.SetTextAlign(22) label2.SetTextColor(ROOT.kBlack) label2.SetTextSize(0.030) if category in ["301"]: label2.DrawLatex(-22.5, 105000, "Low-D_{#zeta}") label2.DrawLatex(10, 105000, "Medium-D_{#zeta}") plot.DrawText(0.75, 0.5, "High-D_{#zeta}", textsize=0.030) else: label2.DrawLatex(-22.5, 125000, "Low-D_{#zeta}") label2.DrawLatex(10, 125000, "Medium-D_{#zeta}") plot.DrawText(0.75, 0.5, "High-D_{#zeta}", textsize=0.030) elif category in ["302"]: _ymax_low = max( 1.05 * plot.subplot(0).get_hist("data_obs").GetMaximum(), split_dict[channel] * 2) _ymax_high = max( 0.6 * plot.subplot(0).get_hist("data_obs").GetMaximum(), split_dict[channel] * 2) plot.add_line(xmin=-35, xmax=-35, ymin=0, ymax=_ymax_low, linestyle=7, color=ROOT.kBlack) plot.add_line(xmin=-10, xmax=-10, ymin=0, ymax=_ymax_low, linestyle=7, color=ROOT.kBlack) plot.add_line(xmin=30, xmax=30, ymin=0, ymax=_ymax_low, linestyle=7, color=ROOT.kBlack) plot.DrawText(0.450, 0.8, "Low-D_{#zeta}", textsize=0.025) plot.DrawText(0.525, 0.8, "Medium-D_{#zeta}", textsize=0.025) plot.DrawText(0.75, 0.45, "High-D_{#zeta}", textsize=0.025) plot.DrawText(0.305, 0.8, "t#bar{t} CR", textsize=0.025) elif channel in ["et", "mt"]: if category in ["300", "301"]: _ymax = max( 0.8 * plot.subplot(0).get_hist("data_obs").GetMaximum(), split_dict[channel] * 2) plot.add_line(xmin=40, xmax=40, ymin=0, ymax=_ymax, linestyle=7, color=ROOT.kBlack) _ymax = max( 0.5 * plot.subplot(0).get_hist("data_obs").GetMaximum(), split_dict[channel] * 2) plot.add_line(xmin=70, xmax=70, ymin=0, ymax=_ymax, linestyle=7, color=ROOT.kBlack) plot.DrawText(0.24, 0.68, "Tight-m_{T}", textsize=0.030) plot.DrawText(0.40, 0.55, "Loose-m_{T}", textsize=0.030) elif category in ["302"]: _ymax = max( 1.3 * plot.subplot(0).get_hist("data_obs").GetMaximum(), split_dict[channel] * 2) plot.add_line(xmin=40, xmax=40, ymin=0, ymax=_ymax, linestyle=7, color=ROOT.kBlack) _ymax = max( 1.3 * plot.subplot(0).get_hist("data_obs").GetMaximum(), split_dict[channel] * 2) plot.add_line(xmin=70, xmax=70, ymin=0, ymax=_ymax, linestyle=7, color=ROOT.kBlack) plot.DrawText(0.18, 0.67, "Tight-m_{T}", textsize=0.030) plot.DrawText(0.40, 0.67, "Loose-m_{T}", textsize=0.030) for line in plot._lines: line.Draw() if args.chi2test: import ROOT as r f = r.TFile(args.input, "read") background = f.Get("htt_{}_{}_Run{}_{}/TotalBkg".format( channel, category, args.era, "prefit" if "prefit" in args.input else "postfit")) data = f.Get("htt_{}_{}_Run{}_{}/data_obs".format( channel, category, args.era, "prefit" if "prefit" in args.input else "postfit")) chi2 = data.Chi2Test(background, "UW CHI2/NDF") plot.DrawText(0.7, 0.3, "\chi^{2}/ndf = " + str(round(chi2, 3))) # plot.add_legend( # reference_subplot=2, pos=1, width=0.5, height=0.03) # plot.legend(1).add_entry(0, "data_obs", "Data", 'PE') # plot.legend(1).add_entry(0, "total_bkg", "Bkg. unc.", 'f') # plot.legend(1).setNColumns(4) # plot.legend(1).Draw() # draw additional labels plot.DrawCMS(cms_sub="") if "2016" in args.era: plot.DrawLumi("36.3 fb^{-1} (2016, 13 TeV)") elif "2017" in args.era: plot.DrawLumi("41.5 fb^{-1} (2017, 13 TeV)") elif "2018" in args.era: plot.DrawLumi("59.7 fb^{-1} (2018, 13 TeV)") elif "combined" in args.era: plot.DrawLumi("138 fb^{-1} (13 TeV)") else: logger.critical("Era {} is not implemented.".format(args.era)) raise Exception plot.DrawChannelCategoryLabel( "#font[42]{%s, %s}" % (channel_dict[channel], category_dict[category]) if category != "300" else "%s" % channel_dict[channel], begin_left=None) # save plot postfix = "prefit" if "prefit" in args.input else "postfit" if "postfit" in args.input else "undefined" plot.save("%s/%s_%s_%s_%s.%s" % (args.outputfolder, args.era, channel, category, postfix, "png" if args.png else "pdf")) plots.append( plot ) # work around to have clean up seg faults only at the end of the script