Skip to content

Commit a259206

Browse files
authored
Update for POWHEG simulations (#1047)
* Update DB for D0 jets * Restrict statistics for inclusive jets * Prepare for gen-only productions * Establish conversion for gen-only * Establish masshisto for gen-only production * Update * Run all conversions * Fix * Run processor * Add submission for feeddown simulation * Extend jet analyzer to read feeddown info from processor * Test with latest Lc trains * Establish runnable version with POWHEG * Fix minor issues * Fix technical issues * Fix technicalities * Propagate POWHEG weights to luminosity scaling * Clean up code * Fix formatting * Update POWHEG scaling
1 parent 971f958 commit a259206

14 files changed

Lines changed: 1048 additions & 448 deletions

machine_learning_hep/analysis/analyzer_jets.py

Lines changed: 74 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -65,15 +65,18 @@ def __init__(self, datap, case, typean, period):
6565
suffix = f"results.{period}" if period is not None else "resultsallp"
6666
self.d_resultsallpmc = self.cfg(f"mc.{suffix}")
6767
self.d_resultsallpdata = self.cfg(f"data.{suffix}")
68+
self.d_resultsallpfd = self.cfg(f"fd.{suffix}")
6869

6970
# input directories (processor output)
7071
self.d_resultsallpdata_proc = self.cfg(f"data_proc.{suffix}")
7172
self.d_resultsallpmc_proc = self.cfg(f"mc_proc.{suffix}")
73+
self.d_resultsallpfd_proc = self.cfg(f"fd_proc.{suffix}")
7274

7375
# input files
7476
n_filemass_name = datap["files_names"]["histofilename"]
7577
self.n_filemass = os.path.join(self.d_resultsallpdata_proc, n_filemass_name)
7678
self.n_filemass_mc = os.path.join(self.d_resultsallpmc_proc, n_filemass_name)
79+
self.n_filemass_fd = os.path.join(self.d_resultsallpfd_proc, n_filemass_name)
7780
self.n_fileeff = datap["files_names"]["efffilename"]
7881
self.n_fileeff = os.path.join(self.d_resultsallpmc_proc, self.n_fileeff)
7982
self.n_fileresp = datap["files_names"]["respfilename"]
@@ -83,9 +86,8 @@ def __init__(self, datap, case, typean, period):
8386
self.p_pdfnames = datap["analysis"][self.typean].get("pdf_names")
8487
self.p_param_names = datap["analysis"][self.typean].get("param_names")
8588

86-
# TODO: should come entirely from DB
8789
self.observables = {
88-
"qa": ["zg", "rg", "nsd", "zpar", "dr", "lntheta", "lnkt", "lntheta-lnkt"],
90+
"qa": [*self.cfg("observables", {})],
8991
"all": [*self.cfg("observables", {})],
9092
}
9193

@@ -114,7 +116,7 @@ def __init__(self, datap, case, typean, period):
114116
for param, symbol in zip(
115117
("mean", "sigma", "significance", "chi2"),
116118
("#it{#mu}", "#it{#sigma}", "significance", "#it{#chi}^{2}"),
117-
strict=False,
119+
strict=True,
118120
)
119121
}
120122
for level in self.fit_levels
@@ -209,7 +211,7 @@ def qa(self): # pylint: disable=invalid-name
209211
# region efficiency
210212
# pylint: disable=too-many-statements
211213
def calculate_efficiencies(self):
212-
self.logger.info("Calculating efficiencies")
214+
self.logger.info("Calculating efficiencies from %s", self.n_fileeff)
213215
cats = {"pr", "np"}
214216
with TFile(self.n_fileeff) as rfile:
215217
h_gen = {cat: rfile.Get(f"h_ptjet-pthf_{cat}_gen") for cat in cats}
@@ -586,9 +588,6 @@ def fit(self):
586588
if iptjet is None:
587589
if not fitcfg.get("per_ptjet"):
588590
for jptjet in range(get_nbins(h, 1)):
589-
self.logger.info(
590-
"Overwriting roows_ptjet for %s iptjet %s ipt %d", level, jptjet, ipt
591-
)
592591
self.roows[(jptjet, ipt)] = roo_ws.Clone()
593592
self.roo_ws[(level, jptjet, ipt)] = roo_ws.Clone()
594593
if level in ("data", "mc"):
@@ -685,7 +684,6 @@ def _subtract_sideband(self, hist, var, mcordata, ipt):
685684
# project out the mass regions (first axis)
686685
axes = list(range(get_dim(hist)))[1:]
687686
fh[region] = project_hist(hist, axes, {0: bins[region]})
688-
self.logger.info("Projecting %s to %s in %s: %g entries", hist, axes, bins[region], fh[region].GetEntries())
689687
self._save_hist(
690688
fh[region], f"sideband/h_ptjet{label}_{region}_{string_range_pthf(range_pthf)}_{mcordata}.png"
691689
)
@@ -702,11 +700,8 @@ def _subtract_sideband(self, hist, var, mcordata, ipt):
702700
self.logger.info("Scaling sidebands in ptjet-%s bins: %s using %s", label, bins_ptjet, fh_sideband)
703701
hx = project_hist(fh_sideband, (0,), {}) if get_dim(fh_sideband) > 1 else fh_sideband
704702
for iptjet in bins_ptjet:
705-
if iptjet:
706-
n = hx.GetBinContent(iptjet)
707-
self.logger.info("Need to scale in ptjet %i: %g", iptjet, n)
708-
if n <= 0:
709-
continue
703+
if iptjet and hx.GetBinContent(iptjet) <= 0:
704+
continue
710705
rws = self.roo_ws.get((mcordata, iptjet, ipt))
711706
if not rws:
712707
self.logger.error("Falling back to incl. roows for %s-iptjet%i-ipt%i", mcordata, iptjet, ipt)
@@ -1063,57 +1058,77 @@ def _extract_signal(self, hist, var, mcordata, ipt):
10631058
# hres.Sumw2() # TODO: check if we should do this here
10641059
return hres
10651060

