Skip to content
This repository was archived by the owner on Jun 14, 2026. It is now read-only.

Commit d31ce86

Browse files
authored
Map Arch sex constraints for target facts (#39)
1 parent 7a961fb commit d31ce86

2 files changed

Lines changed: 85 additions & 6 deletions

File tree

src/microplex_us/targets/arch.py

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4545,6 +4545,9 @@ def _arch_consumer_fact_constraint(
45454545
variable = str(constraint["variable"])
45464546
if variable in ARCH_IGNORED_FACT_CONSTRAINT_VARIABLES:
45474547
return None
4548+
value = _json_scalar_text(constraint.get("value"))
4549+
if variable == "sex":
4550+
return _arch_sex_constraint(str(constraint["operator"]), value)
45484551
try:
45494552
mapped_variable = ARCH_FACT_CONSTRAINT_VARIABLE_ALIASES[variable]
45504553
except KeyError as exc:
@@ -4554,7 +4557,7 @@ def _arch_consumer_fact_constraint(
45544557
return (
45554558
mapped_variable,
45564559
str(constraint["operator"]),
4557-
_json_scalar_text(constraint.get("value")),
4560+
value,
45584561
)
45594562

45604563

@@ -4689,6 +4692,13 @@ def _arch_fact_constraint(row: sqlite3.Row) -> tuple[str, str, str] | None:
46894692
variable = str(row["constraint_variable"])
46904693
if variable in ARCH_IGNORED_FACT_CONSTRAINT_VARIABLES:
46914694
return None
4695+
value = _sqlite_json_scalar_text(
4696+
row["constraint_value_text"],
4697+
row["constraint_value_numeric"],
4698+
row["constraint_value_json"],
4699+
)
4700+
if variable == "sex":
4701+
return _arch_sex_constraint(str(row["constraint_operator"]), value)
46924702
try:
46934703
mapped_variable = ARCH_FACT_CONSTRAINT_VARIABLE_ALIASES[variable]
46944704
except KeyError as exc:
@@ -4698,11 +4708,25 @@ def _arch_fact_constraint(row: sqlite3.Row) -> tuple[str, str, str] | None:
46984708
return (
46994709
mapped_variable,
47004710
str(row["constraint_operator"]),
4701-
_sqlite_json_scalar_text(
4702-
row["constraint_value_text"],
4703-
row["constraint_value_numeric"],
4704-
row["constraint_value_json"],
4705-
),
4711+
value,
4712+
)
4713+
4714+
4715+
def _arch_sex_constraint(operator: str, value: str) -> tuple[str, str, str]:
4716+
canonical_operator = _canonical_arch_constraint_operator(operator)
4717+
value_text = str(value).strip().lower()
4718+
if value_text in {"female", "f", "2", "2.0"}:
4719+
is_female_value = "1"
4720+
elif value_text in {"male", "m", "1", "1.0"}:
4721+
is_female_value = "0"
4722+
else:
4723+
raise ValueError(f"No Microplex Arch sex constraint mapping for value {value!r}")
4724+
if canonical_operator == "==":
4725+
return ("is_female", "==", is_female_value)
4726+
if canonical_operator == "!=":
4727+
return ("is_female", "==", "0" if is_female_value == "1" else "1")
4728+
raise ValueError(
4729+
f"No Microplex Arch sex constraint mapping for operator {operator!r}"
47064730
)
47074731

47084732

tests/targets/test_arch_facts.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1562,6 +1562,61 @@ def test_arch_consumer_fact_jsonl_provider_maps_acs_district_age_rows(
15621562
}
15631563

15641564

1565+
def test_arch_consumer_fact_jsonl_provider_maps_acs_state_age_sex_rows(
1566+
tmp_path: Path,
1567+
) -> None:
1568+
consumer_jsonl = tmp_path / "consumer_facts.jsonl"
1569+
row = _consumer_fact(
1570+
"acs-ca-female-40-44",
1571+
concept="census_acs.person_count",
1572+
domain="total_population",
1573+
source_name="census_acs",
1574+
source_table="ACS B01001 state female age",
1575+
period={"type": "calendar_year", "value": 2023},
1576+
geography={"level": "state", "id": "0400000US06", "name": "California"},
1577+
value=1_300_307,
1578+
constraints=(
1579+
{
1580+
"variable": "age",
1581+
"operator": ">=",
1582+
"value": 40,
1583+
"unit": "years",
1584+
"role": "filter",
1585+
},
1586+
{
1587+
"variable": "age",
1588+
"operator": "<",
1589+
"value": 45,
1590+
"unit": "years",
1591+
"role": "filter",
1592+
},
1593+
{
1594+
"variable": "sex",
1595+
"operator": "==",
1596+
"value": "female",
1597+
"role": "filter",
1598+
},
1599+
),
1600+
)
1601+
consumer_jsonl.write_text(json.dumps(row, sort_keys=True) + "\n")
1602+
1603+
target_set = ArchConsumerFactJSONLTargetProvider(consumer_jsonl).load_target_set(
1604+
TargetQuery(period=2023)
1605+
)
1606+
1607+
assert len(target_set.targets) == 1
1608+
target = target_set.targets[0]
1609+
assert target.value == 1_300_307
1610+
assert target.metadata["variable"] == "person_count"
1611+
assert target.metadata["geo_level"] == "state"
1612+
assert _target_filter_tuples(target) == {
1613+
("age", ">=", "40"),
1614+
("age", "<", "45"),
1615+
("is_female", "==", "1"),
1616+
("state_fips", "==", "06"),
1617+
}
1618+
1619+
15651620
def test_arch_consumer_fact_jsonl_provider_maps_acs_district_snap_rows(
15661621
tmp_path: Path,
15671622
) -> None:

0 commit comments

Comments
 (0)