Exemplo n.º 1
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)
Exemplo n.º 2
0
    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)
Exemplo n.º 3
0
    def run(self, plotData=None):
        super(EstimateQcdTauHadTauHad, self).run(plotData)

        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 = max(0.0, yield_control_signal)

            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 = max(0.0, yield_control_relaxed)

            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 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(EstimateQcd, self).run(plotData)

        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 = max(0.0, yield_qcd)
            if (yield_qcd == 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
            final_yield_qcd = yield_qcd * qcd_extrapolation_factor_ss_os
            #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.plotdict["root_objects"][qcd_shape_nick].Scale(
                scale_factor.nominal_value)
            #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),
            }
Exemplo n.º 6
0
    def run(self, plotData=None):
        super(EstimateFF, self).run(plotData)

        for (ff_data_nick, ff_mc_subtract_nicks, ff_norm_data_nick,
             ff_norm_mc_subtract_nicks) in zip(
                 *[plotData.plotdict[key] for key in self._plotdict_keys]):
            for nick in ff_mc_subtract_nicks:
                plotData.plotdict["root_objects"][ff_data_nick].Add(
                    plotData.plotdict["root_objects"][nick], -1.0)
            for nick in ff_norm_mc_subtract_nicks:
                plotData.plotdict["root_objects"][ff_norm_data_nick].Add(
                    plotData.plotdict["root_objects"][nick], -1.0)
            ff_yield = tools.PoissonYield(
                plotData.plotdict["root_objects"][ff_data_nick])()
            ff_norm_yield = tools.PoissonYield(
                plotData.plotdict["root_objects"][ff_norm_data_nick])()
            if ff_yield != 0.0:
                scale_factor = ff_norm_yield / ff_yield
                plotData.plotdict["root_objects"][ff_data_nick].Scale(
                    scale_factor.nominal_value)
Exemplo n.º 7
0
	def run(self, plotData=None):
		super(EstimateFF, 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 (ff_data_nick, ff_mc_subtract_nicks, ff_norm_data_nick, ff_norm_mc_subtract_nicks) in zip(*[plotData.plotdict[key] for key in self._plotdict_keys]):
			for nick in ff_mc_subtract_nicks:
				plotData.plotdict["root_objects"][ff_data_nick].Add(plotData.plotdict["root_objects"][nick], -1.0)
			for nick in ff_norm_mc_subtract_nicks:
				plotData.plotdict["root_objects"][ff_norm_data_nick].Add(plotData.plotdict["root_objects"][nick], -1.0)
			ff_yield = tools.PoissonYield(plotData.plotdict["root_objects"][ff_data_nick])()
			ff_norm_yield = tools.PoissonYield(plotData.plotdict["root_objects"][ff_norm_data_nick])()
			if ff_yield != 0.0:
				scale_factor = ff_norm_yield/ff_yield
				plotData.plotdict["root_objects"][ff_data_nick].Scale(scale_factor.nominal_value)
Exemplo n.º 8
0
    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),
            }
Exemplo n.º 9
0
    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(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, 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),
			}
