Skip to content

Comments

Add ability to run impacts over subnational regions#231

Merged
anth-volk merged 8 commits intoapp-v2-migrationfrom
feat/add-region-handling
Feb 16, 2026
Merged

Add ability to run impacts over subnational regions#231
anth-volk merged 8 commits intoapp-v2-migrationfrom
feat/add-region-handling

Conversation

@anth-volk
Copy link
Contributor

@anth-volk anth-volk commented Feb 10, 2026

Fixes #230
Fixes #232

Summary

Add support for running policy impact calculations at subnational geographic levels, and fix US reform application.

Changes

Core Region Model (src/policyengine/core/region.py)

  • Region class with code, label, type, and optional dataset paths (HuggingFace/GCS)
  • RegionRegistry for O(1) lookups by code or type with automatic index rebuilding

US Regions (src/policyengine/countries/us/)

  • States: 51 entries (50 states + DC) with FIPS codes
  • Congressional Districts: 436 districts with state-district codes
  • Places/Cities: 333 places matching app v2 exactly

UK Regions (src/policyengine/countries/uk/)

  • Countries: England, Wales, Scotland, Northern Ireland
  • Regions: 12 UK regions
  • Local Authorities: ~370 LAs with reweighting dataset support
  • Constituencies: ~650 constituencies with reweighting dataset support

US Reform Application Fix (#232)

  • Added reform_dict_from_parameter_values() utility to convert ParameterValue objects to reform dict format
  • Updated US model.py to pass reforms at Microsimulation construction time instead of using p.update() after construction
  • This fixes a silent failure where US reforms had no effect due to the shared singleton TaxBenefitSystem in policyengine-us

Integration

  • TaxBenefitModelVersion.regions property for accessing region registries
  • Region registries accessible via US and UK model versions

Testing

  • Unit tests for Region and RegionRegistry classes
  • Country-specific tests validating US and UK region counts and data integrity
  • Unit tests for reform_dict_from_parameter_values() utility (12 tests)
  • Integration tests for US reform application (6 tests)
  • All tests use given-when-then format with fixtures

Verification

Verified budgetary impacts at 3 geographic levels with CTC increase reform:

Region Budgetary Impact Share
US Nationwide $48.1B 100%
Nevada (state) $496M 1.03% of US
NV-01 (district) $122M 24.5% of NV

Subnational impacts are proportional to population shares, confirming correct calculation.

Verified US reform application fix:

Test Baseline Tax Reform Tax Change
Society-wide $2.02T $1.73T -$287B (-14.19%)
Household $12,682 $6,528 -$6,154

anth-volk and others added 7 commits February 16, 2026 23:33
- Remove unused imports
- Sort imports correctly
- Format code with ruff

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The sample_registry fixture was not being discovered by pytest
after linting removed unused imports. Moving fixture imports to
conftest.py is the standard pytest pattern for shared fixtures.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add filter_field and filter_value parameters to Simulation class
- Add _build_entity_relationships() to US and UK models for mapping
  persons to all containing entities
- Add _filter_dataset_by_household_variable() to filter datasets while
  preserving entity integrity
- Apply filtering in run() method when filter parameters are set

This enables filtering datasets by household-level variables like
place_fips (US) or country (UK) for regional analysis.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add filtering_fixtures.py with US and UK test datasets
- Add 18 unit tests for _build_entity_relationships and
  _filter_dataset_by_household_variable methods
- Tests follow given-when-then pattern
- All tests pass

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The US country package uses a shared singleton TaxBenefitSystem, which
means p.update() after Microsimulation construction has no effect on
calculations. This fix:

- Adds reform_dict_from_parameter_values() utility to convert
  ParameterValue objects to the dict format accepted by Microsimulation
- Updates US model.py to build reform dict and pass it at construction
  time instead of using simulation_modifier (p.update) after
- Adds comprehensive unit tests for the utility function and US reform
  application

The UK model continues to use p.update() since policyengine-uk was
refactored to give each simulation its own TaxBenefitSystem instance.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Remove unused imports in test_us_reform_application.py.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@anth-volk anth-volk force-pushed the feat/add-region-handling branch from ef193d5 to 2f52b03 Compare February 16, 2026 22:35
Extract duplicated entity relationship and dataset filtering logic from
US and UK model.py into shared utils/entity_utils.py. Decompose inline
reform dict construction in US run() into single-purpose functions
(build_reform_dict, merge_reform_dicts) in utils/parametric_reforms.py.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@anth-volk anth-volk marked this pull request as ready for review February 16, 2026 23:00
@anth-volk anth-volk merged commit 92ce3e2 into app-v2-migration Feb 16, 2026
2 checks passed
@anth-volk anth-volk deleted the feat/add-region-handling branch February 16, 2026 23:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add ability to run impacts over subnational regions

1 participant