From 612b407b31cb0491399ea60ade1c95c0e186e057 Mon Sep 17 00:00:00 2001 From: Tom Roberts Date: Tue, 20 Feb 2024 10:36:35 +0000 Subject: [PATCH 01/45] Removes sdist from dist creation wheels (bdist) include the version: https://github.com/mtkennerly/dunamai/issues/23 --- .github/workflows/publish_testpypi.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish_testpypi.yml b/.github/workflows/publish_testpypi.yml index 6cafc3e..799c9ce 100644 --- a/.github/workflows/publish_testpypi.yml +++ b/.github/workflows/publish_testpypi.yml @@ -67,7 +67,7 @@ jobs: - name: Create dist/ run: | - python setup.py sdist bdist_wheel + python setup.py bdist_wheel twine check dist/* - name: Publish package to TestPyPI From 7a3b1eb8ad5e6f525b8a1767cfcdd41da2f6c55a Mon Sep 17 00:00:00 2001 From: Tom Roberts Date: Tue, 20 Feb 2024 10:47:37 +0000 Subject: [PATCH 02/45] Adds GHA trigger on PR --- .github/workflows/publish_testpypi.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/publish_testpypi.yml b/.github/workflows/publish_testpypi.yml index 799c9ce..a4c1ead 100644 --- a/.github/workflows/publish_testpypi.yml +++ b/.github/workflows/publish_testpypi.yml @@ -16,6 +16,7 @@ name: Publish package to TestPyPI on: + pull_request_target: push: branches: - main From 45d37a5cf654230c4d5bdd1bc1d35a1fc8d83624 Mon Sep 17 00:00:00 2001 From: Tom Roberts Date: Tue, 20 Feb 2024 11:01:14 +0000 Subject: [PATCH 03/45] Update publish_testpypi.yml --- .github/workflows/publish_testpypi.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish_testpypi.yml b/.github/workflows/publish_testpypi.yml index a4c1ead..e8b22f6 100644 --- a/.github/workflows/publish_testpypi.yml +++ b/.github/workflows/publish_testpypi.yml @@ -16,7 +16,7 @@ name: Publish package to TestPyPI on: - pull_request_target: + pull_request: push: branches: - main From afdb564f12788aa49acc0e3fa69b9b43dd697afd Mon Sep 17 00:00:00 2001 From: Tom Roberts Date: Tue, 20 Feb 2024 11:23:34 +0000 Subject: [PATCH 04/45] Test _dunamai.get_version() Also uses Version.from_any_vcs instead of Version.from_git() --- nii2dcm/_version.py | 5 ++++- setup.py | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/nii2dcm/_version.py b/nii2dcm/_version.py index b8bebde..b4c4465 100644 --- a/nii2dcm/_version.py +++ b/nii2dcm/_version.py @@ -1,2 +1,5 @@ +import dunamai as _dunamai from dunamai import Version, Style -__version__ = Version.from_git().serialize(metadata=False, style=Style.SemVer) +__version__ = _dunamai.get_version( + "nii2dcm", third_choice=_dunamai.Version.from_any_vcs +).serialize(metadata=False, style=Style.SemVer) \ No newline at end of file diff --git a/setup.py b/setup.py index ce87831..9f8c9e7 100644 --- a/setup.py +++ b/setup.py @@ -3,5 +3,5 @@ setup( name="nii2dcm", - version=Version.from_git().serialize(metadata=False, style=Style.SemVer), + version=Version.from_any_vcs().serialize(metadata=False, style=Style.SemVer), ) \ No newline at end of file From a90cbc3fd55bf7ba18c2295c6a307904e474ea38 Mon Sep 17 00:00:00 2001 From: Tom Roberts Date: Tue, 20 Feb 2024 11:29:27 +0000 Subject: [PATCH 05/45] Removes Style.SemVer call during serialize --- nii2dcm/_version.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/nii2dcm/_version.py b/nii2dcm/_version.py index b4c4465..2e76428 100644 --- a/nii2dcm/_version.py +++ b/nii2dcm/_version.py @@ -1,5 +1,3 @@ import dunamai as _dunamai from dunamai import Version, Style -__version__ = _dunamai.get_version( - "nii2dcm", third_choice=_dunamai.Version.from_any_vcs -).serialize(metadata=False, style=Style.SemVer) \ No newline at end of file +__version__ = _dunamai.get_version("nii2dcm", third_choice=_dunamai.Version.from_any_vcs).serialize() \ No newline at end of file From 21ab3bf52a09024f73cedf7b8e7b0da899467eeb Mon Sep 17 00:00:00 2001 From: Tom Roberts Date: Tue, 20 Feb 2024 11:39:38 +0000 Subject: [PATCH 06/45] Tidying --- nii2dcm/_version.py | 1 - 1 file changed, 1 deletion(-) diff --git a/nii2dcm/_version.py b/nii2dcm/_version.py index 2e76428..0699dbf 100644 --- a/nii2dcm/_version.py +++ b/nii2dcm/_version.py @@ -1,3 +1,2 @@ import dunamai as _dunamai -from dunamai import Version, Style __version__ = _dunamai.get_version("nii2dcm", third_choice=_dunamai.Version.from_any_vcs).serialize() \ No newline at end of file From f985a4661eaac6ecb9e29ffa3649b1e67b30c998 Mon Sep 17 00:00:00 2001 From: Tom Roberts Date: Tue, 20 Feb 2024 11:40:33 +0000 Subject: [PATCH 07/45] Changes -d/--dicom_type to list only currently available DICOM types --- nii2dcm/__main__.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/nii2dcm/__main__.py b/nii2dcm/__main__.py index de57792..abd393e 100644 --- a/nii2dcm/__main__.py +++ b/nii2dcm/__main__.py @@ -23,7 +23,11 @@ def cli(args=None): parser.add_argument("input_file", type=str, help="[.nii/.nii.gz] input NIfTI file") parser.add_argument("output_dir", type=str, help="[directory] output DICOM path") - parser.add_argument("-d", "--dicom_type", type=str, help="[string] type of DICOM. e.g. MR, CT, US, XR, etc.") + parser.add_argument( + "-d","--dicom_type", + type=str, + help="[string] type of DICOM. Available types: MR, SVR." + ) parser.add_argument("-r", "--ref_dicom", type=str, help="[.dcm] Reference DICOM file for Attribute transfer") parser.add_argument("-v", "--version", action="version", version=__version__) From 001f1420ea7691eca463d3b75990c5901ba3ea21 Mon Sep 17 00:00:00 2001 From: Tom Roberts Date: Tue, 20 Feb 2024 11:41:32 +0000 Subject: [PATCH 08/45] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 7894e37..6f58ac6 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,7 @@ To install and run nii2dcm locally, you have two options: ### pip +Create a new Python virtual environment, then: ```shell pip install nii2dcm ``` From dce9133ad727323910bc7a4bc4db1f79473032fd Mon Sep 17 00:00:00 2001 From: Tom Roberts Date: Tue, 20 Feb 2024 11:41:50 +0000 Subject: [PATCH 09/45] Adds setuptools and wheel to requirements.txt --- README.md | 1 - requirements.txt | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6f58ac6..68cc552 100644 --- a/README.md +++ b/README.md @@ -75,7 +75,6 @@ python -m pip install --upgrade pip Install dependencies and nii2dcm: ```sh -pip install setuptools wheel pip install -r requirements.txt pip install . ``` diff --git a/requirements.txt b/requirements.txt index 91edd24..d7e88bb 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,5 @@ +setuptools +wheel numpy==1.23.2 matplotlib==3.6.2 nibabel==5.0.0 From 66edf6b4a9c2b34fcc6efe6bf1ffbfb5d1872e4a Mon Sep 17 00:00:00 2001 From: Tom Roberts Date: Tue, 20 Feb 2024 11:44:23 +0000 Subject: [PATCH 10/45] Removes sdist from PyPI build --- .github/workflows/publish_pypi.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish_pypi.yml b/.github/workflows/publish_pypi.yml index 6f37c80..c201874 100644 --- a/.github/workflows/publish_pypi.yml +++ b/.github/workflows/publish_pypi.yml @@ -70,7 +70,7 @@ jobs: - name: Create dist/ run: | - python setup.py sdist bdist_wheel + python setup.py bdist_wheel twine check dist/* - name: Publish package to PyPI From b0b47aef9c18adef42ade0742d73a570997d7c52 Mon Sep 17 00:00:00 2001 From: Tom Roberts Date: Tue, 20 Feb 2024 12:42:29 +0000 Subject: [PATCH 11/45] WIP: create Dockerfile TODO: update pip install nii2dcm with PyPI version --- Dockerfile | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..abada6f --- /dev/null +++ b/Dockerfile @@ -0,0 +1,21 @@ +# Use the official Python image as the base image +FROM python:3.9-slim + +# Install system dependencies +RUN apt-get update && apt-get install -y \ + bash \ + && apt-get clean + +RUN pip install --upgrade pip && \ + pip install setuptools wheel + +RUN pip install --index-url https://test.pypi.org/simple/ \ + --extra-index-url https://pypi.org/simple/ nii2dcm==0.1.2-post.11 + +#RUN pip install nii2dcm + +# Test nii2dcm install +# To see output locally during build process: docker build -t nii2dcm --progress=plain . +RUN nii2dcm -h + +ENTRYPOINT ["nii2dcm"] \ No newline at end of file From 15942d9672e1feeba348d927c4726ce796269ee8 Mon Sep 17 00:00:00 2001 From: Tom Roberts Date: Tue, 20 Feb 2024 13:54:34 +0000 Subject: [PATCH 12/45] Update build_and_test GHA with container creation and testing --- .github/workflows/build_and_test_cli.yml | 31 ++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build_and_test_cli.yml b/.github/workflows/build_and_test_cli.yml index 9c29120..03cf602 100644 --- a/.github/workflows/build_and_test_cli.yml +++ b/.github/workflows/build_and_test_cli.yml @@ -6,8 +6,8 @@ on: pull_request: jobs: - build-and-test: - name: Build + venv-build-and-test: + name: venv build runs-on: ${{ matrix.os }} @@ -65,3 +65,30 @@ jobs: ls ./output # assert DICOM files exist [ -f "./output/IM_0001.dcm" ] && echo "Output DICOM file exists" || exit 1 + + container-build-and-test: + name: container build + + runs-on: ${{ matrix.os }} + + strategy: + fail-fast: false + matrix: + os: [ ubuntu-latest ] + python-version: [ '3.9' ] + + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Build container + run: | + docker build -t nii2dcm --progress=plain --no-cache . + docker ps + + - name: Test nii2dcm container + run: | + docker run nii2dcm -h + echo "nii2dcm version:" + docker run nii2dcm -v \ No newline at end of file From d9b05e3728f8312e65443656b21e830ae690d604 Mon Sep 17 00:00:00 2001 From: Tom Roberts Date: Tue, 20 Feb 2024 15:44:32 +0000 Subject: [PATCH 13/45] Create test_dcm.py --- tests/test_dcm.py | 82 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 tests/test_dcm.py diff --git a/tests/test_dcm.py b/tests/test_dcm.py new file mode 100644 index 0000000..20bf1c3 --- /dev/null +++ b/tests/test_dcm.py @@ -0,0 +1,82 @@ +import pytest +import os +import datetime + +from pydicom.dataset import FileMetaDataset, FileDataset + +from nii2dcm.dcm import Dicom +from nii2dcm.modules.patient import Patient + + +TRANSFER_SYNTAX_UID = '1.2.840.10008.1.2.1' +DATE = datetime.datetime.now().strftime('%Y%m%d') +PATIENT_ID = '12345678' +PATIENT_SEX = '' +IMAGE_TYPE = ['SECONDARY', 'DERIVED'] +CHARACTER_SET = 'ISO_IR 100' + +MIN_UID_LENGTH = 10 # arbitrary just to check UID has some characters +MAX_UID_LENGTH = 64 # DICOM standard max length + +class TestDicom: + def setup_method(self): + self.dicom = Dicom() + + def test_dicom(self): + """ + Tests some metadata in basic Dicom object + """ + assert self.dicom.file_meta.TransferSyntaxUID == TRANSFER_SYNTAX_UID + assert self.dicom.ds.ContentDate == DATE + assert self.dicom.ds.AcquisitionDate == DATE + assert self.dicom.ds.SeriesDate == DATE + assert self.dicom.ds.StudyDate == DATE + + def test_add_module(self): + """ + Tests add_module() method + """ + self.dicom.add_module(Patient()) + assert self.dicom.ds.PatientID == PATIENT_ID + assert self.dicom.ds.PatientSex == PATIENT_SEX + + def test_add_base_modules(self): + """ + Test metadata present following bulk method invocation via add_base_modules() + """ + self.dicom.add_base_modules() + assert self.dicom.ds.SpecificCharacterSet == CHARACTER_SET + assert self.dicom.ds.ImageType[0] == 'SECONDARY' + assert self.dicom.ds.ImageType[1] == 'DERIVED' + + def test_get_file_meta(self): + fm = self.dicom.get_file_meta() + assert isinstance(fm, FileMetaDataset) + + def test_get_dataset(self): + ds = self.dicom.get_dataset() + assert isinstance(ds, FileDataset) + + def test_save_as(self): + """ + Test DICOM save (default save location: cwd) + """ + self.dicom.ds.save_as(self.dicom.filename) + assert os.path.exists(self.dicom.filename) + os.remove(self.dicom.filename) + if os.path.exists(self.dicom.filename): + raise Exception("Failed to delete temporary DICOM during pytest process.") + + def test_init_study_tags(self): + self.dicom.init_study_tags() + assert isinstance(self.dicom.ds.StudyInstanceUID, str) + assert self.dicom.ds.StudyInstanceUID.find(".") + assert MIN_UID_LENGTH < len(self.dicom.ds.StudyInstanceUID) <= MAX_UID_LENGTH + + def test_init_series_tags(self): + self.dicom.init_study_tags() + assert isinstance(self.dicom.ds.SeriesInstanceUID, str) + assert self.dicom.ds.SeriesInstanceUID.find(".") + assert MIN_UID_LENGTH < len(self.dicom.ds.SeriesInstanceUID) <= MAX_UID_LENGTH + + assert len(str(self.dicom.ds.SeriesNumber)) == 4 From 23cf1b01ab9748d4f7cc454612e48657e691328e Mon Sep 17 00:00:00 2001 From: Tom Roberts Date: Tue, 20 Feb 2024 15:56:57 +0000 Subject: [PATCH 14/45] Create test_version.py --- tests/test_version.py | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 tests/test_version.py diff --git a/tests/test_version.py b/tests/test_version.py new file mode 100644 index 0000000..caf55d2 --- /dev/null +++ b/tests/test_version.py @@ -0,0 +1,9 @@ +import pytest +from packaging import version + +from nii2dcm._version import __version__ + + +class TestVersion: + def test_version(self): + assert isinstance(version.parse(__version__), version.Version) From f99e4fd567b558c3883022da3309cce0ce34934d Mon Sep 17 00:00:00 2001 From: Tom Roberts Date: Tue, 20 Feb 2024 16:15:44 +0000 Subject: [PATCH 15/45] Amends Exception output --- tests/test_dcm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_dcm.py b/tests/test_dcm.py index 20bf1c3..046dd0f 100644 --- a/tests/test_dcm.py +++ b/tests/test_dcm.py @@ -65,7 +65,7 @@ def test_save_as(self): assert os.path.exists(self.dicom.filename) os.remove(self.dicom.filename) if os.path.exists(self.dicom.filename): - raise Exception("Failed to delete temporary DICOM during pytest process.") + raise Exception("Failed to delete temporary DICOM created during pytest process.") def test_init_study_tags(self): self.dicom.init_study_tags() From e23e41ba0a73b7c457aed517455853476695eccf Mon Sep 17 00:00:00 2001 From: Tom Roberts Date: Tue, 20 Feb 2024 16:43:21 +0000 Subject: [PATCH 16/45] Changes variable name to slice_index for clarity --- nii2dcm/dcm_writer.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/nii2dcm/dcm_writer.py b/nii2dcm/dcm_writer.py index 4689376..f1291a8 100644 --- a/nii2dcm/dcm_writer.py +++ b/nii2dcm/dcm_writer.py @@ -6,19 +6,19 @@ import pydicom as pyd -def write_slice(dcm, img_data, instance_index, output_dir): +def write_slice(dcm, img_data, slice_index, output_dir): """ write a single DICOM slice dcm – nii2dcm DICOM object img_data - [nX, nY, nSlice] image pixel data, such as from NIfTI file - instance_index – instance index (important: counts from 0) + slice_index – slice index in nibabel img_data array (important: counts from 0, whereas DICOM instances count from 1) output_dir – output DICOM file save location """ - output_filename = r'IM_%04d.dcm' % (instance_index + 1) # begin filename from 1, e.g. IM_0001.dcm + output_filename = r'IM_%04d.dcm' % (slice_index + 1) # begin filename from 1, e.g. IM_0001.dcm - img_slice = img_data[:, :, instance_index] + img_slice = img_data[:, :, slice_index] # Instance UID – unique to current slice dcm.ds.SOPInstanceUID = pyd.uid.generate_uid(None) From a8a6c3e883da9d4b61937bc6b6eb5eed93f0cc28 Mon Sep 17 00:00:00 2001 From: Tom Roberts Date: Tue, 20 Feb 2024 16:44:15 +0000 Subject: [PATCH 17/45] Create test_dcm_writer.py --- tests/test_dcm_writer.py | 46 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 tests/test_dcm_writer.py diff --git a/tests/test_dcm_writer.py b/tests/test_dcm_writer.py new file mode 100644 index 0000000..2b460a0 --- /dev/null +++ b/tests/test_dcm_writer.py @@ -0,0 +1,46 @@ +import os + +import pytest +import nibabel as nib + +from nii2dcm import dcm_writer +from nii2dcm.dcm import Dicom +from nii2dcm.nii import Nifti + + +NII_FILE_PATH = "tests/data/DicomMRISVR/t2-svr-atlas-35wk.nii.gz" +INSTANCE_INDEX = 10 # dcm instances count from 1 +SLICE_NUMBER = INSTANCE_INDEX-1 # nibabel slice array counts from 0 +OUTPUT_DIR = "tests/data" +OUTPUT_DCM_FILENAME = r'IM_%04d.dcm' % (INSTANCE_INDEX) +OUTPUT_DCM_PATH = os.path.join(os.getcwd(), OUTPUT_DIR, OUTPUT_DCM_FILENAME) + +class TestDicomWriter: + def setup_method(self): + self.dicom = Dicom() + self.nii = nib.load(NII_FILE_PATH) + self.img_data = self.nii.get_fdata().astype("uint16") + self.nii2dcm_parameters = Nifti.get_nii2dcm_parameters(self.nii) + + def test_write_slice(self): + dcm_writer.write_slice(self.dicom, self.img_data, SLICE_NUMBER, OUTPUT_DIR) + + assert os.path.exists(OUTPUT_DCM_PATH) + os.remove(OUTPUT_DCM_PATH) + if os.path.exists(OUTPUT_DCM_PATH): + raise Exception("Failed to delete temporary DICOM created during pytest process.") + + def test_transfer_nii_hdr_series_tags(self): + dcm_writer.transfer_nii_hdr_series_tags(self.dicom, self.nii2dcm_parameters) + assert self.dicom.ds.Rows == self.nii.shape[0] + assert self.dicom.ds.Columns == self.nii.shape[1] + + def test_transfer_nii_hdr_instance_tags(self): + dcm_writer.transfer_nii_hdr_instance_tags(self.dicom, self.nii2dcm_parameters, SLICE_NUMBER) + assert self.dicom.ds.InstanceNumber == INSTANCE_INDEX + + def test_transfer_ref_dicom_series_tags(self): + """ + TODO: implement test + """ + pass From 32aec6d3ce1ee4302898b95cfada778187b042a9 Mon Sep 17 00:00:00 2001 From: Tom Roberts Date: Tue, 20 Feb 2024 17:15:55 +0000 Subject: [PATCH 18/45] Create test_nii.py --- tests/test_nii.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 tests/test_nii.py diff --git a/tests/test_nii.py b/tests/test_nii.py new file mode 100644 index 0000000..d59e4a0 --- /dev/null +++ b/tests/test_nii.py @@ -0,0 +1,23 @@ +import pytest + +from nii2dcm.nii import Nifti +import nibabel as nib + + +NII_FILE_PATH = "tests/data/DicomMRISVR/t2-svr-atlas-35wk.nii.gz" +NII_VOXEL_DIMS = (180, 221, 180) +NII_VOXEL_SPACING = (0.5, 0.5, 0.5) + +class TestNifti: + def setup_method(self): + self.nii = nib.load(NII_FILE_PATH) + + def test_get_nii2dcm_parameters(self): + nii_parameters = Nifti.get_nii2dcm_parameters(self.nii) + assert nii_parameters["Rows"] == NII_VOXEL_DIMS[0] + assert nii_parameters["Columns"] == NII_VOXEL_DIMS[1] + assert nii_parameters["NumberOfSlices"] == NII_VOXEL_DIMS[2] + assert nii_parameters["AcquisitionMatrix"] == [0, NII_VOXEL_DIMS[0], NII_VOXEL_DIMS[1], 0] + assert nii_parameters["dimX"] == NII_VOXEL_SPACING[0] + assert nii_parameters["dimY"] == NII_VOXEL_SPACING[1] + assert nii_parameters["SliceThickness"] == str(NII_VOXEL_SPACING[2]) From 7003bf117f55ef3c633ae0f54e845cff7ce6dfd2 Mon Sep 17 00:00:00 2001 From: Tom Roberts Date: Tue, 20 Feb 2024 17:54:16 +0000 Subject: [PATCH 19/45] Create test_run.py --- tests/test_run.py | 55 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 tests/test_run.py diff --git a/tests/test_run.py b/tests/test_run.py new file mode 100644 index 0000000..8c95343 --- /dev/null +++ b/tests/test_run.py @@ -0,0 +1,55 @@ +import pytest +import os, shutil +import pydicom as pyd + +from nii2dcm.run import run_nii2dcm + + +NII_FILE_PATH = "tests/data/DicomMRISVR/t2-svr-atlas-35wk.nii.gz" +OUTPUT_DIR = "tests/data/tmp_dcm_dir" +OUTPUT_DCM_PATH = os.path.join(os.getcwd(), OUTPUT_DIR) +NUM_DICOM_FILES = 180 +SINGLE_DICOM_FILENAME = "IM_0001.dcm" + +class TestRun: + def setup_method(self): + os.makedirs(OUTPUT_DCM_PATH, exist_ok=True) + + @pytest.mark.parametrize( + "TEST_DICOM_TYPE, TEST_DCM_MODALITY", + [ + (None, ''), # basic DICOM with undefined modality + ("MR", "MR"), # MRI DICOM + ("SVR", "MR") # SVR DICOM hence MR modality + ] + ) + def test_run_dicom_types(self, TEST_DICOM_TYPE, TEST_DCM_MODALITY): + """ + Test run_nii2dcm with different dicom_types + """ + run_nii2dcm( + NII_FILE_PATH, + OUTPUT_DCM_PATH, + dicom_type=TEST_DICOM_TYPE + ) + assert os.path.exists(os.path.join(OUTPUT_DCM_PATH, SINGLE_DICOM_FILENAME)) + assert len(os.listdir(OUTPUT_DCM_PATH)) == NUM_DICOM_FILES + + ds = pyd.dcmread(os.path.join(OUTPUT_DCM_PATH, SINGLE_DICOM_FILENAME)) + assert ds.Modality == TEST_DCM_MODALITY + + shutil.rmtree(OUTPUT_DCM_PATH) + + def test_run_reference_dicom(self): + """ + Test run_nii2dcm with different ref_dicom option + """ + # TODO: implement - will involve adding reference DICOM test dataset + pass + + def teardown_method(self): + """ + Remove output DICOM directory in event of test failure + """ + if os.path.exists(OUTPUT_DCM_PATH): + shutil.rmtree(OUTPUT_DCM_PATH) From b2bec4260a7edca0900ccc34beb9928a857fad8f Mon Sep 17 00:00:00 2001 From: Tom Roberts Date: Wed, 21 Feb 2024 16:54:40 +0000 Subject: [PATCH 20/45] Adds unit tests to GHA --- .github/workflows/build_and_test_cli.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build_and_test_cli.yml b/.github/workflows/build_and_test_cli.yml index 9c29120..0e49478 100644 --- a/.github/workflows/build_and_test_cli.yml +++ b/.github/workflows/build_and_test_cli.yml @@ -1,4 +1,4 @@ -# Workflow to build nii2dcm and test different command line interface (CLI) options +# Workflow to build nii2dcm, run unit tests and then execute command line interface (CLI) end-to-end name: Build nii2dcm @@ -7,7 +7,7 @@ on: jobs: build-and-test: - name: Build + name: Build, Unit Tests & E2E runs-on: ${{ matrix.os }} @@ -57,6 +57,10 @@ jobs: nii2dcm -h nii2dcm -v + - name: Run unit tests + run: | + pytest tests/ + - name: Test DicomMRISVR creation run: | # run nii2dcm From ccb57eb85a343a9608629a9f750956dd8edb2e15 Mon Sep 17 00:00:00 2001 From: Tom Roberts Date: Wed, 21 Feb 2024 17:22:18 +0000 Subject: [PATCH 21/45] Adds pytest coverage comment/badge to GHA --- .github/workflows/build_and_test_cli.yml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/.github/workflows/build_and_test_cli.yml b/.github/workflows/build_and_test_cli.yml index 0e49478..4f218f1 100644 --- a/.github/workflows/build_and_test_cli.yml +++ b/.github/workflows/build_and_test_cli.yml @@ -69,3 +69,24 @@ jobs: ls ./output # assert DICOM files exist [ -f "./output/IM_0001.dcm" ] && echo "Output DICOM file exists" || exit 1 + + - name: Build pytest coverage file + run: | + pytest --junitxml=pytest.xml --cov-report=term-missing:skip-covered --cov=nii2dcm tests/ | tee pytest-coverage.txt ; echo $? + + - name: Pytest coverage comment + uses: MishaKav/pytest-coverage-comment@main + with: + pytest-coverage-path: ./pytest-coverage.txt + junitxml-path: ./pytest.xml + + - name: Update Coverage Badge + uses: schneegans/dynamic-badges-action@v1.7.0 + with: + auth: ${{ secrets.PYTEST_COVERAGE_COMMENT }} + gistID: 57ef8057d04f67dbe6e64df410b83079 + filename: nii2dcm-pytest-coverage-comment.json + label: Coverage Report + message: ${{ steps.coverageComment.outputs.coverage }} + color: ${{ steps.coverageComment.outputs.color }} + namedLogo: python From 54e783b99c161609e8a34f55fb3b6bcbce3f1429 Mon Sep 17 00:00:00 2001 From: Tom Roberts Date: Wed, 21 Feb 2024 17:35:53 +0000 Subject: [PATCH 22/45] Updates README with coverage badges --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 68cc552..f277715 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,10 @@ · Request Feature

