Skip to content
Merged
Changes from all commits
Commits
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
196 changes: 131 additions & 65 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,37 +10,41 @@
[![codecov](https://codecov.io/gh/Liohtml/MedCheck/branch/main/graph/badge.svg)](https://codecov.io/gh/Liohtml/MedCheck)
[![PyPI](https://img.shields.io/pypi/v/medcheck)](https://pypi.org/project/medcheck/)
[![Python](https://img.shields.io/pypi/pyversions/medcheck)](https://pypi.org/project/medcheck/)
[![Docker](https://img.shields.io/badge/GHCR-medcheck-blue?logo=docker)](https://github.com/Liohtml/MedCheck/pkgs/container/medcheck)
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
[![GitHub release](https://img.shields.io/github/v/release/Liohtml/MedCheck)](https://github.com/Liohtml/MedCheck/releases)
[![GitHub stars](https://img.shields.io/github/stars/Liohtml/MedCheck)](https://github.com/Liohtml/MedCheck/stargazers)

</div>
Analyze MRI scans with local ML models and frontier Vision-LLMs (Claude, GPT, Gemini)
and generate structured, radiology-style reports — from the CLI, a web UI, or Docker.

MedCheck analyzes MRI scans using local ML models and frontier Vision-LLMs (Claude, GPT, Gemini) to generate professional radiology-style reports with annotated images.
**[Quick Start](#quick-start)** · **[Usage](#usage)** · **[Configuration](#configuration)** · **[Docs](docs/)** · **[Contributing](#contributing)** · **[Report Bug](https://github.com/Liohtml/MedCheck/issues/new?template=bug_report.yml)**

---
</div>

**[Quick Start](#quick-start)** · **[Documentation](docs/)** · **[Contributing](CONTRIBUTING.md)** · **[Report Bug](https://github.com/Liohtml/MedCheck/issues/new?template=bug_report.yml)**
> ⚠️ **MedCheck is a research and educational tool, NOT a medical device.** Every
> output must be reviewed by a qualified radiologist before any clinical use.
> See the full [disclaimer](#disclaimer) below.

---

## Features

- **Plug & Play Docker** — single `docker run` command, no local setup required
- **Multiple data sources** — local DICOM files, easyRadiology platform, and custom plugins
- **Local ML analysis** — on-device inference with LLaVA-Med and MONAI-based models; fully offline capable
- **Vision-LLM analysis** — frontier model support for Claude Opus 4.8, GPT-5.5, and Gemini 3.5 Flash
- **Clinical context input** — attach patient history, symptoms, and prior findings to guide report generation
- **Professional PDF/HTML reports** — annotated images with structured radiology-style findings and impressions
- **Multiple data sources** — local DICOM folders/ZIPs, easyRadiology portal links, and custom plugins
- **Local ML analysis** — on-device anomaly detection and feature extraction; no API key required
- **Vision-LLM analysis** — Claude Opus 4.8, GPT-5.5, and Gemini 3.5 Flash (opt-in, consent-gated)
- **Privacy by default** — nothing leaves your machine without explicit consent; `--deidentify` pseudonymizes reports
- **Clinical context input** — attach symptoms, trauma history, and suspected diagnosis to guide the analysis
- **Professional reports** — structured PDF/HTML/JSON with findings tables, impression, and limitations
- **YAML workflow engine** — compose and version-control custom analysis pipelines as code
- **Generic anatomy support** — brain, spine, knee, shoulder, abdomen, and more
- **Web UI + CLI** — interactive browser dashboard and a scriptable command-line interface
- **Web UI + CLI + REST API** — 3-step browser wizard, scriptable CLI, and an HTTP API

---

## Quick Start

### Option 1 — Docker (recommended)
### Option 1 — Docker (recommended, ~1 minute)

```bash
docker run -p 8080:8080 \
Expand All @@ -49,13 +53,13 @@ docker run -p 8080:8080 \
ghcr.io/liohtml/medcheck:latest
```

Then open [http://localhost:8080](http://localhost:8080).
Open [http://localhost:8080](http://localhost:8080) and follow the 3-step wizard.

### Option 2 — pip install

```bash
pip install medcheck
medcheck serve
medcheck serve # web UI on http://localhost:8080
```

### Option 3 — From source
Expand All @@ -67,6 +71,24 @@ uv sync
uv run medcheck serve
```

### Your first analysis (CLI)

```bash
# Fully local, no API key needed (ML analysis + JSON report):
medcheck analyze ./my-dicom-folder --steps ingest,preprocess,ml_analysis,report

# Full analysis with a cloud Vision-LLM (requires a key + explicit consent):
medcheck analyze ./my-dicom-folder \
--model claude --allow-cloud-llm \
--symptoms "Medial knee pain after sports injury" \
--report pdf --lang en

# Not sure what to type? Let MedCheck ask you:
medcheck analyze ./my-dicom-folder --interactive
```

Reports land in `./output/` (they contain patient data unless you pass `--deidentify` — see [Privacy & Security](#privacy--security)).

---

## How It Works
Expand All @@ -82,10 +104,51 @@ uv run medcheck serve
```

1. **Ingest** — load studies from local paths, the easyRadiology portal, or third-party plugins.
2. **Preprocess** — normalize pixel values, resize to model input dimensions, and strip PHI.
3. **ML Analyze** — run local segmentation and anomaly-detection models (no API key required).
4. **Vision AI** — send annotated slices to a frontier Vision-LLM for language-based findings.
5. **Report** — render a structured radiology report with annotated images in PDF and HTML.
2. **Preprocess** — normalize pixel values, detect anatomy/planes, build volumes.
3. **ML Analyze** — run local anomaly-detection models to find suspicious slices (no API key required).
4. **Vision AI** — send the top slices to a Vision-LLM for structured findings *(only with your consent)*.
5. **Report** — render a structured radiology-style report as PDF, HTML, or JSON.

---

## Usage

### CLI reference

```bash
medcheck analyze SOURCE [OPTIONS] # run an analysis pipeline
medcheck serve # start the web UI / REST API
medcheck providers # list data providers
medcheck models # list LLM providers and availability
```

The most useful `analyze` options:

| Option | Description |
|---|---|
| `--model, -m` | LLM provider: `claude`, `openai`, `gemini`, `local` |
| `--allow-cloud-llm` | Consent to send imaging data to an external cloud LLM |
| `--deidentify` | Replace patient name/ID/DOB with a pseudonym in reports |
| `--symptoms`, `--trauma`, `--diagnosis` | Clinical context to guide the analysis |
| `--report, -r` | Report format: `pdf`, `html`, `json` |
| `--lang, -l` | Report language: `en`, `de`, `fr`, `es` |
| `--steps` | Comma-separated pipeline steps (skip what you don't need) |
| `--workflow, -w` | Run a YAML-defined pipeline instead |
| `--interactive, -i` | Prompt for missing inputs |

Run `medcheck analyze --help` for the full list.

### REST API

`medcheck serve` exposes:

| Endpoint | Description |
|---|---|
| `GET /health` | Liveness probe (always public) |
| `POST /api/analyze` | Run an analysis (JSON body: `source`, `anatomy`, `report_format`, `language`, `allow_cloud_llm`, …) |

When `MEDCHECK_API_KEY` is set, `/api/*` requires an `X-API-Key` header. Requests
are rate-limited per client IP (`MEDCHECK_RATE_LIMIT`, default 10/min).

---

Expand All @@ -98,6 +161,8 @@ uv run medcheck serve
| **Gemini 3.5 Flash** | Google | Speed-optimized, cost-effective batch processing |
| **LLaVA-Med** | Local | Fully offline, no API key required *(coming soon — [#18](https://github.com/Liohtml/MedCheck/issues/18))* |

Default model IDs are overridable via `MEDCHECK_CLAUDE_MODEL`, `MEDCHECK_OPENAI_MODEL`, and `MEDCHECK_GEMINI_MODEL`.

---

## Data Sources
Expand All @@ -118,44 +183,38 @@ Copy `.env.example` and fill in your API keys:
cp .env.example .env
```

```dotenv
# LLM API Keys (at least one needed for Vision analysis)
ANTHROPIC_API_KEY= # https://console.anthropic.com/settings/keys
OPENAI_API_KEY= # https://platform.openai.com/api-keys
GOOGLE_API_KEY= # https://aistudio.google.com/apikey

# Defaults
MEDCHECK_LLM_PROVIDER=claude # claude | openai | gemini
MEDCHECK_LANGUAGE=en # en | de
MEDCHECK_HOST=127.0.0.1 # localhost only; set 0.0.0.0 to expose on the network
MEDCHECK_PORT=8080
MEDCHECK_API_KEY= # when set, /api requires an X-API-Key header
MEDCHECK_RATE_LIMIT=10 # POST /api/analyze requests per IP per minute (0 = off)
```
| Variable | Default | Description |
|---|---|---|
| `ANTHROPIC_API_KEY` / `OPENAI_API_KEY` / `GOOGLE_API_KEY` | — | LLM keys (at least one for cloud Vision analysis) |
| `MEDCHECK_LLM_PROVIDER` | `claude` | Default LLM provider (`claude` \| `openai` \| `gemini` \| `local`) |
| `MEDCHECK_ALLOW_EXTERNAL_LLM` | off | Consent to external LLM transmission (`1` to enable) |
| `MEDCHECK_LANGUAGE` | `en` | Default report language |
| `MEDCHECK_HOST` | `127.0.0.1` | Bind address; set `0.0.0.0` to expose on the network |
| `MEDCHECK_PORT` | `8080` | Bind port |
| `MEDCHECK_API_KEY` | — | When set, `/api` requires an `X-API-Key` header |
| `MEDCHECK_RATE_LIMIT` | `10` | `POST /api/analyze` requests per IP per minute (`0` = off) |
| `MEDCHECK_MAX_VISION_IMAGES` | `12` | Max slice images sent to the LLM per analysis |
| `MEDCHECK_MAX_DOWNLOAD_BYTES` | 2 GiB | Cap on portal exam-ZIP downloads |

> **Security:** The server binds to `127.0.0.1` by default. If you expose it on
> the network (`MEDCHECK_HOST=0.0.0.0`), set `MEDCHECK_API_KEY` so the `/api`
> endpoints require an `X-API-Key` header — this app handles patient PHI.
>
> **Patient data & cloud LLMs:** Vision analysis sends imaging data to an
> external LLM provider only after explicit consent. Pass `--allow-cloud-llm`,
> set `MEDCHECK_ALLOW_EXTERNAL_LLM=1`, or confirm the interactive prompt. If the
> requested provider is unavailable, MedCheck never reroutes data to a different
> cloud provider. See [SECURITY.md](SECURITY.md#handling-of-patient-data-phi).
>
> **Reports contain PHI:** generated reports embed patient name, ID and birth
> date from the DICOM metadata. Pass `--deidentify` to replace them with a
> stable pseudonym. Report files are written with owner-only permissions.
---

> **Note:** easyRadiology requires no API key. Authentication uses the access code provided by your radiology clinic (via SMS, email, or letter). A date of birth may be requested by the portal but is **not** verified by MedCheck.
## Privacy & Security

### Docker environment variables
MedCheck handles patient data (PHI), so the defaults are deliberately conservative:

```bash
docker run -p 8080:8080 \
-e ANTHROPIC_API_KEY=sk-... \
ghcr.io/liohtml/medcheck:lite
```
- **Nothing leaves your machine without consent.** Cloud Vision analysis requires
`--allow-cloud-llm`, `MEDCHECK_ALLOW_EXTERNAL_LLM=1`, or the interactive prompt.
If the requested LLM provider is unavailable, MedCheck never silently reroutes
data to a different cloud provider.
- **Reports contain PHI by default.** Pass `--deidentify` to replace patient
name/ID/DOB with a stable pseudonym. Report files are written with owner-only
permissions.
- **Localhost by default.** The server binds to `127.0.0.1`; network exposure
requires an explicit opt-in and should always be combined with `MEDCHECK_API_KEY`.
- **Logs are pseudonymized**, ZIP extraction is hardened, and the web UI ships a
strict Content-Security-Policy.

Details: [SECURITY.md](SECURITY.md) · vulnerability reports via [private advisory](https://github.com/Liohtml/MedCheck/security/advisories/new).

---

Expand Down Expand Up @@ -191,13 +250,6 @@ Run a workflow:
medcheck analyze --source ./dicoms --workflow workflows/default.yml
```

Discover what's available:

```bash
medcheck providers # list registered data providers
medcheck models # list LLM providers, default models, and availability
```

---

## Documentation
Expand All @@ -215,17 +267,31 @@ medcheck models # list LLM providers, default models, and availability

## Contributing

Contributions are welcome. Please read [CONTRIBUTING.md](CONTRIBUTING.md) first.
Contributions of every size are welcome — from typo fixes to new data providers.

**Where to start:**

- 🟢 [`good first issue`](https://github.com/Liohtml/MedCheck/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) — small, well-scoped tasks with pointers
- 🙋 [`help wanted`](https://github.com/Liohtml/MedCheck/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22) — features we'd love help with (new providers, local LLaVA-Med, …)
- 🗺️ [Roadmap epic #51](https://github.com/Liohtml/MedCheck/issues/51) — validation & enhancement pipeline stages

**Dev setup:**

```bash
git clone https://github.com/Liohtml/MedCheck.git
cd MedCheck
uv sync
uv sync --all-extras
pre-commit install
pytest

# Quality gates (same as CI):
uv run pytest # tests (coverage floor: 80%)
uv run ruff check src tests && uv run ruff format --check src tests
uv run mypy src
uv run bandit -r src/medcheck -ll -q
```

All pull requests require passing CI and at least one approving review.
Please read [CONTRIBUTING.md](CONTRIBUTING.md) before opening a PR. All pull
requests require passing CI and at least one approving review.

---

Expand All @@ -239,8 +305,8 @@ MedCheck builds on the shoulders of excellent open-source work:

---

> **Disclaimer**
>
## Disclaimer

> **MedCheck is NOT a medical device and has NOT been cleared or approved by any regulatory authority (FDA, CE/EU MDR, or otherwise). It is intended solely as a research and educational tool. It must NOT be used to diagnose, screen for, or rule out any condition. All outputs must be reviewed and verified by a qualified radiologist or licensed medical professional before use in any clinical decision-making context. Do not use MedCheck as a substitute for professional medical advice, diagnosis, or treatment.**
>
> See **[Intended Use & Positioning](docs/intended-use.md)** for the scope and the do/don't boundary, and the **[Model Card](docs/model-card.md)** for limitations and known risks.
Expand Down
Loading