Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
c8f56fa
Add campaigns for 2023 pre/postBPix.
jomatthi Jul 10, 2025
9fac55c
Update cmsdb.
jomatthi Jul 10, 2025
785ea7c
Add jetId selection.
jomatthi Aug 6, 2025
df2837c
Update cf.
jomatthi Aug 6, 2025
8346d45
Increase n_files of limited configs to 2 in order to test merging tasks.
jomatthi Aug 6, 2025
5a26867
Adapt law cfg for further alignment to mtt analysis, also fixing some…
jomatthi Aug 6, 2025
c824a12
Update json-pog mirror, fix broken jet calibrations and add metphi co…
jomatthi Aug 6, 2025
b3e6a77
Changing to cf categoriy_ids producer.
jomatthi Aug 6, 2025
e21d688
Little cleaning up of weights producers.
jomatthi Aug 6, 2025
b986bd6
Using PuppiMET for Run 3.
jomatthi Aug 6, 2025
0922904
Adapt configs to also process 2023 data. Used hbw analsyis for refere…
jomatthi Aug 6, 2025
fdbab69
Update cmsdb.
jomatthi Aug 6, 2025
7956927
Add met_phi to wp analysis.
jomatthi Sep 29, 2025
253b3f7
met_phi for real added.
jomatthi Sep 29, 2025
814a874
Update cmsdb.
jomatthi Sep 29, 2025
4c94fdc
Update columnflow:arrow_up:.
jomatthi Mar 23, 2026
5829aca
Update cmsdb.
jomatthi Mar 27, 2026
17f862b
Update/refactor wp config.
jomatthi Mar 27, 2026
a24a7c0
Update calibrator.
jomatthi Mar 27, 2026
88eba91
Update wp selection, now including the functionality to calculate nor…
jomatthi Mar 27, 2026
6ecc9b4
Fix wp plotting functions.
jomatthi Mar 27, 2026
030457c
Update cmsdb for alternative qcd samples.
jomatthi Jun 12, 2026
4a3c0e6
Update columnflow.
jomatthi Jun 12, 2026
2fcb7d2
Adapt law.cfg to columnflow/law change.
jomatthi Jun 12, 2026
ec124b4
Fix wp tasks, now we can actually plot a ROC curve etc. Also, made mi…
jomatthi Jun 12, 2026
7166573
Add flexible hist producers and normalized weights functionality.
jomatthi Jun 12, 2026
0746a2e
Fix tau32 categories.
jomatthi Jun 12, 2026
b265532
Small fixes.
jomatthi Jun 12, 2026
d0ca7ac
Add jet_met & btag jet features.
jomatthi Jun 12, 2026
814df5f
Update law cfg.
jomatthi Jun 12, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 28 additions & 4 deletions law.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ topsf.tasks.inference_v2.post_fit_shapes
topsf.tasks.inference_v2.impacts
topsf.tasks.inference_v2.plot_impacts
topsf.tasks.inference_v2.plot_shapes
topsf.tasks.corrections

[logging]

Expand All @@ -35,7 +36,7 @@ columnflow.columnar_util-perf: INFO

default_analysis: topsf.config.run3.analysis_sf.analysis_sf
default_config: run3_sf_2022_postEE_nano_v12
default_dataset: tt_fh_powheg
default_dataset: tt_sl_powheg
run3_analysis: topsf.config.run3.analysis_sf.analysis_sf
run3_config: run3_sf_2022_preEE_nano_v12

Expand All @@ -44,6 +45,7 @@ default_keep_reduced_events: True
production_modules: columnflow.production.{categories,normalization,mc_weight,pileup,processes,seeds}, columnflow.production.cms.{btag,electron,mc_weight,muon,pdf,pileup,scale,seeds}, topsf.production.{default,gen_top}
calibration_modules: columnflow.calibration.cms.{jets,met}, topsf.calibration.{default,skip_jec}
selection_modules: columnflow.selection.cms.{json_filter,met_filters}, topsf.selection.{default,categories,jet,bjet,fatjet,lepton,wp}
hist_production_modules: topsf.weights.default
ml_modules: columnflow.ml
inference_modules: columnflow.inference, topsf.inference.{default,uhh2}