+

+ + +

From 765af048a71f4627224e269ab3cc7d6278d96801 Mon Sep 17 00:00:00 2001 From: Tom Roberts Date: Wed, 21 Feb 2024 17:57:50 +0000 Subject: [PATCH 23/45] Fixes some formatting issues --- nii2dcm/__main__.py | 2 +- nii2dcm/_version.py | 2 +- nii2dcm/dcm.py | 3 +-- nii2dcm/modules/mr_image.py | 4 ++-- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/nii2dcm/__main__.py b/nii2dcm/__main__.py index abd393e..f3ff34c 100644 --- a/nii2dcm/__main__.py +++ b/nii2dcm/__main__.py @@ -24,7 +24,7 @@ def cli(args=None): parser.add_argument("input_file", type=str, help="[.nii/.nii.gz] input NIfTI file") parser.add_argument("output_dir", type=str, help="[directory] output DICOM path") parser.add_argument( - "-d","--dicom_type", + "-d", "--dicom_type", type=str, help="[string] type of DICOM. Available types: MR, SVR." ) diff --git a/nii2dcm/_version.py b/nii2dcm/_version.py index 0699dbf..2a05741 100644 --- a/nii2dcm/_version.py +++ b/nii2dcm/_version.py @@ -1,2 +1,2 @@ import dunamai as _dunamai -__version__ = _dunamai.get_version("nii2dcm", third_choice=_dunamai.Version.from_any_vcs).serialize() \ No newline at end of file +__version__ = _dunamai.get_version("nii2dcm", third_choice=_dunamai.Version.from_any_vcs).serialize() diff --git a/nii2dcm/dcm.py b/nii2dcm/dcm.py index 7421db0..a7c537a 100644 --- a/nii2dcm/dcm.py +++ b/nii2dcm/dcm.py @@ -11,7 +11,6 @@ import pydicom as pyd from pydicom.dataset import FileDataset, FileMetaDataset -from nii2dcm.utils import dcm_dictionary_update from nii2dcm.modules.patient import Patient from nii2dcm.modules.general_study import GeneralStudy from nii2dcm.modules.patient_study import PatientStudy @@ -67,7 +66,7 @@ def __init__(self, filename=nii2dcm_temp_filename): """ Set Dicom Date/Time - Important: doing this once sets all Instances/Series/Study creation dates and times to the same values. Whereas, + Important: doing this once sets all Instances/Series/Study creation dates and times to the same values. Whereas, doing this within the Modules would every so slightly offset the times """ # TODO shift to utils.py and propagate to Modules, or, create method within this Dicom class diff --git a/nii2dcm/modules/mr_image.py b/nii2dcm/modules/mr_image.py index 7f146da..a460ca7 100644 --- a/nii2dcm/modules/mr_image.py +++ b/nii2dcm/modules/mr_image.py @@ -24,9 +24,9 @@ def __init__(self): # https://dicom.nema.org/medical/Dicom/current/output/chtml/part03/sect_C.8.3.html#sect_C.8.3.1.1.1 # For now, will omit thereby inheriting parent value # self.ds.ImageType = '' - + self.ds.SamplesPerPixel = 1 - + # PhotometricInterpretation # TODO: decide MONOCHROME1 or MONOCHROME2 as default # https://dicom.nema.org/medical/Dicom/current/output/chtml/part03/sect_C.7.6.3.html#sect_C.7.6.3.1.2 From e4cf41d97c9151bbdf70e93aae4b1cd6619a783f Mon Sep 17 00:00:00 2001 From: Tom Roberts Date: Wed, 21 Feb 2024 18:17:25 +0000 Subject: [PATCH 24/45] Amends and re-tests pytest coverage badge --- .github/workflows/build_and_test_cli.yml | 3 ++- README.md | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build_and_test_cli.yml b/.github/workflows/build_and_test_cli.yml index 4f218f1..b3a81e1 100644 --- a/.github/workflows/build_and_test_cli.yml +++ b/.github/workflows/build_and_test_cli.yml @@ -75,7 +75,8 @@ jobs: pytest --junitxml=pytest.xml --cov-report=term-missing:skip-covered --cov=nii2dcm tests/ | tee pytest-coverage.txt ; echo $? - name: Pytest coverage comment - uses: MishaKav/pytest-coverage-comment@main + id: coverageComment + uses: MishaKav/pytest-coverage-comment@unit-tests with: pytest-coverage-path: ./pytest-coverage.txt junitxml-path: ./pytest.xml diff --git a/README.md b/README.md index f277715..0a30d62 100644 --- a/README.md +++ b/README.md @@ -22,8 +22,8 @@

