diff --git a/examples/README.md b/examples/README.md deleted file mode 100644 index 5520e74c..00000000 --- a/examples/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# Tutorials - -For getting a deeper understanding of the package, we have provided with multiple google collabs which showcases -different functionalities of med-imagetools - -## Tutorial 1: Forming Dataset with med-imagetools Autopipeline - -Autopipeline is one of the main features of med-imagetools which turns messy raw data and processes it taking into account -the different relationships between different modalities. This notebook gives a demo of how the autopipeline can be used - -[![Google Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/skim2257/tcia_samples/blob/main/notebooks/Tutorial_1_Forming_Dataset_with_Med_Imagetools.ipynb) - -## Tutorial 2: Machine Learning with med-imagetools and torchio - -This tutorial will showcase how we can form Machine Learning pipeline with the help of med-imagetools and torchio. In this notebook we will go through segmentation of body from head and neck cancer dataset - -[![Google Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/skim2257/tcia_samples/blob/main/notebooks/Tutorial_2_Machine_Learning_with_Med_Imagetools_and_torchio.ipynb) diff --git a/examples/ct_rtstruct_quickstart.py b/examples/ct_rtstruct_quickstart.py deleted file mode 100644 index f4e78b4d..00000000 --- a/examples/ct_rtstruct_quickstart.py +++ /dev/null @@ -1,129 +0,0 @@ -import pathlib - -from argparse import ArgumentParser - -from imgtools.io import read_dicom_rtstruct, read_dicom_series -from imgtools.ops import StructureSetToSegmentation, ImageFileInput, ImageFileOutput -from imgtools.pipeline import Pipeline - - -################################################################ -#every pipeline needs to be inherited from the Pipeline class -class samplePipeline(Pipeline): - """ - Sample starter pipeline for processing CT images and their relevant RTSTRUCTs - - This pipeline is designed to be used with the following directory structure: - - input_directory - - subject_directory (the subject's name) - - CT_file_convention - - CT_image_1.dcm - - CT_image_2.dcm - - ... - - RTSTRUCT_file_convention - - RTSTRUCT.dcm - - The pipeline will look for CT images in the CT_file_convention and RTSTRUCTs in the - RTSTRUCT_file_convention. The pipeline will save the processed images and masks in - the output_directory. - - Attributes: - input_directory (str): the directory where the input images and RTSTRUCTs are stored - output_directory (str): the directory where the output images and masks will be stored - CT_file_convention (str): the glob-supported naming convention for the CT images - RTSTRUCT_file_convention (str): the name of the directory where the RTSTRUCTs are stored - - Methods: - process_one_subject(subject_id): how to process one subject (this function must be defined for all pipelines) - """ - - - def __init__(self, - input_directory, - output_directory, - CT_file_convention, - RTSTRUCT_file_convention): - super().__init__() - - self.input_directory = input_directory - self.output_directory = output_directory - - # the file-reading input class for all the CT images - self.image_input = ImageFileInput( - self.input_directory, # where to look for the images - get_subject_id_from="subject_directory", # how to extract the subject ID, 'subject_directory' means use the name of the subject directory. 'filename' means use the name of the file - subdir_path=CT_file_convention, # whether the images are stored in a subdirectory of the subject directory (also accepts glob patterns) - reader=read_dicom_series # the function used to read individual images - ) - - # the file-reading input class for all the RTSTRUCTs - self.structure_set_input = ImageFileInput( - self.input_directory, - get_subject_id_from="subject_directory", - subdir_path=RTSTRUCT_file_convention, - reader=read_dicom_rtstruct - ) - - # class for converting the RTSTRUCT DICOMs to binary masks - self.make_binary_mask = StructureSetToSegmentation(roi_names=[]) - - # the file-writing output class for all the processed images - self.image_output = ImageFileOutput( - pathlib.Path(self.output_directory, "images").as_posix(), # where to save the processed images - filename_format="{subject_id}_image.nii.gz", # the filename template, {subject_id} will be replaced by each subject's ID at runtime - create_dirs=True # whether to create directories that don't exists already - ) - - # the file-writing output class for all the processed masks - self.mask_output = ImageFileOutput( - pathlib.Path(self.output_directory, "masks").as_posix(), - filename_format="{subject_id}_mask.nii.gz", - create_dirs=True - ) - - - - # pipeline classes must have a definition for how to process one patient - - def process_one_subject(self, subject_id): - # calling the classes initialized in __init__() - image = self.image_input(subject_id).image - structure_set = self.structure_set_input(subject_id) - - # print all the regions of interest in the RTSTRUCT - print(structure_set.roi_names) - - # convert the RTSTRUCT to a binary mask - mask = self.make_binary_mask(structure_set, image) - self.image_output(subject_id, image) - self.mask_output(subject_id, mask) - -if __name__ == "__main__": - parser = ArgumentParser("Quickstart example") - - parser.add_argument("input_directory", type=str, - help="The directory containing the input data") - parser.add_argument("output_directory", type=str, - help="The directory where the output will be stored") - - # sample run: python ct_rtstruct_quickstart.py C:\Users\qukev\BHKLAB\datasetshort\manifest-1598890146597\NSCLC-Radiomics-Interobserver1 C:\Users\qukev\BHKLAB\starteroutput - - # look at your input directory and look at how all the DICOM files are named - CT_file_convention = "*/NA-*" - RTSTRUCT_file_convention = "*/1.000000-ARIA RadOnc Structure Sets-*/1-1.dcm" - - args = parser.parse_args() - pipeline = samplePipeline( - input_directory=args.input_directory, - output_directory=args.output_directory, - CT_file_convention=CT_file_convention, - RTSTRUCT_file_convention=RTSTRUCT_file_convention - ) - - #process each patient one by one in a linear fashion - subject_ids = pipeline._get_loader_subject_ids() - for subject_id in subject_ids: - pipeline.process_one_subject(subject_id) - - # pipeline.run() - # alternatively, use pipeline.run() to run the pipeline in parallel using joblib, which is more efficient for larger datasets \ No newline at end of file diff --git a/examples/process_general.py b/examples/process_general.py deleted file mode 100644 index 59cd3153..00000000 --- a/examples/process_general.py +++ /dev/null @@ -1,215 +0,0 @@ -import pathlib - -from argparse import ArgumentParser - -from imgtools.io import read_dicom_auto -from imgtools.ops import StructureSetToSegmentation, ImageCSVInput, ImageFileOutput, Resample -from imgtools.pipeline import Pipeline -from imgtools.modules.datagraph import DataGraph - -import SimpleITK as sitk - - - -############################################################### -# Example usage: -# python radcure_simple.py ./data/RADCURE/data ./RADCURE_output -############################################################### - - -class AutoPipeline(Pipeline): - """Example processing pipeline for the RADCURE dataset. - This pipeline loads the CT images and structure sets, re-samples the images, - and draws the GTV contour using the resampled image. - """ - - def __init__(self, - output_directory, - query, - spacing=(1., 1., 0.), - n_jobs=-1, - missing_strategy="drop", - show_progress=False, - warn_on_error=False): - - super().__init__( - n_jobs=n_jobs, - missing_strategy=missing_strategy, - show_progress=show_progress, - warn_on_error=warn_on_error) - - # pipeline configuration - self.output_directory = output_directory - self.spacing = spacing - self.existing = [None] #self.existing_patients() - - path_crawl = "/cluster/projects/radiomics/PublicDatasets/HeadNeck/TCIA Head-Neck-PET-CT/imgtools_Head-Neck-PET-CT_2.csv" - edge_path = "/cluster/projects/radiomics/PublicDatasets/HeadNeck/TCIA Head-Neck-PET-CT/HN-PET-CT_2_edgetable.csv" - print("Given query: {}".format(query)) - # query = "CT,RTSTRUCT,RTDOSE" - # query = "CT,PT" - - - graph = DataGraph(path_crawl=path_crawl,edge_path=edge_path) - self.df_combined = graph.parser(query) - # self.column_names = list(self.df_combined.columns) - self.column_names = [cols for cols in self.df_combined.columns if cols.split("_")[0]=="folder"] - print("Column Names: {}".format(self.column_names)) - print(self.df_combined.head()) - print("Returned query has {} cases amongst the crawled data".format(len(self.df_combined))) - - readers = [read_dicom_auto for i in range(len(self.column_names))] - self.input = ImageCSVInput(self.df_combined, - self.column_names, - readers=readers) - - # image processing ops - self.resample = Resample(spacing=self.spacing) - self.make_binary_mask = StructureSetToSegmentation(roi_names=[], continuous=False) - - # output ops - # file name dictionary - file_name = {"CT": "images","RTDOSE_CT":"doses","RTSTRUCT_CT":"ct_masks.seg","RTSTRUCT_PT":"pet_masks.seg","PT_CT":"pets","PT":"pets","RTDOSE":"doses","RTSTRUCT":"masks.seg"} - self.output = [] - for colname in self.column_names: - colname_process = ("_").join(colname.split("_")[1:]) - extension = file_name[colname_process] - self.output.append(ImageFileOutput(pathlib.Path(self.output_directory,extension.split(".")[0]).as_posix(), - filename_format="{subject_id}_"+"{}.nrrd".format(extension))) - - def process_one_subject(self, subject_id): - """Define the processing operations for one subject. - This method must be defined for all pipelines. It is used to define - the preprocessing steps for a single subject (note: that might mean - multiple images, structures, etc.). During pipeline execution, this - method will receive one argument, subject_id, which can be used to - retrieve inputs and save outputs. - Parameters - ---------- - subject_id : str - The ID of currently processed subjectsqusqueue - """ - - print("Processing:", subject_id) - - read_results = self.input(subject_id) - print(read_results) - - print(subject_id, " start") - #For counting multiple connections per modality - counter = [0 for i in range(len(self.column_names))] - for i,colnames in enumerate(self.column_names): - #Based on the modality the operations will differ - modality = colnames.split("_")[1:][0] - #If there are multiple connections existing, multiple connections means two modalities connected to one modality. They end with _1 - mult_conn = colnames.split("_")[-1] - if read_results[i] is None: - print("The subject id: {} has no {}".format(subject_id,("_").join(colnames.split("_")[1:]))) - pass - elif modality=="CT": - image = read_results[i] - if len(image.GetSize()) == 4: - assert image.GetSize()[-1] == 1, f"There is more than one volume in this CT file for {subject_id}." - extractor = sitk.ExtractImageFilter() - extractor.SetSize([*image.GetSize()[:3], 0]) - extractor.SetIndex([0, 0, 0, 0]) - - image = extractor.Execute(image) - print(image.GetSize()) - image = self.resample(image) - #Saving the output - self.output[i](subject_id, image) - print(subject_id, " SAVED IMAGE") - elif modality=="RTDOSE": - try: - doses = read_results[i].resample_rt(image) - except: - Warning("No CT image present. Returning dose image without resampling") - doses = read_results[i] - - if mult_conn!="1": - self.output[i](subject_id, doses) - else: - counter[i] = counter[i]+1 - self.output[i](subject_id+"_{}".format(counter[i]),doses) - print(subject_id, " SAVED DOSE") - elif modality=="RTSTRUCT": - structure_set = read_results[i] - mask = self.make_binary_mask(structure_set, image) - if mult_conn!="1": - self.output[i](subject_id, mask) - else: - counter[i] = counter[i]+1 - self.output[i](subject_id+"_{}".format(counter[i]),mask) - print("SAVED MASK") - elif modality=="PT": - try: - pet = read_results[i].resample_pet(image) - except: - Warning("No CT image present. Returning PET image without resampling") - pet = read_results[i] - - if mult_conn!="1": - self.output[i](subject_id, pet) - else: - counter[i] = counter[i]+1 - self.output[i](subject_id+"_{}".format(counter[i]),pet) - print(subject_id, " SAVED PET") - - print("SUCCESS") - return - -if __name__ == "__main__": - print("WASSUP") - parser = ArgumentParser("Head-Neck-PET-CT processing pipeline.") - parser.add_argument( - "output_directory", - type=str, - help="Path to the directory where the processed images will be saved.") - parser.add_argument( - "--modality", - type=str, - default="CT,RTDOSE,RTSTRUCT,PT", - help="Query to get the sub-dataset. Type it like a string for ex: RTSTRUCT,CT,RTDOSE") - parser.add_argument( - "--spacing", - nargs=3, - type=float, - default=(1., 1., 0.), - help="The resampled voxel spacing in (x, y, z) directions.") - parser.add_argument( - "--n_jobs", - type=int, - default=-1, - help="The number of parallel processes to use.") - parser.add_argument( - "--show_progress", - action="store_true", - help="Whether to print progress to standard output.") - args = parser.parse_args() - pipeline = AutoPipeline( - output_directory=args.output_directory, - query=args.modality, - spacing=args.spacing, - n_jobs=args.n_jobs, - show_progress=args.show_progress) - - print('starting Pipeline...') - # == Parallel Processing == - pipeline.run() - - # == Series (Single-core) Processing == - # Good for finding edge cases - # subject_ids = pipeline._get_loader_subject_ids() - # subject_ids = [202, 205, 209, 163, 149, - # 147, 146, 145, 144, 143, - # 140, 139, 138, 132, 130, - # 129, 0, 1, 2, 3, 4, 5] - # print('starting for loop...') - # for subject_id in subject_ids: - # pipeline.process_one_subject(subject_id) - - # == Just Uno == - # Good for quickly checking on one sample. - # pipeline.process_one_subject(5) - print('finished Pipeline!') \ No newline at end of file diff --git a/examples/process_quebec.sh b/examples/process_quebec.sh deleted file mode 100644 index d7399dd2..00000000 --- a/examples/process_quebec.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env bash -SCRIPT_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" -TOP_DIR="$(dirname "$SCRIPT_DIR")" - -python $TOP_DIR/imgtools/autopipeline.py\ - $SCRIPT_DIR/data/tcia_samples/Head-Neck-PET-CT \ - $SCRIPT_DIR/data/tcia_nrrd \ - --modalities CT,RTDOSE,PT \ - --n_jobs 1 \ No newline at end of file diff --git a/examples/radcure_simple.py b/examples/radcure_simple.py deleted file mode 100644 index 943941d1..00000000 --- a/examples/radcure_simple.py +++ /dev/null @@ -1,164 +0,0 @@ -import pathlib -from argparse import ArgumentParser - -from imgtools.io import (read_dicom_rtstruct, read_dicom_series, read_dicom_rtdose, read_dicom_pet) -from imgtools.ops import StructureSetToSegmentation, ImageFileInput, ImageFileOutput, Resample -from imgtools.pipeline import Pipeline - - -############################################################### -# Example usage: -# python radcure_simple.py ./data/RADCURE/data ./RADCURE_output -############################################################### - - -class RADCUREPipeline(Pipeline): - """Example processing pipeline for the RADCURE dataset. - - This pipeline loads the CT images and structure sets, re-samples the images, - and draws the GTV contour using the resampled image. - """ - - def __init__(self, - input_directory, - output_directory, - spacing=(1., 1., 0.), - n_jobs=-1, - missing_strategy="drop", - show_progress=False, - warn_on_error=False): - super().__init__( - n_jobs=n_jobs, - missing_strategy=missing_strategy, - show_progress=show_progress, - warn_on_error=warn_on_error) - - # pipeline configuration - self.input_directory = input_directory - self.output_directory = output_directory - self.spacing = spacing - - # pipeline ops - # input ops - self.image_input = ImageFileInput( - self.input_directory, # where to look for the images - get_subject_id_from="subject_directory", # how to extract the subject ID, 'subject_directory' means use the name of the subject directory - subdir_path="*/ImageSet_*", # whether the images are stored in a subdirectory of the subject directory (also accepts glob patterns) - reader=read_dicom_series # the function used to read individual images - ) - self.structure_set_input = ImageFileInput( - self.input_directory, - get_subject_id_from="subject_directory", - subdir_path="*/structures/RTSTRUCT.dcm", - reader=read_dicom_rtstruct - ) - self.rtdose_input = ImageFileInput( - self.input_directory, - get_subject_id_from="subject_directory", - subdir_path="*/dose/DOSE.dcm", - reader=read_dicom_rtdose - ) - - self.petscan_input = ImageFileInput( - self.input_directory, - get_subject_id_from="subject_directory", - subdir_path="*/pet_*", - reader=read_dicom_pet - ) - # image processing ops - self.resample = Resample(spacing=self.spacing) - # Note: the ROI name is temporarily changed to match the example data - # since RADCURE is still not public. The correct ROI name for RADCURE is 'GTV'. - self.make_binary_mask = StructureSetToSegmentation(roi_names="GTV-1")#"GTV") - - # output ops - self.image_output = ImageFileOutput( - pathlib.Path(self.output_directory, "images"), # where to save the processed image.as_posix()s - filename_format="{subject_id}_image.nrrd", # the filename template, {subject_id} will be replaced by each subject's ID at runtime - create_dirs=True, # whether to create directories that don't exists already - compress=True # enable compression for NRRD format - ) - self.mask_output = ImageFileOutput( - pathlib.Path(self.output_directory, "masks").as_posix(), - filename_format="{subject_id}_mask.nrrd", - create_dirs=True, - compress=True - ) - self.dose_output = ImageFileOutput( - pathlib.Path(self.output_directory, "doses").as_posix(), - filename_format="{subject_id}_dose.nrrd", - create_dirs=True, - compress=True - ) - self.petscan_output = ImageFileOutput( - pathlib.Path(self.output_directory, "petscan").as_posix(), - filename_format="{subject_id}_petscan.nrrd", - create_dirs=True, - compress=True - ) - - def process_one_subject(self, subject_id): - """Define the processing operations for one subject. - - This method must be defined for all pipelines. It is used to define - the preprocessing steps for a single subject (note: that might mean - multiple images, structures, etc.). During pipeline execution, this - method will receive one argument, subject_id, which can be used to - retrieve inputs and save outputs. - - Parameters - ---------- - subject_id : str - The ID of currently processed subject - """ - - image = self.image_input(subject_id).image - - structure_set = self.structure_set_input(subject_id) # noqa: F841 - dose_set = self.rtdose_input(subject_id) - pet_set = self.petscan_input(subject_id) - - - image = self.resample(image) - # note that the binary mask can be generated with correct spacing using - # the resampled image, eliminating the need to resample it separately - # mask = self.make_binary_mask(structure_set, image) - self.image_output(subject_id, image) - # self.mask_output(subject_id, mask) - self.dose_output(subject_id, dose_set) - self.petscan_output(subject_id, pet_set) - - -if __name__ == "__main__": - parser = ArgumentParser("Example RADCURE processing pipeline.") - parser.add_argument( - "input_directory", - type=str, - help="Path to the input directory of RADCURE dataset.") - parser.add_argument( - "output_directory", - type=str, - help="Path to the directory where the processed images will be saved.") - parser.add_argument( - "--spacing", - nargs=3, - type=float, - default=(1., 1., 0.), - help="The resampled voxel spacing in (x, y, z) directions.") - parser.add_argument( - "--n_jobs", - type=int, - default=1, - help="The number of parallel processes to use.") - parser.add_argument( - "--show_progress", - action="store_true", - help="Whether to print progress to standard output.") - args = parser.parse_args() - pipeline = RADCUREPipeline( - input_directory=args.input_directory, - output_directory=args.output_directory, - spacing=args.spacing, - n_jobs=args.n_jobs, - show_progress=args.show_progress) - pipeline.run() diff --git a/src/imgtools/autopipeline.py b/src/imgtools/autopipeline.py index 0937e009..529201a7 100644 --- a/src/imgtools/autopipeline.py +++ b/src/imgtools/autopipeline.py @@ -461,7 +461,26 @@ def process_one_subject(self, subject_id): metadata.update(doses.metadata) print(subject_id, " SAVED DOSE") - + + # Process PET + elif modality == "PT": + try: + # For cases with no image present + pet = read_results[i].resample_pet(image) + except: + Warning("No CT image present. Returning PT/PET image without resampling.") + pet = read_results[i] + + # output + self.output(subject_id, pet, output_stream) + metadata[f"size_{output_stream}"] = str(pet.GetSize()) + metadata[f"metadata_{colname}"] = [read_results[i].get_metadata()] + + if hasattr(pet, "metadata") and pet.metadata is not None: + metadata.update(pet.metadata) + + print(subject_id, " SAVED PET") + # Process contour elif modality == "RTSTRUCT": num_rtstructs += 1 @@ -551,24 +570,7 @@ def process_one_subject(self, subject_id): print(subject_id, "SAVED MASK ON", conn_to) - # Process PET - elif modality == "PT": - try: - # For cases with no image present - pet = read_results[i].resample_pet(image) - except: - Warning("No CT image present. Returning PT/PET image without resampling.") - pet = read_results[i] - - # output - self.output(subject_id, pet, output_stream) - metadata[f"size_{output_stream}"] = str(pet.GetSize()) - metadata[f"metadata_{colname}"] = [read_results[i].get_metadata()] - - if hasattr(pet, "metadata") and pet.metadata is not None: - metadata.update(pet.metadata) - - print(subject_id, " SAVED PET") + metadata[f"output_folder_{colname}"] = pathlib.Path(subject_id, colname).as_posix() diff --git a/src/imgtools/image.py b/src/imgtools/image.py index d8a6f2e0..f215339b 100644 --- a/src/imgtools/image.py +++ b/src/imgtools/image.py @@ -124,7 +124,6 @@ def geometry(self): direction=self.direction, spacing=self.spacing) - @property def ndim(self): return len(self.size) diff --git a/src/imgtools/io/dataset.py b/src/imgtools/io/dataset.py index bfe746c3..9689e102 100644 --- a/src/imgtools/io/dataset.py +++ b/src/imgtools/io/dataset.py @@ -166,6 +166,15 @@ def process_one_subject( doses = read_results[i] temp[f"mod_{colname}"] = tio.ScalarImage.from_sitk(doses) temp[f"metadata_{colname}"] = read_results[i].get_metadata() + elif modality == "PT": + try: + # For cases with no image present + pet = read_results[i].resample_pet(image) + except: + Warning("No CT image present. Returning PT/PET image without resampling.") + pet = read_results[i] + temp[f"mod_{colname}"] = tio.ScalarImage.from_sitk(pet) + temp[f"metadata_{colname}"] = read_results[i].get_metadata() elif modality == "RTSTRUCT": # For RTSTRUCT, you need image or PT structure_set = read_results[i] @@ -179,13 +188,5 @@ def process_one_subject( raise ValueError("You need to pass a reference CT or PT/PET image to map contours to.") temp[f"mod_{colname}"] = tio.LabelMap.from_sitk(mask) temp[f"metadata_{colname}"] = structure_set.roi_names - elif modality == "PT": - try: - # For cases with no image present - pet = read_results[i].resample_pet(image) - except: - Warning("No CT image present. Returning PT/PET image without resampling.") - pet = read_results[i] - temp[f"mod_{colname}"] = tio.ScalarImage.from_sitk(pet) - temp[f"metadata_{colname}"] = read_results[i].get_metadata() + return tio.Subject(temp) diff --git a/src/imgtools/io/writers.py b/src/imgtools/io/writers.py index 8301a0cb..b7f295eb 100644 --- a/src/imgtools/io/writers.py +++ b/src/imgtools/io/writers.py @@ -119,7 +119,7 @@ def put(self, subject_id, mask, **kwargs): origin = mask.GetOrigin() spacing = mask.GetSpacing() - direction = mask.GetDirection() # noqa: F841 + #direction = mask.GetDirection() space = "left-posterior-superior" # everything is ITK read/write diff --git a/src/imgtools/ops/ops.py b/src/imgtools/ops/ops.py index 16b0790d..4c439cff 100644 --- a/src/imgtools/ops/ops.py +++ b/src/imgtools/ops/ops.py @@ -100,7 +100,8 @@ def __init__(self, import json with open(tree_crawl_path, 'r') as f: - tree_db = json.load(f) # currently unused, TO BE implemented in the future # noqa: F841 + tree_db = json.load(f) # currently unused, TO BE implemented in the future + assert tree_db is not None, "There was no crawler output" # dodging linter # GRAPH # ----- @@ -1636,7 +1637,9 @@ def get_mask(self, reference_image, seg, mask, label, idx, continuous): mask[:,:,:,idx] += seg[:,:,:,idx_seg] else: # if 2D segmentations on 3D images frame = seg.frame_groups[idx_seg] - ref_uid = frame.DerivationImageSequence[0].SourceImageSequence[0].ReferencedSOPInstanceUID # unused but references InstanceUID of slice # noqa: F841 + ref_uid = frame.DerivationImageSequence[0].SourceImageSequence[0].ReferencedSOPInstanceUID # unused but references InstanceUID of slice + assert ref_uid is not None, "There was no ref_uid" # dodging linter + frame_coords = np.array(frame.PlanePositionSequence[0].ImagePositionPatient) img_coords = physical_points_to_idxs(reference_image, np.expand_dims(frame_coords, (0, 1)))[0][0] z = img_coords[0] diff --git a/src/imgtools/utils/nnunet.py b/src/imgtools/utils/nnunet.py index 1ed2bcc0..584a7534 100644 --- a/src/imgtools/utils/nnunet.py +++ b/src/imgtools/utils/nnunet.py @@ -41,7 +41,8 @@ def subfiles(folder: str, join: bool = True, prefix: str = None, suffix: str = N if join: path_fn = os.path.join else: - path_fn = lambda x, y: y # noqa: E731 + def path_fn(x, y): return y + res = [path_fn(folder, i) for i in os.listdir(folder) if os.path.isfile(os.path.join(folder, i)) and (prefix is None or i.startswith(prefix)) and (suffix is None or i.endswith(suffix))] diff --git a/tests/dataset_check.py b/tests/dataset_check.py index 64598068..3b571ada 100644 --- a/tests/dataset_check.py +++ b/tests/dataset_check.py @@ -39,6 +39,8 @@ def dataset_path(): crawl_path = pathlib.Path(imgtools_path, f"imgtools_{dataset_name}.csv").as_posix() json_path = pathlib.Path(imgtools_path, f"imgtools_{dataset_name}.json").as_posix() # noqa: F841 edge_path = pathlib.Path(imgtools_path, f"imgtools_{dataset_name}_edges.csv").as_posix() + assert os.path.exists(crawl_path) & os.path.exists(edge_path) & os.path.exists(json_path), "There was no crawler output" + yield quebec_path, output_path, crawl_path, edge_path class select_roi_names(tio.LabelTransform): diff --git a/tests/test_components.py b/tests/test_components.py index 007d82a0..08ef8960 100644 --- a/tests/test_components.py +++ b/tests/test_components.py @@ -37,6 +37,8 @@ def dataset_path(): crawl_path = pathlib.Path(imgtools_path, f"imgtools_{dataset_name}.csv").as_posix() json_path = pathlib.Path(imgtools_path, f"imgtools_{dataset_name}.json").as_posix() # noqa: F841 edge_path = pathlib.Path(imgtools_path, f"imgtools_{dataset_name}_edges.csv").as_posix() + + assert os.path.exists(crawl_path) & os.path.exists(edge_path) & os.path.exists(json_path), "There was no crawler output" yield quebec_path, output_path, crawl_path, edge_path