Skip to content

Commit

Permalink
Plot updates.
Browse files Browse the repository at this point in the history
  • Loading branch information
riga committed Jan 15, 2025
1 parent 92d0054 commit e7f46e5
Show file tree
Hide file tree
Showing 8 changed files with 95 additions and 80 deletions.
63 changes: 39 additions & 24 deletions hbt/calibration/default.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,30 +71,45 @@ def default_init(self: Calibrator) -> None:
met_name = self.config_inst.x.met_name
raw_met_name = self.config_inst.x.raw_met_name

# derive calibrators to add settings
self.jec_full_cls = jec.derive("jec_full", cls_dict={
"mc_only": True,
"nominal_only": True,
"met_name": met_name,
"raw_met_name": raw_met_name,
})
self.jec_nominal_cls = jec_nominal.derive("jec_nominal", cls_dict={
"met_name": met_name,
"raw_met_name": raw_met_name,
})

# version of jer that uses the first random number from deterministic_seeds
self.deterministic_jer_cls = jer.derive("deterministic_jer", cls_dict={
"deterministic_seed_index": 0,
"met_name": met_name,
})

# derive tec calibrators
self.tec_cls = tec.derive("tec", cls_dict={"met_name": met_name})
self.tec_nominal_cls = tec_nominal.derive("tec_nominal", cls_dict={"met_name": met_name})

# derive met_phi calibrator (currently only for run 2)
self.met_phi_cls = met_phi.derive("met_phi", cls_dict={"met_name": met_name})
# derive calibrators to add settings once
flag = f"custom_calibs_registered_{self.cls_name}"
if not self.config_inst.x(flag, False):
# jec calibrators
self.config_inst.x.calib_jec_full_cls = jec.derive("jec_full", cls_dict={
"mc_only": True,
"nominal_only": True,
"met_name": met_name,
"raw_met_name": raw_met_name,
})
self.config_inst.x.calib_jec_nominal_cls = jec_nominal.derive("jec_nominal", cls_dict={
"met_name": met_name,
"raw_met_name": raw_met_name,
})
# version of jer that uses the first random number from deterministic_seeds
self.config_inst.x.calib_deterministic_jer_cls = jer.derive("deterministic_jer", cls_dict={
"deterministic_seed_index": 0,
"met_name": met_name,
})
# derive tec calibrators
self.config_inst.x.calib_jec_cls = tec.derive("tec", cls_dict={
"met_name": met_name,
})
self.config_inst.x.calib_jec_cls = tec_nominal.derive("tec_nominal", cls_dict={
"met_name": met_name,
})
# derive met_phi calibrator (currently only used in run 2)
self.config_inst.x.calib_met_phi_cls = met_phi.derive("met_phi", cls_dict={
"met_name": met_name,
})
# change the flag
self.config_inst.set_aux(flag, True)

self.jec_full_cls = self.config_inst.x.calib_jec_full_cls
self.jec_nominal_cls = self.config_inst.x.calib_jec_nominal_cls
self.deterministic_jer_cls = self.config_inst.x.calib_deterministic_jer_cls
self.tec_cls = self.config_inst.x.calib_jec_cls
self.tec_nominal_cls = self.config_inst.x.calib_jec_cls
self.met_phi_cls = self.config_inst.x.calib_met_phi_cls

# collect derived calibrators and add them to the calibrator uses and produces
derived_calibrators = {
Expand Down
4 changes: 2 additions & 2 deletions hbt/config/categories.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,11 @@ def kwargs_fn(categories, add_qcd_group=True):
# auxiliary information
"aux": aux,
# label
"label": [
"label": ", ".join([
cat.label or cat.name
for cat in categories.values()
if cat.name != "os" # os is the default
] or None,
]) or None,
}

# main analysis categories
Expand Down
18 changes: 12 additions & 6 deletions hbt/config/configs_hbt.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ def if_not_era(*, values: list[str | None] | None = None, **kwargs) -> list[str]
cfg.add_process(proc)

# configure colors, labels, etc
from hbt.config.styles import stylize_processes, update_legend_labels
from hbt.config.styles import stylize_processes
stylize_processes(cfg)

################################################################################################
Expand Down Expand Up @@ -441,7 +441,8 @@ def if_not_era(*, values: list[str | None] | None = None, **kwargs) -> list[str]
"qcd",
"st",
"tt_multiboson",
"all_v",
"v",
"multiboson",
"h",
"ewk",
]),
Expand Down Expand Up @@ -531,14 +532,19 @@ def if_not_era(*, values: list[str | None] | None = None, **kwargs) -> list[str]
cfg.x.default_selector_steps = "default"

# plotting overwrites
from hbt.config.styles import legend_entries_per_column
cfg.x.default_general_settings = {
"cms_label": "wip",
"whitespace_fraction": 0.31,
}
cfg.x.custom_style_config_groups = {
"small_legend": {
"legend_cfg": {
"ncols": 2, "fontsize": 16, "columnspacing": 0.6, "labelspacing": 0.275,
"update_handles_labels": update_legend_labels,
"ncols": 3, "borderpad": 0.7, "loc": "upper left", "fontsize": 16,
"columnspacing": 1.6, "labelspacing": 0.28,
"entries_per_column": legend_entries_per_column,
},
"annotate_cfg": {"fontsize": 18},
"cms_label": "wip",
"annotate_cfg": {"fontsize": 16, "xycoords": "axes fraction", "xy": (0.035, 0.73), "style": "italic"},
},
}
cfg.x.default_custom_style_config = "small_legend"
Expand Down
39 changes: 20 additions & 19 deletions hbt/config/styles.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,13 @@ def stylize_processes(config: od.Config) -> None:
p.color1 = cfg.x.colors.bright_blue

