def test_create_roi(): rt_ss = dataset.Dataset() rt_ss.StructureSetROISequence = [] rt_ss.StructureSetROISequence.append(dataset.Dataset()) rt_ss.StructureSetROISequence[0].ReferencedFrameOfReferenceUID = "1.2.3" rt_ss.StructureSetROISequence[0].ROINumber = "1" rt_ss.ROIContourSequence = [] rt_ss.RTROIObservationsSequence = [] roi_name = "NewTestROI" roi_coordinates = [0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0] # a closed right triangle image_ds = dataset.Dataset() image_ds.SOPClassUID = "1.2.840.10008.5.1.4.1.1.2" image_ds.SOPInstanceUID = "1.2.3.4.5.6.7.8.9" patient_dict_container = PatientDictContainer() # container has to be initialised with kwargs content for the get/set to not fail for lack of an # "additional_parameters" dict. patient_dict_container.set_initial_values(None, None, None, blah="blah", rois={}) if patient_dict_container.get("rois") is not None: print("rois are present in patient dict container") updated_rtss = create_roi(rt_ss, roi_name, roi_coordinates, image_ds) first_contour = updated_rtss.ROIContourSequence[0].ContourSequence[0] assert (first_contour.ContourImageSequence[0].ReferencedSOPClassUID == image_ds.SOPClassUID) assert (first_contour.ContourGeometricType == "CLOSED_PLANAR") assert (rt_ss.RTROIObservationsSequence[0].RTROIInterpretedType == "ORGAN")
def __init__(self): # Load test DICOM files desired_path = Path.cwd().joinpath('test', 'testdata') selected_files = find_DICOM_files(desired_path) # list of DICOM test files file_path = os.path.dirname(os.path.commonprefix(selected_files)) # file path of DICOM files read_data_dict, file_names_dict = ImageLoading.get_datasets(selected_files) # Create patient dict container object patient_dict_container = PatientDictContainer() patient_dict_container.clear() patient_dict_container.set_initial_values(file_path, read_data_dict, file_names_dict) # Set additional attributes in patient dict container (otherwise program will crash and test will fail) if "rtss" in file_names_dict: dataset_rtss = dcmread(file_names_dict['rtss']) self.rois = ImageLoading.get_roi_info(dataset_rtss) dict_raw_contour_data, dict_numpoints = ImageLoading.get_raw_contour_data(dataset_rtss) dict_pixluts = ImageLoading.get_pixluts(read_data_dict) patient_dict_container.set("rois", self.rois) patient_dict_container.set("raw_contour", dict_raw_contour_data) patient_dict_container.set("num_points", dict_numpoints) patient_dict_container.set("pixluts", dict_pixluts) # Open the main window self.main_window = MainWindow()
def __init__(self): # Load test DICOM files and set path variable path = Path.cwd().joinpath('test', 'testdata') files = get_dicom_files(path) # list of DICOM test files file_path = os.path.dirname(os.path.commonprefix(files)) read_data_dict, file_names_dict = ImageLoading.get_datasets(files) # Create patient dict container object patient_dict_container = PatientDictContainer() patient_dict_container.clear() patient_dict_container.set_initial_values(file_path, read_data_dict, file_names_dict) # Set additional attributes in patient dict container # This prevents crashes if "rtss" in file_names_dict: dataset_rtss = dcmread(file_names_dict['rtss']) self.rois = ImageLoading.get_roi_info(dataset_rtss) patient_dict_container.set("rois", self.rois) # Open the main window self.main_window = MainWindow() self.main_window.right_panel.setCurrentWidget( self.main_window.dicom_tree) self.dicom_tree = self.main_window.dicom_tree
class TestClinicalDataView: """ Class to set up variables required for testing the Clinical Data view. """ __test__ = False def __init__(self): # Load test DICOM files desired_path = Path.cwd().joinpath('test', 'testdata') # list of DICOM test files selected_files = find_DICOM_files(desired_path) # file path of DICOM files self.file_path = os.path.dirname(os.path.commonprefix(selected_files)) read_data_dict, file_names_dict = \ ImageLoading.get_datasets(selected_files) # Create patient dict container object self.patient_dict_container = PatientDictContainer() self.patient_dict_container.clear() self.patient_dict_container.set_initial_values(self.file_path, read_data_dict, file_names_dict) self.file_path = self.patient_dict_container.path self.file_path = Path(self.file_path).joinpath("Clinical-Data-SR.dcm") # Test data to write self.data = [['123456789', 'Jim', 'Jimson']]
def test_save_radiomics_data(): """ Test for saving pyradiomics data to a DICOM SR file. """ # Get test data files # Load test DICOM files desired_path = Path.cwd().joinpath('test', 'testdata') # list of DICOM test files selected_files = find_DICOM_files(desired_path) # file path of DICOM files file_path = os.path.dirname(os.path.commonprefix(selected_files)) read_data_dict, file_names_dict = \ ImageLoading.get_datasets(selected_files) # Create patient dict container object patient_dict_container = PatientDictContainer() patient_dict_container.clear() patient_dict_container.set_initial_values(file_path, read_data_dict, file_names_dict) file_path = patient_dict_container.path file_path = Path(file_path).joinpath("PyRadiomics-SR.dcm") ds = patient_dict_container.dataset[0] dicom_sr = DICOMStructuredReport.generate_dicom_sr(file_path, ds, "text", "PYRADIOMICS") dicom_sr.save_as(file_path) # Assert that the new SR exists assert os.path.isfile(file_path) # Delete the created DICOM SR os.remove(file_path)
def __init__(self): # Load test DICOM files if platform.system() == "Windows": desired_path = "\\testdata\\DICOM-RT-TEST" elif platform.system() == "Linux" or platform.system() == "Darwin": desired_path = "/testdata/DICOM-RT-TEST" desired_path = os.path.dirname( os.path.realpath(__file__)) + desired_path selected_files = find_DICOM_files( desired_path) # list of DICOM test files file_path = os.path.dirname( os.path.commonprefix(selected_files)) # file path of DICOM files read_data_dict, file_names_dict = ImageLoading.get_datasets( selected_files) # Create patient dict container object patient_dict_container = PatientDictContainer() patient_dict_container.clear() patient_dict_container.set_initial_values(file_path, read_data_dict, file_names_dict) # Set additional attributes in patient dict container (otherwise program will crash and test will fail) if "rtss" in file_names_dict: dataset_rtss = dcmread(file_names_dict['rtss']) self.rois = ImageLoading.get_roi_info(dataset_rtss) dict_raw_contour_data, dict_numpoints = ImageLoading.get_raw_contour_data( dataset_rtss) dict_pixluts = ImageLoading.get_pixluts(read_data_dict) patient_dict_container.set("rois", self.rois) patient_dict_container.set("raw_contour", dict_raw_contour_data) patient_dict_container.set("num_points", dict_numpoints) patient_dict_container.set("pixluts", dict_pixluts) # Open the main window self.main_window = MainWindow() self.main_window.show() self.dicom_view = self.main_window.dicom_view self.new_polygons = {} slider_id = self.dicom_view.slider.value() self.curr_slice = self.dicom_view.patient_dict_container.get( "dict_uid")[slider_id]
def test_add_to_roi(): rt_ss = dataset.Dataset() rt_ss.StructureSetROISequence = [] rt_ss.StructureSetROISequence.append(dataset.Dataset()) rt_ss.StructureSetROISequence[0].ReferencedFrameOfReferenceUID = "1.2.3" rt_ss.StructureSetROISequence[0].ROINumber = "1" rt_ss.StructureSetROISequence[0].ROIName = "NewTestROI" rt_ss.ROIContourSequence = [] rt_ss.RTROIObservationsSequence = [] roi_name = "NewTestROI" roi_coordinates = [0, 0, 0, 0, 1, 0, 1, 0, 0] # a right triangle image_ds = dataset.Dataset() image_ds.SOPClassUID = "1.2.840.10008.5.1.4.1.1.2" image_ds.SOPInstanceUID = "1.2.3.4.5.6.7.8.9" patient_dict_container = PatientDictContainer() # container has to be initialised with kwargs content # for the get/set to not fail for lack of an "additional_parameters" dict. patient_dict_container.set_initial_values(None, None, None, blah="blah", rois={}) if patient_dict_container.get("rois") is not None: print("rois are present in patient dict container") updated_rtss = create_roi(rt_ss, roi_name, [{'coords': roi_coordinates, 'ds': image_ds}]) # clearly the above is an opportunity to factor out to a fixture or similar rtss_with_added_roi = add_to_roi(updated_rtss, roi_name, roi_coordinates, image_ds) first_contour = rtss_with_added_roi.ROIContourSequence[0].\ ContourSequence[0] second_contour = rtss_with_added_roi.ROIContourSequence[0].\ ContourSequence[1] assert ( second_contour .ContourImageSequence[0] .ReferencedSOPClassUID == image_ds.SOPClassUID ) assert(first_contour.ContourGeometricType == "OPEN_PLANAR") assert (second_contour.ContourGeometricType == "OPEN_PLANAR")
class TestDvh2RtDose: """ This class is to set up data and variables needed for the DVH2RTDOSE functionality. """ __test__ = False def __init__(self): self.dvh_data = None # Load test DICOM files desired_path = Path.cwd().joinpath('test', 'testdata') selected_files = find_DICOM_files(desired_path) file_path = os.path.dirname(os.path.commonprefix(selected_files)) read_data_dict, file_names_dict = \ ImageLoading.get_datasets(selected_files) # Create patient dict container object self.patient_dict_container = PatientDictContainer() self.patient_dict_container.clear() self.patient_dict_container.set_initial_values(file_path, read_data_dict, file_names_dict)
def load(self, interrupt_flag, progress_callback): """ :param interrupt_flag: A threading.Event() object that tells the function to stop loading. :param progress_callback: A signal that receives the current progress of the loading. :return: PatientDictContainer object containing all values related to the loaded DICOM files. """ progress_callback.emit(("Creating datasets...", 0)) try: path = os.path.dirname(os.path.commonprefix(self.selected_files)) # Gets the common root folder. read_data_dict, file_names_dict = ImageLoading.get_datasets(self.selected_files) except ImageLoading.NotAllowedClassError: raise ImageLoading.NotAllowedClassError # Populate the initial values in the PatientDictContainer singleton. patient_dict_container = PatientDictContainer() patient_dict_container.clear() patient_dict_container.set_initial_values(path, read_data_dict, file_names_dict) # As there is no way to interrupt a QRunnable, this method must check after every step whether or not the # interrupt flag has been set, in which case it will interrupt this method after the currently processing # function has finished running. It's not very pretty, and the thread will still run some functions for, in some # cases, up to a couple seconds after the close button on the Progress Window has been clicked, however it's # the best solution I could come up with. If you have a cleaner alternative, please make your contribution. if interrupt_flag.is_set(): print("stopped") return False if 'rtss' in file_names_dict and 'rtdose' in file_names_dict: self.parent_window.signal_advise_calc_dvh.connect(self.update_calc_dvh) self.signal_request_calc_dvh.emit() while not self.advised_calc_dvh: pass if 'rtss' in file_names_dict: dataset_rtss = dcmread(file_names_dict['rtss']) progress_callback.emit(("Getting ROI info...", 10)) rois = ImageLoading.get_roi_info(dataset_rtss) if interrupt_flag.is_set(): # Stop loading. print("stopped") return False progress_callback.emit(("Getting contour data...", 30)) dict_raw_contour_data, dict_numpoints = ImageLoading.get_raw_contour_data(dataset_rtss) # Determine which ROIs are one slice thick dict_thickness = ImageLoading.get_thickness_dict(dataset_rtss, read_data_dict) if interrupt_flag.is_set(): # Stop loading. print("stopped") return False progress_callback.emit(("Getting pixel LUTs...", 50)) dict_pixluts = ImageLoading.get_pixluts(read_data_dict) if interrupt_flag.is_set(): # Stop loading. print("stopped") return False # Add RTSS values to PatientDictContainer patient_dict_container.set("rois", rois) patient_dict_container.set("raw_contour", dict_raw_contour_data) patient_dict_container.set("num_points", dict_numpoints) patient_dict_container.set("pixluts", dict_pixluts) if 'rtdose' in file_names_dict and self.calc_dvh: dataset_rtdose = dcmread(file_names_dict['rtdose']) # Spawn-based platforms (i.e Windows and MacOS) have a large overhead when creating a new process, which # ends up making multiprocessing on these platforms more expensive than linear calculation. As such, # multiprocessing is only available on Linux until a better solution is found. fork_safe_platforms = ['Linux'] if platform.system() in fork_safe_platforms: progress_callback.emit(("Calculating DVHs...", 60)) raw_dvh = ImageLoading.multi_calc_dvh(dataset_rtss, dataset_rtdose, rois, dict_thickness) else: progress_callback.emit(("Calculating DVHs... (This may take a while)", 60)) raw_dvh = ImageLoading.calc_dvhs(dataset_rtss, dataset_rtdose, rois, dict_thickness, interrupt_flag) if interrupt_flag.is_set(): # Stop loading. print("stopped") return False progress_callback.emit(("Converging to zero...", 80)) dvh_x_y = ImageLoading.converge_to_0_dvh(raw_dvh) if interrupt_flag.is_set(): # Stop loading. print("stopped") return False # Add DVH values to PatientDictContainer patient_dict_container.set("raw_dvh", raw_dvh) patient_dict_container.set("dvh_x_y", dvh_x_y) patient_dict_container.set("dvh_outdated", False) return True else: return True return True
def load_images(cls, patient_files, required_classes): """ Loads required datasets for the selected patient. :param patient_files: dictionary of classes and patient files. :param required_classes: list of classes required for the selected/current process. :return: True if all required datasets found, false otherwise. """ files = [] found_classes = set() # Loop through each item in patient_files for key, value in patient_files.items(): # If the item is an allowed class if key in cls.allowed_classes: for i in range(len(value)): # Add item's files to the files list files.extend(value[i].get_files()) # Get the modality name modality_name = cls.allowed_classes.get(key).get('name') # If the modality name is not found_classes, add it if modality_name not in found_classes \ and modality_name in required_classes: found_classes.add(modality_name) # Get the difference between required classes and found classes class_diff = set(required_classes).difference(found_classes) # If the dataset is missing required files, pass on it if len(class_diff) > 0: print("Skipping dataset. Missing required file(s) {}".format( class_diff)) return False # Try to get the datasets from the selected files try: # Convert paths to a common file system representation for i, file in enumerate(files): files[i] = Path(file).as_posix() read_data_dict, file_names_dict = cls.get_datasets(files) path = os.path.dirname( os.path.commonprefix(list(file_names_dict.values()))) # Otherwise raise an exception (OnkoDICOM does not support the # selected file type) except ImageLoading.NotAllowedClassError: raise ImageLoading.NotAllowedClassError # Populate the initial values in the PatientDictContainer patient_dict_container = PatientDictContainer() patient_dict_container.clear() patient_dict_container.set_initial_values(path, read_data_dict, file_names_dict) # If an RT Struct is included, set relevant values in the # PatientDictContainer if 'rtss' in file_names_dict: dataset_rtss = dcmread(file_names_dict['rtss']) rois = ImageLoading.get_roi_info(dataset_rtss) dict_raw_contour_data, dict_numpoints = \ ImageLoading.get_raw_contour_data(dataset_rtss) dict_pixluts = ImageLoading.get_pixluts(read_data_dict) # Add RT Struct values to PatientDictContainer patient_dict_container.set("rois", rois) patient_dict_container.set("raw_contour", dict_raw_contour_data) patient_dict_container.set("num_points", dict_numpoints) patient_dict_container.set("pixluts", dict_pixluts) return True