Skip to content

Commit f871768

Browse files
authored
Merge pull request #103 from uhh-cms/feature/2023
Feature/2023
2 parents 53caa18 + dfeb377 commit f871768

18 files changed

+231
-102
lines changed

hbw/analysis/create_analysis.py

+12
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,18 @@ def analysis_factory(configs: od.UniqueObjectIndex):
157157
2210,
158158
)
159159

160+
# 2023 prePBix
161+
add_lazy_config(
162+
"c23pre",
163+
2300,
164+
)
165+
166+
# 2023 postPBix
167+
add_lazy_config(
168+
"c23post",
169+
2310,
170+
)
171+
160172
add_lazy_config(
161173
"c22pre_das",
162174
2201,

hbw/config/categories.py

+11-10
Original file line numberDiff line numberDiff line change
@@ -90,13 +90,13 @@ def add_abcd_categories(config: od.Config) -> None:
9090
name="highmet",
9191
id=3,
9292
selection="catid_highmet",
93-
label=r"MET \geq 20",
93+
label=r"$MET \geq 20$",
9494
)
9595
config.add_category(
9696
name="lowmet",
9797
id=6,
9898
selection="catid_lowmet",
99-
label=r"MET < 20",
99+
label=r"$MET < 20$",
100100
)
101101

102102

@@ -110,24 +110,25 @@ def add_mll_categories(config: od.Config) -> None:
110110
name="sr",
111111
id=1,
112112
selection="catid_mll_low",
113+
label=r"$m_{\ell\ell} < 81$",
113114
)
114115
cr = config.add_category(
115116
name="cr",
116117
id=2,
117118
selection="catid_cr",
118-
label=r"m_{\ell\ell} \geq 81",
119+
label=r"$m_{\ell\ell} \geq 81$",
119120
)
120121
cr.add_category(
121122
name="dycr",
122123
id=3,
123124
selection="catid_mll_z",
124-
# label=r"81 \leq m_{\ell\ell} < 101",
125+
label=r"$81 \leq m_{\ell\ell} < 101$",
125126
)
126127
cr.add_category(
127128
name="ttcr",
128129
id=4,
129130
selection="catid_mll_high",
130-
# label=r"m_{\ell\ell} \geq 101",
131+
label=r"$m_{\ell\ell} \geq 101$",
131132
)
132133

133134

@@ -180,13 +181,13 @@ def add_njet_categories(config: od.Config) -> None:
180181
name="njet1",
181182
id=100001,
182183
selection="catid_njet1",
183-
label=r"N_{jet} >= 1",
184+
label=r"$N_{jet} >= 1$",
184185
)
185186
config.add_category(
186187
name="njet3",
187188
id=100003,
188189
selection="catid_njet3",
189-
label=r"N_{jet} >= 3",
190+
label=r"$N_{jet} >= 3$",
190191
)
191192

192193

@@ -209,13 +210,13 @@ def add_jet_categories(config: od.Config) -> None:
209210
name="1b",
210211
id=300,
211212
selection="catid_1b",
212-
label="1b",
213+
label=r"$\leq 1 btag$",
213214
)
214215
cat_2b = config.add_category( # noqa: F841
215216
name="2b",
216217
id=600,
217218
selection="catid_2b",
218-
label="2b",
219+
label=r"$\geq 2 btag$",
219220
)
220221

221222

