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 __init__(self, progress_callback, interrupt_flag, patient_files, input_path): """ Class initialiser function. :param progress_callback: A signal that receives the current progress of the loading. :param interrupt_flag: A threading.Event() object that tells the function to stop loading. :param patient_files: List of patient files. :param output_path: Path of the input CSV file. """ # Call the parent class super(BatchProcessCSV2ClinicalDataSR, self).__init__(progress_callback, interrupt_flag, patient_files) # Set class variables self.patient_dict_container = PatientDictContainer() self.required_classes = ['ct', 'rtdose'] self.required_classes_2 = ['pet', 'rtdose'] # Only need one of either ct or pet (and rtdose) self.ready = False ready = self.load_images(patient_files, self.required_classes) if ready: self.ready = True else: self.ready = \ self.load_images(patient_files, self.required_classes_2) self.input_path = input_path
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 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) # 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) self.patient_dict_container.set("rois", self.rois) self.patient_dict_container.set("raw_contour", \ dict_raw_contour_data) self.patient_dict_container.set("num_points", \ dict_numpoints) self.patient_dict_container.set("pixluts", dict_pixluts) # Open the main window self.main_window = MainWindow()
def cleanup(self): patient_dict_container = PatientDictContainer() patient_dict_container.clear() # Close 3d vtk widget self.three_dimension_view.close() self.cleanup_image_fusion() self.cleanup_pt_ct_viewer()
class TestSuv2Roi: """ Class to set up the OnkoDICOM main window for testing SUV2ROI functionality. Assumes there is test data containing PET CTAC files, in /test/pt-testdata/. Tests will all fail without this data. """ __test__ = False def __init__(self): # Load test DICOM files desired_path = Path.cwd().joinpath('test', 'pet-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 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) # Create variables to be initialised later self.dicom_files = None self.suv_data = [] # Create SUV2ROI object self.suv2roi = SUV2ROI() # Set patient weight. Not actual weight, just for testing # purposes. self.suv2roi.patient_weight = 70000
def on_loaded_suv2roi(self): """ Called when progress bar has finished. Closes the progress window and refreshes the main screen. """ if self.suv2roi.suv2roi_status: patient_dict_container = PatientDictContainer() self.structures_tab.fixed_container_structure_modified(( patient_dict_container.get('dataset_rtss'), {"draw": None})) else: # Alert user that SUV2ROI failed and for what reason if self.suv2roi.failure_reason == "UNIT": failure_reason = \ "PET units are not Bq/mL. OnkoDICOM can currently only\n" \ "perform SUV2ROI on PET images stored in these units." elif self.suv2roi.failure_reason == "DECY": failure_reason = \ "PET is not decay corrected. OnkoDICOM can currently " \ "only\nperform SUV2ROI on PET images that are decay " \ "corrected." else: failure_reason = "The SUV2ROI process has failed." button_reply = \ QtWidgets.QMessageBox( QtWidgets.QMessageBox.Icon.Warning, "SUV2ROI Failed", failure_reason, QtWidgets.QMessageBox.StandardButton.Ok, self) button_reply.button( QtWidgets.QMessageBox.StandardButton.Ok).setStyleSheet( self.stylesheet) button_reply.exec_() # Close progress window self.suv2roi_progress_window.close()
def __init__(self): # Load test DICOM files desired_path = Path.cwd().joinpath('test', 'pet-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 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) # Create variables to be initialised later self.dicom_files = None self.suv_data = [] # Create SUV2ROI object self.suv2roi = SUV2ROI() # Set patient weight. Not actual weight, just for testing # purposes. self.suv2roi.patient_weight = 70000
def save_clinical_data(self): """ Saves clinical data to a DICOM-SR file. Overwrites any existing clinical data SR files in the dataset. """ # Only save if there is at least one row in the table if self.table_cd.rowCount() <= 0: return # Create string from clinical data dictionary text = "" for key in self.data_dict: text += str(key) + ": " + str(self.data_dict[key]) + "\n" # Create and save DICOM SR file patient_dict_container = PatientDictContainer() file_path = patient_dict_container.path file_path = Path(file_path).joinpath("Clinical-Data-SR.dcm") ds = patient_dict_container.dataset[0] dicom_sr = DICOMStructuredReport.generate_dicom_sr( file_path, ds, text, "CLINICAL-DATA") dicom_sr.save_as(file_path) # Update patient dict container patient_dict_container.dataset['sr-cd'] = dicom_sr patient_dict_container.filepaths['sr-cd'] = file_path
def __init__(self): QtWidgets.QWidget.__init__(self) self.patient_dict_container = PatientDictContainer() self.rx_dose_in_cgray = self.patient_dict_container.get( "rx_dose_in_cgray") self.color_dict = self.init_color_isod() self.color_squares = self.init_color_squares() self.checkboxes = self.init_checkboxes() # Create and initialise ISO2ROI button and layout self.iso2roi_button = QtWidgets.QPushButton() self.iso2roi_button.setText("Convert Isodoses to ROIs") self.iso2roi_button.clicked.connect(self.iso2roi_button_clicked) self.iso2roi_layout = QtWidgets.QHBoxLayout() self.iso2roi_layout.setContentsMargins(0, 0, 0, 0) self.iso2roi_layout.addWidget(self.iso2roi_button) self.isodose_tab_layout = QtWidgets.QVBoxLayout() self.isodose_tab_layout.setAlignment(QtCore.Qt.AlignTop | QtCore.Qt.AlignTop) self.isodose_tab_layout.setSpacing(0) self.init_layout() self.iso2roi = ISO2ROI() # Add button to tab self.isodose_tab_layout.addStretch() self.isodose_tab_layout.addLayout(self.iso2roi_layout) self.setLayout(self.isodose_tab_layout) self.progress_window = ProgressWindow( self, QtCore.Qt.WindowTitleHint | QtCore.Qt.WindowCloseButtonHint) self.progress_window.signal_loaded.connect(self.on_loaded_iso2roi)
def __init__(self, roi_color=None, iso_color=None): QtWidgets.QWidget.__init__(self) self.patient_dict_container = PatientDictContainer() self.iso_color = iso_color self.zoom = 1 self.current_slice_number = None self.dicom_view_layout = QtWidgets.QHBoxLayout() # Create components self.slider = QtWidgets.QSlider(QtCore.Qt.Vertical) self.init_slider() self.view = QtWidgets.QGraphicsView() self.init_view() self.scene = QtWidgets.QGraphicsScene() # Set layout self.dicom_view_layout.addWidget(self.view) self.dicom_view_layout.addWidget(self.slider) self.setLayout(self.dicom_view_layout) # Init metadata widgets self.metadata_layout = QtWidgets.QVBoxLayout(self.view) self.label_image_id = QtWidgets.QLabel() self.label_image_pos = QtWidgets.QLabel() self.label_wl = QtWidgets.QLabel() self.label_image_size = QtWidgets.QLabel() self.label_zoom = QtWidgets.QLabel() self.label_patient_pos = QtWidgets.QLabel() self.init_metadata() self.update_view()
def __init__(self, *args, **kwargs): super(CalculateDVHProgressWindow, self).__init__(*args, **kwargs) layout = QtWidgets.QVBoxLayout() text = QtWidgets.QLabel( "Calculating DVHs... (This may take several minutes)") layout.addWidget(text) self.setWindowTitle("Please wait...") self.setLayout(layout) self.threadpool = QtCore.QThreadPool() self.patient_dict_container = PatientDictContainer() dataset_rtss = self.patient_dict_container.dataset["rtss"] dataset_rtdose = self.patient_dict_container.dataset["rtdose"] rois = self.patient_dict_container.get("rois") dict_thickness = ImageLoading.get_thickness_dict( dataset_rtss, self.patient_dict_container.dataset) interrupt_flag = threading.Event() fork_safe_platforms = ['Linux'] if platform.system() in fork_safe_platforms: worker = Worker(ImageLoading.multi_calc_dvh, dataset_rtss, dataset_rtdose, rois, dict_thickness) else: worker = Worker(ImageLoading.calc_dvhs, dataset_rtss, dataset_rtdose, rois, dict_thickness, interrupt_flag) worker.signals.result.connect(self.dvh_calculated) self.threadpool.start(worker)
def __init__(self): QtWidgets.QWidget.__init__(self) self.patient_dict_container = PatientDictContainer() self.dvh_calculated = self.patient_dict_container.has_attribute( "raw_dvh") self.rt_dose = self.patient_dict_container.dataset['rtdose'] self.raw_dvh = None self.dvh_x_y = None self.plot = None self.selected_rois = self.patient_dict_container.get("selected_rois") self.dvh_tab_layout = QtWidgets.QVBoxLayout() try: # Import the DVH from RT Dose self.import_rtdose() except (AttributeError, KeyError): # Construct the layout based on whether or not the DVH has # already been calculated. # TODO: convert to logging print("DVH data not in RT Dose.") if self.dvh_calculated: self.init_layout_dvh() else: self.init_layout_no_dvh() self.setLayout(self.dvh_tab_layout)
def save_rtss(cls): """ Saves the RT Struct. """ patient_dict_container = PatientDictContainer() rtss_directory = Path(patient_dict_container.get("file_rtss")) patient_dict_container.get("dataset_rtss").save_as(rtss_directory)
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 update_ui(self): # Instantiate a local new PatientDictContainer patient_dict_container = PatientDictContainer() patient = patient_dict_container.get("basic_info") # Compare local patient with previous instance of ImageFusion if self.patient_id != patient['id']: self.update_patient()
def update_patient(self): self.clear_checked_leaves() self.patient_dict_container = PatientDictContainer() self.patient = self.patient_dict_container.get("basic_info") self.patient_id = self.patient['id'] dataset = self.patient_dict_container.dataset[0] self.patient_current_image_series_uid = \ dataset.get("SeriesInstanceUID")
def get_fused_window(level, window): """ Apply windowing on the fixed and moving (linear-registered) images. Args: level(int): the level (midpoint) of windowing window(any): the window (range) of windowing Return: color_axial (QtGui.QPixmap): pixmap of the registered image from axial view color_sagittal (QtGui.QPixmap): pixmap of the registered image from sagittal view color_coronal (QtGui.QPixmap): pixmap of the registered image from coronal view tfm (sitk.CompositeTransform): transformation object containing data that is a product from linear_registration """ patient_dict_container = PatientDictContainer() old_images = patient_dict_container.get("sitk_original") fused_image = patient_dict_container.get("fused_images") tfm = fused_image[1] array = sitk.GetArrayFromImage(old_images).shape axial_slice_count = array[0] coronal_slice_count = array[1] sagittal_slice_count = array[1] sp_plane, _, sp_slice = old_images.GetSpacing() asp = (1.0 * sp_slice) / sp_plane color_axial = {} color_sagittal = {} color_coronal = {} windowing = (int(level - CT_RESCALE_INTERCEPT), int(window)) for i in range(axial_slice_count): color_axial[i] = \ get_fused_pixmap(old_images, fused_image[0], asp, i, "axial", windowing) for i in range(sagittal_slice_count): color_sagittal[i] = \ get_fused_pixmap(old_images, fused_image[0], asp, i, "sagittal", windowing) for i in range(coronal_slice_count): color_coronal[i] = \ get_fused_pixmap(old_images, fused_image[0], asp, i, "coronal", windowing) return color_axial, color_sagittal, color_coronal, tfm
def update_ui(self, moving=False): """ Update the UI of Structure Tab when a new patient is opened """ self.patient_dict_container = PatientDictContainer() self.rois = self.patient_dict_container.get("rois") self.color_dict = self.init_color_roi(self.patient_dict_container) self.patient_dict_container.set("roi_color_dict", self.color_dict) if hasattr(self, "modified_indicator_widget"): self.modified_indicator_widget.setParent(None) self.update_content()
def __init__(self): QtWidgets.QWidget.__init__(self) self.patient_dict_container = PatientDictContainer() self.rx_dose_in_cgray = self.patient_dict_container.get("rx_dose_in_cgray") self.color_dict = self.init_color_isod() self.color_squares = self.init_color_squares() self.checkboxes = self.init_checkboxes() self.isodose_tab_layout = QtWidgets.QVBoxLayout() self.isodose_tab_layout.setAlignment(QtCore.Qt.AlignTop) self.isodose_tab_layout.setSpacing(0) self.init_layout() self.setLayout(self.isodose_tab_layout)
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
def __init__(self, action_handler: ActionHandler): QToolBar.__init__(self) self.action_handler = action_handler self.patient_dict_container = PatientDictContainer() self.setCursor(QCursor(Qt.PointingHandCursor)) self.setMovable(False) self.setFloatable(False) self.setContextMenuPolicy(Qt.PreventContextMenu) # Drop-down list for Windowing button on toolbar self.button_windowing = QToolButton() self.button_windowing.setMenu(self.action_handler.menu_windowing) self.button_windowing.setPopupMode(QToolButton.InstantPopup) self.button_windowing.setIcon(self.action_handler.icon_windowing) # Drop-down list for Export button on toolbar self.button_export = QToolButton() self.button_export.setMenu(self.action_handler.menu_export) self.button_export.setPopupMode(QToolButton.InstantPopup) self.button_export.setIcon(self.action_handler.icon_export) # Spacer for the toolbar spacer = QWidget() spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) spacer.setFocusPolicy(Qt.NoFocus) # Add actions to toolbar self.addAction(self.action_handler.action_open) self.addSeparator() self.addAction(self.action_handler.action_zoom_out) self.addAction(self.action_handler.action_zoom_in) self.addSeparator() self.addWidget(self.button_windowing) self.addSeparator() self.addAction(self.action_handler.action_transect) self.addSeparator() self.addAction(self.action_handler.action_one_view) self.addAction(self.action_handler.action_four_views) self.addAction(self.action_handler.action_show_cut_lines) self.addSeparator() self.addAction(self.action_handler.action_image_fusion) self.addSeparator() self.addAction(self.action_handler.action_add_ons) self.addWidget(spacer) self.addWidget(self.button_export) self.addAction(self.action_handler.action_save_as_anonymous) if self.patient_dict_container.has_modality('rtss'): self.addAction(self.action_handler.action_save_structure)
def create_fused_model(old_images, new_image): """ Performs the image fusion and stores fusion information. Args: old_images(sitk): Image set from Primary/Fixed Image new_image(sitk): Image set from the Secondary/Moving Image """ patient_dict_container = PatientDictContainer() fused_image = register_images(old_images, new_image) patient_dict_container.set("fused_images", fused_image) if fused_image[2]: combined_affine = convert_composite_to_affine_transform(fused_image[1]) affine_matrix = convert_combined_affine_to_matrix(combined_affine) write_transform_to_dcm(affine_matrix)
def batch_iso2roi_handler(self, interrupt_flag, progress_callback, patient): """ Handles creating, starting, and processing the results of batch ISO2ROI. :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. :param patient: The patient to perform this process on. """ # Get current patient files cur_patient_files = \ BatchProcessingController.get_patient_files(patient) # Create and start process process = BatchProcessISO2ROI(progress_callback, interrupt_flag, cur_patient_files) success = process.start() # Add rtss to patient in case it is needed in future # processes if success: if PatientDictContainer().get("rtss_modified"): self.update_rtss(patient) reason = "SUCCESS" else: reason = process.summary # Append process summary if patient not in self.batch_summary[0].keys(): self.batch_summary[0][patient] = {} self.batch_summary[0][patient]["iso2roi"] = reason progress_callback.emit(("Completed ISO2ROI", 100))
def populate_table(self): """ Populates the table with data from the DICOM-SR file, if it exists. """ # Attempt to get clinical data dataset patient_dict_container = PatientDictContainer() try: clinical_data = patient_dict_container.dataset['sr-cd'] # Get text from clinical data dataset text = clinical_data.ContentSequence[0].TextValue # Split text into dictionary text_data = text.splitlines() for row in text_data: key, value = row.split(":") self.data_dict[key] = value except KeyError: # See if data has been imported if self.data_dict: pass else: return # Populate table with loaded values for i, key in enumerate(self.data_dict): attrib = QtWidgets.QTableWidgetItem(key) value = QtWidgets.QTableWidgetItem(self.data_dict[key]) self.table_cd.insertRow(i) self.table_cd.setItem(i, 0, attrib) self.table_cd.setItem(i, 1, value) self.table_populated = True
def onSaveClicked(self): """ Save the new ROI """ # Get the name of the new ROI new_roi_name = self.new_roi_name_line_edit.text() # If the new ROI hasn't been drawn, draw the new ROI. Then if the new # ROI is drawn successfully, proceed to save the new ROI. if self.new_ROI_contours is None: if not self.onDrawButtonClicked(): return # Get a dict to convert SOPInstanceUID to slice id slice_ids_dict = get_dict_slice_to_uid(PatientDictContainer()) # Transform new_ROI_contours to a list of roi information rois_to_save = {} for uid, contour_sequence in self.new_ROI_contours.items(): slider_id = slice_ids_dict[uid] location = self.patient_dict_container.filepaths[slider_id] ds = pydicom.dcmread(location) slice_info = {'coords': contour_sequence, 'ds': ds} rois_to_save[slider_id] = slice_info roi_list = ROI.convert_hull_list_to_contours_data( rois_to_save, self.patient_dict_container) connectSaveROIProgress(self, roi_list, self.dataset_rtss, new_roi_name, self.roi_saved)
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 __init__(self): # Load test DICOM files desired_path = Path.cwd().joinpath('test', 'pet-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 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) # Set additional attributes in patient dict container # (otherwise program will crash and test will fail) self.patient_dict_container.set("existing_rtss_files", []) 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) self.patient_dict_container.set("rois", self.rois) self.patient_dict_container.set("raw_contour", dict_raw_contour_data) self.patient_dict_container.set("num_points", dict_numpoints) self.patient_dict_container.set("pixluts", dict_pixluts) else: img_loader = ImageLoader(selected_files, None, None) img_loader.load_temp_rtss(file_path, DummyProgressWindow, DummyProgressWindow) # Open the main window self.main_window = MainWindow() # Get the initial structure and ROI count self.initial_structure_count = \ self.main_window.structures_tab.layout_content.count() self.initial_roi_count = len(self.main_window.structures_tab.rois)
def setup_ui(self, draw_roi_window_instance, rois, dataset_rtss, signal_roi_drawn): """ this function is responsible for setting up the UI for DrawROIWindow param draw_roi_window_instance: the current drawing window instance. :param rois: the rois to be drawn :param dataset_rtss: the rtss to be written to :param signal_roi_drawn: the signal to be triggered when roi is drawn """ self.patient_dict_container = PatientDictContainer() self.rois = rois self.dataset_rtss = dataset_rtss self.signal_roi_drawn = signal_roi_drawn self.drawn_roi_list = {} self.standard_organ_names = [] self.standard_volume_names = [] self.standard_names = [] # Combination of organ and volume self.ROI_name = None # Selected ROI name self.target_pixel_coords = [] # This will contain the new pixel # coordinates specified by the min and max self.drawingROI = None self.slice_changed = False self.drawing_tool_radius = INITIAL_DRAWING_TOOL_RADIUS self.keep_empty_pixel = False # pixel density self.target_pixel_coords_single_array = [] # 1D array self.draw_roi_window_instance = draw_roi_window_instance self.colour = None self.ds = None self.zoom = 1.0 self.upper_limit = None self.lower_limit = None # is_four_view is set to True to stop the SUV2ROI button from appearing self.dicom_view = DicomAxialView(is_four_view=True) self.current_slice = self.dicom_view.slider.value() self.dicom_view.slider.valueChanged.connect(self.slider_value_changed) self.init_layout() QtCore.QMetaObject.connectSlotsByName(draw_roi_window_instance)
def calculate_isodose_boundaries(self, isodose_levels): """ Calculates isodose boundaries for each isodose level. :return: coutours, a list containing the countours for each isodose level. """ # Initialise variables needed to find isodose levels patient_dict_container = PatientDictContainer() pixmaps = patient_dict_container.get("pixmaps_axial") slider_min = 0 slider_max = len(pixmaps) rt_plan_dose = patient_dict_container.dataset['rtdose'] rt_dose_dose = patient_dict_container.get("rx_dose_in_cgray") # If rt_dose_dose does not exist, return None if not rt_dose_dose: return None contours = {} for item in isodose_levels: # Calculate boundaries for each isodose level for each slice contours[item] = [] for slider_id in range(slider_min, slider_max): contours[item].append([]) temp_ds = patient_dict_container.dataset[slider_id] z = temp_ds.ImagePositionPatient[2] grid = get_dose_grid(rt_plan_dose, float(z)) if not (grid == []): if isodose_levels[item][0]: dose_level = isodose_levels[item][1] / \ (rt_plan_dose.DoseGridScaling * 100) contours[item][slider_id] =\ (measure.find_contours(grid, dose_level)) else: dose_level = isodose_levels[item][1] * \ rt_dose_dose / \ (rt_plan_dose.DoseGridScaling * 10000) contours[item][slider_id] = \ (measure.find_contours(grid, dose_level)) # Return list of contours for each isodose level for each slice return contours
def calculate_contours(self): """ Calculate SUV boundaries for each slice from an SUV value of 1 all the way to the maximum SUV value in that slice. :return: Dictionary where key is SUV ROI name and value is a list containing tuples of slice id and lists of contours. """ # Create dictionary to store contour data contour_data = {} # Initialise variables needed for function patient_dict_container = PatientDictContainer() slider_min = 0 slider_max = len(patient_dict_container.get("pixmaps_axial")) # Loop through each PET image in the dataset for slider_id in range(slider_min, slider_max): # Get SUV data from PET file temp_ds = patient_dict_container.dataset[slider_id] suv_data = self.pet2suv(temp_ds) # Return None if PET 2 SUV failed if suv_data is None: return None # Set current and max SUV for the current slice current_suv = 1 max_suv = numpy.amax(suv_data) # Continue calculating SUV contours for the slice until the # max SUV has been reached. while current_suv < max_suv: # Find the contours for the SUV (i) contours = measure.find_contours(suv_data, current_suv) # Get the SUV name name = "SUV-" + str(current_suv) if name not in contour_data: contour_data[name] = [] contour_data[name].append((slider_id, contours)) current_suv += 1 # Return contour data return contour_data