Motion scoring for HR-pQCT scans using deep convolutional neural networks.
This refactor provides a dataset-first pipeline with BIDS-style derivatives and review-state persistence for direct Slicer integration.
Related repositories:
- Core pipeline (this repo): https://github.com/wallematthias/MotionScoreHRpQCT
- Slicer extension: https://github.com/wallematthias/SlicerMotionScoreHRpQCT
- Legacy CLI commands
gradeandconfirmare removed. - New dataset-driven commands:
discover,predict,review-init,review-apply,explain,export. - Default output structure is now:
<dataset_root>/derivatives/MotionScore/
index.tsv
dataset_description.json
<mirrored-source-path-or-flat-aim-name>/
predictions/predictions.tsv
preview/<scan_id>_preview.png
preview/<scan_id>_slice_profile.png
review/review.tsv
review/review.json
review/review_audit.tsv
explain/<scan_id>_gradcam.mha
- AIM reading now uses
aimio-py. - Python baseline is now
>=3.10. - Output path mapping:
- Flat input (
*.AIMdirectly in dataset root): outputs are grouped under folder named after each AIM file stem. - Structured input (nested folders): outputs mirror the source folder structure under
MotionScore.
- Flat input (
- Raw-vs-mask identification:
- Primary: AIM header processing log (ISQ-origin markers indicate raw images).
- Fallback: filename-based heuristics when header signal is unavailable.
conda create -n motionscore python=3.10 -y
conda activate motionscore
# Clone
# git clone <repo-url>
# cd MotionScoreHRpQCT
# Install CLI + torch inference backend
pip install -e ".[torch]"Use a model registry rooted at --model-root (default ~/.motionscore/MotionScore/models).
Each registered profile points to a directory containing torch checkpoints:
DNN_0.pt,DNN_1.pt, ... (ensemble members)model_registry.jsonat the model root
Model weights are licensed for usage tracking. In the current deployment configuration, licenses are automatically granted at signup.
motionscore discover /path/to/dataset
motionscore discover /path/to/dataset --jsonmotionscore predict /path/to/dataset --confidence-threshold 75
# choose a registered model profile
motionscore predict /path/to/dataset --model-id base-v1
# blinded operator training mode
motionscore predict /path/to/dataset --training-mode
# optional: restrict to one scan_id (repeat flag for multiple)
motionscore predict /path/to/dataset --scan-id sub-001_site-tibia_ses-T1_abcdef1234
# optional quick-look PNG controls
motionscore predict /path/to/dataset --preview-panels 5
motionscore predict /path/to/dataset --no-preview-pngDefault output root:
/path/to/dataset/derivatives/MotionScore
Optional custom output root:
motionscore predict /path/to/dataset --output-root /tmp/resultsmotionscore review-init /path/to/dataset/derivatives/MotionScore --confidence-threshold 90
# keep/enable blinded operator training mode
motionscore review-init /path/to/dataset/derivatives/MotionScore --training-mode--confidence-threshold 100 effectively requires review of all scans.
When --training-mode is enabled, pending scans are always operator-first and AI prediction is revealed after manual grading.
motionscore review-apply /path/to/dataset/derivatives/MotionScore \
--scan-id sub-001_site-tibia_ses-T1_abcdef1234 \
--manual-grade 3 \
--reviewer mwalle# clear one operator across all scans
motionscore review-clear /path/to/dataset/derivatives/MotionScore --reviewer opA
# clear everyone
motionscore review-clear /path/to/dataset/derivatives/MotionScore --all-reviewersmotionscore explain /path/to/dataset/derivatives/MotionScore \
--scan-id sub-001_site-tibia_ses-T1_abcdef1234motionscore export /path/to/dataset/derivatives/MotionScoreWrites motion_grades.tsv at the derivatives root (or custom --output).
Export includes current per-scan review state plus machine-readable multi-reviewer summary columns:
reviewer_countreviewers(pipe-delimited reviewer IDs)consensus_method(currentlymean_manual_grade)consensus_mean_manual_gradeconsensus_grade_rounded- dynamic reviewer slots:
reviewer_1_id,reviewer_1_grade,reviewer_2_id,reviewer_2_grade, ...
motionscore train-prepare /path/to/dataset/derivatives/MotionScore \
--output /path/to/dataset/derivatives/MotionScore/training/train_manifest.tsv \
--slice-count 8 \
--min-auto-confidence 0.70 \
--include-auto-without-manualTraining label policy:
- If a manual scan grade exists, it is treated as ground truth and propagated to all slices.
- If no manual grade exists, per-slice auto labels are used (confidence-filtered).
--slice-count 8samples eight randomized, spread-out slices per scan (seeded, reproducible).- Set
--slice-count 0to disable random count sampling and use--slice-stepinstead. train-preparealso builds a slice-wise cache database attraining/slice_db/*.npyand recordscache_npy_path+cache_indexin the manifest so training can load preprocessed slices directly.
motionscore train \
--manifest /path/to/dataset/derivatives/MotionScore/training/train_manifest.tsv \
--model-root ~/.motionscore/MotionScore/models \
--init-model-id base-v1 \
--early-stopping-patience 10 \
--output-model-dir ~/.motionscore/MotionScore/models/knee-v1Training writes:
training_metrics.jsontraining_plot_live.png(updated every epoch)training_plot.png(final summary plot)training_plot_model_<n>.png(per-ensemble-model curves)
motionscore model-register \
--model-root ~/.motionscore/MotionScore/models \
--model-id knee-v1 \
--model-dir ~/.motionscore/MotionScore/models/knee-v1 \
--display-name "Knee Transfer v1" \
--domain knee \
--version v1
motionscore model-list --model-root ~/.motionscore/MotionScore/modelsThis repository is core logic only. A separate Slicer extension should:
- run
motionscore predict ...from aRunbutton, - run
motionscore review-apply ...as reviewers step through scans, - request
motionscore explain ...on demand to overlay Grad-CAM maps, - optionally show
preview/*_preview.pngfor quick QC, - load all outputs from derivatives without ad hoc state files.
Reference Slicer repository:
If you use this software, please cite:
Walle, M., Eggemann, D., Atkins, P.R., Kendall, J.J., Stock, K., Müller, R. and Collins, C.J., 2023. Motion grading of high-resolution quantitative computed tomography supported by deep convolutional neural networks. Bone, 166, p.116607. https://doi.org/10.1016/j.bone.2022.116607
