Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
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
4 changes: 3 additions & 1 deletion backend/app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ async def lifespan(app: FastAPI):
from backend.app.routes.gwas import router as gwas_router
from backend.app.routes.starter_prompts import router as starter_prompts_router
from backend.app.routes.export import router as export_router
from backend.app.routes.life_map import router as life_map_router

app.include_router(snps_router)
app.include_router(sessions_router)
Expand All @@ -101,6 +102,7 @@ async def lifespan(app: FastAPI):
app.include_router(gwas_router)
app.include_router(starter_prompts_router)
app.include_router(export_router)
app.include_router(life_map_router)


@app.get("/api/health")
Expand All @@ -109,7 +111,7 @@ async def health():
return {"status": "ok", "variants": stats["total"]}


ALL_VIEWS = ["snps", "mental-health", "pgx", "addiction", "risk"]
ALL_VIEWS = ["snps", "mental-health", "pgx", "addiction", "risk", "life-map"]

@app.get("/api/settings/views")
async def get_visible_views():
Expand Down
28 changes: 28 additions & 0 deletions backend/app/routes/life_map.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"""Migrant Life-Map routes (#27).

Serves the committed, version-stamped life-table data produced by
``scripts/fetch_life_expectancy.py``. Dumb data server — all blend logic lives in
the frontend (``lib/lifeBlend.ts``). The modifier catalogue is served via the
existing generic ``/api/config/{name}`` endpoint (``config/life-modifiers.yaml``).
"""
from __future__ import annotations

import json
from pathlib import Path

from fastapi import APIRouter, HTTPException

router = APIRouter(prefix="/api/life-map", tags=["life-map"])

_DATA_FILE = Path(__file__).resolve().parents[3] / "config" / "life_tables.json"


@router.get("/life-tables")
async def get_life_tables() -> dict:
"""Return the committed life-table dataset (countries x sex x age -> ex)."""
if not _DATA_FILE.exists():
raise HTTPException(status_code=404, detail="Life tables not generated")
try:
return json.loads(_DATA_FILE.read_text())
except Exception as exc: # noqa: BLE001
raise HTTPException(status_code=500, detail=f"Failed to read life tables: {exc}")
105 changes: 105 additions & 0 deletions config/life-modifiers.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# Life-Map modifiers (#27, track F).
#
# Qualitative, supportive life-context factors layered onto the country anchors.
# They NEVER mutate the blended life-expectancy number. A wide, caveated *range*
# may be revealed (opt-in) ONLY for `evidence: strong` factors. Mental-health
# items are deliberately kept `evidence: weak` so they can never become a number —
# per the project's mental-health UX spec, the map must not greet someone with a
# scary subtraction.
#
# Fields:
# id kebab-case identifier
# category stress | mental-health | family-history
# label short display label
# qualitative supportive, non-alarming description
# actions list of things that move this factor
# evidence strong | moderate | weak (range allowed only when strong)
# range optional {lowYears, highYears} — honored only when evidence==strong

modifiers:
- id: chronic-stress
category: stress
label: Chronic / unmanaged stress
qualitative: >-
Sustained high stress without recovery is a factor worth attention. It is
also one of the most movable — recovery, sleep, and connection shift it.
actions:
- Protect sleep and regular recovery
- Build in downshift routines (walks, breath, nature)
- Reduce avoidable chronic stressors where you can
evidence: moderate

- id: relocation-adjustment
category: stress
label: Relocation / migration adjustment
qualitative: >-
Building a life in a new country carries real adjustment load — language,
systems, distance from old support. It tends to ease as roots deepen.
actions:
- Invest in local community and routine
- Keep ties to your origin culture and people
- Use local healthcare proactively, not only in crisis
evidence: weak

- id: smoking
category: stress
label: Smoking
qualitative: >-
Smoking is the single most studied modifiable mortality factor — and
quitting at any age measurably changes the trajectory.
actions:
- Talk to a clinician about cessation support
- Nicotine replacement / medication options
evidence: strong
range:
lowYears: 5
highYears: 10

- id: physical-inactivity
category: stress
label: Low physical activity
qualitative: >-
Regular movement is strongly tied to healthier later years. Even modest,
consistent activity counts.
actions:
- Aim for regular moderate activity you enjoy
- Add strength / mobility work over time
evidence: strong
range:
lowYears: 2
highYears: 5

- id: anxiety-disorder
category: mental-health
label: Diagnosed anxiety disorder
qualitative: >-
Living with anxiety is a meaningful part of your health picture and worth
ongoing care — but population statistics about it are heavily confounded and
say little about any individual. This is context for support, not a verdict.
actions:
- Continue the care and tools that work for you
- Sleep, movement, and connection support nervous-system regulation
- Revisit treatment with your clinician as needs change
evidence: weak

- id: family-mental-health
category: family-history
label: Family history of mental-health conditions
qualitative: >-
Family patterns can raise awareness of what to watch for and discuss with a
clinician. Awareness and early support are the actionable parts.
actions:
- Note relevant family history for your clinician
- Know your early-warning signs and supports
evidence: weak

- id: family-cardiometabolic
category: family-history
label: Family history of heart / metabolic disease
qualitative: >-
A family history of cardiovascular or metabolic disease is a useful prompt
for earlier, more regular screening — where prevention does the most work.
actions:
- Discuss earlier screening (lipids, blood pressure, glucose)
- Prioritize the modifiable factors above
evidence: moderate
Loading
Loading