def GetSingleMuHistograms(self):
		#this_analyses = ["trigmu_highmass_CSVTM", "trigmu_lowmass_CSVTM", "trigmubbh_highmass_CSVTM", "trigmubbl_lowmass_CSVTM", "trigmubbll_lowmass_CSVTM", "trigmu24i_lowmass_CSVTM", "trigmu24ibbl_lowmass_CSVTM", "trigmu24ibbll_lowmass_CSVTM", "trigmu40_lowmass_CSVTM", "trigmu40bbl_lowmass_CSVTM", "trigmu40bbll_lowmass_CSVTM"]
		this_analyses = ["trigmu24i_lowmass_CSVTM", "trigmu24ibbl_lowmass_CSVTM"]
		this_analyses.extend(["trigmu24i_highmass_CSVTM", "trigmu24ibbh_highmass_CSVTM"])
		for analysis in this_analyses:
			print "Opening " + analysis_config.get_b_histogram_filename(analysis, "SingleMu_2012")
			f = ROOT.TFile(analysis_config.get_b_histogram_filename(analysis, "SingleMu_2012"), "READ")
			self._mjj_histograms_fine[analysis] = f.Get("BHistograms/h_pfjet_mjj")
			self._mjj_histograms_fine[analysis].SetName("h_" + analysis + "_mjj_fine")
			self._mjj_histograms_fine[analysis].SetDirectory(0)
			self._mjj_histograms[analysis] = histogram_tools.rebin_histogram(self._mjj_histograms_fine[analysis], self._mass_bins, normalization_bin_width=1)
			self._mjj_histograms[analysis].SetName("h_" + analysis + "_mjj")
			self._mjj_histograms[analysis].SetDirectory(0)

			if not "highmass" in analysis:
				self._mjj_histograms_csvorder[analysis] = f.Get("BHistograms/h_pfjet_mjj_csvorder")
				self._mjj_histograms_csvorder[analysis].SetName("h_" + analysis + "_mjj_csvorder")
				self._mjj_histograms_csvorder[analysis].SetDirectory(0)
				self._mjj_histograms_csvorder[analysis] = histogram_tools.rebin_histogram(self._mjj_histograms_csvorder[analysis], self._mass_bins, normalization_bin_width=1)

				self._mjj_histograms_vetothirdjet[analysis] = f.Get("BHistograms/h_pfjet_mjj_vetothirdjet")
				self._mjj_histograms_vetothirdjet[analysis].SetName("h_" + analysis + "_mjj_vetothirdjet")
				self._mjj_histograms_vetothirdjet[analysis].SetDirectory(0)
				self._mjj_histograms_vetothirdjet[analysis] = histogram_tools.rebin_histogram(self._mjj_histograms_vetothirdjet[analysis], self._mass_bins, normalization_bin_width=1)

			if "bbll" in analysis:
				self._mjj_histograms_fine[analysis].Scale(1.7) # Prescale for singlemu + 60/53. The prescale was not computer for these analyses.
				self._mjj_histograms[analysis].Scale(1.7) # Prescale for singlemu + 60/53. The prescale was not computer for these analyses.
			self._mjj_histograms_fine[analysis].Rebin(5)
			self._analyses.append(analysis)
			f.Close()
def qcd_efficiency(wp, eta):
    h_num = None
    h_den = None

    numerator_analysis = "NoTrigger_{}_{}".format(eta, wp)
    denominator_analysis = "NoTrigger_{}".format(eta)

    for qcd_sample in qcd_samples:
        numerator_file = TFile(
            analysis_config.get_b_histogram_filename(numerator_analysis,
                                                     qcd_sample))
        denominator_file = TFile(
            analysis_config.get_b_histogram_filename(denominator_analysis,
                                                     qcd_sample))
        this_h_num = numerator_file.Get("BHistograms/h_pfjet_mjj")
        this_h_den = denominator_file.Get("BHistograms/h_pfjet_mjj")
        print "[debug] Scale factor for {} numerator = {}".format(
            qcd_sample, 19700 *
            analysis_config.simulation.background_cross_sections[qcd_sample] /
            numerator_file.Get("BHistograms/h_sample_nevents").Integral())
        print "[debug] \tdenominator = {}".format(
            19700 *
            analysis_config.simulation.background_cross_sections[qcd_sample] /
            numerator_file.Get("BHistograms/h_sample_nevents").Integral())
        this_h_num.Scale(
            19700 *
            analysis_config.simulation.background_cross_sections[qcd_sample] /
            numerator_file.Get("BHistograms/h_sample_nevents").Integral())
        this_h_den.Scale(
            19700 *
            analysis_config.simulation.background_cross_sections[qcd_sample] /
            denominator_file.Get("BHistograms/h_sample_nevents").Integral())
        if h_num:
            h_num.Add(this_h_num)
        else:
            h_num = this_h_num.Clone()
            h_num.SetDirectory(0)
        if h_den:
            h_den.Add(this_h_den)
        else:
            h_den = this_h_den.Clone()
            h_den.SetDirectory(0)
        numerator_file.Close()
        denominator_file.Close()
    f_out = TFile(analysis_config.get_offline_btag_file(wp, eta), "RECREATE")
    h_eff = h_num.Clone()
    h_eff.SetName("h_offline_btag_eff")
    h_eff.Divide(h_num, h_den, 1., 1., "B")
    h_num.SetName("h_num")
    h_num.Write()
    h_den.SetName("h_den")
    h_den.Write()
    f_out.cd()
    h_eff.Write()
    f_out.Close()
Beispiel #3
0
def data_jes_plot(new_sample, old_sample, analysis):
	print "Making data JES plot for {}".format(analysis)
	f_new = TFile(analysis_config.get_b_histogram_filename(analysis, new_sample), "READ")
	h_new = f_new.Get("BHistograms/h_pfjet_mjj")
	h_new.SetName("h_pfjet_mjj_newJEC")
	h_new.SetDirectory(0)
	h_new = histogram_tools.rebin_histogram(h_new, dijet_binning, normalization_bin_width=1.)
	print "New integral = {}".format(h_new.Integral())

	f_old = TFile(analysis_config.get_b_histogram_filename(analysis, old_sample).replace("EightTeeEeVeeBee/BHistograms", "EightTeeEeVeeBee/BHistograms/old/JEC2012"), "READ")
	h_old = f_old.Get("BHistograms/h_pfjet_mjj")
	h_old.SetName("h_pfjet_mjj_oldJEC")
	h_old.SetDirectory(0)
	h_old = histogram_tools.rebin_histogram(h_old, dijet_binning, normalization_bin_width=1.)
	print "Old integral = {}".format(h_old.Integral())

	c = TCanvas("c_jeccomparison_{}".format(analysis), "c_jeccomparison_{}".format(analysis), 800, 1200)
	top = TPad("top", "top", 0., 0.5, 1., 1.)
	top.SetBottomMargin(0.02)
	top.SetLogy()
	top.Draw()
	top.cd()
	h_new.SetMarkerStyle(20)
	h_new.GetXaxis().SetTitleSize(0)
	h_new.GetXaxis().SetLabelSize(0)
	h_new.GetYaxis().SetTitle("Events / GeV")
	h_new.Draw()
	h_old.SetMarkerStyle(25)
	h_old.Draw("same")

	c.cd()
	bottom = TPad("bottom", "bottom", 0., 0., 1., 0.5)
	bottom.SetTopMargin(0.02)
	bottom.SetBottomMargin(0.2)
	bottom.Draw()
	bottom.cd()
	h_ratio = h_new.Clone()
	h_ratio.Divide(h_old)
	h_ratio.GetXaxis().SetTitle("m_{jj} [GeV]")
	h_ratio.GetYaxis().SetTitle("New JEC / Old JEC")
	h_ratio.SetMarkerStyle(21)
	h_ratio.Draw()

	c.cd()
	c.SaveAs(analysis_config.figure_directory + "/" + c.GetName() + ".pdf")


	f_new.Close()
	f_old.Close()
	def GetBJetPlusXHistograms(self):
		this_analyses = ["trigbbh_CSVTM", "trigbbl_CSVTM", "trigbbll_CSVTM", "trigbbh_trigbbl_CSVTM"]
		this_samples = ["BJetPlusX_2012", "BJetPlusX_2012BCD"]
		for analysis in this_analyses:
			for sample in this_samples:
				name = analysis + "_" + sample
				f = ROOT.TFile(analysis_config.get_b_histogram_filename(analysis, sample), "READ")
				self._mjj_histograms_fine[name] = f.Get("BHistograms/h_pfjet_mjj")
				self._mjj_histograms_fine[name].SetName("h_" + name + "_mjj_fine")
				self._mjj_histograms_fine[name].SetDirectory(0)
				self._mjj_histograms[name] = histogram_tools.rebin_histogram(self._mjj_histograms_fine[name], self._mass_bins, normalization_bin_width=1)
				self._mjj_histograms[name].SetName("h_" + name + "_mjj")
				self._mjj_histograms[name].SetDirectory(0)
				self._mjj_histograms_csvorder[name] = f.Get("BHistograms/h_pfjet_mjj_csvorder")
				self._mjj_histograms_csvorder[name].SetName("h_" + name + "_mjj_csvorder")
				self._mjj_histograms_csvorder[name].SetDirectory(0)
				self._mjj_histograms_csvorder[name] = histogram_tools.rebin_histogram(self._mjj_histograms_csvorder[name], self._mass_bins, normalization_bin_width=1)
				self._mjj_histograms_vetothirdjet[name] = f.Get("BHistograms/h_pfjet_mjj_vetothirdjet")
				self._mjj_histograms_vetothirdjet[name].SetName("h_" + name + "_mjj_vetothirdjet")
				self._mjj_histograms_vetothirdjet[name].SetDirectory(0)
				self._mjj_histograms_vetothirdjet[name] = histogram_tools.rebin_histogram(self._mjj_histograms_vetothirdjet[name], self._mass_bins, normalization_bin_width=1)
				self._mjj_histograms_fine[name].Rebin(5)
				self._analyses.append(name)
				f.Close()

				if "bbll" in analysis:
					self._mjj_histograms[name].Scale(1.7)
					self._mjj_histograms_fine[name].Scale(1.7)
	def GetJetHTHistogram(self):
		for sr_name in ["highmass", "lowmass"]:
			analyses = {}
			HT_slices = []
			for mass in xrange(200, 600, 50):
				HT_slices.append("HT" + str(mass))
				analyses["HT" + str(mass)] = "trigjetht" + str(mass)
				if sr_name == "lowmass":
					analyses["HT" + str(mass)] += "_eta1p7"
				analyses["HT" + str(mass)] += "_CSVTM"
			sample = "JetHT_2012BCD"
			HT_slice_histograms = {}
			for HT_slice in HT_slices:
				f = TFile(analysis_config.get_b_histogram_filename(analyses[HT_slice], sample), "READ")
				HT_slice_histograms[HT_slice] = f.Get("BHistograms/h_pfjet_mjj")
				print "On file " + analysis_config.get_b_histogram_filename(analyses[HT_slice], sample)
				HT_slice_histograms[HT_slice].SetName(HT_slice_histograms[HT_slice].GetName() + "_" + analyses[HT_slice])
				HT_slice_histograms[HT_slice].SetDirectory(0)
				f.Close()
			HT_slices.append("HTUnprescaled")
			unprescaled_analysis_name = "trigjetht"
			if sr_name == "lowmass":
				unprescaled_analysis_name += "_eta1p7"
			unprescaled_analysis_name += "_CSVTM"
			analyses["HTUnprescaled"] = unprescaled_analysis_name
			f_unprescaled = TFile(analysis_config.get_b_histogram_filename(unprescaled_analysis_name, sample), "READ")
			HT_slice_histograms["HTUnprescaled"] = f_unprescaled.Get("BHistograms/h_pfjet_mjj")
			HT_slice_histograms["HTUnprescaled"].SetName(HT_slice_histograms["HTUnprescaled"].GetName() + "_" + analyses["HTUnprescaled"])
			HT_slice_histograms["HTUnprescaled"].SetDirectory(0)
			f_unprescaled.Close()
			ranges = {
				"HT200":[220, 386],
				"HT250":[386, 489],
				"HT300":[489, 526],
				"HT350":[526, 606],
				"HT400":[606, 649],
				"HT450":[649, 740],
				"HT500":[740, 788],
				"HT550":[788, 890],
				#"HT650":[800, 890],
				"HTUnprescaled":[890, 2000]
			}

			self._analyses.append("JetHT")
			self._mjj_histograms_fine["JetHT"] = self.FrankenHist(HT_slices, HT_slice_histograms, ranges)
			self._mjj_histograms["JetHT"] = histogram_tools.rebin_histogram(self._mjj_histograms_fine["JetHT"], self._mass_bins, normalization_bin_width=1)
			self._mjj_histograms_fine["JetHT"].Rebin(5)
def qcd_efficiency(wp, eta):
	h_num = None
	h_den = None

	numerator_analysis = "NoTrigger_{}_{}".format(eta, wp)
	denominator_analysis = "NoTrigger_{}".format(eta)

	for qcd_sample in qcd_samples:
		numerator_file = TFile(analysis_config.get_b_histogram_filename(numerator_analysis, qcd_sample))
		denominator_file = TFile(analysis_config.get_b_histogram_filename(denominator_analysis, qcd_sample))
		this_h_num = numerator_file.Get("BHistograms/h_pfjet_mjj")
		this_h_den = denominator_file.Get("BHistograms/h_pfjet_mjj")
		print "[debug] Scale factor for {} numerator = {}".format(qcd_sample, 19700 * analysis_config.simulation.background_cross_sections[qcd_sample] / numerator_file.Get("BHistograms/h_sample_nevents").Integral())
		print "[debug] \tdenominator = {}".format(19700 * analysis_config.simulation.background_cross_sections[qcd_sample] / numerator_file.Get("BHistograms/h_sample_nevents").Integral())
		this_h_num.Scale(19700 * analysis_config.simulation.background_cross_sections[qcd_sample] / numerator_file.Get("BHistograms/h_sample_nevents").Integral())
		this_h_den.Scale(19700 * analysis_config.simulation.background_cross_sections[qcd_sample] / denominator_file.Get("BHistograms/h_sample_nevents").Integral())
		if h_num:
			h_num.Add(this_h_num)
		else:
			h_num = this_h_num.Clone()
			h_num.SetDirectory(0)
		if h_den:
			h_den.Add(this_h_den)
		else:
			h_den = this_h_den.Clone()
			h_den.SetDirectory(0)
		numerator_file.Close()
		denominator_file.Close()
	f_out = TFile(analysis_config.get_offline_btag_file(wp, eta), "RECREATE")
	h_eff = h_num.Clone()
	h_eff.SetName("h_offline_btag_eff")
	h_eff.Divide(h_num, h_den, 1., 1., "B")
	h_num.SetName("h_num")
	h_num.Write()
	h_den.SetName("h_den")
	h_den.Write()
	f_out.cd()
	h_eff.Write()
	f_out.Close()
def plot_all_masses(analysis, model, masses):
	ratio_up = {}
	ratio_down = {}
	for mass in masses:
		f = TFile(analysis_config.get_b_histogram_filename(analysis, analysis_config.simulation.get_signal_tag(model, mass, "FULLSIM")), "READ")
		h_central = f.Get("BHistograms/h_pfjet_mjj")
		h_central.SetDirectory(0)
		h_central = histogram_tools.rebin_histogram(h_central, dijet_binning, normalization_bin_width=1.)
		h_up = f.Get("BHistograms/h_pfjet_mjj_BTagOfflineSFUp")
		h_up.SetDirectory(0)
		h_up = histogram_tools.rebin_histogram(h_up, dijet_binning, normalization_bin_width=1.)
		h_down = f.Get("BHistograms/h_pfjet_mjj_BTagOfflineSFDown")
		h_down.SetDirectory(0)
		h_down = histogram_tools.rebin_histogram(h_down, dijet_binning, normalization_bin_width=1.)
		ratio_up[mass] = h_up.Clone()
		ratio_up[mass].SetName("ratio_up_{}".format(mass))
		ratio_up[mass].SetDirectory(0)
		ratio_up[mass].Divide(h_central)
		ratio_up[mass].SetMarkerStyle(26)
		ratio_up[mass].Draw("p hist same")
		ratio_down[mass] = h_down.Clone()
		ratio_down[mass].SetName("ratio_down_{}".format(mass))
		ratio_down[mass].SetDirectory(0)
		ratio_down[mass].Divide(h_central)
		ratio_down[mass].SetMarkerStyle(32)
		ratio_down[mass].Draw("p hist same")
		norm = h_central.Integral()
		print "{}\t{}\t{}:{}".format(analysis, model, mass, h_up.Integral()/norm-1.)
		f.Close()

	c = TCanvas("c_offb_unc_{}_{}_all".format(analysis, model), "c_offb_unc_{}_{}_all".format(analysis, model), 800, 600)
	frame = TH1D("frame", "frame", 100, 0., 1300.)
	frame.SetMinimum(0.8)
	frame.SetMaximum(1.2)
	frame.GetXaxis().SetTitle("m_{jj}")
	frame.GetYaxis().SetTitle("SF Variation / Central")
	frame.Draw()
	for style_counter, mass in enumerate(masses):
		ratio_up[mass].SetMarkerStyle(20)
		ratio_up[mass].SetMarkerColor(seaborn.GetColorRoot("cubehelixlarge", style_counter, len(masses)+2))
		ratio_up[mass].SetLineColor(seaborn.GetColorRoot("cubehelixlarge", style_counter, len(masses)+2))
		ratio_up[mass].Draw("hist same")
		ratio_down[mass].SetMarkerStyle(20)
		ratio_down[mass].SetMarkerColor(seaborn.GetColorRoot("cubehelixlarge", style_counter, len(masses)+2))
		ratio_down[mass].SetLineColor(seaborn.GetColorRoot("cubehelixlarge", style_counter, len(masses)+2))
		ratio_down[mass].Draw("hist same")
	c.SaveAs(analysis_config.figure_directory + "/" + c.GetName() + ".pdf")
Beispiel #8
0
	#		dratio = 0.
	#	hist_ratio.SetBinContent(bin, ratio)
	#	hist_ratio.SetBinError(bin, dratio)
	#hist_ratio.SetLineColor(1)
	#hist_ratio.SetLineWidth(1)
	#hist_ratio.SetMarkerStyle(20)
	#hist_ratio.SetMarkerSize(1)
	#hist_ratio.SetMarkerColor(1)
	#hist_ratio.Draw("same")

	c.cd()
	c.SaveAs("/uscms/home/dryu/Dijets/data/EightTeeEeVeeBee/Results/figures/{}.pdf".format(c.GetName()))

if __name__ == "__main__":
	import argparse
	parser = argparse.ArgumentParser(description="Run and plot fits")
	parser.add_argument("analysis_num", type=str, default="trigbbl_raw", help='Numerator analysis')
	parser.add_argument("analysis_den", type=str, default="trigbbl_CSVTM", help='Denominator analysis')
	args = parser.parse_args()

	f_num = TFile(analysis_config.get_b_histogram_filename(args.analysis_num, "BJetPlusX_2012"), "READ")
	h_num = f_num.Get("BHistograms/h_pfjet_mjj")
	h_num.SetDirectory(0)
	h_num.Rebin(5)
	f_den = TFile(analysis_config.get_b_histogram_filename(args.analysis_den, "BJetPlusX_2012"), "READ")
	h_den = f_den.Get("BHistograms/h_pfjet_mjj")
	h_den.SetDirectory(0)
	h_den.Rebin(5)
	print "[debug] h_num.Integral() = {}, h_den.Integral() = {}".format(h_num.Integral(), h_den.Integral())

	MakeMjjComparisonPlot(h_num, args.analysis_num, h_den, args.analysis_den, x_range=[0,1000], y_range=[1.e-5, 1.e-1])
