sezer-muhammed's picture
feat: add fold metadata and paginated results
3de92d7
|
Raw
History Blame Contribute Delete
4.25 kB

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.

Requestmultipart/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

  1. Place the .ckpt file in the checkpoints/ directory.
  2. The file stem becomes the model_name — e.g. checkpoints/small3dresnet_v2.ckpt"small3dresnet_v2".
  3. No restart required; GET /models picks it up dynamically.

Note: Checkpoints must be PyTorch Lightning .ckpt files saved from CentiloidRegressorModule. The API extracts hyper_parameters.model_config and hyper_parameters.train_config automatically.