From ef13af551f24a4cbd4f7906f6d16b5cc0f967059 Mon Sep 17 00:00:00 2001 From: neuronflow Date: Sat, 23 Dec 2023 01:36:59 +0100 Subject: [PATCH] blacked and formatted Signed-off-by: neuronflow --- brats_toolkit/__init__.py | 1 - brats_toolkit/cli.py | 14 ++- brats_toolkit/fusionator.py | 10 +- brats_toolkit/util/docker_functions.py | 45 ++++--- brats_toolkit/util/filemanager.py | 166 ++++++++++++++----------- brats_toolkit/util/own_itk.py | 124 +++++++++--------- brats_toolkit/util/prep_utils.py | 6 +- 7 files changed, 205 insertions(+), 161 deletions(-) diff --git a/brats_toolkit/__init__.py b/brats_toolkit/__init__.py index 8b13789..e69de29 100644 --- a/brats_toolkit/__init__.py +++ b/brats_toolkit/__init__.py @@ -1 +0,0 @@ - diff --git a/brats_toolkit/cli.py b/brats_toolkit/cli.py index 63da773..4968b44 100644 --- a/brats_toolkit/cli.py +++ b/brats_toolkit/cli.py @@ -6,13 +6,12 @@ # Please refer to README.md and LICENSE.md for further documentation # This software is not certified for clinical use. -import sys -import subprocess -import pprint import argparse +import pprint +import subprocess +import sys - -from . import segmentor, fusionator, preprocessor +from . import fusionator, preprocessor, segmentor def list_dockers(): @@ -42,7 +41,7 @@ def list_docker_cpu(): if seg.config[id]["runtime"] == "runc": print(id) - + def fusion(): parser = argparse.ArgumentParser( description="Runs the Docker orchestra to fuse segmentations. All inputs have to have equal shape and label values" @@ -84,6 +83,7 @@ def fusion(): except Exception as e: print("ERROR DETAIL: ", e) + def segmentation(): parser = argparse.ArgumentParser( description="Runs the Docker orchestra to segment and fuse segmentations based on the" @@ -179,6 +179,7 @@ def segmentation(): except Exception as e: print("ERROR DETAIL: ", e) + def batchpreprocess(): parser = argparse.ArgumentParser( description="Runs the preprocessing for MRI scans on a folder of images." @@ -242,6 +243,7 @@ def batchpreprocess(): except Exception as e: print("ERROR DETAIL: ", e) + def singlepreprocess(): parser = argparse.ArgumentParser( description="Runs the preprocessing for MRI scans on a single set of images." diff --git a/brats_toolkit/fusionator.py b/brats_toolkit/fusionator.py index 4376c3f..90de8f1 100644 --- a/brats_toolkit/fusionator.py +++ b/brats_toolkit/fusionator.py @@ -4,20 +4,20 @@ # # Please refer to README.md and LICENSE.md for further documentation # This software is not certified for clinical use. -import os -import logging import itertools +import logging import math +import os +import os.path as op import numpy as np -import os.path as op -from .util import own_itk as oitk + from .util import filemanager as fm +from .util import own_itk as oitk from .util.citation_reminder import citation_reminder class Fusionator(object): - @citation_reminder def __init__(self, verbose=True): self.verbose = verbose diff --git a/brats_toolkit/util/docker_functions.py b/brats_toolkit/util/docker_functions.py index b854cc8..00d3758 100644 --- a/brats_toolkit/util/docker_functions.py +++ b/brats_toolkit/util/docker_functions.py @@ -1,12 +1,18 @@ -import shlex -import platform +import os import pathlib +import platform +import shlex import subprocess -import os -def start_docker(exam_import_folder=None, - exam_export_folder=None, dicom_import_folder=None, nifti_export_folder=None, mode="cpu", gpuid='0'): +def start_docker( + exam_import_folder=None, + exam_export_folder=None, + dicom_import_folder=None, + nifti_export_folder=None, + mode="cpu", + gpuid="0", +): # deal with missing arguments if dicom_import_folder is None: dicom_import_folder = exam_import_folder @@ -38,28 +44,31 @@ def start_docker(exam_import_folder=None, operatingSystem = platform.system() if operatingSystem == "Windows": - bashscript = os.path.join(cwd, os.path.normpath( - './backend_scripts/win_docker.cmd')) + bashscript = os.path.join( + cwd, os.path.normpath("./backend_scripts/win_docker.cmd") + ) else: if mode == "cpu": - bashscript = os.path.normpath( - './backend_scripts/unix_docker.sh') + bashscript = os.path.normpath("./backend_scripts/unix_docker.sh") elif mode == "robex": - bashscript = os.path.normpath( - './backend_scripts/unix_docker.sh') + bashscript = os.path.normpath("./backend_scripts/unix_docker.sh") elif mode == "gpu": - bashscript = os.path.normpath( - './backend_scripts/unix_docker_gpu.sh') + bashscript = os.path.normpath("./backend_scripts/unix_docker_gpu.sh") elif mode == "gpu_hdbet": - bashscript = os.path.normpath( - './backend_scripts/unix_docker_gpu.sh') + bashscript = os.path.normpath("./backend_scripts/unix_docker_gpu.sh") # generate subprocess call - command = [bashscript, "3", dicom_import_folder, - nifti_export_folder, exam_import_folder, exam_export_folder, gpuid] + command = [ + bashscript, + "3", + dicom_import_folder, + nifti_export_folder, + exam_import_folder, + exam_export_folder, + gpuid, + ] print(*command) - print("starting docker!") subprocess.run(command, cwd=cwd) print("docker started!") diff --git a/brats_toolkit/util/filemanager.py b/brats_toolkit/util/filemanager.py index 891df36..f79f4c0 100755 --- a/brats_toolkit/util/filemanager.py +++ b/brats_toolkit/util/filemanager.py @@ -10,30 +10,35 @@ # Please refer to README.md and LICENSE.md for further documentation # This software is not certified for clinical use. -import os -import numpy as np +import fnmatch import glob +import os import shutil -import fnmatch + +import numpy as np + from . import own_itk as oitk -modalities = ['fla','t1','t1c','t2'] +modalities = ["fla", "t1", "t1c", "t2"] + def bratsNormalize(image=None, bm=None, bias=0.0001): - ''' + """ Provides normalization of BRATS images to the intensity interval 0...1 and ensures that the background is entirely 0 The bias value ensures that no brain voxel becomes 0 - ''' + """ if bm is None or image is None: - print('[Normalize][Error] You have to pass an image and a corresponding brain mask!') + print( + "[Normalize][Error] You have to pass an image and a corresponding brain mask!" + ) return None if bm.shape != image.shape: - print('[Normalize][Error] Your image and mask dimensions don\'t match!') + print("[Normalize][Error] Your image and mask dimensions don't match!") return None # set bg to zero before calculating anything - image = np.multiply(image,bm) + image = np.multiply(image, bm) # shift range to 0...x image = image - image.min() # add bias value to avoid 0 voxels @@ -44,8 +49,9 @@ def bratsNormalize(image=None, bm=None, bias=0.0001): image = np.multiply(image, bm) return image -def loadGT(path, patid, file='gt.nii.gz', verbose=True): - """ Loads the Ground Truth for a specified patient + +def loadGT(path, patid, file="gt.nii.gz", verbose=True): + """Loads the Ground Truth for a specified patient from a given Ground Truth root directory In: dir, path to the GT folder patid, patient ID @@ -54,17 +60,18 @@ def loadGT(path, patid, file='gt.nii.gz', verbose=True): """ for directory in os.listdir(path): if not os.path.isdir(os.path.join(path, directory)): - continue # Not a directory + continue # Not a directory if patid == directory: if verbose: - print('Loading GT for Patient', patid, 'now..') + print("Loading GT for Patient", patid, "now..") patpath = os.path.join(path, patid) - #TODO change loading to support GT for different methods + # TODO change loading to support GT for different methods groundtruth = oitk.get_itk_image(os.path.join(patpath, file)) break return groundtruth -def convertLabels(originalFile, oldlabels, newlabels=[0,1,2,4]): + +def convertLabels(originalFile, oldlabels, newlabels=[0, 1, 2, 4]): proto_img = oitk.get_itk_image(originalFile) labelfile = oitk.get_itk_array(proto_img) # segm_im = oitk.make_itk_image(proto_image, proto_image) @@ -73,18 +80,20 @@ def convertLabels(originalFile, oldlabels, newlabels=[0,1,2,4]): converted[labelfile == oldlabel] = newlabel oitk.write_itk_image(oitk.make_itk_image(converted, proto_img), originalFile) + def fileFinder(srcPath, filetofind, func=convertLabels, verbose=True): - """ finds a file starting from the source path in subdirectories + """finds a file starting from the source path in subdirectories and runs an arbitrary function on them """ if verbose: print(srcPath) print(filetofind) - for filename in glob.iglob(srcPath+'/**/'+filetofind, recursive=True): - func(filename, [0,1,2,4], [0,2,1,4]) + for filename in glob.iglob(srcPath + "/**/" + filetofind, recursive=True): + func(filename, [0, 1, 2, 4], [0, 2, 1, 4]) + def touchAndConvert(originalFile, gt, verbose=True): - """ Loads the ITK image and saves it with proper + """Loads the ITK image and saves it with proper header data (and conversion to 8-bit unint) """ proto_img = oitk.get_itk_image(originalFile) @@ -92,56 +101,60 @@ def touchAndConvert(originalFile, gt, verbose=True): segm_img = oitk.make_itk_image(labelfile, gt) oitk.write_itk_image(segm_img, originalFile) + def fileIterator(directory, gt_root, verbose=True): for patient in os.listdir(directory): patpath = os.path.join(directory, patient) if not os.path.isdir(patpath): - continue # Not a directory - if 'brats' in patient: - #loads itk ground truth - gt = loadGT(gt_root, patient, file='gt.nii') + continue # Not a directory + if "brats" in patient: + # loads itk ground truth + gt = loadGT(gt_root, patient, file="gt.nii") if verbose: - print ('Current patient:', patient) + print("Current patient:", patient) # loop through patient folder for result in os.listdir(patpath): if not os.path.isdir(os.path.join(patpath, result)): - continue # Not a directory + continue # Not a directory respath = os.path.join(patpath, result) paths = os.listdir(respath) for result in paths: # if there is a results file, run the conversion - if fnmatch.fnmatch(result, '*.nii*'): + if fnmatch.fnmatch(result, "*.nii*"): if verbose: - print('Will convert the following file:', result) + print("Will convert the following file:", result) touchAndConvert(os.path.join(respath, result), gt, True) + def remove_nii(root): for fn in os.listdir(root): if not os.path.isdir(os.path.join(root, fn)): - continue # Not a directory - if 'brats' in fn: + continue # Not a directory + if "brats" in fn: files = os.listdir(os.path.join(root, fn)) subdir = os.path.join(root, fn) for file in files: - if file+'.nii' in modalities: - os.remove(os.path.join(subdir, file+'.nii')) + if file + ".nii" in modalities: + os.remove(os.path.join(subdir, file + ".nii")) + def create_files(root, gz=False): # create nii.gz versions from nii for compatibility print(root) for fn in os.listdir(root): if not os.path.isdir(os.path.join(root, fn)): - continue # Not a directory - if 'brats' in fn: + continue # Not a directory + if "brats" in fn: # files = os.listdir(os.path.join(root, fn)) for file in modalities: path = os.path.join(os.path.join(root, fn), file) - proto_image = oitk.get_itk_image(path+str('.nii')) + proto_image = oitk.get_itk_image(path + str(".nii")) # segm_im = oitk.make_itk_image(proto_image, proto_image) - oitk.write_itk_image(proto_image, path+str('.nii.gz')) + oitk.write_itk_image(proto_image, path + str(".nii.gz")) + def clean(root, gz=False, dir=False): - """ Removes all subfolders and leaves only .nii and .nii.gz input + """Removes all subfolders and leaves only .nii and .nii.gz input files untouched root: path to folder with subfolers gz: If True, compressed Nifti files are also removed @@ -154,77 +167,88 @@ def clean(root, gz=False, dir=False): for file in os.listdir(subdir): if dir and os.path.isdir(os.path.join(subdir, file)): shutil.rmtree(os.path.join(subdir, file)) - if gz and '.nii.gz' in file: + if gz and ".nii.gz" in file: os.remove(os.path.join(subdir, file)) + def validate_files(root): - """ Checks if all input directories contain the right files - """ - print('Looking for BRATS data directory..') + """Checks if all input directories contain the right files""" + print("Looking for BRATS data directory..") for fn in os.listdir(root): if not os.path.isdir(os.path.join(root, fn)): - continue # Not a directory - if 'brats' in fn: - print('Found pat data:', fn) - print('Checking data validity now') + continue # Not a directory + if "brats" in fn: + print("Found pat data:", fn) + print("Checking data validity now") files = os.listdir(os.path.join(root, fn)) if not set(modalities).issubset(files): - print('Not all required files are present!') + print("Not all required files are present!") return False - print('File check okay!') + print("File check okay!") return True + def rename_flair(root): - """ Renames flair.nii files to fla.nii if required - """ + """Renames flair.nii files to fla.nii if required""" for fn in os.listdir(root): if not os.path.isdir(os.path.join(root, fn)): - continue # Not a directory - if 'brats' in fn: + continue # Not a directory + if "brats" in fn: files = os.listdir(os.path.join(root, fn)) subdir = os.path.join(root, fn) for file in files: - if 'flair' in file: - os.rename(os.path.join(subdir, file), - os.path.join(subdir, file.replace('flair', 'fla'))) + if "flair" in file: + os.rename( + os.path.join(subdir, file), + os.path.join(subdir, file.replace("flair", "fla")), + ) + def rename_fla(root): - """ Renames fla.nii files to flair.nii if required - """ + """Renames fla.nii files to flair.nii if required""" for fn in os.listdir(root): if not os.path.isdir(os.path.join(root, fn)): - continue # Not a directory - if 'brats' in fn: + continue # Not a directory + if "brats" in fn: files = os.listdir(os.path.join(root, fn)) subdir = os.path.join(root, fn) for file in files: - if 'fla.nii' == file: - os.rename(os.path.join(subdir, file), - os.path.join(subdir, - file.replace('fla.nii', 'flair.nii'))) - if 'fla.nii.gz' == file: - os.rename(os.path.join(subdir, file), - os.path.join(subdir, - file.replace('fla.nii.gz', 'flair.nii.gz'))) + if "fla.nii" == file: + os.rename( + os.path.join(subdir, file), + os.path.join(subdir, file.replace("fla.nii", "flair.nii")), + ) + if "fla.nii.gz" == file: + os.rename( + os.path.join(subdir, file), + os.path.join( + subdir, file.replace("fla.nii.gz", "flair.nii.gz") + ), + ) + def reduce_filesize(root, gz=False): # create nii.gz versions from nii for compatibility for fn in os.listdir(root): if not os.path.isdir(os.path.join(root, fn)): - continue # Not a directory - if 'brats' in fn: + continue # Not a directory + if "brats" in fn: # files = os.listdir(os.path.join(root, fn)) for file in modalities: path = os.path.join(os.path.join(root, fn), file) - proto_image = oitk.get_itk_image(path+str('.nii')) + proto_image = oitk.get_itk_image(path + str(".nii")) # segm_im = oitk.make_itk_image(proto_image, proto_image) - oitk.write_itk_image(proto_image, path+str('.nii.gz')) + oitk.write_itk_image(proto_image, path + str(".nii.gz")) + def completeclean(root): # maybe remove the root-results folder as well clean(root, False, True) + def conversion(segmentations, verbose=True): - gt_root = '/Users/christoph/Documents/Uni/Bachelorarbeit/Testdaten/testing_nii_LABELS' - #segmentations = '/Users/christoph/Documents/Uni/Bachelorarbeit/Testdaten/Complete_Results' + gt_root = ( + "/Users/christoph/Documents/Uni/Bachelorarbeit/Testdaten/testing_nii_LABELS" + ) + # segmentations = '/Users/christoph/Documents/Uni/Bachelorarbeit/Testdaten/Complete_Results' fileIterator(segmentations, gt_root) diff --git a/brats_toolkit/util/own_itk.py b/brats_toolkit/util/own_itk.py index 7993198..46d9d3c 100755 --- a/brats_toolkit/util/own_itk.py +++ b/brats_toolkit/util/own_itk.py @@ -3,40 +3,43 @@ write ITK images. """ -__version__ = '0.2' -__author__ = 'Esther Alberts' +__version__ = "0.2" +__author__ = "Esther Alberts" import os + import numpy as np import SimpleITK as itk + def reduce_arr_dtype(arr, verbose=False): - """ Change arr.dtype to a more memory-efficient dtype, without changing - any element in arr. """ - - if np.all(arr-np.asarray(arr,'uint8') == 0): - if arr.dtype != 'uint8': + """Change arr.dtype to a more memory-efficient dtype, without changing + any element in arr.""" + + if np.all(arr - np.asarray(arr, "uint8") == 0): + if arr.dtype != "uint8": if verbose: - print('Converting '+str(arr.dtype)+' to uint8 np.ndarray') - arr = np.asarray(arr, dtype='uint8') - elif np.all(arr-np.asarray(arr,'int8') == 0): - if arr.dtype != 'int8': + print("Converting " + str(arr.dtype) + " to uint8 np.ndarray") + arr = np.asarray(arr, dtype="uint8") + elif np.all(arr - np.asarray(arr, "int8") == 0): + if arr.dtype != "int8": if verbose: - print('Converting '+str(arr.dtype)+' to int8 np.ndarray') - arr = np.asarray(arr, dtype='int8') - elif np.all(arr-np.asarray(arr,'uint16') == 0): - if arr.dtype != 'uint16': + print("Converting " + str(arr.dtype) + " to int8 np.ndarray") + arr = np.asarray(arr, dtype="int8") + elif np.all(arr - np.asarray(arr, "uint16") == 0): + if arr.dtype != "uint16": if verbose: - print('Converting '+str(arr.dtype)+' to uint16 np.ndarray') - arr = np.asarray(arr, dtype='uint16') - elif np.all(arr-np.asarray(arr,'int16') == 0): - if arr.dtype != 'int16': + print("Converting " + str(arr.dtype) + " to uint16 np.ndarray") + arr = np.asarray(arr, dtype="uint16") + elif np.all(arr - np.asarray(arr, "int16") == 0): + if arr.dtype != "int16": if verbose: - print('Converting '+str(arr.dtype)+' to int16 np.ndarray') - arr = np.asarray(arr, dtype='int16') - + print("Converting " + str(arr.dtype) + " to int16 np.ndarray") + arr = np.asarray(arr, dtype="int16") + return arr + def make_itk_image(arr, proto_image=None, verbose=True): """Create an itk image given an image array. @@ -53,7 +56,7 @@ def make_itk_image(arr, proto_image=None, verbose=True): The itk image containing the input array `arr`. """ - + arr = reduce_arr_dtype(arr, verbose=verbose) image = itk.GetImageFromArray(arr) @@ -62,6 +65,7 @@ def make_itk_image(arr, proto_image=None, verbose=True): return image + def write_itk_image(image, path): """Write an itk image to a path. @@ -80,12 +84,12 @@ def write_itk_image(image, path): writer = itk.ImageFileWriter() writer.SetFileName(path) - if os.path.splitext(path)[1] == '.nii': - Warning('You are converting nii, ' + \ - 'be careful with type conversions') + if os.path.splitext(path)[1] == ".nii": + Warning("You are converting nii, " + "be careful with type conversions") writer.Execute(image) + def get_itk_image(path_or_image): """Get an itk image given a path. @@ -93,7 +97,7 @@ def get_itk_image(path_or_image): ---------- path : str or itk.Image Path pointing to an image file with extension among - *TIFF, JPEG, PNG, BMP, DICOM, GIPL, Bio-Rad, LSM, Nifti (.nii and .nii.gz), + *TIFF, JPEG, PNG, BMP, DICOM, GIPL, Bio-Rad, LSM, Nifti (.nii and .nii.gz), Analyze, SDT/SPR (Stimulate), Nrrd or VTK images*. Returns @@ -106,7 +110,7 @@ def get_itk_image(path_or_image): return path_or_image if not os.path.exists(path_or_image): - err = path_or_image + ' doesnt exist' + err = path_or_image + " doesnt exist" raise AttributeError(err) reader = itk.ImageFileReader() @@ -116,14 +120,15 @@ def get_itk_image(path_or_image): return image + def get_itk_array(path_or_image): - """ Get an image array given a path or itk image. + """Get an image array given a path or itk image. Parameters ---------- path_or_image : str or itk image Path pointing to an image file with extension among - *TIFF, JPEG, PNG, BMP, DICOM, GIPL, Bio-Rad, LSM, Nifti (.nii and .nii.gz), + *TIFF, JPEG, PNG, BMP, DICOM, GIPL, Bio-Rad, LSM, Nifti (.nii and .nii.gz), Analyze, SDT/SPR (Stimulate), Nrrd or VTK images* or an itk image. Returns @@ -143,42 +148,44 @@ def get_itk_array(path_or_image): image = path_or_image else: - err = 'Image type not recognized: ' + str(type(path_or_image)) + err = "Image type not recognized: " + str(type(path_or_image)) raise RuntimeError(err) arr = itk.GetArrayFromImage(image) return arr + def copy_image_info(input_path, ref_path): - """ Copy origin, direction and spacing information from ref_path - into the header in input_path. """ - - print('OVerwriting '+input_path[-50:]) - + """Copy origin, direction and spacing information from ref_path + into the header in input_path.""" + + print("OVerwriting " + input_path[-50:]) + ref_im = get_itk_image(ref_path) im = get_itk_image(input_path) - + dim = im.GetSize() if dim != ref_im.GetSize(): - err = 'Images are not of same dimension, I will not copy image info!' + err = "Images are not of same dimension, I will not copy image info!" raise RuntimeError(err) - + im.SetOrigin(ref_im.GetOrigin()) im.SetDirection(ref_im.GetDirection()) im.SetSpacing(ref_im.GetSpacing()) - + if im.GetSize() != dim: - err = 'Dimension changed during copying image info: aborting' + err = "Dimension changed during copying image info: aborting" raise RuntimeError(err) - + write_itk_image(im, input_path) - + + def load_arr_from_paths(paths): - """ For every str in paths (paths can consis of nested lists), + """For every str in paths (paths can consis of nested lists), load the image at this path. If any str is not a path, an error - is thrown. All other objects are preserved. """ - + is thrown. All other objects are preserved.""" + if isinstance(paths, str): im_arrs = get_itk_array(paths) elif isinstance(paths, (list, tuple)): @@ -187,9 +194,10 @@ def load_arr_from_paths(paths): im_arrs = paths else: im_arrs = paths - + return im_arrs + def get_itk_data(path_or_image, verbose=False): """Get the image array, image size and pixel dimensions given an itk image or a path. @@ -198,7 +206,7 @@ def get_itk_data(path_or_image, verbose=False): ---------- path_or_image : str or itk image Path pointing to an image file with extension among - *TIFF, JPEG, PNG, BMP, DICOM, GIPL, Bio-Rad, LSM, Nifti (.nii and .nii.gz), + *TIFF, JPEG, PNG, BMP, DICOM, GIPL, Bio-Rad, LSM, Nifti (.nii and .nii.gz), Analyze, SDT/SPR (Stimulate), Nrrd or VTK images* or an itk image. verbose : boolean, optional If true, print image shape, spacing and data type of the image @@ -232,15 +240,15 @@ def get_itk_data(path_or_image, verbose=False): data_type = arr.dtype if verbose: - - print('\t image shape: ' + str(shape)) - print('\t image spacing: ' + str(spacing)) - print('\t image data type: ' + str(data_type)) + print("\t image shape: " + str(shape)) + print("\t image spacing: " + str(spacing)) + print("\t image data type: " + str(data_type)) return arr, shape, spacing + def read_dicom(source_path, verbose=True): - '''Reads dicom series into an itk image. + """Reads dicom series into an itk image. Parameters ---------- @@ -253,15 +261,17 @@ def read_dicom(source_path, verbose=True): ------- image : itk image image volume. - ''' + """ reader = itk.ImageSeriesReader() names = reader.GetGDCMSeriesFileNames(source_path) if len(names) < 1: - raise IOError('No Series can be found at the specified path!') + raise IOError("No Series can be found at the specified path!") elif verbose: - print('image series with %d dicom files found in : %s' \ - % (len(names), source_path[-50:])) + print( + "image series with %d dicom files found in : %s" + % (len(names), source_path[-50:]) + ) reader.SetFileNames(names) image = reader.Execute() if verbose: diff --git a/brats_toolkit/util/prep_utils.py b/brats_toolkit/util/prep_utils.py index 44cbf60..8860daa 100644 --- a/brats_toolkit/util/prep_utils.py +++ b/brats_toolkit/util/prep_utils.py @@ -1,11 +1,11 @@ -from pathlib import Path -import shutil import os +import shutil +from pathlib import Path def tempFiler(orgFilePath, modality, tempFolder): stemName = Path(orgFilePath).stem - stemName = stemName.rsplit('.', 2)[0] + stemName = stemName.rsplit(".", 2)[0] stemName = stemName + "_" + modality + ".nii.gz" tempFile = os.path.join(tempFolder, stemName)