@@ -258,7 +259,7 @@ def name_fn(root_cats):
258259
def kwargs_fn(root_cats):
259260
kwargs = {
260261
"id": sum([c.id for c in root_cats.values()]),
261-
"label": ", ".join([c.name for c in root_cats.values()]),
262+
"label": ",\n".join([c.label for c in root_cats.values()]),
262263
"aux": {
263264
"root_cats": {key: value.name for key, value in root_cats.items()},
264265
},

hbw/config/config_run2.py

+95-44
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@
2525
from hbw.config.hist_hooks import add_hist_hooks
2626
from hbw.util import timeit_multiple
2727

28+
from columnflow.production.cms.electron import ElectronSFConfig
29+
from columnflow.production.cms.muon import MuonSFConfig
30+
from columnflow.production.cms.btag import BTagSFConfig
31+
2832
thisdir = os.path.dirname(os.path.abspath(__file__))
2933

3034
logger = law.logger.get_logger(__name__)
@@ -39,8 +43,6 @@ def add_config(
3943
limit_dataset_files: int | None = None,
4044
add_dataset_extensions: bool = False,
4145
) -> od.Config:
42-
# validations
43-
assert campaign.x.year in [2016, 2017, 2018, 2022]
4446
# gather campaign data
4547
year = campaign.x.year
4648
year2 = year % 100
@@ -54,9 +56,14 @@ def add_config(
5456
if not campaign.has_tag("postEE") and not campaign.has_tag("preEE"):
5557
raise ValueError("2022 campaign must have the 'postEE' or 'preEE' tag")
5658
corr_postfix = "postEE" if campaign.has_tag("postEE") else "preEE"
59+
elif campaign.x.year == 2023:
60+
if not campaign.has_tag("postBPix") and not campaign.has_tag("preBPix"):
61+
raise ValueError("2023 campaign must have the 'postBPix' or 'preBPix' tag")
62+
corr_postfix = "postBPix" if campaign.has_tag("postBPix") else "preBPix"
5763

58-
if campaign.x.year not in [2017, 2022]:
59-
raise NotImplementedError("For now, only 2017 and 2022 campaign is implemented")
64+
implemented_years = [2017, 2022, 2023]
65+
if campaign.x.year not in implemented_years:
66+
raise NotImplementedError(f"For now, only {', '.join(implemented_years)} years are implemented")
6067

6168
# create a config by passing the campaign, so id and name will be identical
6269
# cfg = analysis.add_config(campaign, name=config_name, id=config_id, tags=analysis.tags)
@@ -171,12 +178,12 @@ def if_era(
171178
})
172179
elif year == 2023:
173180
if campaign.has_tag("preBPix"):
174-
cfg.x.luminosity = Number(17.794, {
181+
cfg.x.luminosity = Number(17794, {
175182
"lumi_13TeV_2023": 0.01j,
176183
"lumi_13TeV_correlated": 0.006j,
177184
})
178185
elif campaign.has_tag("postBPix"):
179-
cfg.x.luminosity = Number(9.451, {
186+
cfg.x.luminosity = Number(9451, {
180187
"lumi_13TeV_2023": 0.01j,
181188
"lumi_13TeV_correlated": 0.006j,
182189
})
@@ -197,15 +204,22 @@ def if_era(
197204
# JEC
198205
# https://twiki.cern.ch/twiki/bin/view/CMS/JECDataMC?rev=201
199206
jerc_postfix = campaign.x.postfix
200-
if jerc_postfix not in ("", "APV", "EE"):
207+
if jerc_postfix not in ("", "APV", "EE", "BPix"):
201208
raise ValueError(f"Unknown JERC postfix '{jerc_postfix}'")
202209

203210
if cfg.x.run == 2:
204-
jerc_campaign = f"Summer19UL{year2}{jerc_postfix}"
211+
jer_campaign = jec_campaign = f"Summer19UL{year2}{jerc_postfix}"
205212
jet_type = "AK4PFchs"
206213
fatjet_type = "AK8PFchs"
207214
elif cfg.x.run == 3:
208-
jerc_campaign = f"Summer{year2}{jerc_postfix}_22Sep2023"
215+
if year == 2022:
216+
jer_campaign = jec_campaign = f"Summer{year2}{jerc_postfix}_22Sep2023"
217+
elif year == 2023:
218+
# NOTE: this might be totally wrong, ask Daniel
219+
# TODO: fix for 2023postBPix....
220+
era = "Cv4" if campaign.has_tag("preBPix") else "D"
221+
jer_campaign = f"Summer{year2}{jerc_postfix}Prompt{year2}_Run{era}"
222+
jec_campaign = f"Summer{year2}{jerc_postfix}Prompt{year2}"
209223
jet_type = "AK4PFPuppi"
210224
fatjet_type = "AK8PFPuppi"
211225

@@ -222,17 +236,17 @@ def if_era(
222236
cfg.x.jec = DotDict.wrap({
223237
# NOTE: currently, we set the uncertainty_sources in the calibrator itself
224238
"Jet": {
225-
"campaign": jerc_campaign,
226-
"version": {2016: "V7", 2017: "V5", 2018: "V5", 2022: "V2"}[year],
239+
"campaign": jec_campaign,
240+
"version": {2016: "V7", 2017: "V5", 2018: "V5", 2022: "V2", 2023: "V1"}[year],
227241
"jet_type": jet_type,
228242
"external_file_key": "jet_jerc",
229243
"levels": ["L1FastJet", "L2Relative", "L2L3Residual", "L3Absolute"],
230244
"levels_for_type1_met": ["L1FastJet"],
231245
"uncertainty_sources": jec_uncertainties,
232246
},
233247
"FatJet": {
234-
"campaign": jerc_campaign,
235-
"version": {2016: "V7", 2017: "V5", 2018: "V5", 2022: "V2"}[year],
248+
"campaign": jec_campaign,
249+
"version": {2016: "V7", 2017: "V5", 2018: "V5", 2022: "V2", 2023: "V1"}[year],
236250
"jet_type": fatjet_type,
237251
"external_file_key": "fat_jet_jerc",
238252
"levels": ["L1FastJet", "L2Relative", "L2L3Residual", "L3Absolute"],
@@ -245,14 +259,14 @@ def if_era(
245259
# https://twiki.cern.ch/twiki/bin/view/CMS/JetResolution?rev=107
246260
cfg.x.jer = DotDict.wrap({
247261
"Jet": {
248-
"campaign": jerc_campaign,
249-
"version": {2016: "JRV3", 2017: "JRV2", 2018: "JRV2", 2022: "JRV1"}[year],
262+
"campaign": jer_campaign,
263+
"version": {2016: "JRV3", 2017: "JRV2", 2018: "JRV2", 2022: "JRV1", 2023: "JRV1"}[year],
250264
"jet_type": jet_type,
251265
"external_file_key": "jet_jerc",
252266
},
253267
"FatJet": {
254-
"campaign": jerc_campaign,
255-
"version": {2016: "JRV3", 2017: "JRV2", 2018: "JRV2", 2022: "JRV1"}[year],
268+
"campaign": jer_campaign,
269+
"version": {2016: "JRV3", 2017: "JRV2", 2018: "JRV2", 2022: "JRV1", 2023: "JRV1"}[year],
256270
# "jet_type": "fatjet_type",
257271
# JER info only for AK4 jets, stored in AK4 file
258272
"jet_type": jet_type,
@@ -328,11 +342,28 @@ def if_era(
328342
})
329343

330344
# b-tag configuration. Potentially overwritten by the jet Selector.
331-
cfg.x.b_tagger = {
332-
2: "deepjet",
333-
3: "particlenet",
334-
}[cfg.x.run]
345+
if cfg.x.run == 2:
346+
cfg.x.b_tagger = "deepjet"
347+
cfg.x.btag_sf = BTagSFConfig(
348+
correction_set="deepJet_shape",
349+
jec_sources=cfg.x.btag_sf_jec_sources,
350+
discriminator="btagDeepFlavB",
351+
# corrector_kwargs=...,
352+
)
353+
elif cfg.x.run == 3:
354+
cfg.x.b_tagger = "particlenet"
355+
cfg.x.btag_sf = BTagSFConfig(
356+
correction_set="particleNet_shape",
357+
jec_sources=cfg.x.btag_sf_jec_sources,
358+
discriminator="btagPNetB",
359+
# corrector_kwargs=...,
360+
)
361+
362+
cfg.x.btag_column = cfg.x.btag_sf.discriminator
335363
cfg.x.btag_wp = "medium"
364+
cfg.x.btag_wp_score = (
365+
cfg.x.btag_working_points[cfg.x.b_tagger][cfg.x.btag_wp]
366+
)
336367

337368
# met configuration
338369
cfg.x.met_name = {
@@ -390,29 +421,49 @@ def if_era(
390421
if cfg.x.run == 2:
391422
# names of electron correction sets and working points
392423
# (used in the electron_sf producer)
393-
cfg.x.electron_sf_names = ("UL-Electron-ID-SF", f"{cfg.x.cpn_tag}", "Tight")
424+
cfg.x.electron_sf_names = ElectronSFConfig(
425+
correction="UL-Electron-ID-SF",
426+
campaign=f"{cfg.x.cpn_tag}",
427+
working_point="Tight",
428+
)
394429

395430
# names of muon correction sets and working points
396431
# (used in the muon producer)
397-
cfg.x.muon_sf_names = ("NUM_TightRelIso_DEN_TightIDandIPCut", f"{cfg.x.cpn_tag}_UL")
398432
cfg.x.muon_id_sf_names = ("NUM_TightID_DEN_TrackerMuons", f"{cfg.x.cpn_tag}_UL")
399433
cfg.x.muon_iso_sf_names = ("NUM_TightRelIso_DEN_TightIDandIPCut", f"{cfg.x.cpn_tag}_UL")
400434

401435
elif cfg.x.run == 3:
436+
electron_sf_campaign = {
437+
"2022postEE": "2022Re-recoE+PromptFG",
438+
"2022preEE": "2022Re-recoBCD",
439+
"2023postBPix": "2023PromptD",
440+
"2023preBPix": "2023PromptC",
441+
}[cfg.x.cpn_tag]
442+
443+
cfg.x.electron_sf_names = ElectronSFConfig(
444+
correction="Electron-ID-SF",
445+
campaign=electron_sf_campaign,
446+
working_point="Tight",
447+
)
402448
# names of electron correction sets and working points
403449
# (used in the electron_sf producer)
404450
if cfg.x.cpn_tag == "2022postEE":
405-
# TODO: we need to use different SFs for control regions
451+
# TODO: we might need to use different SFs for control regions
406452
cfg.x.electron_sf_names = ("Electron-ID-SF", "2022Re-recoE+PromptFG", "Tight")
407453
elif cfg.x.cpn_tag == "2022preEE":
408454
cfg.x.electron_sf_names = ("Electron-ID-SF", "2022Re-recoBCD", "Tight")
409455

410456
# names of muon correction sets and working points
411457
# (used in the muon producer)
412-
# TODO: we need to use different SFs for control regions
413-
cfg.x.muon_sf_names = ("NUM_TightPFIso_DEN_TightID", f"{cfg.x.cpn_tag}")
414-
cfg.x.muon_id_sf_names = ("NUM_TightID_DEN_TrackerMuons", f"{cfg.x.cpn_tag}")
415-
cfg.x.muon_iso_sf_names = ("NUM_TightPFIso_DEN_TightID", f"{cfg.x.cpn_tag}")
458+
# TODO: we might need to use different SFs for control regions
459+
cfg.x.muon_id_sf_names = MuonSFConfig(
460+
correction="NUM_TightID_DEN_TrackerMuons",
461+
campaign=f"{cfg.x.cpn_tag}",
462+
)
463+
cfg.x.muon_iso_sf_names = MuonSFConfig(
464+
correction="NUM_TightPFIso_DEN_TightID",
465+
campaign=f"{cfg.x.cpn_tag}",
466+
)
416467

417468
# central trigger SF, only possible for SL
418469
if cfg.x.lepton_tag == "sl":
@@ -592,12 +643,12 @@ def add_external(name, value):
592643
value = DotDict.wrap(value)
593644
cfg.x.external_files[name] = value
594645

595-
json_mirror = "/afs/cern.ch/user/m/mfrahm/public/mirrors/jsonpog-integration-a332cfa"
646+
json_mirror = "/afs/cern.ch/user/m/mfrahm/public/mirrors/jsonpog-integration-cb90b1e8"
596647
if cfg.x.run == 2:
597648
# json_mirror = "/afs/cern.ch/user/m/mrieger/public/mirrors/jsonpog-integration-9ea86c4c"
598649
corr_tag = f"{cfg.x.cpn_tag}_UL"
599650
elif cfg.x.run == 3:
600-
corr_tag = f"{year}_Summer22{jerc_postfix}"
651+
corr_tag = f"{year}_Summer{year2}{jerc_postfix}"
601652

602653
# pileup weight correction
603654
add_external("pu_sf", (f"{json_mirror}/POG/LUM/{corr_tag}/puWeights.json.gz", "v1"))
@@ -608,24 +659,21 @@ def add_external(name, value):
608659
add_external("jet_veto_map", (f"{json_mirror}/POG/JME/{corr_tag}/jetvetomaps.json.gz", "v1"))
609660
# electron scale factors
610661
add_external("electron_sf", (f"{json_mirror}/POG/EGM/{corr_tag}/electron.json.gz", "v1"))
611-
add_external("electron_ss", (f"{json_mirror}/POG/EGM/{corr_tag}/electronSS.json.gz", "v1"))
662+
# add_external("electron_ss", (f"{json_mirror}/POG/EGM/{corr_tag}/electronSS.json.gz", "v1"))
612663
# muon scale factors
613664
add_external("muon_sf", (f"{json_mirror}/POG/MUO/{corr_tag}/muon_Z.json.gz", "v1"))
614665
# trigger_sf from Balduin
615-
# # files with uncertainties, not loadable because there are some NaNs in the json :/
616-
# trigger_sf_path = "/afs/desy.de/user/f/frahmmat/Projects/hh2bbww/data/software/trig_sf"
617-
# add_external("trigger_sf_ee", (f"{trigger_sf_path}/sf_ee+Ele50_CaloI+DoubleEle33_mli_lep_pt-trig_ids.json", "v1"))
618-
# add_external("trigger_sf_mm", (f"{trigger_sf_path}/sf_mm_mli_lep_pt-trig_ids.json", "v1"))
619-
# add_external("trigger_sf_mixed", (f"{trigger_sf_path}/sf_mixed+Ele50_CaloI+DoubleEle33_mli_lep_pt-trig_ids.json", "v1")) # noqa: E501
620-
621-
# files without uncertainties and with wrong triggers
622-
trigger_sf_path = "/nfs/dust/cms/user/letzerba/hh2bbww/data/cf_store/hbw_dl/cf.CalculateTriggerScaleFactors/c22post/nominal/calib__with_b_reg/sel__dl1_no_triggerV11__steps_no_trigger/prod__event_weightsV2__trigger_prodV2__pre_ml_catsV1__dl_ml_inputsV1/weight__ref_cut/datasets_4_10839b14e3/prod3/" # noqa: E501
623-
add_external("trigger_sf_ee", (f"{trigger_sf_path}/sf_ee_mli_lep_pt-trig_ids.json", "v1"))
624-
add_external("trigger_sf_mm", (f"{trigger_sf_path}/sf_mm_mli_lep_pt-trig_ids.json", "v1"))
625-
add_external("trigger_sf_mixed", (f"{trigger_sf_path}/sf_mixed_mli_lep_pt-trig_ids.json", "v1")) # noqa: E501
666+
667+
trigger_sf_path = f"{json_mirror}/data/trig_sf_v0"
668+
# add_external("trigger_sf_ee", (f"{trigger_sf_path}/sf_ee+Ele50_CaloI+DoubleEle33_mli_lep_pt-trig_ids_statanda.json", "v2")) # noqa: E501
669+
# add_external("trigger_sf_mm", (f"{trigger_sf_path}/sf_mm_mli_lep_pt-trig_ids_statanda.json", "v2")) # noqa: E501
670+
# add_external("trigger_sf_mixed", (f"{trigger_sf_path}/sf_mixed+Ele50_CaloI+DoubleEle33_mli_lep_pt-trig_ids_statanda.json", "v2")) # noqa: E501
671+
add_external("trigger_sf_ee", (f"{trigger_sf_path}/sf_ee_mli_lep_pt-trig_ids.json", "v2"))
672+
add_external("trigger_sf_mm", (f"{trigger_sf_path}/sf_mm_mli_lep_pt-trig_ids.json", "v2"))
673+
add_external("trigger_sf_mixed", (f"{trigger_sf_path}/sf_mixed_mli_lep_pt-trig_ids.json", "v2")) # noqa: E501
626674

627675
# btag scale factor
628-
add_external("btag_sf_corr", (f"{json_mirror}/POG/BTV/{corr_tag}/btagging.json.gz", "v1"))
676+
add_external("btag_sf_corr", (f"{json_mirror}/POG/BTV/{corr_tag}/btagging.json.gz", "v2"))
629677
# V+jets reweighting (derived for 13 TeV, custom json converted from ROOT, not centrally produced)
630678
# ROOT files (eej.root and aj.root) taken from here:
631679
# https://github.com/UHH2/2HDM/tree/ultra_legacy/data/ScaleFactors/VJetsCorrections
@@ -660,7 +708,7 @@ def add_external(name, value):
660708
}
661709

662710
# external files with more complex year dependence
663-
if year not in (2017, 2022):
711+
if year not in (2017, 2022, 2023):
664712
raise NotImplementedError("TODO: generalize external files to different years than 2017")
665713

666714
if year == 2017:
@@ -727,6 +775,8 @@ def add_external(name, value):
727775
# isolations for testing
728776
"Electron.{pfRelIso03_all,miniPFRelIso_all,mvaIso,mvaTTH}",
729777
"Muon.{pfRelIso03_all,miniPFRelIso_all,mvaMuID,mvaTTH}",
778+
# Taus
779+
"VetoTau.{pt,eta,phi,mass,decayMode}",
730780
# MET
731781
"{MET,PuppiMET}.{pt,phi}",
732782
# all columns added during selection using a ColumnCollection flag, but skip cutflow ones
@@ -769,6 +819,7 @@ def add_external(name, value):
769819
# sanity check: sometimes the process is not the same as the one in the dataset
770820
p1 = cfg.get_process("dy_m50toinf")
771821
p2 = campaign.get_dataset("dy_m50toinf_amcatnlo").processes.get_first()
822+
# if repr(p1) != repr(p2):
772823
if p1 != p2:
773824
raise Exception(f"Processes are not the same: {repr(p1)} != {repr(p2)}")
774825

0 commit comments

Comments
 (0)