def prepare_args(self, parser, plotData): super(CalculateWJetsOSSSFactor, self).prepare_args(parser, plotData) self._plotdict_keys = [ "wjets_from_mc_os_nicks", "wjets_from_mc_ss_nicks" ] self.prepare_list_args(plotData, self._plotdict_keys) def run(self, plotData=None): super(CalculateWJetsOSSSFactor, self).run(plotData) # make sure that all necessary histograms are available for nicks in zip( *[plotData.plotdict[key] for key in self._plotdict_keys]): for nick in nicks: if isinstance(nick, basestring): assert isinstance( plotData.plotdict["root_objects"].get(nick), ROOT.TH1) elif not isinstance(nick, bool): for subnick in nick: assert isinstance( plotData.plotdict["root_objects"].get(subnick), ROOT.TH1) for wjets_from_mc_os_nicks, wjets_from_mc_ss_nicks in zip( *[plotData.plotdict[key] for key in self._plotdict_keys]): yield_wj_mc_os = tools.PoissonYield( plotData.plotdict["root_objects"][wjets_from_mc_os_nicks])() yield_wj_mc_ss = tools.PoissonYield( plotData.plotdict["root_objects"][wjets_from_mc_ss_nicks])() # make sure we don't have negative yields yield_wj_mc_os = uncertainties.ufloat( max(0.0, yield_wj_mc_os.nominal_value), yield_wj_mc_os.std_dev) yield_wj_mc_ss = uncertainties.ufloat( max(0.0, yield_wj_mc_ss.nominal_value), yield_wj_mc_ss.std_dev) print(yield_wj_mc_os, yield_wj_mc_ss) assert (yield_wj_mc_os != 0.0) or (yield_wj_mc_ss != 0.0) # the final yield in the signal region is N_data, WJ^{SR} = N_data, WJ^{CR} * N_MC,WJ^{SR} / N_MC,WJ^{CR} os_ss_factor = yield_wj_mc_os / yield_wj_mc_ss plotData.metadata[wjets_from_mc_os_nicks] = { "os_ss_factor": os_ss_factor.nominal_value, "os_ss_factor_unc": os_ss_factor.std_dev, "yield_unc_rel": abs(os_ss_factor.std_dev / os_ss_factor.nominal_value if os_ss_factor.nominal_value != 0.0 else 0.0), } plotData.metadata print(plotData.metadata)
def run(self, plotData=None): super(EstimateWjets, self).run(plotData) # make sure that all necessary histograms are available for nicks in zip(*[plotData.plotdict[key] for key in self._plotdict_keys]): for nick in nicks: if isinstance(nick, basestring): assert isinstance(plotData.plotdict["root_objects"].get(nick), ROOT.TH1) elif not isinstance(nick, bool): for subnick in nick: assert isinstance(plotData.plotdict["root_objects"].get(subnick), ROOT.TH1) for wjets_from_mc, wjets_shape_nick, wjets_data_control_nick, wjets_data_substract_nicks, wjets_mc_signal_nick, wjets_mc_control_nick in zip(*[plotData.plotdict[key] for key in self._plotdict_keys]): if not wjets_from_mc: # skips the full estimation of this module and uses MC estimate of WJ instead. # Get yield and uncertainity in data in the control region yield_data_control = tools.PoissonYield(plotData.plotdict["root_objects"][wjets_data_control_nick])() for nick in wjets_data_substract_nicks: # subtract yields of all backgrounds yield_bkg_control = tools.PoissonYield(plotData.plotdict["root_objects"][nick])() if nick in plotData.metadata: yield_bkg_control = uncertainties.ufloat( plotData.metadata[nick].get("yield", yield_bkg_control.nominal_value), plotData.metadata[nick].get("yield_unc", yield_bkg_control.std_dev) ) yield_data_control -= yield_bkg_control # make sure we don't have negative yields yield_data_control = uncertainties.ufloat(max(0.0, yield_data_control.nominal_value), yield_data_control.std_dev) yield_mc_signal = tools.PoissonYield(plotData.plotdict["root_objects"][wjets_mc_signal_nick])() yield_mc_control = tools.PoissonYield(plotData.plotdict["root_objects"][wjets_mc_control_nick])() assert (yield_data_control*yield_mc_signal == 0.0) or (yield_mc_control != 0.0) # the final yield in the signal region is N_data, WJ^{SR} = N_data, WJ^{CR} * N_MC,WJ^{SR} / N_MC,WJ^{CR} final_yield = yield_data_control * yield_mc_signal if final_yield != 0.0: final_yield /= yield_mc_control log.debug("Relative statistical uncertainty of the yield for process W+jets (nick \"{nick}\") is {unc}.".format(nick=wjets_shape_nick, unc=final_yield.std_dev/final_yield.nominal_value if final_yield.nominal_value != 0.0 else 0.0)) plotData.metadata[wjets_shape_nick] = { "yield" : final_yield.nominal_value, "yield_unc" : final_yield.std_dev, "yield_unc_rel" : abs(final_yield.std_dev/final_yield.nominal_value if final_yield.nominal_value != 0.0 else 0.0), } plotData.metadata # scale the wj file by the ratio of the estimated yield and the yield given by MC. integral_shape = tools.PoissonYield(plotData.plotdict["root_objects"][wjets_shape_nick])() if integral_shape != 0.0: scale_factor = final_yield / integral_shape log.debug("Scale factor for process W+jets (nick \"{nick}\") is {scale_factor}.".format(nick=wjets_shape_nick, scale_factor=scale_factor)) plotData.plotdict["root_objects"][wjets_shape_nick].Scale(scale_factor.nominal_value)
def run(self, plotData=None): super(UnpolarisationScaleFactors, self).run(plotData) for unpolarisation_nominal_nick, unpolarisation_shift_up_nick, unpolarisation_shift_down_nick, unpolarisation_forced_gen_polarisation in zip(*[plotData.plotdict[key] for key in ["unpolarisation_nominal_nicks", "unpolarisation_shift_up_nicks", "unpolarisation_shift_down_nicks", "unpolarisation_forced_gen_polarisations"]]): scale_factors = {} scale_factors_pos = {} scale_factors_neg = {} for shift, nick in zip(*[["nominal", "shift up", "shift down"], [unpolarisation_nominal_nick, unpolarisation_shift_up_nick, unpolarisation_shift_down_nick]]): neg_gen_norm = uncertainties.ufloat( plotData.plotdict["root_objects"][nick].GetBinContent(1), plotData.plotdict["root_objects"][nick].GetBinError(1) ) pos_gen_norm = uncertainties.ufloat( plotData.plotdict["root_objects"][nick].GetBinContent(2), plotData.plotdict["root_objects"][nick].GetBinError(2) ) scale_factors[shift] = polarisationsignalscaling.PolarisationScaleFactors(pos_gen_norm, neg_gen_norm, pos_gen_norm, neg_gen_norm, forced_gen_polarisation=unpolarisation_forced_gen_polarisation) scale_factors_pos[shift] = scale_factors[shift].get_bias_removal_factor_pospol() if plotData.plotdict["unpolarisation_remove_bias_instead_unpolarisation"] else scale_factors[shift].get_scale_factor_pospol() log.debug("Positive helicity of \"{nick}\" to be scaled by a factor of {factor} ({shift}).".format( nick=nick, factor=scale_factors_pos[shift], shift=shift )) scale_factors_neg[shift] = scale_factors[shift].get_bias_removal_factor_neg_pol() if plotData.plotdict["unpolarisation_remove_bias_instead_unpolarisation"] else scale_factors[shift].get_scale_factor_negpol() log.debug("Negative helicity of \"{nick}\" to be scaled by a factor of {factor} ({shift}).".format( nick=nick, factor=scale_factors_neg[shift], shift=shift )) total_uncertainties_pos = [abs((scale_factors_pos["shift up"]-scale_factors_pos["nominal"])/scale_factors_pos["nominal"]), abs((scale_factors_pos["shift down"]-scale_factors_pos["nominal"])/scale_factors_pos["nominal"])] total_uncertainties_neg = [abs((scale_factors_neg["shift up"]-scale_factors_neg["nominal"])/scale_factors_neg["nominal"]), abs((scale_factors_neg["shift down"]-scale_factors_neg["nominal"])/scale_factors_neg["nominal"])] log.info("Total uncertainties on scale factor for positive helicity = (+) {tot_pos_plus} / (-) {tot_pos_minus}".format( tot_pos_plus=total_uncertainties_pos[0], tot_pos_minus=total_uncertainties_pos[1] )) log.info("Total uncertainties on scale factor for negative helicity = (+) {tot_neg_plus} / (-) {tot_neg_minus}".format( tot_neg_plus=total_uncertainties_neg[0], tot_neg_minus=total_uncertainties_neg[1] ))
def run(self, plotData=None): super(EstimateQcdTauHadTauHad, self).run(plotData) # make sure that all necessary histograms are available for nicks in zip(*[plotData.plotdict[key] for key in self._plotdict_keys]): for nick in nicks: if isinstance(nick, basestring): assert isinstance(plotData.plotdict["root_objects"].get(nick), ROOT.TH1) elif (not isinstance(nick, float) and not isinstance(nick, bool)): for subnick in nick: assert isinstance(plotData.plotdict["root_objects"].get(subnick), ROOT.TH1) for qcd_data_shape_nick, qcd_data_signal_control_nick, qcd_data_relaxed_control_nick, qcd_data_subtract_nicks, qcd_control_signal_subtract_nicks, qcd_control_relaxed_subtract_nicks in zip(*[plotData.plotdict[key] for key in self._plotdict_keys]): for nick in qcd_data_subtract_nicks: plotData.plotdict["root_objects"][qcd_data_shape_nick].Add(plotData.plotdict["root_objects"][nick], -1.0) yield_control_signal = tools.PoissonYield(plotData.plotdict["root_objects"][qcd_data_signal_control_nick])() for nick in qcd_control_signal_subtract_nicks: yield_bgk_control = tools.PoissonYield(plotData.plotdict["root_objects"][nick])() yield_control_signal -= yield_bgk_control yield_control_signal = uncertainties.ufloat(max(0.0, yield_control_signal.nominal_value), yield_control_signal.std_dev) yield_control_relaxed = tools.PoissonYield(plotData.plotdict["root_objects"][qcd_data_relaxed_control_nick])() for nick in qcd_control_relaxed_subtract_nicks: yield_bgk_control = tools.PoissonYield(plotData.plotdict["root_objects"][nick])() yield_control_relaxed -= yield_bgk_control yield_control_relaxed = uncertainties.ufloat(max(0.0, yield_control_relaxed.nominal_value), yield_control_relaxed.std_dev) scale_factor = yield_control_signal if yield_control_relaxed != 0.0: scale_factor /= yield_control_relaxed log.debug("Scale factor for process QCD (nick \"{nick}\") is {scale_factor}.".format(nick=qcd_data_shape_nick, scale_factor=scale_factor)) plotData.plotdict["root_objects"][qcd_data_shape_nick].Scale(scale_factor.nominal_value) final_yield = tools.PoissonYield(plotData.plotdict["root_objects"][qcd_data_shape_nick])() log.debug("Relative statistical uncertainty of the yield for process QCD (nick \"{nick}\") is {unc}.".format(nick=qcd_data_shape_nick, unc=final_yield.std_dev/final_yield.nominal_value if final_yield.nominal_value != 0.0 else 0.0)) plotData.metadata[qcd_data_shape_nick] = { "yield" : final_yield.nominal_value, "yield_unc" : final_yield.std_dev, "yield_unc_rel" : abs(final_yield.std_dev/final_yield.nominal_value if final_yield.nominal_value != 0.0 else 0.0), }
def run(self, plotData=None): super(EstimateWjets, self).run(plotData) for wjets_from_mc, wjets_shape_nick, wjets_data_control_nick, wjets_data_substract_nicks, wjets_mc_signal_nick, wjets_mc_control_nick in zip( *[plotData.plotdict[key] for key in self._plotdict_keys]): if not wjets_from_mc: yield_data_control = tools.PoissonYield( plotData.plotdict["root_objects"] [wjets_data_control_nick])() for nick in wjets_data_substract_nicks: yield_bkg_control = tools.PoissonYield( plotData.plotdict["root_objects"][nick])() if nick in plotData.metadata: yield_bkg_control = uncertainties.ufloat( plotData.metadata[nick].get( "yield", yield_bkg_control.nominal_value), plotData.metadata[nick].get( "yield_unc", yield_bkg_control.std_dev)) yield_data_control -= yield_bkg_control yield_data_control = max(0.0, yield_data_control) yield_mc_signal = tools.PoissonYield( plotData.plotdict["root_objects"][wjets_mc_signal_nick])() yield_mc_control = tools.PoissonYield( plotData.plotdict["root_objects"][wjets_mc_control_nick])() assert (yield_data_control * yield_mc_signal == 0.0) or (yield_mc_control != 0.0) final_yield = yield_data_control * yield_mc_signal if final_yield != 0.0: final_yield /= yield_mc_control log.debug( "Relative statistical uncertainty of the yield for process W+jets (nick \"{nick}\") is {unc}." .format(nick=wjets_shape_nick, unc=final_yield.std_dev / final_yield.nominal_value if final_yield.nominal_value != 0.0 else 0.0)) plotData.metadata[wjets_shape_nick] = { "yield": final_yield.nominal_value, "yield_unc": final_yield.std_dev, "yield_unc_rel": abs(final_yield.std_dev / final_yield.nominal_value if final_yield.nominal_value != 0.0 else 0.0), } integral_shape = tools.PoissonYield( plotData.plotdict["root_objects"][wjets_shape_nick])() if integral_shape != 0.0: scale_factor = final_yield / integral_shape log.debug( "Scale factor for process W+jets (nick \"{nick}\") is {scale_factor}." .format(nick=wjets_shape_nick, scale_factor=scale_factor)) plotData.plotdict["root_objects"][wjets_shape_nick].Scale( scale_factor.nominal_value)
def run(self, plotData=None): super(EstimateTtbar, self).run(plotData) for ttbar_shape_nick, ttbar_data_control_nick, ttbar_data_subtract_nicks, ttbar_mc_signal_nick, ttbar_mc_control_nick in zip( *[plotData.plotdict[key] for key in self._plotdict_keys]): yield_data_control = tools.PoissonYield( plotData.plotdict["root_objects"][ttbar_data_control_nick])() #print "data_control_yield from nick " + ttbar_data_control_nick + " : " + str(yield_data_control) for nick in ttbar_data_subtract_nicks: yield_bkg_control = tools.PoissonYield( plotData.plotdict["root_objects"][nick])() #print "\t minus " + nick + " : " + str(yield_bkg_control) if nick in plotData.metadata: yield_bkg_control = uncertainties.ufloat( plotData.metadata[nick].get( "yield", yield_bkg_control.nominal_value), plotData.metadata[nick].get("yield_unc", yield_bkg_control.std_dev)) yield_data_control -= yield_bkg_control #print "data_control_yield final " + str(yield_data_control) yield_data_control = max(0.0, yield_data_control) yield_mc_signal = tools.PoissonYield( plotData.plotdict["root_objects"][ttbar_mc_signal_nick])() yield_mc_control = tools.PoissonYield( plotData.plotdict["root_objects"][ttbar_mc_control_nick])() #print "data_mc_signal " + str(yield_mc_signal) #print "data_mc_control " + str(yield_mc_control) integral_shape = plotData.plotdict["root_objects"][ ttbar_shape_nick].Integral() final_yield = yield_mc_control / yield_data_control * integral_shape log.debug( "Relative statistical uncertainty of the yield for process ttbar+jets (nick \"{nick}\") is {unc}." .format(nick=ttbar_shape_nick, unc=final_yield.std_dev / final_yield.nominal_value if final_yield.nominal_value != 0.0 else 0.0)) plotData.metadata[ttbar_shape_nick] = { "yield": final_yield.nominal_value, "yield_unc": final_yield.std_dev, "yield_unc_rel": abs(final_yield.std_dev / final_yield.nominal_value if final_yield.nominal_value != 0.0 else 0.0), } if integral_shape != 0.0: scale_factor = integral_shape / final_yield #print "scale factor: " + str(scale_factor) log.debug( "Scale factor for process ttbar+jets (nick \"{nick}\") is {scale_factor}." .format(nick=ttbar_shape_nick, scale_factor=scale_factor)) plotData.plotdict["root_objects"][ttbar_shape_nick].Scale( scale_factor.nominal_value)
def run(self, plotData=None): super(EstimateQcdPrefit, self).run(plotData) # make sure that all necessary histograms are available for nicks in zip(*[plotData.plotdict[key] for key in self._plotdict_keys]): for nick in nicks: if isinstance(nick, basestring): assert isinstance(plotData.plotdict["root_objects"].get(nick), ROOT.TH1) elif (not isinstance(nick, float) and not isinstance(nick, bool)): for subnick in nick: assert isinstance(plotData.plotdict["root_objects"].get(subnick), ROOT.TH1) for qcd_shape_nick, qcd_yield_nick, qcd_yield_subtract_nicks, qcd_shape_subtract_nicks, qcd_extrapolation_factor_ss_os in zip(*[plotData.plotdict[key] for key in self._plotdict_keys]): ###################### # ------- Step 1 ----- # 1. Get Yield in Control region and subtract all backgrounds. yield_qcd = tools.PoissonYield(plotData.plotdict["root_objects"][qcd_yield_nick])() # estimate the QCD yield for nick in qcd_yield_subtract_nicks: yield_bkg = tools.PoissonYield(plotData.plotdict["root_objects"][nick])() yield_qcd -= yield_bkg yield_qcd = uncertainties.ufloat(max(0.0, yield_qcd.nominal_value), yield_qcd.std_dev) if(yield_qcd.nominal_value == 0.0): log.warning("QCD yield is 0!") ###################### # ------- Step 2 ----- # QCD shape # 1. Subtract the shapes of all backgrounds from data in the control region. # 2. Scale the qcd by the qcd_os_ss_extrapolation_factor to get the prefit estimate. # Sidemark: In this script the factor is supposed to be 1.0 because we want to determine the # factor with this first estimate. for nick in qcd_shape_subtract_nicks: plotData.plotdict["root_objects"][qcd_shape_nick].Add(plotData.plotdict["root_objects"][nick], -1.0/plotData.plotdict["qcd_scale_factor"]) shape_yield = tools.PoissonYield(plotData.plotdict["root_objects"][qcd_shape_nick])() if shape_yield != 0.0: qcd_extrapolation_factor_ss_os = 1.0 scale_factor = yield_qcd / shape_yield * qcd_extrapolation_factor_ss_os plotData.plotdict["root_objects"][qcd_shape_nick].Scale(scale_factor.nominal_value) #log.debug("Relative statistical uncertainty of the yield for process QCD (nick \"{nick}\") is {unc}.".format(nick=qcd_data_shape_nick, unc=final_yield.std_dev/final_yield.nominal_value if final_yield.nominal_value != 0.0 else 0.0)) final_yield_qcd = yield_qcd * qcd_extrapolation_factor_ss_os # save to be picked up plotData.metadata[qcd_shape_nick] = { "yield" : final_yield_qcd.nominal_value, "yield_unc" : final_yield_qcd.std_dev, "yield_unc_rel" : abs(final_yield_qcd.std_dev/final_yield_qcd.nominal_value if final_yield_qcd.nominal_value != 0.0 else 0.0), }
def run(self, plotData=None): super(EstimateQcd, self).run(plotData) # make sure that all necessary histograms are available for nicks in zip(*[plotData.plotdict[key] for key in self._plotdict_keys]): for nick in nicks: if isinstance(nick, basestring): assert isinstance(plotData.plotdict["root_objects"].get(nick), ROOT.TH1) elif (not isinstance(nick, float) and not isinstance(nick, bool)): for subnick in nick: assert isinstance(plotData.plotdict["root_objects"].get(subnick), ROOT.TH1) for qcd_shape_nick, qcd_yield_nick, qcd_yield_subtract_nicks, qcd_shape_subtract_nicks, qcd_extrapolation_factor_ss_os in zip(*[plotData.plotdict[key] for key in self._plotdict_keys]): yield_qcd = tools.PoissonYield(plotData.plotdict["root_objects"][qcd_yield_nick])() # estimate the QCD yield # print "yield qcd total: " + str(yield_qcd) for nick in qcd_yield_subtract_nicks: yield_bkg = tools.PoissonYield(plotData.plotdict["root_objects"][nick])() #print "minus " + nick + " " + str(yield_bkg) yield_qcd -= yield_bkg yield_qcd = uncertainties.ufloat(max(0.0, yield_qcd.nominal_value), yield_qcd.std_dev) if(yield_qcd.nominal_value == 0.0): log.warning("QCD yield is 0!") # QCD shape #print "shape total: " + str(tools.PoissonYield(plotData.plotdict["root_objects"][qcd_shape_nick])()) for nick in qcd_shape_subtract_nicks: #print "\t minus " + nick + " " + str(tools.PoissonYield(plotData.plotdict["root_objects"][nick])()) plotData.plotdict["root_objects"][qcd_shape_nick].Add(plotData.plotdict["root_objects"][nick], -1.0/plotData.plotdict["qcd_scale_factor"]) shape_yield = tools.PoissonYield(plotData.plotdict["root_objects"][qcd_shape_nick])() if shape_yield != 0.0: scale_factor = yield_qcd / shape_yield * qcd_extrapolation_factor_ss_os plotData.plotdict["root_objects"][qcd_shape_nick].Scale(scale_factor.nominal_value) #log.debug("Relative statistical uncertainty of the yield for process QCD (nick \"{nick}\") is {unc}.".format(nick=qcd_data_shape_nick, unc=final_yield.std_dev/final_yield.nominal_value if final_yield.nominal_value != 0.0 else 0.0)) final_yield_qcd = yield_qcd * qcd_extrapolation_factor_ss_os #print "QCD em estimation summary" #print "scale factor : " + str(scale_factor) #print "shape_yield :" + str(shape_yield) #print "yield_qcd :" + str(yield_qcd) # save to be picked up plotData.metadata[qcd_shape_nick] = { "yield" : final_yield_qcd.nominal_value, "yield_unc" : final_yield_qcd.std_dev, "yield_unc_rel" : abs(final_yield_qcd.std_dev/final_yield_qcd.nominal_value if final_yield_qcd.nominal_value != 0.0 else 0.0), }
def run(self, plotData=None): super(EstimateTtbar, self).run(plotData) # make sure that all necessary histograms are available for nicks in zip(*[plotData.plotdict[key] for key in self._plotdict_keys]): for nick in nicks: if isinstance(nick, basestring): assert isinstance(plotData.plotdict["root_objects"].get(nick), ROOT.TH1) elif not isinstance(nick, bool): for subnick in nick: assert isinstance(plotData.plotdict["root_objects"].get(subnick), ROOT.TH1) for ttbar_shape_nick, ttbar_data_control_nick, ttbar_data_subtract_nicks, ttbar_mc_signal_nick, ttbar_mc_control_nick in zip(*[plotData.plotdict[key] for key in self._plotdict_keys]): yield_data_control = tools.PoissonYield(plotData.plotdict["root_objects"][ttbar_data_control_nick])() #print "data_control_yield from nick " + ttbar_data_control_nick + " : " + str(yield_data_control) for nick in ttbar_data_subtract_nicks: yield_bkg_control = tools.PoissonYield(plotData.plotdict["root_objects"][nick])() #print "\t minus " + nick + " : " + str(yield_bkg_control) if nick in plotData.metadata: yield_bkg_control = uncertainties.ufloat( plotData.metadata[nick].get("yield", yield_bkg_control.nominal_value), plotData.metadata[nick].get("yield_unc", yield_bkg_control.std_dev) ) yield_data_control -= yield_bkg_control #print "data_control_yield final " + str(yield_data_control) yield_data_control = max(0.0, yield_data_control) yield_mc_signal = tools.PoissonYield(plotData.plotdict["root_objects"][ttbar_mc_signal_nick])() yield_mc_control = tools.PoissonYield(plotData.plotdict["root_objects"][ttbar_mc_control_nick])() #print "data_mc_signal " + str(yield_mc_signal) #print "data_mc_control " + str(yield_mc_control) integral_shape = plotData.plotdict["root_objects"][ttbar_shape_nick].Integral() final_yield = yield_mc_control / yield_data_control * integral_shape log.debug("Relative statistical uncertainty of the yield for process ttbar+jets (nick \"{nick}\") is {unc}.".format(nick=ttbar_shape_nick, unc=final_yield.std_dev/final_yield.nominal_value if final_yield.nominal_value != 0.0 else 0.0)) plotData.metadata[ttbar_shape_nick] = { "yield" : final_yield.nominal_value, "yield_unc" : final_yield.std_dev, "yield_unc_rel" : abs(final_yield.std_dev/final_yield.nominal_value if final_yield.nominal_value != 0.0 else 0.0), } if integral_shape != 0.0: scale_factor = integral_shape / final_yield #print "scale factor: " + str(scale_factor) log.debug("Scale factor for process ttbar+jets (nick \"{nick}\") is {scale_factor}.".format(nick=ttbar_shape_nick, scale_factor=scale_factor)) plotData.plotdict["root_objects"][ttbar_shape_nick].Scale(scale_factor.nominal_value)
def __init__(self, root_histogram): error = array.array("d", [0.0]) dims = root_histogram.GetDimension() integral_ranges=[] for dim in range(dims): if dim==0: integral_ranges.append(0) integral_ranges.append(root_histogram.GetNbinsX()+1) elif dim==1: integral_ranges.append(0) integral_ranges.append(root_histogram.GetNbinsY()+1) elif dim==2: integral_ranges.append(0) integral_ranges.append(root_histogram.GetNbinsZ()+1) integral_ranges.append(error) integral = root_histogram.IntegralAndError(*integral_ranges) error = error[0] #self.poisson_yield = uncertainties.ufloat(integral, error) self.poisson_yield = uncertainties.ufloat(integral, math.sqrt(abs(integral)))
def __init__(self, root_histogram): error = array.array("d", [0.0]) dims = root_histogram.GetDimension() integral_ranges = [] for dim in range(dims): if dim == 0: integral_ranges.append(0) integral_ranges.append(root_histogram.GetNbinsX() + 1) elif dim == 1: integral_ranges.append(0) integral_ranges.append(root_histogram.GetNbinsY() + 1) elif dim == 2: integral_ranges.append(0) integral_ranges.append(root_histogram.GetNbinsZ() + 1) integral_ranges.append(error) integral = root_histogram.IntegralAndError(*integral_ranges) error = error[0] #self.poisson_yield = uncertainties.ufloat(integral, error) self.poisson_yield = uncertainties.ufloat(integral, math.sqrt(abs(integral)))
def run(self, plotData=None): super(EstimateQcd, self).run(plotData) for qcd_data_shape_nick, qcd_data_yield_nick, qcd_data_control_nick, qcd_data_substract_nicks, qcd_extrapolation_factor_ss_os, qcd_subtract_shape in zip(*[plotData.plotdict[key] for key in self._plotdict_keys]): if qcd_subtract_shape: for nick in qcd_data_substract_nicks: plotData.plotdict["root_objects"][qcd_data_shape_nick].Add(plotData.plotdict["root_objects"][nick], -1.0/plotData.plotdict["qcd_scale_factor"]) plotData.plotdict["root_objects"][qcd_data_shape_nick].Scale(qcd_extrapolation_factor_ss_os) else: yield_data_control = tools.PoissonYield(plotData.plotdict["root_objects"][qcd_data_control_nick])() yield_qcd_control = yield_data_control for nick in qcd_data_substract_nicks: yield_bkg_control = tools.PoissonYield(plotData.plotdict["root_objects"][nick])() if nick in plotData.metadata: yield_bkg_control = uncertainties.ufloat( plotData.metadata[nick].get("yield", yield_bkg_control.nominal_value), plotData.metadata[nick].get("yield_unc", yield_bkg_control.std_dev) ) yield_qcd_control -= yield_bkg_control yield_qcd_control = max(0.0, yield_qcd_control) scale_factor = yield_qcd_control * qcd_extrapolation_factor_ss_os if yield_data_control != 0.0: scale_factor /= yield_data_control final_yield = tools.PoissonYield(plotData.plotdict["root_objects"][qcd_data_yield_nick])() * scale_factor log.debug("Relative statistical uncertainty of the yield for process QCD (nick \"{nick}\") is {unc}.".format(nick=qcd_data_shape_nick, unc=final_yield.std_dev/final_yield.nominal_value if final_yield.nominal_value != 0.0 else 0.0)) plotData.metadata[qcd_data_shape_nick] = { "yield" : final_yield.nominal_value, "yield_unc" : final_yield.std_dev, "yield_unc_rel" : abs(final_yield.std_dev/final_yield.nominal_value if final_yield.nominal_value != 0.0 else 0.0), } integral_shape = tools.PoissonYield(plotData.plotdict["root_objects"][qcd_data_shape_nick])() if integral_shape != 0.0: scale_factor = final_yield / integral_shape log.debug("Scale factor for process QCD (nick \"{nick}\") is {scale_factor}.".format(nick=qcd_data_shape_nick, scale_factor=scale_factor)) plotData.plotdict["root_objects"][qcd_data_shape_nick].Scale(scale_factor.nominal_value)
def run(self, plotData=None): super(EstimateWjets, self).run(plotData) for wjets_from_mc, wjets_shape_nick, wjets_data_control_nick, wjets_data_substract_nicks, wjets_mc_signal_nick, wjets_mc_control_nick in zip(*[plotData.plotdict[key] for key in self._plotdict_keys]): if not wjets_from_mc: yield_data_control = tools.PoissonYield(plotData.plotdict["root_objects"][wjets_data_control_nick])() for nick in wjets_data_substract_nicks: yield_bkg_control = tools.PoissonYield(plotData.plotdict["root_objects"][nick])() if nick in plotData.metadata: yield_bkg_control = uncertainties.ufloat( plotData.metadata[nick].get("yield", yield_bkg_control.nominal_value), plotData.metadata[nick].get("yield_unc", yield_bkg_control.std_dev) ) yield_data_control -= yield_bkg_control yield_data_control = max(0.0, yield_data_control) yield_mc_signal = tools.PoissonYield(plotData.plotdict["root_objects"][wjets_mc_signal_nick])() yield_mc_control = tools.PoissonYield(plotData.plotdict["root_objects"][wjets_mc_control_nick])() assert (yield_data_control*yield_mc_signal == 0.0) or (yield_mc_control != 0.0) final_yield = yield_data_control * yield_mc_signal if final_yield != 0.0: final_yield /= yield_mc_control log.debug("Relative statistical uncertainty of the yield for process W+jets (nick \"{nick}\") is {unc}.".format(nick=wjets_shape_nick, unc=final_yield.std_dev/final_yield.nominal_value if final_yield.nominal_value != 0.0 else 0.0)) plotData.metadata[wjets_shape_nick] = { "yield" : final_yield.nominal_value, "yield_unc" : final_yield.std_dev, "yield_unc_rel" : abs(final_yield.std_dev/final_yield.nominal_value if final_yield.nominal_value != 0.0 else 0.0), } integral_shape = tools.PoissonYield(plotData.plotdict["root_objects"][wjets_shape_nick])() if integral_shape != 0.0: scale_factor = final_yield / integral_shape log.debug("Scale factor for process W+jets (nick \"{nick}\") is {scale_factor}.".format(nick=wjets_shape_nick, scale_factor=scale_factor)) plotData.plotdict["root_objects"][wjets_shape_nick].Scale(scale_factor.nominal_value)
)) plot_configs = [] datacards_workspaces = {} efficiency = {} for datacard, cb in datacards_cbs.iteritems(): for channel in cb.cp().analysis(["ztt"]).era(["13TeV"]).channel_set(): nPassPre = 0 nFailPre = 0 sig_process = cb.cp().bin([category]).signals().process_set() for category in cb.cp().analysis(["ztt"]).era(["13TeV"]).channel([channel]).bin_set(): if "pass" in category: nPassPre = uncertainties.ufloat(cb.cp().bin([category]).process(sig_process).GetRate(), cb.cp().bin([category]).process(sig_process).GetUncertainty()) elif "fail" in category: nFailPre = uncertainties.ufloat(cb.cp().bin([category]).process(sig_process).GetRate(), cb.cp().bin([category]).process(sig_process).GetUncertainty()) efficiency[channel] = nPassPre / (nPassPre + nFailPre) command = ["text2workspace.py -m {MASS} -P {MODEL} --PO \"eff={EFF}\" {DATACARD} -o {OUTPUT}".format( MASS=[mass for mass in cb.mass_set() if mass != "*"][0], MODEL=model_settings["P"], EFF=efficiency[channel].nominal_value, DATACARD=datacard, OUTPUT=os.path.splitext(datacard)[0]+".root")] print "command -->", command tools.parallelize(_call_command, command, n_processes=args.n_processes)
def run(self, plotData=None): super(EstimateQcd, self).run(plotData) # make sure that all necessary histograms are available for nicks in zip( *[plotData.plotdict[key] for key in self._plotdict_keys]): for nick in nicks: if isinstance(nick, basestring): assert isinstance( plotData.plotdict["root_objects"].get(nick), ROOT.TH1) elif (not isinstance(nick, float) and not isinstance(nick, bool)): for subnick in nick: assert isinstance( plotData.plotdict["root_objects"].get(subnick), ROOT.TH1) for qcd_shape_nick, qcd_yield_nick, qcd_yield_subtract_nicks, qcd_shape_subtract_nicks, qcd_extrapolation_factor_ss_os in zip( *[plotData.plotdict[key] for key in self._plotdict_keys]): yield_qcd = tools.PoissonYield( plotData.plotdict["root_objects"][qcd_yield_nick])() # estimate the QCD yield # print "yield qcd total: " + str(yield_qcd) for nick in qcd_yield_subtract_nicks: yield_bkg = tools.PoissonYield( plotData.plotdict["root_objects"][nick])() #print "minus " + nick + " " + str(yield_bkg) yield_qcd -= yield_bkg yield_qcd = uncertainties.ufloat(max(0.0, yield_qcd.nominal_value), yield_qcd.std_dev) if (yield_qcd.nominal_value == 0.0): log.warning("QCD yield is 0!") # QCD shape #print "shape total: " + str(tools.PoissonYield(plotData.plotdict["root_objects"][qcd_shape_nick])()) for nick in qcd_shape_subtract_nicks: #print "\t minus " + nick + " " + str(tools.PoissonYield(plotData.plotdict["root_objects"][nick])()) plotData.plotdict["root_objects"][qcd_shape_nick].Add( plotData.plotdict["root_objects"][nick], -1.0 / plotData.plotdict["qcd_scale_factor"]) shape_yield = tools.PoissonYield( plotData.plotdict["root_objects"][qcd_shape_nick])() if shape_yield != 0.0: scale_factor = yield_qcd / shape_yield * qcd_extrapolation_factor_ss_os plotData.plotdict["root_objects"][qcd_shape_nick].Scale( scale_factor.nominal_value) #log.debug("Relative statistical uncertainty of the yield for process QCD (nick \"{nick}\") is {unc}.".format(nick=qcd_data_shape_nick, unc=final_yield.std_dev/final_yield.nominal_value if final_yield.nominal_value != 0.0 else 0.0)) final_yield_qcd = yield_qcd * qcd_extrapolation_factor_ss_os #print "QCD em estimation summary" #print "scale factor : " + str(scale_factor) #print "shape_yield :" + str(shape_yield) #print "yield_qcd :" + str(yield_qcd) # save to be picked up plotData.metadata[qcd_shape_nick] = { "yield": final_yield_qcd.nominal_value, "yield_unc": final_yield_qcd.std_dev, "yield_unc_rel": abs(final_yield_qcd.std_dev / final_yield_qcd.nominal_value if final_yield_qcd.nominal_value != 0.0 else 0.0), }
def run(self, plotData=None): super(EstimateWjetsAndQCD, self).run(plotData) for qcd_extrapolation_factor_ss_os, qcd_shape_nick, qcd_ss_lowmt_nick, qcd_ss_highmt_shape_nick, qcd_os_highmt_nick, qcd_shape_highmt_substract_nick, qcd_yield_nick, qcd_shape_substract_nick, qcd_yield_substract_nick, wjets_os_highmt_mc_nick, wjets_ss_highmt_mc_nick, wjets_ss_substract_nick, wjets_ss_data_nick, wjets_os_substract_nick, wjets_os_data_nick, wjets_shape_nick, wjets_relaxed_os_highmt_nick, wjets_relaxed_os_lowmt_nick, wjets_scale_factor_shift, wjets_final_selection in zip(*[plotData.plotdict[key] for key in self._plotdict_keys]): ######################################## # estimate QCD for the highmT region # get qcd ss high mt shape for nick in qcd_shape_highmt_substract_nick+[wjets_ss_highmt_mc_nick]: plotData.plotdict["root_objects"][qcd_ss_highmt_shape_nick].Add(plotData.plotdict["root_objects"][nick], -1) # get qcd yield in ss high mt region yield_qcd_ss_highmt = tools.PoissonYield(plotData.plotdict["root_objects"][wjets_ss_data_nick])() for nick in wjets_ss_substract_nick+[wjets_ss_highmt_mc_nick]: yield_qcd_ss_highmt -= tools.PoissonYield(plotData.plotdict["root_objects"][nick])() yield_qcd_ss_highmt = max(uncertainties.ufloat(0.0, yield_qcd_ss_highmt.std_dev), yield_qcd_ss_highmt) # scale qcd ss high mt shape by qcd yield found in data integral_shape = tools.PoissonYield(plotData.plotdict["root_objects"][qcd_ss_highmt_shape_nick])() if integral_shape != 0.0: scale_factor = yield_qcd_ss_highmt / integral_shape plotData.plotdict["root_objects"][qcd_ss_highmt_shape_nick].Scale(scale_factor.nominal_value) # scale qcd os high mt shape by qcd yield found in ss data and ss->os extrapolation factor integral_shape = tools.PoissonYield(plotData.plotdict["root_objects"][qcd_os_highmt_nick])() if integral_shape != 0.0: scale_factor = yield_qcd_ss_highmt * qcd_extrapolation_factor_ss_os / integral_shape plotData.plotdict["root_objects"][qcd_os_highmt_nick].Scale(scale_factor.nominal_value) ######################################## # estimate W+jets # get w+jets yield in os high mt region yield_wjets_os_highmt = tools.PoissonYield(plotData.plotdict["root_objects"][wjets_os_data_nick])() for nick in wjets_os_substract_nick: yield_wjets_os_highmt -= tools.PoissonYield(plotData.plotdict["root_objects"][nick])() yield_wjets_os_highmt -= qcd_extrapolation_factor_ss_os*yield_qcd_ss_highmt yield_wjets_os_highmt = max(uncertainties.ufloat(0.0, yield_wjets_os_highmt.std_dev), yield_wjets_os_highmt) if yield_wjets_os_highmt.nominal_value == 0.0: log.warning("W+jets & QCD estimation: data yield in high mT region after background subtraction is 0!") # get high mt -> low mt extrapolation factor from MC if tools.PoissonYield(plotData.plotdict["root_objects"][wjets_relaxed_os_highmt_nick])() != 0.0: wjets_extrapolation_factor_mt = tools.PoissonYield(plotData.plotdict["root_objects"][wjets_relaxed_os_lowmt_nick])()/tools.PoissonYield(plotData.plotdict["root_objects"][wjets_relaxed_os_highmt_nick])() else: log.warning("W+jets & QCD estimation: W+jets high mT region in MC has no entries. High->low mT extrapolation factor is set to 1.0!") wjets_extrapolation_factor_mt = 1.0 # get w+jets yield in low mt region wjets_yield = yield_wjets_os_highmt*wjets_extrapolation_factor_mt # extrapolate to final selection if wjets_final_selection != None: wjets_yield = wjets_yield * tools.PoissonYield(plotData.plotdict["root_objects"][wjets_final_selection])() / tools.PoissonYield(plotData.plotdict["root_objects"][wjets_relaxed_os_lowmt_nick])() # scale signal region histograms integral_shape = tools.PoissonYield(plotData.plotdict["root_objects"][wjets_shape_nick])() if integral_shape != 0.0: scale_factor = wjets_yield / integral_shape log.debug("Scale factor for process W+jets (nick \"{nick}\") is {scale_factor}.".format(nick=wjets_shape_nick, scale_factor=scale_factor)) plotData.plotdict["root_objects"][wjets_shape_nick].Scale(scale_factor.nominal_value) plotData.metadata[wjets_shape_nick] = { "yield" : wjets_yield.nominal_value, "yield_unc" : wjets_yield.std_dev, "yield_unc_rel" : abs(wjets_yield.std_dev/wjets_yield.nominal_value if wjets_yield.nominal_value != 0.0 else 0.0), } ######################################## # estimate QCD for the lowmT # define w+jets scale factor for qcd estimation if tools.PoissonYield(plotData.plotdict["root_objects"][wjets_os_highmt_mc_nick])() != 0.0: wjets_scale_factor = yield_wjets_os_highmt/tools.PoissonYield(plotData.plotdict["root_objects"][wjets_os_highmt_mc_nick])() else: log.warning("W+jets & QCD estimation: W+jets high mT region in MC has no entries. Scale factor for W+jets in QCD estimation is set to 1.0!") wjets_scale_factor = uncertainties.ufloat(1.0, 0.0) for nick in qcd_shape_substract_nick: if "wj" in nick: scale_factor = wjets_scale_factor * wjets_scale_factor_shift plotData.plotdict["root_objects"][nick].Scale(scale_factor.nominal_value) plotData.plotdict["root_objects"][qcd_shape_nick].Add(plotData.plotdict["root_objects"][nick], -1) yield_qcd_ss_lowmt = tools.PoissonYield(plotData.plotdict["root_objects"][qcd_yield_nick])() for nick in qcd_yield_substract_nick: if "wj" in nick and tools.PoissonYield(plotData.plotdict["root_objects"][nick])() != 0.0: scale_factor = wjets_scale_factor * wjets_scale_factor_shift plotData.plotdict["root_objects"][nick].Scale(scale_factor.nominal_value) yield_qcd_ss_lowmt -= tools.PoissonYield(plotData.plotdict["root_objects"][nick])() yield_qcd_ss_lowmt = max(uncertainties.ufloat(0.0, yield_qcd_ss_lowmt.std_dev), yield_qcd_ss_lowmt) if yield_qcd_ss_lowmt.nominal_value == 0.0: log.warning("W+jets & QCD estimation: data yield in low mT SS region after background subtraction is 0!") # get qcd yield in low mt region qcd_yield = yield_qcd_ss_lowmt * qcd_extrapolation_factor_ss_os integral_shape = tools.PoissonYield(plotData.plotdict["root_objects"][qcd_shape_nick])() if integral_shape != 0.0: scale_factor = qcd_yield / integral_shape plotData.plotdict["root_objects"][qcd_shape_nick].Scale(scale_factor.nominal_value) integral_shape = tools.PoissonYield(plotData.plotdict["root_objects"][qcd_ss_lowmt_nick])() if integral_shape != 0.0: scale_factor = yield_qcd_ss_lowmt / integral_shape plotData.plotdict["root_objects"][qcd_ss_lowmt_nick].Scale(scale_factor.nominal_value) # write relative uncertainties to metadata to pick them up with combine plotData.metadata[qcd_shape_nick] = { "yield" : qcd_yield.nominal_value, "yield_unc" : qcd_yield.std_dev, "yield_unc_rel" : abs(qcd_yield.std_dev/qcd_yield.nominal_value if qcd_yield.nominal_value != 0.0 else 0.0), }
def run(self, plotData=None): super(EstimateWjetsAndQCD, self).run(plotData) for qcd_extrapolation_factor_ss_os, qcd_shape_nick, qcd_ss_lowmt_nick, qcd_ss_highmt_shape_nick, qcd_os_highmt_nick, qcd_shape_highmt_substract_nick, qcd_yield_nick, qcd_shape_substract_nick, qcd_yield_substract_nick, wjets_ss_mc_nick, wjets_os_mc_nick, wjets_os_highmt_mc_nick, wjets_os_lowmt_mc_nick, wjets_ss_highmt_mc_nick, wjets_ss_substract_nick, wjets_ss_data_nick, wjets_os_substract_nick, wjets_os_data_nick, wjets_shape_nick in zip( *[plotData.plotdict[key] for key in self._plotdict_keys]): # estimate QCD for the lowmT for nick in qcd_shape_substract_nick: plotData.plotdict["root_objects"][qcd_shape_nick].Add( plotData.plotdict["root_objects"][nick], -1) yield_qcd_control = tools.PoissonYield( plotData.plotdict["root_objects"][qcd_yield_nick])() for nick in qcd_yield_substract_nick: yield_bkg_control = tools.PoissonYield( plotData.plotdict["root_objects"][nick])() if nick in plotData.metadata: yield_bkg_control = uncertainties.ufloat( plotData.metadata[nick].get( "yield", yield_bkg_control.nominal_value), plotData.metadata[nick].get("yield_unc", yield_bkg_control.std_dev)) yield_qcd_control -= yield_bkg_control yield_qcd_control = max(0.0, yield_qcd_control) integral_shape = tools.PoissonYield( plotData.plotdict["root_objects"][qcd_shape_nick])() if integral_shape != 0.0: scale_factor = yield_qcd_control * qcd_extrapolation_factor_ss_os / integral_shape plotData.plotdict["root_objects"][qcd_shape_nick].Scale( scale_factor.nominal_value) integral_shape = tools.PoissonYield( plotData.plotdict["root_objects"][qcd_ss_lowmt_nick])() if integral_shape != 0.0: scale_factor = yield_qcd_control / integral_shape plotData.plotdict["root_objects"][qcd_ss_lowmt_nick].Scale( scale_factor.nominal_value) # estimate W+jets yield_ss_control = tools.PoissonYield( plotData.plotdict["root_objects"][wjets_ss_data_nick])() for nick in wjets_ss_substract_nick: yield_bkg_control = tools.PoissonYield( plotData.plotdict["root_objects"][nick])() yield_ss_control -= yield_bkg_control yield_os_control = tools.PoissonYield( plotData.plotdict["root_objects"][wjets_os_data_nick])() for nick in wjets_os_substract_nick: yield_bkg_control = tools.PoissonYield( plotData.plotdict["root_objects"][nick])() yield_os_control -= yield_bkg_control wjets_extrapolation_factor_ss_os = tools.PoissonYield( plotData.plotdict["root_objects"] [wjets_os_mc_nick])() / tools.PoissonYield( plotData.plotdict["root_objects"][wjets_ss_mc_nick])() wjets_extrapolation_factor_mt = tools.PoissonYield( plotData.plotdict["root_objects"][wjets_os_lowmt_mc_nick] )() / tools.PoissonYield( plotData.plotdict["root_objects"][wjets_os_highmt_mc_nick])() wjets_yield = ( yield_os_control - qcd_extrapolation_factor_ss_os * yield_ss_control ) * wjets_extrapolation_factor_ss_os / ( wjets_extrapolation_factor_ss_os - qcd_extrapolation_factor_ss_os) * wjets_extrapolation_factor_mt # scale signal region histograms integral_shape = tools.PoissonYield( plotData.plotdict["root_objects"][wjets_shape_nick])() if integral_shape != 0.0: scale_factor = wjets_yield / integral_shape log.debug( "Scale factor for process W+jets (nick \"{nick}\") is {scale_factor}." .format(nick=wjets_shape_nick, scale_factor=scale_factor)) plotData.plotdict["root_objects"][wjets_shape_nick].Scale( scale_factor.nominal_value) integral_shape = tools.PoissonYield( plotData.plotdict["root_objects"][wjets_os_highmt_mc_nick])() if integral_shape != 0.0: scale_factor = wjets_yield / (integral_shape * wjets_extrapolation_factor_mt) log.debug( "Scale factor for process W+jets (nick \"{nick}\") is {scale_factor}." .format(nick=wjets_os_highmt_mc_nick, scale_factor=scale_factor)) plotData.plotdict["root_objects"][ wjets_os_highmt_mc_nick].Scale(scale_factor.nominal_value) integral_shape = tools.PoissonYield( plotData.plotdict["root_objects"][wjets_ss_highmt_mc_nick])() if integral_shape != 0.0: scale_factor = wjets_yield / (integral_shape * wjets_extrapolation_factor_mt * wjets_extrapolation_factor_ss_os) log.debug( "Scale factor for process W+jets (nick \"{nick}\") is {scale_factor}." .format(nick=wjets_ss_highmt_mc_nick, scale_factor=scale_factor)) plotData.plotdict["root_objects"][ wjets_ss_highmt_mc_nick].Scale(scale_factor.nominal_value) # estimate QCD for the highmT region for nick in qcd_shape_highmt_substract_nick + [ wjets_ss_highmt_mc_nick ]: plotData.plotdict["root_objects"][ qcd_ss_highmt_shape_nick].Add( plotData.plotdict["root_objects"][nick], -1) yield_qcd_ss_highmt = yield_ss_control - tools.PoissonYield( plotData.plotdict["root_objects"][wjets_ss_highmt_mc_nick])() yield_qcd_ss_highmt = max(0.0, yield_qcd_ss_highmt) integral_shape = tools.PoissonYield( plotData.plotdict["root_objects"][qcd_ss_highmt_shape_nick])() if integral_shape != 0.0: scale_factor = yield_qcd_ss_highmt / integral_shape plotData.plotdict["root_objects"][ qcd_ss_highmt_shape_nick].Scale(scale_factor.nominal_value) integral_shape = tools.PoissonYield( plotData.plotdict["root_objects"][qcd_os_highmt_nick])() if integral_shape != 0.0: scale_factor = yield_qcd_ss_highmt * qcd_extrapolation_factor_ss_os / integral_shape plotData.plotdict["root_objects"][qcd_os_highmt_nick].Scale( scale_factor.nominal_value)
def run(self, plotData=None): super(EstimateWjetsAndQCDSimEquationMethod, self).run(plotData) # make sure that all necessary histograms are available for nicks in zip(*[plotData.plotdict[key] for key in self._plotdict_keys[:-1]]): for nick in nicks: print(nick) if isinstance(nick, basestring): assert isinstance(plotData.plotdict["root_objects"].get(nick), ROOT.TH1) elif (not isinstance(nick, float) and not isinstance(nick, bool)): for subnick in nick: print(subnick) assert isinstance(plotData.plotdict["root_objects"].get(subnick), ROOT.TH1) for use_inclusive_wjets_mc, wjets_ss_mc_nick, wjets_os_mc_nick, wjets_D_mc_nick, wjets_A_mc_nick, wjets_C_mc_nick, wjets_B_mc_nick, wjets_C_data_nick, C_subtract_nicks, wjets_D_data_nick, D_subtract_nicks, wjets_C_shape_nick, wjets_B_shape_nick, wjets_A_shape_nick, wjets_D_shape_nick, qcd_extrapolation_factor_ss_os, qcd_os_highmt_nick, qcd_ss_highmt_nick, qcd_ss_lowmt_nick, qcd_ss_data_nick, qcd_shape_nick, B_subtract_nicks in zip(*[plotData.plotdict[key] for key in self._plotdict_keys]): ######################################## # ------------ Step 1 ------------------ # Measure W OS/SS factor from MonteCarlo # 1. Needs inclusive wj_mc for OS and SS # 2. Therefore the scale factor is the same in the high mt control region (mT>70) and the low mt signal like region. yield_wj_mc_os = tools.PoissonYield(plotData.plotdict["root_objects"][wjets_os_mc_nick])() yield_wj_mc_ss = tools.PoissonYield(plotData.plotdict["root_objects"][wjets_ss_mc_nick])() # correct negative yields yield_wj_mc_os = uncertainties.ufloat(max(0.0, yield_wj_mc_os.nominal_value), yield_wj_mc_os.std_dev) yield_wj_mc_ss = uncertainties.ufloat(max(0.0, yield_wj_mc_ss.nominal_value), yield_wj_mc_ss.std_dev) yield_wj_mc_os_highmt = tools.PoissonYield(plotData.plotdict["root_objects"][wjets_D_mc_nick])() yield_wj_mc_ss_highmt = tools.PoissonYield(plotData.plotdict["root_objects"][wjets_C_mc_nick])() assert (yield_wj_mc_os_highmt != 0.0) or (yield_wj_mc_ss_highmt != 0.0), "Yield of MC in opposite-sign or same-sign region is zero." # calculate w_os_ss factor and store it in the metadata if use_inclusive_wjets_mc: w_os_ss_extrapolation_factor = yield_wj_mc_os / yield_wj_mc_ss else: w_os_ss_extrapolation_factor = yield_wj_mc_os_highmt / yield_wj_mc_ss_highmt log.debug("W+jets Opposite sign Same-sign factor is \"{FACTOR}\".".format(FACTOR = w_os_ss_extrapolation_factor)) ######################################## # ------------ Step 2 ------------------ # Measure opposite-sign extrapolation factor from high Mt Control region (mT>70) to low Mt (mt<50) # 1. Needs wj_mc in opposite region for both mT regions. yield_wj_mc_os_highmt = tools.PoissonYield(plotData.plotdict["root_objects"][wjets_D_mc_nick])() yield_wj_mc_os_lowmt = tools.PoissonYield(plotData.plotdict["root_objects"][wjets_A_mc_nick])() assert (yield_wj_mc_os_highmt != 0.0) or (yield_wj_mc_os_lowmt != 0.0), "Yield of MC in opposite-sign lowmt or opposite-sign highmt region is zero." # calculate w_highmt_lowmt factor and store it in the metadata w_os_highmt_lowmt_extrapolation_factor = yield_wj_mc_os_lowmt/yield_wj_mc_os_highmt log.debug("W+jets Opposite-sign High mT to low mT factor is \"{FACTOR}\".".format(FACTOR = w_os_highmt_lowmt_extrapolation_factor)) ######################################## # ------------ Step 3 ------------------ # Measure same-sign extrapolation factor from high Mt Control region (mT>70) to low Mt (mt<50) # This is needed to get the first estimate for Qcd in the same-sign region. # 1. Needs wj_mc in opposite region for both mT regions. # calculate w_highmt_lowmt factor and store it in the metadata if tools.PoissonYield(plotData.plotdict["root_objects"][wjets_C_mc_nick])() != 0.0: w_ss_highmt_lowmt_extrapolation_factor = tools.PoissonYield(plotData.plotdict["root_objects"][wjets_B_mc_nick])()/tools.PoissonYield(plotData.plotdict["root_objects"][wjets_C_mc_nick])() else: log.warning("W+jets & QCD estimation: W+jets high mT region in MC has no entries. High->low mT extrapolation factor is set to 1.0!") w_ss_highmt_lowmt_extrapolation_factor = 1.0 log.debug("W+jets Same-sign High mT to low mT factor is \"{FACTOR}\".".format(FACTOR = w_ss_highmt_lowmt_extrapolation_factor)) ######################################## # ------------ Step 4 ------------------ # Estimate same-sign lowMt QCD with inverted isolation # 1. Get the QCD OS/SS extrapolation factor which is measured using the makePlots_datacardsQCDfactors script. # qcd_extrapolation_factor_ss_os ######################################## # ------------ Step 5 ------------------ # Estimate highmt same-sign W+jets yield # 1. Get data yield in same-sign highmt region # 2. Subtract all MC backgrounds from same-sign highmt region from it. # 3. Scale it by the qcd_ss_os_extrapolation_factor # 4. Get data yield in opposite sign high mt region # 5. Subtract all MC backgrounds from opposite-sign highmt region from it. # 6. Subtract the estimate for the yield for same-sign highmt from it. # 7. Scale it by the differene between the W+jets and QCD extrapolation factor. # 8. Scale the shape according to the scale factor. yield_wjets_ss_highmt = tools.PoissonYield(plotData.plotdict["root_objects"][wjets_C_data_nick])() for nick in C_subtract_nicks: yield_wjets_ss_highmt -= tools.PoissonYield(plotData.plotdict["root_objects"][nick])() log.debug("W+jets Same-sign High mT before estimation yield is \"{YIELD}\".".format(YIELD = yield_wjets_ss_highmt)) yield_wjets_ss_highmt = uncertainties.ufloat(max(0.0, yield_wjets_ss_highmt.nominal_value), yield_wjets_ss_highmt.std_dev) yield_qcd_ss_highmt = yield_wjets_ss_highmt yield_wjets_os_highmt = tools.PoissonYield(plotData.plotdict["root_objects"][wjets_D_data_nick])() for nick in D_subtract_nicks: yield_wjets_os_highmt -= tools.PoissonYield(plotData.plotdict["root_objects"][nick])() yield_wjets_os_highmt = uncertainties.ufloat(max(0.0, yield_wjets_os_highmt.nominal_value), yield_wjets_os_highmt.std_dev) log.debug("W+jets Same-sign High mT before estimation yield is \"{YIELD}\".".format(YIELD = yield_wjets_ss_highmt)) log.debug("W+jets opposite-sign High mT before estimation yield is \"{YIELD}\".".format(YIELD = yield_wjets_os_highmt)) print(qcd_extrapolation_factor_ss_os * yield_wjets_ss_highmt) yield_wjets_ss_highmt = yield_wjets_os_highmt - qcd_extrapolation_factor_ss_os * yield_wjets_ss_highmt # yield_wjets_ss_highmt = uncertainties.ufloat(max(0.0, yield_wjets_ss_highmt.nominal_value), yield_wjets_ss_highmt.std_dev) yield_wjets_ss_highmt = yield_wjets_ss_highmt / (w_os_ss_extrapolation_factor - qcd_extrapolation_factor_ss_os) log.debug("W+jets Same-sign High mT after estimation yield is \"{YIELD}\".".format(YIELD = yield_wjets_ss_highmt)) yield_wjets_ss_highmt = uncertainties.ufloat(max(0.0, yield_wjets_ss_highmt.nominal_value), yield_wjets_ss_highmt.std_dev) log.debug("W+jets Same-sign High mT after estimation yield is \"{YIELD}\".".format(YIELD = yield_wjets_ss_highmt)) # store the eyield that might be expected for QCD after having determined Wjets in the highmt ss region yield_qcd_ss_highmt -= yield_wjets_ss_highmt if yield_wjets_ss_highmt.nominal_value == 0.0: log.warning("W+jets & QCD estimation: data yield in high mT same-sign region after background subtraction is 0!") # scale same-sign highmt Wjets histograms for controlplots. integral_shape = tools.PoissonYield(plotData.plotdict["root_objects"][wjets_C_shape_nick])() if integral_shape != 0.0: scale_factor = yield_wjets_ss_highmt / integral_shape log.debug("Scale factor for process W+jets (nick \"{nick}\") is {scale_factor}.".format(nick=wjets_C_shape_nick, scale_factor=scale_factor)) plotData.plotdict["root_objects"][wjets_C_shape_nick].Scale(scale_factor.nominal_value) plotData.plotdict["root_objects"][wjets_C_shape_nick].Print() ######################################## # ------------ Step 6 a ------------------ # Estimate final opposite-sign lowmT W+jets yield # 1. Multiply yield from before the Wjets OS/SS and the low-highmt factor. # 2. Scale the shape nicks by the resulting scale factor. final_yield_wjets_os_lowmt = w_os_highmt_lowmt_extrapolation_factor * w_os_ss_extrapolation_factor * yield_wjets_ss_highmt log.debug("W+jets Opposite-sign low mT yield is \"{YIELD}\".".format(YIELD = final_yield_wjets_os_lowmt)) if final_yield_wjets_os_lowmt.nominal_value == 0.0: log.warning("W+jets estimation: Final yield in low mT opposite-sign is 0!") # scale same-sign highmt Wjets histograms for controlplots. integral_shape = tools.PoissonYield(plotData.plotdict["root_objects"][wjets_A_shape_nick])() if integral_shape != 0.0: scale_factor = final_yield_wjets_os_lowmt/integral_shape log.debug("Scale factor for process W+jets (nick \"{nick}\") is {scale_factor}.".format(nick=wjets_A_shape_nick, scale_factor=scale_factor)) plotData.plotdict["root_objects"][wjets_A_shape_nick].Scale(scale_factor.nominal_value) plotData.plotdict["root_objects"][wjets_A_shape_nick].Print() ######################################## # ------------ Step 6 b ------------------ # Estimate final same-sign lowmT W+jets yield # 1. Multiply yield from before the Wjets OS/SS and the low-highmt factor. # 2. Scale the shape nicks by the resulting scale factor. final_yield_wjets_ss_lowmt = w_ss_highmt_lowmt_extrapolation_factor * yield_wjets_ss_highmt log.debug("W+jets Same-sign low mT yield is \"{YIELD}\".".format(YIELD = final_yield_wjets_ss_lowmt)) if final_yield_wjets_ss_lowmt.nominal_value == 0.0: log.warning("W+jets estimation: Final yield in low mT same-sign is 0!") # scale same-sign highmt Wjets histograms for controlplots. integral_shape = tools.PoissonYield(plotData.plotdict["root_objects"][wjets_B_shape_nick])() if integral_shape != 0.0: scale_factor = final_yield_wjets_ss_lowmt / integral_shape log.debug("Scale factor for process W+jets (nick \"{nick}\") is {scale_factor}.".format(nick=wjets_B_shape_nick, scale_factor=scale_factor)) plotData.plotdict["root_objects"][wjets_B_shape_nick].Scale(scale_factor.nominal_value) plotData.plotdict["root_objects"][wjets_B_shape_nick].Print() ######################################## # ------------ Step 6 c ------------------ # Estimate final opposite-sign highmT W+jets yield # 1. Multiply yield from before the Wjets OS/SS factor. # 2. Scale the shape nicks by the resulting scale factor. final_yield_wjets_os_highmt = w_os_ss_extrapolation_factor * yield_wjets_ss_highmt log.debug("W+jets opposite-sign high mT yield is \"{YIELD}\".".format(YIELD = final_yield_wjets_os_highmt)) if final_yield_wjets_os_highmt.nominal_value == 0.0: log.warning("W+jets estimation: Final yield in low mT same-sign is 0!") # scale same-sign highmt Wjets histograms for controlplots. integral_shape = tools.PoissonYield(plotData.plotdict["root_objects"][wjets_D_shape_nick])() if integral_shape != 0.0: scale_factor = final_yield_wjets_os_highmt / integral_shape log.debug("Scale factor for process W+jets (nick \"{nick}\") is {scale_factor}.".format(nick=wjets_D_shape_nick, scale_factor=scale_factor)) plotData.plotdict["root_objects"][wjets_D_shape_nick].Scale(scale_factor.nominal_value) plotData.plotdict["root_objects"][wjets_D_shape_nick].Print() plotData.metadata[wjets_A_shape_nick] = { "w_os_ss_factor" : w_os_ss_extrapolation_factor.nominal_value, "w_os_ss_factor_unc" : w_os_ss_extrapolation_factor.std_dev, "w_os_ss_factor_unc_rel" : abs(w_os_ss_extrapolation_factor.std_dev/w_os_ss_extrapolation_factor.nominal_value if w_os_ss_extrapolation_factor.nominal_value != 0.0 else 0.0), "w_os_highmt_lowmt_factor" : w_os_highmt_lowmt_extrapolation_factor.nominal_value, "w_os_highmt_lowmt_factor_unc" : w_os_highmt_lowmt_extrapolation_factor.std_dev, "w_os_highmt_lowmt_factor_unc_rel" : abs(w_os_highmt_lowmt_extrapolation_factor.std_dev/w_os_highmt_lowmt_extrapolation_factor.nominal_value if w_os_highmt_lowmt_extrapolation_factor.nominal_value != 0.0 else 0.0), "w_ss_highmt_lowmt_factor" : w_ss_highmt_lowmt_extrapolation_factor.nominal_value, "w_ss_highmt_lowmt_factor_unc" : w_ss_highmt_lowmt_extrapolation_factor.std_dev, "w_ss_highmt_lowmt_factor_unc_rel" : abs(w_ss_highmt_lowmt_extrapolation_factor.std_dev/w_ss_highmt_lowmt_extrapolation_factor.nominal_value if w_ss_highmt_lowmt_extrapolation_factor.nominal_value != 0.0 else 0.0), "w_ss_highmt_yield" : yield_wjets_ss_highmt.nominal_value, "w_ss_highmt_yield_unc" : yield_wjets_ss_highmt.std_dev, "w_ss_highmt_yield_unc_rel" : abs(yield_wjets_ss_highmt.std_dev/yield_wjets_ss_highmt.nominal_value if yield_wjets_ss_highmt.nominal_value != 0.0 else 0.0), "w_os_lowmt_yield" : final_yield_wjets_os_lowmt.nominal_value, "w_os_lowmt_yield_unc" : final_yield_wjets_os_lowmt.std_dev, "w_os_lowmt_yield_unc_rel" : abs(final_yield_wjets_os_lowmt.std_dev/final_yield_wjets_os_lowmt.nominal_value if final_yield_wjets_os_lowmt.nominal_value != 0.0 else 0.0), "w_ss_lowmt_yield" : final_yield_wjets_ss_lowmt.nominal_value, "w_ss_lowmt_yield_unc" : final_yield_wjets_ss_lowmt.std_dev, "w_ss_lowmt_yield_unc_rel" : abs(final_yield_wjets_ss_lowmt.std_dev/final_yield_wjets_ss_lowmt.nominal_value if final_yield_wjets_ss_lowmt.nominal_value != 0.0 else 0.0), } log.debug(plotData.metadata) ######################################## # ------------ Step 7 ------------------ # Get a opposite-sign region QCD estimate # 1. Get same-sign low-mt data yield. # 2. Subtract all background except for Wjets from it. # 3. Calculate same-sign lowmt Wjets estimate using the highMt estimte from step 5. # 4. Subtract also Wjets to get the same-sign QCD yield. # 5. Get the shapes for all histograms and background and get a QCD shape estimate yield_qcd_ss = tools.PoissonYield(plotData.plotdict["root_objects"][qcd_ss_data_nick])() for nick in B_subtract_nicks: yield_qcd_ss -= tools.PoissonYield(plotData.plotdict["root_objects"][nick])() yield_qcd_ss -= tools.PoissonYield(plotData.plotdict["root_objects"][wjets_B_shape_nick])() yield_qcd_ss = uncertainties.ufloat(max(0.0, yield_qcd_ss.nominal_value), yield_qcd_ss.std_dev) log.debug("QCD Same-sign yield is \"{YIELD}\".".format(YIELD = yield_qcd_ss)) if yield_qcd_ss.nominal_value == 0.0: log.warning("QCD estimation: yield in low mT same-sign is 0!") for nick in B_subtract_nicks: plotData.plotdict["root_objects"][qcd_shape_nick].Add(plotData.plotdict["root_objects"][nick], -1) plotData.plotdict["root_objects"][qcd_shape_nick].Add(plotData.plotdict["root_objects"][wjets_B_shape_nick], -1) qcd_shape_yield = tools.PoissonYield(plotData.plotdict["root_objects"][qcd_shape_nick])() qcd_shape_yield = uncertainties.ufloat(max(0.0, qcd_shape_yield.nominal_value), qcd_shape_yield.std_dev) yield_qcd_os = yield_qcd_ss * qcd_extrapolation_factor_ss_os if qcd_shape_yield.nominal_value != 0: scale_factor = yield_qcd_os / qcd_shape_yield log.debug("Scale factor for process QCD (nick \"{nick}\") is {scale_factor}.".format(nick=qcd_shape_nick, scale_factor=scale_factor)) plotData.plotdict["root_objects"][qcd_shape_nick].Scale(scale_factor.nominal_value) plotData.plotdict["root_objects"][qcd_shape_nick].Print() plotData.metadata[qcd_shape_nick] = { "QCD SS/OS factor" : qcd_extrapolation_factor_ss_os, "QCD Opposite-sign yield" : yield_qcd_os.nominal_value, "QCD Opposite-sign yield_unc" : yield_qcd_os.std_dev, "QCD Opposite-sign yield_unc_rel" : abs(yield_qcd_os.std_dev/yield_qcd_os.nominal_value if yield_qcd_os.nominal_value != 0.0 else 0.0), } qcd_shape_yield = tools.PoissonYield(plotData.plotdict["root_objects"][qcd_ss_lowmt_nick])() qcd_shape_yield = uncertainties.ufloat(max(0.0, qcd_shape_yield.nominal_value), qcd_shape_yield.std_dev) if qcd_shape_yield.nominal_value != 0: scale_factor = yield_qcd_ss / qcd_shape_yield log.debug("Scale factor for process QCD (nick \"{nick}\") is {scale_factor}.".format(nick=qcd_ss_lowmt_nick, scale_factor=scale_factor)) plotData.plotdict["root_objects"][qcd_ss_lowmt_nick].Scale(scale_factor.nominal_value) plotData.plotdict["root_objects"][qcd_ss_lowmt_nick].Print() plotData.metadata[qcd_shape_nick] = { "QCD Same-sign yield" : yield_qcd_ss.nominal_value, "QCD Same-sign yield_unc" : yield_qcd_ss.std_dev, "QCD Same-sign yield_unc_rel" : abs(yield_qcd_ss.std_dev/yield_qcd_ss.nominal_value if yield_qcd_ss.nominal_value != 0.0 else 0.0), } qcd_shape_yield = tools.PoissonYield(plotData.plotdict["root_objects"][qcd_ss_highmt_nick])() qcd_shape_yield = uncertainties.ufloat(max(0.0, qcd_shape_yield.nominal_value), qcd_shape_yield.std_dev) if qcd_shape_yield.nominal_value != 0: scale_factor = yield_qcd_ss_highmt / qcd_shape_yield log.debug("Scale factor for process QCD (nick \"{nick}\") is {scale_factor}.".format(nick=qcd_ss_highmt_nick, scale_factor=scale_factor)) plotData.plotdict["root_objects"][qcd_ss_highmt_nick].Scale(scale_factor.nominal_value) plotData.plotdict["root_objects"][qcd_ss_highmt_nick].Print() plotData.metadata[qcd_shape_nick] = { "QCD Same-sign highmt yield" : yield_qcd_ss_highmt.nominal_value, "QCD Same-sign highmt yield_unc" : yield_qcd_ss_highmt.std_dev, "QCD Same-sign highmt yield_unc_rel" : abs(yield_qcd_ss_highmt.std_dev/yield_qcd_ss_highmt.nominal_value if yield_qcd_ss_highmt.nominal_value != 0.0 else 0.0), } qcd_shape_yield = tools.PoissonYield(plotData.plotdict["root_objects"][qcd_os_highmt_nick])() qcd_shape_yield = uncertainties.ufloat(max(0.0, qcd_shape_yield.nominal_value), qcd_shape_yield.std_dev) if qcd_shape_yield.nominal_value != 0: scale_factor = yield_qcd_ss_highmt * qcd_extrapolation_factor_ss_os / qcd_shape_yield log.debug("Scale factor for process QCD (nick \"{nick}\") is {scale_factor}.".format(nick=qcd_os_highmt_nick, scale_factor=scale_factor)) plotData.plotdict["root_objects"][qcd_os_highmt_nick].Scale(scale_factor.nominal_value) plotData.plotdict["root_objects"][qcd_os_highmt_nick].Print() plotData.metadata[qcd_shape_nick] = { "QCD opposite-sign highmt yield" : yield_qcd_ss_highmt.nominal_value, "QCD opposite-sign highmt yield_unc" : yield_qcd_ss_highmt.std_dev, "QCD opposite-sign highmt yield_unc_rel" : abs(yield_qcd_ss_highmt.std_dev/yield_qcd_ss_highmt.nominal_value if yield_qcd_ss_highmt.nominal_value != 0.0 else 0.0), }
def run(self, plotData=None): super(UnpolarisationScaleFactors, self).run(plotData) for unpolarisation_nominal_nick, unpolarisation_shift_up_nick, unpolarisation_shift_down_nick, unpolarisation_forced_gen_polarisation in zip( *[ plotData.plotdict[key] for key in [ "unpolarisation_nominal_nicks", "unpolarisation_shift_up_nicks", "unpolarisation_shift_down_nicks", "unpolarisation_forced_gen_polarisations" ] ]): scale_factors = {} scale_factors_pos = {} scale_factors_neg = {} for shift, nick in zip(*[["nominal", "shift up", "shift down"], [ unpolarisation_nominal_nick, unpolarisation_shift_up_nick, unpolarisation_shift_down_nick ]]): neg_gen_norm = uncertainties.ufloat( plotData.plotdict["root_objects"][nick].GetBinContent(1), plotData.plotdict["root_objects"][nick].GetBinError(1)) pos_gen_norm = uncertainties.ufloat( plotData.plotdict["root_objects"][nick].GetBinContent(2), plotData.plotdict["root_objects"][nick].GetBinError(2)) scale_factors[ shift] = polarisationsignalscaling.PolarisationScaleFactors( pos_gen_norm, neg_gen_norm, pos_gen_norm, neg_gen_norm, forced_gen_polarisation= unpolarisation_forced_gen_polarisation) scale_factors_pos[shift] = scale_factors[ shift].get_bias_removal_factor_pospol( ) if plotData.plotdict[ "unpolarisation_remove_bias_instead_unpolarisation"] else scale_factors[ shift].get_scale_factor_pospol() log.debug( "Positive helicity of \"{nick}\" to be scaled by a factor of {factor} ({shift})." .format(nick=nick, factor=scale_factors_pos[shift], shift=shift)) scale_factors_neg[shift] = scale_factors[ shift].get_bias_removal_factor_neg_pol( ) if plotData.plotdict[ "unpolarisation_remove_bias_instead_unpolarisation"] else scale_factors[ shift].get_scale_factor_negpol() log.debug( "Negative helicity of \"{nick}\" to be scaled by a factor of {factor} ({shift})." .format(nick=nick, factor=scale_factors_neg[shift], shift=shift)) total_uncertainties_pos = [ abs((scale_factors_pos["shift up"] - scale_factors_pos["nominal"]) / scale_factors_pos["nominal"]), abs((scale_factors_pos["shift down"] - scale_factors_pos["nominal"]) / scale_factors_pos["nominal"]) ] total_uncertainties_neg = [ abs((scale_factors_neg["shift up"] - scale_factors_neg["nominal"]) / scale_factors_neg["nominal"]), abs((scale_factors_neg["shift down"] - scale_factors_neg["nominal"]) / scale_factors_neg["nominal"]) ] log.info( "Total uncertainties on scale factor for positive helicity = (+) {tot_pos_plus} / (-) {tot_pos_minus}" .format(tot_pos_plus=total_uncertainties_pos[0], tot_pos_minus=total_uncertainties_pos[1])) log.info( "Total uncertainties on scale factor for negative helicity = (+) {tot_neg_plus} / (-) {tot_neg_minus}" .format(tot_neg_plus=total_uncertainties_neg[0], tot_neg_minus=total_uncertainties_neg[1]))
def run(self, plotData=None): super(EstimateQcdTauHadTauHad, self).run(plotData) # make sure that all necessary histograms are available for nicks in zip( *[plotData.plotdict[key] for key in self._plotdict_keys]): for nick in nicks: if isinstance(nick, basestring): assert isinstance( plotData.plotdict["root_objects"].get(nick), ROOT.TH1) elif (not isinstance(nick, float) and not isinstance(nick, bool)): for subnick in nick: assert isinstance( plotData.plotdict["root_objects"].get(subnick), ROOT.TH1) for qcd_data_shape_nick, qcd_data_signal_control_nick, qcd_data_relaxed_control_nick, qcd_data_subtract_nicks, qcd_control_signal_subtract_nicks, qcd_control_relaxed_subtract_nicks in zip( *[plotData.plotdict[key] for key in self._plotdict_keys]): for nick in qcd_data_subtract_nicks: plotData.plotdict["root_objects"][qcd_data_shape_nick].Add( plotData.plotdict["root_objects"][nick], -1.0) yield_control_signal = tools.PoissonYield( plotData.plotdict["root_objects"] [qcd_data_signal_control_nick])() for nick in qcd_control_signal_subtract_nicks: yield_bgk_control = tools.PoissonYield( plotData.plotdict["root_objects"][nick])() yield_control_signal -= yield_bgk_control yield_control_signal = uncertainties.ufloat( max(0.0, yield_control_signal.nominal_value), yield_control_signal.std_dev) yield_control_relaxed = tools.PoissonYield( plotData.plotdict["root_objects"] [qcd_data_relaxed_control_nick])() for nick in qcd_control_relaxed_subtract_nicks: yield_bgk_control = tools.PoissonYield( plotData.plotdict["root_objects"][nick])() yield_control_relaxed -= yield_bgk_control yield_control_relaxed = uncertainties.ufloat( max(0.0, yield_control_relaxed.nominal_value), yield_control_relaxed.std_dev) scale_factor = yield_control_signal if yield_control_relaxed != 0.0: scale_factor /= yield_control_relaxed log.debug( "Scale factor for process QCD (nick \"{nick}\") is {scale_factor}." .format(nick=qcd_data_shape_nick, scale_factor=scale_factor)) plotData.plotdict["root_objects"][qcd_data_shape_nick].Scale( scale_factor.nominal_value) final_yield = tools.PoissonYield( plotData.plotdict["root_objects"][qcd_data_shape_nick])() log.debug( "Relative statistical uncertainty of the yield for process QCD (nick \"{nick}\") is {unc}." .format(nick=qcd_data_shape_nick, unc=final_yield.std_dev / final_yield.nominal_value if final_yield.nominal_value != 0.0 else 0.0)) plotData.metadata[qcd_data_shape_nick] = { "yield": final_yield.nominal_value, "yield_unc": final_yield.std_dev, "yield_unc_rel": abs(final_yield.std_dev / final_yield.nominal_value if final_yield.nominal_value != 0.0 else 0.0), }
def run(self, plotData=None): super(EstimateWjetsAndQCD, self).run(plotData) for qcd_extrapolation_factor_ss_os, qcd_shape_nick, qcd_ss_lowmt_nick, qcd_ss_highmt_shape_nick, qcd_os_highmt_nick, qcd_shape_highmt_substract_nick, qcd_yield_nick, qcd_shape_substract_nick, qcd_yield_substract_nick, wjets_os_highmt_mc_nick, wjets_ss_highmt_mc_nick, wjets_ss_substract_nick, wjets_ss_data_nick, wjets_os_substract_nick, wjets_os_data_nick, wjets_shape_nick, wjets_relaxed_os_highmt_nick, wjets_relaxed_os_lowmt_nick, wjets_scale_factor_shift, wjets_final_selection in zip( *[plotData.plotdict[key] for key in self._plotdict_keys]): ######################################## # estimate QCD for the highmT region # get qcd ss high mt shape for nick in qcd_shape_highmt_substract_nick + [ wjets_ss_highmt_mc_nick ]: plotData.plotdict["root_objects"][ qcd_ss_highmt_shape_nick].Add( plotData.plotdict["root_objects"][nick], -1) # get qcd yield in ss high mt region yield_qcd_ss_highmt = tools.PoissonYield( plotData.plotdict["root_objects"][wjets_ss_data_nick])() for nick in wjets_ss_substract_nick + [wjets_ss_highmt_mc_nick]: yield_qcd_ss_highmt -= tools.PoissonYield( plotData.plotdict["root_objects"][nick])() yield_qcd_ss_highmt = max( uncertainties.ufloat(0.0, yield_qcd_ss_highmt.std_dev), yield_qcd_ss_highmt) # scale qcd ss high mt shape by qcd yield found in data integral_shape = tools.PoissonYield( plotData.plotdict["root_objects"][qcd_ss_highmt_shape_nick])() if integral_shape != 0.0: scale_factor = yield_qcd_ss_highmt / integral_shape plotData.plotdict["root_objects"][ qcd_ss_highmt_shape_nick].Scale(scale_factor.nominal_value) # scale qcd os high mt shape by qcd yield found in ss data and ss->os extrapolation factor integral_shape = tools.PoissonYield( plotData.plotdict["root_objects"][qcd_os_highmt_nick])() if integral_shape != 0.0: scale_factor = yield_qcd_ss_highmt * qcd_extrapolation_factor_ss_os / integral_shape plotData.plotdict["root_objects"][qcd_os_highmt_nick].Scale( scale_factor.nominal_value) ######################################## # estimate W+jets # get w+jets yield in os high mt region yield_wjets_os_highmt = tools.PoissonYield( plotData.plotdict["root_objects"][wjets_os_data_nick])() for nick in wjets_os_substract_nick: yield_wjets_os_highmt -= tools.PoissonYield( plotData.plotdict["root_objects"][nick])() yield_wjets_os_highmt -= qcd_extrapolation_factor_ss_os * yield_qcd_ss_highmt yield_wjets_os_highmt = max( uncertainties.ufloat(0.0, yield_wjets_os_highmt.std_dev), yield_wjets_os_highmt) if yield_wjets_os_highmt.nominal_value == 0.0: log.warning( "W+jets & QCD estimation: data yield in high mT region after background subtraction is 0!" ) # get high mt -> low mt extrapolation factor from MC if tools.PoissonYield(plotData.plotdict["root_objects"] [wjets_relaxed_os_highmt_nick])() != 0.0: wjets_extrapolation_factor_mt = tools.PoissonYield( plotData.plotdict["root_objects"] [wjets_relaxed_os_lowmt_nick])() / tools.PoissonYield( plotData.plotdict["root_objects"] [wjets_relaxed_os_highmt_nick])() else: log.warning( "W+jets & QCD estimation: W+jets high mT region in MC has no entries. High->low mT extrapolation factor is set to 1.0!" ) wjets_extrapolation_factor_mt = 1.0 # get w+jets yield in low mt region wjets_yield = yield_wjets_os_highmt * wjets_extrapolation_factor_mt # extrapolate to final selection if wjets_final_selection != None: wjets_yield = wjets_yield * tools.PoissonYield( plotData.plotdict["root_objects"][wjets_final_selection])( ) / tools.PoissonYield(plotData.plotdict["root_objects"] [wjets_relaxed_os_lowmt_nick])() # scale signal region histograms integral_shape = tools.PoissonYield( plotData.plotdict["root_objects"][wjets_shape_nick])() if integral_shape != 0.0: scale_factor = wjets_yield / integral_shape log.debug( "Scale factor for process W+jets (nick \"{nick}\") is {scale_factor}." .format(nick=wjets_shape_nick, scale_factor=scale_factor)) plotData.plotdict["root_objects"][wjets_shape_nick].Scale( scale_factor.nominal_value) plotData.metadata[wjets_shape_nick] = { "yield": wjets_yield.nominal_value, "yield_unc": wjets_yield.std_dev, "yield_unc_rel": abs(wjets_yield.std_dev / wjets_yield.nominal_value if wjets_yield.nominal_value != 0.0 else 0.0), } ######################################## # estimate QCD for the lowmT # define w+jets scale factor for qcd estimation if tools.PoissonYield(plotData.plotdict["root_objects"] [wjets_os_highmt_mc_nick])() != 0.0: wjets_scale_factor = yield_wjets_os_highmt / tools.PoissonYield( plotData.plotdict["root_objects"] [wjets_os_highmt_mc_nick])() else: log.warning( "W+jets & QCD estimation: W+jets high mT region in MC has no entries. Scale factor for W+jets in QCD estimation is set to 1.0!" ) wjets_scale_factor = uncertainties.ufloat(1.0, 0.0) for nick in qcd_shape_substract_nick: if "wj" in nick: scale_factor = wjets_scale_factor * wjets_scale_factor_shift plotData.plotdict["root_objects"][nick].Scale( scale_factor.nominal_value) plotData.plotdict["root_objects"][qcd_shape_nick].Add( plotData.plotdict["root_objects"][nick], -1) yield_qcd_ss_lowmt = tools.PoissonYield( plotData.plotdict["root_objects"][qcd_yield_nick])() for nick in qcd_yield_substract_nick: if "wj" in nick and tools.PoissonYield( plotData.plotdict["root_objects"][nick])() != 0.0: scale_factor = wjets_scale_factor * wjets_scale_factor_shift plotData.plotdict["root_objects"][nick].Scale( scale_factor.nominal_value) yield_qcd_ss_lowmt -= tools.PoissonYield( plotData.plotdict["root_objects"][nick])() yield_qcd_ss_lowmt = max( uncertainties.ufloat(0.0, yield_qcd_ss_lowmt.std_dev), yield_qcd_ss_lowmt) if yield_qcd_ss_lowmt.nominal_value == 0.0: log.warning( "W+jets & QCD estimation: data yield in low mT SS region after background subtraction is 0!" ) # get qcd yield in low mt region qcd_yield = yield_qcd_ss_lowmt * qcd_extrapolation_factor_ss_os integral_shape = tools.PoissonYield( plotData.plotdict["root_objects"][qcd_shape_nick])() if integral_shape != 0.0: scale_factor = qcd_yield / integral_shape plotData.plotdict["root_objects"][qcd_shape_nick].Scale( scale_factor.nominal_value) integral_shape = tools.PoissonYield( plotData.plotdict["root_objects"][qcd_ss_lowmt_nick])() if integral_shape != 0.0: scale_factor = yield_qcd_ss_lowmt / integral_shape plotData.plotdict["root_objects"][qcd_ss_lowmt_nick].Scale( scale_factor.nominal_value) # write relative uncertainties to metadata to pick them up with combine plotData.metadata[qcd_shape_nick] = { "yield": qcd_yield.nominal_value, "yield_unc": qcd_yield.std_dev, "yield_unc_rel": abs(qcd_yield.std_dev / qcd_yield.nominal_value if qcd_yield.nominal_value != 0.0 else 0.0), }
def run(self, plotData=None): super(EstimateQcd, self).run(plotData) for qcd_data_shape_nick, qcd_data_yield_nick, qcd_data_control_nick, qcd_data_substract_nicks, qcd_extrapolation_factor_ss_os, qcd_subtract_shape in zip( *[plotData.plotdict[key] for key in self._plotdict_keys]): yield_data_control = tools.PoissonYield( plotData.plotdict["root_objects"][qcd_data_control_nick])() yield_qcd_control = yield_data_control for nick in qcd_data_substract_nicks: yield_bkg_control = tools.PoissonYield( plotData.plotdict["root_objects"][nick])() if nick in plotData.metadata: yield_bkg_control = uncertainties.ufloat( plotData.metadata[nick].get( "yield", yield_bkg_control.nominal_value), plotData.metadata[nick].get("yield_unc", yield_bkg_control.std_dev)) yield_qcd_control -= yield_bkg_control if qcd_subtract_shape: plotData.plotdict["root_objects"][ qcd_data_control_nick].Add( plotData.plotdict["root_objects"][nick], -1.0 / plotData.plotdict["qcd_scale_factor"]) if qcd_subtract_shape: plotData.plotdict["root_objects"][ qcd_data_shape_nick] = plotData.plotdict["root_objects"][ qcd_data_control_nick] yield_qcd_control = max(0.0, yield_qcd_control) scale_factor = yield_qcd_control * qcd_extrapolation_factor_ss_os if yield_data_control != 0.0: scale_factor /= yield_data_control final_yield = tools.PoissonYield( plotData.plotdict["root_objects"] [qcd_data_yield_nick])() * scale_factor log.debug( "Relative statistical uncertainty of the yield for process QCD (nick \"{nick}\") is {unc}." .format(nick=qcd_data_shape_nick, unc=final_yield.std_dev / final_yield.nominal_value if final_yield.nominal_value != 0.0 else 0.0)) plotData.metadata[qcd_data_shape_nick] = { "yield": final_yield.nominal_value, "yield_unc": final_yield.std_dev, "yield_unc_rel": abs(final_yield.std_dev / final_yield.nominal_value if final_yield.nominal_value != 0.0 else 0.0), } integral_shape = tools.PoissonYield( plotData.plotdict["root_objects"][qcd_data_shape_nick])() if integral_shape != 0.0: scale_factor = final_yield / integral_shape log.debug( "Scale factor for process QCD (nick \"{nick}\") is {scale_factor}." .format(nick=qcd_data_shape_nick, scale_factor=scale_factor)) plotData.plotdict["root_objects"][qcd_data_shape_nick].Scale( scale_factor.nominal_value)
def __init__(self, root_histogram): error = array.array("d", [0.0]) integral = root_histogram.IntegralAndError(1, root_histogram.GetNbinsX(), error) error = error[0] #self.poisson_yield = uncertainties.ufloat(integral, error) self.poisson_yield = uncertainties.ufloat(integral, math.sqrt(abs(integral)))
def run(self, plotData=None): super(EstimateWjetsAndQCD, self).run(plotData) for qcd_extrapolation_factor_ss_os, qcd_shape_nick, qcd_ss_lowmt_nick, qcd_ss_highmt_shape_nick, qcd_os_highmt_nick, qcd_shape_highmt_substract_nick, qcd_yield_nick, qcd_shape_substract_nick, qcd_yield_substract_nick, wjets_ss_mc_nick, wjets_os_mc_nick, wjets_os_highmt_mc_nick, wjets_os_lowmt_mc_nick, wjets_ss_highmt_mc_nick, wjets_ss_substract_nick, wjets_ss_data_nick, wjets_os_substract_nick, wjets_os_data_nick, wjets_shape_nick, wjets_final_selection in zip(*[plotData.plotdict[key] for key in self._plotdict_keys]): # estimate QCD for the lowmT for nick in qcd_shape_substract_nick: plotData.plotdict["root_objects"][qcd_shape_nick].Add(plotData.plotdict["root_objects"][nick], -1) yield_qcd_control = tools.PoissonYield(plotData.plotdict["root_objects"][qcd_yield_nick])() for nick in qcd_yield_substract_nick: yield_bkg_control = tools.PoissonYield(plotData.plotdict["root_objects"][nick])() if nick in plotData.metadata: yield_bkg_control = uncertainties.ufloat( plotData.metadata[nick].get("yield", yield_bkg_control.nominal_value), plotData.metadata[nick].get("yield_unc", yield_bkg_control.std_dev) ) yield_qcd_control -= yield_bkg_control yield_qcd_control = max(0.0, yield_qcd_control) integral_shape = tools.PoissonYield(plotData.plotdict["root_objects"][qcd_shape_nick])() if integral_shape != 0.0: scale_factor = yield_qcd_control * qcd_extrapolation_factor_ss_os / integral_shape final_qcd_yield = yield_qcd_control * qcd_extrapolation_factor_ss_os plotData.plotdict["root_objects"][qcd_shape_nick].Scale(scale_factor.nominal_value) integral_shape = tools.PoissonYield(plotData.plotdict["root_objects"][qcd_ss_lowmt_nick])() if integral_shape != 0.0: scale_factor = yield_qcd_control / integral_shape plotData.plotdict["root_objects"][qcd_ss_lowmt_nick].Scale(scale_factor.nominal_value) # write relative uncertainties to metadata to pick them up with combine plotData.metadata[qcd_shape_nick] = { "yield" : final_qcd_yield.nominal_value, "yield_unc" : final_qcd_yield.std_dev, "yield_unc_rel" : abs(final_qcd_yield.std_dev/final_qcd_yield.nominal_value if final_qcd_yield.nominal_value != 0.0 else 0.0), } # estimate W+jets yield_ss_control = tools.PoissonYield(plotData.plotdict["root_objects"][wjets_ss_data_nick])() for nick in wjets_ss_substract_nick: yield_bkg_control = tools.PoissonYield(plotData.plotdict["root_objects"][nick])() yield_ss_control -= yield_bkg_control yield_os_control = tools.PoissonYield(plotData.plotdict["root_objects"][wjets_os_data_nick])() for nick in wjets_os_substract_nick: yield_bkg_control = tools.PoissonYield(plotData.plotdict["root_objects"][nick])() yield_os_control -= yield_bkg_control wjets_extrapolation_factor_ss_os = tools.PoissonYield(plotData.plotdict["root_objects"][wjets_os_mc_nick])()/tools.PoissonYield(plotData.plotdict["root_objects"][wjets_ss_mc_nick])() wjets_extrapolation_factor_mt = tools.PoissonYield(plotData.plotdict["root_objects"][wjets_os_lowmt_mc_nick])()/tools.PoissonYield(plotData.plotdict["root_objects"][wjets_os_highmt_mc_nick])() wjets_yield = (yield_os_control-qcd_extrapolation_factor_ss_os*yield_ss_control)*wjets_extrapolation_factor_ss_os/(wjets_extrapolation_factor_ss_os-qcd_extrapolation_factor_ss_os)*wjets_extrapolation_factor_mt # extrapolate to final selection if wjets_final_selection != None: wjets_yield = wjets_yield * tools.PoissonYield(plotData.plotdict["root_objects"][wjets_final_selection])() / tools.PoissonYield(plotData.plotdict["root_objects"][wjets_os_lowmt_mc_nick])() #print "scale factor inclusive to categorized" #print str(tools.PoissonYield(plotData.plotdict["root_objects"][wjets_final_selection])() / tools.PoissonYield(plotData.plotdict["root_objects"][wjets_os_lowmt_mc_nick])()) #print "final selection " + str(tools.PoissonYield(plotData.plotdict["root_objects"][wjets_final_selection])()) #print "inclusive " + str(tools.PoissonYield(plotData.plotdict["root_objects"][wjets_os_lowmt_mc_nick])()) # scale signal region histograms integral_shape = tools.PoissonYield(plotData.plotdict["root_objects"][wjets_shape_nick])() #print "QCD/WJets estimation summary" #print "Extrapolation factors" #print "\t QCD OS/SS: " + str(qcd_extrapolation_factor_ss_os) #print "\t WJets OS/SS: " + str(wjets_extrapolation_factor_ss_os) #print "\t WJets high-low mT: " + str(wjets_extrapolation_factor_mt) #print "WJets yield" #print "\t before: " + str(integral_shape) #print "\t after: " + str(wjets_yield) #print "Scale factor: " + str(wjets_yield / integral_shape) if integral_shape != 0.0: scale_factor = wjets_yield / integral_shape log.debug("Scale factor for process W+jets (nick \"{nick}\") is {scale_factor}.".format(nick=wjets_shape_nick, scale_factor=scale_factor)) plotData.plotdict["root_objects"][wjets_shape_nick].Scale(scale_factor.nominal_value) integral_shape = tools.PoissonYield(plotData.plotdict["root_objects"][wjets_os_highmt_mc_nick])() if integral_shape != 0.0: scale_factor = wjets_yield / (integral_shape * wjets_extrapolation_factor_mt) log.debug("Scale factor for process W+jets (nick \"{nick}\") is {scale_factor}.".format(nick=wjets_os_highmt_mc_nick, scale_factor=scale_factor)) plotData.plotdict["root_objects"][wjets_os_highmt_mc_nick].Scale(scale_factor.nominal_value) integral_shape = tools.PoissonYield(plotData.plotdict["root_objects"][wjets_ss_highmt_mc_nick])() if integral_shape != 0.0: scale_factor = wjets_yield / (integral_shape * wjets_extrapolation_factor_mt * wjets_extrapolation_factor_ss_os) log.debug("Scale factor for process W+jets (nick \"{nick}\") is {scale_factor}.".format(nick=wjets_ss_highmt_mc_nick, scale_factor=scale_factor)) plotData.plotdict["root_objects"][wjets_ss_highmt_mc_nick].Scale(scale_factor.nominal_value) # estimate QCD for the highmT region for nick in qcd_shape_highmt_substract_nick+[wjets_ss_highmt_mc_nick]: plotData.plotdict["root_objects"][qcd_ss_highmt_shape_nick].Add(plotData.plotdict["root_objects"][nick], -1) yield_qcd_ss_highmt = yield_ss_control - tools.PoissonYield(plotData.plotdict["root_objects"][wjets_ss_highmt_mc_nick])() yield_qcd_ss_highmt = max(0.0, yield_qcd_ss_highmt) integral_shape = tools.PoissonYield(plotData.plotdict["root_objects"][qcd_ss_highmt_shape_nick])() if integral_shape != 0.0: scale_factor = yield_qcd_ss_highmt / integral_shape plotData.plotdict["root_objects"][qcd_ss_highmt_shape_nick].Scale(scale_factor.nominal_value) integral_shape = tools.PoissonYield(plotData.plotdict["root_objects"][qcd_os_highmt_nick])() if integral_shape != 0.0: scale_factor = yield_qcd_ss_highmt * qcd_extrapolation_factor_ss_os / integral_shape plotData.plotdict["root_objects"][qcd_os_highmt_nick].Scale(scale_factor.nominal_value) plotData.metadata[wjets_shape_nick] = { "yield" : wjets_yield.nominal_value, "yield_unc" : wjets_yield.std_dev, "yield_unc_rel" : abs(wjets_yield.std_dev/wjets_yield.nominal_value if wjets_yield.nominal_value != 0.0 else 0.0), }
def run(self, plotData=None): super(Unpolarisation, self).run(plotData) remove_bias_instead_unpolarisation = plotData.plotdict["unpolarisation_remove_bias_instead_unpolarisation"] for index, (nominal_pos_pol_nick, shift_up_pos_pol_nicks, shift_down_pos_pol_nicks, nominal_neg_pol_nick, shift_up_neg_pol_nicks, shift_down_neg_pol_nicks, forced_gen_polarisation, scale_factor_pos_pol_nick, scale_factor_neg_pol_nick, polarisation_before_nick, polarisation_after_nick) in enumerate(zip(*[plotData.plotdict[key] for key in ["unpolarisation_nominal_pos_pol_nicks", "unpolarisation_shift_up_pos_pol_nicks", "unpolarisation_shift_down_pos_pol_nicks", "unpolarisation_nominal_neg_pol_nicks", "unpolarisation_shift_up_neg_pol_nicks", "unpolarisation_shift_down_neg_pol_nicks", "unpolarisation_forced_gen_polarisations", "unpolarisation_scale_factor_pos_pol_nicks", "unpolarisation_scale_factor_neg_pol_nicks", "unpolarisation_polarisation_before_nicks", "unpolarisation_polarisation_after_nicks"]])): nominal_pos_pol_hist = plotData.plotdict["root_objects"][nominal_pos_pol_nick] shift_up_pos_pol_hists = [plotData.plotdict["root_objects"][nick] for nick in shift_up_pos_pol_nicks] shift_down_pos_pol_hists = [plotData.plotdict["root_objects"][nick] for nick in shift_down_pos_pol_nicks] nominal_neg_pol_hist = plotData.plotdict["root_objects"][nominal_neg_pol_nick] shift_up_neg_pol_hists = [plotData.plotdict["root_objects"][nick] for nick in shift_up_neg_pol_nicks] shift_down_neg_pol_hists = [plotData.plotdict["root_objects"][nick] for nick in shift_down_neg_pol_nicks] name = hashlib.md5("_".join(map(str, [nominal_pos_pol_nick, shift_up_pos_pol_nicks, shift_down_pos_pol_nicks, nominal_neg_pol_nick, shift_up_neg_pol_nicks, shift_down_neg_pol_nicks, forced_gen_polarisation, scale_factor_pos_pol_nick, scale_factor_neg_pol_nick]))).hexdigest() scale_factor_pos_pol_hist = nominal_pos_pol_hist.Clone("unpol_pos_"+name) scale_factor_pos_pol_hist.Reset() scale_factor_neg_pol_hist = nominal_neg_pol_hist.Clone("unpol_neg_"+name) scale_factor_neg_pol_hist.Reset() polarisation_before_hist = nominal_pos_pol_hist.Clone("unpol_pol_before_"+name) polarisation_before_hist.Reset() polarisation_after_hist = nominal_pos_pol_hist.Clone("unpol_pol_after_"+name) polarisation_after_hist.Reset() # assume same binning for all histograms for x_bin in xrange(1, nominal_pos_pol_hist.GetNbinsX()+1): for y_bin in xrange(1, nominal_pos_pol_hist.GetNbinsY()+1): for z_bin in xrange(1, nominal_pos_pol_hist.GetNbinsZ()+1): global_bin = nominal_pos_pol_hist.GetBin(x_bin, y_bin, z_bin) n_pos_pol = uncertainties.ufloat( nominal_pos_pol_hist.GetBinContent(global_bin), nominal_pos_pol_hist.GetBinError(global_bin) ) unc_up = pow(n_pos_pol.std_dev, 2) for shift_hist in shift_up_pos_pol_hists: n_shift = uncertainties.ufloat(shift_hist.GetBinContent(global_bin), shift_hist.GetBinError(global_bin)) unc_up += pow(n_shift-n_pos_pol, 2).nominal_value unc_up = math.sqrt(unc_up) unc_down = pow(n_pos_pol.std_dev, 2) for shift_hist in shift_down_pos_pol_hists: n_shift = uncertainties.ufloat(shift_hist.GetBinContent(global_bin), shift_hist.GetBinError(global_bin)) unc_down += pow(n_shift-n_pos_pol, 2).nominal_value unc_down = math.sqrt(unc_down) n_pos_pol.std_dev = max(unc_up, unc_down) n_neg_pol = uncertainties.ufloat( nominal_neg_pol_hist.GetBinContent(global_bin), nominal_neg_pol_hist.GetBinError(global_bin) ) unc_up = pow(n_neg_pol.std_dev, 2) for shift_hist in shift_up_neg_pol_hists: n_shift = uncertainties.ufloat(shift_hist.GetBinContent(global_bin), shift_hist.GetBinError(global_bin)) unc_up += pow(n_shift-n_neg_pol, 2).nominal_value unc_up = math.sqrt(unc_up) unc_down = pow(n_neg_pol.std_dev, 2) for shift_hist in shift_down_neg_pol_hists: n_shift = uncertainties.ufloat(shift_hist.GetBinContent(global_bin), shift_hist.GetBinError(global_bin)) unc_down += pow(n_shift-n_neg_pol, 2).nominal_value unc_down = math.sqrt(unc_down) n_neg_pol.std_dev = max(unc_up, unc_down) scale_factors = polarisationsignalscaling.PolarisationScaleFactors( n_pos_pol, n_neg_pol, n_pos_pol, n_neg_pol, forced_gen_polarisation=forced_gen_polarisation ) scale_factor_pos_pol = scale_factors.get_bias_removal_factor_pospol() if remove_bias_instead_unpolarisation else scale_factors.get_scale_factor_pospol() scale_factor_pos_pol_hist.SetBinContent(global_bin, scale_factor_pos_pol.nominal_value) scale_factor_pos_pol_hist.SetBinError(global_bin, scale_factor_pos_pol.std_dev) scale_factor_neg_pol = scale_factors.get_bias_removal_factor_negpol() if remove_bias_instead_unpolarisation else scale_factors.get_scale_factor_negpol() scale_factor_neg_pol_hist.SetBinContent(global_bin, scale_factor_neg_pol.nominal_value) scale_factor_neg_pol_hist.SetBinError(global_bin, scale_factor_neg_pol.std_dev) polarisation_before = scale_factors.get_gen_polarisation() polarisation_before_hist.SetBinContent(global_bin, polarisation_before.nominal_value) polarisation_before_hist.SetBinError(global_bin, polarisation_before.std_dev) # Caution: scale_factors object is modified! scale_factors.n_gen_pospol *= scale_factor_pos_pol scale_factors.n_gen_negpol *= scale_factor_neg_pol polarisation_after = scale_factors.get_gen_polarisation() polarisation_after_hist.SetBinContent(global_bin, polarisation_after.nominal_value) polarisation_after_hist.SetBinError(global_bin, polarisation_after.std_dev) plotData.plotdict["root_objects"][scale_factor_pos_pol_nick] = scale_factor_pos_pol_hist plotData.plotdict["root_objects"][scale_factor_neg_pol_nick] = scale_factor_neg_pol_hist plotData.plotdict["root_objects"][polarisation_before_nick] = polarisation_before_hist plotData.plotdict["root_objects"][polarisation_after_nick] = polarisation_after_hist
def run(self, plotData=None): super(EstimateQcdPrefit, self).run(plotData) # make sure that all necessary histograms are available for nicks in zip( *[plotData.plotdict[key] for key in self._plotdict_keys]): for nick in nicks: if isinstance(nick, basestring): assert isinstance( plotData.plotdict["root_objects"].get(nick), ROOT.TH1) elif (not isinstance(nick, float) and not isinstance(nick, bool)): for subnick in nick: assert isinstance( plotData.plotdict["root_objects"].get(subnick), ROOT.TH1) for qcd_shape_nick, qcd_yield_nick, qcd_yield_subtract_nicks, qcd_shape_subtract_nicks, qcd_extrapolation_factor_ss_os in zip( *[plotData.plotdict[key] for key in self._plotdict_keys]): ###################### # ------- Step 1 ----- # 1. Get Yield in Control region and subtract all backgrounds. yield_qcd = tools.PoissonYield( plotData.plotdict["root_objects"][qcd_yield_nick])() # estimate the QCD yield for nick in qcd_yield_subtract_nicks: yield_bkg = tools.PoissonYield( plotData.plotdict["root_objects"][nick])() yield_qcd -= yield_bkg yield_qcd = uncertainties.ufloat(max(0.0, yield_qcd.nominal_value), yield_qcd.std_dev) if (yield_qcd.nominal_value == 0.0): log.warning("QCD yield is 0!") ###################### # ------- Step 2 ----- # QCD shape # 1. Subtract the shapes of all backgrounds from data in the control region. # 2. Scale the qcd by the qcd_os_ss_extrapolation_factor to get the prefit estimate. # Sidemark: In this script the factor is supposed to be 1.0 because we want to determine the # factor with this first estimate. for nick in qcd_shape_subtract_nicks: plotData.plotdict["root_objects"][qcd_shape_nick].Add( plotData.plotdict["root_objects"][nick], -1.0 / plotData.plotdict["qcd_scale_factor"]) shape_yield = tools.PoissonYield( plotData.plotdict["root_objects"][qcd_shape_nick])() if shape_yield != 0.0: qcd_extrapolation_factor_ss_os = 1.0 scale_factor = yield_qcd / shape_yield * qcd_extrapolation_factor_ss_os plotData.plotdict["root_objects"][qcd_shape_nick].Scale( scale_factor.nominal_value) #log.debug("Relative statistical uncertainty of the yield for process QCD (nick \"{nick}\") is {unc}.".format(nick=qcd_data_shape_nick, unc=final_yield.std_dev/final_yield.nominal_value if final_yield.nominal_value != 0.0 else 0.0)) final_yield_qcd = yield_qcd * qcd_extrapolation_factor_ss_os # save to be picked up plotData.metadata[qcd_shape_nick] = { "yield": final_yield_qcd.nominal_value, "yield_unc": final_yield_qcd.std_dev, "yield_unc_rel": abs(final_yield_qcd.std_dev / final_yield_qcd.nominal_value if final_yield_qcd.nominal_value != 0.0 else 0.0), }
args.output_dir )) plot_configs = [] datacards_workspaces = {} efficiency = {} for datacard, cb in datacards_cbs.iteritems(): for channel in cb.cp().analysis(["ztt"]).era(["13TeV"]).channel_set(): nPassPre = 0 nFailPre = 0 sig_process = cb.cp().bin([category]).signals().process_set() for category in cb.cp().analysis(["ztt"]).era(["13TeV"]).channel([channel]).bin_set(): if "pass" in category: nPassPre = uncertainties.ufloat(cb.cp().bin([category]).process(sig_process).GetRate(), cb.cp().bin([category]).process(sig_process).GetUncertainty()) elif "fail" in category: nFailPre = uncertainties.ufloat(cb.cp().bin([category]).process(sig_process).GetRate(), cb.cp().bin([category]).process(sig_process).GetUncertainty()) efficiency[channel] = nPassPre / (nPassPre + nFailPre) command = ["text2workspace.py -m {MASS} -P {MODEL} --PO \"eff={EFF}\" {DATACARD} -o {OUTPUT}".format( MASS=[mass for mass in cb.mass_set() if mass != "*"][0], MODEL=model_settings["P"], EFF=efficiency[channel].nominal_value, DATACARD=datacard, OUTPUT=os.path.splitext(datacard)[0]+".root")] print "command -->", command tools.parallelize(_call_command, command, n_processes=args.n_processes)
def run(self, plotData=None): super(Unpolarisation, self).run(plotData) remove_bias_instead_unpolarisation = plotData.plotdict[ "unpolarisation_remove_bias_instead_unpolarisation"] for index, (nominal_pos_pol_nick, shift_up_pos_pol_nicks, shift_down_pos_pol_nicks, nominal_neg_pol_nick, shift_up_neg_pol_nicks, shift_down_neg_pol_nicks, forced_gen_polarisation, scale_factor_pos_pol_nick, scale_factor_neg_pol_nick, polarisation_before_nick, polarisation_after_nick) in enumerate( zip(*[ plotData.plotdict[key] for key in [ "unpolarisation_nominal_pos_pol_nicks", "unpolarisation_shift_up_pos_pol_nicks", "unpolarisation_shift_down_pos_pol_nicks", "unpolarisation_nominal_neg_pol_nicks", "unpolarisation_shift_up_neg_pol_nicks", "unpolarisation_shift_down_neg_pol_nicks", "unpolarisation_forced_gen_polarisations", "unpolarisation_scale_factor_pos_pol_nicks", "unpolarisation_scale_factor_neg_pol_nicks", "unpolarisation_polarisation_before_nicks", "unpolarisation_polarisation_after_nicks" ] ])): nominal_pos_pol_hist = plotData.plotdict["root_objects"][ nominal_pos_pol_nick] shift_up_pos_pol_hists = [ plotData.plotdict["root_objects"][nick] for nick in shift_up_pos_pol_nicks if not nick is None ] shift_down_pos_pol_hists = [ plotData.plotdict["root_objects"][nick] for nick in shift_down_pos_pol_nicks if not nick is None ] nominal_neg_pol_hist = plotData.plotdict["root_objects"][ nominal_neg_pol_nick] shift_up_neg_pol_hists = [ plotData.plotdict["root_objects"][nick] for nick in shift_up_neg_pol_nicks if not nick is None ] shift_down_neg_pol_hists = [ plotData.plotdict["root_objects"][nick] for nick in shift_down_neg_pol_nicks if not nick is None ] name = hashlib.md5("_".join( map(str, [ nominal_pos_pol_nick, shift_up_pos_pol_nicks, shift_down_pos_pol_nicks, nominal_neg_pol_nick, shift_up_neg_pol_nicks, shift_down_neg_pol_nicks, forced_gen_polarisation, scale_factor_pos_pol_nick, scale_factor_neg_pol_nick ]))).hexdigest() scale_factor_pos_pol_hist = nominal_pos_pol_hist.Clone( "unpol_pos_" + name) scale_factor_pos_pol_hist.Reset() scale_factor_neg_pol_hist = nominal_neg_pol_hist.Clone( "unpol_neg_" + name) scale_factor_neg_pol_hist.Reset() polarisation_before_hist = nominal_pos_pol_hist.Clone( "unpol_pol_before_" + name) polarisation_before_hist.Reset() polarisation_after_hist = nominal_pos_pol_hist.Clone( "unpol_pol_after_" + name) polarisation_after_hist.Reset() # assume same binning for all histograms for x_bin in xrange(1, nominal_pos_pol_hist.GetNbinsX() + 1): for y_bin in xrange(1, nominal_pos_pol_hist.GetNbinsY() + 1): for z_bin in xrange(1, nominal_pos_pol_hist.GetNbinsZ() + 1): global_bin = nominal_pos_pol_hist.GetBin( x_bin, y_bin, z_bin) n_pos_pol = uncertainties.ufloat( nominal_pos_pol_hist.GetBinContent(global_bin), nominal_pos_pol_hist.GetBinError(global_bin)) unc_up = pow(n_pos_pol.std_dev, 2) for shift_hist in shift_up_pos_pol_hists: n_shift = uncertainties.ufloat( shift_hist.GetBinContent(global_bin), shift_hist.GetBinError(global_bin)) unc_up += pow(n_shift - n_pos_pol, 2).nominal_value unc_up = math.sqrt(unc_up) unc_down = pow(n_pos_pol.std_dev, 2) for shift_hist in shift_down_pos_pol_hists: n_shift = uncertainties.ufloat( shift_hist.GetBinContent(global_bin), shift_hist.GetBinError(global_bin)) unc_down += pow(n_shift - n_pos_pol, 2).nominal_value unc_down = math.sqrt(unc_down) n_pos_pol.std_dev = max(unc_up, unc_down) n_neg_pol = uncertainties.ufloat( nominal_neg_pol_hist.GetBinContent(global_bin), nominal_neg_pol_hist.GetBinError(global_bin)) unc_up = pow(n_neg_pol.std_dev, 2) for shift_hist in shift_up_neg_pol_hists: n_shift = uncertainties.ufloat( shift_hist.GetBinContent(global_bin), shift_hist.GetBinError(global_bin)) unc_up += pow(n_shift - n_neg_pol, 2).nominal_value unc_up = math.sqrt(unc_up) unc_down = pow(n_neg_pol.std_dev, 2) for shift_hist in shift_down_neg_pol_hists: n_shift = uncertainties.ufloat( shift_hist.GetBinContent(global_bin), shift_hist.GetBinError(global_bin)) unc_down += pow(n_shift - n_neg_pol, 2).nominal_value unc_down = math.sqrt(unc_down) n_neg_pol.std_dev = max(unc_up, unc_down) if (n_pos_pol * n_neg_pol).nominal_value != 0.0: scale_factors = polarisationsignalscaling.PolarisationScaleFactors( n_pos_pol, n_neg_pol, n_pos_pol, n_neg_pol, forced_gen_polarisation=forced_gen_polarisation ) scale_factor_pos_pol = scale_factors.get_bias_removal_factor_pospol( ) if remove_bias_instead_unpolarisation else scale_factors.get_scale_factor_pospol( ) scale_factor_pos_pol_hist.SetBinContent( global_bin, scale_factor_pos_pol.nominal_value) scale_factor_pos_pol_hist.SetBinError( global_bin, scale_factor_pos_pol.std_dev) scale_factor_neg_pol = scale_factors.get_bias_removal_factor_negpol( ) if remove_bias_instead_unpolarisation else scale_factors.get_scale_factor_negpol( ) scale_factor_neg_pol_hist.SetBinContent( global_bin, scale_factor_neg_pol.nominal_value) scale_factor_neg_pol_hist.SetBinError( global_bin, scale_factor_neg_pol.std_dev) polarisation_before = scale_factors.get_gen_polarisation( ) polarisation_before_hist.SetBinContent( global_bin, polarisation_before.nominal_value) polarisation_before_hist.SetBinError( global_bin, polarisation_before.std_dev) # Caution: scale_factors object is modified! scale_factors.n_gen_pospol *= scale_factor_pos_pol scale_factors.n_gen_negpol *= scale_factor_neg_pol polarisation_after = scale_factors.get_gen_polarisation( ) polarisation_after_hist.SetBinContent( global_bin, polarisation_after.nominal_value) polarisation_after_hist.SetBinError( global_bin, polarisation_after.std_dev) else: scale_factor_pos_pol_hist.SetBinContent( global_bin, 0.0) scale_factor_pos_pol_hist.SetBinError( global_bin, 0.0) scale_factor_neg_pol_hist.SetBinContent( global_bin, 0.0) scale_factor_neg_pol_hist.SetBinError( global_bin, 0.0) polarisation_before_hist.SetBinContent( global_bin, 0.0) polarisation_before_hist.SetBinError( global_bin, 0.0) polarisation_after_hist.SetBinContent( global_bin, 0.0) polarisation_after_hist.SetBinError( global_bin, 0.0) plotData.plotdict["root_objects"][ scale_factor_pos_pol_nick] = scale_factor_pos_pol_hist plotData.plotdict["root_objects"][ scale_factor_neg_pol_nick] = scale_factor_neg_pol_hist plotData.plotdict["root_objects"][ polarisation_before_nick] = polarisation_before_hist plotData.plotdict["root_objects"][ polarisation_after_nick] = polarisation_after_hist
def run(self, plotData=None): super(EstimateWjets, self).run(plotData) # make sure that all necessary histograms are available for nicks in zip( *[plotData.plotdict[key] for key in self._plotdict_keys]): for nick in nicks: if isinstance(nick, basestring): assert isinstance( plotData.plotdict["root_objects"].get(nick), ROOT.TH1) elif not isinstance(nick, bool): for subnick in nick: assert isinstance( plotData.plotdict["root_objects"].get(subnick), ROOT.TH1) for wjets_from_mc, wjets_shape_nick, wjets_data_control_nick, wjets_data_substract_nicks, wjets_mc_signal_nick, wjets_mc_control_nick in zip( *[plotData.plotdict[key] for key in self._plotdict_keys]): if not wjets_from_mc: # skips the full estimation of this module and uses MC estimate of WJ instead. # Get yield and uncertainity in data in the control region yield_data_control = tools.PoissonYield( plotData.plotdict["root_objects"] [wjets_data_control_nick])() for nick in wjets_data_substract_nicks: # subtract yields of all backgrounds yield_bkg_control = tools.PoissonYield( plotData.plotdict["root_objects"][nick])() if nick in plotData.metadata: yield_bkg_control = uncertainties.ufloat( plotData.metadata[nick].get( "yield", yield_bkg_control.nominal_value), plotData.metadata[nick].get( "yield_unc", yield_bkg_control.std_dev)) yield_data_control -= yield_bkg_control # make sure we don't have negative yields yield_data_control = uncertainties.ufloat( max(0.0, yield_data_control.nominal_value), yield_data_control.std_dev) yield_mc_signal = tools.PoissonYield( plotData.plotdict["root_objects"][wjets_mc_signal_nick])() yield_mc_control = tools.PoissonYield( plotData.plotdict["root_objects"][wjets_mc_control_nick])() assert (yield_data_control * yield_mc_signal == 0.0) or (yield_mc_control != 0.0) # the final yield in the signal region is N_data, WJ^{SR} = N_data, WJ^{CR} * N_MC,WJ^{SR} / N_MC,WJ^{CR} final_yield = yield_data_control * yield_mc_signal if final_yield != 0.0: final_yield /= yield_mc_control log.debug( "Relative statistical uncertainty of the yield for process W+jets (nick \"{nick}\") is {unc}." .format(nick=wjets_shape_nick, unc=final_yield.std_dev / final_yield.nominal_value if final_yield.nominal_value != 0.0 else 0.0)) plotData.metadata[wjets_shape_nick] = { "yield": final_yield.nominal_value, "yield_unc": final_yield.std_dev, "yield_unc_rel": abs(final_yield.std_dev / final_yield.nominal_value if final_yield.nominal_value != 0.0 else 0.0), } plotData.metadata # scale the wj file by the ratio of the estimated yield and the yield given by MC. integral_shape = tools.PoissonYield( plotData.plotdict["root_objects"][wjets_shape_nick])() if integral_shape != 0.0: scale_factor = final_yield / integral_shape log.debug( "Scale factor for process W+jets (nick \"{nick}\") is {scale_factor}." .format(nick=wjets_shape_nick, scale_factor=scale_factor)) plotData.plotdict["root_objects"][wjets_shape_nick].Scale( scale_factor.nominal_value)