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