-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
224 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
name: documentation | ||
on: [push, pull_request, workflow_dispatch] | ||
permissions: | ||
contents: write | ||
|
||
jobs: | ||
docs: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- uses: actions/setup-python@v5 | ||
- name: Install dependencies | ||
run: | | ||
make .venv | ||
- name: Sphinx build | ||
run: | | ||
make docs/ | ||
- name: Deploy to GitHub Pages | ||
uses: peaceiris/actions-gh-pages@v3 | ||
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }} | ||
with: | ||
publish_branch: gh-pages | ||
github_token: ${{ secrets.GITHUB_TOKEN }} | ||
publish_dir: docs/ | ||
force_orphan: true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,21 @@ | ||
.PHONY: test | ||
|
||
# how to get into the python virtual environment | ||
source_venv := source .venv/bin/activate | ||
|
||
docs/: .venv/ $(wildcard *.py) sphinx/conf.py $(wildcard sphinx/*.rst) | ||
$(source_venv) && sphinx-build sphinx/ docs/ | ||
|
||
test: | ||
$(source_venv) && python3 -m doctest change_header.py | ||
|
||
.venv/: | ||
python -m venv .venv && $(source_venv) && pip install -r requirements.txt | ||
|
||
|
||
db.sqlite: | ||
sqlite3 < schema.sql | ||
|
||
# TODO: replace me actual code | ||
db.txt: | ||
./00_build_db.bash |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
#!/usr/bin/env python3 | ||
""" | ||
Modify protocol names. | ||
""" | ||
import os | ||
from pathlib import Path | ||
from typing import List, Optional | ||
from itertools import chain | ||
import pydicom | ||
|
||
|
||
def change_protocol_name( | ||
dcm_dir: Path, new_data: List[pydicom.DataElement], out_dir: Optional[Path] = None | ||
): | ||
""" | ||
Change specified tags of all dicoms in a directory. Optionally make copies in out_dir. | ||
:param dcm_dir: input directory with dicom files (``MR*``, ``*IMA`` , or ``*dcm``) | ||
:param new_data: list of data elements to replace | ||
like ``[pydicom.DataElement(value="newpname", VR="LO", tag=(0x0018, 0x1030))]`` | ||
:param out_dir: Optional. Where to save modified dicoms | ||
:return: example modified dicom. last if out_dir, first and only if no ``out_dir``. | ||
sideffect: writes copies of dcm_dir dicoms inot out_dir unless out_dir is None. | ||
>>> new_data = [pydicom.DataElement(value="newpname", VR="LO", tag=(0x0018, 0x1030))] | ||
>>> ex_path = Path('example/dicom/11903_20221222/HabitTask_704x752.18/') | ||
>>> ex = change_protocol_name(ex_path, new_data) | ||
>>> ex.ProtocolName | ||
'newpname' | ||
""" | ||
all_dicoms = chain(dcm_dir.glob("MR*"), dcm_dir.glob("*IMA"), dcm_dir.glob("*dcm")) | ||
ex_dcm = None | ||
for ex_dcm_file in all_dicoms: | ||
ex_dcm = pydicom.dcmread(ex_dcm_file) | ||
|
||
for datum in new_data: | ||
ex_dcm[datum.tag] = datum | ||
|
||
# dont need to do anything if not writing files | ||
if out_dir is None: | ||
return ex_dcm | ||
|
||
new_file = os.path.join(out_dir, os.path.basename(ex_dcm_file)) | ||
# assume if we have one, we have them all (leave loop at first existing) | ||
if os.path.exists(new_file): | ||
return ex_dcm | ||
|
||
# and save out | ||
os.makedirs(out_dir, exist_ok=True) | ||
ex_dcm.save_as(new_file) | ||
|
||
return ex_dcm | ||
|
||
|
||
if __name__ == "__main__": | ||
new_tags = [ | ||
# Repetition Time | ||
pydicom.DataElement(value="1301", VR="DS", tag=(0x0018, 0x0080)), | ||
# Patient ID | ||
pydicom.DataElement(value="mod1", VR="PN", tag=(0x0010, 0x0010)), | ||
pydicom.DataElement(value="mod1", VR="LO", tag=(0x0010, 0x0020)), | ||
## anonymize | ||
# DOB | ||
pydicom.DataElement(value="19991231", VR="DA", tag=(0x0010, 0x0030)), | ||
# age | ||
pydicom.DataElement(value="100Y", VR="AS", tag=(0x0010, 0x1010)), | ||
# sex | ||
pydicom.DataElement(value="20240131", VR="CS", tag=(0x0010, 0x0040)), | ||
] | ||
|
||
change_protocol_name( | ||
Path("example/dicom/11903_20221222/HabitTask_704x752.18/"), | ||
new_tags, | ||
Path("example/dicom/mod1/HabitTask/"), | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# MRRC Dicom Header Quality Assurance | ||
Parse dicoms into a template database and alert on non-conforming sequences. | ||
|
||
See | ||
* `make docs/` for building sphinx documentation | ||
* locally in [`sphinx/index.rst`](sphinx/index.rst)) | ||
* reference for restructured text [`sphinx docstrings`](https://sphinx-rtd-tutorial.readthedocs.io/en/latest/docstrings.html) | ||
* `make test` for using `doctests` | ||
* [`schema.sql`](schema.sql) for DB schema | ||
|
||
## Strategy | ||
|
||
* build sqlite db of all acquisitions with subset of parameters | ||
* use db summary to pull out "ideal template" | ||
* check new sessions' acquisitions against template to alert | ||
|
||
## Prior Art | ||
* mrQA | ||
* sister project https://github.com/NPACore/mrqart/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,4 @@ | ||
pydicom | ||
mrQA | ||
dicom-parser | ||
sphinx |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
-- acquisition. time id | ||
create table acq ( | ||
param_id integer, -- join to session-consitent settings | ||
AcqTime text, | ||
AcqDate text, | ||
SeiresNumber text, | ||
SubID text, | ||
Operator text | ||
); | ||
|
||
-- acq params that should match across sessions | ||
create table acq_param ( | ||
is_ideal timestamp, | ||
Project text, | ||
SequenceName text, | ||
-- TODO: should this be json blob? to extend easier? | ||
iPAT text, | ||
Comments text, | ||
SequenceType text, | ||
PED_major text, | ||
TR text, | ||
TE text, | ||
Matrix text, | ||
PixelResol text, | ||
BWP text, | ||
BWPPE text, | ||
FA text, | ||
TA text, | ||
FoV text | ||
-- TODO: add shim settings from CSA | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import sys | ||
import os | ||
sys.path.insert(0, os.path.abspath('../')) # Source code dir relative to this file | ||
# Configuration file for the Sphinx documentation builder. | ||
# | ||
# For the full list of built-in configuration values, see the documentation: | ||
# https://www.sphinx-doc.org/en/master/usage/configuration.html | ||
|
||
# -- Project information ----------------------------------------------------- | ||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information | ||
|
||
project = 'mrrc-hdr-qa' | ||
copyright = '2024, EH, WF' | ||
author = 'EH, WF' | ||
|
||
# -- General configuration --------------------------------------------------- | ||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration | ||
|
||
extensions = [ 'sphinx.ext.autodoc', 'sphinx.ext.autosummary'] | ||
autodoc_default_options = { 'members': True } | ||
autodoc_typehints = "description" | ||
autosummary_generate = True | ||
|
||
templates_path = ['_templates'] | ||
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store', 'docs', '.venv', 'lib'] | ||
|
||
|
||
|
||
# -- Options for HTML output ------------------------------------------------- | ||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output | ||
|
||
html_theme = 'alabaster' | ||
html_static_path = ['_static'] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
.. mrrc-hdr-qa documentation master file, created by | ||
sphinx-quickstart on Mon Oct 21 19:00:25 2024. | ||
You can adapt this file completely to your liking, but it should at least | ||
contain the root `toctree` directive. | ||
mrrc-hdr-qa documentation | ||
========================= | ||
|
||
Code to parse dicoms into a template database and alert on non-conforming sequences. | ||
|
||
|
||
.. toctree:: | ||
:caption: Contents: | ||
|
||
.. autosummary:: | ||
:toctree: _autosummary | ||
:recursive: | ||
|
||
change_header |