if (p := config.get_process("vv", default=None)):
p.color1 = cfg.x.colors.aubergine
p.color1 = cfg.x.colors.yellow

if (p := config.get_process("vvv", default=None)):
p.color1 = cfg.x.colors.aubergine
p.color1 = cfg.x.colors.yellow

if (p := config.get_process("multiboson", default=None)):
p.color1 = cfg.x.colors.aubergine
p.color1 = cfg.x.colors.yellow

if (p := config.get_process("w", default=None)):
p.color1 = cfg.x.colors.aubergine
Expand Down Expand Up @@ -102,23 +102,24 @@ def stylize_processes(config: od.Config) -> None:
p.color1 = cfg.x.colors.red


def update_legend_labels(ax, handles, labels, n_cols):
def legend_entries_per_column(ax, handles: list, labels: list, n_cols: int) -> list[int]:
"""
Fill empty handles so that all backgrounds are in the first column.
Control number of entries such that backgrounds are in the first n - 1 columns, and everything
else in the last one.
"""
# only implemented for 2 columns so far
if n_cols != 2:
return
# get number of entries per column
# get number of background and remaining entries
n_backgrounds = sum(1 for handle in handles if handle.__class__.__name__ == "StepPatch")
n_other = len(handles) - n_backgrounds
if n_backgrounds == n_other:
return

# fill left or right column
n_add = abs(n_backgrounds - n_other)
pos = len(handles) if n_backgrounds > n_other else n_backgrounds
empty_handle = ax.plot([], label="", linestyle="None")[0]
for _ in range(n_add):
handles.insert(pos, empty_handle)
labels.insert(pos, "")

# fill number of entries per column
entries_per_col = n_cols * [0]
n_bkg_cols = n_cols
# set last column if non-backgrounds are present
if n_other:
entries_per_col[-1] = n_other
n_bkg_cols -= 1
# fill background columns
for i in range(n_bkg_cols):
entries_per_col[i] = n_backgrounds // n_bkg_cols + (n_backgrounds % n_bkg_cols > i)

return entries_per_col
4 changes: 3 additions & 1 deletion hbt/config/variables.py
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,9 @@ def dilep_mass_test(events):
config,
name="dilep_mass",
expression=dilep_mass_test,
aux={"inputs": ["{Electron,Muon,Tau}.{pt,eta,phi,mass}"]},
aux={
"inputs": ["{Electron,Muon,Tau}.{pt,eta,phi,mass}"],
},
binning=(40, 40, 120),
unit="GeV",
x_title=r"$m_{ll}$",
Expand Down
43 changes: 17 additions & 26 deletions hbt/production/btag.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,29 +47,23 @@ def _normalized_btag_weights(self: Producer, events: ak.Array, **kwargs) -> ak.A
if not weight_name.startswith(self.weight_name):
continue

# BUG in prod3: some stats fields were missing so skip them for now
# # create a weight vectors starting with ones for both weight variations, i.e.,
# # nomalization per pid and normalization per pid and jet multiplicity
# norm_weight_per_pid = np.ones(len(events), dtype=np.float32)
# norm_weight_per_pid_njet = np.ones(len(events), dtype=np.float32)

# # fill weights with a new mask per unique process id (mostly just one)
# for pid in self.unique_process_ids:
# pid_mask = events.process_id == pid
# # single value
# norm_weight_per_pid[pid_mask] = self.ratio_per_pid[weight_name][pid]
# # lookup table
# n_jets = ak.to_numpy(ak.num(events[pid_mask].Jet.pt, axis=1))
# norm_weight_per_pid_njet[pid_mask] = self.ratio_per_pid_njet[weight_name][pid][n_jets]

# # multiply with actual weight
# norm_weight_per_pid = norm_weight_per_pid * events[weight_name]
# norm_weight_per_pid_njet = norm_weight_per_pid_njet * events[weight_name]

# fake values
from columnflow.columnar_util import full_like
norm_weight_per_pid = full_like(events.event, 1.0, dtype=np.float32)
norm_weight_per_pid_njet = norm_weight_per_pid
# create a weight vectors starting with ones for both weight variations, i.e.,
# nomalization per pid and normalization per pid and jet multiplicity
norm_weight_per_pid = np.ones(len(events), dtype=np.float32)
norm_weight_per_pid_njet = np.ones(len(events), dtype=np.float32)

# fill weights with a new mask per unique process id (mostly just one)
for pid in self.unique_process_ids:
pid_mask = events.process_id == pid
# single value
norm_weight_per_pid[pid_mask] = self.ratio_per_pid[weight_name][pid]
# lookup table
n_jets = ak.to_numpy(ak.num(events[pid_mask].Jet.pt, axis=1))
norm_weight_per_pid_njet[pid_mask] = self.ratio_per_pid_njet[weight_name][pid][n_jets]

# multiply with actual weight
norm_weight_per_pid = norm_weight_per_pid * events[weight_name]
norm_weight_per_pid_njet = norm_weight_per_pid_njet * events[weight_name]

# store them
events = set_ak_column_f32(events, f"normalized_{weight_name}", norm_weight_per_pid)
Expand Down Expand Up @@ -107,9 +101,6 @@ def _normalized_btag_weights_requires(self: Producer, reqs: dict) -> None:

@_normalized_btag_weights.setup
def _normalized_btag_weights_setup(self: Producer, reqs: dict, inputs: dict, reader_targets: InsertableDict) -> None:
# BUG in prod3: some stats fields were missing so skip them for now
return

# load the selection stats
selection_stats = self.task.cached_value(
key="selection_stats",
Expand Down
2 changes: 1 addition & 1 deletion modules/cmsdb

0 comments on commit e7f46e5

Please sign in to comment.