From 4ef0e02b0eb394a1e443b2c055c1cdf8303232b3 Mon Sep 17 00:00:00 2001
From: Tamino Huxohl <thuxohl@techfak.uni-bielefeld.de>
Date: Thu, 22 Dec 2022 15:48:50 +0100
Subject: [PATCH] move file conversion into one script

---
 mu_map/file/convert.py            | 98 +++++++++++++++++++++++++++++++
 mu_map/file/dicom_to_interfile.py | 56 ------------------
 mu_map/file/interfile_to_dicom.py | 45 --------------
 3 files changed, 98 insertions(+), 101 deletions(-)
 create mode 100644 mu_map/file/convert.py
 delete mode 100644 mu_map/file/dicom_to_interfile.py
 delete mode 100644 mu_map/file/interfile_to_dicom.py

diff --git a/mu_map/file/convert.py b/mu_map/file/convert.py
new file mode 100644
index 0000000..7e72656
--- /dev/null
+++ b/mu_map/file/convert.py
@@ -0,0 +1,98 @@
+import numpy as np
+
+from mu_map.file.dicom import DICOM
+from mu_map.file.interfile import (
+    Interfile,
+    parse_interfile_header_str,
+    TEMPLATE_HEADER_IMAGE,
+)
+
+"""
+Module for the conversion between the different formats.
+"""
+
+
+def dicom_to_interfile(dcm: DICOM, image: np.ndarray) -> Interfile:
+    """
+    Convert a DICOM image to Interfile format.
+
+    :param dcm: the DICOM image
+    :param image: the image as a numpy array
+    :return: an Interfile as a combination of header and image
+    """
+    header = TEMPLATE_HEADER_IMAGE.replace("{ROWS}", str(dcm.Rows))
+    header = header.replace("{SPACING_X}", f"{dcm.PixelSpacing[0]:.4f}")
+    header = header.replace("{COLUMNS}", str(dcm.Columns))
+    header = header.replace("{SPACING_Y}", f"{dcm.PixelSpacing[1]:.4f}")
+    header = header.replace("{SLICES}", str(dcm.NumberOfSlices))
+    header = header.replace("{SPACING_Z}", f"{dcm.SliceThickness:.4f}")
+    header = header.replace("{OFFSET_X}", str(-0.5 * dcm.Rows * dcm.PixelSpacing[0]))
+    header = header.replace("{OFFSET_Y}", str(-0.5 * dcm.Columns * dcm.PixelSpacing[1]))
+    header = parse_interfile_header_str(header)
+    return Interfile(header, image.astype(np.float32))
+
+
+if __name__ == "__main__":
+    import argparse
+    import os
+
+    import pydicom
+
+    from mu_map.file.dicom import change_uid, load_dcm, update_dcm, EXTENSION_DICOM
+    from mu_map.file.interfile import write_interfile, load_interfile_img
+
+    def main_interfile(args):
+        args.out = args.file if args.out is None else args.out
+
+        dcm, image = load_dcm(args.file)
+        interfile = dicom_to_interfile(dcm, image)
+        write_interfile(args.out, interfile)
+
+    def main_dicom(args):
+        args.out = args.file if args.out is None else args.out
+        args.out = os.path.splitext(args.out)[0]
+        args.out = f"{args.out}{EXTENSION_DICOM}"
+
+        image = load_interfile_img(args.file)
+        reference = pydicom.dcmread(args.reference)
+        dcm = update_dcm(reference.copy(), image)
+        dcm = change_uid(dcm)
+
+        if args.description:
+            dcm.SeriesDescription = args.description
+
+        pydicom.dcmwrite(args.out, dcm)
+
+    parser = argparse.ArgumentParser(
+        description="convert images between different formats",
+        formatter_class=argparse.ArgumentDefaultsHelpFormatter,
+    )
+    parser.add_argument(
+        "file",
+        type=str,
+        help="the file to be converted (a DICOM image or an Interfile header)",
+    )
+    parser.add_argument(
+        "--out",
+        type=str,
+        help="the filename for the output file. If not specified it defaults to the input name with different extensions.",
+    )
+    subparsers = parser.add_subparsers(help="file to convert to")
+
+    parser_dcm = subparsers.add_parser("dicom", help="convert to a DICOM file")
+    parser_dcm.add_argument(
+        "--reference",
+        type=str,
+        required=True,
+        help="reference DICOM file to use for the header",
+    )
+    parser_dcm.add_argument(
+        "--description", type=str, help="update the series description"
+    )
+    parser_dcm.set_defaults(func=main_dicom)
+
+    parser_inter = subparsers.add_parser("interfile", help="convert to an Interfile")
+    parser_inter.set_defaults(func=main_interfile)
+
+    args = parser.parse_args()
+    args.func(args)
diff --git a/mu_map/file/dicom_to_interfile.py b/mu_map/file/dicom_to_interfile.py
deleted file mode 100644
index 98a4c4e..0000000
--- a/mu_map/file/dicom_to_interfile.py
+++ /dev/null
@@ -1,56 +0,0 @@
-from typing import Dict, Tuple
-
-import numpy as np
-from pydicom.dataset import FileDataset as DCMImage
-
-from mu_map.file.interfile import TEMPLATE_HEADER_IMAGE, parse_interfile_header_str
-
-
-def to_interfile(dcm: DCMImage, image: np.ndarray) -> Tuple[Dict[str, str], np.ndarray]:
-    """
-    Convert a DICOM image to INTERFILE format.
-
-    :param dcm: the DICOM image
-    :param image: the image as a numpy array
-    :return: the header and image in INTERFILE format
-    """
-    header = TEMPLATE_HEADER_IMAGE.replace("{ROWS}", str(dcm.Rows))
-    header = header.replace("{SPACING_X}", f"{dcm.PixelSpacing[0]:.4f}")
-    header = header.replace("{COLUMNS}", str(dcm.Columns))
-    header = header.replace("{SPACING_Y}", f"{dcm.PixelSpacing[1]:.4f}")
-    header = header.replace("{SLICES}", str(dcm.NumberOfSlices))
-    header = header.replace("{SPACING_Z}", f"{dcm.SliceThickness:.4f}")
-    header = header.replace("{OFFSET_X}", str(-0.5 * dcm.Rows * dcm.PixelSpacing[0]))
-    header = header.replace("{OFFSET_Y}", str(-0.5 * dcm.Columns * dcm.PixelSpacing[1]))
-    header = parse_interfile_header_str(header)
-    return header, image.astype(np.float32)
-
-
-if __name__ == "__main__":
-    import argparse
-    import os
-
-    from mu_map.file.dicom import load_dcm
-    from mu_map.file.interfile import write_interfile
-
-    parser = argparse.ArgumentParser(
-        description="convert a DICOM image to the INTERFILE format"
-    )
-    parser.add_argument(
-        "--dcm", type=str, required=True, help="the DICOM image to convert"
-    )
-    parser.add_argument(
-        "--out",
-        type=str,
-        help="the filename for the resulting INTERFILE format. If not specified it defaults to the input name with different extensions.",
-    )
-    args = parser.parse_args()
-
-    args.out = args.dcm if args.out is None else args.out
-    args.out = os.path.splitext(args.out)[
-        0
-    ]  # make sure the output file does not have an extension
-
-    dcm, image = load_dcm(args.dcm)
-    header, image = to_interfile(dcm, image)
-    write_interfile(args.out, header, image)
diff --git a/mu_map/file/interfile_to_dicom.py b/mu_map/file/interfile_to_dicom.py
deleted file mode 100644
index 830d49b..0000000
--- a/mu_map/file/interfile_to_dicom.py
+++ /dev/null
@@ -1,45 +0,0 @@
-import argparse
-import os
-
-import numpy as np
-import pydicom
-
-from mu_map.file.dicom import update_dcm, change_uid
-from mu_map.file.interfile import load_interfile_img
-
-parser = argparse.ArgumentParser(
-    description="convert an Interfile image to a DICOM image",
-    formatter_class=argparse.ArgumentDefaultsHelpFormatter,
-)
-parser.add_argument(
-    "--inter", type=str, required=True, help="the Interfile image to be converted"
-)
-parser.add_argument(
-    "--dcm",
-    type=str,
-    required=True,
-    help="a DICOM reference image - data and according fields are exchanged from the Interfile image",
-)
-parser.add_argument(
-    "--out",
-    type=str,
-    help="the output file - defaults to the Interfile input with a dcm extension",
-)
-parser.add_argument(
-    "--description",
-    type=str,
-    help="if provided the series description will be updated",
-)
-args = parser.parse_args()
-
-if args.out is None:
-    args.out = os.path.splitext(args.inter)[0] + ".dcm"
-
-image = load_interfile_img(args.inter)
-
-dcm = pydicom.dcmread(args.dcm)
-dcm = update_dcm(dcm.copy(), image)
-dcm = change_uid(dcm)
-if args.description:
-    dcm.SeriesDescription = args.description
-pydicom.dcmwrite(args.out, dcm)
-- 
GitLab