qcd_cross_sections["QCD_Pt-600to800_TuneZ2star_8TeV_pythia6"] = 26.9921
qcd_cross_sections["QCD_Pt-800to1000_TuneZ2star_8TeV_pythia6"] = 3.550036
qcd_cross_sections["QCD_Pt-1000to1400_TuneZ2star_8TeV_pythia6"] = 0.737844
qcd_cross_sections["QCD_Pt-1400to1800_TuneZ2star_8TeV_pythia6"] = 0.03352235
qcd_cross_sections["QCD_Pt-1800_TuneZ2star_8TeV_pythia6"] = 0.001829005
online_btag_eff = {
    "trigbbl_CSVTM": 1.82719e-01,
    "trigbbh_CSVTM": 4.89446e-01,
}
qcd_hists_num = {}  # QCD with trigbb*
qcd_hists_den = {}  # QCD with NoTrigger*
qcd_hists_eff = {}
for sr in srs:
    for qcd_sample in qcd_samples:
        f_num = TFile(
            analysis_config.get_b_histogram_filename(trig_analyses[sr],
                                                     qcd_sample), "READ")
        f_den = TFile(
            analysis_config.get_b_histogram_filename(notrig_analyses[sr],
                                                     qcd_sample), "READ")
        input_nevents_num = f_num.Get("BHistograms/h_input_nevents").Integral()
        this_num_hist = f_num.Get("BHistograms/h_pfjet_mjj")
        #this_num_hist.Scale(19700.*qcd_cross_sections[qcd_sample] / input_nevents_num)
        input_nevents_den = f_den.Get("BHistograms/h_input_nevents").Integral()
        this_den_hist = f_den.Get("BHistograms/h_pfjet_mjj")
        #this_den_hist.Scale(19700.*qcd_cross_sections[qcd_sample] / input_nevents_den)
        if not sr in qcd_hists_num:
            qcd_hists_num[sr] = this_num_hist.Clone()
            qcd_hists_num[sr].SetDirectory(0)
            qcd_hists_den[sr] = this_den_hist.Clone()
            qcd_hists_den[sr].SetDirectory(0)
        else:
	analyses = ["trigbbl_CSVTM", "trigbbh_CSVTM"]
	masses = {"trigbbl_CSVTM":range(350, 850, 50), "trigbbh_CSVTM":range(600, 1250, 50)}
	mjj_min = {"trigbbl_CSVTM":296, "trigbbh_CSVTM":526}
	mjj_max = {"trigbbl_CSVTM":1058, "trigbbh_CSVTM":1607}
else:
	analyses = ["NoTrigger_eta1p7_CSVTM", "NoTrigger_eta2p2_CSVTM"]
	masses = {"NoTrigger_eta1p7_CSVTM":range(350, 850, 50), "NoTrigger_eta2p2_CSVTM":range(600, 1250, 50)}
	mjj_min = {"NoTrigger_eta1p7_CSVTM":296, "NoTrigger_eta2p2_CSVTM":526}
	mjj_max = {"NoTrigger_eta1p7_CSVTM":1058, "NoTrigger_eta2p2_CSVTM":1607}

data_sample = "QCD_TuneZ2star_8TeV_pythia6"

for model in ["Hbb", "RSG"]:
	for analysis in analyses:
		for mass in masses[analysis]:
			data_file_path = analysis_config.get_b_histogram_filename(analysis, data_sample)

			if useMCTrigger:
				signal_pdf_file = analysis_config.get_signal_fit_file(analysis, model, mass, "bukin", interpolated=(not mass in analysis_config.simulation.simulated_masses))
			else:
				if analysis == "trigbbl_CSVTM" or analysis == "NoTrigger_eta1p7_CSVTM":
					notrig_analysis = "trigbbl_notrig_CSVTM"
				elif analysis == "trigbbh_CSVTM" or analysis == "NoTrigger_eta2p2_CSVTM":
					notrig_analysis = "trigbbh_notrig_CSVTM"
				else:
					print "ERROR : I don't know a no-trigger variant of analysis {}. Please make one, or specify useMCTrigger.".format(analysis) 
					sys.exit(1)
				signal_pdf_file = analysis_config.get_signal_fit_file(notrig_analysis, model, mass, "bukin", interpolated=(not mass in analysis_config.simulation.simulated_masses))
			input_files = [data_file_path, signal_pdf_file]
			command = "python $CMSSW_BASE/src/CMSDIJET/StatisticalTools/scripts/create_datacards_parallel.py {} {}".format(analysis, model)
			command += " --massMin {} --massMax {} --mass {}".format(mjj_min[analysis], mjj_max[analysis], mass)
			"HT550":"trigjetht550",
			"HT650":"trigjetht650",
			"HTUnprescaled":"trigjetht"
		}
	for wp in ["CSVT", "CSVM", "CSVL"]:
		numerator_histograms[sr][wp] = {}
		denominator_histograms[sr][wp] = {}
		efficiency_histograms[sr][wp] = {}
		for which in [0, 1]:
			numerator_histograms[sr][wp][which] = None
			denominator_histograms[sr][wp][which] = None
			efficiency_histograms[sr][wp][which] = None
			# Load histograms
			first = True
			for ht_slice in ht_slices:
				f = TFile(analysis_config.get_b_histogram_filename(analyses[ht_slice], "JetHT_2012BCD"), "READ")
				this_numerator_histogram_3D = f.Get("BHistograms/h_pfjet_jet{}_pt_eta_{}".format(which, wp))
				this_denominator_histogram_3D = f.Get("BHistograms/h_pfjet_jet{}_pt_eta".format(which))
				zbin_min = this_numerator_histogram_3D.GetZaxis().FindBin(ht_ranges[ht_slice][0] + 1.e-5)
				zbin_max = this_numerator_histogram_3D.GetZaxis().FindBin(ht_ranges[ht_slice][0] - 1.e-5)
				if first:
					numerator_histograms[sr][wp][which] = TH2D(this_numerator_histogram_3D.GetName() + "_xy" + wp + str(which), this_numerator_histogram_3D.GetName() + "_xy", this_numerator_histogram_3D.GetXaxis().GetNbins(), this_numerator_histogram_3D.GetXaxis().GetXmin(), this_numerator_histogram_3D.GetXaxis().GetXmax(), this_numerator_histogram_3D.GetYaxis().GetNbins(), this_numerator_histogram_3D.GetYaxis().GetXmin(), this_numerator_histogram_3D.GetYaxis().GetXmax())
					numerator_histograms[sr][wp][which].SetDirectory(0)
					numerator_histograms[sr][wp][which].Sumw2()
					denominator_histograms[sr][wp][which] = TH2D(this_denominator_histogram_3D.GetName() + "_xy" + wp + str(which), this_denominator_histogram_3D.GetName() + "_xy", this_denominator_histogram_3D.GetXaxis().GetNbins(), this_denominator_histogram_3D.GetXaxis().GetXmin(), this_denominator_histogram_3D.GetXaxis().GetXmax(), this_denominator_histogram_3D.GetYaxis().GetNbins(), this_denominator_histogram_3D.GetYaxis().GetXmin(), this_denominator_histogram_3D.GetYaxis().GetXmax())
					denominator_histograms[sr][wp][which].SetDirectory(0)
					denominator_histograms[sr][wp][which].Sumw2()
					first = False
				for zbin in xrange(zbin_min, zbin_max+1):
					for xbin in xrange(1, this_numerator_histogram_3D.GetNbinsX()+1):
						for ybin in xrange(1, this_numerator_histogram_3D.GetNbinsY()+1):
Beispiel #12
0
data_analyses = {"lowmass": "trigbbl_CSVTM", "highmass": "trigbbh_CSVTM"}

dijet_binning = array(
    "d", [
        1, 3, 6, 10, 16, 23, 31, 40, 50, 61, 74, 88, 103, 119, 137, 156, 176,
        197, 220, 244, 270, 296, 325, 354, 386, 419, 453, 489, 526, 565, 606,
        649, 693, 740, 788, 838, 890, 944, 1000, 1058, 1118, 1181, 1246, 1313,
        1383, 1455, 1530, 1607, 1687, 1770, 1856, 1945, 2037, 2132, 2231, 2332,
        2438, 2546, 2659, 2775, 2895, 3019, 3147, 3279, 3416, 3558, 3704, 3854,
        4010, 4171, 4337, 4509, 4686, 4869, 5000
    ]
)  #5058, 5253, 5455, 5663, 5877, 6099, 6328, 6564, 6808, 7060, 7320, 7589, 7866, 8000])

for signal_region in signal_regions:
    f_data = TFile(
        analysis_config.get_b_histogram_filename(data_analyses[signal_region],
                                                 "BJetPlusX_2012"), "READ")
    data_hist_raw = f_data.Get("BHistograms/h_pfjet_mjj")
    data_hist_raw.SetName("mjj_data_" + signal_region)
    data_hist_raw.SetDirectory(0)
    f_data.Close()

    for strategy in strategies:
        f_mc = TFile(
            analysis_config.get_b_histogram_filename(
                mc_analyses[signal_region][strategy],
                "QCD_TuneZ2star_8TeV_pythia6"), "READ")
        mc_hist = f_mc.Get("BHistograms/h_pfjet_mjj")
        mc_hist.SetName("mjj_mc_" + signal_region + "_" + strategy)
        mc_hist.SetDirectory(0)
        if strategy == "datatrigger":
            if signal_region == "lowmass":
        masses = args.mass

    # sort masses
    masses.sort()

    # import ROOT stuff
    from ROOT import TFile, TH1F, TH1D, TGraph, kTRUE, kFALSE
    from ROOT import RooRealVar, RooDataHist, RooArgList, RooArgSet, RooAddPdf, RooFit, RooGenericPdf, RooWorkspace, RooMsgService, RooHistPdf, PdfDiagonalizer

    if not args.debug:
        RooMsgService.instance().setSilentMode(kTRUE)
        RooMsgService.instance().setStreamStatus(0,kFALSE)
        RooMsgService.instance().setStreamStatus(1,kFALSE)

    # input data file
    data_file = TFile(analysis_config.get_b_histogram_filename(args.analysis, args.data_sample), "READ")
    # input data histogram
    hData = data_file.Get(args.data_hist)

    # input sig file
    signal_shapes_file = TFile(args.signal_shapes)

    sqrtS = args.sqrtS

    # mass variable
    mjj = RooRealVar('mjj','mjj',float(args.min_mass),float(args.max_mass))

    # integrated luminosity and signal cross section
    lumi = args.lumi
    signalCrossSection = 1. # set to 1. so that the limit on r can be interpreted as a limit on the signal cross section
def plot_all_masses(analysis, model, masses):
    ratio_up = {}
    ratio_down = {}
    for mass in masses:
        f = TFile(
            analysis_config.get_b_histogram_filename(
                analysis,
                analysis_config.simulation.get_signal_tag(
                    model, mass, "FULLSIM")), "READ")
        h_central = f.Get("BHistograms/h_pfjet_mjj")
        h_central.SetDirectory(0)
        h_central = histogram_tools.rebin_histogram(h_central,
                                                    dijet_binning,
                                                    normalization_bin_width=1.)
        h_up = f.Get("BHistograms/h_pfjet_mjj_BTagOfflineSFUp")
        h_up.SetDirectory(0)
        h_up = histogram_tools.rebin_histogram(h_up,
                                               dijet_binning,
                                               normalization_bin_width=1.)
        h_down = f.Get("BHistograms/h_pfjet_mjj_BTagOfflineSFDown")
        h_down.SetDirectory(0)
        h_down = histogram_tools.rebin_histogram(h_down,
                                                 dijet_binning,
                                                 normalization_bin_width=1.)
        ratio_up[mass] = h_up.Clone()
        ratio_up[mass].SetName("ratio_up_{}".format(mass))
        ratio_up[mass].SetDirectory(0)
        ratio_up[mass].Divide(h_central)
        ratio_up[mass].SetMarkerStyle(26)
        ratio_up[mass].Draw("p hist same")
        ratio_down[mass] = h_down.Clone()
        ratio_down[mass].SetName("ratio_down_{}".format(mass))
        ratio_down[mass].SetDirectory(0)
        ratio_down[mass].Divide(h_central)
        ratio_down[mass].SetMarkerStyle(32)
        ratio_down[mass].Draw("p hist same")
        norm = h_central.Integral()
        print "{}\t{}\t{}:{}".format(analysis, model, mass,
                                     h_up.Integral() / norm - 1.)
        f.Close()

    c = TCanvas("c_offb_unc_{}_{}_all".format(analysis, model),
                "c_offb_unc_{}_{}_all".format(analysis, model), 800, 600)
    frame = TH1D("frame", "frame", 100, 0., 1300.)
    frame.SetMinimum(0.8)
    frame.SetMaximum(1.2)
    frame.GetXaxis().SetTitle("m_{jj}")
    frame.GetYaxis().SetTitle("SF Variation / Central")
    frame.Draw()
    for style_counter, mass in enumerate(masses):
        ratio_up[mass].SetMarkerStyle(20)
        ratio_up[mass].SetMarkerColor(
            seaborn.GetColorRoot("cubehelixlarge", style_counter,
                                 len(masses) + 2))
        ratio_up[mass].SetLineColor(
            seaborn.GetColorRoot("cubehelixlarge", style_counter,
                                 len(masses) + 2))
        ratio_up[mass].Draw("hist same")
        ratio_down[mass].SetMarkerStyle(20)
        ratio_down[mass].SetMarkerColor(
            seaborn.GetColorRoot("cubehelixlarge", style_counter,
                                 len(masses) + 2))
        ratio_down[mass].SetLineColor(
            seaborn.GetColorRoot("cubehelixlarge", style_counter,
                                 len(masses) + 2))
        ratio_down[mass].Draw("hist same")
    c.SaveAs(analysis_config.figure_directory + "/" + c.GetName() + ".pdf")
