コード例 #1
0
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']]
コード例 #2
0
    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
コード例 #3
0
    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()
コード例 #4
0
ファイル: GUIController.py プロジェクト: celeron533/OnkoDICOM
 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()
コード例 #5
0
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
コード例 #6
0
    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()
コード例 #7
0
    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
コード例 #8
0
    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
コード例 #9
0
ファイル: IsodoseTab.py プロジェクト: celeron533/OnkoDICOM
    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)
コード例 #10
0
ファイル: DicomView.py プロジェクト: sjswerdloff/OnkoDICOM
    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()
コード例 #11
0
ファイル: DVHTab.py プロジェクト: sjswerdloff/OnkoDICOM
    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)
コード例 #12
0
    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)
コード例 #13
0
 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)
コード例 #14
0
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")
コード例 #15
0
ファイル: GUIController.py プロジェクト: celeron533/OnkoDICOM
    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()
コード例 #16
0
    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")
コード例 #17
0
ファイル: ImageFusion.py プロジェクト: celeron533/OnkoDICOM
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
コード例 #18
0
ファイル: StructureTab.py プロジェクト: celeron533/OnkoDICOM
 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()
コード例 #19
0
ファイル: IsodoseTab.py プロジェクト: sjswerdloff/OnkoDICOM
    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)
コード例 #20
0
    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
コード例 #21
0
ファイル: Toolbar.py プロジェクト: celeron533/OnkoDICOM
    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)
コード例 #22
0
ファイル: ImageFusion.py プロジェクト: celeron533/OnkoDICOM
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)
コード例 #23
0
    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))
コード例 #24
0
    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
コード例 #25
0
    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)
コード例 #26
0
    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)
コード例 #27
0
    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)
コード例 #28
0
    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)
コード例 #29
0
ファイル: ISO2ROI.py プロジェクト: celeron533/OnkoDICOM
    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
コード例 #30
0
    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