From b79279b1c8264c8e01c36d7e12ee3e0f84b5261e Mon Sep 17 00:00:00 2001
From: Tamino Huxohl <thuxohl@techfak.uni-bielefeld.de>
Date: Thu, 17 Nov 2022 13:46:39 +0100
Subject: [PATCH] enhance interfile utils

---
 mu_map/file/interfile.py | 60 ++++++++++++++--------------------------
 1 file changed, 21 insertions(+), 39 deletions(-)

diff --git a/mu_map/file/interfile.py b/mu_map/file/interfile.py
index ea28503..c879af1 100644
--- a/mu_map/file/interfile.py
+++ b/mu_map/file/interfile.py
@@ -55,39 +55,6 @@ number of time frames := 1
 !END OF INTERFILE :=
 """
 
-HEADER_TEMPLATE_PROJ = """
-!INTERFILE  :=
-!imaging modality := nucmed
-!version of keys := 3.3
-name of data file := {DATA_FILE}
-;data offset in bytes := 0
-
-!GENERAL IMAGE DATA :=
-!type of data := Tomographic
-imagedata byte order := LITTLEENDIAN
-!number format := float
-!number of bytes per pixel := 4
-
-!SPECT STUDY (General) := 
-;number of dimensions := 2
-;matrix axis label [2] := axial coordinate
-!matrix size [2] := {ROWS}
-!scaling factor (mm/pixel) [2] := {SPACING_X}
-;matrix axis label [1] := bin coordinate
-!matrix size [1] := {COLUMNS}
-!scaling factor (mm/pixel) [1] := {SPACING_Y}
-!number of projections := {N_PROJECTIONS}
-!extent of rotation := {ROTATION}
-!process status := acquired
-
-!SPECT STUDY (acquired data) :=
-!direction of rotation := CW
-start angle := {START_ANGLE}
-orbit := circular
-radius := {RADIUS}
-
-!END OF INTERFILE :=
-"""
 
 
 def type_by_format(number_format: str, bytes_per_pixel: int) -> type:
@@ -105,23 +72,33 @@ def type_by_format(number_format: str, bytes_per_pixel: int) -> type:
     raise ValueError("Unknown mapping from format {number_format} with {bytes_per_pixel} bytes to numpy type")
 
 
-def parse_interfile_header(filename: str) -> Dict[str, str]:
+def parse_interfile_header_str(header: str) -> Dict[str, str]:
     """
     Parse an INTERFILE header into a dict.
     This is done by splitting non-empty lines in the INTERFILE header by ":=".
 
-    :param filename: the filename of the INTERFILE header
+    :param header: the text of an INTERFILE header
     :return: a dictionary of value in the header
     """
-    with open(filename, mode="r") as f:
-        lines = f.readlines()
-
+    lines = header.strip().split("\n")
     items = map(lambda line: line.split(":="), lines)
     items = filter(lambda item: len(item) == 2, items)
     items = map(lambda item: [item[0].strip(), item[1].strip()], items)
     return dict(items)
 
 
+def parse_interfile_header(filename: str) -> Dict[str, str]:
+    """
+    Parse an INTERFILE header into a dict.
+    This is done by splitting non-empty lines in the INTERFILE header by ":=".
+
+    :param filename: the filename of the INTERFILE header
+    :return: a dictionary of value in the header
+    """
+    with open(filename, mode="r") as f:
+        return parse_interfile_header_str(f.read())
+
+
 def load_interfile(filename: str) -> Tuple[Dict[str, str], np.ndarray]:
     """
     Load an INTERFILE header and its image as a numpy array.
@@ -164,7 +141,10 @@ def write_interfile(filename: str, header: Dict[str, str], image: np.ndarray):
 
     header[KEY_DATA_FILE] = os.path.basename(filename_data)
     header[KEY_DIM_3] = str(image.shape[0])
+    header[KEY_DIM_2] = str(image.shape[1])
+    header[KEY_DIM_1] = str(image.shape[2])
 
+    image = image.astype(np.float32)
 
     header_str = map(lambda item: f"{item[0]} := {item[1]}", header.items())
     header_str = "\n".join(header_str)
@@ -181,7 +161,7 @@ if __name__ == "__main__":
     parser = argparse.ArgumentParser(description="Modify an interfile image")
     parser.add_argument("--interfile", type=str, required=True, help="the interfile input")
     parser.add_argument("--out", type=str, help="the interfile output - if not set the input file will be overwritte")
-    parser.add_argument("--cmd", choices=["fill", "crop", "pad"], help="the modification to perform")
+    parser.add_argument("--cmd", choices=["fill", "crop", "pad", "flip"], help="the modification to perform")
     parser.add_argument("--param", type=int, required=True, help="the parameters for the modification [fill: value, crop & pad: target size of z dimension]")
     args = parser.parse_args()
     args.out = args.interfile if args.out is None else args.out
@@ -210,6 +190,8 @@ if __name__ == "__main__":
         crop_lower = center - math.floor(diff)
         crop_upper = center + math.ceil(diff)
         image = image[crop_lower:crop_upper]
+    if args.cmd == "flip":
+        image = image[:, :, ::-1]
 
     write_interfile(args.out, header, image)
 
-- 
GitLab