Exemplo n.º 12
0
    def run(self, plotData=None):
        super(NormalizeForPolarisation, self).run(plotData)

        for ztt_pos_pol_gen_nick, ztt_neg_pol_gen_nick, ztt_pos_pol_reco_nick, ztt_neg_pol_reco_nick, ztt_forced_gen_polarisation, ztt_pos_pol_reco_result_nick, ztt_neg_pol_reco_result_nick in zip(
                *[
                    plotData.plotdict[key] for key in [
                        "ztt_pos_pol_gen_nicks", "ztt_neg_pol_gen_nicks",
                        "ztt_pos_pol_reco_nicks", "ztt_neg_pol_reco_nicks",
                        "ztt_forced_gen_polarisations",
                        "ztt_pos_pol_reco_result_nicks",
                        "ztt_neg_pol_reco_result_nicks"
                    ]
                ]):

            if ztt_pos_pol_reco_result_nick != ztt_pos_pol_reco_nick:
                new_name = "zttpospol_" + hashlib.md5(
                    ztt_pos_pol_gen_nick + ztt_pos_pol_reco_nick +
                    ztt_pos_pol_reco_result_nick).hexdigest()
                new_histogram = plotData.plotdict["root_objects"][
                    ztt_pos_pol_reco_nick].Clone(new_name)
                plotData.plotdict["root_objects"][
                    ztt_pos_pol_reco_result_nick] = new_histogram

            if ztt_neg_pol_reco_result_nick != ztt_neg_pol_reco_nick:
                new_name = "zttnegpol_" + hashlib.md5(
                    ztt_neg_pol_gen_nick + ztt_neg_pol_reco_nick +
                    ztt_neg_pol_reco_result_nick).hexdigest()
                new_histogram = plotData.plotdict["root_objects"][
                    ztt_neg_pol_reco_nick].Clone(new_name)
                plotData.plotdict["root_objects"][
                    ztt_neg_pol_reco_result_nick] = new_histogram

            pos_reco_norm = tools.PoissonYield(
                plotData.plotdict["root_objects"][ztt_pos_pol_reco_nick])()
            neg_reco_norm = tools.PoissonYield(
                plotData.plotdict["root_objects"][ztt_neg_pol_reco_nick])()
            pos_gen_norm = tools.PoissonYield(
                plotData.plotdict["root_objects"][ztt_pos_pol_gen_nick])()
            neg_gen_norm = tools.PoissonYield(
                plotData.plotdict["root_objects"][ztt_neg_pol_gen_nick])()

            scale_factors = polarisationsignalscaling.PolarisationScaleFactors(
                pos_reco_norm,
                neg_reco_norm,
                pos_gen_norm,
                neg_gen_norm,
                forced_gen_polarisation=ztt_forced_gen_polarisation)
            log.debug("Gen.  level polarisation = {polarisation}".format(
                polarisation=scale_factors.get_gen_polarisation()))
            log.debug("Reco. level polarisation = {polarisation}".format(
                polarisation=scale_factors.get_reco_polarisation()))

            pos_reco_scale_factor = scale_factors.get_bias_removal_factor_pospol(
            ) if plotData.plotdict[
                "ztt_remove_bias_instead_unpolarisation"] else scale_factors.get_scale_factor_pospol(
                )
            plotData.plotdict["root_objects"][
                ztt_pos_pol_reco_result_nick].Scale(
                    pos_reco_scale_factor.nominal_value)
            log.debug(
                "Scaled histogram \"{nick}\" by a factor of {factor}".format(
                    nick=ztt_pos_pol_reco_result_nick,
                    factor=pos_reco_scale_factor))

            neg_reco_scale_factor = scale_factors.get_bias_removal_factor_neg_pol(
            ) if plotData.plotdict[
                "ztt_remove_bias_instead_unpolarisation"] else scale_factors.get_scale_factor_negpol(
                )
            plotData.plotdict["root_objects"][
                ztt_neg_pol_reco_result_nick].Scale(
                    neg_reco_scale_factor.nominal_value)
            log.debug(
                "Scaled histogram \"{nick}\" by a factor of {factor}".format(
                    nick=ztt_neg_pol_reco_result_nick,
                    factor=neg_reco_scale_factor))

            if log.isEnabledFor(logging.DEBUG):
                reco_polarisation_before_scaling = (
                    pos_reco_norm - neg_reco_norm) / (pos_reco_norm +
                                                      neg_reco_norm)
                reco_polarisation_after_scaling = (
                    pos_reco_norm * pos_reco_scale_factor -
                    neg_reco_norm * neg_reco_scale_factor) / (
                        pos_reco_norm * pos_reco_scale_factor +
                        neg_reco_norm * neg_reco_scale_factor)
                log.debug("Tau polarisation changed from {before} to {after}.".
                          format(before=reco_polarisation_before_scaling,
                                 after=reco_polarisation_after_scaling))
    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(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 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)