Inspiration

Spirometry only flags COPD once airflow obstruction has already set in, but the evidence says lung damage shows up earlier than that: in one of the studies behind our challenge, roughly a third of smokers with completely normal breathing tests already had emphysema visible on CT. We picked the RESPIRA Hackathon's MAPS challenge, mapping early lung damage in Pre-COPD, because it asks exactly the question that matters: can you see the damage before the test that's supposed to catch it actually does? We wanted to build toward an answer without pretending we already had one.

What it does

Talea is a research workspace where clinicians and researchers can browse a cohort, open a participant's full record, and follow their observations across visits over time, with every value traceable back to its source and moment of capture. For the MAPS challenge specifically, we built a CT pipeline that converts raw scan pixel values into calibrated Hounsfield units, segments the lungs out of the scan with TotalSegmentator, and measures the share of lung tissue that falls below a density threshold associated with emphysema. Each patient record surfaces that result directly, alongside an explicit note that it's a research measurement, not a diagnosis. The whole platform runs multilingual (English, Spanish, Catalan), with role-based accounts so demo users only ever see synthetic data.

How we built it

React, Vite, TypeScript, and Tailwind on the frontend; FastAPI, Pydantic, async SQLAlchemy, and Alembic on the backend; SQLite locally. The CT pipeline lives as a small layered service: a reusable detection/overlay module, a standalone CLI for previewing results on disk, and an import script that attaches a result to a participant through the existing observation model, so imaging slots into the same data model as every other measurement instead of becoming a special case. The heavier processing, Hounsfield calibration and TotalSegmentator, runs on MareNostrum, on the real scan data, under the access rules we were given. Everything ships through Docker Compose, with CI gating a self-hosted deployment to our own homelab runner behind a Cloudflare Tunnel, so the whole thing is self-hosted end to end, including the patient-facing app, not just the model.

Challenges we ran into

Our first version of the CT overlay highlighted the brightest region of the scan. That's backwards, dense tissue like bone reads bright on CT, while emphysema, the actual damage we care about, reads dark. We caught it ourselves before merging, flipped the detection logic, and renamed everything that still carried the old framing so the mistake couldn't quietly resurface later. On the data side, only a small, balanced subset of our cohort has expert-adjudicated labels across the three groups we care about (Pre-COPD, COPD, Control), and that subset isn't an independent holdout, so a recurring challenge was resisting the pull to oversell a threshold result as more validated than 15 cases can support. A few sharper-edged codebook fields (inconsistent DLCO scales across visits, an unconfirmed sex code, an undocumented status field) forced us to store values as-is rather than guess at a transformation we couldn't verify.

Compute was its own obstacle: the infrastructure we were given access to for the heavier CT processing, is a shared, restricted system, no general internet access, jobs run through a queue rather than an interactive session, and the available Python environment is older than what our pipeline's dependencies targeted. That meant preparing our data and resolving dependencies locally before anything could be submitted to the cluster, which added real overhead against an already tight hackathon deadline.

Accomplishments that we're proud of

Keeping every CT-derived number honestly labeled as a research signal instead of dressing it up as a diagnosis, even under hackathon time pressure. Building the multilingual, role-gated foundation — English, Spanish, Catalan, with demo accounts locked to synthetic data, so the tool works for the clinical team that would actually use it, not just an English-speaking judge panel. And getting the unglamorous part right: a real self-hosted deployment, CI-gated, running behind our own infrastructure rather than a third-party cloud service, because patient-adjacent imaging work only means anything if it can run somewhere the clinical team actually controls.

What we learned

That a labeled set of 15 is genuinely useful for sanity-checking a pipeline end to end, and genuinely useless as evidence of accuracy, and that those two facts don't contradict each other. That a codebook with inconsistent units and undocumented fields is its own kind of risk, storing a value as-is because we couldn't verify a transformation felt unsatisfying in the moment, but guessing would have been worse. And a smaller technical lesson: a translation key built dynamically from a variable can pass every type check and build cleanly while still rendering nothing at runtime, the kind of bug that only shows up if someone actually looks at the page.

What's next for Talea - EPOC Platform

Close out the open data-governance questions, confirmed label criteria for the three-group subset, resolved codebook ambiguities, and whether molecular data beyond FeNO exists, before scaling anything further. Run the full Hounsfield-and-segmentation pipeline across the complete cohort on MareNostrum, not just the local pilot scans, and add the other candidate CT measures from our roadmap alongside emphysema extent: airway structure, dysanapsis, and air trapping. Give every per-participant result an explicit quality flag so a failed or borderline scan is visible, not silently dropped. And only once that foundation is solid, consider a pretrained imaging model as an optional exploratory comparison, strictly as a feasibility check, never as a replacement for a measurement a clinician can see and understand.

Built With

Share this project:

Updates

Submission history