euromod_linking.scenarios¶
Running a linking scenario: validate, transform, (optionally) simulate.
Two entry points:
apply_scenario(system, data, scenario)The core. Turns external-model shocks into transformed EUROMOD input — the counterfactual and, when a methodology restructures rows, a matching baseline built on the same rows. Executes nothing.
run_scenario(system, scenario, input_path=...)Convenience: loads the dataset, applies the scenario and runs both halves through
System.run().
Applications that need caching, retries or their own response envelope build on apply_scenario and run the frames themselves; that is why nothing here knows about caches or run ids.
The API exposes shocks, not methodologies: each shock channel in the table is
dispatched to the methodology that consumes it, and the resolved methods are
reported back. A table carrying several channels is handled by several methods,
run one after another in their declared stage order — see
euromod_linking.registry for why the order is theirs and not the
caller’s. An optional methodology pin exists only for exact reproduction or
disambiguation.
Constants semantics:
scenario
constantsare context, applied to BOTH runs, so the delta isolates the shock;shock records with
channel: constantare part of the shock and apply to the COUNTERFACTUAL only (metric = constant name, period = constant group, op must beset). A constants-only shock table needs no methodology.
Errors are exceptions (ScenarioError carrying .problems, RunError), not error dicts — callers that need a machine-readable envelope build it themselves.
Exceptions¶
The methodology transformed the input but the engine produced identical |
|
A scenario cannot be applied. |
Functions¶
|
Transform input microdata according to a scenario. Executes nothing. |
|
Weighted people matched by each distinct shock cell. |
|
Validate everything that does not need the model or the data. |
|
Canonical scenario hash for a result-cache key. Shocks are represented by |
|
The records a method is handed: those of the channels it consumes. |
|
The one |
|
Add-ons and extension switches the run needs: every method's own |
|
Apply a scenario and run both halves through |
Module Contents¶
- exception euromod_linking.scenarios.NoEffectError[source]¶
The methodology transformed the input but the engine produced identical output — the run is invalid.
Emphatically not “the reform has no impact”: it means the model never acted on the transformation (typically a required add-on or switch is not available for this country/system).
- exception euromod_linking.scenarios.ScenarioError(problems: list[str])[source]¶
A scenario cannot be applied.
.problemslists every problem found, not just the first, so one call surfaces everything to fix.- problems¶
- euromod_linking.scenarios.apply_scenario(system, data, scenario: dict, *, dataset_name: str | None = None, validate_only: bool = False) dict[source]¶
Transform input microdata according to a scenario. Executes nothing.
Returns a dict with:
counterfactual the transformed input baseline the matching baseline (same rows) when a methodology restructures rows, else None — run the untouched `data` diagnostics the methods' account of what they did: flat for one method, nested under each method's name (with ``order``) for several methodology the resolved reference, e.g. "lma_labour_alignment" or "scale_variables+lma_labour_alignment" (run order) methods, stages what ran, and in which order constants {(name, group): value} for the counterfactual run context_constants ... applied to BOTH runs addons, extensions what the runs must activate compatibility what each method needs from the model and whether this model has it: a list of CompatibilityReport, one per method (None entries when the model could not be inspected)Several methods run in stage order, each on the frame the previous one produced. The paired
baselineis the one built by the last method that restructured rows, on the frame it received — so it carries every earlier stage’s changes, which is what keeps it row-aligned with the counterfactual.Raises ScenarioError (with .problems) when the scenario cannot be applied.
- euromod_linking.scenarios.cell_population(data, population_shocks) dict[source]¶
Weighted people matched by each distinct shock cell.
Surfacing this before a run is what turns a mistyped cell (
deh=34) into a visible zero rather than a shock that silently hits nobody.
- euromod_linking.scenarios.check_scenario(scenario: dict) dict[source]¶
Validate everything that does not need the model or the data.
Structure, shock resolution, methodology dispatch, declared params and the methods’ contracts. Separated so a caller can reject a malformed scenario without paying to load a model. Raises ScenarioError with .problems; returns the resolved pieces for apply_scenario.
- euromod_linking.scenarios.fingerprint(scenario: dict, shock_table_id: str, methodology: str, code_fingerprint: str = '') str[source]¶
Canonical scenario hash for a result-cache key. Shocks are represented by the table’s content id, so inline vs stored vs re-ingested identical shocks hit the same cache entry. Excludes the free-text ‘name’ label.
methodologyis the run’s method reference (registry.pipeline_name) andcode_fingerprintitsregistry.pipeline_fingerprint: both carry the order the methods ran in, which is part of what the run did.
- euromod_linking.scenarios.own_shocks(population_shocks, spec)[source]¶
The records a method is handed: those of the channels it consumes.
- euromod_linking.scenarios.params_schema(specs) dict[source]¶
The one
paramsschema a scenario is validated against: the union of its methods’ schemas.paramsare scenario semantics — which external-model period, a reporting threshold — and one scenario has one set of them however many methods it runs, so every method reads the sameperiod. The union keepsadditionalProperties: false, which is what blocks methodology knobs: a param no method declares is still an error.
- euromod_linking.scenarios.run_arguments(scenario: dict, specs) tuple[list, list][source]¶
Add-ons and extension switches the run needs: every method’s own requirements (with
{cc}resolved) plus anything the scenario adds.
- euromod_linking.scenarios.run_scenario(system, scenario: dict, *, input_path: str, paired_baseline: bool = False) dict[source]¶
Apply a scenario and run both halves through
System.run().paired_baselineruns the baseline on the counterfactual’s own rows, so the two outputs are observation-paired — needed by any baseline-vs-reform comparison that works row by row, such as one applying a fixed poverty line or baseline-defined decile groups.Returns the apply_scenario dict with
baseline_outputandcounterfactual_outputframes added. Raises NoEffectError when the methodology changed people but the outputs are identical.