policyengine 6.2.3__tar.gz → 6.2.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {policyengine-6.2.3 → policyengine-6.2.4}/CHANGELOG.md +7 -0
- {policyengine-6.2.3/src/policyengine.egg-info → policyengine-6.2.4}/PKG-INFO +1 -1
- {policyengine-6.2.3 → policyengine-6.2.4}/docs/microsim.md +39 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/pyproject.toml +1 -1
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/data/bundle/manifest.json +10 -10
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/data/bundle/uk.trace.tro.jsonld +5 -5
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/data/bundle/us.trace.tro.jsonld +5 -5
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/tax_benefit_models/common/model_version.py +15 -0
- policyengine-6.2.4/src/policyengine/tax_benefit_models/uk/datasets.py +404 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/tax_benefit_models/uk/model.py +138 -8
- {policyengine-6.2.3 → policyengine-6.2.4/src/policyengine.egg-info}/PKG-INFO +1 -1
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine.egg-info/SOURCES.txt +1 -0
- policyengine-6.2.4/tests/test_uk_year_file_data_year.py +624 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/uv.lock +1 -1
- policyengine-6.2.3/src/policyengine/tax_benefit_models/uk/datasets.py +0 -270
- {policyengine-6.2.3 → policyengine-6.2.4}/.claude/policyengine-guide.md +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/.claude/quick-reference.md +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/.github/CONTRIBUTING.md +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/.github/bump_version.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/.github/capture-version.sh +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/.github/changelog_template.md +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/.github/check-changelog.sh +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/.github/copilot-instructions.md +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/.github/dispatch-policyengine-release.sh +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/.github/fetch_version.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/.github/get-changelog-diff.sh +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/.github/has-functional-changes.sh +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/.github/is-version-number-acceptable.sh +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/.github/publish-git-tag.sh +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/.github/wait-for-pypi.sh +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/.github/workflows/draft-pdf.yml +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/.github/workflows/pr_code_changes.yaml +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/.github/workflows/pr_docs_changes.yaml +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/.github/workflows/push.yaml +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/.gitignore +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/.python-version +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/AGENTS.md +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/CITATION.cff +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/CLAUDE.md +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/CODE_OF_CONDUCT.md +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/CONTRIBUTING.md +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/LICENSE +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/Makefile +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/README.md +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/architecture.png +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/architecture.svg +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/changelog.d/.gitkeep +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/docs/.gitignore +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/docs/_generator/README.md +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/docs/_generator/build_reference.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/docs/_quarto.yml +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/docs/bundles.md +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/docs/countries.md +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/docs/data-publishing-design.md +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/docs/decile-impact-spec.md +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/docs/dev.md +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/docs/engineering/runbooks/build-m-us-populace-certification.md +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/docs/engineering/runbooks/canonical-spm-development.md +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/docs/engineering/skills/README.md +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/docs/engineering/skills/data-certification.md +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/docs/engineering/skills/github-prs.md +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/docs/engineering/skills/repository-guidance.md +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/docs/examples.md +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/docs/getting-started.md +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/docs/households.md +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/docs/impact-analysis.md +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/docs/index.md +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/docs/methodology/index.md +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/docs/methodology/model-architecture.md +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/docs/methodology/us-health-costs.md +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/docs/outputs.md +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/docs/programs/index.md +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/docs/programs/us-chip.md +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/docs/reference/index.md +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/docs/reforms.md +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/docs/regions.md +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/docs/release-bundles.md +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/docs/run-records.md +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/docs/trace-case-study.md +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/docs/visualisation.md +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/examples/belgium_axiom_pilot.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/examples/employment_income_variation_uk.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/examples/employment_income_variation_us.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/examples/household_impact_example.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/examples/income_bands_uk.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/examples/income_distribution_us.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/examples/paper_repro_uk.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/examples/policy_change_uk.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/examples/speedtest_us_simulation.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/examples/us_budgetary_impact.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/paper-preview.html +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/paper.bib +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/paper.md +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/scripts/bundle.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/scripts/certify_data_release.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/scripts/check_data_staleness.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/scripts/check_native_spm_loading.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/scripts/check_release_credentials.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/scripts/export_bundle_release_assets.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/scripts/generate_bundle_artifacts.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/scripts/generate_trace_tros.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/scripts/prepare_package_bundle_update.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/scripts/release_lock.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/scripts/spm_bundle.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/setup.cfg +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/__init__.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/bundle.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/cli.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/core/__init__.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/core/cache.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/core/dataset.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/core/dynamic.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/core/output.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/core/parameter.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/core/parameter_node.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/core/parameter_value.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/core/policy.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/core/region.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/core/run_record.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/core/scoping_strategy.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/core/simulation.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/core/spm.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/core/tax_benefit_model.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/core/tax_benefit_model_version.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/core/variable.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/countries/__init__.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/countries/uk/__init__.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/countries/uk/regions.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/countries/us/__init__.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/countries/us/data/__init__.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/countries/us/data/districts.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/countries/us/data/places.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/countries/us/data/states.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/countries/us/regions.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/data/__init__.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/data/schemas/trace_tro.schema.json +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/data/uk_geography_assets.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/derivations/__init__.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/derivations/narrate.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/derivations/trace.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/graph/__init__.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/graph/extractor.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/graph/graph.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/outputs/__init__.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/outputs/aggregate.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/outputs/change_aggregate.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/outputs/cliff_impact.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/outputs/congressional_district_impact.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/outputs/constituency_impact.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/outputs/decile_analysis.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/outputs/decile_grouping.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/outputs/decile_impact.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/outputs/extra_variables.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/outputs/inequality.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/outputs/intra_decile_impact.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/outputs/labor_supply_response.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/outputs/local_authority_impact.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/outputs/poverty.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/outputs/program_statistics.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/outputs/uk_geography_assets.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/outputs/uk_geography_impact.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/provenance/__init__.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/provenance/bundle_validation.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/provenance/certification.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/provenance/dataset_materialization.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/provenance/manifest.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/provenance/pyproject_pins.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/provenance/spm_configuration.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/provenance/trace.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/provenance/verify.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/provenance/zenodo.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/results/__init__.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/results/schema.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/results/trace_tro.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/results/tracking.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/tax_benefit_models/be/__init__.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/tax_benefit_models/be/datasets.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/tax_benefit_models/be/model.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/tax_benefit_models/common/__init__.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/tax_benefit_models/common/axes.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/tax_benefit_models/common/extra_variables.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/tax_benefit_models/common/household.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/tax_benefit_models/common/reform.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/tax_benefit_models/common/result.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/tax_benefit_models/uk/__init__.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/tax_benefit_models/uk/analysis.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/tax_benefit_models/uk/household.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/tax_benefit_models/us/__init__.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/tax_benefit_models/us/analysis.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/tax_benefit_models/us/datasets.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/tax_benefit_models/us/household.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/tax_benefit_models/us/legacy_inputs.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/tax_benefit_models/us/model.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/tax_benefit_models/us/spm.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/utils/__init__.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/utils/dates.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/utils/design.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/utils/entity_utils.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/utils/errors.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/utils/hashing.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/utils/household_validation.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/utils/parameter_labels.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/utils/parametric_reforms.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine/utils/plotting.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine.egg-info/dependency_links.txt +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine.egg-info/entry_points.txt +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine.egg-info/requires.txt +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/src/policyengine.egg-info/top_level.txt +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/__init__.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/conftest.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/fixtures/__init__.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/fixtures/filtering_fixtures.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/fixtures/household_calculator_snapshots/uk_couple_two_kids.json +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/fixtures/household_calculator_snapshots/uk_model_surface.json +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/fixtures/household_calculator_snapshots/uk_single_adult_employment_income.json +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/fixtures/household_calculator_snapshots/uk_single_adult_no_income.json +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/fixtures/household_calculator_snapshots/uk_single_parent_one_child.json +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/fixtures/household_calculator_snapshots/us_married_two_kids_high_income.json +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/fixtures/household_calculator_snapshots/us_model_surface.json +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/fixtures/household_calculator_snapshots/us_single_adult_employment_income.json +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/fixtures/household_calculator_snapshots/us_single_adult_no_income.json +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/fixtures/household_calculator_snapshots/us_single_parent_one_child.json +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/fixtures/parameter_labels_fixtures.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/fixtures/parametric_reforms_fixtures.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/fixtures/poverty_by_demographics_fixtures.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/fixtures/region_fixtures.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/fixtures/release_tros/README.md +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/fixtures/release_tros/country-models.lock.toml +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/fixtures/release_tros/manifest.json +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/fixtures/release_tros/us-release_manifest.json +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/fixtures/release_tros/us.trace.tro.jsonld +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/fixtures/spm_development.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/fixtures/us_reform_fixtures.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/fixtures/variable_label_fixtures.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_aggregate.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_be_axiom_pilot.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_budgetary_impact.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_bump_version.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_bundle.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_bundle_metadata.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_cache.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_certify_data_release.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_change_aggregate.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_cliff_impact.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_cliff_impact_analysis.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_congressional_district_impact.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_constituency_impact.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_dataset_materialization.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_dataset_persistence.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_dataset_runtime.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_dataset_source.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_decile_grouping.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_derivations.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_dict_reforms_on_simulation.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_entity_mapping.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_entity_utils.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_entity_utils_characterization.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_errors.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_extra_variables.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_filtering.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_generate_trace_tros.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_graph/__init__.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_graph/conftest.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_graph/test_extractor.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_household_calculator_snapshot.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_household_impact.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_inequality.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_intra_decile_impact.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_labor_supply_response.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_local_authority_impact.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_manifest_version_mismatch.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_models.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_pandas3_compatibility.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_parameter_labels.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_parameter_nodes.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_parameter_values.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_parametric_reforms.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_poverty.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_poverty_by_demographics.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_poverty_run.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_preservation_mirror.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_program_statistics.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_pyproject_pins.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_region.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_region_group_strategy.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_release_credentials.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_release_lock.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_release_manifests.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_release_tro_generation.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_results.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_run_record.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_scoping_strategy.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_small_follow_ups.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_spm_bundle_bootstrap.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_spm_bundle_tooling.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_spm_decile.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_spm_development_authentication.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_spm_household.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_spm_model.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_spm_selection.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_spm_selection_schema.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_trace_tro.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_trace_tro_verify.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_uk_analysis.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_uk_geography_assets.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_uk_program_statistics.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_uk_regions.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_us_legacy_inputs.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_us_legacy_inputs_integration.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_us_long_term_datasets.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_us_microsim_structural_reforms.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_us_native_alignment.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_us_native_hdf_weights.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_us_program_statistics.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_us_reform_application.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_us_regions.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_variable_labels.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_variable_metadata.py +0 -0
- {policyengine-6.2.3 → policyengine-6.2.4}/tests/test_zenodo_mirror.py +0 -0
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
## [6.2.4] - 2026-10-09
|
|
2
|
+
|
|
3
|
+
### Fixed
|
|
4
|
+
|
|
5
|
+
- UK population runs now anchor the State Pension on the survey year their data was projected from, as policyengine-uk does, so a run of a UK year file matches policyengine-uk on the certified dataset, with or without a reform. Before, it took the projected year as the survey year: the State Pension was uprated by CPI rather than the triple lock, and State Pension rate reforms had no effect on it under policyengine-uk 2.102.3 and were understated under 2.123. Projected year files now also store the survey year's tables, which doubles their size. `ensure_datasets` regenerates year files from earlier releases and `load_datasets` refuses them; `Simulation.load()` refuses UK outputs saved by earlier releases, and `Simulation.ensure()` runs them again.
|
|
6
|
+
|
|
7
|
+
|
|
1
8
|
## [6.2.3] - 2026-10-09
|
|
2
9
|
|
|
3
10
|
### Changed
|
|
@@ -231,6 +231,45 @@ not need repository-specific download logic. Authentication or authorization
|
|
|
231
231
|
failures are reported directly and do not cause a retry against another
|
|
232
232
|
repository type.
|
|
233
233
|
|
|
234
|
+
### UK year files and the data year
|
|
235
|
+
|
|
236
|
+
`ensure_datasets` and `create_datasets` cut one file per requested year from
|
|
237
|
+
the projection policyengine-uk makes of the certified dataset. policyengine-uk
|
|
238
|
+
takes the first year of a dataset as observed data. Its State Pension formulas
|
|
239
|
+
split each person's reported State Pension against that year's legislated
|
|
240
|
+
rates, and scale the share to the simulated year's rates, which follow the
|
|
241
|
+
triple lock. The projection uprates the reported amount by CPI, so handing a
|
|
242
|
+
projected year's tables to policyengine-uk as observed data would make the
|
|
243
|
+
State Pension follow CPI instead.
|
|
244
|
+
|
|
245
|
+
Each projected year file therefore keeps its data year, `dataset.data_year`
|
|
246
|
+
(2024 for Enhanced FRS 2024–25), and that year's tables,
|
|
247
|
+
`dataset.data_year_data`. `Simulation.run()` projects the data year's tables
|
|
248
|
+
forward as policyengine-uk does, and uses the file's own tables for the
|
|
249
|
+
simulated year. A run of a year file then gives the same result, record by
|
|
250
|
+
record, as `policyengine_uk.Microsimulation` on the certified file, with or
|
|
251
|
+
without a reform. Keeping the data year's tables doubles a projected file: the
|
|
252
|
+
Enhanced FRS 2026 file is 226 MB, against 113 MB for its own tables. A dataset
|
|
253
|
+
built in memory without a data year is observed data for its own year, which
|
|
254
|
+
is how policyengine-uk treats a single-year dataset.
|
|
255
|
+
|
|
256
|
+
Row filtering applies to both sets of tables, matched by entity ID. Weight
|
|
257
|
+
replacement changes the simulated year's weights only; the data year and the
|
|
258
|
+
years between keep national weights. A row-filtered run is a simulation of the
|
|
259
|
+
region's households alone, so
|
|
260
|
+
variables that policyengine-uk calculates over every household in the
|
|
261
|
+
simulation are calculated over the region: income deciles, the relative
|
|
262
|
+
poverty median, and `shareholding`, which spreads corporate taxes across
|
|
263
|
+
households (PolicyEngine/policyengine.py#567). Variables of a person or
|
|
264
|
+
benefit unit that do not depend on those match the national run.
|
|
265
|
+
|
|
266
|
+
Year files written by earlier releases have no recorded data year.
|
|
267
|
+
`ensure_datasets` writes them again and `load_datasets` refuses them. A year
|
|
268
|
+
file opened directly, as `PolicyEngineUKDataset(filepath=...)`, is not
|
|
269
|
+
checked. A saved UK simulation output records the data year its run anchored
|
|
270
|
+
on; `Simulation.load()` refuses an output saved without one, and
|
|
271
|
+
`Simulation.ensure()` runs it again.
|
|
272
|
+
|
|
234
273
|
## Simulations
|
|
235
274
|
|
|
236
275
|
A `Simulation` needs a dataset, a tax-benefit model version, and optionally a policy (reform):
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
|
-
"bundle_version": "6.2.
|
|
2
|
+
"bundle_version": "6.2.4",
|
|
3
3
|
"citation": {
|
|
4
4
|
"publisher": "PolicyEngine",
|
|
5
|
-
"title": "PolicyEngine bundle 6.2.
|
|
5
|
+
"title": "PolicyEngine bundle 6.2.4",
|
|
6
6
|
"type": "software-bundle",
|
|
7
|
-
"version": "6.2.
|
|
7
|
+
"version": "6.2.4"
|
|
8
8
|
},
|
|
9
9
|
"countries": {
|
|
10
10
|
"uk": {
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"data_releases": {
|
|
18
18
|
"uk": {
|
|
19
19
|
"build_id": "policyengine-uk-data-1.56.16",
|
|
20
|
-
"bundle_id": "uk-6.2.
|
|
20
|
+
"bundle_id": "uk-6.2.4",
|
|
21
21
|
"certification": {
|
|
22
22
|
"built_with_model_git_sha": "12a1e028afeef08d8b2d74ee03fd9de3a78b2dd3",
|
|
23
23
|
"built_with_model_version": "2.89.2",
|
|
@@ -99,7 +99,7 @@
|
|
|
99
99
|
"version": "2.102.3",
|
|
100
100
|
"wheel_url": "https://files.pythonhosted.org/packages/37/e6/e8d9069d498f1510a1380f24a78e957902d01f00b10248c146d6710d5b37/policyengine_uk-2.102.3-py3-none-any.whl"
|
|
101
101
|
},
|
|
102
|
-
"policyengine_version": "6.2.
|
|
102
|
+
"policyengine_version": "6.2.4",
|
|
103
103
|
"region_datasets": {
|
|
104
104
|
"national": {
|
|
105
105
|
"path_template": "enhanced_frs_2024_25.h5"
|
|
@@ -112,7 +112,7 @@
|
|
|
112
112
|
},
|
|
113
113
|
"us": {
|
|
114
114
|
"build_id": "populace-us-2024-spm-20260915",
|
|
115
|
-
"bundle_id": "us-6.2.
|
|
115
|
+
"bundle_id": "us-6.2.4",
|
|
116
116
|
"certification": {
|
|
117
117
|
"built_with_model_version": "2.2.1",
|
|
118
118
|
"certified_by": "policyengine.py bundle certification",
|
|
@@ -217,7 +217,7 @@
|
|
|
217
217
|
"version": "2.2.1",
|
|
218
218
|
"wheel_url": "https://files.pythonhosted.org/packages/5e/09/86ac3968d2a18e28fce3ba1186fc21728e9f299b96a806d6f204f1e0aaed/policyengine_us-2.2.1-py3-none-any.whl"
|
|
219
219
|
},
|
|
220
|
-
"policyengine_version": "6.2.
|
|
220
|
+
"policyengine_version": "6.2.4",
|
|
221
221
|
"region_datasets": {
|
|
222
222
|
"congressional_district": {
|
|
223
223
|
"path_template": "populace_us_2024_acs_local.h5"
|
|
@@ -295,10 +295,10 @@
|
|
|
295
295
|
"packages": {
|
|
296
296
|
"policyengine": {
|
|
297
297
|
"import_name": "policyengine",
|
|
298
|
-
"install_requirement": "policyengine==6.2.
|
|
298
|
+
"install_requirement": "policyengine==6.2.4",
|
|
299
299
|
"name": "policyengine",
|
|
300
300
|
"role": "bundle_carrier",
|
|
301
|
-
"version": "6.2.
|
|
301
|
+
"version": "6.2.4"
|
|
302
302
|
},
|
|
303
303
|
"policyengine-core": {
|
|
304
304
|
"import_name": "policyengine_core",
|
|
@@ -334,6 +334,6 @@
|
|
|
334
334
|
"wheel_url": "https://files.pythonhosted.org/packages/19/a0/c484f69a0ebf88a9b9fd0ac28176f8df66550f46714f1b0c5ec0b360824e/spm_calculator-1.0.0-py3-none-any.whl"
|
|
335
335
|
}
|
|
336
336
|
},
|
|
337
|
-
"policyengine_version": "6.2.
|
|
337
|
+
"policyengine_version": "6.2.4",
|
|
338
338
|
"schema_version": 2
|
|
339
339
|
}
|
|
@@ -18,18 +18,18 @@
|
|
|
18
18
|
"schema:url": "https://policyengine.org"
|
|
19
19
|
},
|
|
20
20
|
"schema:dateCreated": "2026-08-18T14:20:32.100961Z",
|
|
21
|
-
"schema:description": "TRACE TRO for certified runtime bundle uk-6.2.
|
|
21
|
+
"schema:description": "TRACE TRO for certified runtime bundle uk-6.2.4 covering the bundle manifest, the certified dataset artifact, the country model wheel, and the country data release manifest when it is available.",
|
|
22
22
|
"schema:name": "policyengine uk certified bundle TRO",
|
|
23
23
|
"trov:createdWith": {
|
|
24
24
|
"@type": "schema:SoftwareApplication",
|
|
25
25
|
"schema:name": "policyengine",
|
|
26
|
-
"schema:softwareVersion": "6.2.
|
|
26
|
+
"schema:softwareVersion": "6.2.4"
|
|
27
27
|
},
|
|
28
28
|
"trov:hasArrangement": [
|
|
29
29
|
{
|
|
30
30
|
"@id": "arrangement/1",
|
|
31
31
|
"@type": "trov:ArtifactArrangement",
|
|
32
|
-
"rdfs:comment": "Certified arrangement for bundle uk-6.2.
|
|
32
|
+
"rdfs:comment": "Certified arrangement for bundle uk-6.2.4.",
|
|
33
33
|
"trov:hasArtifactLocation": [
|
|
34
34
|
{
|
|
35
35
|
"@id": "arrangement/1/location/bundle_manifest",
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
"@type": "trov:ResearchArtifact",
|
|
76
76
|
"schema:name": "policyengine.py bundle manifest for uk",
|
|
77
77
|
"trov:mimeType": "application/json",
|
|
78
|
-
"trov:sha256": "
|
|
78
|
+
"trov:sha256": "4e830a845f54782daed05f1331203c68fa138396025f2da49d34b34ba7ac3c42"
|
|
79
79
|
},
|
|
80
80
|
{
|
|
81
81
|
"@id": "composition/1/artifact/data_release_manifest",
|
|
@@ -102,7 +102,7 @@
|
|
|
102
102
|
"trov:hasFingerprint": {
|
|
103
103
|
"@id": "composition/1/fingerprint",
|
|
104
104
|
"@type": "trov:CompositionFingerprint",
|
|
105
|
-
"trov:sha256": "
|
|
105
|
+
"trov:sha256": "d238f72a1fe43bb3b1c8c92c27eb3bf717f2c00527da1cab6277f65ccf382606"
|
|
106
106
|
}
|
|
107
107
|
},
|
|
108
108
|
"trov:hasPerformance": {
|
|
@@ -17,18 +17,18 @@
|
|
|
17
17
|
"schema:name": "PolicyEngine",
|
|
18
18
|
"schema:url": "https://policyengine.org"
|
|
19
19
|
},
|
|
20
|
-
"schema:description": "TRACE TRO for certified runtime bundle us-6.2.
|
|
20
|
+
"schema:description": "TRACE TRO for certified runtime bundle us-6.2.4 covering the bundle manifest, the certified dataset artifact, the country model wheel, and the country data release manifest when it is available.",
|
|
21
21
|
"schema:name": "policyengine us certified bundle TRO",
|
|
22
22
|
"trov:createdWith": {
|
|
23
23
|
"@type": "schema:SoftwareApplication",
|
|
24
24
|
"schema:name": "policyengine",
|
|
25
|
-
"schema:softwareVersion": "6.2.
|
|
25
|
+
"schema:softwareVersion": "6.2.4"
|
|
26
26
|
},
|
|
27
27
|
"trov:hasArrangement": [
|
|
28
28
|
{
|
|
29
29
|
"@id": "arrangement/1",
|
|
30
30
|
"@type": "trov:ArtifactArrangement",
|
|
31
|
-
"rdfs:comment": "Certified arrangement for bundle us-6.2.
|
|
31
|
+
"rdfs:comment": "Certified arrangement for bundle us-6.2.4.",
|
|
32
32
|
"trov:hasArtifactLocation": [
|
|
33
33
|
{
|
|
34
34
|
"@id": "arrangement/1/location/bundle_manifest",
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"@type": "trov:ResearchArtifact",
|
|
75
75
|
"schema:name": "policyengine.py bundle manifest for us",
|
|
76
76
|
"trov:mimeType": "application/json",
|
|
77
|
-
"trov:sha256": "
|
|
77
|
+
"trov:sha256": "4e830a845f54782daed05f1331203c68fa138396025f2da49d34b34ba7ac3c42"
|
|
78
78
|
},
|
|
79
79
|
{
|
|
80
80
|
"@id": "composition/1/artifact/data_release_manifest",
|
|
@@ -101,7 +101,7 @@
|
|
|
101
101
|
"trov:hasFingerprint": {
|
|
102
102
|
"@id": "composition/1/fingerprint",
|
|
103
103
|
"@type": "trov:CompositionFingerprint",
|
|
104
|
-
"trov:sha256": "
|
|
104
|
+
"trov:sha256": "122720c1301231fb4ff791dd2e80120dd7c64633e34aff5583aaac56c34c10bb"
|
|
105
105
|
}
|
|
106
106
|
},
|
|
107
107
|
"trov:hasPerformance": {
|
|
@@ -443,6 +443,21 @@ class MicrosimulationModelVersion(TaxBenefitModelVersion):
|
|
|
443
443
|
"stored inputs (it has no record of them); run it again"
|
|
444
444
|
)
|
|
445
445
|
|
|
446
|
+
if self.country_code == "uk":
|
|
447
|
+
from policyengine.tax_benefit_models.uk.datasets import (
|
|
448
|
+
_year_file_records_data_year,
|
|
449
|
+
)
|
|
450
|
+
|
|
451
|
+
# UK outputs saved before runs anchored on the observed data year
|
|
452
|
+
# (PolicyEngine/policyengine.py#556) took a projected year as
|
|
453
|
+
# observed and uprated the State Pension by CPI, so they are not
|
|
454
|
+
# reused. ``Simulation.ensure()`` runs such a simulation again.
|
|
455
|
+
if not _year_file_records_data_year(Path(filepath)):
|
|
456
|
+
raise ValueError(
|
|
457
|
+
"Saved UK simulation predates anchoring on the observed "
|
|
458
|
+
"data year (it records none); run it again"
|
|
459
|
+
)
|
|
460
|
+
|
|
446
461
|
simulation.output_dataset = self._dataset_class(
|
|
447
462
|
id=simulation.id,
|
|
448
463
|
name=simulation.dataset.name,
|
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from typing import Optional
|
|
3
|
+
|
|
4
|
+
import pandas as pd
|
|
5
|
+
from microdf import MicroDataFrame
|
|
6
|
+
from pydantic import ConfigDict
|
|
7
|
+
|
|
8
|
+
from policyengine.core import Dataset, YearData
|
|
9
|
+
from policyengine.provenance.dataset_materialization import (
|
|
10
|
+
materialize_dataset,
|
|
11
|
+
)
|
|
12
|
+
from policyengine.provenance.manifest import (
|
|
13
|
+
dataset_logical_name,
|
|
14
|
+
get_release_manifest,
|
|
15
|
+
resolve_dataset_reference,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
#: HDF5 key holding the data year of a UK year file: the year of the observed
|
|
19
|
+
#: data the file's tables were projected from (see
|
|
20
|
+
#: ``PolicyEngineUKDataset.data_year``). ``create_datasets`` writes it into
|
|
21
|
+
#: every year file. Year files written before policyengine.py kept the data
|
|
22
|
+
#: year have none: policyengine-uk would take their projected tables as
|
|
23
|
+
#: observed data, so ``ensure_datasets`` regenerates them and
|
|
24
|
+
#: ``load_datasets`` refuses them.
|
|
25
|
+
DATA_YEAR_KEY = "data_year"
|
|
26
|
+
|
|
27
|
+
#: Prefix of the HDF5 keys holding the data year's entity tables in a year
|
|
28
|
+
#: file whose year comes after its data year.
|
|
29
|
+
DATA_YEAR_TABLE_PREFIX = "data_year_"
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class UKYearData(YearData):
|
|
33
|
+
"""Entity-level data for a single year."""
|
|
34
|
+
|
|
35
|
+
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
36
|
+
|
|
37
|
+
person: MicroDataFrame
|
|
38
|
+
benunit: MicroDataFrame
|
|
39
|
+
household: MicroDataFrame
|
|
40
|
+
|
|
41
|
+
@property
|
|
42
|
+
def entity_data(self) -> dict[str, MicroDataFrame]:
|
|
43
|
+
"""Return a dictionary of entity names to their data."""
|
|
44
|
+
return {
|
|
45
|
+
"person": self.person,
|
|
46
|
+
"benunit": self.benunit,
|
|
47
|
+
"household": self.household,
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class PolicyEngineUKDataset(Dataset):
|
|
52
|
+
"""UK dataset with multi-year entity-level data."""
|
|
53
|
+
|
|
54
|
+
data: Optional[UKYearData] = None
|
|
55
|
+
|
|
56
|
+
data_year: Optional[int] = None
|
|
57
|
+
"""Year of the observed data that ``data`` was projected from.
|
|
58
|
+
|
|
59
|
+
policyengine-uk takes the first year of a dataset as observed data. It
|
|
60
|
+
splits each person's reported State Pension against that year's
|
|
61
|
+
legislated rates and scales the share to the simulated year's rates,
|
|
62
|
+
which follow the triple lock. ``create_datasets`` records the source
|
|
63
|
+
dataset's first year here. ``None`` means ``data`` is itself observed
|
|
64
|
+
data for ``year``, as it is for a dataset built in memory.
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
data_year_data: Optional[UKYearData] = None
|
|
68
|
+
"""Entity tables of ``data_year``, when it comes before ``year``.
|
|
69
|
+
|
|
70
|
+
``run()`` projects them forward as policyengine-uk does in a direct run,
|
|
71
|
+
and uses ``data`` for ``year`` itself. Without them, policyengine-uk
|
|
72
|
+
would take the projected ``data`` as observed data for ``year`` and the
|
|
73
|
+
State Pension would follow the CPI uprating of its reported amount
|
|
74
|
+
instead of the triple lock.
|
|
75
|
+
"""
|
|
76
|
+
|
|
77
|
+
def model_post_init(self, __context):
|
|
78
|
+
"""Called after Pydantic initialization.
|
|
79
|
+
|
|
80
|
+
Constructing with only a ``filepath`` hydrates ``data`` from disk.
|
|
81
|
+
Construction never *writes*: persistence is always explicit via
|
|
82
|
+
``save()``. Auto-saving on construction (the previous behaviour)
|
|
83
|
+
made an in-memory, region-scoped copy that reused its source's
|
|
84
|
+
``filepath`` silently truncate the shared dataset file it was
|
|
85
|
+
derived from. See run() in model.py, which now builds scoped
|
|
86
|
+
copies with ``filepath=None``.
|
|
87
|
+
"""
|
|
88
|
+
if self.data is None and self.filepath:
|
|
89
|
+
self.load()
|
|
90
|
+
self._check_data_year()
|
|
91
|
+
|
|
92
|
+
def _check_data_year(self) -> None:
|
|
93
|
+
"""Refuse a data year that cannot be the source of ``year``."""
|
|
94
|
+
if self.data_year is None:
|
|
95
|
+
if self.data_year_data is not None:
|
|
96
|
+
raise ValueError(
|
|
97
|
+
"PolicyEngineUKDataset has data-year tables but no "
|
|
98
|
+
"data_year. Set data_year to the year they hold."
|
|
99
|
+
)
|
|
100
|
+
return
|
|
101
|
+
if self.data_year > self.year:
|
|
102
|
+
raise ValueError(
|
|
103
|
+
f"PolicyEngineUKDataset data_year {self.data_year} is after "
|
|
104
|
+
f"its year {self.year}; data can only be projected forward."
|
|
105
|
+
)
|
|
106
|
+
if self.data_year == self.year and self.data_year_data is not None:
|
|
107
|
+
raise ValueError(
|
|
108
|
+
f"PolicyEngineUKDataset year {self.year} is its data year, so "
|
|
109
|
+
"`data` holds the observed tables and data_year_data must be "
|
|
110
|
+
"None."
|
|
111
|
+
)
|
|
112
|
+
# An output records the data year its run anchored on, without the
|
|
113
|
+
# tables.
|
|
114
|
+
if (
|
|
115
|
+
self.data_year < self.year
|
|
116
|
+
and self.data is not None
|
|
117
|
+
and self.data_year_data is None
|
|
118
|
+
and not self.is_output_dataset
|
|
119
|
+
):
|
|
120
|
+
raise ValueError(
|
|
121
|
+
f"PolicyEngineUKDataset for {self.year} was projected from "
|
|
122
|
+
f"{self.data_year} but has no data_year_data, so "
|
|
123
|
+
"policyengine-uk cannot anchor the State Pension on the "
|
|
124
|
+
"observed year. Pass the data year's tables, or set "
|
|
125
|
+
"data_year=None to treat `data` as observed data."
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
def save(self) -> None:
|
|
129
|
+
"""Save dataset to HDF5 file.
|
|
130
|
+
|
|
131
|
+
Converts object columns to categorical dtype to avoid slow pickle serialization.
|
|
132
|
+
"""
|
|
133
|
+
if not self.filepath:
|
|
134
|
+
raise ValueError(
|
|
135
|
+
"Cannot save a PolicyEngineUKDataset with no filepath. This "
|
|
136
|
+
"is an in-memory dataset (e.g. a region-scoped copy); set "
|
|
137
|
+
"`.filepath` to a destination before calling save()."
|
|
138
|
+
)
|
|
139
|
+
filepath = Path(self.filepath)
|
|
140
|
+
if not filepath.parent.exists():
|
|
141
|
+
filepath.parent.mkdir(parents=True, exist_ok=True)
|
|
142
|
+
|
|
143
|
+
with pd.HDFStore(filepath, mode="w") as store:
|
|
144
|
+
_put_year_data(store, self.data)
|
|
145
|
+
if self.data_year_data is not None:
|
|
146
|
+
_put_year_data(store, self.data_year_data, DATA_YEAR_TABLE_PREFIX)
|
|
147
|
+
# Written last: its presence marks a complete file.
|
|
148
|
+
if self.data_year is not None:
|
|
149
|
+
store.put(DATA_YEAR_KEY, pd.Series([int(self.data_year)]))
|
|
150
|
+
|
|
151
|
+
def load(self) -> None:
|
|
152
|
+
"""Load dataset from HDF5 file into this instance."""
|
|
153
|
+
filepath = self.filepath
|
|
154
|
+
with pd.HDFStore(filepath, mode="r") as store:
|
|
155
|
+
keys = set(store.keys())
|
|
156
|
+
self.data = _read_year_data(store)
|
|
157
|
+
self.data_year = (
|
|
158
|
+
int(store[DATA_YEAR_KEY].iloc[0])
|
|
159
|
+
if f"/{DATA_YEAR_KEY}" in keys
|
|
160
|
+
else None
|
|
161
|
+
)
|
|
162
|
+
self.data_year_data = (
|
|
163
|
+
_read_year_data(store, DATA_YEAR_TABLE_PREFIX)
|
|
164
|
+
if f"/{DATA_YEAR_TABLE_PREFIX}person" in keys
|
|
165
|
+
else None
|
|
166
|
+
)
|
|
167
|
+
self._check_data_year()
|
|
168
|
+
|
|
169
|
+
def __repr__(self) -> str:
|
|
170
|
+
if self.data is None:
|
|
171
|
+
return f"<PolicyEngineUKDataset id={self.id} year={self.year} filepath={self.filepath} (not loaded)>"
|
|
172
|
+
else:
|
|
173
|
+
n_people = len(self.data.person)
|
|
174
|
+
n_benunits = len(self.data.benunit)
|
|
175
|
+
n_households = len(self.data.household)
|
|
176
|
+
return f"<PolicyEngineUKDataset id={self.id} year={self.year} data_year={self.data_year} filepath={self.filepath} people={n_people} benunits={n_benunits} households={n_households}>"
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def _put_year_data(store: pd.HDFStore, data: UKYearData, prefix: str = "") -> None:
|
|
180
|
+
"""Write one year's entity tables to an open HDF5 store.
|
|
181
|
+
|
|
182
|
+
Object columns are stored as categoricals to avoid slow pickle
|
|
183
|
+
serialization; ``format="table"`` supports categorical dtypes.
|
|
184
|
+
"""
|
|
185
|
+
for name, frame in data.entity_data.items():
|
|
186
|
+
frame = pd.DataFrame(frame)
|
|
187
|
+
for column in frame.columns:
|
|
188
|
+
if frame[column].dtype == "object":
|
|
189
|
+
frame[column] = frame[column].astype("category")
|
|
190
|
+
store.put(f"{prefix}{name}", frame, format="table")
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def _read_year_data(store: pd.HDFStore, prefix: str = "") -> UKYearData:
|
|
194
|
+
"""Read one year's entity tables from an open HDF5 store."""
|
|
195
|
+
return UKYearData(
|
|
196
|
+
person=MicroDataFrame(store[f"{prefix}person"], weights="person_weight"),
|
|
197
|
+
benunit=MicroDataFrame(store[f"{prefix}benunit"], weights="benunit_weight"),
|
|
198
|
+
household=MicroDataFrame(
|
|
199
|
+
store[f"{prefix}household"], weights="household_weight"
|
|
200
|
+
),
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def _year_data_with_weights(year_dataset) -> UKYearData:
|
|
205
|
+
"""Return a policyengine-uk year's tables with person and benunit weights.
|
|
206
|
+
|
|
207
|
+
policyengine-uk stores household weights only; each person and benefit
|
|
208
|
+
unit takes its household's weight.
|
|
209
|
+
"""
|
|
210
|
+
# Convert to pandas DataFrames and add weight columns
|
|
211
|
+
person_df = pd.DataFrame(year_dataset.person)
|
|
212
|
+
benunit_df = pd.DataFrame(year_dataset.benunit)
|
|
213
|
+
household_df = pd.DataFrame(year_dataset.household)
|
|
214
|
+
|
|
215
|
+
# Map household weights to person and benunit levels
|
|
216
|
+
person_df = person_df.merge(
|
|
217
|
+
household_df[["household_id", "household_weight"]],
|
|
218
|
+
left_on="person_household_id",
|
|
219
|
+
right_on="household_id",
|
|
220
|
+
how="left",
|
|
221
|
+
)
|
|
222
|
+
person_df = person_df.rename(columns={"household_weight": "person_weight"})
|
|
223
|
+
person_df = person_df.drop(columns=["household_id"])
|
|
224
|
+
|
|
225
|
+
# Get household_id for each benunit from person table
|
|
226
|
+
benunit_household_map = person_df[
|
|
227
|
+
["person_benunit_id", "person_household_id"]
|
|
228
|
+
].drop_duplicates()
|
|
229
|
+
benunit_df = benunit_df.merge(
|
|
230
|
+
benunit_household_map,
|
|
231
|
+
left_on="benunit_id",
|
|
232
|
+
right_on="person_benunit_id",
|
|
233
|
+
how="left",
|
|
234
|
+
)
|
|
235
|
+
benunit_df = benunit_df.merge(
|
|
236
|
+
household_df[["household_id", "household_weight"]],
|
|
237
|
+
left_on="person_household_id",
|
|
238
|
+
right_on="household_id",
|
|
239
|
+
how="left",
|
|
240
|
+
)
|
|
241
|
+
benunit_df = benunit_df.rename(columns={"household_weight": "benunit_weight"})
|
|
242
|
+
benunit_df = benunit_df.drop(
|
|
243
|
+
columns=[
|
|
244
|
+
"person_benunit_id",
|
|
245
|
+
"person_household_id",
|
|
246
|
+
"household_id",
|
|
247
|
+
],
|
|
248
|
+
errors="ignore",
|
|
249
|
+
)
|
|
250
|
+
return UKYearData(
|
|
251
|
+
person=MicroDataFrame(person_df, weights="person_weight"),
|
|
252
|
+
benunit=MicroDataFrame(benunit_df, weights="benunit_weight"),
|
|
253
|
+
household=MicroDataFrame(household_df, weights="household_weight"),
|
|
254
|
+
)
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
def _year_file_records_data_year(path: Path) -> bool:
|
|
258
|
+
"""Return whether a UK file records its data year (``DATA_YEAR_KEY``).
|
|
259
|
+
|
|
260
|
+
A missing or unreadable file raises rather than reading as unrecorded.
|
|
261
|
+
"""
|
|
262
|
+
with pd.HDFStore(path, mode="r") as store:
|
|
263
|
+
return f"/{DATA_YEAR_KEY}" in store.keys()
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
def create_datasets(
|
|
267
|
+
datasets: Optional[list[str]] = None,
|
|
268
|
+
years: list[int] = [2026, 2027, 2028, 2029, 2030],
|
|
269
|
+
data_folder: str = "./data",
|
|
270
|
+
allow_unmanaged: bool = False,
|
|
271
|
+
) -> dict[str, PolicyEngineUKDataset]:
|
|
272
|
+
dataset_requests: list[Optional[str]] = [None] if datasets is None else datasets
|
|
273
|
+
result = {}
|
|
274
|
+
for dataset in dataset_requests:
|
|
275
|
+
source = materialize_dataset(
|
|
276
|
+
"uk",
|
|
277
|
+
dataset,
|
|
278
|
+
allow_unmanaged=allow_unmanaged,
|
|
279
|
+
data_dir=Path(data_folder),
|
|
280
|
+
)
|
|
281
|
+
dataset_stem = source.name
|
|
282
|
+
from policyengine_uk import Microsimulation
|
|
283
|
+
|
|
284
|
+
sim = Microsimulation(dataset=source.path)
|
|
285
|
+
if not years:
|
|
286
|
+
continue
|
|
287
|
+
# policyengine-uk takes a dataset's first year as observed data and
|
|
288
|
+
# projects the rest from it (see PolicyEngineUKDataset.data_year).
|
|
289
|
+
# Each year file keeps that year and its tables, so a run of the
|
|
290
|
+
# file anchors on the same observed year as a run of the source.
|
|
291
|
+
data_year = int(min(sim.dataset.years))
|
|
292
|
+
data_year_data = _year_data_with_weights(sim.dataset[data_year])
|
|
293
|
+
for year in years:
|
|
294
|
+
uk_dataset = PolicyEngineUKDataset(
|
|
295
|
+
id=f"{dataset_stem}_year_{year}",
|
|
296
|
+
name=f"{dataset_stem}-year-{year}",
|
|
297
|
+
description=f"UK Dataset for year {year} based on {dataset_stem}",
|
|
298
|
+
filepath=f"{data_folder}/{dataset_stem}_year_{year}.h5",
|
|
299
|
+
year=int(year),
|
|
300
|
+
data=_year_data_with_weights(sim.dataset[year]),
|
|
301
|
+
data_year=data_year,
|
|
302
|
+
data_year_data=data_year_data if int(year) > data_year else None,
|
|
303
|
+
)
|
|
304
|
+
uk_dataset.save()
|
|
305
|
+
|
|
306
|
+
dataset_key = f"{dataset_stem}_{year}"
|
|
307
|
+
result[dataset_key] = uk_dataset
|
|
308
|
+
|
|
309
|
+
return result
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
def load_datasets(
|
|
313
|
+
datasets: Optional[list[str]] = None,
|
|
314
|
+
years: list[int] = [2026, 2027, 2028, 2029, 2030],
|
|
315
|
+
data_folder: str = "./data",
|
|
316
|
+
) -> dict[str, PolicyEngineUKDataset]:
|
|
317
|
+
"""Load UK year files written by ``create_datasets``.
|
|
318
|
+
|
|
319
|
+
A year file without a recorded data year (``DATA_YEAR_KEY``) was written
|
|
320
|
+
before policyengine.py kept the observed year its tables were projected
|
|
321
|
+
from. policyengine-uk would take those projected tables as observed data
|
|
322
|
+
and uprate the State Pension by CPI rather than the triple lock, so such
|
|
323
|
+
a file is refused.
|
|
324
|
+
"""
|
|
325
|
+
if datasets is None:
|
|
326
|
+
datasets = [get_release_manifest("uk").default_dataset]
|
|
327
|
+
result = {}
|
|
328
|
+
for dataset in datasets:
|
|
329
|
+
resolved_dataset = resolve_dataset_reference("uk", dataset)
|
|
330
|
+
dataset_stem = dataset_logical_name(resolved_dataset)
|
|
331
|
+
for year in years:
|
|
332
|
+
filepath = f"{data_folder}/{dataset_stem}_year_{year}.h5"
|
|
333
|
+
if Path(filepath).exists() and not _year_file_records_data_year(
|
|
334
|
+
Path(filepath)
|
|
335
|
+
):
|
|
336
|
+
raise ValueError(
|
|
337
|
+
f"UK year file {filepath} has no recorded data year, so it "
|
|
338
|
+
"was written before policyengine.py kept the observed year "
|
|
339
|
+
"its tables were projected from. policyengine-uk would "
|
|
340
|
+
"take the projected tables as observed data and uprate the "
|
|
341
|
+
"State Pension by CPI rather than the triple lock. "
|
|
342
|
+
"Regenerate it with ensure_datasets() or create_datasets()."
|
|
343
|
+
)
|
|
344
|
+
# Constructing with a filepath loads the file.
|
|
345
|
+
uk_dataset = PolicyEngineUKDataset(
|
|
346
|
+
name=f"{dataset_stem}-year-{year}",
|
|
347
|
+
description=f"UK Dataset for year {year} based on {dataset_stem}",
|
|
348
|
+
filepath=filepath,
|
|
349
|
+
year=int(year),
|
|
350
|
+
)
|
|
351
|
+
|
|
352
|
+
dataset_key = f"{dataset_stem}_{year}"
|
|
353
|
+
result[dataset_key] = uk_dataset
|
|
354
|
+
|
|
355
|
+
return result
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
def ensure_datasets(
|
|
359
|
+
datasets: Optional[list[str]] = None,
|
|
360
|
+
years: list[int] = [2026, 2027, 2028, 2029, 2030],
|
|
361
|
+
data_folder: str = "./data",
|
|
362
|
+
allow_unmanaged: bool = False,
|
|
363
|
+
) -> dict[str, PolicyEngineUKDataset]:
|
|
364
|
+
"""Ensure datasets exist, loading if available or creating if not.
|
|
365
|
+
|
|
366
|
+
Year files without a recorded data year were written before
|
|
367
|
+
policyengine.py kept the observed year their tables were projected from
|
|
368
|
+
(see ``load_datasets``), so they are created again rather than loaded.
|
|
369
|
+
|
|
370
|
+
Args:
|
|
371
|
+
datasets: List of HuggingFace dataset paths
|
|
372
|
+
years: List of years to load/create data for
|
|
373
|
+
data_folder: Directory containing or to save the dataset files
|
|
374
|
+
|
|
375
|
+
Returns:
|
|
376
|
+
Dictionary mapping dataset keys to PolicyEngineUKDataset objects
|
|
377
|
+
"""
|
|
378
|
+
if datasets is None:
|
|
379
|
+
datasets = [get_release_manifest("uk").default_dataset]
|
|
380
|
+
|
|
381
|
+
# Check if all dataset files exist
|
|
382
|
+
all_exist = True
|
|
383
|
+
for dataset in datasets:
|
|
384
|
+
resolved_dataset = resolve_dataset_reference("uk", dataset)
|
|
385
|
+
dataset_stem = dataset_logical_name(resolved_dataset)
|
|
386
|
+
for year in years:
|
|
387
|
+
filepath = Path(f"{data_folder}/{dataset_stem}_year_{year}.h5")
|
|
388
|
+
# A year file without a recorded data year would run as observed
|
|
389
|
+
# data, so it is regenerated rather than reused.
|
|
390
|
+
if not filepath.exists() or not _year_file_records_data_year(filepath):
|
|
391
|
+
all_exist = False
|
|
392
|
+
break
|
|
393
|
+
if not all_exist:
|
|
394
|
+
break
|
|
395
|
+
|
|
396
|
+
if all_exist:
|
|
397
|
+
return load_datasets(datasets=datasets, years=years, data_folder=data_folder)
|
|
398
|
+
else:
|
|
399
|
+
return create_datasets(
|
|
400
|
+
datasets=datasets,
|
|
401
|
+
years=years,
|
|
402
|
+
data_folder=data_folder,
|
|
403
|
+
allow_unmanaged=allow_unmanaged,
|
|
404
|
+
)
|