Expand All @@ -58,7 +60,7 @@ skip_ensure_proxy: False

# some remote workflow parameter defaults
htcondor_flavor: $CF_HTCONDOR_FLAVOR
htcondor_share_software: False
htcondor_share_software: True
slurm_flavor: $CF_SLURM_FLAVOR
slurm_partition: $CF_SLURM_PARTITION

Expand All @@ -81,10 +83,11 @@ log_array_function_runtime: False
[outputs]

# list of all used file systems
wlcg_file_systems: wlcg_fs, wlcg_fs_cernbox, wlcg_fs_infn_redirector, wlcg_fs_global_redirector
wlcg_file_systems: wlcg_fs, wlcg_fs_desy, wlcg_fs_cernbox, wlcg_fs_desy_store, wlcg_fs_infn_redirector, wlcg_fs_global_redirector

# list of file systems used by columnflow.tasks.external.GetDatasetLFNs.iter_nano_files to
# look for the correct fs per nano input file (in that order)
# lfn_sources: local_desy_dcache, wlcg_fs_desy_store, wlcg_fs_infn_redirector, wlcg_fs_global_redirector
lfn_sources: local_desy_dcache, wlcg_fs_infn_redirector, wlcg_fs_global_redirector

# output locations per task family
Expand Down Expand Up @@ -122,6 +125,7 @@ task_cf.CreateDatacards: local

job_file_dir: $CF_JOB_BASE
job_file_dir_cleanup: False
job_file_dir_mkdtemp: sub_{{task_id}}_XXX


[local_fs]
Expand All @@ -139,6 +143,7 @@ base: /pnfs/desy.de/cms/tier2
# set this to your desired location, e.g.:
# base: root://eosuser.cern.ch/eos/user/$CF_CERN_USER_FIRSTCHAR/$CF_CERN_USER/$CF_STORE_NAME
base: &::wlcg_fs_desy::base
base_mkdir_rec: &::wlcg_fs_desy::webdav_base
create_file_dir: True
use_cache: $CF_WLCG_USE_CACHE
cache_root: $CF_WLCG_CACHE_ROOT
Expand All @@ -152,6 +157,23 @@ xrootd_base: root://dcache-cms-xrootd.desy.de:1094/pnfs/desy.de/cms/tier2/store/
gsiftp_base: gsiftp://dcache-cms-gridftp.desy.de/pnfs/desy.de/cms/tier2/store/user/$CF_CERN_USER/$CF_STORE_NAME
webdav_base: davs://dcache-cms-webdav-wan.desy.de:2880/pnfs/desy.de/cms/tier2/store/user/$CF_CERN_USER/$CF_STORE_NAME
base: &::webdav_base
base_filecopy: &::webdav_base
base_stat: &::webdav_base


[wlcg_fs_desy_store]

xrootd_base: root://dcache-cms-xrootd.desy.de:1094/pnfs/desy.de/cms/tier2
gsiftp_base: gsiftp://dcache-door-cms04.desy.de:2811/pnfs/desy.de/cms/tier2
webdav_base: davs://dcache-cms-webdav-wan.desy.de:2880/pnfs/desy.de/cms/tier2
base: &::webdav_base
use_cache: $CF_WLCG_USE_CACHE
cache_root: $CF_WLCG_CACHE_ROOT
cache_cleanup: $CF_WLCG_CACHE_CLEANUP
cache_max_size: 15GB
cache_global_lock: True
cache_mtime_patience: -1
rucio_report_access: T2_DE_DESY


[wlcg_fs_cernbox]
Expand All @@ -170,6 +192,7 @@ cache_cleanup: $CF_WLCG_CACHE_CLEANUP
cache_max_size: 15GB
cache_global_lock: True
cache_mtime_patience: -1
rucio_report_access: True


