Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions chronicle/source_package.py
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,7 @@
),
"soi-table-4-3": Path("irs_soi/table_4_3"),
"soi-state-2022": Path("irs_soi/state_2022"),
"soi-state-2023": Path("irs_soi/state_2023"),
"soi-county-2022": Path("irs_soi/county_2022"),
"soi-congressional-district-2022": Path("irs_soi/congressional_district_2022"),
"soi-historic-table-2": Path("irs_soi/historic_table_2"),
Expand All @@ -374,7 +375,11 @@
"soi-ira-traditional-contributions-2022": Path(
"irs_soi/ira_traditional_contributions_2022"
),
"soi-ira-traditional-contributions-2023": Path(
"irs_soi/ira_traditional_contributions_2023"
),
"soi-ira-roth-contributions-2022": Path("irs_soi/ira_roth_contributions_2022"),
"soi-ira-roth-contributions-2023": Path("irs_soi/ira_roth_contributions_2023"),
"ssa-annual-statistical-supplement-2025": Path(
"ssa/annual_statistical_supplement_2025"
),
Expand Down
48 changes: 46 additions & 2 deletions chronicle/sources/cells.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from zipfile import ZipFile

import openpyxl
from openpyxl.cell.cell import MergedCell
import xlrd

from chronicle.epoch import EMIT_EPOCH, HASH_DOMAINS, Epoch, hash_domain
Expand Down Expand Up @@ -172,8 +173,9 @@ def source_cells_from_xlsx(
if sheets and sheet.title not in sheets:
continue
formula_sheet = formula_workbook[sheet.title]
for row_index in range(1, sheet.max_row + 1):
for column_index in range(1, sheet.max_column + 1):
max_row, max_column = _xlsx_used_range_bounds(sheet)
for row_index in range(1, max_row + 1):
for column_index in range(1, max_column + 1):
cell = sheet.cell(row=row_index, column=column_index)
formula_cell = formula_sheet.cell(
row=row_index,
Expand All @@ -199,6 +201,48 @@ def source_cells_from_xlsx(
return cells


# The last column (XFD) and row an .xlsx worksheet can address.
_XLSX_MAX_COLUMN = 16_384
_XLSX_MAX_ROW = 1_048_576


def _xlsx_used_range_bounds(sheet: Any) -> tuple[int, int]:
"""Return the (max_row, max_column) of a worksheet's used range.

This is openpyxl's ``(sheet.max_row, sheet.max_column)`` unless the sheet
has a merged range that runs to the worksheet edge. openpyxl fills every
position of a merged range with a ``MergedCell`` placeholder, so one
footnote row merged across the whole sheet width (``A179:XFD179`` in the
IRS's TY2023 ``23in54us.xlsx``) stretches ``max_column`` to 16,384 and the
used range to about 70 million empty cells. Such an edge-to-edge range is
sheet-width formatting, not table extent: its placeholders do not widen
the bounds, while its anchor cell and every other cell still do. Sheets
without one keep openpyxl's bounds exactly.
"""
edge_ranges = [
cell_range
for cell_range in sheet.merged_cells.ranges
if cell_range.max_col >= _XLSX_MAX_COLUMN or cell_range.max_row >= _XLSX_MAX_ROW
]
if not edge_ranges:
return sheet.max_row, sheet.max_column

def edge_placeholder(row_index: int, column_index: int, cell: Any) -> bool:
return isinstance(cell, MergedCell) and any(
cell_range.min_row <= row_index <= cell_range.max_row
and cell_range.min_col <= column_index <= cell_range.max_col
for cell_range in edge_ranges
)

max_row = max_column = 1
for (row_index, column_index), cell in sheet._cells.items():
if edge_placeholder(row_index, column_index, cell):
continue
max_row = max(max_row, row_index)
max_column = max(max_column, column_index)
return max_row, max_column


def source_cells_from_ods(
content: bytes,
artifact: SourceArtifactMetadata,
Expand Down
1 change: 1 addition & 0 deletions chronicle/targets/us_poverty.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ def has_chronicle_package(self) -> bool:
"soi-filing-season-week47-2024-eitc-total",
"soi-table-4-3",
"soi-state-2022",
"soi-state-2023",
"soi-historic-table-2",
"soi-historic-table-2-state-agi-2022",
"soi-historic-table-2-state-broad-2022",
Expand Down
Binary file added db/data/irs_soi/ira_contributions/23in05ira.xlsx
Binary file not shown.
Binary file added db/data/irs_soi/ira_contributions/23in06ira.xlsx
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
source_id: irs_soi
package_id: soi-ira-roth-contributions-2023
dataset: irs_soi_roth_ira_contributions_2023
source_page: https://www.irs.gov/statistics/soi-tax-stats-accumulation-and-distribution-of-individual-retirement-arrangements
table: Table 6. Taxpayers with Roth Individual Retirement Arrangement (IRA) Plan Contributions,
by Size of Contribution and Age of Taxpayer
files:
2023:
filename: 23in06ira.xlsx
source_url: https://www.irs.gov/pub/irs-soi/23in06ira.xlsx
sha256: b526e4d4163172ed9992d16375cbf601b1c8b4d5bcf66f86e038c0e91c420418
size_bytes: 11380
fetched_at: '2026-09-27T05:55:43+00:00'
source_table: Table 6. Taxpayers with Roth Individual Retirement Arrangement (IRA)
Plan Contributions, by Size of Contribution and Age of Taxpayer
storage:
r2:
provider: r2
bucket: ledger-raw
key: raw/irs_soi/soi-ira-roth-contributions-2023/2023/b526e4d4163172ed9992d16375cbf601b1c8b4d5bcf66f86e038c0e91c420418/23in06ira.xlsx
uri: r2://ledger-raw/raw/irs_soi/soi-ira-roth-contributions-2023/2023/b526e4d4163172ed9992d16375cbf601b1c8b4d5bcf66f86e038c0e91c420418/23in06ira.xlsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
source_id: irs_soi
package_id: soi-ira-traditional-contributions-2023
dataset: irs_soi_traditional_ira_contributions_2023
source_page: https://www.irs.gov/statistics/soi-tax-stats-accumulation-and-distribution-of-individual-retirement-arrangements
table: Table 5. Taxpayers with Traditional Individual Retirement Arrangement (IRA)
Plan Contributions, by Size of Contribution and Age of Taxpayer
files:
2023:
filename: 23in05ira.xlsx
source_url: https://www.irs.gov/pub/irs-soi/23in05ira.xlsx
sha256: 17b02670eeb35dab5d3f8be6a26333d527993f8b22933fa77bb3a06f3c8ad143
size_bytes: 11345
fetched_at: '2026-09-27T05:55:45+00:00'
source_table: Table 5. Taxpayers with Traditional Individual Retirement Arrangement
(IRA) Plan Contributions, by Size of Contribution and Age of Taxpayer
storage:
r2:
provider: r2
bucket: ledger-raw
key: raw/irs_soi/soi-ira-traditional-contributions-2023/2023/17b02670eeb35dab5d3f8be6a26333d527993f8b22933fa77bb3a06f3c8ad143/23in05ira.xlsx
uri: r2://ledger-raw/raw/irs_soi/soi-ira-traditional-contributions-2023/2023/17b02670eeb35dab5d3f8be6a26333d527993f8b22933fa77bb3a06f3c8ad143/23in05ira.xlsx
Binary file added db/data/irs_soi/state_2023/23in54us.xlsx
Binary file not shown.
18 changes: 18 additions & 0 deletions db/data/irs_soi/state_2023/manifest.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
source_id: irs_soi
package_id: soi-state-2023
dataset: irs_soi_state_2023
source_page: https://www.irs.gov/statistics/soi-tax-stats-historic-table-2
table: IRS SOI State Data 2023
files:
2023:
filename: 23in54us.xlsx
source_url: https://www.irs.gov/pub/irs-soi/23in54us.xlsx
sha256: 4bc45f2586fb924c1e0e7818773096bdcf71223b6407120ca058efaed728607a
size_bytes: 265549
fetched_at: '2026-09-27T05:55:34+00:00'
storage:
r2:
provider: r2
bucket: ledger-raw
key: raw/irs_soi/soi-state-2023/2023/4bc45f2586fb924c1e0e7818773096bdcf71223b6407120ca058efaed728607a/23in54us.xlsx
uri: r2://ledger-raw/raw/irs_soi/soi-state-2023/2023/4bc45f2586fb924c1e0e7818773096bdcf71223b6407120ca058efaed728607a/23in54us.xlsx
2 changes: 1 addition & 1 deletion docs/pe-calibration-targets.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ them to model variables.
|---|---|---|
| Population by age, sex, state, and congressional district | Census PEP and ACS demographics | `census-pep-2024-national-age-sex`, `census-pep-2024-state-age-sex`, `census-acs-s0101-national-age-2024`, `census-acs-s0101-state-age-2024`, `census-acs-s0101-congressional-district-age-2024` |
| NIPA personal income, transfers, taxes, and pensions | BEA NIPA full-population aggregates | `bea-nipa-total-wages-salaries`, `bea-nipa-personal-income-components`, `bea-nipa-personal-income-disposition`, `bea-nipa-pension-contributions` |
| SOI filer income, taxes, deductions, and credits | IRS SOI administrative totals | `soi-table-1-1`, `soi-table-1-2`, `soi-table-1-4`, `soi-table-2-1`, `soi-table-2-5`, `soi-table-2-5-eitc-agi-children-2023`, `soi-table-4-3`, `soi-state-2022`, `soi-historic-table-2`, `soi-historic-table-2-state-agi-2022`, `soi-historic-table-2-state-broad-2022`, `soi-historic-table-2-state-eitc-2022`, `soi-w2-statistics-2020` |
| SOI filer income, taxes, deductions, and credits | IRS SOI administrative totals | `soi-table-1-1`, `soi-table-1-2`, `soi-table-1-4`, `soi-table-2-1`, `soi-table-2-5`, `soi-table-2-5-eitc-agi-children-2023`, `soi-table-4-3`, `soi-state-2022`, `soi-state-2023`, `soi-historic-table-2`, `soi-historic-table-2-state-agi-2022`, `soi-historic-table-2-state-broad-2022`, `soi-historic-table-2-state-eitc-2022`, `soi-w2-statistics-2020` |
| Social Security and SSI | SSA administrative totals | `ssa-annual-statistical-supplement-2025`, `ssa-ssi-table-7b1-2024` |
| SNAP | USDA FNS administrative totals | `usda-snap-fy69-to-current` |
| TANF | HHS ACF caseload and financial totals | `hhs-acf-tanf-caseload-2024`, `hhs-acf-tanf-financial-2024` |
Expand Down
69 changes: 69 additions & 0 deletions packages/irs_soi/ira_roth_contributions_2023/source_package.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
schema_version: ledger.source_package.v1
package_id: soi-ira-roth-contributions-2023
label: IRS SOI 2023 Roth IRA contribution totals
dimension_labels:
'irs_soi.ira_contribution_size': 'IRA contribution size'
artifact:
source_name: irs_soi
source_table: Table 6. Taxpayers with Roth Individual Retirement Arrangement (IRA) Plan Contributions, by Size of Contribution and Age of Taxpayer
resource_package: db
resource_directory: data/irs_soi/ira_contributions
manifest: manifest_roth_2023_source_package.yaml
vintage: tax_year_2023
extracted_at: '2026-09-27'
extraction_method: xlsx whole-workbook used-range cell parse
parser: xlsx_used_range
artifact_year: 2023
record_sets:
- record_set_id: irs_soi.ty2023.roth_ira_contributions.all_taxpayers
provenance_class: administrative
record_set_spec_id: irs_soi.roth_ira_contributions.all_taxpayers.v1
source_record_id_prefix: irs_soi.ty2023.roth_ira_contributions.all_taxpayers
sheet_name: Estimates
period_type: tax_year
period: '2023'
geography_id: 0100000US
geography_level: country
geography_name: United States
geography_vintage: current
entity: tax_unit
entity_role: filing_unit
domain: individual_retirement_arrangement_contributions
groupby_dimension: irs_soi.ira_contribution_size
rows:
- value_id: all_taxpayers
label: All taxpayers
ordinal: 0
row_number: 7
expected_row_header_column: A
expected_row_header: All taxpayers
table_record_kind: total
guard_cells:
- column: B
row: 4
expected_value: Total
label: total contribution size
measures:
- measure_id: taxpayer_count
label: Number of taxpayers
ordinal: 0
column: B
source_column_id: number_of_taxpayers
expected_column_header_row: 5
expected_column_header: Number of taxpayers
concept: irs_soi.roth_ira_contributors
unit: count
aggregation: sum
expected_cell_type: number
- measure_id: amount
label: Contribution amount
ordinal: 1
column: C
source_column_id: amount
expected_column_header_row: 5
expected_column_header: Amount
concept: irs_soi.roth_ira_contributions
unit: usd
aggregation: sum
value_scale: 1000
expected_cell_type: number
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
schema_version: ledger.source_package.v1
package_id: soi-ira-traditional-contributions-2023
label: IRS SOI 2023 Traditional IRA contribution totals
dimension_labels:
'irs_soi.ira_contribution_size': 'IRA contribution size'
artifact:
source_name: irs_soi
source_table: Table 5. Taxpayers with Traditional Individual Retirement Arrangement (IRA) Plan Contributions, by Size of Contribution and Age of Taxpayer
resource_package: db
resource_directory: data/irs_soi/ira_contributions
manifest: manifest_traditional_2023_source_package.yaml
vintage: tax_year_2023
extracted_at: '2026-09-27'
extraction_method: xlsx whole-workbook used-range cell parse
parser: xlsx_used_range
artifact_year: 2023
record_sets:
- record_set_id: irs_soi.ty2023.traditional_ira_contributions.all_taxpayers
provenance_class: administrative
record_set_spec_id: irs_soi.traditional_ira_contributions.all_taxpayers.v1
source_record_id_prefix: irs_soi.ty2023.traditional_ira_contributions.all_taxpayers
sheet_name: Estimates
period_type: tax_year
period: '2023'
geography_id: 0100000US
geography_level: country
geography_name: United States
geography_vintage: current
entity: tax_unit
entity_role: filing_unit
domain: individual_retirement_arrangement_contributions
groupby_dimension: irs_soi.ira_contribution_size
rows:
- value_id: all_taxpayers
label: All taxpayers
ordinal: 0
row_number: 7
expected_row_header_column: A
expected_row_header: All taxpayers
table_record_kind: total
guard_cells:
- column: B
row: 4
expected_value: Total
label: total contribution size
measures:
- measure_id: taxpayer_count
label: Number of taxpayers
ordinal: 0
column: B
source_column_id: number_of_taxpayers
expected_column_header_row: 5
expected_column_header: Number of taxpayers
concept: irs_soi.traditional_ira_contributors
unit: count
aggregation: sum
expected_cell_type: number
- measure_id: amount
label: Contribution amount
ordinal: 1
column: C
source_column_id: amount
expected_column_header_row: 5
expected_column_header: Amount
concept: irs_soi.traditional_ira_contributions
unit: usd
aggregation: sum
value_scale: 1000
expected_cell_type: number
Loading
Loading