def plot_data_mc(hists_mc, hist_data, name): canv = ROOT.TCanvas() p1 = ROOT.TPad("p1", "p1", 0, 0.3, 1, 1) p1.Draw() p1.SetTicks(1, 1); p1.SetGrid(); p1.SetFillStyle(0); p1.cd() stacks_d = OrderedDict() print "MC",hists_mc print "VAL",hists_mc.values() stacks_d["mc"] = hists_mc.values() stacks_d["data"] = [hist_data] stacks = plot_hists_stacked( p1, stacks_d, x_label=var, y_label="", do_log_y=True ) leg = legend([hist_data] + list(reversed(hists_mc.values())), styles=["p", "f"]) print canv, hist_data print get_stack_total_hist(stacks["mc"]) ratio_pad, hratio = plot_data_mc_ratio(canv, get_stack_total_hist(stacks["mc"]), hist_data) plot_info = PlotMetaInfo( name, "CUT", "WEIGHT", [infile], subdir=fit.name, comments=str(result[SIGNAL]) ) of.savePlot(canv, plot_info) canv.Close()
hists_tot_mc_syst[name] = tuple(tots) #Draw the ratio plot with the systematics do_norm = plot_def.get("normalize", False) if not do_norm and len(hists_tot_mc_syst.items())>0: syst_hists = total_syst(htot_mc, hists_tot_mc_syst) for h in list(syst_hists): try: logger.info("Chi2 = %.2f" % (htot_mc.Chi2Test(h, "WW CHI2/NDF"))) except rootpy.ROOTError as e: logger.error("Couldn't calculate the chi2: %s" % str(e)) else: syst_hists = None ratio_pad, hratio = plot_data_mc_ratio(canv, htot_data, htot_mc, syst_hists=syst_hists) #This is adopted in the AN if lepton_channel=="ele": _lepton_channel = "el" else: _lepton_channel = "mu" if use_antiiso: _lepton_channel+='_aiso' subpath = "" if "dir" in plot_def.keys(): subpath = plot_def["dir"] #Set the plot metadata
def data_mc_plot(pd): hists = load_theta_format(pd.infile, styles) for (variable, sample, systtype, systdir), hist in hists.items_flat(): #Scale all MC samples except QCD to the luminosity if sample_types.is_mc(sample) and not sample=="qcd": hist.Scale(pd.lumi) if hasattr(pd, "rebin"): hist.Rebin(pd.rebin) if sample=="qcd" and hasattr(pd, "qcd_yield"): hist.Scale(pd.qcd_yield / hist.Integral()) rescale_to_fit(sample, hist, pd.process_scale_factor) hist.SetTitle(sample) hist.SetName(sample) #Assuming we only have 1 variable hists = hists[pd.var] hists_nominal = hists.pop("nominal")[None] hists_nom_data = hists_nominal.pop('data') hists_nom_mc = hists_nominal.values() hists_syst = hists hists_nom_data.SetTitle('data') #A list of all the systematic up, down variation templates as 2-tuples all_systs = [ ] all_systs = hists_syst.keys() systs_to_consider = [] #See which systematics where asked to switch on for syst in all_systs: for sm in pd.systematics: if re.match(sm, syst): systs_to_consider.append(syst) #The total nominal MC histogram nom = sum(hists_nom_mc) if pd.normalize: ratio = hists_nom_data.Integral() / nom.Integral() hists_nom_data.Scale(1.0/ratio) #Get all the variated up/down total templates #A list with all the up/down total templates all_systs = [] sumsqs = [] logger.info("Considering systematics %s" % str(systs_to_consider)) for syst in systs_to_consider: #A list with the up/down variated template for a particular systematic totupdown = [] sumsq = [] for systdir in ["up", "down"]: #Get all the templates corresponding to a systematic scenario and a variation _hists = hists_syst[syst][systdir] for k, h in _hists.items(): """ Consider only the shape variation of the systematic, hence the variated template is normalized to the corresponding unvariated template. """ if pd.systematics_shapeonly: if h.Integral()>0: h.Scale(hists_nominal[k].Integral() / h.Integral()) #For the missing variated templates, use the nominal ones, but warn the user present = set(_hists.keys()) all_mc = set(hists_nominal.keys()) missing = list(all_mc.difference(present)) for m in missing: logger.warning("Missing systematic template for %s:%s" % (syst, systdir)) #Calculate the total variated template tot = sum(_hists.values()) + sum([hists_nominal[m] for m in missing]) totupdown.append(tot) sumsq.append( math.sqrt(numpy.sum(numpy.power(numpy.array(list(nom.y())) - numpy.array(list(tot.y())), 2))) ) logger.debug("Systematic %s: sumsq=%.2Eu, %.2Ed" % (syst, sumsq[0], sumsq[1])) sumsqs.append((syst, max(sumsq))) all_systs.append( (syst, tuple(totupdown)) ) sumsqs = sorted(sumsqs, key=lambda x: x[1], reverse=True) for syst, sumsq in sumsqs[0:7]: logger.info("Systematic %s, %.4f" % (syst, sumsq)) #Calculate the total up/down variated templates by summing in quadrature syst_stat_up, syst_stat_down = total_syst( nom, all_systs, ) for k, v in hists_nominal.items(): if hasattr(PhysicsProcess, k): pp = getattr(PhysicsProcess, k) v.SetTitle(pp.pretty_name) else: logger.warning("Not setting pretty name for %s" % k) #If QCD is high-stats, put it in the bottom plotorder = copy.copy(PhysicsProcess.desired_plot_order_mc) if hists_nominal["qcd"].GetEntries()>100: plotorder.pop(plotorder.index("qcd")) plotorder.insert(0, "qcd") stacks_d = OrderedDict() stacks_d['mc'] = reorder(hists_nominal, plotorder) stacks_d['data'] = [hists_nom_data] #Systematic style for s in [syst_stat_up, syst_stat_down]: s.SetFillStyle(0) s.SetLineWidth(3) s.SetMarkerSize(0) s.SetLineColor(ROOT.kBlue+2) s.SetLineStyle('dashed') s.SetTitle("stat. + syst.") #c = ROOT.TCanvas("c", "c", 1000, 1000) c = ROOT.TCanvas("c", "c") p1 = ROOT.TPad("p1", "p1", 0, 0.3, 1, 1) p1.Draw() p1.SetTicks(1, 1); p1.SetGrid(); p1.SetFillStyle(0); p1.cd() stacks = plot_hists_stacked( p1, stacks_d, x_label=pd.get_x_label(), max_bin_mult=pd.get_max_bin_mult(), min_bin=pd.get_min_bin() ) p1.SetLogy(pd.log) syst_stat_up.Draw("SAME hist") syst_stat_down.Draw("SAME hist") ratio_pad, hratio = plot_data_mc_ratio( c, hists_nom_data, nom, syst_hists=(syst_stat_down, syst_stat_up), min_max=pd.get_ratio_minmax() ) p1.cd() leg = legend( stacks_d['data'] + list(reversed(stacks_d['mc'])) + [syst_stat_up], nudge_x=pd.legend_nudge_x, nudge_y=pd.legend_nudge_y, **pd.__dict__ ) lb = lumi_textbox(pd.lumi, line2=pd.get_lumibox_comments(channel=pd.channel_pretty), pos=pd.get_lumi_pos() ) c.children = [p1, ratio_pad, stacks, leg, lb] tot = 0 for k, v in hists_nominal.items(): print k, v.Integral(), v.GetEntries() tot += v.Integral() tot_data = hists_nom_data.Integral() print "MC: %.2f Data: %.2f" % (tot, tot_data) #import pdb; pdb.set_trace() return c, (hists_nominal, hists_nom_data)