- -

+ +

From 2deaf280900b25f3a0bf2601f73f0a82b6930cf2 Mon Sep 17 00:00:00 2001 From: Tom Roberts Date: Wed, 21 Feb 2024 18:18:59 +0000 Subject: [PATCH 25/45] =?UTF-8?q?Typo=20=E2=80=93=20re-test?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/build_and_test_cli.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_and_test_cli.yml b/.github/workflows/build_and_test_cli.yml index b3a81e1..1497aef 100644 --- a/.github/workflows/build_and_test_cli.yml +++ b/.github/workflows/build_and_test_cli.yml @@ -76,7 +76,7 @@ jobs: - name: Pytest coverage comment id: coverageComment - uses: MishaKav/pytest-coverage-comment@unit-tests + uses: MishaKav/pytest-coverage-comment@main with: pytest-coverage-path: ./pytest-coverage.txt junitxml-path: ./pytest.xml From 0f382d9bf3f178bb8749d4849a3fd2b14330b583 Mon Sep 17 00:00:00 2001 From: Tom Roberts Date: Wed, 21 Feb 2024 18:21:19 +0000 Subject: [PATCH 26/45] Test coverage badge on unit-tests branch --- .github/workflows/build_and_test_cli.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build_and_test_cli.yml b/.github/workflows/build_and_test_cli.yml index 1497aef..f3a662c 100644 --- a/.github/workflows/build_and_test_cli.yml +++ b/.github/workflows/build_and_test_cli.yml @@ -80,6 +80,7 @@ jobs: with: pytest-coverage-path: ./pytest-coverage.txt junitxml-path: ./pytest.xml + default-branch: unit-tests - name: Update Coverage Badge uses: schneegans/dynamic-badges-action@v1.7.0 From be589f94ca63ba0fec0ba1ac613180a79857657e Mon Sep 17 00:00:00 2001 From: Tom Roberts Date: Wed, 21 Feb 2024 18:32:57 +0000 Subject: [PATCH 27/45] Create __init__.py --- tests/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/__init__.py diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 From 2bb4058c37d1bebb3444dcecc15daf1d4ef89631 Mon Sep 17 00:00:00 2001 From: Tom Roberts Date: Wed, 21 Feb 2024 18:35:18 +0000 Subject: [PATCH 28/45] Update .gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index d7c3b9c..8234174 100644 --- a/.gitignore +++ b/.gitignore @@ -48,6 +48,8 @@ coverage.xml .hypothesis/ .pytest_cache/ cover/ +pytest-coverage.txt +pytest.xml # Sphinx documentation docs/_build/ From 1f972949b23f55c03c94e68450f3d3577b997214 Mon Sep 17 00:00:00 2001 From: Tom Roberts Date: Thu, 22 Feb 2024 17:21:36 +0000 Subject: [PATCH 29/45] Adds Docker section to README --- README.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/README.md b/README.md index 0a30d62..3e6cade 100644 --- a/README.md +++ b/README.md @@ -142,6 +142,26 @@ Currently, attributes to transfer are [listed here in the DicomMRI class](https:

