From da865037ac7eaa749b3dc55edc1535cc0922af2c Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Mon, 23 Sep 2024 08:00:21 +0200 Subject: [PATCH 01/20] Apply ruff/Pyflakes rule F401 F401 imported but unused --- .ci/build/apt.py | 1 - .ci/build/build.py | 2 -- src/python/dicomifier/dicom_to_nifti/image.py | 1 - tests/python/bruker/test_grammar.py | 2 -- tests/python/bruker_to_dicom/test_convert.py | 2 -- tests/python/bruker_to_dicom/test_enhanced_mr_image_storage.py | 2 -- tests/python/bruker_to_dicom/test_frame_index_generator.py | 2 -- .../python/dicom_to_nifti/series/test_default_series_finder.py | 1 - .../series/test_siemens_xa_classic_2d_series_finder.py | 1 - tests/python/dicom_to_nifti/test_image.py | 1 - tests/python/dicom_to_nifti/test_meta_data.py | 2 -- tests/python/dicom_to_nifti/test_stacks.py | 1 - tests/python/nifti/test_diffusion.py | 1 - tests/python/test_meta_data.py | 2 -- 14 files changed, 21 deletions(-) diff --git a/.ci/build/apt.py b/.ci/build/apt.py index fd8d0ce8..ff7edc46 100644 --- a/.ci/build/apt.py +++ b/.ci/build/apt.py @@ -1,6 +1,5 @@ import os import subprocess -import sys import tempfile import urllib.request diff --git a/.ci/build/build.py b/.ci/build/build.py index 142c4cba..4a94bc42 100644 --- a/.ci/build/build.py +++ b/.ci/build/build.py @@ -1,6 +1,4 @@ -import multiprocessing import os -import re import subprocess import sys diff --git a/src/python/dicomifier/dicom_to_nifti/image.py b/src/python/dicomifier/dicom_to_nifti/image.py index 7eddcf1b..fb89f59c 100644 --- a/src/python/dicomifier/dicom_to_nifti/image.py +++ b/src/python/dicomifier/dicom_to_nifti/image.py @@ -9,7 +9,6 @@ import math import re -import nibabel import numpy import odil diff --git a/tests/python/bruker/test_grammar.py b/tests/python/bruker/test_grammar.py index e2b275d1..e1374112 100644 --- a/tests/python/bruker/test_grammar.py +++ b/tests/python/bruker/test_grammar.py @@ -1,7 +1,5 @@ import os -import pathlib import tempfile -import textwrap import unittest import dicomifier diff --git a/tests/python/bruker_to_dicom/test_convert.py b/tests/python/bruker_to_dicom/test_convert.py index f998041c..fcc8685e 100644 --- a/tests/python/bruker_to_dicom/test_convert.py +++ b/tests/python/bruker_to_dicom/test_convert.py @@ -1,7 +1,5 @@ import unittest -import numpy - import dicomifier import odil diff --git a/tests/python/bruker_to_dicom/test_enhanced_mr_image_storage.py b/tests/python/bruker_to_dicom/test_enhanced_mr_image_storage.py index 81bd6c29..2fedf043 100644 --- a/tests/python/bruker_to_dicom/test_enhanced_mr_image_storage.py +++ b/tests/python/bruker_to_dicom/test_enhanced_mr_image_storage.py @@ -1,7 +1,5 @@ import unittest -import numpy - from dicomifier.bruker_to_dicom.iods.enhanced_mr_image_storage import merge_shared_groups import dicomifier import odil diff --git a/tests/python/bruker_to_dicom/test_frame_index_generator.py b/tests/python/bruker_to_dicom/test_frame_index_generator.py index a8244e5e..6481c767 100644 --- a/tests/python/bruker_to_dicom/test_frame_index_generator.py +++ b/tests/python/bruker_to_dicom/test_frame_index_generator.py @@ -1,7 +1,5 @@ import unittest -import numpy - import dicomifier class TestFrameIndexGenerator(unittest.TestCase): diff --git a/tests/python/dicom_to_nifti/series/test_default_series_finder.py b/tests/python/dicom_to_nifti/series/test_default_series_finder.py index 11872180..95930240 100644 --- a/tests/python/dicom_to_nifti/series/test_default_series_finder.py +++ b/tests/python/dicom_to_nifti/series/test_default_series_finder.py @@ -1,6 +1,5 @@ import unittest -import numpy import odil import dicomifier diff --git a/tests/python/dicom_to_nifti/series/test_siemens_xa_classic_2d_series_finder.py b/tests/python/dicom_to_nifti/series/test_siemens_xa_classic_2d_series_finder.py index ab9fe65f..c8be3051 100644 --- a/tests/python/dicom_to_nifti/series/test_siemens_xa_classic_2d_series_finder.py +++ b/tests/python/dicom_to_nifti/series/test_siemens_xa_classic_2d_series_finder.py @@ -1,6 +1,5 @@ import unittest -import numpy import odil import dicomifier diff --git a/tests/python/dicom_to_nifti/test_image.py b/tests/python/dicom_to_nifti/test_image.py index f8c18d54..76fac836 100644 --- a/tests/python/dicom_to_nifti/test_image.py +++ b/tests/python/dicom_to_nifti/test_image.py @@ -1,4 +1,3 @@ -import base64 import unittest import numpy diff --git a/tests/python/dicom_to_nifti/test_meta_data.py b/tests/python/dicom_to_nifti/test_meta_data.py index 9dbf1473..977777c4 100644 --- a/tests/python/dicom_to_nifti/test_meta_data.py +++ b/tests/python/dicom_to_nifti/test_meta_data.py @@ -1,8 +1,6 @@ import base64 import unittest -import numpy - import dicomifier import odil diff --git a/tests/python/dicom_to_nifti/test_stacks.py b/tests/python/dicom_to_nifti/test_stacks.py index bc837367..c3205e83 100644 --- a/tests/python/dicom_to_nifti/test_stacks.py +++ b/tests/python/dicom_to_nifti/test_stacks.py @@ -1,6 +1,5 @@ import unittest -import numpy import odil import dicomifier diff --git a/tests/python/nifti/test_diffusion.py b/tests/python/nifti/test_diffusion.py index 52ce3b58..7cbf2a75 100644 --- a/tests/python/nifti/test_diffusion.py +++ b/tests/python/nifti/test_diffusion.py @@ -1,6 +1,5 @@ import io import json -import textwrap import unittest import dicomifier diff --git a/tests/python/test_meta_data.py b/tests/python/test_meta_data.py index 93938af8..75488d9f 100644 --- a/tests/python/test_meta_data.py +++ b/tests/python/test_meta_data.py @@ -1,7 +1,5 @@ import unittest -import numpy - import dicomifier class TestMetaData(unittest.TestCase): From 69c31408b51dec137d329850addf8b80dc86d55d Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Mon, 23 Sep 2024 08:03:14 +0200 Subject: [PATCH 02/20] Apply ruff/Pyflakes rule F841 F841 Local variable is assigned to but never used --- src/python/dicomifier/dicom_to_nifti/meta_data.py | 4 ++-- tests/diff/to_dicom.py | 2 +- tests/diff/to_nifti.py | 6 +++--- tests/python/bruker_to_dicom/test_convert.py | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/python/dicomifier/dicom_to_nifti/meta_data.py b/src/python/dicomifier/dicom_to_nifti/meta_data.py index eb568608..ef21c368 100644 --- a/src/python/dicomifier/dicom_to_nifti/meta_data.py +++ b/src/python/dicomifier/dicom_to_nifti/meta_data.py @@ -84,7 +84,7 @@ def get_meta_data(stack, cache=None): for i, (data_set, frame) in enumerate(stack): try: sop_instance_uid = data_set[odil.registry.SOPInstanceUID][0] - except Exception as e: + except Exception: raise # Fetch non-frame-specific elements from cache for tag, element in cache[sop_instance_uid].items(): @@ -170,7 +170,7 @@ def get_tag_name(tag): try: tag_name = tag.get_name() - except odil.Exception as e: + except odil.Exception: tag_name = str(tag) return tag_name diff --git a/tests/diff/to_dicom.py b/tests/diff/to_dicom.py index 4206c273..c57606a0 100755 --- a/tests/diff/to_dicom.py +++ b/tests/diff/to_dicom.py @@ -45,7 +45,7 @@ def main(): "to-dicom", "--dicomdir"] +arguments +[case_input, case_output]) - except subprocess.CalledProcessError as e: + except subprocess.CalledProcessError: return 1 different |= diff_directories(case_baseline, case_output) diff --git a/tests/diff/to_nifti.py b/tests/diff/to_nifti.py index 54f01909..2e3d47fa 100755 --- a/tests/diff/to_nifti.py +++ b/tests/diff/to_nifti.py @@ -15,7 +15,7 @@ def main(): root = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "data")) - input_ = os.path.join(root, "baseline") + _input = os.path.join(root, "baseline") baseline = os.path.join(root, "baseline") inputs = [ @@ -45,7 +45,7 @@ def main(): # "-v", "debug", "to-nifti", case_input, case_output]) - except subprocess.CalledProcessError as e: + except subprocess.CalledProcessError: return 1 different = different or diff_directories(case_baseline, case_output) @@ -115,7 +115,7 @@ def diff_directories(baseline, test): subprocess.check_output( ["diff", baseline_filename, test_filename], stderr=subprocess.STDOUT) - except subprocess.CalledProcessError as e: + except subprocess.CalledProcessError: different = True print("Differences on {}".format( os.path.join(relative_pathname, filename))) diff --git a/tests/python/bruker_to_dicom/test_convert.py b/tests/python/bruker_to_dicom/test_convert.py index fcc8685e..9a924def 100644 --- a/tests/python/bruker_to_dicom/test_convert.py +++ b/tests/python/bruker_to_dicom/test_convert.py @@ -78,7 +78,7 @@ def test_convert_element_required(self): tag, odil.DataSet(), odil.registry.ImplicitVRLittleEndian) with self.assertRaises(Exception) as context: - val = dicomifier.bruker_to_dicom.convert.convert_element( + _ = dicomifier.bruker_to_dicom.convert.convert_element( bruker_data_set, dicom_data_set, "VisuSubjectName", "PatientName", 1, None, frame_index, generator, vr_finder_function From 3113335cbb9278bfa8c952d2a9719a00fbe8e76d Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Mon, 23 Sep 2024 08:08:53 +0200 Subject: [PATCH 03/20] Apply ruff/pyupgrade rule UP010 UP010 Unnecessary `__future__` import `print_function` for target Python version --- tests/diff/to_nifti.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/diff/to_nifti.py b/tests/diff/to_nifti.py index 2e3d47fa..e6f44cdf 100755 --- a/tests/diff/to_nifti.py +++ b/tests/diff/to_nifti.py @@ -1,5 +1,3 @@ -from __future__ import print_function - import base64 import json import os From 071ca3b946a104f9e3800f7091cb14f60554378a Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Mon, 23 Sep 2024 08:09:39 +0200 Subject: [PATCH 04/20] Apply ruff/pyupgrade rule UP025 UP025 Remove unicode literals from strings --- tests/python/dicom_to_nifti/test_meta_data.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/python/dicom_to_nifti/test_meta_data.py b/tests/python/dicom_to_nifti/test_meta_data.py index 977777c4..2d95bed9 100644 --- a/tests/python/dicom_to_nifti/test_meta_data.py +++ b/tests/python/dicom_to_nifti/test_meta_data.py @@ -56,7 +56,7 @@ def test_convert_element(self): self.assertEqual( dicomifier.dicom_to_nifti.meta_data.convert_element( element, ["ISO_IR 126"]), - [{u"Alphabetic" : u"\x03\x91"}]) + [{"Alphabetic" : "\x03\x91"}]) element = odil.Element( [odil.Value.BinaryItem(b"\01\x02\x03\x04")], odil.VR.OB) From 68233ae0b21c62d3fc31019b1f45565d17b494b8 Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Mon, 23 Sep 2024 08:11:11 +0200 Subject: [PATCH 05/20] Apply ruff/pyupgrade rule UP030 UP030 Use implicit references for positional format fields --- src/python/dicomifier/dicom_to_nifti/siemens.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/python/dicomifier/dicom_to_nifti/siemens.py b/src/python/dicomifier/dicom_to_nifti/siemens.py index 0861c504..0262d6d6 100644 --- a/src/python/dicomifier/dicom_to_nifti/siemens.py +++ b/src/python/dicomifier/dicom_to_nifti/siemens.py @@ -138,8 +138,8 @@ def parse_item(csa, start): length = struct.unpack(format, csa[start:start+header_size]) format = ("<" # Little endian - "{0}s" # Content - "{1}s" # Padding (?) + "{}s" # Content + "{}s" # Padding (?) ).format(length[1], (4-length[1]%4)%4) content_size = struct.calcsize(format) content, padding = struct.unpack( From 557fd9a0badfeb00676e7c4a0c4b4f5432b7d744 Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Mon, 23 Sep 2024 08:16:34 +0200 Subject: [PATCH 06/20] Apply ruff/pyupgrade rule UP031 UP031 Use format specifiers instead of percent format --- .../dicomifier/dicom_to_nifti/series/__init__.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/python/dicomifier/dicom_to_nifti/series/__init__.py b/src/python/dicomifier/dicom_to_nifti/series/__init__.py index ef19577b..350b9f00 100644 --- a/src/python/dicomifier/dicom_to_nifti/series/__init__.py +++ b/src/python/dicomifier/dicom_to_nifti/series/__init__.py @@ -21,8 +21,8 @@ def split_series(files): """ logger.info( - "Splitting %d DICOM file%s in series", - len(files), "s" if len(files) > 1 else "") + "Splitting {} DICOM file{} in series".format( + len(files), "s" if len(files) > 1 else "")) series = {} for file_ in files: @@ -31,7 +31,7 @@ def split_series(files): file_, halt_condition=lambda x: x>odil.registry.SeriesInstanceUID) except odil.Exception as e: - logger.warning("Could not read %s: %s" % (file_, e)) + logger.warning(f"Could not read {file_}: {e}") continue uncompressed_ts = [ @@ -43,7 +43,7 @@ def split_series(files): ]] if header[odil.registry.TransferSyntaxUID][0] not in uncompressed_ts: logger.warning( - "Could not read %s: compressed transfer syntax", file_) + f"Could not read {file_}: compressed transfer syntax") continue series_instance_uid = None @@ -55,13 +55,13 @@ def split_series(files): series_instance_uid = finder(data_set) except Exception as e: logger.warning( - "Could not run %s: %s" % (finder_class.__name__, e)) + f"Could not run {finder_class.__name__}: {e}") continue if series_instance_uid is not None: break if series_instance_uid is None: - logger.warning("Could not find a series for %s", file_) + logger.warning(f"Could not find a series for {file_}") continue series.setdefault(finder, []).append(file_) From f6c2a5158ad50df889573a2ee3a28a2d7a361290 Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Mon, 23 Sep 2024 08:32:18 +0200 Subject: [PATCH 07/20] Apply ruff/pyupgrade rule UP032 UP032 Use f-string instead of `format` call --- .ci/build/apt.py | 6 +++--- .ci/build/build.py | 4 ++-- .../dicomifier/bruker_to_dicom/io/flat_dicom_writer.py | 3 ++- .../dicomifier/bruker_to_dicom/io/nested_dicom_writer.py | 3 ++- src/python/dicomifier/dicom_to_nifti/convert.py | 6 +----- src/python/dicomifier/dicom_to_nifti/siemens.py | 8 ++++---- tests/diff/to_dicom.py | 4 ++-- tests/diff/to_nifti.py | 7 +++---- 8 files changed, 19 insertions(+), 22 deletions(-) diff --git a/.ci/build/apt.py b/.ci/build/apt.py index ff7edc46..000b13f7 100644 --- a/.ci/build/apt.py +++ b/.ci/build/apt.py @@ -13,16 +13,16 @@ repository = "https://iris-packages.s3.unistra.fr" try: - urllib.request.urlopen("{}/apt/dists/{}/Release".format(repository, codename)) + urllib.request.urlopen(f"{repository}/apt/dists/{codename}/Release") except urllib.request.HTTPError: pass else: with tempfile.NamedTemporaryFile() as fd: - fd.write(urllib.request.urlopen("{}/gpg.key".format(repository)).read()) + fd.write(urllib.request.urlopen(f"{repository}/gpg.key").read()) fd.flush() subprocess.check_call(["apt-key", "add", fd.name]) subprocess.check_call([ - "add-apt-repository", "deb {}/apt {} main".format(repository, codename)]) + "add-apt-repository", f"deb {repository}/apt {codename} main"]) subprocess.check_call(["apt-get", "update"]) subprocess.check_call([ diff --git a/.ci/build/build.py b/.ci/build/build.py index 4a94bc42..796aaf79 100644 --- a/.ci/build/build.py +++ b/.ci/build/build.py @@ -16,8 +16,8 @@ [ "cmake", "-G", "Ninja", - "-DPython_EXECUTABLE={}".format(sys.executable), - "-DCMAKE_INSTALL_PREFIX={}".format(install_dir), + f"-DPython_EXECUTABLE={sys.executable}", + f"-DCMAKE_INSTALL_PREFIX={install_dir}", workspace], cwd=build_dir) diff --git a/src/python/dicomifier/bruker_to_dicom/io/flat_dicom_writer.py b/src/python/dicomifier/bruker_to_dicom/io/flat_dicom_writer.py index a7ea6c80..2ee11319 100644 --- a/src/python/dicomifier/bruker_to_dicom/io/flat_dicom_writer.py +++ b/src/python/dicomifier/bruker_to_dicom/io/flat_dicom_writer.py @@ -26,7 +26,8 @@ def __call__(self, data_set): os.makedirs(self.root) if self.iso_9660: - filename = "{:08d}.dcm".format(1+len(self.files)) + count = 1 + len(self.files) + filename = f"{count:08}.dcm" else: filename = data_set[odil.registry.SOPInstanceUID][0].decode() diff --git a/src/python/dicomifier/bruker_to_dicom/io/nested_dicom_writer.py b/src/python/dicomifier/bruker_to_dicom/io/nested_dicom_writer.py index 66f03519..eb1350ef 100644 --- a/src/python/dicomifier/bruker_to_dicom/io/nested_dicom_writer.py +++ b/src/python/dicomifier/bruker_to_dicom/io/nested_dicom_writer.py @@ -30,7 +30,8 @@ def __call__(self, data_set): self._counts.setdefault(directory, 0) if self.iso_9660: - filename = "IM{:06d}".format(1+self._counts[directory]) + count = 1 + self._counts[directory] + filename = f"IM{count:06}" else: filename = data_set[odil.registry.SOPInstanceUID][0].decode() diff --git a/src/python/dicomifier/dicom_to_nifti/convert.py b/src/python/dicomifier/dicom_to_nifti/convert.py index 93da1ac4..b4b9677f 100644 --- a/src/python/dicomifier/dicom_to_nifti/convert.py +++ b/src/python/dicomifier/dicom_to_nifti/convert.py @@ -215,11 +215,7 @@ def convert_series_data_sets(data_sets, dtype=None, extra_splitters=None): # Update progress information if len(stacks) > 1: - stack_info = "{}/{}".format(1 + stack_index, len(stacks)) - else: - stack_info = "" - if stack_info: - logger.debug("Converting stack %s", stack_info) + logger.debug(f"Converting stack {1 + stack_index}/{len(stacks)}") sort(key, stack) nifti_meta_data = meta_data.get_meta_data(stack, meta_data_cache) diff --git a/src/python/dicomifier/dicom_to_nifti/siemens.py b/src/python/dicomifier/dicom_to_nifti/siemens.py index 0262d6d6..62c6492d 100644 --- a/src/python/dicomifier/dicom_to_nifti/siemens.py +++ b/src/python/dicomifier/dicom_to_nifti/siemens.py @@ -138,9 +138,9 @@ def parse_item(csa, start): length = struct.unpack(format, csa[start:start+header_size]) format = ("<" # Little endian - "{}s" # Content - "{}s" # Padding (?) - ).format(length[1], (4-length[1]%4)%4) + f"{length[1]}s" # Content + f"{(4-length[1]%4)%4}s" # Padding (?) + ) content_size = struct.calcsize(format) content, padding = struct.unpack( format, csa[start+header_size:start+header_size+content_size]) @@ -206,7 +206,7 @@ def value_parser(type_, value): element) is_array, type_, name, index = match.groups() - full_name = "{}{}{}".format(is_array.decode(), type_.decode(), name.decode()) + full_name = f"{is_array.decode()}{type_.decode()}{name.decode()}" is_array = (is_array == b"a") if index: diff --git a/tests/diff/to_dicom.py b/tests/diff/to_dicom.py index c57606a0..3ed62b32 100755 --- a/tests/diff/to_dicom.py +++ b/tests/diff/to_dicom.py @@ -92,8 +92,8 @@ def diff_directories(baseline, test): for filename in filenames: if not os.path.isfile(os.path.join(baseline_pathname, filename)): different = True - print("{} missing in baseline".format( - os.path.join(relative_pathname, filename))) + relative_filename = os.path.join(relative_pathname, filename) + print(f"{relative_filename} missing in baseline") return different diff --git a/tests/diff/to_nifti.py b/tests/diff/to_nifti.py index e6f44cdf..0eba6a11 100755 --- a/tests/diff/to_nifti.py +++ b/tests/diff/to_nifti.py @@ -115,8 +115,7 @@ def diff_directories(baseline, test): stderr=subprocess.STDOUT) except subprocess.CalledProcessError: different = True - print("Differences on {}".format( - os.path.join(relative_pathname, filename))) + print(f"Differences on {relative_filename}") # Walk the test to find files missing in baseline (the difference between # files has already been tested). @@ -126,8 +125,8 @@ def diff_directories(baseline, test): for filename in filenames: if not os.path.isfile(os.path.join(baseline_pathname, filename)): different = True - print("{} missing in baseline".format( - os.path.join(relative_pathname, filename))) + relative_filename = os.path.join(relative_pathname, filename) + print(f"{relative_filename} missing in baseline") return different From 4baf29585839731d7bc43985cb181be86cb95e7a Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Mon, 23 Sep 2024 08:36:38 +0200 Subject: [PATCH 08/20] Apply ruff/Perflint rule PERF401 PERF401 Use a list comprehension to create a transformed list --- src/python/dicomifier/dicom_to_nifti/io.py | 16 +++++++--------- tests/diff/to_nifti.py | 13 +++++++------ 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/python/dicomifier/dicom_to_nifti/io.py b/src/python/dicomifier/dicom_to_nifti/io.py index 6e9d3c14..942846d5 100644 --- a/src/python/dicomifier/dicom_to_nifti/io.py +++ b/src/python/dicomifier/dicom_to_nifti/io.py @@ -62,16 +62,14 @@ def get_dicomdir_files(path): """ Return the list of files indexed in a DICOMDIR file. """ - dicom_files = [] dicomdir = odil.Reader.read_file(path)[1] - for record in dicomdir[odil.registry.DirectoryRecordSequence]: - if record[odil.registry.DirectoryRecordType][0] == b"IMAGE": - dicom_files.append( - os.path.join( - os.path.dirname(path), - *[x.decode() for x in record[odil.registry.ReferencedFileID]])) - - return dicom_files + return [ + os.path.join( + os.path.dirname(path), + *[x.decode() for x in record[odil.registry.ReferencedFileID]]) + for record in dicomdir[odil.registry.DirectoryRecordSequence] + if record[odil.registry.DirectoryRecordType][0] == b"IMAGE" + ] def write_nifti(nifti_data, destination, zip, series_directory=None): """ Write the NIfTI image and meta-data in the given destination. diff --git a/tests/diff/to_nifti.py b/tests/diff/to_nifti.py index 0eba6a11..73ad20e9 100755 --- a/tests/diff/to_nifti.py +++ b/tests/diff/to_nifti.py @@ -24,12 +24,13 @@ def main(): "lb_140721.Bx1" ] - tests = [] - for path in inputs: - for suffix in ["", ".multi"]: - tests.append([ - os.path.join(baseline, f"{path}.dcm{suffix}"), - os.path.join(baseline, f"{path}.nii{suffix}")]) + tests = [ + [ + os.path.join(baseline, f"{path}.dcm{suffix}"), + os.path.join(baseline, f"{path}.nii{suffix}")] + for path in inputs + for suffix in ("", ".multi") + ] different = False for case_input, case_baseline in tests: From 262056c3324763a2716312a937d4984321c3c7fa Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Mon, 23 Sep 2024 08:39:20 +0200 Subject: [PATCH 09/20] Apply ruff/bugbear rule B904 B904 Within an `except` clause, raise exceptions with `raise ... from err` or `raise ... from None` to distinguish them from errors in exception handling --- src/python/dicomifier/commands/search.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/python/dicomifier/commands/search.py b/src/python/dicomifier/commands/search.py index 929a0c02..5e60953c 100644 --- a/src/python/dicomifier/commands/search.py +++ b/src/python/dicomifier/commands/search.py @@ -44,9 +44,9 @@ def __init__(self, argument): else: try: tag = int(items[0], 16) - except ValueError: + except ValueError as e: raise argparse.ArgumentTypeError( - f"Invalid DICOM tag '{items[0]}'") + f"Invalid DICOM tag '{items[0]}'") from e else: self.tag = odil.Tag(tag) From 1ab77bde8fddd999d6eae2de8f3c87962feb39fe Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Mon, 23 Sep 2024 08:42:12 +0200 Subject: [PATCH 10/20] Apply ruff/flake8-simplify rule SIM114 SIM114 Combine `if` branches using logical `or` operator --- src/python/dicomifier/dicom_to_nifti/meta_data.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/python/dicomifier/dicom_to_nifti/meta_data.py b/src/python/dicomifier/dicom_to_nifti/meta_data.py index ef21c368..e8d061be 100644 --- a/src/python/dicomifier/dicom_to_nifti/meta_data.py +++ b/src/python/dicomifier/dicom_to_nifti/meta_data.py @@ -182,9 +182,7 @@ def convert_element(element, specific_character_set): result = None # element can be None because a get is called above - if element is None: - result = None - elif element.empty(): + if element is None or element.empty(): result = None elif element.is_int() or element.is_real(): result = list(element) From f38da39dea7a9d2d5bd092a93aec0c04d20001c1 Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Mon, 23 Sep 2024 08:44:00 +0200 Subject: [PATCH 11/20] Apply ruff/flake8-simplify rule SIM118 SIM118 Use `key in dict` instead of `key in dict.keys()` --- src/python/dicomifier/dicom_to_nifti/stacks.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/python/dicomifier/dicom_to_nifti/stacks.py b/src/python/dicomifier/dicom_to_nifti/stacks.py index a4a37a81..0b84ecec 100644 --- a/src/python/dicomifier/dicom_to_nifti/stacks.py +++ b/src/python/dicomifier/dicom_to_nifti/stacks.py @@ -91,10 +91,10 @@ def build_selector( # Normalize the keys so that all stacks have the same key fields key_items = set() - for key in stacks.keys(): + for key in stacks: key_items.update(x[0] for x in key) normalized_keys = {} - for key in stacks.keys(): + for key in stacks: normalized_keys[key] = list(key) for key_item in key_items: if key_item not in [x[0] for x in key]: From ede0174c4c688f1398a46865967d25677a07d67b Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Mon, 23 Sep 2024 08:54:26 +0200 Subject: [PATCH 12/20] Apply ruff/flake8-simplify rule C416 C416 Unnecessary `list` comprehension (rewrite using `list()`) --- tests/python/bruker/test_dataset.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/python/bruker/test_dataset.py b/tests/python/bruker/test_dataset.py index 59b806a1..e5dfb054 100644 --- a/tests/python/bruker/test_dataset.py +++ b/tests/python/bruker/test_dataset.py @@ -36,7 +36,7 @@ def test_load(self): dataset.load(self.path) fields = [[name, value] for name, value in dataset.items()] - self.assertEqual([x[0] for x in fields], [x for x in dataset]) + self.assertEqual([x[0] for x in fields], list(dataset)) expected_fields = [ ["FieldName", [], ["1 Field Value"]], From dd756f8e110135f95dcea6735d6736b98a9d7250 Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Mon, 23 Sep 2024 08:55:31 +0200 Subject: [PATCH 13/20] Apply ruff/flake8-simplify rule C419 C419 Unnecessary list comprehension --- tests/python/test_meta_data.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/python/test_meta_data.py b/tests/python/test_meta_data.py index 75488d9f..df5dc023 100644 --- a/tests/python/test_meta_data.py +++ b/tests/python/test_meta_data.py @@ -14,7 +14,7 @@ def test_expand_0d(self): value = meta_data.expand("ImageType", (2, 3)) self.assertEqual(value.shape, (2, 3, 2)) self.assertTrue( - all([all(x == ["ORIGINAL", "PRIMARY"]) for x in value.reshape(-1, 2)]) + all(all(x == ["ORIGINAL", "PRIMARY"]) for x in value.reshape(-1, 2)) ) def test_expand_1d(self): From ccef9098a2b669c3c0a2e763588d867bb6f38a13 Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Mon, 23 Sep 2024 08:58:29 +0200 Subject: [PATCH 14/20] Apply ruff/flake8-pie rule PIE808 PIE808 Unnecessary `start` argument in `range` --- src/python/dicomifier/dicom_to_nifti/stacks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/python/dicomifier/dicom_to_nifti/stacks.py b/src/python/dicomifier/dicom_to_nifti/stacks.py index 0b84ecec..9a23fc91 100644 --- a/src/python/dicomifier/dicom_to_nifti/stacks.py +++ b/src/python/dicomifier/dicom_to_nifti/stacks.py @@ -559,7 +559,7 @@ def _find_private_creator(data_set, private_creator, group): tag = odil.Tag(group, 0x0000) private_group = None - for element in range(0, 256): + for element in range(256): tag.element = element # Get the content of the potential private creator. It may be stored as From 1657a92b0ad99bba009aa4219f9364ae11b13a18 Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Mon, 23 Sep 2024 08:59:24 +0200 Subject: [PATCH 15/20] Apply ruff/flake8-pie rule PIE810 PIE810 Call `endswith` once with a `tuple` --- tests/diff/to_nifti.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/diff/to_nifti.py b/tests/diff/to_nifti.py index 73ad20e9..2c932f73 100755 --- a/tests/diff/to_nifti.py +++ b/tests/diff/to_nifti.py @@ -93,7 +93,7 @@ def diff_directories(baseline, test): different = True print(f"Encapsulated document differences in {relative_filename}") diff.print_differences(differences, 1) - elif filename.endswith(".nii") or filename.endswith(".nii.gz"): + elif filename.endswith((".nii", ".nii.gz")): images = [ nibabel.load(x) for x in [baseline_filename, test_filename]] From d9ce7162db62c64816627553151d568ecc0c1038 Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Mon, 23 Sep 2024 09:00:35 +0200 Subject: [PATCH 16/20] Apply ruff/flake8-quotes rule Q000 Q000 Single quotes found but double quotes preferred --- src/python/dicomifier/bruker_to_dicom/modules/image.py | 2 +- src/python/dicomifier/dicom_to_nifti/convert.py | 2 +- src/python/dicomifier/dicom_to_nifti/siemens.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/python/dicomifier/bruker_to_dicom/modules/image.py b/src/python/dicomifier/bruker_to_dicom/modules/image.py index e5e35401..69e7d20e 100644 --- a/src/python/dicomifier/bruker_to_dicom/modules/image.py +++ b/src/python/dicomifier/bruker_to_dicom/modules/image.py @@ -108,7 +108,7 @@ def get_frame_index(generator, frame_index): contribution = [ [fg[1], frame_index[i]] for i, fg in enumerate(generator.frame_groups) - if fg[1] != 'FG_SLICE'] + if fg[1] != "FG_SLICE"] return odil.DataSet( PurposeOfReferenceCodeSequence=[odil.DataSet( diff --git a/src/python/dicomifier/dicom_to_nifti/convert.py b/src/python/dicomifier/dicom_to_nifti/convert.py index b4b9677f..01fc12ca 100644 --- a/src/python/dicomifier/dicom_to_nifti/convert.py +++ b/src/python/dicomifier/dicom_to_nifti/convert.py @@ -126,7 +126,7 @@ def __init__(self, data_set): self.prefix = "{}: ".format(" / ".join(elements)) except Exception as e: - logger.debug("Series context configuration error: \"%s\"", e) + logger.debug('Series context configuration error: "%s"', e) self.prefix = "" def filter(self, record): diff --git a/src/python/dicomifier/dicom_to_nifti/siemens.py b/src/python/dicomifier/dicom_to_nifti/siemens.py index 62c6492d..826d33f3 100644 --- a/src/python/dicomifier/dicom_to_nifti/siemens.py +++ b/src/python/dicomifier/dicom_to_nifti/siemens.py @@ -48,7 +48,7 @@ def parse_value(value, name): if value.startswith(b"0x"): return int(value.split()[0], 16) - elif value.startswith(b"\""): + elif value.startswith(b'"'): return re.findall(br'""(.*)""', value)[0].decode() else: int_match = re.match(br"^[+-]?\d+$", value) From fa28e7d742c4f4879962bcf4e46a506dfb5c029c Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Mon, 23 Sep 2024 09:01:17 +0200 Subject: [PATCH 17/20] Apply ruff/flake8-raise rule RSE102 RSE102 Unnecessary parentheses on raised exception --- tests/python/test_exception.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/python/test_exception.py b/tests/python/test_exception.py index de69cd37..fbb86cdc 100644 --- a/tests/python/test_exception.py +++ b/tests/python/test_exception.py @@ -5,11 +5,11 @@ class TestException(unittest.TestCase): def test_python_generic(self): with self.assertRaises(Exception): - raise dicomifier.Exception() + raise dicomifier.Exception def test_python_specific(self): with self.assertRaises(dicomifier.Exception): - raise dicomifier.Exception() + raise dicomifier.Exception def test_cpp_generic(self): with self.assertRaises(Exception): From 77e5e7dbd9acfa9a8927e42f965bfb44cfd58260 Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Mon, 23 Sep 2024 09:03:34 +0200 Subject: [PATCH 18/20] Apply ruff/Pylint rule PLR5501 PLR5501 Use `elif` instead of `else` then `if`, to reduce indentation --- tests/diff/to_nifti.py | 89 +++++++++++++++++++++--------------------- 1 file changed, 44 insertions(+), 45 deletions(-) diff --git a/tests/diff/to_nifti.py b/tests/diff/to_nifti.py index 2c932f73..ee3b30b8 100755 --- a/tests/diff/to_nifti.py +++ b/tests/diff/to_nifti.py @@ -69,54 +69,53 @@ def diff_directories(baseline, test): if not os.path.isfile(os.path.join(test_pathname, filename)): print(f"{relative_filename} missing in test") - else: - if filename.endswith(".json"): - meta_data = [ - json.load(open(baseline_filename)), - json.load(open(test_filename))] - # Process EncapsulatedDocument separately - differences = diff.diff( - *meta_data, exclusions=["EncapsulatedDocument"]) - if differences: - different = True - print(f"Meta-data differences in {relative_filename}") - diff.print_differences(differences, 1) - - encapsulated_documents = [ - [ - json.loads(base64.b64decode(x).strip(b"\x00").decode()) - for x in m.get("EncapsulatedDocument", [])] - for m in meta_data] - for documents in zip(*encapsulated_documents): - differences = diff.diff(*documents) - if differences: - different = True - print(f"Encapsulated document differences in {relative_filename}") - diff.print_differences(differences, 1) - elif filename.endswith((".nii", ".nii.gz")): - images = [ - nibabel.load(x) - for x in [baseline_filename, test_filename]] - meta_data = [ - [x.affine.shape, x.affine.ravel().tolist(), x.shape] - for x in images] - differences = diff.diff(*meta_data) + elif filename.endswith(".json"): + meta_data = [ + json.load(open(baseline_filename)), + json.load(open(test_filename))] + # Process EncapsulatedDocument separately + differences = diff.diff( + *meta_data, exclusions=["EncapsulatedDocument"]) + if differences: + different = True + print(f"Meta-data differences in {relative_filename}") + diff.print_differences(differences, 1) + + encapsulated_documents = [ + [ + json.loads(base64.b64decode(x).strip(b"\x00").decode()) + for x in m.get("EncapsulatedDocument", [])] + for m in meta_data] + for documents in zip(*encapsulated_documents): + differences = diff.diff(*documents) if differences: different = True - print(f"Geometry differences in {relative_filename}") + print(f"Encapsulated document differences in {relative_filename}") diff.print_differences(differences, 1) - pixel_data = [numpy.asanyarray(x.dataobj) for x in images] - if not numpy.allclose(*pixel_data): - different = True - print(f"Pixel data differences in {relative_filename}") - else: - try: - subprocess.check_output( - ["diff", baseline_filename, test_filename], - stderr=subprocess.STDOUT) - except subprocess.CalledProcessError: - different = True - print(f"Differences on {relative_filename}") + elif filename.endswith((".nii", ".nii.gz")): + images = [ + nibabel.load(x) + for x in [baseline_filename, test_filename]] + meta_data = [ + [x.affine.shape, x.affine.ravel().tolist(), x.shape] + for x in images] + differences = diff.diff(*meta_data) + if differences: + different = True + print(f"Geometry differences in {relative_filename}") + diff.print_differences(differences, 1) + pixel_data = [numpy.asanyarray(x.dataobj) for x in images] + if not numpy.allclose(*pixel_data): + different = True + print(f"Pixel data differences in {relative_filename}") + else: + try: + subprocess.check_output( + ["diff", baseline_filename, test_filename], + stderr=subprocess.STDOUT) + except subprocess.CalledProcessError: + different = True + print(f"Differences on {relative_filename}") # Walk the test to find files missing in baseline (the difference between # files has already been tested). From 36f548193e30702b23d9d5760162045f886ab4a2 Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Mon, 23 Sep 2024 09:06:23 +0200 Subject: [PATCH 19/20] Apply ruff rule RUF019 RUF019 Unnecessary key check before dictionary access --- src/python/dicomifier/dicom_to_nifti/io.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/python/dicomifier/dicom_to_nifti/io.py b/src/python/dicomifier/dicom_to_nifti/io.py index 942846d5..b8e43403 100644 --- a/src/python/dicomifier/dicom_to_nifti/io.py +++ b/src/python/dicomifier/dicom_to_nifti/io.py @@ -144,12 +144,12 @@ def get_first_item(item): # Patient directory: or or . patient_directory = None - if "PatientName" in meta_data and meta_data["PatientName"]: + if meta_data.get("PatientName"): patient_directory = get_first_item( meta_data["PatientName"])["Alphabetic"] - elif "PatientID" in meta_data and meta_data["PatientID"]: + elif meta_data.get("PatientID"): patient_directory = meta_data["PatientID"][0] - elif "StudyInstanceUID" in meta_data and meta_data["StudyInstanceUID"]: + elif meta_data.get("StudyInstanceUID"): patient_directory = meta_data["StudyInstanceUID"][0] else: raise Exception("Cannot determine patient directory") @@ -157,15 +157,15 @@ def get_first_item(item): # Study directory: _, both parts are # optional. If both tags are missing or empty, raise an exception study_directory = [] - if "StudyID" in meta_data and meta_data["StudyID"]: + if meta_data.get("StudyID"): study_directory.append( numpy.ravel([x for x in meta_data["StudyID"] if x])[0]) - if "StudyDescription" in meta_data and meta_data["StudyDescription"]: + if meta_data.get("StudyDescription"): study_directory.append( numpy.ravel([x for x in meta_data["StudyDescription"] if x])[0]) if not study_directory: - if "StudyInstanceUID" in meta_data and meta_data["StudyInstanceUID"]: + if meta_data.get("StudyInstanceUID"): study_directory = [meta_data["StudyInstanceUID"][0]] else: raise Exception("Cannot determine study directory") @@ -175,18 +175,18 @@ def get_first_item(item): # Study directory: _, both parts are # optional. If both tags are missing or empty, raise an exception series_directory = [] - if "SeriesNumber" in meta_data and meta_data["SeriesNumber"]: + if meta_data.get("SeriesNumber"): series_directory.append(str(get_series_number(meta_data))) - if "SeriesDescription" in meta_data and meta_data["SeriesDescription"]: + if meta_data.get("SeriesDescription"): series_directory.append( numpy.ravel( [x for x in meta_data["SeriesDescription"] if x])[0]) - elif "ProtocolName" in meta_data and meta_data["ProtocolName"]: + elif meta_data.get("ProtocolName"): series_directory.append( numpy.ravel([x for x in meta_data["ProtocolName"] if x])[0]) if not series_directory: - if "SeriesInstanceUID" in meta_data and meta_data["SeriesInstanceUID"]: + if meta_data.get("SeriesInstanceUID"): series_directory = [meta_data["SeriesInstanceUID"][0]] else: raise Exception("Cannot determine series directory") From 14ced55c54804d64a6c6f30a4a8cdd55f077367b Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Sun, 7 Dec 2025 11:08:24 +0100 Subject: [PATCH 20/20] Apply ruff rule RUF046 RUF046 Value being cast to `int` is already an integer --- src/python/dicomifier/dicom_to_nifti/image.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/python/dicomifier/dicom_to_nifti/image.py b/src/python/dicomifier/dicom_to_nifti/image.py index fb89f59c..253bdddf 100644 --- a/src/python/dicomifier/dicom_to_nifti/image.py +++ b/src/python/dicomifier/dicom_to_nifti/image.py @@ -39,7 +39,7 @@ def get_slice_image(data_set, shape, cache=None): siemens_data = siemens.parse_csa(item.get_memory_view().tobytes()) number_of_tiles = siemens_data["NumberOfImagesInMosaic"][0] - tiles_per_line = int(math.ceil(math.sqrt(number_of_tiles))) + tiles_per_line = math.ceil(math.sqrt(number_of_tiles)) # Re-arrange array so that tiles are contiguous array = array.reshape( @@ -106,7 +106,7 @@ def get_shape(stack): siemens_data = siemens.parse_csa(item.get_memory_view().tobytes()) number_of_tiles = siemens_data["NumberOfImagesInMosaic"][0] - tiles_per_line = int(math.ceil(math.sqrt(number_of_tiles))) + tiles_per_line = math.ceil(math.sqrt(number_of_tiles)) rows = data_set[odil.registry.Rows][0] // tiles_per_line cols = data_set[odil.registry.Columns][0] // tiles_per_line @@ -310,7 +310,7 @@ def get_geometry(stack): siemens_data = siemens.parse_csa(item.get_memory_view().tobytes()) number_of_tiles = siemens_data["NumberOfImagesInMosaic"][0] - tiles_per_line = int(math.ceil(math.sqrt(number_of_tiles))) + tiles_per_line = math.ceil(math.sqrt(number_of_tiles)) # Get the origin of the tiles (i.e. origin of the first tile), cf. # http://nipy.org/nibabel/dicom/dicom_mosaic.html