policyengine 6.3.3__tar.gz → 6.4.0__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.3.3 → policyengine-6.4.0}/CHANGELOG.md +24 -0
- {policyengine-6.3.3/src/policyengine.egg-info → policyengine-6.4.0}/PKG-INFO +1 -1
- {policyengine-6.3.3 → policyengine-6.4.0}/docs/_quarto.yml +1 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/docs/bundles.md +3 -1
- policyengine-6.4.0/docs/disclosure.md +239 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/docs/engineering/runbooks/build-m-us-populace-certification.md +23 -6
- policyengine-6.4.0/docs/engineering/runbooks/us-legacy-spm-sources.md +122 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/docs/engineering/skills/data-certification.md +27 -2
- {policyengine-6.3.3 → policyengine-6.4.0}/docs/examples.md +7 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/docs/microsim.md +18 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/docs/outputs.md +28 -1
- {policyengine-6.3.3 → policyengine-6.4.0}/docs/regions.md +14 -4
- {policyengine-6.3.3 → policyengine-6.4.0}/docs/release-bundles.md +2 -1
- policyengine-6.4.0/examples/uk_geography_disclosure.py +84 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/examples/us_budgetary_impact.py +12 -3
- {policyengine-6.3.3 → policyengine-6.4.0}/pyproject.toml +1 -1
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/core/run_record.py +9 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/core/simulation.py +8 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/data/bundle/manifest.json +12 -12
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/data/bundle/uk.trace.tro.jsonld +5 -5
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/data/bundle/us.trace.tro.jsonld +5 -5
- policyengine-6.4.0/src/policyengine/disclosure/__init__.py +65 -0
- policyengine-6.4.0/src/policyengine/disclosure/__main__.py +37 -0
- policyengine-6.4.0/src/policyengine/disclosure/areas.py +216 -0
- policyengine-6.4.0/src/policyengine/disclosure/estimate.py +472 -0
- policyengine-6.4.0/src/policyengine/disclosure/noise.py +102 -0
- policyengine-6.4.0/src/policyengine/disclosure/release.py +858 -0
- policyengine-6.4.0/src/policyengine/disclosure/schema.py +278 -0
- policyengine-6.4.0/src/policyengine/disclosure/support.py +166 -0
- policyengine-6.4.0/src/policyengine/disclosure/validate.py +211 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/outputs/__init__.py +6 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/outputs/constituency_impact.py +12 -1
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/outputs/local_authority_impact.py +12 -1
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/outputs/poverty.py +21 -1
- policyengine-6.4.0/src/policyengine/outputs/uk_geography_disclosure.py +275 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/outputs/uk_geography_impact.py +19 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/tax_benefit_models/common/model_version.py +23 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/tax_benefit_models/uk/model.py +6 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/tax_benefit_models/us/datasets.py +126 -3
- policyengine-6.4.0/src/policyengine/tax_benefit_models/us/legacy_spm/__init__.py +120 -0
- policyengine-6.4.0/src/policyengine/tax_benefit_models/us/legacy_spm/declarations.py +218 -0
- policyengine-6.4.0/src/policyengine/tax_benefit_models/us/legacy_spm/independence.py +121 -0
- policyengine-6.4.0/src/policyengine/tax_benefit_models/us/legacy_spm/model_adapter.py +337 -0
- policyengine-6.4.0/src/policyengine/tax_benefit_models/us/legacy_spm/record.py +167 -0
- policyengine-6.4.0/src/policyengine/tax_benefit_models/us/legacy_spm/registry.py +76 -0
- policyengine-6.4.0/src/policyengine/tax_benefit_models/us/legacy_spm/runs.py +140 -0
- policyengine-6.4.0/src/policyengine/tax_benefit_models/us/legacy_spm/universe.py +137 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/tax_benefit_models/us/model.py +54 -4
- {policyengine-6.3.3 → policyengine-6.4.0/src/policyengine.egg-info}/PKG-INFO +1 -1
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine.egg-info/SOURCES.txt +32 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_constituency_impact.py +29 -0
- policyengine-6.4.0/tests/test_disclosure_areas.py +132 -0
- policyengine-6.4.0/tests/test_disclosure_estimate.py +558 -0
- policyengine-6.4.0/tests/test_disclosure_noise.py +108 -0
- policyengine-6.4.0/tests/test_disclosure_release.py +678 -0
- policyengine-6.4.0/tests/test_disclosure_schema.py +186 -0
- policyengine-6.4.0/tests/test_disclosure_support.py +242 -0
- policyengine-6.4.0/tests/test_disclosure_validate.py +217 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_extra_variables.py +3 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_local_authority_impact.py +31 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_poverty_run.py +4 -3
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_release_manifests.py +19 -5
- policyengine-6.4.0/tests/test_uk_geography_disclosure.py +277 -0
- policyengine-6.4.0/tests/test_us_legacy_spm.py +565 -0
- policyengine-6.4.0/tests/test_us_legacy_spm_integration.py +772 -0
- policyengine-6.4.0/tests/test_us_legacy_spm_model_contract.py +243 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_us_regions.py +11 -8
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_us_year_file_stamp.py +10 -1
- {policyengine-6.3.3 → policyengine-6.4.0}/uv.lock +1 -1
- {policyengine-6.3.3 → policyengine-6.4.0}/.claude/policyengine-guide.md +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/.claude/quick-reference.md +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/.github/CONTRIBUTING.md +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/.github/bump_version.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/.github/capture-version.sh +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/.github/changelog_template.md +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/.github/check-changelog.sh +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/.github/copilot-instructions.md +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/.github/dispatch-policyengine-release.sh +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/.github/fetch_version.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/.github/get-changelog-diff.sh +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/.github/has-functional-changes.sh +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/.github/is-version-number-acceptable.sh +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/.github/publish-git-tag.sh +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/.github/wait-for-pypi.sh +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/.github/workflows/draft-pdf.yml +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/.github/workflows/pr_code_changes.yaml +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/.github/workflows/pr_docs_changes.yaml +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/.github/workflows/push.yaml +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/.gitignore +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/.python-version +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/AGENTS.md +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/CITATION.cff +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/CLAUDE.md +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/CODE_OF_CONDUCT.md +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/CONTRIBUTING.md +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/LICENSE +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/Makefile +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/README.md +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/architecture.png +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/architecture.svg +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/changelog.d/.gitkeep +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/docs/.gitignore +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/docs/_generator/README.md +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/docs/_generator/build_reference.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/docs/countries.md +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/docs/data-publishing-design.md +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/docs/decile-impact-spec.md +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/docs/dev.md +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/docs/engineering/runbooks/acs-local-wic-replacement.md +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/docs/engineering/runbooks/canonical-spm-development.md +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/docs/engineering/skills/README.md +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/docs/engineering/skills/github-prs.md +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/docs/engineering/skills/repository-guidance.md +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/docs/getting-started.md +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/docs/households.md +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/docs/impact-analysis.md +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/docs/index.md +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/docs/methodology/index.md +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/docs/methodology/model-architecture.md +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/docs/methodology/us-health-costs.md +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/docs/programs/index.md +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/docs/programs/us-chip.md +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/docs/reference/index.md +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/docs/reforms.md +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/docs/run-records.md +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/docs/trace-case-study.md +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/docs/visualisation.md +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/examples/belgium_axiom_pilot.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/examples/employment_income_variation_uk.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/examples/employment_income_variation_us.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/examples/household_impact_example.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/examples/income_bands_uk.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/examples/income_distribution_us.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/examples/paper_repro_uk.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/examples/policy_change_uk.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/examples/speedtest_us_simulation.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/paper-preview.html +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/paper.bib +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/paper.md +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/scripts/bundle.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/scripts/certify_data_release.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/scripts/check_data_staleness.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/scripts/check_native_spm_loading.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/scripts/check_release_credentials.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/scripts/export_bundle_release_assets.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/scripts/generate_bundle_artifacts.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/scripts/generate_trace_tros.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/scripts/prepare_package_bundle_update.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/scripts/release_lock.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/scripts/spm_bundle.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/setup.cfg +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/__init__.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/bundle.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/cli.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/core/__init__.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/core/cache.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/core/dataset.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/core/dynamic.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/core/output.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/core/parameter.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/core/parameter_node.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/core/parameter_value.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/core/policy.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/core/region.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/core/scoping_strategy.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/core/spm.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/core/tax_benefit_model.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/core/tax_benefit_model_version.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/core/variable.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/countries/__init__.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/countries/uk/__init__.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/countries/uk/regions.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/countries/us/__init__.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/countries/us/data/__init__.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/countries/us/data/districts.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/countries/us/data/places.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/countries/us/data/states.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/countries/us/regions.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/data/__init__.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/data/schemas/trace_tro.schema.json +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/data/uk_geography_assets.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/derivations/__init__.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/derivations/narrate.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/derivations/trace.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/graph/__init__.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/graph/extractor.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/graph/graph.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/outputs/aggregate.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/outputs/change_aggregate.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/outputs/cliff_impact.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/outputs/congressional_district_impact.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/outputs/decile_analysis.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/outputs/decile_grouping.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/outputs/decile_impact.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/outputs/extra_variables.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/outputs/inequality.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/outputs/intra_decile_impact.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/outputs/labor_supply_response.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/outputs/program_statistics.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/outputs/uk_geography_assets.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/provenance/__init__.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/provenance/bundle_validation.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/provenance/certification.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/provenance/dataset_materialization.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/provenance/manifest.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/provenance/pyproject_pins.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/provenance/spm_configuration.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/provenance/trace.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/provenance/verify.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/provenance/zenodo.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/results/__init__.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/results/schema.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/results/trace_tro.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/results/tracking.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/tax_benefit_models/be/__init__.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/tax_benefit_models/be/datasets.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/tax_benefit_models/be/model.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/tax_benefit_models/common/__init__.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/tax_benefit_models/common/axes.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/tax_benefit_models/common/extra_variables.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/tax_benefit_models/common/household.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/tax_benefit_models/common/reform.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/tax_benefit_models/common/result.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/tax_benefit_models/uk/__init__.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/tax_benefit_models/uk/analysis.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/tax_benefit_models/uk/budget_reform_contract.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/tax_benefit_models/uk/budget_reform_population.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/tax_benefit_models/uk/datasets.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/tax_benefit_models/uk/household.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/tax_benefit_models/us/__init__.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/tax_benefit_models/us/analysis.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/tax_benefit_models/us/household.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/tax_benefit_models/us/legacy_inputs.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/tax_benefit_models/us/spm.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/utils/__init__.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/utils/dates.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/utils/design.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/utils/entity_utils.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/utils/errors.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/utils/hashing.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/utils/household_validation.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/utils/parameter_labels.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/utils/parametric_reforms.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine/utils/plotting.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine.egg-info/dependency_links.txt +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine.egg-info/entry_points.txt +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine.egg-info/requires.txt +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/src/policyengine.egg-info/top_level.txt +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/__init__.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/conftest.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/fixtures/__init__.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/fixtures/filtering_fixtures.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/fixtures/household_calculator_snapshots/uk_couple_two_kids.json +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/fixtures/household_calculator_snapshots/uk_model_surface.json +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/fixtures/household_calculator_snapshots/uk_single_adult_employment_income.json +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/fixtures/household_calculator_snapshots/uk_single_adult_no_income.json +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/fixtures/household_calculator_snapshots/uk_single_parent_one_child.json +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/fixtures/household_calculator_snapshots/us_married_two_kids_high_income.json +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/fixtures/household_calculator_snapshots/us_model_surface.json +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/fixtures/household_calculator_snapshots/us_single_adult_employment_income.json +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/fixtures/household_calculator_snapshots/us_single_adult_no_income.json +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/fixtures/household_calculator_snapshots/us_single_parent_one_child.json +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/fixtures/parameter_labels_fixtures.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/fixtures/parametric_reforms_fixtures.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/fixtures/poverty_by_demographics_fixtures.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/fixtures/region_fixtures.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/fixtures/release_tros/README.md +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/fixtures/release_tros/country-models.lock.toml +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/fixtures/release_tros/manifest.json +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/fixtures/release_tros/us-release_manifest.json +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/fixtures/release_tros/us.trace.tro.jsonld +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/fixtures/spm_development.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/fixtures/us_reform_fixtures.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/fixtures/variable_label_fixtures.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_aggregate.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_be_axiom_pilot.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_budgetary_impact.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_bump_version.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_bundle.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_bundle_metadata.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_cache.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_certify_data_release.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_change_aggregate.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_cliff_impact.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_cliff_impact_analysis.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_congressional_district_impact.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_dataset_materialization.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_dataset_persistence.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_dataset_runtime.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_dataset_source.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_decile_grouping.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_derivations.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_dict_reforms_on_simulation.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_entity_mapping.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_entity_utils.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_entity_utils_characterization.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_errors.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_filtering.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_generate_trace_tros.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_graph/__init__.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_graph/conftest.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_graph/test_extractor.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_household_calculator_snapshot.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_household_impact.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_inequality.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_intra_decile_impact.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_labor_supply_response.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_manifest_version_mismatch.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_models.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_pandas3_compatibility.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_parameter_labels.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_parameter_nodes.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_parameter_values.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_parametric_reforms.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_poverty.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_poverty_by_demographics.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_preservation_mirror.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_program_statistics.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_pyproject_pins.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_region.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_region_group_strategy.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_release_credentials.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_release_lock.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_release_tro_generation.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_results.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_run_record.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_scoping_strategy.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_small_follow_ups.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_spm_bundle_bootstrap.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_spm_bundle_tooling.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_spm_decile.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_spm_development_authentication.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_spm_household.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_spm_model.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_spm_selection.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_spm_selection_schema.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_trace_tro.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_trace_tro_verify.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_uk_analysis.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_uk_budget_reform_contract.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_uk_dated_reforms.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_uk_geography_assets.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_uk_program_statistics.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_uk_regions.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_uk_year_file_data_year.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_us_legacy_inputs.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_us_legacy_inputs_integration.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_us_long_term_datasets.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_us_microsim_structural_reforms.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_us_native_alignment.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_us_native_hdf_weights.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_us_program_statistics.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_us_reform_application.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_variable_labels.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_variable_metadata.py +0 -0
- {policyengine-6.3.3 → policyengine-6.4.0}/tests/test_zenodo_mirror.py +0 -0
|
@@ -1,3 +1,27 @@
|
|
|
1
|
+
## [6.4.0] - 2026-10-14
|
|
2
|
+
|
|
3
|
+
### Added
|
|
4
|
+
|
|
5
|
+
- Added `policyengine.disclosure`, a self-contained layer for statistical disclosure control and uncertainty on area-level outputs, and `compute_uk_geography_disclosure` for UK regions, constituencies and local authorities. Each published number rests on at least 10 distinct survey households (clones counted once through `source_household_id`), carries a 90% bootstrap interval and is rounded to the order of its standard error. Rows are `reported`, `approximate` or `withheld`. A release check reports numbers a reader could recover by subtraction across geography levels, a package and its components, and earlier publications. Keyed noise per survey household is available behind `DisclosureSettings(noise=True)`. `validate_public` and `python -m policyengine.disclosure validate` check the format of published files. UK runs now keep `source_household_id` and `region` on the household output when the dataset provides them.
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- Deprecated `compute_uk_constituency_impacts`, `compute_uk_local_authority_impacts` and their `ConstituencyImpact` and `LocalAuthorityImpact` classes. Their output is not disclosure-controlled; use `compute_uk_geography_disclosure` instead. They now log a warning through the `policyengine` logger and emit a `DeprecationWarning`, and otherwise behave as before.
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
## [6.3.4] - 2026-10-13
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
|
|
16
|
+
- `Poverty.rate` is now `None`, not `0.0`, when nobody in the group is measured (its weighted population with a poverty status is zero), for every source. `headcount` and `total_population` are unchanged, and the poverty DataFrame helpers report the rate as missing. Callers that format or subtract rates must handle `None`.
|
|
17
|
+
- US state and congressional-district regions temporarily filter the certified national dataset again, as in 6.2.1, because the ACS-local release lacks source-backed SPM independence and canonical SPM refused every state-region run (PolicyEngine/microcosm#1263).
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
- Measure SPM poverty on legacy certified US sources that predate SPM measurement-scope declarations, such as the ACS-local Build O release. Following Census's ACS household-population method, ACS group-quarters units are outside the SPM measurement: their SPM results are missing instead of stopping the run with `SPM_COMPOSITION_REQUIRED`, and poverty rates count measured people only. Ordinary tax and benefit results are unchanged.
|
|
22
|
+
- Supply the certified SPM independence role from the national release for the ASEC and PUF records of legacy certified US sources, so independent-teen SPM units are measured instead of stopping SPM calculations.
|
|
23
|
+
|
|
24
|
+
|
|
1
25
|
## [6.3.3] - 2026-10-13
|
|
2
26
|
|
|
3
27
|
### Changed
|
|
@@ -147,7 +147,9 @@ python scripts/bundle.py certify-data \
|
|
|
147
147
|
--model-version <policyengine-us-version>
|
|
148
148
|
```
|
|
149
149
|
|
|
150
|
-
|
|
150
|
+
**Temporarily**, state and congressional-district regions filter the certified national dataset (`populace_us_2024`), as in policyengine 6.2.1. The certified ACS-local release has no source-backed SPM independence, so canonical SPM refuses thousands of its SPM units (PolicyEngine/microcosm#1263, PolicyEngine/policyengine-sim-api#747). They move back to the ACS-local dataset with a release whose SPM units all have a classified adult.
|
|
151
|
+
|
|
152
|
+
When they use it, US state and congressional-district regions scope one certified ACS-local
|
|
151
153
|
Populace dataset with row filters. Pass its non-default local-area release
|
|
152
154
|
manifest through `--regional-manifest-uri`; certification adds the pinned H5
|
|
153
155
|
artifact to `data_releases.us.datasets` and writes both regional path templates
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Disclosure control"
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Local results from survey microdata rest on few households, and a licence
|
|
6
|
+
binds every published number. `policyengine.disclosure` turns per-household
|
|
7
|
+
results into area tables that follow the licence's rules and carry their
|
|
8
|
+
uncertainty. Use it for every UK result below the national level that leaves
|
|
9
|
+
your machine.
|
|
10
|
+
|
|
11
|
+
```python
|
|
12
|
+
from policyengine.outputs import compute_uk_geography_disclosure
|
|
13
|
+
|
|
14
|
+
impact = compute_uk_geography_disclosure(
|
|
15
|
+
baseline_simulation=baseline,
|
|
16
|
+
reform_simulation=reform,
|
|
17
|
+
year=2026,
|
|
18
|
+
levels=("region", "constituency"),
|
|
19
|
+
reform="budget",
|
|
20
|
+
)
|
|
21
|
+
impact.findings # what blocks publication, if anything
|
|
22
|
+
impact.public # the rows that may be published, or None while blocked
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
The UK datasets derive from surveys under the UK Data Service End User
|
|
26
|
+
Licence. The defaults below follow its disclosure rules. You can raise them
|
|
27
|
+
for a study with stricter conditions; you cannot lower them.
|
|
28
|
+
|
|
29
|
+
## What a published row holds
|
|
30
|
+
|
|
31
|
+
Each row is one outcome for one area, reform and year.
|
|
32
|
+
|
|
33
|
+
| Column | Content |
|
|
34
|
+
|---|---|
|
|
35
|
+
| `level`, `area_code`, `reform`, `year`, `outcome` | The key of the row |
|
|
36
|
+
| `value`, `lo`, `hi` | The rounded estimate and its 90% interval |
|
|
37
|
+
| `direction` | `gain`, `loss`, `too_close_to_call` or `no_change` |
|
|
38
|
+
| `tier` | `reported`, `approximate` or `withheld` |
|
|
39
|
+
| `reason` | `thin_support` for an approximate row, `disclosure_control` for a withheld row |
|
|
40
|
+
| `support_band` | `<10`, `10–29` or `30+` survey households, never an exact count |
|
|
41
|
+
| `noise` | Whether the row carries keyed noise |
|
|
42
|
+
| `estimator` | `direct`: the estimate comes from the area's own records |
|
|
43
|
+
|
|
44
|
+
The outcomes are `average_change`, `relative_change`, `total_change`,
|
|
45
|
+
`share_gaining`, `share_losing` and `share_no_change`. A withheld row carries
|
|
46
|
+
no value, interval, direction or support band.
|
|
47
|
+
|
|
48
|
+
## The rules
|
|
49
|
+
|
|
50
|
+
**Count floor.** A number must rest on at least 10 distinct survey households
|
|
51
|
+
that contribute to it. For a change, a household contributes when its income
|
|
52
|
+
changes by more than `change_tolerance` (£1 a year, which is also the lowest
|
|
53
|
+
value the setting takes). Copies and clones of one survey household count
|
|
54
|
+
once, through the dataset's `source_household_id`. For a share, both sides
|
|
55
|
+
must pass: the households that gain and those that do not.
|
|
56
|
+
|
|
57
|
+
**Dominance.** While noise is off, a number is withheld in two cases:
|
|
58
|
+
|
|
59
|
+
- one survey household carries more than half of it, by size;
|
|
60
|
+
- the p% rule: a reader of the number, or one household that knows its own
|
|
61
|
+
part, could estimate some household's part to within 10%. Every household
|
|
62
|
+
is a possible target and every other household a possible reader, so the
|
|
63
|
+
rule also catches a total whose other parts cancel.
|
|
64
|
+
|
|
65
|
+
These rules protect each household against any reader and against any one
|
|
66
|
+
other household. They do not stop two or more households that pool what they
|
|
67
|
+
know: a number that three households carry almost alone passes, as long as 10
|
|
68
|
+
contribute.
|
|
69
|
+
|
|
70
|
+
**Effective sample.** Weights that differ a lot make an estimate less precise
|
|
71
|
+
than its household count suggests. Where the data gives one area and one
|
|
72
|
+
weight per record, a low effective sample makes a row `approximate`: it keeps
|
|
73
|
+
its value and interval, but the interval understates the uncertainty. Where
|
|
74
|
+
the data is an area × household weight matrix, the household count passes by
|
|
75
|
+
construction, so the effective sample must also be at least 10. Weights given
|
|
76
|
+
as a matrix keep this rule whatever they hold: one row of a dense matrix has
|
|
77
|
+
one weight per record, yet every household of the nation sits in that area.
|
|
78
|
+
|
|
79
|
+
**Zero cells.** A cell with no contributing household is published as zero,
|
|
80
|
+
with the interval [0, 0] and the direction `no_change`. It means that no
|
|
81
|
+
surveyed household in the area changed, not that no household there does. Its
|
|
82
|
+
support band counts the households it was measured on.
|
|
83
|
+
|
|
84
|
+
**Settings.** The layer validates its settings again before it uses them, so
|
|
85
|
+
a copy made with `model_copy(update=...)` cannot lower a floor.
|
|
86
|
+
|
|
87
|
+
**Linked outcomes.** Average, relative and total change share a numerator, so
|
|
88
|
+
they are published or withheld together. Gaining, losing and no change add to
|
|
89
|
+
one, so the third share is published only when it is safe to derive.
|
|
90
|
+
|
|
91
|
+
## Uncertainty and rounding
|
|
92
|
+
|
|
93
|
+
Intervals come from a Poisson bootstrap over survey households with 1,000
|
|
94
|
+
replicates. A ratio resamples its numerator and denominator together. The
|
|
95
|
+
weights stay fixed, so the intervals leave out calibration uncertainty and are
|
|
96
|
+
too narrow, most of all where support is thin.
|
|
97
|
+
|
|
98
|
+
Values are rounded to the order of magnitude of their standard error. The
|
|
99
|
+
interval is rounded outward on the same base.
|
|
100
|
+
|
|
101
|
+
## The release check
|
|
102
|
+
|
|
103
|
+
Published numbers constrain each other. If a region is public and all but one
|
|
104
|
+
of its constituencies are public, subtraction gives the last one. The check
|
|
105
|
+
looks for such remainders:
|
|
106
|
+
|
|
107
|
+
- child areas against their parent area (constituencies in regions, regions in
|
|
108
|
+
the nation);
|
|
109
|
+
- the components of a package against the package;
|
|
110
|
+
- when two levels that do not nest are released together, an area against
|
|
111
|
+
the areas of the other level that lie wholly inside it, and against the
|
|
112
|
+
areas that meet it (their sum minus the area is what they hold outside it);
|
|
113
|
+
- earlier publications, passed as `prior_public`.
|
|
114
|
+
|
|
115
|
+
A remainder gets the rules of a cell. Estimates added with `publish=False`
|
|
116
|
+
are a reference: the release does not emit their rows, but it treats the rows
|
|
117
|
+
that pass as public elsewhere and the withheld ones as secret, and checks
|
|
118
|
+
them like its own.
|
|
119
|
+
|
|
120
|
+
`compute_uk_geography_disclosure` always checks constituencies and local
|
|
121
|
+
authorities against their region, and regions against the nation, also when
|
|
122
|
+
you publish one level only. A level given as a weight matrix needs
|
|
123
|
+
`parent_of=` with the region of each area; without it the function raises,
|
|
124
|
+
because a check against the nation alone nearly always passes.
|
|
125
|
+
|
|
126
|
+
The check reports; it does not withhold cells by itself. A blocking finding
|
|
127
|
+
names the group and suggests a cell. Withhold it, then check again. When a
|
|
128
|
+
finding suggests no cell, withhold the parent (`finding.group` at
|
|
129
|
+
`finding.group_level`) instead:
|
|
130
|
+
|
|
131
|
+
```python
|
|
132
|
+
for finding in impact.findings:
|
|
133
|
+
print(finding.code, finding.group, finding.suggested)
|
|
134
|
+
|
|
135
|
+
impact.release.withhold(
|
|
136
|
+
level="constituency",
|
|
137
|
+
area_code="E14001234",
|
|
138
|
+
reform="budget",
|
|
139
|
+
year=2026,
|
|
140
|
+
outcome="average_change",
|
|
141
|
+
)
|
|
142
|
+
impact.refresh() # checks again and fills impact.public once nothing blocks
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Two findings can be accepted after review, with `acknowledge=[...]`:
|
|
146
|
+
|
|
147
|
+
- `unchecked_overlap`: levels that overlap without nesting, such as
|
|
148
|
+
constituencies and local authorities, are released together. The release
|
|
149
|
+
checks each area against the areas wholly inside it and against the areas
|
|
150
|
+
that meet it. It does not check other differences between overlapping
|
|
151
|
+
areas, and on weight-matrix data it checks none.
|
|
152
|
+
- `noise_reference_public`: an earlier table shows the same cells under
|
|
153
|
+
another noise setting.
|
|
154
|
+
|
|
155
|
+
## Noise
|
|
156
|
+
|
|
157
|
+
Noise is off by default. With `DisclosureSettings(noise=True)`, each survey
|
|
158
|
+
household's change is scaled by a fixed factor between 8% and 12% away from 1,
|
|
159
|
+
derived from its id and a secret key. The same household has the same factor
|
|
160
|
+
in every table and every rebuild. Noise replaces the dominance rule; the count
|
|
161
|
+
floor still applies. The range cannot start closer to 1 than 8%.
|
|
162
|
+
|
|
163
|
+
A number that one household dominates, published with noise, gives that
|
|
164
|
+
household's part to within 8 to 12%. The p% rule treats 10% as the line, so
|
|
165
|
+
noise puts such a number right at that line, not safely past it. Whether the
|
|
166
|
+
UK Data Service accepts noise in place of the dominance rule is a licence
|
|
167
|
+
question, which is why noise stays off by default.
|
|
168
|
+
|
|
169
|
+
- **Size.** The noise in a total is about a tenth of that total's sampling
|
|
170
|
+
error.
|
|
171
|
+
- **Key.** Pass `noise_key=` or set `POLICYENGINE_DISCLOSURE_NOISE_KEY`. There
|
|
172
|
+
is no default key. Keep the key out of repositories and CI logs, and do not
|
|
173
|
+
change it between releases of one dataset: two noised versions of a number
|
|
174
|
+
average towards the truth.
|
|
175
|
+
- **Limits.** Denominators carry no noise. The factor cancels in a ratio of
|
|
176
|
+
two numbers that the same household dominates. A remainder that subtraction
|
|
177
|
+
recovers is the noised sum of the withheld cells, so it has the protection
|
|
178
|
+
of a noised cell and no more: the count floor applies to it, and noise
|
|
179
|
+
stands in for the dominance rule as it does for a cell. An un-noised copy
|
|
180
|
+
of the same cell gives the factor away.
|
|
181
|
+
|
|
182
|
+
## Validating published files
|
|
183
|
+
|
|
184
|
+
`validate_public` checks the format of a table, a CSV file or a directory. It
|
|
185
|
+
needs no key and no microdata, so it can run on every pull request:
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
python -m policyengine.disclosure validate public/data --reviewed notes.csv
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
It rejects private audit columns, unknown tiers, a value in a withheld row,
|
|
192
|
+
unrounded values, a direction that does not match its interval, and files it
|
|
193
|
+
does not recognise. It cannot tell whether a number rested on enough
|
|
194
|
+
households; only the release that made the file can.
|
|
195
|
+
|
|
196
|
+
## Private objects
|
|
197
|
+
|
|
198
|
+
`audit_dir=` writes the exact values, household counts and shares behind every
|
|
199
|
+
row. The directory must be outside any git repository.
|
|
200
|
+
|
|
201
|
+
`AreaEstimates`, the object that `estimate_change` returns, holds the same
|
|
202
|
+
exact values. With noise on it also holds the noise factor of every household
|
|
203
|
+
that gains or loses, and within one dataset those factors do the same job as
|
|
204
|
+
the key. Keep it in memory and treat it as you treat the key. It cannot be
|
|
205
|
+
pickled or copied.
|
|
206
|
+
|
|
207
|
+
## What a reader can still derive
|
|
208
|
+
|
|
209
|
+
`average_change` and `relative_change` together give the area's total
|
|
210
|
+
baseline income to within a few per cent (household count × average ÷
|
|
211
|
+
relative). That total is a denominator: it carries no noise and is not
|
|
212
|
+
checked for dominance.
|
|
213
|
+
|
|
214
|
+
## Arrays without a simulation
|
|
215
|
+
|
|
216
|
+
The package works on arrays and imports nothing from the rest of the library:
|
|
217
|
+
|
|
218
|
+
```python
|
|
219
|
+
from policyengine.disclosure import AreaWeights, Release, estimate_change
|
|
220
|
+
|
|
221
|
+
seats = estimate_change(
|
|
222
|
+
level="constituency",
|
|
223
|
+
reform="budget",
|
|
224
|
+
year=2026,
|
|
225
|
+
areas=AreaWeights.from_labels(seat_codes, household_weights),
|
|
226
|
+
source_ids=source_household_ids,
|
|
227
|
+
baseline=baseline_net_income,
|
|
228
|
+
reformed=reformed_net_income,
|
|
229
|
+
)
|
|
230
|
+
release = Release()
|
|
231
|
+
release.add(seats)
|
|
232
|
+
release.check()
|
|
233
|
+
public = release.to_public()
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
`AreaWeights.from_matrix(matrix, area_codes)` takes an area × household weight
|
|
237
|
+
matrix instead. A dataset without `source_household_id` needs `source_ids=`
|
|
238
|
+
from the caller; the layer does not guess which records share a survey
|
|
239
|
+
household.
|
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
Use this runbook to certify a new national US Populace release together with
|
|
4
4
|
the shared ACS-local release used for state and congressional-district
|
|
5
|
-
simulations.
|
|
6
|
-
|
|
5
|
+
simulations. For now, state and district simulations use the national release
|
|
6
|
+
instead; see the interim exception in Step 2. Read the
|
|
7
|
+
[data certification](../skills/data-certification.md) skill first for
|
|
8
|
+
validation semantics.
|
|
7
9
|
|
|
8
10
|
This historical filename is retained so existing links remain valid; the
|
|
9
11
|
procedure itself is release-independent.
|
|
@@ -13,7 +15,8 @@ procedure itself is release-independent.
|
|
|
13
15
|
Both release manifests have been published to `policyengine/populace-us`, and
|
|
14
16
|
the model version used by the national release is known. The national release
|
|
15
17
|
will remain the default dataset; the local-area release will remain
|
|
16
|
-
non-default and be selected only for supported regional runs
|
|
18
|
+
non-default and be selected only for supported regional runs (none while the
|
|
19
|
+
interim exception in Step 2 holds).
|
|
17
20
|
|
|
18
21
|
## Prerequisites
|
|
19
22
|
|
|
@@ -60,6 +63,19 @@ This one command:
|
|
|
60
63
|
- writes the changelog fragment
|
|
61
64
|
`changelog.d/certify-us-$NATIONAL_RELEASE_ID.changed.md`.
|
|
62
65
|
|
|
66
|
+
**Interim exception (from policyengine 6.3.4; PolicyEngine/policyengine.py#604).**
|
|
67
|
+
State and congressional-district regions filter the national dataset until an
|
|
68
|
+
ACS-local release has no SPM unit without a classified adult
|
|
69
|
+
(PolicyEngine/microcosm#1263). Run the command above unchanged, with
|
|
70
|
+
`--regional-manifest-uri`: without it, certification drops the ACS-local
|
|
71
|
+
dataset and leaves no state or district template. Then, before Step 3, set
|
|
72
|
+
`region_datasets.state` and `region_datasets.congressional_district` in
|
|
73
|
+
`data_releases.us` to `{"path_template": "populace_us_2024.h5"}` by hand. In
|
|
74
|
+
Step 5, expect those two templates to select the national artifact, not the
|
|
75
|
+
local-area one. The data-certification skill
|
|
76
|
+
(`docs/engineering/skills/data-certification.md`) says what must hold before
|
|
77
|
+
the exception ends.
|
|
78
|
+
|
|
63
79
|
## Step 3 — regenerate TRACE sidecars
|
|
64
80
|
|
|
65
81
|
The certify step does not touch TRACE sidecars. Regenerate them so they record
|
|
@@ -87,15 +103,16 @@ PE_UPDATE_SNAPSHOTS=1 pytest tests/test_household_calculator_snapshot.py
|
|
|
87
103
|
|
|
88
104
|
## Step 5 — certify and verify the local-area release
|
|
89
105
|
|
|
90
|
-
The certification command passes the immutable ACS-local
|
|
91
|
-
`--regional-manifest-uri`. Confirm all of the following:
|
|
106
|
+
The certification command passes the immutable ACS-local
|
|
107
|
+
release manifest with `--regional-manifest-uri`. Confirm all of the following:
|
|
92
108
|
|
|
93
109
|
- `default_dataset` remains the national Populace dataset;
|
|
94
110
|
- the local-area artifact appears in `data_releases.us.datasets` with its
|
|
95
111
|
repository type, immutable revision, and SHA-256;
|
|
96
112
|
- `region_datasets.national` selects the national artifact;
|
|
97
113
|
- `region_datasets.state` and `region_datasets.congressional_district` select
|
|
98
|
-
the shared local-area artifact
|
|
114
|
+
the shared local-area artifact (the national artifact while the interim
|
|
115
|
+
exception in Step 2 holds);
|
|
99
116
|
- no derived `states/*.h5` or `districts/*.h5` artifacts are runtime inputs.
|
|
100
117
|
|
|
101
118
|
```bash
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# Legacy US SPM sources (backward compatibility)
|
|
2
|
+
|
|
3
|
+
> **Backward compatibility, not a data contract.** This layer exists so that
|
|
4
|
+
> certified US sources published *before* SPM declarations existed can still
|
|
5
|
+
> be measured. New certified sources must carry the declarations themselves;
|
|
6
|
+
> do not register them here.
|
|
7
|
+
|
|
8
|
+
policyengine-us measures SPM poverty only when a source declares two things:
|
|
9
|
+
|
|
10
|
+
- **Measurement scope:** which SPM units are inside the SPM measurement
|
|
11
|
+
population (`spm_unit_spm_universe_status`: `INCLUDED`/`OUTSIDE`, the
|
|
12
|
+
contract of PolicyEngine/microcosm#977).
|
|
13
|
+
- **Independence role:** which 15–17-year-olds independently head their own
|
|
14
|
+
SPM unit (`is_spm_independent_minor_role`).
|
|
15
|
+
|
|
16
|
+
A legacy source carries neither. Every SPM calculation on it stops with
|
|
17
|
+
`SPM_COMPOSITION_REQUIRED` ("SPM unit has no classified adult").
|
|
18
|
+
|
|
19
|
+
The package
|
|
20
|
+
[`policyengine.tax_benefit_models.us.legacy_spm`](../../../src/policyengine/tax_benefit_models/us/legacy_spm/__init__.py)
|
|
21
|
+
derives the missing declarations from evidence a legacy source does carry.
|
|
22
|
+
Nobody is dropped: memberships, weights and every ordinary tax, benefit and
|
|
23
|
+
income calculation are unchanged.
|
|
24
|
+
|
|
25
|
+
## Registered sources
|
|
26
|
+
|
|
27
|
+
Sources are keyed by certified SHA-256 in `legacy_spm/registry.py`.
|
|
28
|
+
|
|
29
|
+
| Source | Scope rule | Independence list |
|
|
30
|
+
| --- | --- | --- |
|
|
31
|
+
| `populace_us_2024_acs_local` Build O (`769756c3…a7ec`) | `acs_household_population` | national release `source_spm_person_independence.csv` (`22b5968d…3ce5`) |
|
|
32
|
+
|
|
33
|
+
### Scope rule `acs_household_population` (#597)
|
|
34
|
+
|
|
35
|
+
Census's ACS SPM methodology measures the household population only.
|
|
36
|
+
|
|
37
|
+
- ACS records with `TYPEHUGQ` 2 or 3 and the matching `RELSHIPP` (37 or 38) are
|
|
38
|
+
group quarters, so their SPM units are `OUTSIDE`.
|
|
39
|
+
- ACS housing-unit records are `INCLUDED`.
|
|
40
|
+
- Records from the `asec` and `puf_tax_detail` channels are `INCLUDED`.
|
|
41
|
+
|
|
42
|
+
Age is never used. Unknown channels, missing or inconsistent evidence, and SPM
|
|
43
|
+
units that mix group quarters with household people all raise.
|
|
44
|
+
|
|
45
|
+
On the full Build O source, 183,206 SPM units are outside the measurement.
|
|
46
|
+
|
|
47
|
+
### Independence list (#598)
|
|
48
|
+
|
|
49
|
+
The source's ASEC/PUF records are the same records the certified national
|
|
50
|
+
release carries with a source-backed independence role. The list is joined by
|
|
51
|
+
`person_id` and `person_spm_unit_id`, and the join must be exact:
|
|
52
|
+
|
|
53
|
+
- every ASEC/PUF person appears once, in the same SPM unit;
|
|
54
|
+
- the list names nobody else.
|
|
55
|
+
|
|
56
|
+
ACS people keep the model's own fallback (household head or spouse).
|
|
57
|
+
|
|
58
|
+
On Build O, exactly 28 units change: Census-built units around an independent
|
|
59
|
+
teen.
|
|
60
|
+
|
|
61
|
+
## How runs get the declarations
|
|
62
|
+
|
|
63
|
+
| Path | What happens |
|
|
64
|
+
| --- | --- |
|
|
65
|
+
| `create_datasets` / `ensure_datasets` | Year files store the declarations as ordinary input columns, with a `policyengine_legacy_spm_declarations` record. |
|
|
66
|
+
| `Simulation.run()` over a raw legacy source file | The declarations are derived in memory. The file is recognised by its evidence columns and then its SHA-256, which is hashed once per process. |
|
|
67
|
+
| `managed_microsimulation` | The declarations are derived from the loaded tables and set on the simulation and its branches. |
|
|
68
|
+
|
|
69
|
+
`legacy_spm.model_adapter` then makes the model honour the scope:
|
|
70
|
+
|
|
71
|
+
- **native:** policyengine-us defines `spm_unit_spm_universe_status`
|
|
72
|
+
(PolicyEngine/policyengine-us#9462). The declaration is just an input, and
|
|
73
|
+
nothing is overridden.
|
|
74
|
+
- **override:** policyengine-us 2.2.1 cannot read it. A variable-only reform:
|
|
75
|
+
- adds the input;
|
|
76
|
+
- wraps the installed SPM chain so that outside units never reach the
|
|
77
|
+
canonical provider and every SPM outcome for them is NaN ("not measured").
|
|
78
|
+
|
|
79
|
+
Poverty indicators become floats (1.0, 0.0 or NaN). The override wraps the
|
|
80
|
+
installed formulas, with one exception: `spm_unit_income_decile` ranks
|
|
81
|
+
units, so it is recalculated over measured units with the installed method.
|
|
82
|
+
A contract test pins that method. The override refuses to run if the SPM
|
|
83
|
+
chain no longer has the verified shape.
|
|
84
|
+
|
|
85
|
+
Poverty rates count measured people only. A group with nobody measured has a
|
|
86
|
+
rate of `None`, not 0.
|
|
87
|
+
|
|
88
|
+
## Staleness
|
|
89
|
+
|
|
90
|
+
The record holds a `LegacySPMProfile`: the registry entry plus
|
|
91
|
+
`ADAPTER_REVISION`. Checks are total and exact, like the year-file stamp:
|
|
92
|
+
|
|
93
|
+
- `ensure_datasets` cuts a year file again, and `load_datasets` refuses it, when
|
|
94
|
+
its record is absent, unreadable, malformed, or from another profile.
|
|
95
|
+
- `Simulation.load()` refuses an output saved under a different profile.
|
|
96
|
+
|
|
97
|
+
Raise `ADAPTER_REVISION` whenever a change to derivation or the override means
|
|
98
|
+
existing files must be made again.
|
|
99
|
+
|
|
100
|
+
## When the model or data changes
|
|
101
|
+
|
|
102
|
+
- **policyengine-us gains native scope (#9462).**
|
|
103
|
+
`test_the_installed_model_does_not_read_scope_natively_yet` fails. Check that
|
|
104
|
+
the native members include `INCLUDED` and `OUTSIDE`, and confirm the native
|
|
105
|
+
runs in the integration tests. Then delete the override half of
|
|
106
|
+
`model_adapter` (keep the derivation) and raise `ADAPTER_REVISION`.
|
|
107
|
+
- **The SPM chain changes.** `test_the_override_covers_every_variable_that_depends_on_the_provider`,
|
|
108
|
+
`test_the_installed_chain_has_the_verified_shape` or
|
|
109
|
+
`test_the_recalculated_decile_matches_the_installed_method` fails. Re-verify
|
|
110
|
+
the override against the new chain before bumping the pin.
|
|
111
|
+
- **A rebuilt source declares scope and role itself.** Point the bundle at it.
|
|
112
|
+
Keep the Build O registry entry only while anything still reads Build O,
|
|
113
|
+
then delete it.
|
|
114
|
+
|
|
115
|
+
## Related
|
|
116
|
+
|
|
117
|
+
- Microcosm #977: scope classification at source.
|
|
118
|
+
- Microcosm #959: independence role in US builds.
|
|
119
|
+
- policyengine-us #9462: native scope.
|
|
120
|
+
- policyengine.py #519: nullable SPM summaries.
|
|
121
|
+
- The year-file and output stamps (#590, and #593/#594 in flight). Fold this
|
|
122
|
+
record into them once those land.
|
|
@@ -35,8 +35,33 @@ python scripts/bundle.py certify-data --country us --data-producer populace \
|
|
|
35
35
|
--model-version "<policyengine-us-version>"
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
**Interim exception (from policyengine 6.3.4; PolicyEngine/policyengine.py#604).**
|
|
39
|
+
State and congressional-district regions currently filter the certified
|
|
40
|
+
national dataset, not the ACS-local one. The certified ACS-local release has
|
|
41
|
+
no source-backed SPM independence, so canonical SPM refuses its SPM units that
|
|
42
|
+
have no classified adult, and with them every state-region run
|
|
43
|
+
(PolicyEngine/microcosm#1263, PolicyEngine/policyengine-sim-api#747). The 6.3.4
|
|
44
|
+
manifest was certified with `--regional-manifest-uri`, as below, and then
|
|
45
|
+
edited by hand. Until the exception ends, do the same:
|
|
46
|
+
|
|
47
|
+
- still pass `--regional-manifest-uri`. Without it, certification rewrites
|
|
48
|
+
`data_releases.us` from the national manifest alone, which drops the
|
|
49
|
+
ACS-local dataset and leaves no state or district template at all;
|
|
50
|
+
- then set `region_datasets.state` and `region_datasets.congressional_district`
|
|
51
|
+
to `{"path_template": "populace_us_2024.h5"}` by hand, before regenerating
|
|
52
|
+
the TRACE sidecars. `tests/test_release_manifests.py` fails if they name
|
|
53
|
+
the ACS-local file, and also if the ACS-local dataset is no longer
|
|
54
|
+
certified.
|
|
55
|
+
|
|
56
|
+
Restore the ACS-local regions only with an ACS-local release in which every
|
|
57
|
+
SPM unit has at least one classified adult under the pinned spm-calculator's
|
|
58
|
+
rule (zero unclassified units), and after a state-region run through the
|
|
59
|
+
public wrapper succeeds on it. Then remove this exception, the temporary test
|
|
60
|
+
and the matching notes in `docs/regions.md` and `docs/bundles.md`.
|
|
61
|
+
|
|
62
|
+
Outside that exception, US state and congressional-district regions are row
|
|
63
|
+
filters over one shared, certified ACS-local Populace dataset. Its release
|
|
64
|
+
manifest must declare
|
|
40
65
|
`dataset_role: non_default_local_area`, `is_default: false`, no default
|
|
41
66
|
datasets, and exactly one pinned H5 microdata artifact. Certification writes:
|
|
42
67
|
|
|
@@ -16,6 +16,13 @@ Applying parametric reforms, comparing baseline and reform with `ChangeAggregate
|
|
|
16
16
|
```{.python include="../examples/policy_change_uk.py"}
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
+
## UK geography results under disclosure control
|
|
20
|
+
|
|
21
|
+
Estimating results by area from per-household arrays, checking the release, withholding a cell and validating the public table. The data is synthetic.
|
|
22
|
+
|
|
23
|
+
```{.python include="../examples/uk_geography_disclosure.py"}
|
|
24
|
+
```
|
|
25
|
+
|
|
19
26
|
## UK income bands
|
|
20
27
|
|
|
21
28
|
Calculating net income and tax by income decile using representative microdata and `Aggregate` with quantile filters.
|
|
@@ -87,6 +87,24 @@ before passing them to the country model. Generic adult/child counts remain
|
|
|
87
87
|
separate. The native source enrichment is not recalibration, and inherited
|
|
88
88
|
schema-5 calibration diagnostics cannot be relabeled as schema 6.
|
|
89
89
|
|
|
90
|
+
**Legacy SPM sources (backward compatibility).** Some certified US sources
|
|
91
|
+
predate SPM declarations, for example the ACS-local Build O release. For those
|
|
92
|
+
sources, .py derives the declarations from evidence they carry, following
|
|
93
|
+
Census's ACS SPM methodology, which measures the household population only:
|
|
94
|
+
|
|
95
|
+
- ACS group-quarters SPM units are outside the SPM measurement. Their SPM
|
|
96
|
+
thresholds, resources and poverty indicators are missing (NaN).
|
|
97
|
+
- Poverty indicators on those sources are floats: 1.0, 0.0, or NaN for "not
|
|
98
|
+
measured".
|
|
99
|
+
- Poverty rates count measured people only. A group with nobody measured has
|
|
100
|
+
a rate of `None`, not 0.
|
|
101
|
+
- The sources' ASEC and PUF records take the certified SPM independence role
|
|
102
|
+
from the national release.
|
|
103
|
+
|
|
104
|
+
Ordinary tax, benefit and income results are unchanged. Outputs record the
|
|
105
|
+
declarations they used under `legacy_spm_declarations`. See
|
|
106
|
+
[the runbook](engineering/runbooks/us-legacy-spm-sources.md).
|
|
107
|
+
|
|
90
108
|
The wrapper's native pandas HDF loader accepts files that store only calibrated
|
|
91
109
|
`household_weight`. It maps missing person and group weight columns through
|
|
92
110
|
native membership IDs in memory, retaining supplied weight columns and the
|
|
@@ -167,6 +167,12 @@ rate.run()
|
|
|
167
167
|
rate.headcount, rate.total_population, rate.rate
|
|
168
168
|
```
|
|
169
169
|
|
|
170
|
+
`rate.rate` is `None` when nobody in the group is measured: the group's
|
|
171
|
+
weighted population with a poverty status is zero, for example a filter that
|
|
172
|
+
matches no one, or a group whose members are all outside the SPM measurement
|
|
173
|
+
on a legacy source. That is not a measured rate of zero, so handle `None`
|
|
174
|
+
before formatting or subtracting rates.
|
|
175
|
+
|
|
170
176
|
For all canonical poverty measures over one simulation:
|
|
171
177
|
|
|
172
178
|
```python
|
|
@@ -260,7 +266,28 @@ for row in impacts.district_results:
|
|
|
260
266
|
print(row["district_geoid"], row["avg_change"], row["winner_percentage"])
|
|
261
267
|
```
|
|
262
268
|
|
|
263
|
-
### UK constituencies
|
|
269
|
+
### UK regions, constituencies and local authorities
|
|
270
|
+
|
|
271
|
+
`compute_uk_geography_disclosure` returns results by area under disclosure
|
|
272
|
+
control: each number passes a floor on the survey households behind it and
|
|
273
|
+
carries a 90% interval. Use it for anything you publish. See
|
|
274
|
+
[Disclosure control](disclosure.md).
|
|
275
|
+
|
|
276
|
+
```python
|
|
277
|
+
from policyengine.outputs import compute_uk_geography_disclosure
|
|
278
|
+
|
|
279
|
+
impact = compute_uk_geography_disclosure(
|
|
280
|
+
baseline_simulation=baseline,
|
|
281
|
+
reform_simulation=reform,
|
|
282
|
+
year=2026,
|
|
283
|
+
levels=("region", "constituency"),
|
|
284
|
+
)
|
|
285
|
+
impact.public.to_frame()
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
The two older functions below are deprecated. Their output is not
|
|
289
|
+
disclosure-controlled, so do not publish it when the data is licensed survey
|
|
290
|
+
microdata.
|
|
264
291
|
|
|
265
292
|
Constituency and local-authority breakdowns group household output rows by
|
|
266
293
|
dataset-provided longwise geography columns. Constituencies use
|
|
@@ -23,9 +23,13 @@ ca_snap = Aggregate(
|
|
|
23
23
|
ca_snap.run()
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
Each state is a region in the US registry. State regions load the
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
Each state is a region in the US registry. State regions load the Populace
|
|
27
|
+
dataset declared by `region.dataset_path`, then scope its rows by `state_fips`.
|
|
28
|
+
They do not require separate state H5 files.
|
|
29
|
+
|
|
30
|
+
**Temporarily**, state and congressional-district regions filter the certified national dataset (`populace_us_2024`), as in policyengine 6.2.1. The certified ACS-local release has no source-backed SPM independence, so canonical SPM refuses thousands of its SPM units (PolicyEngine/microcosm#1263, PolicyEngine/policyengine-sim-api#747). They move back to the ACS-local dataset with a release whose SPM units all have a classified adult.
|
|
31
|
+
|
|
32
|
+
For example:
|
|
29
33
|
|
|
30
34
|
```python
|
|
31
35
|
states = pe.us.model.region_registry.get_by_type("state")
|
|
@@ -52,7 +56,8 @@ for row in impacts.district_results:
|
|
|
52
56
|
|
|
53
57
|
`district_geoid` is the SSDD integer (state FIPS × 100 + district number;
|
|
54
58
|
at-large districts use `00`). Congressional district regions load the same
|
|
55
|
-
|
|
59
|
+
file as state regions (for now the national dataset; see above) and scope its rows by
|
|
60
|
+
`congressional_district_geoid`.
|
|
56
61
|
|
|
57
62
|
## UK countries
|
|
58
63
|
|
|
@@ -88,6 +93,11 @@ national UK dataset.
|
|
|
88
93
|
|
|
89
94
|
## UK parliamentary constituencies
|
|
90
95
|
|
|
96
|
+
To publish results by constituency, local authority or region, use
|
|
97
|
+
`compute_uk_geography_disclosure`; see [Disclosure control](disclosure.md).
|
|
98
|
+
The functions in this section and the next are deprecated: their output is
|
|
99
|
+
not disclosure-controlled.
|
|
100
|
+
|
|
91
101
|
Constituency-level impacts group household output rows by the longwise
|
|
92
102
|
`constituency_code_oa` column carried by the dataset. If the constituency CSV is
|
|
93
103
|
available locally or from the PolicyEngine UK GCS bucket, PolicyEngine uses it
|
|
@@ -207,7 +207,8 @@ python scripts/bundle.py certify-data --country us --data-producer populace \
|
|
|
207
207
|
|
|
208
208
|
That produces one US bundle manifest entry containing the Populace national
|
|
209
209
|
default dataset and the certified ACS-local regional dataset. State and
|
|
210
|
-
congressional-district simulations use
|
|
210
|
+
congressional-district simulations use one of them with runtime row filters (for now the
|
|
211
|
+
national dataset; see [Regions](regions.md)), so
|
|
211
212
|
derived `states/*.h5` or `districts/*.h5` files are not vendored into
|
|
212
213
|
`data_releases.us.datasets`.
|
|
213
214
|
|