(back to top)

+ +## Docker +nii2dcm is also available as a Docker container. + +Pull the latest container with: +```shell +docker pull ghcr.io/tomaroberts/nii2dcm/nii2dcm:latest +``` + +Run the containerised nii2dcm: +```shell +# display nii2dcm version +docker run nii2dcm -v + +# perform nii2dcm conversion +docker run nii2dcm nifti-file.nii.gz dicom-output-directory/ -d MR +``` + +

(back to top)

+ ## Roadmap From 4edd9eb571d5cda0dc71385250a0d3a33b2f4242 Mon Sep 17 00:00:00 2001 From: Tom Roberts Date: Fri, 1 Mar 2024 10:30:36 +0000 Subject: [PATCH 30/45] Test container build GHA --- .github/workflows/publish_testpypi.yml | 32 ++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/.github/workflows/publish_testpypi.yml b/.github/workflows/publish_testpypi.yml index e8b22f6..9c57ec7 100644 --- a/.github/workflows/publish_testpypi.yml +++ b/.github/workflows/publish_testpypi.yml @@ -96,3 +96,35 @@ jobs: nii2dcm -h echo "nii2dcm version:" nii2dcm -v + + ghcr-publish: + needs: testpypi-publish + runs-on: ubuntu-latest + + permissions: + contents: read + packages: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Log in to the Container registry + uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GHCR_TOKEN }} + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + + - name: Build and push Docker image + uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4 + with: + context: . + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} From a711e2e20f75d7460b96e148c6480bc46da2cc66 Mon Sep 17 00:00:00 2001 From: Tom Roberts Date: Fri, 1 Mar 2024 12:42:53 +0000 Subject: [PATCH 31/45] Adds LABEL --- Dockerfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Dockerfile b/Dockerfile index abada6f..1ba41d2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,8 @@ # Use the official Python image as the base image FROM python:3.9-slim +LABEL org.opencontainers.image.source https://github.com/tomaroberts/nii2dcm + # Install system dependencies RUN apt-get update && apt-get install -y \ bash \ From e538735959b766cdfacbe3097bcdb6daca028a17 Mon Sep 17 00:00:00 2001 From: Tom Roberts Date: Fri, 1 Mar 2024 12:43:01 +0000 Subject: [PATCH 32/45] Revert "Test container build GHA" This reverts commit 4edd9eb571d5cda0dc71385250a0d3a33b2f4242. --- .github/workflows/publish_testpypi.yml | 32 -------------------------- 1 file changed, 32 deletions(-) diff --git a/.github/workflows/publish_testpypi.yml b/.github/workflows/publish_testpypi.yml index 9c57ec7..e8b22f6 100644 --- a/.github/workflows/publish_testpypi.yml +++ b/.github/workflows/publish_testpypi.yml @@ -96,35 +96,3 @@ jobs: nii2dcm -h echo "nii2dcm version:" nii2dcm -v - - ghcr-publish: - needs: testpypi-publish - runs-on: ubuntu-latest - - permissions: - contents: read - packages: write - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - name: Log in to the Container registry - uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GHCR_TOKEN }} - - - name: Extract metadata (tags, labels) for Docker - id: meta - uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7 - with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - - - name: Build and push Docker image - uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4 - with: - context: . - push: true - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} From 5539c404d5dd7e9edad2013e3456379005d442d1 Mon Sep 17 00:00:00 2001 From: Tom Roberts Date: Fri, 1 Mar 2024 12:43:43 +0000 Subject: [PATCH 33/45] Adds publish container to GHCR workflow --- .github/workflows/publish_ghcr.yml | 51 ++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 .github/workflows/publish_ghcr.yml diff --git a/.github/workflows/publish_ghcr.yml b/.github/workflows/publish_ghcr.yml new file mode 100644 index 0000000..1a282bc --- /dev/null +++ b/.github/workflows/publish_ghcr.yml @@ -0,0 +1,51 @@ +# Publish container to GHCR +# +# This workflow builds a nii2dcm container and publishes to GHCR + +name: Create and publish container on GHCR +on: + release: + types: [published] + push: + branches: + - docker-build + workflow_run: + workflows: ["Publish package to TestPyPI"] + types: + - completed + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + build-and-push-image: + runs-on: ubuntu-latest + + permissions: + contents: read + packages: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Log in to the Container registry + uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GHCR_TOKEN }} + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + + - name: Build and push Docker image + uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4 + with: + context: . + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} \ No newline at end of file From bd824eb738a4af54cb9fa6afa4e8145c81ba5af2 Mon Sep 17 00:00:00 2001 From: Tom Roberts Date: Fri, 1 Mar 2024 12:47:30 +0000 Subject: [PATCH 34/45] Update publish_ghcr.yml --- .github/workflows/publish_ghcr.yml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/.github/workflows/publish_ghcr.yml b/.github/workflows/publish_ghcr.yml index 1a282bc..51912b0 100644 --- a/.github/workflows/publish_ghcr.yml +++ b/.github/workflows/publish_ghcr.yml @@ -4,11 +4,6 @@ name: Create and publish container on GHCR on: - release: - types: [published] - push: - branches: - - docker-build workflow_run: workflows: ["Publish package to TestPyPI"] types: @@ -34,7 +29,7 @@ jobs: with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} - password: ${{ secrets.GHCR_TOKEN }} + password: ${{ secrets.GITHUB_TOKEN }} - name: Extract metadata (tags, labels) for Docker id: meta From d2e69035c1d2fd1c484bba71a01b4ea1b42c322f Mon Sep 17 00:00:00 2001 From: Tom Roberts Date: Fri, 1 Mar 2024 12:52:38 +0000 Subject: [PATCH 35/45] Update publish_ghcr.yml --- .github/workflows/publish_ghcr.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/publish_ghcr.yml b/.github/workflows/publish_ghcr.yml index 51912b0..8aec2ff 100644 --- a/.github/workflows/publish_ghcr.yml +++ b/.github/workflows/publish_ghcr.yml @@ -1,6 +1,7 @@ # Publish container to GHCR # # This workflow builds a nii2dcm container and publishes to GHCR +# name: Create and publish container on GHCR on: From 0fcb428fa57e4e158203321daea75a37a0697ac8 Mon Sep 17 00:00:00 2001 From: Tom Roberts Date: Fri, 1 Mar 2024 13:16:26 +0000 Subject: [PATCH 36/45] Test container build with TestPyPI package build --- .github/workflows/build_and_test_cli.yml | 4 +- .github/workflows/publish_ghcr.yml | 47 ------------------------ .github/workflows/publish_testpypi.yml | 32 ++++++++++++++++ 3 files changed, 34 insertions(+), 49 deletions(-) delete mode 100644 .github/workflows/publish_ghcr.yml diff --git a/.github/workflows/build_and_test_cli.yml b/.github/workflows/build_and_test_cli.yml index 120e24d..5cfa47e 100644 --- a/.github/workflows/build_and_test_cli.yml +++ b/.github/workflows/build_and_test_cli.yml @@ -6,8 +6,8 @@ on: pull_request: jobs: - build-and-test: - name: Build, Unit Tests & E2E + venv-build-and-test: + name: venv Build, Unit Tests & E2E runs-on: ${{ matrix.os }} diff --git a/.github/workflows/publish_ghcr.yml b/.github/workflows/publish_ghcr.yml deleted file mode 100644 index 8aec2ff..0000000 --- a/.github/workflows/publish_ghcr.yml +++ /dev/null @@ -1,47 +0,0 @@ -# Publish container to GHCR -# -# This workflow builds a nii2dcm container and publishes to GHCR -# - -name: Create and publish container on GHCR -on: - workflow_run: - workflows: ["Publish package to TestPyPI"] - types: - - completed - -env: - REGISTRY: ghcr.io - IMAGE_NAME: ${{ github.repository }} - -jobs: - build-and-push-image: - runs-on: ubuntu-latest - - permissions: - contents: read - packages: write - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - name: Log in to the Container registry - uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Extract metadata (tags, labels) for Docker - id: meta - uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7 - with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - - - name: Build and push Docker image - uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4 - with: - context: . - push: true - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} \ No newline at end of file diff --git a/.github/workflows/publish_testpypi.yml b/.github/workflows/publish_testpypi.yml index e8b22f6..9c57ec7 100644 --- a/.github/workflows/publish_testpypi.yml +++ b/.github/workflows/publish_testpypi.yml @@ -96,3 +96,35 @@ jobs: nii2dcm -h echo "nii2dcm version:" nii2dcm -v + + ghcr-publish: + needs: testpypi-publish + runs-on: ubuntu-latest + + permissions: + contents: read + packages: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Log in to the Container registry + uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GHCR_TOKEN }} + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + + - name: Build and push Docker image + uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4 + with: + context: . + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} From c3d6e996b9f121bcac10e581aa9614b81764c5f6 Mon Sep 17 00:00:00 2001 From: Tom Roberts Date: Fri, 1 Mar 2024 13:30:16 +0000 Subject: [PATCH 37/45] Update publish_testpypi.yml --- .github/workflows/publish_testpypi.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish_testpypi.yml b/.github/workflows/publish_testpypi.yml index 9c57ec7..630f0bf 100644 --- a/.github/workflows/publish_testpypi.yml +++ b/.github/workflows/publish_testpypi.yml @@ -108,10 +108,11 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v4 + - name: Log in to the Container registry uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1 with: - registry: ${{ env.REGISTRY }} + registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GHCR_TOKEN }} @@ -119,7 +120,9 @@ jobs: id: meta uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7 with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + images: | + ghcr.io/tomaroberts/nii2dcm + - name: Build and push Docker image uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4 From 975800a3e728c4372528482d9a9d07503849101b Mon Sep 17 00:00:00 2001 From: Tom Roberts Date: Fri, 1 Mar 2024 13:38:34 +0000 Subject: [PATCH 38/45] Re-test --- .github/workflows/publish_testpypi.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/publish_testpypi.yml b/.github/workflows/publish_testpypi.yml index 630f0bf..fb495e0 100644 --- a/.github/workflows/publish_testpypi.yml +++ b/.github/workflows/publish_testpypi.yml @@ -12,6 +12,7 @@ # They are provided by a third-party and are governed by # separate terms of service, privacy policy, and support # documentation. +# name: Publish package to TestPyPI @@ -108,7 +109,7 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v4 - + - name: Log in to the Container registry uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1 with: From 94e6c8171393bdc3ea0896fb0f3f8518168694bb Mon Sep 17 00:00:00 2001 From: Tom Roberts Date: Fri, 1 Mar 2024 13:52:14 +0000 Subject: [PATCH 39/45] Adds second wait time if TestPyPI install fails --- .github/workflows/publish_testpypi.yml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/.github/workflows/publish_testpypi.yml b/.github/workflows/publish_testpypi.yml index fb495e0..9773ab0 100644 --- a/.github/workflows/publish_testpypi.yml +++ b/.github/workflows/publish_testpypi.yml @@ -86,6 +86,28 @@ jobs: time: '150' # seconds - name: Install latest TestPyPI version in fresh venv + id: attempt1 + run: | + NII2DCM_VERSION=`echo "$(nii2dcm -v)"` + echo $NII2DCM_VERSION + python -m venv nii2dcm-temp + source nii2dcm-temp/bin/activate + pip install --upgrade pip + pip install setuptools wheel + pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ nii2dcm==$NII2DCM_VERSION + nii2dcm -h + echo "nii2dcm version:" + nii2dcm -v + continue-on-error: true + + - name: Wait longer + if: steps.attempt1.outcome != 'success' + uses: GuillaumeFalourd/wait-sleep-action@v1 + with: + time: '150' # seconds + + - name: Re-attempt TestPyPI install + if: steps.attempt1.outcome != 'success' run: | NII2DCM_VERSION=`echo "$(nii2dcm -v)"` echo $NII2DCM_VERSION From 2b72406d06fa1eeca3bc65092d97caab03c1910d Mon Sep 17 00:00:00 2001 From: Tom Roberts Date: Fri, 1 Mar 2024 14:06:07 +0000 Subject: [PATCH 40/45] Test updated secrets --- .github/workflows/publish_testpypi.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/publish_testpypi.yml b/.github/workflows/publish_testpypi.yml index 9773ab0..e1293d4 100644 --- a/.github/workflows/publish_testpypi.yml +++ b/.github/workflows/publish_testpypi.yml @@ -132,23 +132,23 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 - - name: Log in to the Container registry - uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1 + - name: Log in to GHCR + uses: docker/login-action@v3 with: registry: ghcr.io - username: ${{ github.actor }} + username: ${{ secrets.GHCR_USERNAME }} password: ${{ secrets.GHCR_TOKEN }} - name: Extract metadata (tags, labels) for Docker id: meta - uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7 + uses: docker/metadata-action@v5 with: images: | ghcr.io/tomaroberts/nii2dcm - name: Build and push Docker image - uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4 + uses: docker/build-push-action@v5 with: context: . push: true From e9a0c42718f1ef943283f72297327916ad52faa3 Mon Sep 17 00:00:00 2001 From: Tom Roberts Date: Fri, 1 Mar 2024 15:20:50 +0000 Subject: [PATCH 41/45] Moves container GHCR build to PyPI release GHA --- .github/workflows/publish_pypi.yml | 59 +++++++++++++++++++++++++- .github/workflows/publish_testpypi.yml | 35 --------------- 2 files changed, 58 insertions(+), 36 deletions(-) diff --git a/.github/workflows/publish_pypi.yml b/.github/workflows/publish_pypi.yml index c201874..fbf32fb 100644 --- a/.github/workflows/publish_pypi.yml +++ b/.github/workflows/publish_pypi.yml @@ -27,7 +27,7 @@ permissions: actions: write jobs: - testpypi-publish: + pypi-publish: name: Publish to PyPI runs-on: ubuntu-latest @@ -86,6 +86,7 @@ jobs: time: '150' # seconds - name: Install latest PyPI version in fresh venv + id: attempt1 run: | NII2DCM_VERSION=`echo "$(nii2dcm -v)"` echo $NII2DCM_VERSION @@ -97,3 +98,59 @@ jobs: nii2dcm -h echo "nii2dcm version:" nii2dcm -v + continue-on-error: true + + - name: Wait longer + if: steps.attempt1.outcome != 'success' + uses: GuillaumeFalourd/wait-sleep-action@v1 + with: + time: '150' # seconds + + - name: Re-attempt PyPI install + if: steps.attempt1.outcome != 'success' + run: | + NII2DCM_VERSION=`echo "$(nii2dcm -v)"` + echo $NII2DCM_VERSION + python -m venv nii2dcm-temp + source nii2dcm-temp/bin/activate + pip install --upgrade pip + pip install setuptools wheel + pip install nii2dcm==$NII2DCM_VERSION + nii2dcm -h + echo "nii2dcm version:" + nii2dcm -v + + ghcr-publish: + needs: pypi-publish + runs-on: ubuntu-latest + + permissions: + contents: read + packages: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Log in to GHCR + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ secrets.GHCR_USERNAME }} + password: ${{ secrets.GHCR_TOKEN }} + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@v5 + with: + images: | + ghcr.io/tomaroberts/nii2dcm + + + - name: Build and push Docker image + uses: docker/build-push-action@v5 + with: + context: . + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} diff --git a/.github/workflows/publish_testpypi.yml b/.github/workflows/publish_testpypi.yml index e1293d4..9a250d7 100644 --- a/.github/workflows/publish_testpypi.yml +++ b/.github/workflows/publish_testpypi.yml @@ -119,38 +119,3 @@ jobs: nii2dcm -h echo "nii2dcm version:" nii2dcm -v - - ghcr-publish: - needs: testpypi-publish - runs-on: ubuntu-latest - - permissions: - contents: read - packages: write - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Log in to GHCR - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ secrets.GHCR_USERNAME }} - password: ${{ secrets.GHCR_TOKEN }} - - - name: Extract metadata (tags, labels) for Docker - id: meta - uses: docker/metadata-action@v5 - with: - images: | - ghcr.io/tomaroberts/nii2dcm - - - - name: Build and push Docker image - uses: docker/build-push-action@v5 - with: - context: . - push: true - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} From c8473c7f761b00ccc7fbcc44c807f82fa1bf81b3 Mon Sep 17 00:00:00 2001 From: Tom Roberts Date: Fri, 1 Mar 2024 15:21:01 +0000 Subject: [PATCH 42/45] Minor formatting changes --- .github/workflows/build_and_test_cli.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build_and_test_cli.yml b/.github/workflows/build_and_test_cli.yml index 5cfa47e..04ac3fb 100644 --- a/.github/workflows/build_and_test_cli.yml +++ b/.github/workflows/build_and_test_cli.yml @@ -1,13 +1,13 @@ # Workflow to build nii2dcm, run unit tests and then execute command line interface (CLI) end-to-end -name: Build nii2dcm +name: Build & Test nii2dcm on: pull_request: jobs: venv-build-and-test: - name: venv Build, Unit Tests & E2E + name: venv + E2E runs-on: ${{ matrix.os }} @@ -94,7 +94,7 @@ jobs: namedLogo: python container-build-and-test: - name: Container Build & Test + name: Container runs-on: ${{ matrix.os }} From d46fbf44dbf2c29eb50dae03c42d67634ec8d1b9 Mon Sep 17 00:00:00 2001 From: Tom Roberts Date: Fri, 1 Mar 2024 15:38:55 +0000 Subject: [PATCH 43/45] Formatting fix --- .github/workflows/publish_pypi.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/publish_pypi.yml b/.github/workflows/publish_pypi.yml index fbf32fb..5ca0459 100644 --- a/.github/workflows/publish_pypi.yml +++ b/.github/workflows/publish_pypi.yml @@ -146,7 +146,6 @@ jobs: images: | ghcr.io/tomaroberts/nii2dcm - - name: Build and push Docker image uses: docker/build-push-action@v5 with: From ee2cc62036148494632a6bc2270a569eed50fa3e Mon Sep 17 00:00:00 2001 From: Tom Roberts Date: Fri, 1 Mar 2024 15:45:53 +0000 Subject: [PATCH 44/45] Update so coverage comment displayed on all branches --- .github/workflows/build_and_test_cli.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/build_and_test_cli.yml b/.github/workflows/build_and_test_cli.yml index f3a662c..1497aef 100644 --- a/.github/workflows/build_and_test_cli.yml +++ b/.github/workflows/build_and_test_cli.yml @@ -80,7 +80,6 @@ jobs: with: pytest-coverage-path: ./pytest-coverage.txt junitxml-path: ./pytest.xml - default-branch: unit-tests - name: Update Coverage Badge uses: schneegans/dynamic-badges-action@v1.7.0 From ee02e23839ec322fe5aa9b543e32bab70a9557ec Mon Sep 17 00:00:00 2001 From: Tom Roberts Date: Fri, 1 Mar 2024 16:17:11 +0000 Subject: [PATCH 45/45] Update Dockerfile to build from source --- Dockerfile | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index 1ba41d2..7bd4b02 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,18 +3,24 @@ FROM python:3.9-slim LABEL org.opencontainers.image.source https://github.com/tomaroberts/nii2dcm +# Setup +COPY . /home/nii2dcm +WORKDIR /home/nii2dcm + # Install system dependencies RUN apt-get update && apt-get install -y \ - bash \ + bash git \ && apt-get clean +# Update base packages RUN pip install --upgrade pip && \ pip install setuptools wheel -RUN pip install --index-url https://test.pypi.org/simple/ \ - --extra-index-url https://pypi.org/simple/ nii2dcm==0.1.2-post.11 +# Install nii2dcm requirements +RUN pip install -r requirements.txt -#RUN pip install nii2dcm +# Build package from source +RUN pip install . # Test nii2dcm install # To see output locally during build process: docker build -t nii2dcm --progress=plain .