🇬🇧 English | 🇮🇷 فارسی
👉 https://donziglary.github.io/BirthAtlas/
No installation needed — the demo runs entirely in your browser.
BirthAtlas is a data visualization project that explores the probability of being born in a given country, in a given year.
Using official World Bank demographic data and the UNDP Human Development Index, the project estimates each country's annual share of global births and pairs that with a measure of human development for the same year. The result is presented two ways: an animated world map for exploring the global picture, and an interactive "Birth Story" panel that turns the raw numbers into a short, personal narrative for any country and year.
The project combines demographic analysis, statistical modeling, and interactive front-end engineering — from data cleaning in pandas to a hand-built Canvas-based image export — to turn raw population data into something people actually want to explore and share.
Every person is born into circumstances they never chose.
BirthAtlas explores this idea quantitatively, through a simple question:
If a person were selected at random from everyone ever born in the last three decades, in which country — and in which year — would that most likely have happened?
This is closely related to the philosophical idea of the Birth Lottery: the place and moment of birth are decided before anyone has any say in the matter, yet they shape the opportunities, living conditions, and life outcomes a person is born into.
World map
- Interactive Plotly choropleth of global birth probability, 1993–2020
- Animated timeline slider
- Log-scaled color encoding tuned for this dataset's heavily skewed distribution
- Country-level ranking and detailed hover tooltips
Your birth story
- Pick any country and year (or let the page pick one for you) to see:
- Birth probability, with a human-scale analogy ("rarer than a hole-in-one in golf")
- World rank by birth share, and how it compares to that year's global average
- Human Development Index and its rank, when available for that country/year
- A birth-probability vs. HDI trend chart across the full time range
- Download the result as a shareable 1200×630 image card, rendered entirely with the Canvas API
- Subtle, restrained motion throughout (tab transitions, staggered reveals, an eased count-up on the headline number), fully disabled for anyone with
prefers-reduced-motionset
Engineering details worth noting
- Fully static: the whole site is one
index.htmlfile with no backend and no build step - Self-hosted fonts (no external font CDN dependency)
- Defensive against the two classic causes of "broken on mobile, fine on desktop": Plotly's default-size fallbacks, and CSS Grid's implicit
min-width: auto
For each country and year:
Births = Population × Birth Rate / 1000
Birth Probability (%) = (Country Births / Global Births) × 100
Human Development Index values come directly from UNDP's published composite index (already normalized 0–1) and are merged in by ISO-3 country code and year, not by country name — country names differ between the World Bank and UNDP sources (e.g. "Iran, Islamic Rep." vs. "Iran (Islamic Republic of)"), and an earlier version of this pipeline that joined on name silently dropped around 25 countries because of that mismatch.
HDI rank is computed within each year, not across the full dataset, since the number of countries with available HDI data changes from year to year.
BirthAtlas/
│
├── assets/
│ └── fonts/ # Self-hosted Space Grotesk (all weights)
│
├── data/
│ ├── raw/ # World Bank + UNDP source files
│ └── processed/ # Cleaned, merged datasets
│ ├── birth_probability.csv
│ └── birth_probability_hdi.csv
│
├── notebooks/
│ ├── 01_process_data.ipynb # Clean & merge World Bank source data
│ ├── 02_add_hdi.ipynb # Merge in UNDP HDI data
│ ├── 03_visualize.ipynb # Builds index.html (map + Birth Story UI)
│ ├── 04_country_comparison.ipynb # Comparison engine tests
│ ├── 05_birth_story.ipynb # Narrative generation tests
│ └── 06_lottery_simulator.ipynb # Random-birth simulator tests
│
├── src/
│ └── birth_atlas/ # Shared analysis logic (imported by notebooks 04–06)
│ ├── comparison.py # get_country_summary, yearly stats
│ ├── narrative.py # Birth Story text generation, odds-ladder analogies
│ └── simulator.py # Weighted random birth simulator
│
├── index.html # Generated output — the live site
├── requirements.txt
├── LICENSE
└── README.md
notebooks/04 through 06 no longer define their own copies of the comparison, narrative, and simulator logic — that logic now lives once in src/birth_atlas/ and is imported. Each notebook keeps its own test/verification cells (including edge cases like missing HDI data) so the shared logic stays easy to validate in isolation.
git clone https://github.com/Donziglary/BirthAtlas.git
cd BirthAtlas
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txtRun the notebooks in numerical order (01 → 06) from the notebooks/ folder. Notebook 03_visualize.ipynb is the one that regenerates index.html; the rest are analysis and verification.
To just view the site without running anything, open index.html directly in a browser, or use the live demo.
Data pipeline: Python, pandas, NumPy, Jupyter Notebook Visualization: Plotly (choropleth map, trend charts) Front end: vanilla HTML/CSS/JavaScript — no framework, no build step Image export: Canvas API (hand-drawn shareable cards, no external rendering library)
- World Bank Open Data — population and crude birth rate
- UNDP Human Development Reports — Human Development Index
- HDI data is unavailable for some country/year combinations (mainly smaller states and earlier years); the Birth Story panel handles this gracefully but the underlying gap is a real limitation of the source data, not something this project fills in.
- Only fonts are self-hosted — Plotly.js and the flag-icons stylesheet are still loaded from CDNs, so a fully offline environment will lose the map and country flags (the rest of the page still works).
- The narrative logic (odds-ladder analogies, Birth Story wording) exists in two places:
src/birth_atlas/narrative.py(Python, used by notebooks) and a JavaScript reimplementation insideindex.html(used by the live page). This is a deliberate trade-off — the site is a single static HTML file with no build step, so it cannotimportthe Python package directly — but it means the two must be kept in sync by hand. If the analogy wording or thresholds change, both places need updating.
This project is currently a stable, complete release. If development continues, candidate directions include:
- Birth probability forecasting (e.g. linear regression, Prophet, or a small time-series model) for future years
- Regional/continental aggregation views
- Additional socioeconomic indicators alongside HDI
This project is released under the MIT License.