3 from __future__
import print_function
18 ROOT.PyConfig.IgnoreCommandLineOptions =
True 22 if not overwrite
and rfile.Get(
"sig_obs"):
23 print(
" Kept observed significance: {:8.3f}".format(rfile.Get(
"sig_obs")[0]))
27 work_dir = tempfile.mkdtemp()
28 link_path = os.path.join(work_dir, os.path.basename(output_path))
29 os.symlink(output_path, link_path)
32 command = [
"combine",
"-M",
"ProfileLikelihood",
"--significance",
"--uncapped=1",
"--rMin=-10.",
"-d",link_path]
33 with open(log_path,
"a")
as dn:
34 subprocess.check_call(command, stdout=dn, stderr=dn)
37 result_path = os.path.join(work_dir,
"higgsCombineTest.ProfileLikelihood.mH120.root")
40 tree = result.Get(
"limit")
43 signif_vec = ROOT.TVectorD(1)
44 signif_vec[0] = signif
46 signif_vec.Write(
"sig_obs",ROOT.TObject.kWriteDelete)
47 shutil.rmtree(work_dir)
48 print(
"Saved observed significance: {:8.3f}".format(signif))
52 if not overwrite
and rfile.Get(
"sig_exp"):
53 print(
" Kept expected significance: {:8.3f}".format(rfile.Get(
"sig_exp")[0]))
57 work_dir = tempfile.mkdtemp()
58 link_path = os.path.join(work_dir, os.path.basename(output_path))
59 os.symlink(output_path, link_path)
62 command = [
"combine",
"-M",
"ProfileLikelihood",
"--significance",
"--uncapped=1",
"--rMin=-10.",
"--expectSignal=1",
"--toysFreq",
"-t",
"-1",
"-d",link_path]
63 with open(log_path,
"a")
as dn:
64 subprocess.check_call(command, stdout=dn, stderr=dn)
67 result_path = os.path.join(work_dir,
"higgsCombineTest.ProfileLikelihood.mH120.root")
70 tree = result.Get(
"limit")
73 signif_vec = ROOT.TVectorD(1)
74 signif_vec[0] = signif
76 signif_vec.Write(
"sig_exp",ROOT.TObject.kWriteDelete)
77 shutil.rmtree(work_dir)
78 print(
"Saved expected significance: {:8.3f}".format(signif))
82 if not overwrite
and rfile.Get(
"lim_obs")
and rfile.Get(
"lim_exp16")
and rfile.Get(
"lim_exp50")
and rfile.Get(
"lim_exp84"):
83 print(
" Kept observed limit: {:8.3f}".format(rfile.Get(
"lim_obs")[0]))
84 print(
" Kept expected limit (16%): {:8.3f}".format(rfile.Get(
"lim_exp16")[0]))
85 print(
" Kept expected limit (50%): {:8.3f}".format(rfile.Get(
"lim_exp50")[0]))
86 print(
" Kept expected limit (84%): {:8.3f}".format(rfile.Get(
"lim_exp84")[0]))
90 work_dir = tempfile.mkdtemp()
91 link_path = os.path.join(work_dir, os.path.basename(output_path))
92 os.symlink(output_path, link_path)
95 command = [
"combine",
"-M",
"Asymptotic",
"-d",link_path]
96 with open(log_path,
"a")
as dn:
97 subprocess.check_call(command, stdout=dn, stderr=dn)
100 result_path = os.path.join(work_dir,
"higgsCombineTest.Asymptotic.mH120.root")
106 tree = result.Get(
"limit")
108 if entry.quantileExpected < 0.:
110 elif entry.quantileExpected > 0.15
and entry.quantileExpected < 0.17:
112 elif entry.quantileExpected > 0.49
and entry.quantileExpected < 0.51:
114 elif entry.quantileExpected > 0.83
and entry.quantileExpected < 0.85:
116 obs_vec = ROOT.TVectorD(1)
117 exp16_vec = ROOT.TVectorD(1)
118 exp50_vec = ROOT.TVectorD(1)
119 exp84_vec = ROOT.TVectorD(1)
125 obs_vec.Write(
"lim_obs",ROOT.TObject.kWriteDelete)
126 exp16_vec.Write(
"lim_exp16",ROOT.TObject.kWriteDelete)
127 exp50_vec.Write(
"lim_exp50",ROOT.TObject.kWriteDelete)
128 exp84_vec.Write(
"lim_exp84",ROOT.TObject.kWriteDelete)
129 shutil.rmtree(work_dir)
130 print(
"Saved observed limit: {:8.3f}".format(obs))
131 print(
"Saved expected limit (16%): {:8.3f}".format(exp16))
132 print(
"Saved expected limit (50%): {:8.3f}".format(exp50))
133 print(
"Saved expected limit (84%): {:8.3f}".format(exp84))
135 def run_fit(output_path, overwrite, log_path):
137 if not overwrite
and rfile.Get(
"fit_b")
and rfile.Get(
"fit_s"):
138 print(
" Kept fit results")
142 work_dir = tempfile.mkdtemp()
143 link_path = os.path.join(work_dir, os.path.basename(output_path))
144 os.symlink(output_path, link_path)
147 command = [
"combine",
"-M",
"MaxLikelihoodFit",
"--forceRecreateNLL",
"--saveWorkspace",
"--saveWithUncertainties",
"--minos=all",
"-w",
"w",
"--dataset",
"data_obs",
"-d",link_path]
148 with open(log_path,
"a")
as dn:
149 subprocess.check_call(command, stdout=dn, stderr=dn)
152 result_path = os.path.join(work_dir,
"mlfit.root")
154 fit_b = result.Get(
"fit_b")
156 fit_b.Write(
"fit_b",ROOT.TObject.kWriteDelete)
157 fit_s = result.Get(
"fit_s")
159 fit_s.Write(
"fit_s",ROOT.TObject.kWriteDelete)
160 shutil.rmtree(work_dir)
161 print(
"Saved fit results")
165 if not rfile.Get(
"fit_b"):
170 f = rfile.Get(
"fit_b")
171 if not rfile.Get(
"w_orig"):
174 pars = f.floatParsFinal()
175 for i
in range(pars.getSize()):
177 v = w.var(p.GetName())
179 v.setError(p.getError())
180 w.Write(
"w", ROOT.TObject.kWriteDelete)
181 print(
"Set variables to background-only best fit values")
187 pval = rfile.Get(
"pval")
188 chi_sq = rfile.Get(
"chi2")
189 saved_ndof = rfile.Get(
"ndof")
190 if not overwrite
and (pval
or chi_sq
or saved_ndof):
192 print(
" Kept p-value: {:8.3f}".format(pval[0]))
194 print(
" Kept chi^2: {:8.3f}".format(chi_sq[0]))
196 print(
" Kept N.D.o.F.: {:4d}".format(int(saved_ndof[0])))
199 if not rfile.Get(
"w_orig"):
200 print(
'Skipping goodness of fit. Run with "--full_fit --overwrite" first to enable.')
204 pdf = w.pdf(
"model_b")
205 fit_nll = -pdf.getLogVal()
208 variables = w.allVars()
209 iterator = variables.createIterator()
210 variable = iterator.Next()
212 name = variable.GetName()
213 if "nobs_BLK_" in name
or "nobsmc_BLK_" in name:
214 val = variable.getVal()
216 sat_nll -= val*math.log(val) - val - math.lgamma(val+1.)
217 variable = iterator.Next()
219 chi_sq = 2.*(fit_nll-sat_nll)
220 pval = scipy.stats.chi2.sf(chi_sq,ndof)
221 chi_sq_vec = ROOT.TVectorD(1)
222 ndof_vec = ROOT.TVectorD(1)
223 pval_vec = ROOT.TVectorD(1)
224 chi_sq_vec[0] = chi_sq
225 ndof_vec[0] = float(ndof)
230 chi_sq_vec.Write(
"chi2",ROOT.TObject.kWriteDelete)
231 ndof_vec.Write(
"ndof",ROOT.TObject.kWriteDelete)
232 pval_vec.Write(
"pval",ROOT.TObject.kWriteDelete)
234 print(
"Saved p-value: {:8.3f}".format(pval))
235 print(
"Saved chi^2: {:8.3f}".format(chi_sq))
236 print(
"Saved N.D.o.F.: {:4d}".format(int(ndof)))
238 def run_combine(workspace_path, output_path, do_full_fit, overwrite, log_path, ndof):
242 with open(log_path,
"w")
as log_file:
243 print(
"Workspace file: {}".format(workspace_path),file=log_file)
245 if output_path
is None:
246 output_path = workspace_path
249 shutil.copy2(workspace_path, output_path)
253 run_fit(output_path, overwrite, log_path)
259 run_limit(output_path, overwrite, log_path)
261 if __name__ ==
"__main__":
262 parser = argparse.ArgumentParser(description=
"Runs combine to find significance, limits, and best fit parameter values",
263 formatter_class=argparse.ArgumentDefaultsHelpFormatter)
264 parser.add_argument(
"workspace_file", help=
"File containing RooWorkspace")
265 parser.add_argument(
"--full_fit", action=
"store_true", help=
"Do full (slow) maximum likelihood fit, storing results. Also sets workspace parameters to best fit values if --overwrite option used.")
266 parser.add_argument(
"--output_file", default=
None, help=
"Store results in specified file instead of caching in input file")
267 parser.add_argument(
"--overwrite", action=
"store_true", help=
"Overwrite/update already computed results")
268 parser.add_argument(
"--log_file", default=os.devnull, help=
"Log file in which to write combine output (not yet working)")
269 parser.add_argument(
"--ndof", type=int, default=18, help=
"Number of degrees of freedom for goodness of fit test")
271 args = parser.parse_args()
273 run_combine(args.workspace_file, args.output_file, args.full_fit, args.overwrite, args.log_file, args.ndof)
def run_obs_signif(output_path, overwrite, log_path)
def run_limit(output_path, overwrite, log_path)
def fix_vars(output_path)
def run_fit(output_path, overwrite, log_path)
def run_exp_signif(output_path, overwrite, log_path)
def run_combine(workspace_path, output_path, do_full_fit, overwrite, log_path, ndof)
def goodness_of_fit(output_path, overwrite, ndof)