3 from __future__
import print_function
16 funcs = w.allFunctions()
17 iterator = funcs.createIterator()
18 func = iterator.Next()
19 names = [
"Systematics"]
22 if name.startswith(
"nbkg_BLK_"):
23 names.append(name[9:])
24 func = iterator.Next()
29 funcs = w.allFunctions()
30 iterator = funcs.createIterator()
31 func = iterator.Next()
35 if name.startswith(
"nmc_BLK_")
and "_PRC_" in name:
36 pos = name.find(
"_PRC_") + 5
37 names.append(name[pos:])
38 func = iterator.Next()
44 iterator = pdfs.createIterator()
49 if name.startswith(
"constraint_"):
50 names.append(name[11:])
59 if name ==
"Systematics":
continue 60 nobs = w.var(
"nobs_BLK_"+name).getVal()
62 b[3] -= nobs*math.log(nobs) - nobs - math.lgamma(nobs+1.)
64 nobs = w.var(
"nobsmc_BLK_{}_PRC_{}".format(name, p)).getVal()
66 b[3] -= nobs*math.log(nobs) - nobs - math.lgamma(nobs+1.)
69 pars = f.floatParsFinal()
71 for i
in range(pars.getSize()):
73 var = w.var(par.GetName())
75 var.setVal(par.getVal())
76 var.setError(par.getError())
77 if par.GetName() ==
"r": 91 if name ==
"Systematics":
93 b[1] -= w.pdf(
"constraint_{}".format(c)).getLogVal(
None)
96 b[1] -= w.pdf(
"pdf_null_BLK_{}".format(name)).getLogVal()
98 b[1] -= w.pdf(
"pdf_mc_BLK_{}_PRC_{}".format(name, p)).getLogVal()
105 if name ==
"Systematics":
106 for c
in constraints:
107 b[2] -= w.pdf(
"constraint_{}".format(c)).getLogVal(
None)
110 b[2] -= w.pdf(
"pdf_alt_BLK_{}".format(name)).getLogVal()
112 b[2] -= w.pdf(
"pdf_mc_BLK_{}_PRC_{}".format(name, p)).getLogVal()
117 pos = name.find(
"_BIN_")+5
120 name = name.replace(
"r1_",
"R1: ")
121 name = name.replace(
"r2_",
"R2: ")
122 name = name.replace(
"r3_",
"R3: ")
123 name = name.replace(
"r4_",
"R4: ")
125 name = name.replace(
"lowmet",
"200<MET#leq 350")
126 name = name.replace(
"medmet",
"350<MET#leq 500")
127 name = name.replace(
"highmet",
"MET>500")
129 name = name.replace(
"_lownj",
", 6#leq N_{jets}#leq 8")
130 name = name.replace(
"_highnj",
", N_{jets}#geq 9")
132 name = name.replace(
"_allnb",
"")
133 name = name.replace(
"_1b",
", N_{b}=1")
134 name = name.replace(
"_2b",
", N_{b}=2")
135 name = name.replace(
"_3b",
", N_{b}#geq 3")
140 norm_cdf = scipy.stats.norm.cdf(n_sigma)
141 chi2_ppf = scipy.stats.chi2.ppf(norm_cdf, n_dof)
142 return chi2_ppf/n_bins
145 h.SetLineWidth(width)
146 h.SetLineStyle(style)
147 h.SetLineColor(color)
149 def make_plot(out_dir, input_name, bins, ndof, r_sign, bkg_idx, sig_idx):
156 for i
in range(len(bins)):
157 chisq += 2.*(bins[i][bkg_idx]-bins[i][sig_idx])
158 p = scipy.stats.chi2.sf(chisq,ndof)
163 z = scipy.stats.norm.isf(p)
165 out_name =
"{}_chisq_{}_model.pdf".format(input_name,
166 "signal" if sig_idx == 2
else "saturated")
167 out_path = os.path.join(out_dir, out_name)
169 h_name =
"Background-Only vs {} Model (#chi^{{2}}={:.2f}, N.D.o.F.={:d}, p={:.3f}, Z={:.2f});;#chi^{{2}}" 170 h_name = h_name.format(
"Signal" if sig_idx == 2
else "Saturated", chisq, ndof, p, z)
172 h = ROOT.TH1D(
"", h_name, len(bins), -0.5, len(bins)-0.5)
174 h0 = ROOT.TH1D(
"", h_name, len(bins), -0.5, len(bins)-0.5)
176 style(h, 4, 1, ROOT.kBlack)
177 style(h0, 1, 2, ROOT.kBlack)
181 for i
in range(len(bins)):
182 h.GetXaxis().SetBinLabel(i+1,
pretty_name(bins[i][0]))
183 chisq = 2.*(bins[i][bkg_idx]-bins[i][sig_idx])
184 h.SetBinContent(i+1,chisq)
185 h0.SetBinContent(i+1, y0)
187 h.LabelsOption(
"v",
"x")
191 c.SetMargin(0.1, 0.05, 0.4, 0.1)
200 input_name = os.path.splitext(os.path.basename(input_path))[0]
204 fit_b = f.Get(
"fit_b")
205 fit_s = f.Get(
"fit_s")
210 r = fit_s.floatParsFinal().find(
"r") 213 elif r.getVal() > 0.:
220 print(
"{:>48s}: {:>12s} {:>12s} {:>12s}".format(
"Bin Name",
"Bkg NLL",
"Sig NLL",
"Sat NLL"))
222 print(
"{:>48s}: {:>12.3f} {:>12.3f} {:>12.3f}".format(b[0],b[1],b[2],b[3]))
224 make_plot(out_dir, input_name, bins, ndof, r_sign, 1, 2)
225 make_plot(out_dir, input_name, bins, ndof, 0, 1, 3)
227 if __name__ ==
"__main__":
228 parser = argparse.ArgumentParser(description=
"Finds approximate significance contribution from each bin",
229 formatter_class=argparse.ArgumentDefaultsHelpFormatter)
230 parser.add_argument(
"in_file", help=
"File to analyze, containing global workspace and cached fit results")
231 parser.add_argument(
"out_dir", default=
".", nargs=
"?", help=
"Directory in which to place results")
232 parser.add_argument(
"--ndof", type=int, default=18, help=
"Degrees of freedom added by saturated model compared to background-only model")
234 args = parser.parse_args()
def find_sat_nlls(bins, procs, w)
def find_bkg_nlls(bins, procs, constraints, w, fit_b)
def get_threshold(n_sigma, n_bins, n_dof)
def make_plot(out_dir, input_name, bins, ndof, r_sign, bkg_idx, sig_idx)
def style(h, width, style, color)
def bin_significance(out_dir, input_path, ndof)
def get_constraint_names(w)
def find_sig_nlls(bins, procs, constraints, w, fit_s)