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