[wlcg_fs_global_redirector]
Expand All @@ -181,6 +204,7 @@ cache_cleanup: $CF_WLCG_CACHE_CLEANUP
cache_max_size: 15GB
cache_global_lock: True
cache_mtime_patience: -1
rucio_report_access: True


[versions]
Expand Down Expand Up @@ -213,7 +237,7 @@ cache_mtime_patience: -1

# for quick changes of the scheduler
local_scheduler: false
scheduler_host: naf-cms12.desy.de
scheduler_host: naf-cms14.desy.de
scheduler_port: 8082

[luigi_resources]
Expand Down
2 changes: 1 addition & 1 deletion modules/cmsdb
Submodule cmsdb updated 142 files
2 changes: 1 addition & 1 deletion modules/columnflow
Submodule columnflow updated 99 files
+22 −2 .all-contributorsrc
+4 −2 README.md
+2 −15 analysis_templates/cms_minimal/__cf_module_name__/columnflow_patches.py
+3 −6 analysis_templates/cms_minimal/__cf_module_name__/config/analysis___cf_short_name_lc__.py
+14 −2 analysis_templates/cms_minimal/law.cfg
+11 −1 bin/cf_inspect
+76 −22 bin/cf_inspect.py
+17 −2 bin/cf_remove_tmp
+18 −20 columnflow/__init__.py
+1 −0 columnflow/__version__.py
+77 −23 columnflow/calibration/__init__.py
+213 −607 columnflow/calibration/cms/egamma.py
+89 −42 columnflow/calibration/cms/jets.py
+236 −63 columnflow/calibration/cms/met.py
+227 −0 columnflow/calibration/cms/muon.py
+56 −63 columnflow/calibration/cms/tau.py
+1 −1 columnflow/calibration/util.py
+1 −4 columnflow/categorization/__init__.py
+225 −0 columnflow/cms_util.py
+527 −424 columnflow/columnar_util.py
+252 −44 columnflow/config_util.py
+345 −36 columnflow/hist_util.py
+24 −18 columnflow/histogramming/__init__.py
+50 −17 columnflow/histogramming/default.py
+87 −84 columnflow/inference/__init__.py
+517 −118 columnflow/inference/cms/datacard.py
+4 −3 columnflow/ml/__init__.py
+43 −16 columnflow/plotting/plot_all.py
+73 −17 columnflow/plotting/plot_functions_1d.py
+16 −10 columnflow/plotting/plot_functions_2d.py
+32 −22 columnflow/plotting/plot_ml_evaluation.py
+100 −39 columnflow/plotting/plot_util.py
+68 −13 columnflow/production/__init__.py
+4 −2 columnflow/production/categories.py
+396 −45 columnflow/production/cms/btag.py
+104 −57 columnflow/production/cms/dy.py
+77 −58 columnflow/production/cms/electron.py
+359 −0 columnflow/production/cms/gen_particles.py
+0 −90 columnflow/production/cms/gen_top_decay.py
+14 −5 columnflow/production/cms/jet.py
+49 −29 columnflow/production/cms/muon.py
+2 −0 columnflow/production/cms/pdf.py
+16 −8 columnflow/production/cms/pileup.py
+8 −2 columnflow/production/cms/scale.py
+13 −0 columnflow/production/cms/seeds.py
+79 −115 columnflow/production/cms/top_pt_weight.py
+2 −0 columnflow/production/matching.py
+409 −236 columnflow/production/normalization.py
+63 −9 columnflow/production/util.py
+10 −3 columnflow/reduction/__init__.py
+12 −0 columnflow/reduction/default.py
+15 −2 columnflow/reduction/util.py
+29 −24 columnflow/selection/__init__.py
+109 −0 columnflow/selection/cms/btag.py
+74 −39 columnflow/selection/cms/jets.py
+7 −3 columnflow/selection/cms/json_filter.py
+6 −4 columnflow/selection/cms/met_filters.py
+3 −1 columnflow/selection/empty.py
+8 −0 columnflow/selection/stats.py
+9 −9 columnflow/tasks/calibration.py
+1 −0 columnflow/tasks/cms/base.py
+82 −1 columnflow/tasks/cms/external.py
+176 −91 columnflow/tasks/cms/inference.py
+11 −24 columnflow/tasks/cutflow.py
+235 −125 columnflow/tasks/external.py
+155 −50 columnflow/tasks/framework/base.py
+73 −62 columnflow/tasks/framework/histograms.py
+194 −130 columnflow/tasks/framework/inference.py
+338 −148 columnflow/tasks/framework/mixins.py
+12 −12 columnflow/tasks/framework/plotting.py
+116 −44 columnflow/tasks/framework/remote.py
+56 −28 columnflow/tasks/framework/remote_bootstrap.sh
+146 −58 columnflow/tasks/histograms.py
+61 −12 columnflow/tasks/inspection.py
+39 −32 columnflow/tasks/ml.py
+240 −193 columnflow/tasks/plotting.py
+29 −9 columnflow/tasks/production.py
+82 −38 columnflow/tasks/reduction.py
+23 −29 columnflow/tasks/selection.py
+58 −23 columnflow/tasks/union.py
+2 −8 columnflow/tasks/yields.py
+5 −2 columnflow/types.py
+104 −2 columnflow/util.py
+1 −1 create_analysis.sh
+8 −1 law.cfg
+1 −1 modules/law
+1 −1 modules/order
+17 −7 sandboxes/_setup_venv.sh
+2 −2 sandboxes/cf.txt
+2 −2 sandboxes/cmssw_columnar.sh
+2 −2 sandboxes/cmssw_default.sh
+9 −9 sandboxes/columnar.txt
+9 −7 sandboxes/dev.txt
+1 −1 sandboxes/ml_tf.txt
+96 −44 setup.sh
+6 −9 tests/test_base_tasks.py
+1 −0 tests/test_columnar_util.py
+9 −5 tests/test_hist_util.py
+2 −32 tests/test_inference.py
198 changes: 167 additions & 31 deletions topsf/calibration/default.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,82 +4,218 @@
Calibration methods.
"""
import functools
import law

from columnflow.calibration import Calibrator, calibrator
from columnflow.calibration.cms.jets import jets_ak4, jets_ak8
from columnflow.calibration.cms.jets import jec_ak4, jer_ak4, jec_ak8, jer_ak8
from columnflow.calibration.cms.met import met_phi
from columnflow.production.cms.mc_weight import mc_weight
from columnflow.production.cms.jet import msoftdrop
from columnflow.production.cms.seeds import deterministic_seeds
from columnflow.util import maybe_import
from columnflow.columnar_util import set_ak_column
from columnflow.production.cms.jet import jet_id, fatjet_id

from topsf.calibration.jets import (
jet_lepton_cleaner,
jec_subjets,
# jer_subjets
jer_subjets
)
from topsf.util import has_tag, record_calls

logger = law.logger.get_logger(__name__)

np = maybe_import("numpy")
ak = maybe_import("awkward")

set_ak_column_f32 = functools.partial(set_ak_column, value_type=np.float32)

jec_ak4_Puppi = jec_ak4.derive(
"jec_ak4_Puppi",
cls_dict={
"met_name": "PuppiMET",
"raw_met_name": "RawPuppiMET",
}
)
jer_ak4_Puppi = jer_ak4.derive(
"jer_ak4_Puppi",
cls_dict={
"met_name": "PuppiMET",
"raw_met_name": "RawPuppiMET",
}
)

jec_ak8_Puppi = jec_ak8.derive(
"jec_ak8_Puppi",
cls_dict={
"propagate_met": False,
"met_name": "DO_NOT_USE",
"raw_met_name": "DO_NOT_USE",
},
)

jer_ak8_Puppi = jer_ak8.derive(
"jer_ak8_Puppi",
cls_dict={
"propagate_met": False,
"met_name": "DO_NOT_USE",
"raw_met_name": "DO_NOT_USE",
}
)

jec_subjets_Puppi = jec_subjets.derive(
"jec_subjets_Puppi",
cls_dict={
"propagate_met": False,
"met_name": "DO_NOT_USE",
"raw_met_name": "DO_NOT_USE",
}
)

jer_subjets_Puppi = jer_subjets.derive(
"jer_subjets_Puppi",
cls_dict={
"propagate_met": False,
"met_name": "DO_NOT_USE",
"raw_met_name": "DO_NOT_USE",
}
)


@calibrator(
uses={
mc_weight,
deterministic_seeds,
jet_lepton_cleaner,
jets_ak4,
jets_ak8,
jec_subjets,
# jer_subjets,
msoftdrop,
"Muon.pt", "Muon.tunepRelPt",
},
produces={
mc_weight,
deterministic_seeds,
jet_lepton_cleaner,
jets_ak4,
jets_ak8,
jec_subjets,
# jer_subjets,
msoftdrop,
"Muon.pt", "Muon.rawPt",
},
)
def default(self: Calibrator, events: ak.Array, **kwargs) -> ak.Array:
events = self[jet_lepton_cleaner](events, **kwargs) # set Jet.pt to raw Pt -> run before jets (JER) calibrator
if self.dataset_inst.is_mc:
events = self[mc_weight](events, **kwargs)
run_list = []
with record_calls(self, run_list):
# highPt muons: use tuneP pT
events = set_ak_column_f32(events, "Muon.rawPt", events.Muon.pt)
events = set_ak_column_f32(events, "Muon.pt", events.Muon.tunepRelPt * events.Muon.pt)
logger.info_once(
"Finished recalculating muon pt with tuneP for highPt muons. Stored original pt in Muon.rawPt."
)
if self.dataset_inst.is_mc:
events = self[mc_weight](events, **kwargs)
events = self[deterministic_seeds](events, **kwargs)

events = self[jet_lepton_cleaner](events, **kwargs) # set Jet.pt to raw Pt -> run before jets (JER) calibrator
# run JEC calibrators for AK4 and AK8 jets
# fake subjet area column by setting it to an array with the same structure as the subjet pt column containing 0.5
# (needed to be able to use same code as for top-level AK4/AK8 jets, as the producer formally requires an `area`
# column, despite not actually using it)
events = set_ak_column_f32(events, "SubJet.area", 0.5 * ak.ones_like(events.SubJet.pt))
if self.config_inst.x.year == 2024:
events = self[jec_ak4_Puppi](events, **kwargs)
events = self[jec_ak8_Puppi](events, **kwargs)
events = self[jec_subjets_Puppi](events, **kwargs)
if self.dataset_inst.is_mc:
events = self[jer_ak4_Puppi](events, **kwargs)
events = self[jer_ak8_Puppi](events, **kwargs)
# events = self[jer_subjets_Puppi](events, **kwargs)
else:
events = self[jec_ak4](events, **kwargs)
events = self[jec_ak8](events, **kwargs)
events = self[jec_subjets](events, **kwargs)
if self.dataset_inst.is_mc:
events = self[jer_ak4](events, **kwargs)
events = self[jer_ak8](events, **kwargs)
# events = self[jer_subjets](events, **kwargs)

events = self[msoftdrop](events, **kwargs)
if self.config_inst.x.year in {2022, 2023}:
events = self[met_phi](events, **kwargs)
elif self.config_inst.x.year == 2024:
logger.warning_once("met_phi calibrator not run for 2024 config, as it is not yet available.")
else:
raise ValueError(f"Unsupported year {self.config_inst.x.year} in default calibrator")

if not has_tag("skip_jet_ids", self.config_inst, self.dataset_inst, operator=any):
logger.debug("Recalulating (fat)jet IDs.")
events = self[jet_id](events, **kwargs)
events = self[fatjet_id](events, **kwargs)

logger.info_once(
"Finished default calibration steps:\n" +
"\n".join(run_list)
)

events = self[jets_ak4](events, **kwargs) # call_force ?
events = self[jets_ak8](events, **kwargs) # call_force ?

events = self[deterministic_seeds](events, **kwargs)

# fake subjet area column by setting it to an array with the same structure as the subjet pt column containing 0.5
# (needed to be able to use same code as for top-level AK4/AK8 jets, as the producer formally requires an `area`
# column, despite not actually using it)
events = set_ak_column_f32(events, "SubJet.area", 0.5 * ak.ones_like(events.SubJet.pt))
return events

events = self[jec_subjets](events, **kwargs)
# if self.dataset_inst.is_mc:
# events = self[jer_subjets](events, **kwargs)
events = self[msoftdrop](events, **kwargs)

return events
@default.init
def default_init(self: Calibrator) -> None:
# add met_phi only for 2022/23 configs
if self.config_inst.x.year in {2022, 2023}:
self.uses |= {
met_phi,
jec_ak4,
jec_ak8,
jer_ak4,
jer_ak8,
jec_subjets,
jer_subjets,
}
self.produces |= {
met_phi,
jec_ak4,
jec_ak8,
jer_ak4,
jer_ak8,
jec_subjets,
jer_subjets,
}
elif self.config_inst.x.year == 2024:
self.uses |= {
jec_ak4_Puppi,
jec_ak8_Puppi,
jer_ak4_Puppi,
jer_ak8_Puppi,
jec_subjets_Puppi,
jer_subjets_Puppi,
}
self.produces |= {
jec_ak4_Puppi,
jec_ak8_Puppi,
jer_ak4_Puppi,
jer_ak8_Puppi,
jec_subjets_Puppi,
jer_subjets_Puppi,
}

if not has_tag("skip_jet_ids", self.config_inst, self.dataset_inst, operator=any):
self.uses |= {
jet_id,
fatjet_id,
}
self.produces |= {
jet_id,
fatjet_id,
}


@calibrator(
uses={mc_weight, deterministic_seeds, jets_ak4, jets_ak8},
produces={mc_weight, deterministic_seeds, jets_ak4, jets_ak8},
uses={mc_weight, deterministic_seeds},
produces={mc_weight, deterministic_seeds},
)
def no_jet_cleaning(self: Calibrator, events: ak.Array, **kwargs) -> ak.Array:
if self.dataset_inst.is_mc:
events = self[mc_weight](events, **kwargs)

events = self[jets_ak4](events, **kwargs)
events = self[jets_ak8](events, **kwargs) # call_force ?
# events = self[jets_ak4](events, **kwargs)
# events = self[jets_ak8](events, **kwargs) # call_force ?
events = self[deterministic_seeds](events, **kwargs)

return events
10 changes: 8 additions & 2 deletions topsf/calibration/jets.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,10 @@ def jet_lepton_cleaner(self: Calibrator, events: ak.Array, **kwargs) -> ak.Array

# revert JEC for jet pt and jet mass,
# set correction factor to 0
events = set_ak_column(events, "Jet.pt", events.Jet.pt * (1 - events.Jet.rawFactor))
events = set_ak_column(events, "Jet.mass", events.Jet.mass * (1 - events.Jet.rawFactor))
raw_pt = events.Jet.pt * (1 - events.Jet.rawFactor)
raw_mass = events.Jet.mass * (1 - events.Jet.rawFactor)
events = set_ak_column(events, "Jet.pt", raw_pt)
events = set_ak_column(events, "Jet.mass", raw_mass)
events = set_ak_column(events, "Jet.rawFactor", 0)

# build jet lorentz vectors
Expand Down Expand Up @@ -158,6 +160,10 @@ def jet_lepton_cleaner(self: Calibrator, events: ak.Array, **kwargs) -> ak.Array
value = ak.fill_none(ak.nan_to_none(getattr(jet_lv, var)), 0.0)
events = set_ak_column(events, f"Jet.{var}", value)

# do not set to updated raw factor as out dated JECs are already reverted
# raw_factor = ak.nan_to_num(1 - raw_pt / events.Jet.pt, nan=0.0)
# events = set_ak_column(events, "Jet.rawFactor", raw_factor)

return events


Expand Down
Loading