1066-
# region feeddown
1067-
# pylint: disable=too-many-statements
10681061
def estimate_feeddown(self):
1069-
self.logger.info("Estimating feeddown")
1062+
"""Estimate feeddown from legacy Run 2 trees or gen-only simulation"""
1063+
match self.cfg("fd_input", "tree"):
1064+
case "tree":
1065+
self.logger.info("Reading feeddown information from trees")
1066+
with TFile(self.cfg("fd_root")) as rfile:
1067+
powheg_xsection = rfile.Get("fHistXsection")
1068+
powheg_xsection_scale_factor = powheg_xsection.GetBinContent(1) / powheg_xsection.GetEntries()
1069+
self.logger.info("POWHEG luminosity (mb^{-1}): %g", 1.0 / powheg_xsection_scale_factor)
1070+
1071+
df = pd.read_parquet(self.cfg("fd_parquet"))
1072+
col_mapping = {"dr": "delta_r_jet", "zpar": "z"} # TODO: check mapping
1073+
1074+
# TODO: generalize to higher dimensions
1075+
h3_fd_gen_orig = {}
1076+
for var in self.observables["all"]:
1077+
bins_ptjet = np.asarray(self.cfg("bins_ptjet"), "d")
1078+
# TODO: generalize or derive from histogram?
1079+
bins_obs = {}
1080+
if binning := self.cfg(f"observables.{var}.bins_gen_var"):
1081+
bins_tmp = np.asarray(binning, "d")
1082+
elif binning := self.cfg(f"observables.{var}.bins_gen_fix"):
1083+
bins_tmp = bin_array(*binning)
1084+
elif binning := self.cfg(f"observables.{var}.bins_var"):
1085+
bins_tmp = np.asarray(binning, "d")
1086+
elif binning := self.cfg(f"observables.{var}.bins_fix"):
1087+
bins_tmp = bin_array(*binning)
1088+
else:
1089+
self.logger.error("no binning specified for %s, using defaults", var)
1090+
bins_tmp = bin_array(10, 0.0, 1.0)
1091+
bins_obs[var] = bins_tmp
10701092

1071-
with TFile(self.cfg("fd_root")) as rfile:
1072-
powheg_xsection = rfile.Get("fHistXsection")
1073-
powheg_xsection_scale_factor = powheg_xsection.GetBinContent(1) / powheg_xsection.GetEntries()
1074-
self.logger.info("POWHEG luminosity (mb^{-1}): %g", 1.0 / powheg_xsection_scale_factor)
1093+
colname = col_mapping.get(var, f"{var}_jet")
1094+
if f"{colname}" not in df:
1095+
if var is not None:
1096+
self.logger.error(
1097+
"No feeddown information for %s (%s), cannot estimate feeddown", var, colname
1098+
)
1099+
# print(df.info(), flush=True)
1100+
continue
10751101

