Metadata-Version: 2.4
Name: libby
Version: 0.2.1
Summary: Radiocarbon calibration tool with LLM-powered narrative explanations, Bayesian modelling, and GIS curve selection
Author: Marcus Quinn
License: MIT
Project-URL: Homepage, https://github.com/mabo-du/libby
Project-URL: Repository, https://github.com/mabo-du/libby
Project-URL: Documentation, https://github.com/mabo-du/libby#readme
Keywords: radiocarbon,calibration,archaeology,bayesian,llm
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Science/Research
Classifier: Topic :: Scientific/Engineering
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Requires-Python: >=3.12
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: fastapi>=0.115.0
Requires-Dist: uvicorn[standard]>=0.32.0
Requires-Dist: iosacal>=0.6.0
Requires-Dist: pydantic>=2.0
Requires-Dist: pydantic-settings>=2.0
Requires-Dist: aiosqlite>=0.20
Requires-Dist: numpy>=2.0
Requires-Dist: httpx>=0.28
Requires-Dist: openai>=1.0.0
Requires-Dist: reportlab>=4.5.1
Requires-Dist: matplotlib>=3.5.0
Requires-Dist: scipy>=1.10.0
Requires-Dist: requests>=2.34.2
Requires-Dist: beautifulsoup4>=4.12.0
Requires-Dist: lxml>=5.0.0
Requires-Dist: slowapi>=0.1.9
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.24; extra == "dev"
Requires-Dist: ruff>=0.7; extra == "dev"
Requires-Dist: httpx>=0.28; extra == "dev"
Dynamic: license-file

# Libby

<p align="center">
  <img src="assets/LibbyLogo.png" alt="Libby logo" width="200"/>
</p>

<p align="center">
  <a href="https://pypi.org/project/libby/"><img src="https://img.shields.io/pypi/v/libby?color=2c6e49" alt="PyPI"></a>
  <a href="https://github.com/mabo-du/libby"><img src="https://img.shields.io/github/license/mabo-du/libby?color=2c6e49" alt="License"></a>
  <a href="https://www.python.org/"><img src="https://img.shields.io/pypi/pyversions/libby?color=2c6e49" alt="Python"></a>
</p>

**Modern radiocarbon calibration with LLM-powered narrative explanations, Bayesian modelling, and GIS curve selection.**

Libby is a full-featured web application for calibrating radiocarbon dates with
a modern Svelte 5 frontend, a Python/FastAPI backend, and unique features —
including plain-English narrative explanations of calibration results, summed
probability distributions, and a lat/lng-based curve selector for IntCal vs
SHCal vs mixed curves.

<p align="center">
  <img src="assets/libby-demo.webp" alt="Libby WebUI demo — single date calibration workflow" width="700"/>
  <br/>
  <em>Calibrating the Shroud of Turin (691 ± 31 BP) — from input to narrative result</em>
</p>

---

## Features

- **Single-date calibration** — BP age + σ → calibrated PDF chart with 1σ/2σ HPD ranges
- **Batch calibration** — paste multiple dates at once, view SPD/KDE chart and results table
- **Kernel Density Estimation (KDE)** — alternative to SPD for batch date visualisation; avoids artifactual peaks from calibration curve steepness
- **LLM-powered narratives** — plain-English explanation of every calibration result
- **Multi-language support** — narratives in 12 languages (English, French, German, Spanish, Italian, Portuguese, Japanese, Arabic, Chinese, Dutch, Swedish, Polish)
- **Multi-provider LLM support** — Nvidia NIM (free tier, 40 req/min), Anthropic Claude
- **Bayesian Phase & Sequence modelling** — Metropolis-Hastings MCMC with Agreement Index (validated against known references)
- **GIS curve selector** — Leaflet map pin-drop auto-suggests the appropriate calibration curve based on latitude
- **Marine reservoir correction (ΔR)** — automatic ΔR lookup from the 14CHRONO Marine Reservoir Database (calib.org); Bevington error-weighted mean, deposit-feeder filtering, 24h cache
- **Project management** — group dates by site, context, or research project
- **Summed Probability Distribution (SPD)** — combined probability across all dates
- **Taphonomic warnings** — material-aware notes (old-wood effect, collagen preservation, marine reservoir effect, etc.)
- **CRM report automation** — generate Section 106 (US), UK HER, and generic compliance reports (PDF + DOCX)
- **Export:** formatted PDF report, CRM compliance reports (PDF/DOCX), CSV, OxCal CQL2 script, publication-ready text, **publication-quality figures (PNG/SVG/TIFF)**, auto-generated journal captions
- **Multi-chart output** — tab-selectable chart types: interactive PDF curve, OxCal-style calibration plot (curve + measurement overlay), multi-panel publication figure (curve overview + SPD)
- **Dynamic curve registry** — SQLite-backed curve metadata; add new curves (IntCal25, SHCal25) by dropping .14c files into the curves directory — no code changes needed
- **Calibration curves:** IntCal20, SHCal20, Marine20 (CC BY 4.0)
- **GIS map** — OpenStreetMap with zone overlays (journal-safe, no Google Maps)
- **Docker deployment** and **pip install** packaging
- **127 tests** — 64 unit (fast, no network) + 9 live calib.org integration + 54 full E2E API tests

