MRI Inference API
Base URL (local): http://localhost:7860
Base URL (HF Space): https://<your-space>.hf.space
Endpoints
GET /models
Returns the list of available model checkpoint names.
Response
{
"models": ["small3dresnet_centiloid_v1"]
}
POST /inference
Runs centiloid regression on an uploaded MRI scan and stores the result.
Re-submitting the same filename + model_name pair overwrites the existing row.
Request — multipart/form-data
| Field | Type | Required | Description |
|---|---|---|---|
file |
file | yes | .nii, .nii.gz, or .tar / .tar.gz containing a .nii |
model_name |
string | yes | Must match a name returned by GET /models |
label |
string | no | Ground-truth centiloid label (for tracking) |
fold |
integer | no | Optional fold id, 0-10, for train/val/test analysis splits |
curl
curl -X POST http://localhost:7860/inference \
-F "file=@subject_001.nii.gz" \
-F "model_name=small3dresnet_centiloid_v1" \
-F "label=38.5"
Python (requests)
import requests
with open("subject_001.nii.gz", "rb") as f:
r = requests.post(
"http://localhost:7860/inference",
files={"file": f},
data={"model_name": "small3dresnet_centiloid_v1", "label": "38.5"},
)
print(r.json())
Response 200
{
"id": 1,
"filename": "subject_001.nii.gz",
"model_name": "small3dresnet_centiloid_v1",
"centiloid": 42.317,
"raw_output": 0.648231,
"label": "38.5",
"fold": null
}
| Field | Description |
|---|---|
centiloid |
Predicted centiloid value (inverse-transformed: sinh(raw_output) × 50) |
raw_output |
Raw model output in asinh-transformed space |
label |
Ground-truth label as provided, or null |
fold |
Optional fold id, or null |
Errors
| Status | Reason |
|---|---|
400 |
Empty file |
404 |
model_name not found in checkpoints/ |
422 |
Preprocessing or inference failed (bad NIfTI, no valid voxels, etc.) |
GET /results
Returns paginated past inference results, most recent first.
Query params:
| Param | Type | Default | Description |
|---|---|---|---|
limit |
integer | 250 |
Page size, max 1000 |
offset |
integer | 0 |
Row offset |
fold |
integer | none | Optional fold filter, 0-10 |
curl
curl "http://localhost:7860/results?limit=250&offset=0"
Response 200
{
"count": 2,
"limit": 250,
"offset": 0,
"has_more": false,
"results": [
{
"id": 2,
"filename": "subject_002.nii.gz",
"model_name": "small3dresnet_centiloid_v1",
"centiloid": 87.14,
"raw_output": 1.053812,
"label": null,
"fold": null,
"created_at": "2026-05-24T10:31:00.123456"
},
{
"id": 1,
"filename": "subject_001.nii.gz",
"model_name": "small3dresnet_centiloid_v1",
"centiloid": 42.317,
"raw_output": 0.648231,
"label": "38.5",
"fold": 2,
"created_at": "2026-05-24T10:28:44.987654"
}
]
}
GET /results/done
Returns only completed (filename, model_name) pairs for resume scripts.
curl http://localhost:7860/results/done
GET /results/folds
Returns the fold ids currently present in the DB.
{ "folds": [0, 1, 2] }
PATCH /results/fold
Updates fold values in bulk. Use either id or filename + model_name. Set fold to null to clear it.
curl -X PATCH http://localhost:7860/results/fold \
-H "Content-Type: application/json" \
-d '{"updates":[{"filename":"subject_001.nii.gz","model_name":"small3dresnet_centiloid_v1","fold":2}]}'
{ "updated": 1, "missing": [] }
Adding a New Model
- Place the
.ckptfile in thecheckpoints/directory. - The file stem becomes the
model_name— e.g.checkpoints/small3dresnet_v2.ckpt→"small3dresnet_v2". - No restart required;
GET /modelspicks it up dynamically.
Note: Checkpoints must be PyTorch Lightning
.ckptfiles saved fromCentiloidRegressorModule. The API extractshyper_parameters.model_configandhyper_parameters.train_configautomatically.