1076-
df = pd.read_parquet(self.cfg("fd_parquet"))
1077-
col_mapping = {"dr": "delta_r_jet", "zpar": "z"} # TODO: check mapping
1102+
# TODO: derive histogram
1103+
h3_fd_gen_orig[var] = create_hist(
1104+
"h3_feeddown_gen",
1105+
f";p_{{T}}^{{jet}} (GeV/#it{{c}});p_{{T}}^{{HF}} (GeV/#it{{c}});{var}",
1106+
bins_ptjet,
1107+
self.bins_candpt,
1108+
bins_obs[var],
1109+
)
1110+
fill_hist_fast(h3_fd_gen_orig[var], df[["pt_jet", "pt_cand", f"{colname}"]])
1111+
1112+
case "sim":
1113+
h3_fd_gen_orig = {}
1114+
with TFile(self.n_filemass_fd) as rfile:
1115+
for var in self.observables["all"]:
1116+
self.logger.info("Running feeddown analysis for obs. %s", var)
1117+
label = f"-{var}" if var else ""
1118+
if fh := rfile.Get(f"h_mass-ptjet-pthf{label}"):
1119+
h3_fd_gen_orig[var] = project_hist(fh, list(range(1, get_dim(fh))), {})
1120+
h_norm = rfile.Get("histonorm")
1121+
powheg_xsection_avg = h_norm.GetBinContent(6) / h_norm.GetBinContent(5)
1122+
powheg_xsection_scale_factor = powheg_xsection_avg / h_norm.GetBinContent(5)
1123+
self.logger.info("powheg_xsection_scale_factor = %f", powheg_xsection_scale_factor)
1124+
self.logger.info("POWHEG luminosity (mb^{-1}): %g", 1. / powheg_xsection_scale_factor)
1125+
1126+
case fd_input:
1127+
self.logger.critical("Invalid feeddown input %s", fd_input)
10781128

1079-
# TODO: generalize to higher dimensions
10801129
for var in self.observables["all"]:
1081-
bins_ptjet = np.asarray(self.cfg("bins_ptjet"), "d")
1082-
# TODO: generalize or derive from histogram?
1083-
bins_obs = {}
1084-
if binning := self.cfg(f"observables.{var}.bins_gen_var"):
1085-
bins_tmp = np.asarray(binning, "d")
1086-
elif binning := self.cfg(f"observables.{var}.bins_gen_fix"):
1087-
bins_tmp = bin_array(*binning)
1088-
elif binning := self.cfg(f"observables.{var}.bins_var"):
1089-
bins_tmp = np.asarray(binning, "d")
1090-
elif binning := self.cfg(f"observables.{var}.bins_fix"):
1091-
bins_tmp = bin_array(*binning)
1092-
else:
1093-
self.logger.error("no binning specified for %s, using defaults", var)
1094-
bins_tmp = bin_array(10, 0.0, 1.0)
1095-
bins_obs[var] = bins_tmp
1096-
1097-
colname = col_mapping.get(var, f"{var}_jet")
1098-
if f"{colname}" not in df:
1099-
if var is not None:
1100-
self.logger.error("No feeddown information for %s (%s), cannot estimate feeddown", var, colname)
1101-
# print(df.info(), flush=True)
1102-
continue
1103-
1104-
# TODO: derive histogram
1105-
h3_fd_gen_orig = create_hist(
1106-
"h3_feeddown_gen",
1107-
f";p_{{T}}^{{jet}} (GeV/#it{{c}});p_{{T}}^{{HF}} (GeV/#it{{c}});{var}",
1108-
bins_ptjet,
1109-
self.bins_candpt,
1110-
bins_obs[var],
1111-
)
1112-
fill_hist_fast(h3_fd_gen_orig, df[["pt_jet", "pt_cand", f"{colname}"]])
1113-
self._save_hist(project_hist(h3_fd_gen_orig, [0, 2], {}), f"fd/h_ptjet-{var}_feeddown_gen_noeffscaling.png")
1114-
11151130
# new method
1116-
h3_fd_gen = h3_fd_gen_orig.Clone()
1131+
h3_fd_gen = h3_fd_gen_orig[var].Clone()
11171132
ensure_sumw2(h3_fd_gen)
11181133
self._save_hist(project_hist(h3_fd_gen, [0, 2], {}), f"fd/h_ptjet-{var}_fdnew_gen.png")
11191134
# apply np efficiency
@@ -1158,7 +1173,7 @@ def estimate_feeddown(self):
11581173
h_fd_det = project_hist(h3_fd_det, [0, 2], {})
11591174

11601175
# old method
1161-
h3_fd_gen = h3_fd_gen_orig.Clone()
1176+
h3_fd_gen = h3_fd_gen_orig[var].Clone()
11621177
ensure_sumw2(h3_fd_gen)
11631178
for ipt in range(get_nbins(h3_fd_gen, 1)):
11641179
eff_pr = self.hcandeff["pr"].GetBinContent(ipt + 1)

machine_learning_hep/common.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from enum import Enum
2+
3+
class DataType(Enum):
4+
MC = "mc"
5+
DATA = "data"
6+
FD = "fd"

0 commit comments

Comments
 (0)