Configuration system¶
FLAF's behaviour — which datasets exist, which corrections apply, where outputs go, which processes make up the analysis — is driven by YAML configuration. This page explains how the configuration is assembled. For how to change specific things, see the Configuration guide.
The implementation lives in FLAF/Common/Setup.py.
Four layers, merged in order¶
When you run a task with --era <era>, FLAF loads configuration from four directories, in
this order:
config_path_order = [
"<analysis>/FLAF/config", # 1. framework defaults (all analyses)
"<analysis>/FLAF/config/<era>", # 2. framework defaults for this era
"<analysis>/config", # 3. analysis-wide settings
"<analysis>/config/<era>", # 4. analysis settings for this era
]
Think of it as general → specific: the framework provides sensible cross-analysis defaults (layer 1–2), and each analysis overrides or extends them (layer 3–4). The per-era directories let 2022 and 2023 differ without duplicating everything.
Each kind of configuration is looked up under its own file name in all four directories (a
missing file is skipped): datasets.yaml, processes.yaml, phys_models.yaml, weights.yaml,
plot/histograms.yaml. The global settings are special: in every directory FLAF reads
global.yaml and then user_custom.yaml, and a file passed with --user-custom comes last
({ana} below is the analysis checkout, $ANALYSIS_PATH).
flowchart TD
L1["1. {ana}/FLAF/config<br/>global.yaml, user_custom.yaml"] --> L2["2. {ana}/FLAF/config/{era}<br/>global.yaml, user_custom.yaml"]
L2 --> L3["3. {ana}/config<br/>global.yaml, user_custom.yaml"]
L3 --> L4["4. {ana}/config/{era}<br/>global.yaml, user_custom.yaml"]
L4 --> UC["--user-custom FILE (last)"]
UC --> P["Texts concatenated, parsed once:<br/>a repeated top-level key<br/>replaces the earlier value"]
P --> C["--customisations overrides<br/>single values of the result"]
The framework layers come from the analysis's FLAF submodule
Layers 1–2 are always read from <analysis>/FLAF/config — also when FLAF_PATH points at a
dev-overlay copy of FLAF. An edit to
config/ in the overlay copy is therefore not seen by Setup.
How values combine¶
FLAF does not merge values key by key. For each kind of configuration it concatenates the text of all the files it finds, in the order above, and parses the result as one YAML document. Two consequences follow:
- A repeated top-level key replaces the earlier value wholesale — scalars, lists and nested
maps alike. The last file that sets a key has the final say. An era-level
corrections:block, for example, replaces the analysis-wide one entirely instead of adding to it, so it has to repeat every entry it wants to keep — or inherit them with an anchor, below. -
YAML anchors work across files. An anchor defined in an earlier file can be referenced in a later one. Top-level keys starting with
.are dropped after parsing, so an analysis keeps shared blocks under such keys — e.g. the.DY_processors: &DY_processorsdefinitions inconfig/processes.yaml, used asprocessors: *DY_processorsinconfig/<era>/processes.yaml. An era file can also override part of a top-level block with a merge key, so that what it does not override stays in step with the analysis-wide block:# config/global.yaml corrections: &corrections_default pu: { ... } btag: { ..., tagger: particleNet } # config/Run3_2024/global.yaml corrections: <<: *corrections_default btag: { ..., tagger: UParTAK4 } # replaces the whole btag entry, the rest is inheritedThe merge is one level deep: an overridden entry (
btaghere) is replaced as a whole. Setup also readsglobal.yamlfrom the same four directories for the era named inreuse_mc_from_era(to take itsshared_mc), so the alias resolves there too. Code that parses an era'sglobal.yamlon its own, outsideConfig, cannot resolve it.
Datasets combine across layers only because each dataset is its own top-level key: SM
backgrounds and data live in the framework's FLAF/config/<era>/datasets.yaml, signals and custom
samples in the analysis's config/<era>/datasets.yaml, and after loading all of them are
available together. A dataset name defined in both files keeps the analysis's entry. See
Datasets.
The objects you may meet in code¶
Class (in Common/Setup.py) |
Role |
|---|---|
Config |
Loads one logical config (e.g. "datasets") from the four directories as described above. Accessed like a dict: cfg["key"] (raises KeyError when the key is missing), cfg.get("key", default). |
Setup |
The master configuration object: the global parameters, the selected datasets and processes, the physics model and more. It expands the meta-processes while loading. |
PhysicsModel |
Classifies each process as background, signal or data, and keeps the list of concrete processes each meta-process expanded into. |
Setup.getGlobal(...) returns a cached instance: one per combination of analysis path, era,
version, --process/--dataset/--model selection, --customisations and --user-custom. Every
task of a run with the same parameters therefore sees the same configuration.
The key configuration files¶
| File | Lives in | Holds |
|---|---|---|
user_custom.yaml |
analysis config/ |
Your personal, git-ignored settings: storage, model, options. Guide. |
global.yaml |
FLAF/config/<era>/, analysis config/ and config/<era>/ (FLAF/config/ itself has none) |
Global settings: anaTuple/histTuple definitions, corrections, payload producers, signal types, the NanoAOD source. For 2024+ this also holds weight_base_branch (weight_base for a single year, weight_base_cmb for the 24+25+26 combination). shared_mc is declared on Run3_2024 and inherited when reuse_mc_from_era is set. |
datasets.yaml |
FLAF/config/<era>/ and analysis config/<era>/ |
Dataset (sample) definitions. Guide. |
processes.yaml |
analysis config/<era>/ (shared YAML anchors in analysis config/processes.yaml) |
Logical processes built from datasets. Guide. |
phys_models.yaml |
analysis config/ |
Which processes are background/signal/data for a model. Guide. |
crossSections13p6TeV.yaml |
FLAF/config/ |
Cross-section values referenced by datasets; each era selects its file with crossSectionsFile in global.yaml. |
Validate your config without running the pipeline
Loading Setup.py for an era is exactly what the test-setup-loading CI check does — it
catches typos and missing references early. The same check runs locally from the analysis
checkout with python FLAF/test/test_setup_loading.py Run3_2022 Run3_2024 (any list of eras);
if it loads, the config is internally consistent.
user_custom.yaml is part of the merge too¶
Your config/user_custom.yaml adds personal values (storage locations, phys_model, options like
compute_unc_variations). It is read right after config/global.yaml, so it overrides the
framework and analysis-wide settings — but config/<era>/global.yaml is read after it and
wins for every top-level key it sets (e.g. corrections, nanoAODVersions, met_type). For a
single run you can layer an extra file on top with --user-custom <path>, which is loaded last
and therefore wins over every file — handy for one-off tests without editing your
user_custom.yaml. See
user_custom.yaml.