---

## Tech Stack

| Layer | Technology |
|---|---|
| **Backend** | Python 3.13+ / FastAPI |
| **Frontend** | Svelte 5 / SvelteKit / Chart.js / Leaflet |
| **Calibration engine** | iosacal + direct IntCal curve data |
| **Bayesian MCMC** | Pure numpy/scipy Metropolis-Hastings (validated) |
| **KDE** | Pure numpy/scipy Gaussian KDE (Silverman's rule) |
| **Delta-R** | calib.org on-the-fly proxy query + Bevington weighted mean |
| **LLM** | Nvidia NIM (OpenAI-compatible) or Anthropic Claude |
| **Database** | SQLite (aiosqlite) — curves, projects, calibrations, ΔR cache |
| **PDF** | ReportLab (academic + CRM reports) |
| **DOCX** | python-docx (CRM compliance reports) |
| **Charts** | Chart.js (frontend), matplotlib (figure export + PDF reports) |
| **Curve registry** | DB-backed with auto-ingestion; IntCal25-ready |

---

## Quick Start

### Install via pip

```bash
pip install libby
libby
```

Open **http://localhost:50001** in your browser.

### Run with Docker

```bash
docker compose up -d
# Open http://localhost:50001
```

Or pull from GitHub Container Registry (once published):

```bash
docker pull ghcr.io/mabo-du/libby:latest
docker run -p 50001:50001 ghcr.io/mabo-du/libby:latest
```

To publish the Docker image yourself:

```bash
docker build -t libby .
docker tag libby:latest ghcr.io/mabo-du/libby:latest
docker push ghcr.io/mabo-du/libby:latest
```

### Build and run from source

```bash
git clone https://github.com/mabo-du/libby.git
cd libby

# Backend + frontend (single server)
uv sync
uv run uvicorn libby.main:app --reload --port 50001
# Open http://localhost:50001

# Frontend dev server (for UI development, requires backend on 50001)
cd frontend
npm install
npm run dev -- --port 50002
# Open http://localhost:50002 (points at backend API on :50001)
```

### LLM Narratives (Optional)

Libby works without any LLM — a deterministic fallback generates coherent
narratives from the numbers alone. For AI-powered narratives, set:

```bash
# Nvidia NIM (free — sign up at build.nvidia.com)
echo 'LIBBY_NIM_API_KEY=nvapi-...' > .env

# Or Anthropic Claude
# echo 'LIBBY_LLM_PROVIDER=anthropic' >> .env
# echo 'LIBBY_ANTHROPIC_API_KEY=sk-ant-...' >> .env
```

---

## Usage

### Single Calibration
Enter a BP age and standard deviation, select a curve, click **Calibrate**.
View the probability distribution chart, 1σ/2σ ranges, and plain-English narrative.

**Chart types** — use the tabs above the chart to switch between:
- **PDF Curve** — interactive probability density with hover crosshair and HPD fills
- **OxCal Plot** — publication-style calibration plot showing the IntCal curve with
  graduated uncertainty bands, your radiocarbon measurement overlaid, and the
  calibrated probability distribution (matching the format archaeologists expect
  in journal publications)
- **Multi-Panel** — double-column publication figure with calibration curve
  overview and summed probability distribution

**Export options** — once calibrated, download your results as:
- PNG / SVG / TIFF figures (300–600 DPI) in your selected chart type
- Journal-compliant figure caption with CC BY 4.0 curve attribution
- Publication-ready text block
- PDF report, CSV data, OxCal CQL2 script

### Batch Calibration
Click **Batch** in the nav, paste dates as CSV-like text, calibrate all at once
with Summed Probability Distribution.

### GIS Curve Selector
On the calibration page, expand **Curve selector by site location**.
Click anywhere on the map to place a pin — Libby suggests the correct curve
based on latitude and explains the reasoning.

### Marine Reservoir Correction (ΔR)
When calibrating marine samples against Marine20, Libby automatically looks up
the local ΔR (Delta-R) correction from the 14CHRONO Marine Reservoir Database
at calib.org. Enter your site coordinates and Libby:
- Queries nearby ΔR measurements within 500 km
- Filters out deposit feeders (organisms that ingest old carbonates)
- Computes the Bevington error-weighted mean and conservative uncertainty
- Displays source citations per the database's attribution requirements
- Caches results for 24 hours for speed and resilience
- Falls back to manual ΔR entry if no data is available

### CRM Reports
Generate compliance-ready radiocarbon dating appendices for:
- **US Section 106 (NHPA)** — letter-size, regulatory language
- **UK HER** — A4, NPPF-compliant formatting  
- **Generic CRM** — grey literature appendix

Output as PDF or editable DOCX. Each report includes project metadata,
a date table with calibrated 2σ ranges, contextual notes, and methodology
boilerplate with CC BY 4.0 curve citations.

### Projects
Create projects to group dates by site. Each project shows:
- All dates with full calibration data
- Summed Probability Distribution chart
- Project summary narrative
- Bayesian modelling (Phase or Sequence)
- PDF report, publication-quality figures, OxCal export, CSV export

### Bayesian Modelling
With 2+ dates in a project:
- **Phase model** — estimates start/end boundaries for an activity period
- **Sequence model** — applies stratigraphic ordering constraints
- Agreement Index (A) per date, following OxCal's convention (A ≥ 60 = acceptable)

### Lab Report Import
Navigate to **Import**, paste CSV/TSV from your radiocarbon lab.
Auto-detects columns, handles "3000±30" embedded sigma format,
previews all rows, then batch-calibrates with one click.

---

## Project Structure

```
libby/
├── src/libby/              # Python backend
│   ├── main.py             # FastAPI app factory and routes
│   ├── calibration.py      # iosacal integration (async, curve-resolver)
│   ├── bayesian.py         # MCMC Phase/Sequence models (validated)
│   ├── kde.py              # Kernel Density Estimation (Silverman's rule)
│   ├── reservoir.py        # ΔR marine correction (calib.org proxy)
│   ├── crm.py              # CRM report generation (PDF + DOCX)
│   ├── narrative.py        # LLM + fallback narrative generation
│   ├── models.py           # Pydantic schemas
│   ├── database.py         # SQLite (projects, calibrations, curves, ΔR cache)
│   ├── curve_registry.py   # DB-backed dynamic curve discovery
│   ├── gis.py              # Curve suggestion by latitude
│   ├── spd.py              # Summed Probability Distribution
│   ├── export.py           # CSV/text formatters
│   ├── figures/            # Multi-chart figure generation (PDF, OxCal-style, multi-panel, KDE)
│   ├── figure.py           # Backward-compat shim → figures/
│   ├── oxcal.py            # OxCal CQL2 script export (forward-compatible)
│   ├── report.py           # Academic PDF report generation
│   ├── importer.py         # Lab report CSV/TSV parser
│   └── providers/          # LLM providers (NIM, Anthropic)
├── scripts/
│   └── ingest_curve.py     # CLI tool for registering .14c curve files
├── frontend/src/           # Svelte 5 frontend
│   ├── routes/             # Pages (/, /batch, /import, /projects)
│   └── lib/                # Components (form with ΔR panel, chart, map, etc.)
├── tests/                  # pytest (73 tests: 64 unit + 9 live)
├── docs/research/          # Deep research reports + risk assessments
├── Dockerfile              # Multi-stage Docker build
├── docker-compose.yml      # Docker deployment
└── MANIFEST.in             # PyPI package manifest
```

---

## Calibration Curves

This tool uses the internationally ratified calibration curves:
- **IntCal20** — Northern Hemisphere terrestrial (Reimer et al. 2020)
- **SHCal20** — Southern Hemisphere terrestrial (Hogg et al. 2020)
- **Marine20** — Global marine (Heaton et al. 2020)

All curves are CC BY 4.0 licensed. Calibration engine: iosacal (GPLv3).

---

## Licence

MIT License. See [LICENSE](LICENSE) for details.

## Citation

If you use Libby in published research, please cite:
- IntCal20: Reimer et al. 2020, *Radiocarbon* 62(4)
- SHCal20: Hogg et al. 2020, *Radiocarbon* 62(4)
- Marine20: Heaton et al. 2020, *Radiocarbon* 62(4)