Beispiel #15
0
            565, 606, 649, 693, 740, 788, 838, 890, 944, 1000, 1058, 1118,
            1181, 1246, 1313, 1383, 1455, 1530, 1607, 1687, 1770, 1856, 1945,
            2037, 2132, 2231, 2332, 2438, 2546, 2659, 2775, 2895, 3019, 3147,
            3279, 3416, 3558, 3704, 3854, 4010, 4171, 4337, 4509, 4686, 4869,
            5000
        ]
    )  #5058, 5253, 5455, 5663, 5877, 6099, 6328, 6564, 6808, 7060, 7320, 7589, 7866, 8000])
    if args.x_range:
        x_range = args.x_range
    else:
        x_range = [0., 2000.]

    if args.what == "mjj":
        for analysis in analyses:
            histogram_file = TFile(
                analysis_config.get_b_histogram_filename(
                    analysis, "BJetPlusX_2012"), "READ")
            data_histogram_raw = histogram_file.Get("BHistograms/h_pfjet_mjj")
            data_histogram = CorrectTriggerEfficiency(data_histogram_raw,
                                                      analysis)
            print "Data integral = {}".format(data_histogram.Integral())
            #if "trigbbh" in analysis:
            #	trigger_correction = "bbh"
            #elif "trigbbl" in analysis:
            #	trigger_correction = "bbl"
            data_histogram.SetDirectory(0)
            for model in models:
                background_workspace = limit_config.get_workspace_filename(
                    analysis,
                    model,
                    750,
                    fitBonly=True,
Beispiel #16
0
mc_analyses = {
	"lowmass":{
		"mctrigger":"trigbbl_CSVTM",
		"datatrigger":"NoTrigger_eta1p7_CSVTM"
	}, 
	"highmass":{
		"mctrigger":"trigbbh_CSVTM",
		"datatrigger":"NoTrigger_eta2p2_CSVTM"
	}
}
data_analyses = {"lowmass":"trigbbl_CSVTM", "highmass":"trigbbh_CSVTM"}

dijet_binning = array("d", [1, 3, 6, 10, 16, 23, 31, 40, 50, 61, 74, 88, 103, 119, 137, 156, 176, 197, 220, 244, 270, 296, 325, 354, 386, 419, 453, 489, 526, 565, 606, 649, 693, 740, 788, 838, 890, 944, 1000, 1058, 1118, 1181, 1246, 1313, 1383, 1455, 1530, 1607, 1687, 1770, 1856, 1945, 2037, 2132, 2231, 2332, 2438, 2546, 2659, 2775, 2895, 3019, 3147, 3279, 3416, 3558, 3704, 3854, 4010, 4171, 4337, 4509, 4686, 4869, 5000]) #5058, 5253, 5455, 5663, 5877, 6099, 6328, 6564, 6808, 7060, 7320, 7589, 7866, 8000])

for signal_region in signal_regions:
	f_data = TFile(analysis_config.get_b_histogram_filename(data_analyses[signal_region], "BJetPlusX_2012"), "READ")
	data_hist_raw = f_data.Get("BHistograms/h_pfjet_mjj")
	data_hist_raw.SetName("mjj_data_" + signal_region)
	data_hist_raw.SetDirectory(0)
	f_data.Close()

	for strategy in strategies:
		f_mc = TFile(analysis_config.get_b_histogram_filename(mc_analyses[signal_region][strategy], "QCD_TuneZ2star_8TeV_pythia6"), "READ")
		mc_hist = f_mc.Get("BHistograms/h_pfjet_mjj")
		mc_hist.SetName("mjj_mc_" + signal_region + "_" + strategy)
		mc_hist.SetDirectory(0)
		if strategy == "datatrigger":
			if signal_region == "lowmass":
				mc_hist.Scale(trigger_efficiency.online_btag_eff["trigbbl_CSVTM"][0])
			elif signal_region == "highmass":
				mc_hist.Scale(trigger_efficiency.online_btag_eff["trigbbh_CSVTM"][0])
Beispiel #17
0
qcd_cross_sections["QCD_Pt-1800_TuneZ2star_8TeV_pythia6"] = 0.001829005
online_btag_eff = {
	"trigbbl_CSVTM":1.82719e-01,
	"trigbbh_CSVTM":4.89446e-01,
}

truth_categories = ["bb", "bc", "bg", "bl", "cc", "cg", "cl", "gg", "gl", "ll"]
truth_categories_incl = ["inclusive", "bb", "bc", "bg", "bl", "cc", "cg", "cl", "gg", "gl", "ll"]



for analysis in analyses:
	h_mjj = None
	h_mjj_truthbb = None
	for qcd_sample in qcd_samples:
		f = TFile(analysis_config.get_b_histogram_filename(analysis, qcd_sample), "READ")
		input_nevents = f.Get("BHistograms/h_input_nevents").Integral()
		this_h_mjj = f.Get("BHistograms/h_pfjet_mjj").Clone()
		this_h_mjj.Scale(19700.*qcd_cross_sections[qcd_sample] / input_nevents)
		this_h_mjj_truthbb = f.Get("BHistograms/h_pfjet_mjj_truthbb").Clone()
		this_h_mjj_truthbb.Scale(19700.*qcd_cross_sections[qcd_sample] / input_nevents)
		if not h_mjj:
			h_mjj = this_h_mjj.Clone()
			h_mjj.SetDirectory(0)
			h_mjj_truthbb = this_h_mjj_truthbb.Clone()
			h_mjj_truthbb.SetDirectory(0)
		else:
			h_mjj.Add(this_h_mjj)
			h_mjj_truthbb.Add(this_h_mjj_truthbb)
		f.Close()
	h_mjj = histogram_tools.rebin_histogram(h_mjj, dijet_binning, normalization_bin_width=1.)
	max_eff = -1.
	for model in ["Hbb", "ZPrime", "RSG"]:
		#if analysis == "trigbbl_CSVTM":
		#	notrig_analysis = "NoTrigger_eta1p7_CSVTM"
		#elif analysis == "trigbbh_CSVTM":
		#	notrig_analysis = "NoTrigger_eta2p2_CSVTM"

        #signal_pdf_file = analysis_config.get_signal_fit_file(notrig_analysis, args.model, mass, "bukin", interpolated=(not mass in analysis_config.simulation.simulated_masses))
		if "bbl" in analysis:
			mjj_range = [296, 1058]
		elif "bbh" in analysis:
			mjj_range = [526, 1607]

		tg_eff[analysis][model] = TGraphErrors(len(masses[analysis]))
		for i, mass in enumerate(masses[analysis]):
			f = TFile(analysis_config.get_b_histogram_filename(analysis, analysis_config.simulation.get_signal_tag(model, mass, "FULLSIM")))
			if not f.IsOpen():
				continue
			low_bin = f.Get("BHistograms/h_pfjet_mjj").GetXaxis().FindBin(mjj_range[0] + 1.e-5)
			high_bin = f.Get("BHistograms/h_pfjet_mjj").GetXaxis().FindBin(mjj_range[1] - 1.e-5)
			numerator = f.Get("BHistograms/h_pfjet_mjj").Integral(low_bin, high_bin)
			if model == "ZPrime":
				denominator = f.Get("BHistograms/h_input_nevents").Integral()
				print "{} / {} den = {}".format(model, analysis, denominator)
			else:
				denominator = f.Get("BHistograms/h_sample_nevents").Integral()
			if denominator > 0:
				eff = numerator/denominator
				deff = (eff*(1.-eff)/denominator)**0.5
				eff *= 100
				deff *= 100
Beispiel #19
0
	#parser.add_argument("--fit_max_mjj", dest="fit_max_mjj",
	#					default=1500., type=float,
	#					help="Upper bound of the mass range used for fitting (default: %(default)s)",
	#					metavar="MASS_MAX")

	args = parser.parse_args()

	# Pack up fit options
	fit_options = {}
	fit_options["min_mjj"] = args.min_mjj
	fit_options["max_mjj"] = args.max_mjj
	#fit_options["fit_range"] = [args.fit_min_mjj, args.fit_max_mjj]
	mjj_fit = MjjFit([args.min_mjj, args.max_mjj])
	#if args.fit_range:
	#	mjj_fit.set_fit_range(args.fit_range)
	data_file = TFile(analysis_config.get_b_histogram_filename(args.analysis_name, args.data_sample), "READ")
	mjj_fit.add_data(data_file.Get("BHistograms/h_pfjet_mjj"), args.lumi)
	data_file.Close()

	if args.backgrounds:
		backgrounds = args.backgrounds.split(",")
		for background in backgrounds:
			if analysis_config.simulation.background_supersamples.has_key(background):
				first = True
				for subbackground in analysis_config.simulation.background_supersamples[background]:
					background_file = TFile(analysis_config.get_b_histogram_filename(args.analysis_name, subbackground), "READ")
					input_nevents = background_file.Get("BHistograms/h_input_nevents").Integral()
					if first:
						background_histogram = background_file.Get("BHistograms/h_pfjet_mjj").Clone()
						print "Scaling background histogram " + subbackground + " by " + str(args.lumi) + "*" + str(analysis_config.simulation.background_cross_sections[subbackground]) + " / " + str(input_nevents) + " = " + str(args.lumi * analysis_config.simulation.background_cross_sections[subbackground] / input_nevents)
						background_histogram.Scale(args.lumi * analysis_config.simulation.background_cross_sections[subbackground] / input_nevents)
Beispiel #20
0
def mc_jes_plot(analysis, model, mass):
	f_new = TFile(analysis_config.get_b_histogram_filename(analysis, analysis_config.simulation.get_signal_tag(model, mass, "FULLSIM")), "READ")
	h_new = f_new.Get("BHistograms/h_pfjet_mjj")
	h_new.SetName("h_pfjet_mjj_newJEC")
	h_new.SetDirectory(0)
	h_new = histogram_tools.rebin_histogram(h_new, dijet_binning, normalization_bin_width=1.)

	f_old = TFile(analysis_config.get_b_histogram_filename(analysis, analysis_config.simulation.get_signal_tag(model, mass, "FULLSIM")).replace("EightTeeEeVeeBee/BHistograms", "EightTeeEeVeeBee/BHistograms/old/JEC2012"), "READ")
	h_old = f_old.Get("BHistograms/h_pfjet_mjj")
	h_old.SetName("h_pfjet_mjj_oldJEC")
	h_old.SetDirectory(0)
	h_old = histogram_tools.rebin_histogram(h_old, dijet_binning, normalization_bin_width=1.)

	c = TCanvas("c_jeccomparison_{}_{}_{}".format(analysis, model, mass), "c_jeccomparison_{}_{}_{}".format(analysis, model, mass), 800, 1200)
	top = TPad("top", "top", 0., 0.5, 1., 1.)
	top.SetBottomMargin(0.02)
	#top.SetLogy()
	top.Draw()
	top.cd()
	frame_top = TH1D("frame_top", "frame_top", 100, 0., mass*2)
	frame_top.GetXaxis().SetTitleSize(0)
	frame_top.GetXaxis().SetLabelSize(0)
	frame_top.GetYaxis().SetTitle("Events / GeV")
	frame_top.SetMinimum(0.01)
	frame_top.SetMaximum(h_new.GetMaximum() * 1.3)
	frame_top.Draw()
	h_new.SetMarkerStyle(20)
	h_new.GetXaxis().SetTitleSize(0)
	h_new.GetXaxis().SetLabelSize(0)
	h_new.GetYaxis().SetTitle("Events / GeV")
	h_new.Draw("same")
	h_old.SetMarkerStyle(25)
	h_old.Draw("same")
	l = TLegend(0.6, 0.6, 0.88, 0.8)
	l.SetFillColor(0)
	l.SetBorderSize(0)
	l.AddEntry(h_new, "New JEC")
	l.AddEntry(h_old, "Old JEC")
	l.Draw()

	c.cd()
	bottom = TPad("bottom", "bottom", 0., 0., 1., 0.5)
	bottom.SetTopMargin(0.02)
	bottom.SetBottomMargin(0.2)
	bottom.Draw()
	bottom.cd()
	frame_bottom = TH1D("frame_bottom", "frame_bottom", 100, 0., mass*2)
	frame_bottom.GetXaxis().SetTitle("m_{jj} [GeV]")
	frame_bottom.GetYaxis().SetTitle("New JEC / Old JEC")
	frame_bottom.SetMinimum(0.5)
	frame_bottom.SetMaximum(1.5)
	frame_bottom.Draw()
	h_ratio = h_new.Clone()
	h_ratio.Divide(h_old)
	h_ratio.SetMarkerStyle(21)
	h_ratio.Draw("same")

	c.cd()
	c.SaveAs(analysis_config.figure_directory + "/" + c.GetName() + ".pdf")


	f_new.Close()
	f_old.Close()
qcd_cross_sections["QCD_Pt-470to600_TuneZ2star_8TeV_pythia6"] = 113.8791
qcd_cross_sections["QCD_Pt-600to800_TuneZ2star_8TeV_pythia6"] = 26.9921
qcd_cross_sections["QCD_Pt-800to1000_TuneZ2star_8TeV_pythia6"] = 3.550036
qcd_cross_sections["QCD_Pt-1000to1400_TuneZ2star_8TeV_pythia6"] = 0.737844
qcd_cross_sections["QCD_Pt-1400to1800_TuneZ2star_8TeV_pythia6"] = 0.03352235
qcd_cross_sections["QCD_Pt-1800_TuneZ2star_8TeV_pythia6"] = 0.001829005
online_btag_eff = {
	"trigbbl_CSVTM":1.82719e-01,
	"trigbbh_CSVTM":4.89446e-01,
}
qcd_hists_num = {} # QCD with trigbb*
qcd_hists_den = {} # QCD with NoTrigger*
qcd_hists_eff = {}
for sr in srs:
	for qcd_sample in qcd_samples:
		f_num = TFile(analysis_config.get_b_histogram_filename(trig_analyses[sr], qcd_sample), "READ")
		f_den = TFile(analysis_config.get_b_histogram_filename(notrig_analyses[sr], qcd_sample), "READ")
		input_nevents_num = f_num.Get("BHistograms/h_input_nevents").Integral()
		this_num_hist = f_num.Get("BHistograms/h_pfjet_mjj")
		#this_num_hist.Scale(19700.*qcd_cross_sections[qcd_sample] / input_nevents_num)
		input_nevents_den = f_den.Get("BHistograms/h_input_nevents").Integral()
		this_den_hist = f_den.Get("BHistograms/h_pfjet_mjj")
		#this_den_hist.Scale(19700.*qcd_cross_sections[qcd_sample] / input_nevents_den)
		if not sr in qcd_hists_num:
			qcd_hists_num[sr] = this_num_hist.Clone()
			qcd_hists_num[sr].SetDirectory(0)
			qcd_hists_den[sr] = this_den_hist.Clone()
			qcd_hists_den[sr].SetDirectory(0)
		else:
			qcd_hists_num[sr].Add(this_num_hist)
			qcd_hists_den[sr].Add(this_den_hist)
    # sort masses
    masses.sort()

    # import ROOT stuff
    from ROOT import TFile, TH1F, TH1D, TGraph, kTRUE, kFALSE
    from ROOT import RooRealVar, RooDataHist, RooArgList, RooArgSet, RooAddPdf, RooFit, RooGenericPdf, RooWorkspace, RooMsgService, RooHistPdf, PdfDiagonalizer

    if not args.debug:
        RooMsgService.instance().setSilentMode(kTRUE)
        RooMsgService.instance().setStreamStatus(0, kFALSE)
        RooMsgService.instance().setStreamStatus(1, kFALSE)

    # input data file
    data_file = TFile(
        analysis_config.get_b_histogram_filename(args.analysis,
                                                 args.data_sample), "READ")
    # input data histogram
    hData = data_file.Get(args.data_hist)

    # input sig file
    signal_shapes_file = TFile(args.signal_shapes)

    sqrtS = args.sqrtS

    # mass variable
    mjj = RooRealVar('mjj', 'mjj', float(args.min_mass), float(args.max_mass))

    # integrated luminosity and signal cross section
    lumi = args.lumi
    signalCrossSection = 1.  # set to 1. so that the limit on r can be interpreted as a limit on the signal cross section
Beispiel #23
0
        #if analysis == "trigbbl_CSVTM":
        #	notrig_analysis = "NoTrigger_eta1p7_CSVTM"
        #elif analysis == "trigbbh_CSVTM":
        #	notrig_analysis = "NoTrigger_eta2p2_CSVTM"

        #signal_pdf_file = analysis_config.get_signal_fit_file(notrig_analysis, args.model, mass, "bukin", interpolated=(not mass in analysis_config.simulation.simulated_masses))
        if "bbl" in analysis:
            mjj_range = [296, 1058]
        elif "bbh" in analysis:
            mjj_range = [526, 1607]

        tg_eff[analysis][model] = TGraphErrors(len(masses[analysis]))
        for i, mass in enumerate(masses[analysis]):
            f = TFile(
                analysis_config.get_b_histogram_filename(
                    analysis,
                    analysis_config.simulation.get_signal_tag(
                        model, mass, "FULLSIM")))
            if not f.IsOpen():
                continue
            low_bin = f.Get("BHistograms/h_pfjet_mjj").GetXaxis().FindBin(
                mjj_range[0] + 1.e-5)
            high_bin = f.Get("BHistograms/h_pfjet_mjj").GetXaxis().FindBin(
                mjj_range[1] - 1.e-5)
            numerator = f.Get("BHistograms/h_pfjet_mjj").Integral(
                low_bin, high_bin)
            if model == "ZPrime":
                denominator = f.Get("BHistograms/h_input_nevents").Integral()
                print "{} / {} den = {}".format(model, analysis, denominator)
            else:
                denominator = f.Get("BHistograms/h_sample_nevents").Integral()
            if denominator > 0:
def plot(analysis, model, mass):
    f = TFile(
        analysis_config.get_b_histogram_filename(
            analysis,
            analysis_config.simulation.get_signal_tag(model, mass, "FULLSIM")),
        "READ")
    h_central = f.Get("BHistograms/h_pfjet_mjj")
    h_central.SetDirectory(0)
    h_central = histogram_tools.rebin_histogram(h_central,
                                                dijet_binning,
                                                normalization_bin_width=1.)
    h_up = f.Get("BHistograms/h_pfjet_mjj_BTagOfflineSFUp")
    h_up.SetDirectory(0)
    h_up = histogram_tools.rebin_histogram(h_up,
                                           dijet_binning,
                                           normalization_bin_width=1.)
    h_down = f.Get("BHistograms/h_pfjet_mjj_BTagOfflineSFDown")
    h_down.SetDirectory(0)
    h_down = histogram_tools.rebin_histogram(h_down,
                                             dijet_binning,
                                             normalization_bin_width=1.)

    c = TCanvas("c_offb_unc_{}_{}{}".format(analysis, model, mass),
                "c_offb_unc_{}_{}{}".format(analysis, model, mass), 800, 1000)
    top = TPad("top", "top", 0., 0.5, 1., 1.)
    top.SetBottomMargin(0.02)
    #top.SetLogy()
    top.Draw()
    top.cd()
    frame_top = TH1D("frame_top", "frame_top", 100, 0., mass * 2)
    frame_top.GetXaxis().SetTitleSize(0)
    frame_top.GetXaxis().SetLabelSize(0)
    frame_top.GetYaxis().SetTitle("Events / GeV")
    frame_top.SetMinimum(0.01)
    frame_top.SetMaximum(h_central.GetMaximum() * 1.3)
    frame_top.Draw()
    h_central.SetMarkerStyle(20)
    h_central.Draw("same")
    h_up.SetMarkerStyle(26)
    h_up.Draw("same")
    h_down.SetMarkerStyle(32)
    h_down.Draw("same")
    l = TLegend(0.6, 0.6, 0.88, 0.8)
    l.SetFillColor(0)
    l.SetBorderSize(0)
    l.AddEntry(h_central, "Central", "p")
    l.AddEntry(h_up, "SF unc up", "p")
    l.AddEntry(h_down, "SF unc down", "p")
    l.Draw()

    c.cd()
    bottom = TPad("bottom", "bottom", 0., 0., 1., 0.5)
    bottom.SetTopMargin(0.02)
    bottom.SetBottomMargin(0.2)
    bottom.Draw()
    bottom.cd()
    frame_bottom = TH1D("frame_bottom", "frame_bottom", 100, 0., mass * 2)
    frame_bottom.GetXaxis().SetTitle("m_{jj} [GeV]")
    frame_bottom.GetYaxis().SetTitle("Unc / Central")
    frame_bottom.SetMinimum(0.5)
    frame_bottom.SetMaximum(1.5)
    frame_bottom.Draw()
    ratio_up = h_up.Clone()
    ratio_up.Divide(h_central)
    ratio_up.SetMarkerStyle(26)
    ratio_up.Draw("p hist same")
    ratio_down = h_down.Clone()
    ratio_down.Divide(h_central)
    ratio_down.SetMarkerStyle(32)
    ratio_down.Draw("p hist same")

    avg_up = TLine(0.,
                   h_up.Integral() / h_central.Integral(), mass * 2,
                   h_up.Integral() / h_central.Integral())
    avg_up.SetLineStyle(2)
    avg_up.SetLineColor(seaborn.GetColorRoot("pastel", 2))
    avg_up.Draw("same")
    avg_down = TLine(0.,
                     h_down.Integral() / h_central.Integral(), mass * 2,
                     h_down.Integral() / h_central.Integral())
    avg_down.SetLineStyle(2)
    avg_down.SetLineColor(seaborn.GetColorRoot("pastel", 2))
    avg_down.Draw("same")

    c.cd()
    c.SaveAs(analysis_config.figure_directory + "/" + c.GetName() + ".pdf")

    f.Close()
Beispiel #25
0
		if analysis == "trigbbl_CSVTM":
			notrig_analysis = "NoTrigger_eta1p7_CSVTM"
		elif analysis == "trigbbh_CSVTM":
			notrig_analysis = "NoTrigger_eta2p2_CSVTM"


        #signal_pdf_file = analysis_config.get_signal_fit_file(notrig_analysis, args.model, mass, "bukin", interpolated=(not mass in analysis_config.simulation.simulated_masses))
		signal_acc_times_eff[model][analysis] = {}
		if "bbl" in analysis:
			mjj_range = [296, 1058]
		elif "bbh" in analysis:
			mjj_range = [526, 1607]

		for mass in masses[analysis]:
			if use_MC_trigger:
				f = TFile(analysis_config.get_b_histogram_filename(analysis, analysis_config.simulation.get_signal_tag(model, mass, "FULLSIM")))
			else:
				f = TFile(analysis_config.get_b_histogram_filename(notrig_analysis, analysis_config.simulation.get_signal_tag(model, mass, "FULLSIM")))
			if not f.IsOpen():
				signal_acc_times_eff[model][analysis][mass] = 0.
				continue
			low_bin = f.Get("BHistograms/h_pfjet_mjj").GetXaxis().FindBin(mjj_range[0] + 1.e-5)
			high_bin = f.Get("BHistograms/h_pfjet_mjj").GetXaxis().FindBin(mjj_range[1] - 1.e-5)
			numerator = f.Get("BHistograms/h_pfjet_mjj").Integral(low_bin, high_bin)
			if "ZPrime" in model:
				denominator = f.Get("BHistograms/h_input_nevents").Integral()
				print "{} / {} den = {}".format(model, analysis, denominator)
			else:
				denominator = f.Get("BHistograms/h_sample_nevents").Integral()

			if denominator > 0:
def plot(analysis, model, mass):
	f = TFile(analysis_config.get_b_histogram_filename(analysis, analysis_config.simulation.get_signal_tag(model, mass, "FULLSIM")), "READ")
	h_central = f.Get("BHistograms/h_pfjet_mjj")
	h_central.SetDirectory(0)
	h_central = histogram_tools.rebin_histogram(h_central, dijet_binning, normalization_bin_width=1.)
	h_up = f.Get("BHistograms/h_pfjet_mjj_BTagOfflineSFUp")
	h_up.SetDirectory(0)
	h_up = histogram_tools.rebin_histogram(h_up, dijet_binning, normalization_bin_width=1.)
	h_down = f.Get("BHistograms/h_pfjet_mjj_BTagOfflineSFDown")
	h_down.SetDirectory(0)
	h_down = histogram_tools.rebin_histogram(h_down, dijet_binning, normalization_bin_width=1.)

	c = TCanvas("c_offb_unc_{}_{}{}".format(analysis, model, mass), "c_offb_unc_{}_{}{}".format(analysis, model, mass), 800, 1000)
	top = TPad("top", "top", 0., 0.5, 1., 1.)
	top.SetBottomMargin(0.02)
	#top.SetLogy()
	top.Draw()
	top.cd()
	frame_top = TH1D("frame_top", "frame_top", 100, 0., mass*2)
	frame_top.GetXaxis().SetTitleSize(0)
	frame_top.GetXaxis().SetLabelSize(0)
	frame_top.GetYaxis().SetTitle("Events / GeV")
	frame_top.SetMinimum(0.01)
	frame_top.SetMaximum(h_central.GetMaximum() * 1.3)
	frame_top.Draw()
	h_central.SetMarkerStyle(20)
	h_central.Draw("same")
	h_up.SetMarkerStyle(26)
	h_up.Draw("same")
	h_down.SetMarkerStyle(32)
	h_down.Draw("same")
	l = TLegend(0.6, 0.6, 0.88, 0.8)
	l.SetFillColor(0)
	l.SetBorderSize(0)
	l.AddEntry(h_central, "Central", "p")
	l.AddEntry(h_up, "SF unc up", "p")
	l.AddEntry(h_down, "SF unc down", "p")
	l.Draw()

	c.cd()
	bottom = TPad("bottom", "bottom", 0., 0., 1., 0.5)
	bottom.SetTopMargin(0.02)
	bottom.SetBottomMargin(0.2)
	bottom.Draw()
	bottom.cd()
	frame_bottom = TH1D("frame_bottom", "frame_bottom", 100, 0., mass*2)
	frame_bottom.GetXaxis().SetTitle("m_{jj} [GeV]")
	frame_bottom.GetYaxis().SetTitle("Unc / Central")
	frame_bottom.SetMinimum(0.5)
	frame_bottom.SetMaximum(1.5)
	frame_bottom.Draw()
	ratio_up = h_up.Clone()
	ratio_up.Divide(h_central)
	ratio_up.SetMarkerStyle(26)
	ratio_up.Draw("p hist same")
	ratio_down = h_down.Clone()
	ratio_down.Divide(h_central)
	ratio_down.SetMarkerStyle(32)
	ratio_down.Draw("p hist same")

	avg_up = TLine(0., h_up.Integral() / h_central.Integral(), mass*2, h_up.Integral() / h_central.Integral())
	avg_up.SetLineStyle(2)
	avg_up.SetLineColor(seaborn.GetColorRoot("pastel", 2))
	avg_up.Draw("same")
	avg_down = TLine(0., h_down.Integral() / h_central.Integral(), mass*2, h_down.Integral() / h_central.Integral())
	avg_down.SetLineStyle(2)
	avg_down.SetLineColor(seaborn.GetColorRoot("pastel", 2))
	avg_down.Draw("same")


	c.cd()
	c.SaveAs(analysis_config.figure_directory + "/" + c.GetName() + ".pdf")

	f.Close()
def main():
    # usage description
    usage = "Example: ./scripts/createDatacards.py --inputData inputs/rawhistV7_Run2015D_scoutingPFHT_UNBLINDED_649_838_JEC_HLTplusV7_Mjj_cor_smooth.root --dataHistname mjj_mjjcor_gev --inputSig inputs/ResonanceShapes_gg_13TeV_Scouting_Spring15.root -f gg -o datacards -l 1866 --lumiUnc 0.027 --massrange 1000 1500 50 --runFit --p1 5 --p2 7 --p3 0.4 --massMin 838 --massMax 2037 --fitStrategy 2"

    # input parameters
    parser = ArgumentParser(
        description=
        'Script that creates combine datacards and corresponding RooFit workspaces',
        epilog=usage)
    parser.add_argument("analysis", type=str, help="Analysis name")
    parser.add_argument("model", type=str, help="Model (Hbb, RSG)")

    #parser.add_argument("--inputData", dest="inputData", required=True,
    #                    help="Input data spectrum",
    #                    metavar="INPUT_DATA")

    parser.add_argument("--dataHistname",
                        dest="dataHistname",
                        type=str,
                        default="h_data",
                        help="Data histogram name",
                        metavar="DATA_HISTNAME")

    #parser.add_argument("--inputSig", dest="inputSig", required=True,
    #                    help="Input signal shapes",
    #                    metavar="INPUT_SIGNAL")

    parser.add_argument("-f",
                        "--final_state",
                        dest="final_state",
                        default="qq",
                        help="Final state (e.g. qq, qg, gg)",
                        metavar="FINAL_STATE")
    parser.add_argument("--fit_functions",
                        dest="fit_functions",
                        default="f1,f2,f3,f4,f5",
                        help="List of fit functions")

    #parser.add_argument("-f2", "--type", dest="atype", required=True, help="Type (e.g. hG, lG, hR, lR)")

    parser.add_argument(
        "-o",
        "--output_path",
        dest="output_path",
        help=
        "Output path where datacards and workspaces will be stored. If not specified, this is derived from limit_configuration.",
        metavar="OUTPUT_PATH")

    parser.add_argument("--correctTrigger",
                        dest="correctTrigger",
                        action='store_true',
                        help="Include trigger correction in PDF")

    parser.add_argument(
        "-l",
        "--lumi",
        dest="lumi",
        default=19700.,
        type=float,
        help="Integrated luminosity in pb-1 (default: %(default).1f)",
        metavar="LUMI")

    parser.add_argument(
        "--massMin",
        dest="massMin",
        default=500,
        type=int,
        help=
        "Lower bound of the mass range used for fitting (default: %(default)s)",
        metavar="MASS_MIN")

    parser.add_argument(
        "--massMax",
        dest="massMax",
        default=1200,
        type=int,
        help=
        "Upper bound of the mass range used for fitting (default: %(default)s)",
        metavar="MASS_MAX")
    parser.add_argument(
        "--fitSignal",
        action="store_true",
        help=
        "Use signal fitted shapes (CB+Voigtian) instead of histogram templates"
    )
    #parser.add_argument("--lumiUnc", dest="lumiUnc",
    #                    required=True, type=float,
    #                    help="Relative uncertainty in the integrated luminosity",
    #                    metavar="LUMI_UNC")

    #parser.add_argument("--jesUnc", dest="jesUnc",
    #                    type=float,
    #                    help="Relative uncertainty in the jet energy scale",
    #                    metavar="JES_UNC")

    #parser.add_argument("--jerUnc", dest="jerUnc",
    #                    type=float,
    #                    help="Relative uncertainty in the jet energy resolution",
    #                    metavar="JER_UNC")

    parser.add_argument(
        "--sqrtS",
        dest="sqrtS",
        default=8000.,
        type=float,
        help="Collision center-of-mass energy (default: %(default).1f)",
        metavar="SQRTS")

    parser.add_argument("--fixP3",
                        dest="fixP3",
                        default=False,
                        action="store_true",
                        help="Fix the fit function p3 parameter")

    parser.add_argument("--runFit",
                        dest="runFit",
                        default=False,
                        action="store_true",
                        help="Run the fit")

    parser.add_argument("--fitBonly",
                        dest="fitBonly",
                        default=False,
                        action="store_true",
                        help="Run B-only fit")

    parser.add_argument("--fixBkg",
                        dest="fixBkg",
                        default=False,
                        action="store_true",
                        help="Fix all background parameters")

    parser.add_argument("--decoBkg",
                        dest="decoBkg",
                        default=False,
                        action="store_true",
                        help="Decorrelate background parameters")

    parser.add_argument("--fitStrategy",
                        dest="fitStrategy",
                        type=int,
                        default=1,
                        help="Fit strategy (default: %(default).1f)")

    parser.add_argument("--debug",
                        dest="debug",
                        default=False,
                        action="store_true",
                        help="Debug printout")

    parser.add_argument(
        "--postfix",
        dest="postfix",
        default='',
        help="Postfix for the output file names (default: %(default)s)")

    parser.add_argument("--pyes",
                        dest="pyes",
                        default=False,
                        action="store_true",
                        help="Make files for plots")

    parser.add_argument("--jyes",
                        dest="jyes",
                        default=False,
                        action="store_true",
                        help="Make files for JES/JER plots")

    parser.add_argument(
        "--pdir",
        dest="pdir",
        default='testarea',
        help="Name a directory for the plots (default: %(default)s)")

    parser.add_argument("--chi2",
                        dest="chi2",
                        default=False,
                        action="store_true",
                        help="Compute chi squared")

    parser.add_argument("--widefit",
                        dest="widefit",
                        default=False,
                        action="store_true",
                        help="Fit with wide bin hist")

    mass_group = parser.add_mutually_exclusive_group(required=True)
    mass_group.add_argument(
        "--mass",
        type=int,
        nargs='*',
        default=1000,
        help=
        "Mass can be specified as a single value or a whitespace separated list (default: %(default)i)"
    )
    mass_group.add_argument(
        "--massrange",
        type=int,
        nargs=3,
        help="Define a range of masses to be produced. Format: min max step",
        metavar=('MIN', 'MAX', 'STEP'))
    mass_group.add_argument("--masslist",
                            help="List containing mass information")

    args = parser.parse_args()

    fit_functions = args.fit_functions.split(",")

    # mass points for which resonance shapes will be produced
    masses = []

    if args.fitBonly:
        masses.append(750)
    else:
        if args.massrange != None:
            MIN, MAX, STEP = args.massrange
            masses = range(MIN, MAX + STEP, STEP)
        elif args.masslist != None:
            # A mass list was provided
            print "Will create mass list according to", args.masslist
            masslist = __import__(args.masslist.replace(".py", ""))
            masses = masslist.masses
        else:
            masses = args.mass

    # sort masses
    masses.sort()

    # import ROOT stuff
    from ROOT import gStyle, TFile, TH1F, TH1D, TGraph, kTRUE, kFALSE, TCanvas, TLegend, TPad, TLine
    from ROOT import RooHist, RooRealVar, RooDataHist, RooArgList, RooArgSet, RooAddPdf, RooProdPdf, RooEffProd, RooFit, RooGenericPdf, RooWorkspace, RooMsgService, RooHistPdf, RooExtendPdf

    if not args.debug:
        RooMsgService.instance().setSilentMode(kTRUE)
        RooMsgService.instance().setStreamStatus(0, kFALSE)
        RooMsgService.instance().setStreamStatus(1, kFALSE)

    # input data file
    #inputData = TFile(limit_config.get_data_input(args.analysis))
    # input data histogram
    #hData = inputData.Get(args.dataHistname)
    #hData.SetDirectory(0)
    data_file = TFile(
        analysis_config.get_b_histogram_filename(args.analysis,
                                                 "BJetPlusX_2012"))
    hData = data_file.Get("BHistograms/h_pfjet_mjj")
    hData.SetDirectory(0)

    # input sig file
    if not args.fitSignal:
        print "[create_datacards] INFO : Opening resonance shapes file at " + limit_config.get_resonance_shapes(
            args.analysis, args.model)
        inputSig = TFile(
            limit_config.get_resonance_shapes(args.analysis, args.model),
            "READ")

    sqrtS = args.sqrtS

    # mass variable
    mjj = RooRealVar('mjj', 'mjj', float(args.massMin), float(args.massMax))

    # integrated luminosity and signal cross section
    lumi = args.lumi
    signalCrossSection = 1.  # set to 1. so that the limit on r can be interpreted as a limit on the signal cross section

    if args.correctTrigger:
        trigger_efficiency_pdf = trigger_efficiency.get_pdf(args.analysis, mjj)
        trigger_efficiency_formula = trigger_efficiency.get_formula(
            args.analysis, mjj)
    else:
        trigger_efficiency_pdf = trigger_efficiency.get_trivial_pdf(mjj)
        trigger_efficiency_formula = trigger_efficiency.get_trivial_formula(
            mjj)

    for mass in masses:

        print ">> Creating datacard and workspace for %s resonance with m = %i GeV..." % (
            args.final_state, int(mass))

        rooDataHist = RooDataHist('rooDatahist', 'rooDathist', RooArgList(mjj),
                                  hData)

        if not args.fitSignal:
            hSig = inputSig.Get("h_" + args.final_state + "_" + str(int(mass)))
            if not hSig:
                raise Exception("Couldn't find histogram " + "h_" +
                                args.final_state + "_" + str(int(mass)) +
                                " in file " +
                                limit_config.get_resonance_shapes(
                                    args.analysis, args.model))
            # normalize signal shape to the expected event yield (works even if input shapes are not normalized to unity)
            hSig.Scale(
                signalCrossSection * lumi / hSig.Integral()
            )  # divide by a number that provides roughly an r value of 1-10
            rooSigHist = RooDataHist('rooSigHist', 'rooSigHist',
                                     RooArgList(mjj), hSig)
            print 'Signal acceptance:', (rooSigHist.sumEntries() /
                                         hSig.Integral())

        # If using fitted signal shapes, load the signal PDF
        if args.fitSignal:
            print "[create_datacards] Loading fitted signal PDFs from " + analysis_config.get_signal_fit_file(
                args.analysis,
                args.model,
                mass,
                "bukin",
                interpolated=(not mass
                              in analysis_config.simulation.simulated_masses))
            f_signal_pdfs = TFile(
                analysis_config.get_signal_fit_file(
                    args.analysis,
                    args.model,
                    mass,
                    "bukin",
                    interpolated=(
                        not mass
                        in analysis_config.simulation.simulated_masses)),
                "READ")
            w_signal = f_signal_pdfs.Get("w_signal")
            input_parameters = signal_fits.get_parameters(
                w_signal.pdf("signal"))

            # Make a new PDF with nuisance parameters
            signal_pdf_notrig, signal_vars = signal_fits.make_signal_pdf_systematic(
                "bukin", mjj, mass=mass)
            signal_pdf_name = signal_pdf_notrig.GetName()
            signal_pdf_notrig.SetName(signal_pdf_name + "_notrig")
            #signal_pdf = RooProdPdf(signal_pdf_name, signal_pdf_name, signal_pdf_notrig, trigger_efficiency_pdf)
            signal_pdf = RooEffProd(signal_pdf_name, signal_pdf_name,
                                    signal_pdf_notrig,
                                    trigger_efficiency_formula)

            # Copy input parameter values
            signal_vars["xp_0"].setVal(input_parameters["xp"][0])
            signal_vars["xp_0"].setError(input_parameters["xp"][1])
            signal_vars["xp_0"].setConstant()
            signal_vars["sigp_0"].setVal(input_parameters["sigp"][0])
            signal_vars["sigp_0"].setError(input_parameters["sigp"][1])
            signal_vars["sigp_0"].setConstant()
            signal_vars["xi_0"].setVal(input_parameters["xi"][0])
            signal_vars["xi_0"].setError(input_parameters["xi"][1])
            signal_vars["xi_0"].setConstant()
            signal_vars["rho1_0"].setVal(input_parameters["rho1"][0])
            signal_vars["rho1_0"].setError(input_parameters["rho1"][1])
            signal_vars["rho1_0"].setConstant()
            signal_vars["rho2_0"].setVal(input_parameters["rho2"][0])
            signal_vars["rho2_0"].setError(input_parameters["rho2"][1])
            signal_vars["rho2_0"].setConstant()
            f_signal_pdfs.Close()

        signal_parameters = {}
        signal_pdfs_notrig = {}
        signal_pdfs = {}
        signal_norms = {}
        background_pdfs = {}
        background_pdfs_notrig = {}
        background_parameters = {}
        background_norms = {}
        signal_epdfs = {}
        background_epdfs = {}
        models = {}
        fit_results = {}

        for fit_function in fit_functions:
            print "[create_datacards] INFO : On fit function {}".format(
                fit_function)

            if args.fitSignal:
                # Make a copy of the signal PDF, so that each fitTo call uses its own copy.
                # The copy should have all variables set constant.
                #signal_pdfs[fit_function], signal_parameters[fit_function] = signal_fits.copy_signal_pdf("bukin", signal_pdf, mjj, tag=fit_function, include_systematics=True)
                signal_pdfs_notrig[fit_function] = ROOT.RooBukinPdf(
                    signal_pdf_notrig,
                    signal_pdf_notrig.GetName() + "_" + fit_function)
                signal_pdfs[fit_function] = RooEffProd(
                    signal_pdf.GetName() + "_" + fit_function,
                    signal_pdf.GetName() + "_" + fit_function,
                    signal_pdfs_notrig[fit_function],
                    trigger_efficiency_formula)
                #signal_pdfs[fit_function] = RooProdPdf(signal_pdf.GetName() + "_" + fit_function, signal_pdf.GetName() + "_" + fit_function, signal_pdfs_notrig[fit_function], trigger_efficiency_pdf)
                iterator = signal_pdfs_notrig[fit_function].getVariables(
                ).createIterator()
                this_parameter = iterator.Next()
                while this_parameter:
                    this_parameter.setConstant()
                    this_parameter = iterator.Next()
            else:
                signal_pdfs[fit_function] = RooHistPdf(
                    'signal_' + fit_function, 'signal_' + fit_function,
                    RooArgSet(mjj), rooSigHist)
            signal_norms[fit_function] = RooRealVar(
                'signal_norm_' + fit_function, 'signal_norm_' + fit_function,
                0., 0., 1e+05)
            if args.fitBonly:
                signal_norms[fit_function].setConstant()
            background_pdfs_notrig[fit_function], background_parameters[
                fit_function] = make_background_pdf(fit_function,
                                                    mjj,
                                                    collision_energy=8000.)
            background_pdf_name = background_pdfs_notrig[fit_function].GetName(
            )
            background_pdfs_notrig[fit_function].SetName(background_pdf_name +
                                                         "_notrig")
            background_pdfs[fit_function] = RooEffProd(
                background_pdf_name, background_pdf_name,
                background_pdfs_notrig[fit_function],
                trigger_efficiency_formula)
            #background_pdfs[fit_function] = RooProdPdf(background_pdf_name, background_pdf_name, background_pdfs_notrig[fit_function], trigger_efficiency_pdf)
            #background_pdfs[fit_function] = background_pdfs_notrig[fit_function]
            #background_pdfs[fit_function].SetName(background_pdf_name)

            # Initial values
            if "trigbbh" in args.analysis:
                if fit_function == "f3":
                    background_parameters[fit_function]["p1"].setVal(55.)
                    background_parameters[fit_function]["p1"].setMin(20.)
                    background_parameters[fit_function]["p2"].setVal(8.)
                elif fit_function == "f4":
                    background_parameters[fit_function]["p1"].setVal(28.)
                    background_parameters[fit_function]["p2"].setVal(-22.)
                    background_parameters[fit_function]["p3"].setVal(10.)
            elif "trigbbl" in args.analysis:
                if fit_function == "f3":
                    background_parameters[fit_function]["p1"].setVal(82.)
                    background_parameters[fit_function]["p1"].setMin(60.)
                    background_parameters[fit_function]["p2"].setVal(8.)
                elif fit_function == "f4":
                    background_parameters[fit_function]["p1"].setVal(41.)
                    background_parameters[fit_function]["p2"].setVal(-45.)
                    background_parameters[fit_function]["p3"].setVal(10.)

            data_integral = hData.Integral(
                hData.GetXaxis().FindBin(float(args.massMin)),
                hData.GetXaxis().FindBin(float(args.massMax)))
            background_norms[fit_function] = RooRealVar(
                'background_' + fit_function + '_norm',
                'background_' + fit_function + '_norm', data_integral, 0.,
                1.e8)

            signal_epdfs[fit_function] = RooExtendPdf(
                'esignal_' + fit_function, 'esignal_' + fit_function,
                signal_pdfs[fit_function], signal_norms[fit_function])
            background_epdfs[fit_function] = RooExtendPdf(
                'ebackground_' + fit_function, 'ebackground_' + fit_function,
                background_pdfs[fit_function], background_norms[fit_function])

            models[fit_function] = RooAddPdf(
                'model_' + fit_function, 's+b',
                RooArgList(background_epdfs[fit_function],
                           signal_epdfs[fit_function]))

            if args.runFit:
                print "[create_datacards] INFO : Starting fit with function {}".format(
                    fit_function)
                fit_results[fit_function] = models[fit_function].fitTo(
                    rooDataHist, RooFit.Save(kTRUE), RooFit.Extended(kTRUE),
                    RooFit.Strategy(args.fitStrategy), RooFit.Verbose(0))
                print "[create_datacards] INFO : Done with fit {}. Printing results.".format(
                    fit_function)
                fit_results[fit_function].Print()
                print "[create_datacards] DEBUG : End args.runFit if block."

            # needed if want to evaluate limits without background systematics
            if args.fixBkg:
                background_norms[fit_function].setConstant()
                for par_name, par in background_parameters[
                        fit_function].iteritems():
                    par.setConstant()

        # -----------------------------------------
        #signal_pdfs_syst = {}
        # JES and JER uncertainties
        if args.fitSignal:
            print "[create_datacards] INFO : Getting signal PDFs from " + analysis_config.get_signal_fit_file(
                args.analysis,
                args.model,
                mass,
                "bukin",
                interpolated=(not mass
                              in analysis_config.simulation.simulated_masses))
            f_signal_pdfs = TFile(
                analysis_config.get_signal_fit_file(
                    args.analysis,
                    args.model,
                    mass,
                    "bukin",
                    interpolated=(
                        not mass
                        in analysis_config.simulation.simulated_masses)))
            w_signal = f_signal_pdfs.Get("w_signal")
            if "jes" in systematics:
                xp_central = signal_vars["xp_0"].getVal()
                #print w_signal.pdf("signal__JESUp")
                #print signal_fits.get_parameters(w_signal.pdf("signal__JESUp"))
                xp_up = signal_fits.get_parameters(
                    w_signal.pdf("signal__JESUp"))["xpJESUp"][0]
                xp_down = signal_fits.get_parameters(
                    w_signal.pdf("signal__JESDown"))["xpJESDown"][0]
                signal_vars["dxp"].setVal(
                    max(abs(xp_up - xp_central), abs(xp_down - xp_central)))
                if signal_vars["dxp"].getVal() > 2 * mass * 0.1:
                    print "[create_datacards] WARNING : Large dxp value. dxp = {}, xp_down = {}, xp_central = {}, xp_up = {}".format(
                        signal_vars["dxp"].getVal(), xp_down, xp_central,
                        xp_up)
                signal_vars["alpha_jes"].setVal(0.)
                signal_vars["alpha_jes"].setConstant(False)
            else:
                signal_vars["dxp"].setVal(0.)
                signal_vars["alpha_jes"].setVal(0.)
                signal_vars["alpha_jes"].setConstant()
            signal_vars["dxp"].setError(0.)
            signal_vars["dxp"].setConstant()

            if "jer" in systematics:
                sigp_central = signal_vars["sigp_0"].getVal()
                sigp_up = signal_fits.get_parameters(
                    w_signal.pdf("signal__JERUp"))["sigpJERUp"][0]
                sigp_down = signal_fits.get_parameters(
                    w_signal.pdf("signal__JERDown"))["sigpJERDown"][0]
                signal_vars["dsigp"].setVal(
                    max(abs(sigp_up - sigp_central),
                        abs(sigp_down - sigp_central)))
                signal_vars["alpha_jer"].setVal(0.)
                signal_vars["alpha_jer"].setConstant(False)
            else:
                signal_vars["dsigp"].setVal(0.)
                signal_vars["alpha_jer"].setVal(0.)
                signal_vars["alpha_jer"].setConstant()
            signal_vars["dsigp"].setError(0.)
            signal_vars["dsigp"].setConstant()
            #for variation in ["JERUp", "JERDown"]:
            #    signal_pdfs_syst[variation] = w_signal.pdf("signal__" + variation)
            #for variation, pdf in signal_pdfs_syst.iteritems():
            #    signal_parameters = pdf.getVariables()
            #    iter = signal_parameters.createIterator()
            #    var = iter.Next()
            #    while var:
            #        var.setConstant()
            #        var = iter.Next()
            f_signal_pdfs.Close()
        else:
            # dictionaries holding systematic variations of the signal shape
            hSig_Syst = {}
            hSig_Syst_DataHist = {}
            sigCDF = TGraph(hSig.GetNbinsX() + 1)

            if "jes" in systematics or "jer" in systematics:

                sigCDF.SetPoint(0, 0., 0.)
                integral = 0.
                for i in range(1, hSig.GetNbinsX() + 1):
                    x = hSig.GetXaxis().GetBinLowEdge(i + 1)
                    integral = integral + hSig.GetBinContent(i)
                    sigCDF.SetPoint(i, x, integral)

            if "jes" in systematics:
                hSig_Syst['JESUp'] = copy.deepcopy(hSig)
                hSig_Syst['JESDown'] = copy.deepcopy(hSig)

            if "jer" in systematics:
                hSig_Syst['JERUp'] = copy.deepcopy(hSig)
                hSig_Syst['JERDown'] = copy.deepcopy(hSig)

            # reset signal histograms
            for key in hSig_Syst.keys():
                hSig_Syst[key].Reset()
                hSig_Syst[key].SetName(hSig_Syst[key].GetName() + '_' + key)

            # produce JES signal shapes
            if "jes" in systematics:
                for i in range(1, hSig.GetNbinsX() + 1):
                    xLow = hSig.GetXaxis().GetBinLowEdge(i)
                    xUp = hSig.GetXaxis().GetBinLowEdge(i + 1)
                    jes = 1. - systematics["jes"]
                    xLowPrime = jes * xLow
                    xUpPrime = jes * xUp
                    hSig_Syst['JESUp'].SetBinContent(
                        i,
                        sigCDF.Eval(xUpPrime) - sigCDF.Eval(xLowPrime))
                    jes = 1. + systematics["jes"]
                    xLowPrime = jes * xLow
                    xUpPrime = jes * xUp
                    hSig_Syst['JESDown'].SetBinContent(
                        i,
                        sigCDF.Eval(xUpPrime) - sigCDF.Eval(xLowPrime))
                hSig_Syst_DataHist['JESUp'] = RooDataHist(
                    'hSig_JESUp', 'hSig_JESUp', RooArgList(mjj),
                    hSig_Syst['JESUp'])
                hSig_Syst_DataHist['JESDown'] = RooDataHist(
                    'hSig_JESDown', 'hSig_JESDown', RooArgList(mjj),
                    hSig_Syst['JESDown'])

            # produce JER signal shapes
            if "jer" in systematics:
                for i in range(1, hSig.GetNbinsX() + 1):
                    xLow = hSig.GetXaxis().GetBinLowEdge(i)
                    xUp = hSig.GetXaxis().GetBinLowEdge(i + 1)
                    jer = 1. - systematics["jer"]
                    xLowPrime = jer * (xLow - float(mass)) + float(mass)
                    xUpPrime = jer * (xUp - float(mass)) + float(mass)
                    hSig_Syst['JERUp'].SetBinContent(
                        i,
                        sigCDF.Eval(xUpPrime) - sigCDF.Eval(xLowPrime))
                    jer = 1. + systematics["jer"]
                    xLowPrime = jer * (xLow - float(mass)) + float(mass)
                    xUpPrime = jer * (xUp - float(mass)) + float(mass)
                    hSig_Syst['JERDown'].SetBinContent(
                        i,
                        sigCDF.Eval(xUpPrime) - sigCDF.Eval(xLowPrime))
                hSig_Syst_DataHist['JERUp'] = RooDataHist(
                    'hSig_JERUp', 'hSig_JERUp', RooArgList(mjj),
                    hSig_Syst['JERUp'])
                hSig_Syst_DataHist['JERDown'] = RooDataHist(
                    'hSig_JERDown', 'hSig_JERDown', RooArgList(mjj),
                    hSig_Syst['JERDown'])

        # -----------------------------------------
        # create a datacard and corresponding workspace
        postfix = (('_' + args.postfix) if args.postfix != '' else '')
        wsName = 'workspace_' + args.final_state + '_m' + str(
            mass) + postfix + '.root'

        w = RooWorkspace('w', 'workspace')
        if args.fitSignal:
            signal_pdf.SetName("signal")
            getattr(w, 'import')(signal_pdf, RooFit.Rename("signal"))
            # Create a norm variable "signal_norm" which normalizes the PDF to unity.
            norm = args.lumi
            #signal_norm = ROOT.RooRealVar("signal_norm", "signal_norm", 1. / norm, 0.1 / norm, 10. / norm)
            #if args.analysis == "trigbbh_CSVTM" and mass >= 1100:
            signal_norm = ROOT.RooRealVar("signal_norm", "signal_norm",
                                          norm / 100., norm / 100. / 10.,
                                          norm * 10.)
            #else:
            #    signal_norm = ROOT.RooRealVar("signal_norm", "signal_norm", norm, norm / 10., norm * 10.)
            print "[create_datacards] INFO : Set signal norm to {}".format(
                signal_norm.getVal())
            signal_norm.setConstant()
            getattr(w, 'import')(signal_norm, ROOT.RooCmdArg())
            #if "jes" in systematics:
            #    getattr(w,'import')(signal_pdfs_syst['JESUp'],RooFit.Rename("signal__JESUp"))
            #    getattr(w,'import')(signal_pdfs_syst['JESDown'],RooFit.Rename("signal__JESDown"))
            #if "jer" in systematics:
            #    getattr(w,'import')(signal_pdfs_syst['JERUp'],RooFit.Rename("signal__JERUp"))
            #    getattr(w,'import')(signal_pdfs_syst['JERDown'],RooFit.Rename("signal__JERDown"))
        else:
            getattr(w, 'import')(rooSigHist, RooFit.Rename("signal"))
            if "jes" in systematics:
                getattr(w, 'import')(hSig_Syst_DataHist['JESUp'],
                                     RooFit.Rename("signal__JESUp"))
                getattr(w, 'import')(hSig_Syst_DataHist['JESDown'],
                                     RooFit.Rename("signal__JESDown"))
            if "jer" in systematics:
                getattr(w, 'import')(hSig_Syst_DataHist['JERUp'],
                                     RooFit.Rename("signal__JERUp"))
                getattr(w, 'import')(hSig_Syst_DataHist['JERDown'],
                                     RooFit.Rename("signal__JERDown"))
        if args.decoBkg:
            getattr(w, 'import')(background_deco, ROOT.RooCmdArg())
        else:
            for fit_function in fit_functions:
                print "Importing background PDF"
                print background_pdfs[fit_function]
                background_pdfs[fit_function].Print()
                getattr(w,
                        'import')(background_pdfs[fit_function],
                                  ROOT.RooCmdArg(),
                                  RooFit.Rename("background_" + fit_function),
                                  RooFit.RecycleConflictNodes())
                w.pdf("background_" + fit_function).Print()
                getattr(w, 'import')(background_norms[fit_function],
                                     ROOT.RooCmdArg(),
                                     RooFit.Rename("background_" +
                                                   fit_function + "_norm"))
                getattr(w, 'import')(fit_results[fit_function])
                getattr(w, 'import')(signal_norms[fit_function],
                                     ROOT.RooCmdArg())
                if args.fitBonly:
                    getattr(w, 'import')(models[fit_function],
                                         ROOT.RooCmdArg(),
                                         RooFit.RecycleConflictNodes())
        getattr(w, 'import')(rooDataHist, RooFit.Rename("data_obs"))

        w.Print()
        print "Starting save"
        if args.output_path:
            if not os.path.isdir(os.path.join(os.getcwd(), args.output_path)):
                os.mkdir(os.path.join(os.getcwd(), args.output_path))
            print "[create_datacards] INFO : Writing workspace to file {}".format(
                os.path.join(args.output_path, wsName))
            w.writeToFile(os.path.join(args.output_path, wsName))
        else:
            print "[create_datacards] INFO : Writing workspace to file {}".format(
                limit_config.get_workspace_filename(
                    args.analysis,
                    args.model,
                    mass,
                    fitBonly=args.fitBonly,
                    fitSignal=args.fitSignal,
                    correctTrigger=args.correctTrigger))
            w.writeToFile(
                limit_config.get_workspace_filename(
                    args.analysis,
                    args.model,
                    mass,
                    fitBonly=args.fitBonly,
                    fitSignal=args.fitSignal,
                    correctTrigger=args.correctTrigger))

        # Clean up
        for name, obj in signal_norms.iteritems():
            if obj:
                obj.IsA().Destructor(obj)
        for name, obj in background_pdfs.iteritems():
            if obj:
                obj.IsA().Destructor(obj)
        for name, obj in background_pdfs_notrig.iteritems():
            if obj:
                obj.IsA().Destructor(obj)
        for name, obj in background_norms.iteritems():
            if obj:
                obj.IsA().Destructor(obj)
        for name, obj in signal_pdfs.iteritems():
            if obj:
                obj.IsA().Destructor(obj)
        for name, obj in signal_pdfs_notrig.iteritems():
            if obj:
                obj.IsA().Destructor(obj)
        for name, obj in signal_epdfs.iteritems():
            if obj:
                obj.IsA().Destructor(obj)
        for name, obj in background_epdfs.iteritems():
            if obj:
                obj.IsA().Destructor(obj)
        for name, obj in fit_results.iteritems():
            if obj:
                obj.IsA().Destructor(obj)
        for name, dict_l2 in background_parameters.iteritems():
            for name2, obj in dict_l2.iteritems():
                if obj:
                    obj.IsA().Destructor(obj)
        for name, obj in models.iteritems():
            if obj:
                obj.IsA().Destructor(obj)
        rooDataHist.IsA().Destructor(rooDataHist)
        w.IsA().Destructor(w)

        # Make datacards only if S+B fitted
        if not args.fitBonly:
            beffUnc = 0.3
            boffUnc = 0.06
            for fit_function in fit_functions:
                if args.output_path:
                    dcName = 'datacard_' + args.final_state + '_m' + str(
                        mass) + postfix + '_' + fit_function + '.txt'
                    print "[create_datacards] INFO : Writing datacard to file {}".format(
                        os.path.join(args.output_path, dcName))
                    datacard = open(os.path.join(args.output_path, dcName),
                                    'w')
                else:
                    print "[create_datacards] INFO : Writing datacard to file {}".format(
                        limit_config.get_datacard_filename(
                            args.analysis,
                            args.model,
                            mass,
                            fit_function,
                            fitSignal=args.fitSignal,
                            correctTrigger=args.correctTrigger))
                    datacard = open(
                        limit_config.get_datacard_filename(
                            args.analysis,
                            args.model,
                            mass,
                            fit_function,
                            fitSignal=args.fitSignal,
                            correctTrigger=args.correctTrigger), 'w')
                datacard.write('imax 1\n')
                datacard.write('jmax 1\n')
                datacard.write('kmax *\n')
                datacard.write('---------------\n')
                if ("jes" in systematics
                        or "jer" in systematics) and not args.fitSignal:
                    if args.output_path:
                        datacard.write('shapes * * ' + wsName +
                                       ' w:$PROCESS w:$PROCESS__$SYSTEMATIC\n')
                    else:
                        datacard.write('shapes * * ' + os.path.basename(
                            limit_config.get_workspace_filename(
                                args.analysis,
                                args.model,
                                mass,
                                fitSignal=args.fitSignal,
                                correctTrigger=args.correctTrigger)) +
                                       ' w:$PROCESS w:$PROCESS__$SYSTEMATIC\n')
                else:
                    if args.output_path:
                        datacard.write('shapes * * ' + wsName +
                                       ' w:$PROCESS\n')
                    else:
                        datacard.write('shapes * * ' + os.path.basename(
                            limit_config.get_workspace_filename(
                                args.analysis,
                                args.model,
                                mass,
                                fitSignal=args.fitSignal,
                                correctTrigger=args.correctTrigger)) +
                                       ' w:$PROCESS\n')
                datacard.write('---------------\n')
                datacard.write('bin 1\n')
                datacard.write('observation -1\n')
                datacard.write('------------------------------\n')
                datacard.write('bin          1          1\n')
                datacard.write('process      signal     background_' +
                               fit_function + '\n')
                datacard.write('process      0          1\n')
                if args.fitSignal:
                    datacard.write('rate         1         1\n')
                else:
                    datacard.write('rate         -1         1\n')
                datacard.write('------------------------------\n')
                datacard.write('lumi  lnN    %f         -\n' %
                               (1. + systematics["luminosity"]))
                datacard.write('beff  lnN    %f         -\n' % (1. + beffUnc))
                datacard.write('boff  lnN    %f         -\n' % (1. + boffUnc))
                #datacard.write('bkg   lnN     -         1.03\n')
                if args.fitSignal:
                    if "jes" in systematics:
                        datacard.write("alpha_jes  param  0.0  1.0\n")
                    if "jer" in systematics:
                        datacard.write("alpha_jer  param  0.0  1.0\n")
                else:
                    if "jes" in systematics:
                        datacard.write('JES  shape   1          -\n')
                    if "jer" in systematics:
                        datacard.write('JER  shape   1          -\n')
                # flat parameters --- flat prior
                datacard.write('background_' + fit_function +
                               '_norm  flatParam\n')
                if args.decoBkg:
                    datacard.write('deco_eig1  flatParam\n')
                    datacard.write('deco_eig2  flatParam\n')
                else:
                    for par_name, par in background_parameters[
                            fit_function].iteritems():
                        datacard.write(fit_function + "_" + par_name +
                                       '  flatParam\n')
                datacard.close()
                print "[create_datacards] INFO : Done with this datacard"

    #print '>> Datacards and workspaces created and stored in %s/'%( os.path.join(os.getcwd(),args.output_path) )
    print "All done."
# Make datacards for 375 GeV
masses["trigbbl_CSVTM"] = [375]
analyses = ["trigbbl_CSVTM"]

for model in ["Hbb", "ZPrime", "RSG"]:
    #for model in ["ZPrime"]:
    for analysis in analyses:
        for mass in masses[analysis]:
            if do_qcd:
                data_sample = "QCD_TuneZ2star_8TeV_pythia6"
            if "trigbb" in analysis:
                data_sample = "BJetPlusX_2012"
            elif "trigmu" in analysis:
                data_sample = "SingleMu_2012"
            data_file_path = analysis_config.get_b_histogram_filename(
                analysis, data_sample)

            if useMCTrigger:
                signal_pdf_file = analysis_config.get_signal_fit_file(
                    analysis,
                    model,
                    mass,
                    "bukin",
                    interpolated=(
                        not mass
                        in analysis_config.simulation.simulated_masses))
            else:
                if analysis == "trigbbl_CSVTM":
                    notrig_analysis = "NoTrigger_eta1p7_CSVTM"
                elif analysis == "trigbbh_CSVTM":
                    notrig_analysis = "NoTrigger_eta2p2_CSVTM"
def main():
    # usage description
    usage = "Example: ./scripts/createDatacards.py --inputData inputs/rawhistV7_Run2015D_scoutingPFHT_UNBLINDED_649_838_JEC_HLTplusV7_Mjj_cor_smooth.root --dataHistname mjj_mjjcor_gev --inputSig inputs/ResonanceShapes_gg_13TeV_Scouting_Spring15.root -f gg -o datacards -l 1866 --lumiUnc 0.027 --massrange 1000 1500 50 --runFit --p1 5 --p2 7 --p3 0.4 --massMin 838 --massMax 2037 --fitStrategy 2"

    # input parameters
    parser = ArgumentParser(description='Script that creates combine datacards and corresponding RooFit workspaces',epilog=usage)
    parser.add_argument("analysis", type=str, help="Analysis name")
    parser.add_argument("model", type=str, help="Model (Hbb, RSG)")

    #parser.add_argument("--inputData", dest="inputData", required=True,
    #                    help="Input data spectrum",
    #                    metavar="INPUT_DATA")

    parser.add_argument("--dataHistname", dest="dataHistname", type=str, default="h_data",
                        help="Data histogram name",
                        metavar="DATA_HISTNAME")

    #parser.add_argument("--inputSig", dest="inputSig", required=True,
    #                    help="Input signal shapes",
    #                    metavar="INPUT_SIGNAL")

    parser.add_argument("-f", "--final_state", dest="final_state", default="qq",
                        help="Final state (e.g. qq, qg, gg)",
                        metavar="FINAL_STATE")
    parser.add_argument("--fit_functions", dest="fit_functions", default="f1,f2,f3,f4,f5", help="List of fit functions")

    #parser.add_argument("-f2", "--type", dest="atype", required=True, help="Type (e.g. hG, lG, hR, lR)")

    parser.add_argument("-o", "--output_path", dest="output_path",
                        help="Output path where datacards and workspaces will be stored. If not specified, this is derived from limit_configuration.",
                        metavar="OUTPUT_PATH")

    parser.add_argument("--correctTrigger", dest="correctTrigger",
                        action='store_true',
                        help="Include trigger correction in PDF")

    parser.add_argument("-l", "--lumi", dest="lumi",
                        default=19700., type=float,
                        help="Integrated luminosity in pb-1 (default: %(default).1f)",
                        metavar="LUMI")

    parser.add_argument("--massMin", dest="massMin",
                        default=500, type=int,
                        help="Lower bound of the mass range used for fitting (default: %(default)s)",
                        metavar="MASS_MIN")

    parser.add_argument("--massMax", dest="massMax",
                        default=1200, type=int,
                        help="Upper bound of the mass range used for fitting (default: %(default)s)",
                        metavar="MASS_MAX")
    parser.add_argument("--fitSignal", action="store_true", help="Use signal fitted shapes (CB+Voigtian) instead of histogram templates")
    #parser.add_argument("--lumiUnc", dest="lumiUnc",
    #                    required=True, type=float,
    #                    help="Relative uncertainty in the integrated luminosity",
    #                    metavar="LUMI_UNC")

    #parser.add_argument("--jesUnc", dest="jesUnc",
    #                    type=float,
    #                    help="Relative uncertainty in the jet energy scale",
    #                    metavar="JES_UNC")

    #parser.add_argument("--jerUnc", dest="jerUnc",
    #                    type=float,
    #                    help="Relative uncertainty in the jet energy resolution",
    #                    metavar="JER_UNC")

    parser.add_argument("--sqrtS", dest="sqrtS",
                        default=8000., type=float,
                        help="Collision center-of-mass energy (default: %(default).1f)",
                        metavar="SQRTS")

    parser.add_argument("--fixP3", dest="fixP3", default=False, action="store_true", help="Fix the fit function p3 parameter")

    parser.add_argument("--runFit", dest="runFit", default=False, action="store_true", help="Run the fit")

    parser.add_argument("--fitBonly", dest="fitBonly", default=False, action="store_true", help="Run B-only fit")

    parser.add_argument("--fixBkg", dest="fixBkg", default=False, action="store_true", help="Fix all background parameters")

    parser.add_argument("--decoBkg", dest="decoBkg", default=False, action="store_true", help="Decorrelate background parameters")

    parser.add_argument("--fitStrategy", dest="fitStrategy", type=int, default=1, help="Fit strategy (default: %(default).1f)")

    parser.add_argument("--debug", dest="debug", default=False, action="store_true", help="Debug printout")

    parser.add_argument("--postfix", dest="postfix", default='', help="Postfix for the output file names (default: %(default)s)")

    parser.add_argument("--pyes", dest="pyes", default=False, action="store_true", help="Make files for plots")

    parser.add_argument("--jyes", dest="jyes", default=False, action="store_true", help="Make files for JES/JER plots")

    parser.add_argument("--pdir", dest="pdir", default='testarea', help="Name a directory for the plots (default: %(default)s)")

    parser.add_argument("--chi2", dest="chi2", default=False, action="store_true", help="Compute chi squared")

    parser.add_argument("--widefit", dest="widefit", default=False, action="store_true", help="Fit with wide bin hist")

    mass_group = parser.add_mutually_exclusive_group(required=True)
    mass_group.add_argument("--mass",
                            type=int,
                            nargs = '*',
                            default = 1000,
                            help="Mass can be specified as a single value or a whitespace separated list (default: %(default)i)"
                            )
    mass_group.add_argument("--massrange",
                            type=int,
                            nargs = 3,
                            help="Define a range of masses to be produced. Format: min max step",
                            metavar = ('MIN', 'MAX', 'STEP')
                            )
    mass_group.add_argument("--masslist",
                            help = "List containing mass information"
                            )

    args = parser.parse_args()

    fit_functions = args.fit_functions.split(",")

    # mass points for which resonance shapes will be produced
    masses = []

    if args.fitBonly:
        masses.append(750)
    else:
        if args.massrange != None:
            MIN, MAX, STEP = args.massrange
            masses = range(MIN, MAX+STEP, STEP)
        elif args.masslist != None:
            # A mass list was provided
            print  "Will create mass list according to", args.masslist
            masslist = __import__(args.masslist.replace(".py",""))
            masses = masslist.masses
        else:
            masses = args.mass

    # sort masses
    masses.sort()

    # import ROOT stuff
    from ROOT import gStyle, TFile, TH1F, TH1D, TGraph, kTRUE, kFALSE, TCanvas, TLegend, TPad, TLine
    from ROOT import RooHist, RooRealVar, RooDataHist, RooArgList, RooArgSet, RooAddPdf, RooProdPdf, RooEffProd, RooFit, RooGenericPdf, RooWorkspace, RooMsgService, RooHistPdf, RooExtendPdf

    if not args.debug:
        RooMsgService.instance().setSilentMode(kTRUE)
        RooMsgService.instance().setStreamStatus(0,kFALSE)
        RooMsgService.instance().setStreamStatus(1,kFALSE)

    # input data file
    #inputData = TFile(limit_config.get_data_input(args.analysis))
    # input data histogram
    #hData = inputData.Get(args.dataHistname)
    #hData.SetDirectory(0)
    data_file = TFile(analysis_config.get_b_histogram_filename(args.analysis, "BJetPlusX_2012"))
    hData = data_file.Get("BHistograms/h_pfjet_mjj")
    hData.SetDirectory(0)

    # input sig file
    if not args.fitSignal:
        print "[create_datacards] INFO : Opening resonance shapes file at " + limit_config.get_resonance_shapes(args.analysis, args.model)
        inputSig = TFile(limit_config.get_resonance_shapes(args.analysis, args.model), "READ")

    sqrtS = args.sqrtS

    # mass variable
    mjj = RooRealVar('mjj','mjj',float(args.massMin),float(args.massMax))

    # integrated luminosity and signal cross section
    lumi = args.lumi
    signalCrossSection = 1. # set to 1. so that the limit on r can be interpreted as a limit on the signal cross section

    if args.correctTrigger:
        trigger_efficiency_pdf = trigger_efficiency.get_pdf(args.analysis, mjj)
        trigger_efficiency_formula = trigger_efficiency.get_formula(args.analysis, mjj)
    else:
        trigger_efficiency_pdf = trigger_efficiency.get_trivial_pdf(mjj)
        trigger_efficiency_formula = trigger_efficiency.get_trivial_formula(mjj)

    for mass in masses:

        print ">> Creating datacard and workspace for %s resonance with m = %i GeV..."%(args.final_state, int(mass))
        
        rooDataHist = RooDataHist('rooDatahist','rooDathist',RooArgList(mjj),hData)

        if not args.fitSignal:
            hSig = inputSig.Get( "h_" + args.final_state + "_" + str(int(mass)) )
            if not hSig:
                raise Exception("Couldn't find histogram " + "h_" + args.final_state + "_" + str(int(mass)) + " in file " + limit_config.get_resonance_shapes(args.analysis, args.model))
            # normalize signal shape to the expected event yield (works even if input shapes are not normalized to unity)
            hSig.Scale(signalCrossSection*lumi/hSig.Integral()) # divide by a number that provides roughly an r value of 1-10
            rooSigHist = RooDataHist('rooSigHist','rooSigHist',RooArgList(mjj),hSig)
            print 'Signal acceptance:', (rooSigHist.sumEntries()/hSig.Integral())

        # If using fitted signal shapes, load the signal PDF
        if args.fitSignal:
            print "[create_datacards] Loading fitted signal PDFs from " + analysis_config.get_signal_fit_file(args.analysis, args.model, mass, "bukin", interpolated=(not mass in analysis_config.simulation.simulated_masses))
            f_signal_pdfs = TFile(analysis_config.get_signal_fit_file(args.analysis, args.model, mass, "bukin", interpolated=(not mass in analysis_config.simulation.simulated_masses)), "READ")
            w_signal = f_signal_pdfs.Get("w_signal")
            input_parameters = signal_fits.get_parameters(w_signal.pdf("signal"))

            # Make a new PDF with nuisance parameters
            signal_pdf_notrig, signal_vars = signal_fits.make_signal_pdf_systematic("bukin", mjj, mass=mass)
            signal_pdf_name = signal_pdf_notrig.GetName()
            signal_pdf_notrig.SetName(signal_pdf_name + "_notrig")
            #signal_pdf = RooProdPdf(signal_pdf_name, signal_pdf_name, signal_pdf_notrig, trigger_efficiency_pdf) 
            signal_pdf = RooEffProd(signal_pdf_name, signal_pdf_name, signal_pdf_notrig, trigger_efficiency_formula)

            # Copy input parameter values
            signal_vars["xp_0"].setVal(input_parameters["xp"][0])
            signal_vars["xp_0"].setError(input_parameters["xp"][1])
            signal_vars["xp_0"].setConstant()
            signal_vars["sigp_0"].setVal(input_parameters["sigp"][0])
            signal_vars["sigp_0"].setError(input_parameters["sigp"][1])
            signal_vars["sigp_0"].setConstant()
            signal_vars["xi_0"].setVal(input_parameters["xi"][0])
            signal_vars["xi_0"].setError(input_parameters["xi"][1])
            signal_vars["xi_0"].setConstant()
            signal_vars["rho1_0"].setVal(input_parameters["rho1"][0])
            signal_vars["rho1_0"].setError(input_parameters["rho1"][1])
            signal_vars["rho1_0"].setConstant()
            signal_vars["rho2_0"].setVal(input_parameters["rho2"][0])
            signal_vars["rho2_0"].setError(input_parameters["rho2"][1])
            signal_vars["rho2_0"].setConstant()
            f_signal_pdfs.Close()

        signal_parameters = {}
        signal_pdfs_notrig = {}
        signal_pdfs = {}
        signal_norms = {}
        background_pdfs = {}
        background_pdfs_notrig = {}
        background_parameters = {}
        background_norms = {}
        signal_epdfs = {}
        background_epdfs = {}
        models = {}
        fit_results = {}

        for fit_function in fit_functions:
            print "[create_datacards] INFO : On fit function {}".format(fit_function)

            if args.fitSignal:
                # Make a copy of the signal PDF, so that each fitTo call uses its own copy.
                # The copy should have all variables set constant.  
                #signal_pdfs[fit_function], signal_parameters[fit_function] = signal_fits.copy_signal_pdf("bukin", signal_pdf, mjj, tag=fit_function, include_systematics=True)
                signal_pdfs_notrig[fit_function] = ROOT.RooBukinPdf(signal_pdf_notrig, signal_pdf_notrig.GetName() + "_" + fit_function)
                signal_pdfs[fit_function] = RooEffProd(signal_pdf.GetName() + "_" + fit_function, signal_pdf.GetName() + "_" + fit_function, signal_pdfs_notrig[fit_function], trigger_efficiency_formula) 
                #signal_pdfs[fit_function] = RooProdPdf(signal_pdf.GetName() + "_" + fit_function, signal_pdf.GetName() + "_" + fit_function, signal_pdfs_notrig[fit_function], trigger_efficiency_pdf) 
                iterator = signal_pdfs_notrig[fit_function].getVariables().createIterator()
                this_parameter = iterator.Next()
                while this_parameter:
                    this_parameter.setConstant()
                    this_parameter = iterator.Next()
            else:
                signal_pdfs[fit_function] = RooHistPdf('signal_' + fit_function,'signal_' + fit_function, RooArgSet(mjj), rooSigHist)
            signal_norms[fit_function] = RooRealVar('signal_norm_' + fit_function, 'signal_norm_' + fit_function, 0., 0., 1e+05)
            if args.fitBonly: 
                signal_norms[fit_function].setConstant()
            background_pdfs_notrig[fit_function], background_parameters[fit_function] = make_background_pdf(fit_function, mjj, collision_energy=8000.)
            background_pdf_name = background_pdfs_notrig[fit_function].GetName()
            background_pdfs_notrig[fit_function].SetName(background_pdf_name + "_notrig")
            background_pdfs[fit_function] = RooEffProd(background_pdf_name, background_pdf_name, background_pdfs_notrig[fit_function], trigger_efficiency_formula)
            #background_pdfs[fit_function] = RooProdPdf(background_pdf_name, background_pdf_name, background_pdfs_notrig[fit_function], trigger_efficiency_pdf)
            #background_pdfs[fit_function] = background_pdfs_notrig[fit_function]
            #background_pdfs[fit_function].SetName(background_pdf_name)
            
            # Initial values
            if "trigbbh" in args.analysis:
                if fit_function == "f3":
                    background_parameters[fit_function]["p1"].setVal(55.)
                    background_parameters[fit_function]["p1"].setMin(20.)
                    background_parameters[fit_function]["p2"].setVal(8.)
                elif fit_function == "f4":
                    background_parameters[fit_function]["p1"].setVal(28.)
                    background_parameters[fit_function]["p2"].setVal(-22.)
                    background_parameters[fit_function]["p3"].setVal(10.)
            elif "trigbbl" in args.analysis:
                if fit_function == "f3":
                    background_parameters[fit_function]["p1"].setVal(82.)
                    background_parameters[fit_function]["p1"].setMin(60.)
                    background_parameters[fit_function]["p2"].setVal(8.)
                elif fit_function == "f4":
                    background_parameters[fit_function]["p1"].setVal(41.)
                    background_parameters[fit_function]["p2"].setVal(-45.)
                    background_parameters[fit_function]["p3"].setVal(10.)

            data_integral = hData.Integral(hData.GetXaxis().FindBin(float(args.massMin)),hData.GetXaxis().FindBin(float(args.massMax)))
            background_norms[fit_function] = RooRealVar('background_' + fit_function + '_norm', 'background_' + fit_function + '_norm', data_integral, 0., 1.e8)

            signal_epdfs[fit_function] = RooExtendPdf('esignal_' + fit_function, 'esignal_' + fit_function, signal_pdfs[fit_function], signal_norms[fit_function])
            background_epdfs[fit_function] = RooExtendPdf('ebackground_' + fit_function, 'ebackground_' + fit_function, background_pdfs[fit_function], background_norms[fit_function])

            models[fit_function] = RooAddPdf('model_' + fit_function, 's+b', RooArgList(background_epdfs[fit_function], signal_epdfs[fit_function]))

            if args.runFit:
                print "[create_datacards] INFO : Starting fit with function {}".format(fit_function)
                fit_results[fit_function] = models[fit_function].fitTo(rooDataHist, RooFit.Save(kTRUE), RooFit.Extended(kTRUE), RooFit.Strategy(args.fitStrategy), RooFit.Verbose(0))
                print "[create_datacards] INFO : Done with fit {}. Printing results.".format(fit_function)
                fit_results[fit_function].Print()
                print "[create_datacards] DEBUG : End args.runFit if block."

            # needed if want to evaluate limits without background systematics
            if args.fixBkg:
                background_norms[fit_function].setConstant()
                for par_name, par in background_parameters[fit_function].iteritems():
                    par.setConstant()

        # -----------------------------------------
        #signal_pdfs_syst = {}
        # JES and JER uncertainties
        if args.fitSignal:
            print "[create_datacards] INFO : Getting signal PDFs from " + analysis_config.get_signal_fit_file(args.analysis, args.model, mass, "bukin", interpolated=(not mass in analysis_config.simulation.simulated_masses))
            f_signal_pdfs = TFile(analysis_config.get_signal_fit_file(args.analysis, args.model, mass, "bukin", interpolated=(not mass in analysis_config.simulation.simulated_masses)))
            w_signal = f_signal_pdfs.Get("w_signal")
            if "jes" in systematics:
                xp_central = signal_vars["xp_0"].getVal()
                #print w_signal.pdf("signal__JESUp")
                #print signal_fits.get_parameters(w_signal.pdf("signal__JESUp"))
                xp_up = signal_fits.get_parameters(w_signal.pdf("signal__JESUp"))["xpJESUp"][0]
                xp_down = signal_fits.get_parameters(w_signal.pdf("signal__JESDown"))["xpJESDown"][0]
                signal_vars["dxp"].setVal(max(abs(xp_up - xp_central), abs(xp_down - xp_central)))
                if signal_vars["dxp"].getVal() > 2 * mass * 0.1:
                    print "[create_datacards] WARNING : Large dxp value. dxp = {}, xp_down = {}, xp_central = {}, xp_up = {}".format(signal_vars["dxp"].getVal(), xp_down, xp_central, xp_up)
                signal_vars["alpha_jes"].setVal(0.)
                signal_vars["alpha_jes"].setConstant(False)
            else:
                signal_vars["dxp"].setVal(0.)
                signal_vars["alpha_jes"].setVal(0.)
                signal_vars["alpha_jes"].setConstant()
            signal_vars["dxp"].setError(0.)
            signal_vars["dxp"].setConstant()

            if "jer" in systematics:
                sigp_central = signal_vars["sigp_0"].getVal()
                sigp_up = signal_fits.get_parameters(w_signal.pdf("signal__JERUp"))["sigpJERUp"][0]
                sigp_down = signal_fits.get_parameters(w_signal.pdf("signal__JERDown"))["sigpJERDown"][0]
                signal_vars["dsigp"].setVal(max(abs(sigp_up - sigp_central), abs(sigp_down - sigp_central)))
                signal_vars["alpha_jer"].setVal(0.)
                signal_vars["alpha_jer"].setConstant(False)
            else:
                signal_vars["dsigp"].setVal(0.)
                signal_vars["alpha_jer"].setVal(0.)
                signal_vars["alpha_jer"].setConstant()
            signal_vars["dsigp"].setError(0.)
            signal_vars["dsigp"].setConstant()
                #for variation in ["JERUp", "JERDown"]:
                #    signal_pdfs_syst[variation] = w_signal.pdf("signal__" + variation)
            #for variation, pdf in signal_pdfs_syst.iteritems():
            #    signal_parameters = pdf.getVariables()
            #    iter = signal_parameters.createIterator()
            #    var = iter.Next()
            #    while var:
            #        var.setConstant()
            #        var = iter.Next()
            f_signal_pdfs.Close()
        else:
            # dictionaries holding systematic variations of the signal shape
            hSig_Syst = {}
            hSig_Syst_DataHist = {}
            sigCDF = TGraph(hSig.GetNbinsX()+1)

            if "jes" in systematics or "jer" in systematics:

                sigCDF.SetPoint(0,0.,0.)
                integral = 0.
                for i in range(1, hSig.GetNbinsX()+1):
                    x = hSig.GetXaxis().GetBinLowEdge(i+1)
                    integral = integral + hSig.GetBinContent(i)
                    sigCDF.SetPoint(i,x,integral)

            if "jes" in systematics:
                hSig_Syst['JESUp'] = copy.deepcopy(hSig)
                hSig_Syst['JESDown'] = copy.deepcopy(hSig)

            if "jer" in systematics:
                hSig_Syst['JERUp'] = copy.deepcopy(hSig)
                hSig_Syst['JERDown'] = copy.deepcopy(hSig)

            # reset signal histograms
            for key in hSig_Syst.keys():
                hSig_Syst[key].Reset()
                hSig_Syst[key].SetName(hSig_Syst[key].GetName() + '_' + key)

            # produce JES signal shapes
            if "jes" in systematics:
                for i in range(1, hSig.GetNbinsX()+1):
                    xLow = hSig.GetXaxis().GetBinLowEdge(i)
                    xUp = hSig.GetXaxis().GetBinLowEdge(i+1)
                    jes = 1. - systematics["jes"]
                    xLowPrime = jes*xLow
                    xUpPrime = jes*xUp
                    hSig_Syst['JESUp'].SetBinContent(i, sigCDF.Eval(xUpPrime) - sigCDF.Eval(xLowPrime))
                    jes = 1. + systematics["jes"]
                    xLowPrime = jes*xLow
                    xUpPrime = jes*xUp
                    hSig_Syst['JESDown'].SetBinContent(i, sigCDF.Eval(xUpPrime) - sigCDF.Eval(xLowPrime))
                hSig_Syst_DataHist['JESUp'] = RooDataHist('hSig_JESUp','hSig_JESUp',RooArgList(mjj),hSig_Syst['JESUp'])
                hSig_Syst_DataHist['JESDown'] = RooDataHist('hSig_JESDown','hSig_JESDown',RooArgList(mjj),hSig_Syst['JESDown'])
            
            # produce JER signal shapes
            if "jer" in systematics:
                for i in range(1, hSig.GetNbinsX()+1):
                    xLow = hSig.GetXaxis().GetBinLowEdge(i)
                    xUp = hSig.GetXaxis().GetBinLowEdge(i+1)
                    jer = 1. - systematics["jer"]
                    xLowPrime = jer*(xLow-float(mass))+float(mass)
                    xUpPrime = jer*(xUp-float(mass))+float(mass)
                    hSig_Syst['JERUp'].SetBinContent(i, sigCDF.Eval(xUpPrime) - sigCDF.Eval(xLowPrime))
                    jer = 1. + systematics["jer"]
                    xLowPrime = jer*(xLow-float(mass))+float(mass)
                    xUpPrime = jer*(xUp-float(mass))+float(mass)
                    hSig_Syst['JERDown'].SetBinContent(i, sigCDF.Eval(xUpPrime) - sigCDF.Eval(xLowPrime))
                hSig_Syst_DataHist['JERUp'] = RooDataHist('hSig_JERUp','hSig_JERUp',RooArgList(mjj),hSig_Syst['JERUp'])
                hSig_Syst_DataHist['JERDown'] = RooDataHist('hSig_JERDown','hSig_JERDown',RooArgList(mjj),hSig_Syst['JERDown'])


        # -----------------------------------------
        # create a datacard and corresponding workspace
        postfix = (('_' + args.postfix) if args.postfix != '' else '')
        wsName = 'workspace_' + args.final_state + '_m' + str(mass) + postfix + '.root'

        w = RooWorkspace('w','workspace')
        if args.fitSignal:
            signal_pdf.SetName("signal")
            getattr(w,'import')(signal_pdf,RooFit.Rename("signal"))
            # Create a norm variable "signal_norm" which normalizes the PDF to unity.
            norm = args.lumi
            #signal_norm = ROOT.RooRealVar("signal_norm", "signal_norm", 1. / norm, 0.1 / norm, 10. / norm)
            #if args.analysis == "trigbbh_CSVTM" and mass >= 1100:
            signal_norm = ROOT.RooRealVar("signal_norm", "signal_norm", norm/100., norm/100. / 10., norm * 10.)
            #else:
            #    signal_norm = ROOT.RooRealVar("signal_norm", "signal_norm", norm, norm / 10., norm * 10.)
            print "[create_datacards] INFO : Set signal norm to {}".format(signal_norm.getVal())
            signal_norm.setConstant()
            getattr(w,'import')(signal_norm,ROOT.RooCmdArg())
            #if "jes" in systematics:
            #    getattr(w,'import')(signal_pdfs_syst['JESUp'],RooFit.Rename("signal__JESUp"))
            #    getattr(w,'import')(signal_pdfs_syst['JESDown'],RooFit.Rename("signal__JESDown"))
            #if "jer" in systematics:
            #    getattr(w,'import')(signal_pdfs_syst['JERUp'],RooFit.Rename("signal__JERUp"))
            #    getattr(w,'import')(signal_pdfs_syst['JERDown'],RooFit.Rename("signal__JERDown"))
        else:
            getattr(w,'import')(rooSigHist,RooFit.Rename("signal"))
            if "jes" in systematics:
                getattr(w,'import')(hSig_Syst_DataHist['JESUp'],RooFit.Rename("signal__JESUp"))
                getattr(w,'import')(hSig_Syst_DataHist['JESDown'],RooFit.Rename("signal__JESDown"))
            if "jer" in systematics:
                getattr(w,'import')(hSig_Syst_DataHist['JERUp'],RooFit.Rename("signal__JERUp"))
                getattr(w,'import')(hSig_Syst_DataHist['JERDown'],RooFit.Rename("signal__JERDown"))
        if args.decoBkg:
            getattr(w,'import')(background_deco,ROOT.RooCmdArg())
        else:
            for fit_function in fit_functions:
                print "Importing background PDF"
                print background_pdfs[fit_function]
                background_pdfs[fit_function].Print()
                getattr(w,'import')(background_pdfs[fit_function],ROOT.RooCmdArg(),RooFit.Rename("background_" + fit_function), RooFit.RecycleConflictNodes())
                w.pdf("background_" + fit_function).Print()
                getattr(w,'import')(background_norms[fit_function],ROOT.RooCmdArg(),RooFit.Rename("background_" + fit_function + "_norm"))
                getattr(w,'import')(fit_results[fit_function])
                getattr(w,'import')(signal_norms[fit_function],ROOT.RooCmdArg())
                if args.fitBonly:
                    getattr(w,'import')(models[fit_function],ROOT.RooCmdArg(),RooFit.RecycleConflictNodes())
        getattr(w,'import')(rooDataHist,RooFit.Rename("data_obs"))

        w.Print()
        print "Starting save"
        if args.output_path:
            if not os.path.isdir( os.path.join(os.getcwd(),args.output_path) ):
                os.mkdir( os.path.join(os.getcwd(),args.output_path) )
            print "[create_datacards] INFO : Writing workspace to file {}".format(os.path.join(args.output_path,wsName))
            w.writeToFile(os.path.join(args.output_path,wsName))
        else:
            print "[create_datacards] INFO : Writing workspace to file {}".format(limit_config.get_workspace_filename(args.analysis, args.model, mass, fitBonly=args.fitBonly, fitSignal=args.fitSignal, correctTrigger=args.correctTrigger))
            w.writeToFile(limit_config.get_workspace_filename(args.analysis, args.model, mass, fitBonly=args.fitBonly, fitSignal=args.fitSignal, correctTrigger=args.correctTrigger))

        # Clean up
        for name, obj in signal_norms.iteritems():
            if obj:
                obj.IsA().Destructor(obj)
        for name, obj in background_pdfs.iteritems():
            if obj:
                obj.IsA().Destructor(obj)
        for name, obj in background_pdfs_notrig.iteritems():
            if obj:
                obj.IsA().Destructor(obj)
        for name, obj in background_norms.iteritems():
            if obj:
                obj.IsA().Destructor(obj)
        for name, obj in signal_pdfs.iteritems():
            if obj:
                obj.IsA().Destructor(obj)
        for name, obj in signal_pdfs_notrig.iteritems():
            if obj:
                obj.IsA().Destructor(obj)
        for name, obj in signal_epdfs.iteritems():
            if obj:
                obj.IsA().Destructor(obj)
        for name, obj in background_epdfs.iteritems():
            if obj:
                obj.IsA().Destructor(obj)
        for name, obj in fit_results.iteritems():
            if obj:
                obj.IsA().Destructor(obj)
        for name, dict_l2 in background_parameters.iteritems():
            for name2, obj in dict_l2.iteritems():
                if obj:
                    obj.IsA().Destructor(obj)
        for name, obj in models.iteritems():
            if obj:
                obj.IsA().Destructor(obj)
        rooDataHist.IsA().Destructor(rooDataHist)
        w.IsA().Destructor(w)

        # Make datacards only if S+B fitted
        if not args.fitBonly:
            beffUnc = 0.3
            boffUnc = 0.06
            for fit_function in fit_functions:
                if args.output_path:
                    dcName = 'datacard_' + args.final_state + '_m' + str(mass) + postfix + '_' + fit_function + '.txt'
                    print "[create_datacards] INFO : Writing datacard to file {}".format(os.path.join(args.output_path,dcName)) 
                    datacard = open(os.path.join(args.output_path,dcName),'w')
                else:
                    print "[create_datacards] INFO : Writing datacard to file {}".format(limit_config.get_datacard_filename(args.analysis, args.model, mass, fit_function, fitSignal=args.fitSignal, correctTrigger=args.correctTrigger)) 
                    datacard = open(limit_config.get_datacard_filename(args.analysis, args.model, mass, fit_function, fitSignal=args.fitSignal, correctTrigger=args.correctTrigger), 'w')
                datacard.write('imax 1\n')
                datacard.write('jmax 1\n')
                datacard.write('kmax *\n')
                datacard.write('---------------\n')
                if ("jes" in systematics or "jer" in systematics) and not args.fitSignal:
                    if args.output_path:
                        datacard.write('shapes * * '+wsName+' w:$PROCESS w:$PROCESS__$SYSTEMATIC\n')
                    else:
                        datacard.write('shapes * * '+os.path.basename(limit_config.get_workspace_filename(args.analysis, args.model, mass, fitSignal=args.fitSignal, correctTrigger=args.correctTrigger))+' w:$PROCESS w:$PROCESS__$SYSTEMATIC\n')
                else:
                    if args.output_path:
                        datacard.write('shapes * * '+wsName+' w:$PROCESS\n')
                    else:
                        datacard.write('shapes * * '+os.path.basename(limit_config.get_workspace_filename(args.analysis, args.model, mass, fitSignal=args.fitSignal, correctTrigger=args.correctTrigger))+' w:$PROCESS\n')
                datacard.write('---------------\n')
                datacard.write('bin 1\n')
                datacard.write('observation -1\n')
                datacard.write('------------------------------\n')
                datacard.write('bin          1          1\n')
                datacard.write('process      signal     background_' + fit_function + '\n')
                datacard.write('process      0          1\n')
                if args.fitSignal:
                    datacard.write('rate         1         1\n')
                else:
                    datacard.write('rate         -1         1\n')
                datacard.write('------------------------------\n')
                datacard.write('lumi  lnN    %f         -\n'%(1.+systematics["luminosity"]))
                datacard.write('beff  lnN    %f         -\n'%(1.+beffUnc))
                datacard.write('boff  lnN    %f         -\n'%(1.+boffUnc))
                #datacard.write('bkg   lnN     -         1.03\n')
                if args.fitSignal:
                    if "jes" in systematics:
                        datacard.write("alpha_jes  param  0.0  1.0\n")
                    if "jer" in systematics:
                        datacard.write("alpha_jer  param  0.0  1.0\n")
                else:
                    if "jes" in systematics:
                        datacard.write('JES  shape   1          -\n')
                    if "jer" in systematics:
                        datacard.write('JER  shape   1          -\n')
                # flat parameters --- flat prior
                datacard.write('background_' + fit_function + '_norm  flatParam\n')
                if args.decoBkg:
                    datacard.write('deco_eig1  flatParam\n')
                    datacard.write('deco_eig2  flatParam\n')
                else:
                    for par_name, par in background_parameters[fit_function].iteritems():
                        datacard.write(fit_function + "_" + par_name + '  flatParam\n')
                datacard.close()
                print "[create_datacards] INFO : Done with this datacard"

    #print '>> Datacards and workspaces created and stored in %s/'%( os.path.join(os.getcwd(),args.output_path) )
    print "All done."
Beispiel #30
0
	parser.add_argument("--normalize", action="store_true", help="Normalize histograms")
	parser.add_argument("--rebin", type=int, help="Rebin histograms")
	args = parser.parse_args()

	variables = args.variables.split(",")
	analyses = args.analyses.split(",")
	models = args.models.split(",")
	masses = [int(x) for x in args.masses.split(",")]

	for variable in variables:
		histograms = {}
		histogram_names = []
		for analysis in analyses:
			for model in models:
				for mass in masses:
					histogram_name = GetLegendEntry(analysis, model, mass)
					f = TFile(analysis_config.get_b_histogram_filename(analysis, analysis_config.simulation.get_signal_tag(model, mass, "FULLSIM")), "READ")
					histogram_names.append(histogram_name)
					histograms[histogram_name] = f.Get(args.prefix + variable)
					if not histograms[histogram_name]:
						print "[signal_plots] ERROR : Histogram {} not found in file {}".format(args.prefix + variable, analysis_config.get_b_histogram_filename(analysis, analysis_config.simulation.get_signal_tag(model, mass, "FULLSIM")))
					histograms[histogram_name].SetDirectory(0)
					f.Close()
					if args.normalize:
						if histograms[histogram_name].Integral() > 0:
							histograms[histogram_name].Scale(1. / histograms[histogram_name].Integral())
					if args.rebin:
						histograms[histogram_name].Rebin(args.rebin)
		canvas_name = "c_signal_distribution_{}_{}_{}_{}".format(variable, "_".join(analyses), "_".join(models), "_".join(args.masses.split(",")))
		MakeSignalPlot(canvas_name, histogram_names, histograms, x_range=args.x_range, y_range=args.y_range, logx=args.logx, logy=args.logy)
	
Beispiel #31
0
         "HT650": "trigjetht650",
         "HTUnprescaled": "trigjetht"
     }
 for wp in ["CSVT", "CSVM", "CSVL"]:
     numerator_histograms[sr][wp] = {}
     denominator_histograms[sr][wp] = {}
     efficiency_histograms[sr][wp] = {}
     for which in [0, 1]:
         numerator_histograms[sr][wp][which] = None
         denominator_histograms[sr][wp][which] = None
         efficiency_histograms[sr][wp][which] = None
         # Load histograms
         first = True
         for ht_slice in ht_slices:
             f = TFile(
                 analysis_config.get_b_histogram_filename(
                     analyses[ht_slice], "JetHT_2012BCD"), "READ")
             this_numerator_histogram_3D = f.Get("BHistograms/h_pfjet_jet" +
                                                 str(which) + "_pt_eta_" +
                                                 wp)
             this_denominator_histogram_3D = f.Get(
                 "BHistograms/h_pfjet_jet" + str(which) + "_pt_eta")
             zbin_min = this_numerator_histogram_3D.GetZaxis().FindBin(
                 ht_ranges[ht_slice][0] + 1.e-5)
             zbin_max = this_numerator_histogram_3D.GetZaxis().FindBin(
                 ht_ranges[ht_slice][0] - 1.e-5)
             if first:
                 numerator_histograms[sr][wp][which] = TH2D(
                     this_numerator_histogram_3D.GetName() + "_xy" + wp +
                     str(which),
                     this_numerator_histogram_3D.GetName() + "_xy",
                     this_numerator_histogram_3D.GetXaxis().GetNbins(),
Beispiel #32
0
online_btag_eff = {
    "trigbbl_CSVTM": 1.82719e-01,
    "trigbbh_CSVTM": 4.89446e-01,
}

truth_categories = ["bb", "bc", "bg", "bl", "cc", "cg", "cl", "gg", "gl", "ll"]
truth_categories_incl = [
    "inclusive", "bb", "bc", "bg", "bl", "cc", "cg", "cl", "gg", "gl", "ll"
]

for analysis in analyses:
    h_mjj = None
    h_mjj_truthbb = None
    for qcd_sample in qcd_samples:
        f = TFile(
            analysis_config.get_b_histogram_filename(analysis, qcd_sample),
            "READ")
        input_nevents = f.Get("BHistograms/h_input_nevents").Integral()
        this_h_mjj = f.Get("BHistograms/h_pfjet_mjj").Clone()
        this_h_mjj.Scale(19700. * qcd_cross_sections[qcd_sample] /
                         input_nevents)
        this_h_mjj_truthbb = f.Get("BHistograms/h_pfjet_mjj_truthbb").Clone()
        this_h_mjj_truthbb.Scale(19700. * qcd_cross_sections[qcd_sample] /
                                 input_nevents)
        if not h_mjj:
            h_mjj = this_h_mjj.Clone()
            h_mjj.SetDirectory(0)
            h_mjj_truthbb = this_h_mjj_truthbb.Clone()
            h_mjj_truthbb.SetDirectory(0)
        else:
            h_mjj.Add(this_h_mjj)
def run_single_mass(args, mass):
    print "[run_single_mass] INFO : Creating datacard and workspace for m = %i GeV..."%(int(mass))
    if args.fit_functions == "all":
        #fit_functions = ["dijet4", "dijet5", "modexp4", "polyx6", "atlas4", "atlas5", "polypower4", "rational3", "rational4"]
        fit_functions = ["dijet4", "modexp4", "polyx6", "polypower4"]
    else:
        fit_functions = args.fit_functions.split(",")

    # import ROOT stuff
    from ROOT import gStyle, TFile, TH1F, TH1D, TGraph, kTRUE, kFALSE, TCanvas, TLegend, TPad, TLine
    from ROOT import RooHist, RooRealVar, RooDataHist, RooArgList, RooArgSet, RooAddPdf, RooProdPdf, RooEffProd, RooFit, RooGenericPdf, RooWorkspace, RooMsgService, RooHistPdf, RooExtendPdf, RooFormulaVar

    if not args.debug:
        RooMsgService.instance().setSilentMode(kTRUE)
        RooMsgService.instance().setStreamStatus(0,kFALSE)
        RooMsgService.instance().setStreamStatus(1,kFALSE)

    # Stuff
    mjj = RooRealVar('mjj','mjj',float(args.massMin),float(args.massMax))
    lumi = args.lumi
    signalCrossSection = 1. # Set to 1 so that the limit on r can be interpreted as a limit on the signal cross section

    # Input data file
    if args.qcd:
        data_sample = "QCD_TuneZ2star_8TeV_pythia6"
    elif "trigbb" in args.analysis:
        data_sample = "BJetPlusX_2012"
    elif "trigmu" in args.analysis:
        data_sample = "SingleMu_2012"
    data_file_path = analysis_config.get_b_histogram_filename(args.analysis, data_sample)
    if args.condor:
        data_file_path = os.path.basename(data_file_path)
    data_file = TFile(data_file_path)
    hData_notrigcorr = data_file.Get("BHistograms/h_pfjet_mjj")
    hData_notrigcorr.SetDirectory(0)
    hData_name = hData_notrigcorr.GetName()
    hData_notrigcorr.SetName(hData_name + "_notrigcorr")

    # Trigger correction on data
    if args.fitTrigger:
        # Make trigger correction objects
        trigeff_pt_formula, trigeff_vars = trigger_efficiency.get_var_formula(args.analysis, mjj)
        trigeff_btag_var      = RooRealVar("trigeff_btag", "trigeff_btag", 0., 1.)
        trigeff_btag_var.setVal(trigger_efficiency.online_btag_eff[args.analysis][0])
        trigeff_btag_var.setConstant()
        trigeff_btag_formula  = RooFormulaVar("trigeff_btag_formula", "@0", RooArgList(trigeff_btag_var))
        #trigeff_btag_var.setConstant()
        trigeff_total_formula = RooFormulaVar("trigeff_total_formula", "@0*@1", RooArgList(trigeff_btag_var, trigeff_pt_formula))
        #for trigeff_var_name, trigeff_var in trigeff_vars.iteritems():
        #    trigeff_var.setConstant()
    if args.correctTrigger:
        # Apply trigger correction to data histogram
        hData = CorrectTriggerEfficiency(hData_notrigcorr, args.analysis)

        # Still need b-tagging efficiency to scale the MC
        if not args.useMCTrigger:
            trigeff_btag_var      = RooRealVar("trigeff_btag", "trigeff_btag", 0., 1.)
            trigeff_btag_var.setVal(trigger_efficiency.online_btag_eff[args.analysis][0])
            trigeff_btag_var.setConstant()
            trigeff_btag_formula  = RooFormulaVar("trigeff_btag_formula", "@0", RooArgList(trigeff_btag_var))
            # Use a RooRealVar instead! You want to be able to apply a systematic in combine. 
            # trigeff_btag_formula  = RooFormulaVar("trigeff_btag_formula", str(trigger_efficiency.online_btag_eff[args.analysis][0]), RooArgList())
    else:
        hData = hData_notrigcorr
    if args.qcd:
        # For QCD, scale the histogram by the online b-tag trigger efficiency.
        if args.analysis == "NoTrigger_eta1p7_CSVTM":
            trigeff_btag_formula  = RooFormulaVar("trigeff_btag_formula", str(trigger_efficiency.online_btag_eff["trigbbl_CSVTM"][0]), RooArgList())
        elif args.analysis == "NoTrigger_eta2p2_CSVTM":
            trigeff_btag_formula  = RooFormulaVar("trigeff_btag_formula", str(trigger_efficiency.online_btag_eff["trigbbh_CSVTM"][0]), RooArgList())
        if args.analysis == "NoTrigger_eta1p7_CSVTM":
            hData.Scale(trigger_efficiency.online_btag_eff["trigbbl_CSVTM"][0])
        elif args.analysis == "NoTrigger_eta2p2_CSVTM":
            hData.Scale(trigger_efficiency.online_btag_eff["trigbbh_CSVTM"][0])
        else:
            print "[create_datacards_parallel] ERROR : QCD fit requested, but analysis != NoTrigger_etaXpY_CSVTM. I don't know what to do!"
            sys.exit(1)
    hData.SetName(hData_name)
    
    rooDataHist = RooDataHist('rooDatahist','rooDatahist',RooArgList(mjj),hData)
    if args.correctTrigger:
        rooDataHist_notrigcorr = RooDataHist("rooDatahist_notrigcorr", "rooDatahist_notrigcorr", RooArgList(mjj), hData_notrigcorr)

    # Get signal pdf * btag efficiency
    if args.useMCTrigger:
        signal_pdf_file = analysis_config.get_signal_fit_file(args.analysis, args.model, mass, "bukin", interpolated=(not mass in analysis_config.simulation.simulated_masses))
        if args.condor:
            signal_pdf_file = os.path.basename(signal_pdf_file)
        print "[create_datacards] Loading fitted signal PDFs from " + signal_pdf_file
        f_signal_pdfs = TFile(signal_pdf_file, "READ")
        f_signal_pdfs.Print()
        w_signal = f_signal_pdfs.Get("w_signal")
        w_signal.Print()
        bukin_pdf = w_signal.pdf("signal_bukin")
        bukin_pdf.Print()
    else:
        if args.analysis == "trigbbl_CSVTM" or args.analysis == "NoTrigger_eta1p7_CSVTM":
            notrig_analysis = "NoTrigger_eta1p7_CSVTM"
        elif args.analysis == "trigbbh_CSVTM" or args.analysis == "NoTrigger_eta2p2_CSVTM":
            notrig_analysis = "NoTrigger_eta2p2_CSVTM"
        elif args.analysis == "trigbbl_CSVM" or args.analysis == "NoTrigger_eta1p7_CSVM":
            notrig_analysis = "NoTrigger_eta1p7_CSVM"
        elif args.analysis == "trigbbh_CSVM" or args.analysis == "NoTrigger_eta2p2_CSVM":
            notrig_analysis = "NoTrigger_eta2p2_CSVM"
        else:
            print "[run_single_mass] ERROR : I don't know a no-trigger variant of analysis {}. Please make one, or specify --useMCTrigger.".format(args.analysis) 
            sys.exit(1)
        print analysis_config.simulation.simulated_masses
        signal_pdf_file = analysis_config.get_signal_fit_file(notrig_analysis, args.model, mass, "bukin", interpolated=(not mass in analysis_config.simulation.simulated_masses))
        print "[create_datacards] Loading fitted signal PDFs from " + signal_pdf_file
        if args.condor:
            signal_pdf_file = os.path.basename(signal_pdf_file)
        f_signal_pdfs = TFile(signal_pdf_file, "READ")
        w_signal = f_signal_pdfs.Get("w_signal")
        bukin_pdf = w_signal.pdf("signal")
        bukin_pdf.SetName("signal_bukin")
    input_signal_parameters = signal_fits.get_parameters(bukin_pdf)

    # Make a new PDF with nuisance parameters
    signal_pdf_notrig, signal_vars = signal_fits.make_signal_pdf_systematic("bukin", mjj, mass=mass)
    signal_pdf_name = signal_pdf_notrig.GetName()
    signal_pdf_notrig.SetName(signal_pdf_name + "_notrig")

    # Add trigger efficiency
    if args.useMCTrigger:
        if args.fitTrigger:
            # Online b-tagging eff incorporated in Bukin/acceptance, so signal pdf = Bukin * pT efficiency
            signal_pdf = RooEffProd("signal", "signal", signal_pdf_notrig, trigeff_pt_formula)
        elif args.correctTrigger:
            # Signal PDF = bukin; b-tag efficiency already included in normalization
            signal_pdf = signal_pdf_notrig
            signal_pdf.SetName(signal_pdf_name)
    else:
        if args.fitTrigger:
            # Signal PDF = bukin * total trigger efficiency
            signal_pdf = RooEffProd("signal", "signal", signal_pdf_notrig, trigeff_total_formula)
        elif args.correctTrigger:
            if args.useMCTrigger:
                signal_pdf = signal_pdf_notrig
                signal_pdf.SetName("signal")
            else:
                # Signal PDF = bukin * btag efficiency
                signal_pdf = RooEffProd("signal", "signal", signal_pdf_notrig, trigeff_btag_formula)
        elif args.qcd:
            # Signal PDF = bukin * btag efficiency
            # Same as correctTrigger
            signal_pdf = RooEffProd("signal", "signal", signal_pdf_notrig, trigeff_btag_formula)

    # Copy input parameter values
    signal_vars["xp_0"].setVal(input_signal_parameters["xp"][0])
    signal_vars["xp_0"].setError(input_signal_parameters["xp"][1])
    signal_vars["xp_0"].setConstant()
    signal_vars["sigp_0"].setVal(input_signal_parameters["sigp"][0])
    signal_vars["sigp_0"].setError(input_signal_parameters["sigp"][1])
    signal_vars["sigp_0"].setConstant()
    signal_vars["xi_0"].setVal(input_signal_parameters["xi"][0])
    signal_vars["xi_0"].setError(input_signal_parameters["xi"][1])
    signal_vars["xi_0"].setConstant()
    signal_vars["rho1_0"].setVal(input_signal_parameters["rho1"][0])
    signal_vars["rho1_0"].setError(input_signal_parameters["rho1"][1])
    signal_vars["rho1_0"].setConstant()
    signal_vars["rho2_0"].setVal(input_signal_parameters["rho2"][0])
    signal_vars["rho2_0"].setError(input_signal_parameters["rho2"][1])
    signal_vars["rho2_0"].setConstant()
    f_signal_pdfs.Close()

    signal_parameters = {}
    signal_pdfs_notrig = {}
    signal_pdfs = {}
    signal_norms = {}
    background_pdfs = {}
    background_pdfs_notrig = {}
    background_parameters = {}
    background_norms = {}
    signal_epdfs = {}
    background_epdfs = {}
    models = {}
    fit_results = {}

    if args.fitOffB:
        # Load RooHistPdf
        if "bbl" in args.analysis or "eta1p7" in args.analysis:
            eta_region = "eta1p7"
            offline_btag_eff_vars = {
                "p0":RooRealVar("offline_btag_eff_p0", "offline_btag_eff_p0",  6.78251e-03,  6.78251e-03 - 10.*7.66906e-05,  6.78251e-03 + 10.*7.66906e-05),
                "p1":RooRealVar("offline_btag_eff_p1", "offline_btag_eff_p1", -9.55614e-06, -9.55614e-06 - 10.*1.04286e-07, -9.55614e-06 + 10.*1.04286e-07),
                "p2":RooRealVar("offline_btag_eff_p2", "offline_btag_eff_p2",  4.39468e-09,  4.39468e-09 - 1.e-07,  4.39468e-09 + 1.e-07),
            }
            offline_btag_eff_formula = RooFormulaVar("offline_btag_eff", "max(@0+(@1*@3)+(@2*@3*@3), 0.)", RooArgList(offline_btag_eff_vars["p0"], offline_btag_eff_vars["p1"], offline_btag_eff_vars["p2"], mjj))
        elif "bbh" in args.analysis or "eta2p2" in args.analysis:
            eta_region = "eta2p2"
            offline_btag_eff_vars = {
                "p0":RooRealVar("offline_btag_eff_p0", "offline_btag_eff_p0", -1.72721e-03, -1.72721e-03 - 10.*3.04992e-05, -1.72721e-03 + 10.*3.04992e-05),
                "p1":RooRealVar("offline_btag_eff_p1", "offline_btag_eff_p1",  1.72562e-06,  1.72562e-06 - 10.*3.23472e-08,  1.72562e-06 + 10.*3.23472e-08),
                "p2":RooRealVar("offline_btag_eff_p2", "offline_btag_eff_p2",  8.74866e-03,  8.74866e-03 - 10.*7.81413e-05,  8.74866e-03 + 10.*7.81413e-05),
                "p3":RooRealVar("offline_btag_eff_p3", "offline_btag_eff_p3", -1.67123e-03, -1.67123e-03 - 10.*4.30607e-05, -1.67123e-03 + 10.*4.30607e-05),
            }
            offline_btag_eff_formula = RooFormulaVar("offline_btag_eff", "max(@0+@1*@4+ @2*exp(@3*@4), 0.)", RooArgList(offline_btag_eff_vars["p0"],offline_btag_eff_vars["p1"],offline_btag_eff_vars["p2"],offline_btag_eff_vars["p3"], mjj))

        #f_offline_btag_eff = TFile(analysis_config.get_offline_btag_file("CSVTM", eta_region))
        #h_offline_btag_eff = f_offline_btag_eff.Get("h_offline_btag_eff")
        #print h_offline_btag_eff
        #offline_btag_eff_rdh = RooDataHist("rdh_offline_btag_eff", "rdh_offline_btag_eff", RooArgList(mjj), h_offline_btag_eff)
        #offline_btag_eff_pdf = RooHistPdf("pdf_offline_btag_eff", "pdf_offline_btag_eff", RooArgSet(mjj), offline_btag_eff_rdh)

    for fit_function in fit_functions:
        print "[create_datacards] INFO : On fit function {}".format(fit_function)

        # Make a copy of the signal PDF, so that each fitTo call uses its own copy.
        # The copy should have all variables set constant.  
        #signal_pdfs[fit_function], signal_parameters[fit_function] = signal_fits.copy_signal_pdf("bukin", signal_pdf, mjj, tag=fit_function, include_systematics=True)

        signal_pdfs_notrig[fit_function] = ROOT.RooBukinPdf(signal_pdf_notrig, signal_pdf_notrig.GetName() + "_" + fit_function)
        iterator = signal_pdfs_notrig[fit_function].getVariables().createIterator()
        this_parameter = iterator.Next()
        while this_parameter:
            this_parameter.setConstant()
            this_parameter = iterator.Next()

        # Add trigger efficiency
        if args.useMCTrigger:
            if args.fitTrigger:
                signal_pdfs[fit_function] = RooEffProd(signal_pdf.GetName() + "_" + fit_function, signal_pdf.GetName() + "_" + fit_function, signal_pdfs_notrig[fit_function], trigeff_pt_formula)
            else:
                signal_pdfs[fit_function] = signal_pdfs_notrig[fit_function]
                signal_pdfs[fit_functions].SetName(signal_pdf.GetName() + "_" + fit_function)
        elif args.fitTrigger:
            # Signal PDF = bukin * total trigger efficiency
            signal_pdfs[fit_function] = RooEffProd(signal_pdf.GetName() + "_" + fit_function, signal_pdf.GetName() + "_" + fit_function, signal_pdfs_notrig[fit_function], trigeff_total_formula)
        elif args.correctTrigger:
            # Signal PDF = bukin * btag efficiency
            signal_pdfs[fit_function] = RooEffProd(signal_pdf.GetName() + "_" + fit_function, signal_pdf.GetName() + "_" + fit_function, signal_pdfs_notrig[fit_function], trigeff_btag_formula)
        elif args.qcd:
            # Signal PDF = bukin * btag efficiency
            signal_pdfs[fit_function] = RooEffProd(signal_pdf.GetName() + "_" + fit_function, signal_pdf.GetName() + "_" + fit_function, signal_pdfs_notrig[fit_function], trigeff_btag_formula)
        signal_norms[fit_function] = RooRealVar('signal_norm_' + fit_function, 'signal_norm_' + fit_function, 0., 0., 1e+05)
        if args.fitBonly: 
            signal_norms[fit_function].setConstant()

        # Make background PDF
        background_pdfs_notrig[fit_function], background_parameters[fit_function] = make_background_pdf(fit_function, mjj, collision_energy=8000.)
        background_pdf_name = background_pdfs_notrig[fit_function].GetName()
        background_pdfs_notrig[fit_function].SetName(background_pdf_name + "_notrig")
        if args.fitTrigger and args.fitOffB:
            background_pdf_intermediate = RooEffProd(background_pdf_name + "_intermediate", background_pdf_name + "_intermediate", background_pdfs_notrig[fit_function], offline_btag_eff_formula)
            background_pdfs[fit_function] = RooEffProd(background_pdf_name, background_pdf_name, background_pdf_intermediate, trigeff_pt_formula)
        elif args.fitTrigger and not args.fitOffB:
            background_pdfs[fit_function] = RooEffProd(background_pdf_name, background_pdf_name, background_pdfs_notrig[fit_function], trigeff_pt_formula)
        elif args.fitOffB and not args.fitTrigger:
            background_pdfs[fit_function] = RooEffProd(background_pdf_name, background_pdf_name, background_pdfs_notrig[fit_function], offline_btag_eff_formula)
        else:
            background_pdfs[fit_function] = background_pdfs_notrig[fit_function]
            background_pdfs[fit_function].SetName(background_pdf_name)
        
        # Initial values
        if "trigbbh" in args.analysis:
            if fit_function == "dijet4":
                if mass == 650:
                    background_parameters[fit_function]["p1"].setVal(-2.2473e+01)
                    background_parameters[fit_function]["p2"].setVal(1.4923e+01)
                    background_parameters[fit_function]["p3"].setVal(1.3077e+00)
                else:
                    background_parameters[fit_function]["p1"].setVal(-13.5877235358)
                    background_parameters[fit_function]["p2"].setVal(14.0659901462)
                    background_parameters[fit_function]["p3"].setVal(1.24550474025)
                background_parameters[fit_function]["p1"].setMin(-50.)
                background_parameters[fit_function]["p1"].setMax(50.)
            elif fit_function == "f2":
                background_parameters[fit_function]["p1"].setVal(6.06731321562)
                background_parameters[fit_function]["p2"].setVal(6.06264502704)
            elif fit_function == "polypower3":
                background_parameters[fit_function]["p1"].setVal(50.0270215343)
                background_parameters[fit_function]["p2"].setVal(8.17180937688)
                background_parameters[fit_function]["p1"].setMin(20.)
            elif fit_function == "polypower4":
                background_parameters[fit_function]["p1"].setVal(31.3765210572)
                background_parameters[fit_function]["p2"].setVal(-22.5800092219)
                background_parameters[fit_function]["p3"].setVal(9.94548656557)
            elif fit_function == "f5":
                background_parameters[fit_function]["p1"].setVal(5.51929170927)
                background_parameters[fit_function]["p2"].setVal(4.25521547671)
            elif fit_function == "f6":
                background_parameters[fit_function]["p1"].setVal(35.)
                background_parameters[fit_function]["p2"].setVal(-28.)
                background_parameters[fit_function]["p3"].setVal(0.)
                background_parameters[fit_function]["p4"].setVal(10.)
        elif "trigbbl" in args.analysis:
            if fit_function == "dijet4":
                background_parameters[fit_function]["p1"].setVal(-32.4727133488)
                background_parameters[fit_function]["p2"].setVal(18.7641649883)
                background_parameters[fit_function]["p3"].setVal(1.84028034937)
            elif fit_function == "f2":
                background_parameters[fit_function]["p1"].setVal(4.96261586452)
                background_parameters[fit_function]["p2"].setVal(19.0848105961)
            if fit_function == "polypower3":
                background_parameters[fit_function]["p1"].setVal(60.0000032579)
                background_parameters[fit_function]["p2"].setVal(8.00317534363)
                background_parameters[fit_function]["p1"].setMin(60.)
            elif fit_function == "polypower4":
                background_parameters[fit_function]["p1"].setVal(25.4109169544)
                background_parameters[fit_function]["p2"].setVal(-42.56719661)
                background_parameters[fit_function]["p3"].setVal(12.3295648189)
            elif fit_function == "f5":                
                background_parameters[fit_function]["p1"].setVal(3.74859358646)
                background_parameters[fit_function]["p2"].setVal(11.4366903839)
            elif fit_function == "f6":
                background_parameters[fit_function]["p1"].setVal(35.)
                background_parameters[fit_function]["p2"].setVal(-43.)
                background_parameters[fit_function]["p3"].setVal(0.)
                background_parameters[fit_function]["p4"].setVal(10.)

        data_integral = hData.Integral(hData.GetXaxis().FindBin(float(args.massMin)),hData.GetXaxis().FindBin(float(args.massMax)))
        background_norms[fit_function] = RooRealVar('background_' + fit_function + '_norm', 'background_' + fit_function + '_norm', data_integral, 0., 1.e8)

        signal_epdfs[fit_function] = RooExtendPdf('esignal_' + fit_function, 'esignal_' + fit_function, signal_pdfs[fit_function], signal_norms[fit_function])
        background_epdfs[fit_function] = RooExtendPdf('ebackground_' + fit_function, 'ebackground_' + fit_function, background_pdfs[fit_function], background_norms[fit_function])

        models[fit_function] = RooAddPdf('model_' + fit_function, 's+b', RooArgList(background_epdfs[fit_function], signal_epdfs[fit_function]))

        if args.runFit and not args.dconly:
            print "[create_datacards] INFO : Starting fit with function {}".format(fit_function)
            models[fit_function].Print()
            # Fix the trigger efficiency for this fit
            if args.fitTrigger:
                trigeff_vars["alpha_trigeff_p0"].setConstant(True)
                trigeff_vars["alpha_trigeff_p1"].setConstant(True)
                trigeff_btag_var.setConstant(True)
            if args.fitOffB:
                for var in offline_btag_eff_vars.values():
                    var.setConstant(True)
            fit_results[fit_function] = models[fit_function].fitTo(rooDataHist, RooFit.Save(kTRUE), RooFit.Extended(kTRUE), RooFit.Strategy(args.fitStrategy), RooFit.Verbose(0))
            print "[create_datacards] INFO : Done with fit {}. Printing results.".format(fit_function)
            fit_results[fit_function].Print()
            if args.fitTrigger:
                # Current strategy: freeze the trigger nuisance parameters. 
                trigeff_vars["alpha_trigeff_p0"].setConstant(True)
                trigeff_vars["alpha_trigeff_p1"].setConstant(True)
                trigeff_btag_var.setConstant(True)
            if args.fitOffB:
                for var in offline_btag_eff_vars.values():
                    var.setConstant(False)
            print "[create_datacards] DEBUG : End args.runFit if block."


        # needed if want to evaluate limits without background systematics
        if args.fixBkg:
            background_norms[fit_function].setConstant()
            for par_name, par in background_parameters[fit_function].iteritems():
                par.setConstant()

    # -----------------------------------------
    # Set values of signal systematic variables
    # JES and JER uncertainties
    if "jes" in systematics:
        xp_central = signal_vars["xp_0"].getVal()
        xp_up = signal_fits.get_parameters(w_signal.pdf("signal__JESUp"))["xpJESUp"][0]
        xp_down = signal_fits.get_parameters(w_signal.pdf("signal__JESDown"))["xpJESDown"][0]
        signal_vars["dxp"].setVal(max(abs(xp_up - xp_central), abs(xp_down - xp_central)))
        if signal_vars["dxp"].getVal() > 2 * mass * 0.1:
            print "[create_datacards] WARNING : Large dxp value. dxp = {}, xp_down = {}, xp_central = {}, xp_up = {}".format(signal_vars["dxp"].getVal(), xp_down, xp_central, xp_up)
        signal_vars["alpha_jes"].setVal(0.)
        signal_vars["alpha_jes"].setConstant(False)
    else:
        signal_vars["dxp"].setVal(0.)
        signal_vars["alpha_jes"].setVal(0.)
        signal_vars["alpha_jes"].setConstant()
    signal_vars["dxp"].setError(0.)
    signal_vars["dxp"].setConstant()

    if "jer" in systematics:
        sigp_central = signal_vars["sigp_0"].getVal()
        sigp_up = signal_fits.get_parameters(w_signal.pdf("signal__JERUp"))["sigpJERUp"][0]
        sigp_down = signal_fits.get_parameters(w_signal.pdf("signal__JERDown"))["sigpJERDown"][0]
        signal_vars["dsigp"].setVal(max(abs(sigp_up - sigp_central), abs(sigp_down - sigp_central)))
        signal_vars["alpha_jer"].setVal(0.)
        signal_vars["alpha_jer"].setConstant(False)
    else:
        signal_vars["dsigp"].setVal(0.)
        signal_vars["alpha_jer"].setVal(0.)
        signal_vars["alpha_jer"].setConstant()
    signal_vars["dsigp"].setError(0.)
    signal_vars["dsigp"].setConstant()

    # -----------------------------------------
    # create a datacard and corresponding workspace
    postfix = (('_' + args.postfix) if args.postfix != '' else '')
    wsName = 'workspace_' + args.final_state + '_m' + str(mass) + postfix + '.root'

    if not args.dconly:
        w = RooWorkspace('w','workspace')
        signal_pdf.SetName("signal")
        getattr(w,'import')(signal_pdf,RooFit.Rename("signal"))
        norm = args.lumi
        signal_norm = ROOT.RooRealVar("signal_norm", "signal_norm", norm/100., norm/100. / 10., norm * 10.)
        print "[create_datacards] INFO : Set signal norm to {}".format(signal_norm.getVal())
        signal_norm.setConstant()
        getattr(w,'import')(signal_norm,ROOT.RooCmdArg())
        for fit_function in fit_functions:
            print "Importing background PDF"
            print background_pdfs[fit_function]
            background_pdfs[fit_function].Print()
            getattr(w,'import')(background_pdfs[fit_function],ROOT.RooCmdArg(),RooFit.Rename("background_" + fit_function), RooFit.RecycleConflictNodes())
            w.pdf("background_" + fit_function).Print()
            getattr(w,'import')(background_norms[fit_function],ROOT.RooCmdArg(),RooFit.Rename("background_" + fit_function + "_norm"))
            getattr(w,'import')(fit_results[fit_function])
            getattr(w,'import')(signal_norms[fit_function],ROOT.RooCmdArg())
            if args.fitBonly:
                getattr(w,'import')(models[fit_function],ROOT.RooCmdArg(),RooFit.RecycleConflictNodes())
        getattr(w,'import')(rooDataHist,RooFit.Rename("data_obs"))
        if args.correctTrigger:
            getattr(w,'import')(rooDataHist_notrigcorr, RooFit.Rename("data_obs_notrigcorr"))

        w.Print()
        print "Starting save"
        if args.output_path:
            if not os.path.isdir( os.path.join(os.getcwd(),args.output_path) ):
                os.mkdir( os.path.join(os.getcwd(),args.output_path) )
            workspace_output_path = os.path.join(args.output_path,wsName)
        else:
            workspace_output_path = limit_config.get_workspace_filename(args.analysis, args.model, mass, fitBonly=args.fitBonly, fitTrigger=args.fitTrigger, correctTrigger=args.correctTrigger, useMCTrigger=args.useMCTrigger, qcd=args.qcd, fitOffB=args.fitOffB)
        if args.condor:
            workspace_output_path = os.path.basename(workspace_output_path)
        print "[create_datacards] INFO : Writing workspace to file {}".format(workspace_output_path)
        w.writeToFile(workspace_output_path)
        if args.correctTrigger:
            f_workspace = TFile(workspace_output_path, "UPDATE")
            hData.Write()
            hData_notrigcorr.Write()

    # Clean up
    for name, obj in signal_norms.iteritems():
        if obj:
            obj.IsA().Destructor(obj)
    for name, obj in background_pdfs.iteritems():
        if obj:
            obj.IsA().Destructor(obj)
    for name, obj in background_pdfs_notrig.iteritems():
        if obj:
            obj.IsA().Destructor(obj)
    for name, obj in background_norms.iteritems():
        if obj:
            obj.IsA().Destructor(obj)
    for name, obj in signal_pdfs.iteritems():
        if obj:
            obj.IsA().Destructor(obj)
    for name, obj in signal_pdfs_notrig.iteritems():
        if obj:
            obj.IsA().Destructor(obj)
    for name, obj in signal_epdfs.iteritems():
        if obj:
            obj.IsA().Destructor(obj)
    for name, obj in background_epdfs.iteritems():
        if obj:
            obj.IsA().Destructor(obj)
    for name, obj in fit_results.iteritems():
        if obj:
            obj.IsA().Destructor(obj)
    for name, dict_l2 in background_parameters.iteritems():
        for name2, obj in dict_l2.iteritems():
            if obj:
                obj.IsA().Destructor(obj)
    for name, obj in models.iteritems():
        if obj:
            obj.IsA().Destructor(obj)
    rooDataHist.IsA().Destructor(rooDataHist)
    if not args.dconly:
        w.IsA().Destructor(w)

    # Make datacards only if S+B fitted
    #beffUnc = 0.3
    boffUnc = systematics["boff"][args.analysis][args.model].Eval(mass)
    pdfUnc = systematics["pdfunc"][args.analysis][args.model].Eval(mass)
    for fit_function in fit_functions:
        if args.output_path:
            dcName = 'datacard_' + args.final_state + '_m' + str(mass) + postfix + '_' + fit_function + '.txt'
            datacard_output_path = os.path.join(args.output_path,dcName)
        else:
            datacard_output_path = limit_config.get_datacard_filename(args.analysis, args.model, mass, fit_function, fitTrigger=args.fitTrigger, correctTrigger=args.correctTrigger, useMCTrigger=args.useMCTrigger, qcd=args.qcd, fitOffB=args.fitOffB, fitBonly=args.fitBonly)
        if args.condor:
            datacard_output_path = os.path.basename(datacard_output_path)
        print "[create_datacards] INFO : Writing datacard to file {}".format(datacard_output_path) 
        datacard = open(datacard_output_path, 'w')
        datacard.write('imax 1\n')
        datacard.write('jmax 1\n')
        datacard.write('kmax *\n')
        datacard.write('---------------\n')
        if args.output_path:
            datacard.write('shapes * * '+wsName+' w:$PROCESS\n')
        else:
            datacard.write('shapes * * '+os.path.basename(limit_config.get_workspace_filename(args.analysis, args.model, mass, fitTrigger=args.fitTrigger, correctTrigger=args.correctTrigger, useMCTrigger=args.useMCTrigger, qcd=args.qcd, fitOffB=args.fitOffB, fitBonly=args.fitBonly))+' w:$PROCESS\n')
        datacard.write('---------------\n')
        datacard.write('bin 1\n')
        datacard.write('observation -1\n')
        datacard.write('------------------------------\n')
        datacard.write('bin          1          1\n')
        datacard.write('process      signal     background_' + fit_function + '\n')
        datacard.write('process      0          1\n')
        datacard.write('rate         1         1\n')
        datacard.write('------------------------------\n')
        datacard.write('lumi  lnN    %f         -\n'%(1.+systematics["luminosity"]))
        if not args.useMCTrigger:
            datacard.write('bon  lnN    %f         -\n'%(1.+ (trigger_efficiency.online_btag_eff[args.analysis][2] / trigger_efficiency.online_btag_eff[args.analysis][0])))
        else:
            datacard.write('bon  lnN    %f         -\n'%(1.+ systematics["bon"]))
        #datacard.write('beff  lnN    %f         -\n'%(1.+beffUnc))
        datacard.write('boff  lnN    %f         -\n'%(1.+boffUnc))
        datacard.write('pdf  lnN    %f         -\n'%(1.+pdfUnc))
        #datacard.write('bkg   lnN     -         1.03\n')
        if "jes" in systematics:
            datacard.write("alpha_jes  param  0.0  1.0\n")
        if "jer" in systematics:
            datacard.write("alpha_jer  param  0.0  1.0\n")
        if args.fitOffB:
            if eta_region == "eta1p7":
                datacard.write("offline_btag_eff_p0  param   6.78251e-03  3.82505e-04\n")
                datacard.write("offline_btag_eff_p1  param  -9.55614e-06  1.13679e-06\n")
                datacard.write("offline_btag_eff_p2  param   4.39468e-09  7.90724e-10\n")
            elif eta_region == "eta2p2":
                datacard.write("offline_btag_eff_p0  param  -1.72721e-03  3.04992e-05\n")
                datacard.write("offline_btag_eff_p1  param   1.72562e-06  3.23472e-08\n")
                datacard.write("offline_btag_eff_p2  param   8.74866e-03  7.81413e-05\n")
                datacard.write("offline_btag_eff_p3  param  -1.67123e-03  4.30607e-05\n")

        # Current decision: don't put in nuisance parameters for trigger efficiency sigmoid. Impact is likely small.
        #if args.fitTrigger:
        #    if "bbl" in args.analysis or "eta1p7" in args.analysis:
        #        datacard.write("alpha_trigeff_p0  param  {}  {}\n".format(0.0, 1.0))
        #        datacard.write("alpha_trigeff_p1  param  {}  {}\n".format(0.0, 1.0))
        # Background fit parameters --- flat prior
        datacard.write('background_' + fit_function + '_norm  flatParam\n')
        for par_name, par in background_parameters[fit_function].iteritems():
                datacard.write(fit_function + "_" + par_name + '  flatParam\n')
        datacard.close()
        print "[create_datacards] INFO : Done with this datacard"

    #print '>> Datacards and workspaces created and stored in %s/'%( os.path.join(os.getcwd(),args.output_path) )
    print "Done with mass {}.".format(mass)