A fast preflight checklist tool for a networked PET scanner. It connects to the instrument over TCP/IP, speaks SCPI, runs every data check, and prints a clean pass/fail summary so a run can start with confidence.
This is a reproducible simulation. A simulated instrument ships with the tool, so everything here runs with no scanner attached. Point it at real hardware by dropping
--simand passing--hostand--port.
Before every scan, the researcher ran a 13-step morning checklist by hand. It took 15 to 20 minutes. Eight of those steps were data checks: read a number off the scanner or a file and compare it to an allowed range. Five were physical and had to stay manual.
The scanner sits on the local network and speaks SCPI: open a TCP socket, send a text command, read a text response. So the eight data checks were a natural fit for automation. This tool connects, runs all eight, and prints a single pass/fail summary. It runs every check and reports everything at the end rather than stopping at the first failure, and it blocks proceeding if anything fails.
The morning checklist went from 15 to 20 minutes of careful manual reading down to about 8 seconds against the real instrument.
- Detector Channel 1 sensitivity:
MEAS:VOLT? CHAN1, must be 4.8 to 5.2 V. - Detector Channel 2 sensitivity:
MEAS:VOLT? CHAN2, must be 2.9 to 3.1 V. - Detector Channel 3 sensitivity:
MEAS:VOLT? CHAN3, must be 1.4 to 1.6 V. - Calibration values:
sensor_gainandoffset_correctionfrom a JSON file, each in range. - Calibration age:
last_calibratedmust be within the 30-day recalibration rule. - Device self-test:
*TST?must return0. - Disk space: the scan-output directory must have at least 10 GB free.
- Output directory: must exist and be writable.
Load the animal, clean the detector bore, verify the anesthesia line, confirm room setup, sign the usage log. The tool prints these as a reminder at the end.
This project uses uv.
uv sync --extra dev
# or run the CLI without installing:
uv run --with click scan-preflight run --simscan-preflight run --simSample output:
Preflight checklist
----------------------------------------
[ PASS ] Detector Channel 1: 4.97V (range: 4.8-5.2V)
[ PASS ] Detector Channel 2: 3V (range: 2.9-3.1V)
[ PASS ] Detector Channel 3: 1.5V (range: 1.4-1.6V)
[ PASS ] Device Self-Test: self-test returned 0 (no faults)
[ PASS ] Calibration Values: sensor_gain=1, offset_correction=0.01 all in range
[ PASS ] Calibration Age: 11 days old (rule: recalibrate every 30 days)
[ PASS ] Disk Space: 96.2GB free (need at least 10GB)
[ PASS ] Output Directory: . exists and is writable
----------------------------------------
8/8 checks passed. Cleared for scan.
Total time: 4ms
Manual steps still on you:
[ ] Load the animal onto the bed
[ ] Clean the detector bore
[ ] Verify the anesthesia line
[ ] Confirm room setup
[ ] Sign the usage log
The simulator runs in milliseconds; the ~8 seconds in the story is the real instrument round trip over the lab network. Either way it beats 15 to 20 minutes by hand.
Each flag forces one failure so you can see the report react and the exit code go non-zero:
scan-preflight run --sim --low-disk # Disk Space fails
scan-preflight run --sim --bad-channel 1 # Detector Channel 1 fails
scan-preflight run --sim --fail-selftest # Device Self-Test fails
scan-preflight run --sim --expire-calibration # Calibration Age failsExample failing run:
[ FAIL ] Disk Space: only 6.2GB free, need at least 10GB
...
7/8 checks passed. Clear the failures above before proceeding.
The process exits with status 1 whenever any check fails, so it can gate a
downstream "start scan" step in a script.
scan-preflight run \
--host 192.168.1.50 --port 5025 \
--calibration ./calibration.json \
--out-dir /data/scanscalibration.json:
{
"sensor_gain": 1.00,
"offset_correction": 0.01,
"last_calibrated": "2026-06-01"
}make install # uv sync --extra dev
make lint # ruff + mypy
make test # unit tests with coverage
make test-integration # boots the simulator on a loopback port
make demo # scan-preflight run --simdocker build -t scan-preflight .
docker run --rm scan-preflight # runs the simulationMIT, Sai Asish Y. See LICENSE. Architecture notes in ARCHITECTURE.md.