示例#1
0
class Toolbar(QToolBar):

    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)
示例#2
0
class MenuBar(QtWidgets.QMenuBar):
    def __init__(self, action_handler: ActionHandler):
        QtWidgets.QMenuBar.__init__(self)
        self.action_handler = action_handler
        self.patient_dict_container = PatientDictContainer()
        self.setGeometry(QtCore.QRect(0, 0, 901, 35))
        self.setContextMenuPolicy(Qt.PreventContextMenu)

        # Menu Bar: File, Tools, Export, Help
        self.menu_file = QtWidgets.QMenu()
        self.menu_file.setTitle("File")
        self.addMenu(self.menu_file)

        self.menu_tools = QtWidgets.QMenu()
        self.menu_tools.setTitle("Tools")
        self.addMenu(self.menu_tools)

        self.addMenu(self.action_handler.menu_export)

        # Help button opens OnkoDICOM website
        self.action_help = QtWidgets.QAction()
        self.action_help.setText("Help")
        self.action_help.triggered.connect(
            lambda: webbrowser.open("https://onkodicom.com.au/"))

        self.addAction(self.action_help)

        # Add actions to File menu
        self.menu_file.addAction(self.action_handler.action_open)
        self.menu_file.addSeparator()
        if self.patient_dict_container.has_modality('rtss'):
            self.menu_file.addAction(self.action_handler.action_save_structure)
        self.menu_file.addAction(self.action_handler.action_save_as_anonymous)
        self.menu_file.addSeparator()
        self.menu_file.addAction(self.action_handler.action_exit)

        # Add actions to Tool menu
        self.menu_tools.addAction(self.action_handler.action_zoom_in)
        self.menu_tools.addAction(self.action_handler.action_zoom_out)
        self.menu_tools.addSeparator()
        self.menu_tools.addMenu(self.action_handler.menu_windowing)
        self.menu_tools.addSeparator()
        self.menu_tools.addAction(self.action_handler.action_transect)
        self.menu_tools.addSeparator()
        self.menu_tools.addAction(self.action_handler.action_add_ons)
示例#3
0
    def setup_central_widget(self):
        patient_dict_container = PatientDictContainer()
        self.central_widget = QtWidgets.QWidget()
        self.central_widget_layout = QtWidgets.QVBoxLayout()

        self.patient_bar = PatientBar()

        splitter = QtWidgets.QSplitter(QtCore.Qt.Horizontal)

        # Left panel contains stuctures tab, isodoses tab, and structure information
        self.left_panel = QtWidgets.QTabWidget()
        self.left_panel.setMinimumWidth(300)
        self.left_panel.setMaximumWidth(500)

        # Add structures tab to left panel
        if patient_dict_container.has_modality("rtss"):
            self.structures_tab = StructureTab()
            self.structures_tab.request_update_structures.connect(self.update_views)
            self.left_panel.addTab(self.structures_tab, "Structures")

        if patient_dict_container.has_modality("rtdose"):
            self.isodoses_tab = IsodoseTab()
            self.isodoses_tab.request_update_isodoses.connect(self.update_views)
            self.left_panel.addTab(self.isodoses_tab, "Isodoses")

        # Hide left panel if no rtss or rtdose
        if not patient_dict_container.has_modality("rtss") and not patient_dict_container.has_modality("rtdose"):
            self.left_panel.hide()

        # Right panel contains the different tabs of DICOM view, DVH, clinical data, DICOM tree
        self.right_panel = QtWidgets.QTabWidget()

        # Add DICOM view to right panel as a tab
        roi_color_dict = self.structures_tab.color_dict if hasattr(self, 'structures_tab') else None
        iso_color_dict = self.isodoses_tab.color_dict if hasattr(self, 'isodoses_tab') else None
        self.dicom_view = DicomView(roi_color=roi_color_dict, iso_color=iso_color_dict)
        self.right_panel.addTab(self.dicom_view, "DICOM View")

        # Add DVH tab to right panel as a tab
        if patient_dict_container.has_modality("rtss") and patient_dict_container.has_modality("rtdose"):
            self.dvh_tab = DVHTab()
            self.right_panel.addTab(self.dvh_tab, "DVH")

        self.dicom_tree = DicomTreeView()
        self.right_panel.addTab(self.dicom_tree, "DICOM Tree")

        # Create Clinical Data tab
        # TODO refactor the entire Clinical Data form/display class
        # As they currently stand, they are given the right tab widget, and make direct modifications to the tab.
        # This class should be refactored in the same way as the rest of the main window's components, i.e. the Clinical
        # Data should be a child of QWidget that can exist independently of OnkoDICOM. This class would differ from most
        # other main window components in that rather than interacting with the PatientDictContainer as its model, it
        # would use the patient's ClinicalData csv file as the model (which means that the QWidget would theoretically
        # easily exist outside OnkoDICOM).
        # There are two classes: one for displaying the clinical data, and another for modifying the clinical data.
        # The check below determines whether there already exists a clinical data csv for the patient, and loads either
        # the data display or the data form depending on what exists.
        reg = '/CSV/ClinicalData*[.csv]'
        if not glob.glob(patient_dict_container.path + reg):
            self.call_class.display_cd_form(self.right_panel, patient_dict_container.path)
        else:
            self.call_class.display_cd_dat(self.right_panel, patient_dict_container.path)

        splitter.addWidget(self.left_panel)
        splitter.addWidget(self.right_panel)

        # Create footer
        self.footer = QtWidgets.QWidget()
        self.create_footer()

        # Set layout
        self.central_widget_layout.addWidget(self.patient_bar)
        self.central_widget_layout.addWidget(splitter)
        self.central_widget_layout.addWidget(self.footer)

        self.central_widget.setLayout(self.central_widget_layout)
        self.main_window_instance.setCentralWidget(self.central_widget)
示例#4
0
def create_initial_model():
    """
    This function initializes all the attributes in the PatientDictContainer model required for the operation of the
    main window. This should be called before the main window's components are constructed, but after the initial
    values of the PatientDictContainer instance are set (i.e. dataset and filepaths).
    """
    ##############################
    #  LOAD PATIENT INFORMATION  #
    ##############################
    patient_dict_container = PatientDictContainer()

    dataset = patient_dict_container.dataset
    filepaths = patient_dict_container.filepaths
    patient_dict_container.set("rtss_modified", False)

    if ('WindowWidth' in dataset[0]):
        if isinstance(dataset[0].WindowWidth, pydicom.valuerep.DSfloat):
            window = int(dataset[0].WindowWidth)
        elif isinstance(dataset[0].WindowWidth, pydicom.multival.MultiValue):
            window = int(dataset[0].WindowWidth[1])
    else:
        window = int(400)

    if ('WindowCenter' in dataset[0]):
        if isinstance(dataset[0].WindowCenter, pydicom.valuerep.DSfloat):
            level = int(dataset[0].WindowCenter)
        elif isinstance(dataset[0].WindowCenter, pydicom.multival.MultiValue):
            level = int(dataset[0].WindowCenter[1])
    else:
        level = int(800)

    patient_dict_container.set("window", window)
    patient_dict_container.set("level", level)

    # Check to see if the imageWindowing.csv file exists
    if os.path.exists(resource_path('data/csv/imageWindowing.csv')):
        # If it exists, read data from file into the self.dict_windowing variable
        dict_windowing = {}
        with open(resource_path('data/csv/imageWindowing.csv'),
                  "r") as fileInput:
            next(fileInput)
            dict_windowing["Normal"] = [window, level]
            for row in fileInput:
                # Format: Organ - Scan - Window - Level
                items = [item for item in row.split(',')]
                dict_windowing[items[0]] = [int(items[2]), int(items[3])]
    else:
        # If csv does not exist, initialize dictionary with default values
        dict_windowing = {
            "Normal": [window, level],
            "Lung": [1600, -300],
            "Bone": [1400, 700],
            "Brain": [160, 950],
            "Soft Tissue": [400, 800],
            "Head and Neck": [275, 900]
        }

    patient_dict_container.set("dict_windowing", dict_windowing)

    pixel_values = convert_raw_data(dataset)
    pixmaps = get_pixmaps(pixel_values, window, level)
    patient_dict_container.set("pixmaps", pixmaps)
    patient_dict_container.set("pixel_values", pixel_values)

    basic_info = get_basic_info(dataset[0])
    patient_dict_container.set("basic_info", basic_info)

    patient_dict_container.set("dict_uid", dict_instanceUID(dataset))

    # Set RTSS attributes
    if patient_dict_container.has_modality("rtss"):
        patient_dict_container.set("file_rtss", filepaths['rtss'])
        patient_dict_container.set("dataset_rtss", dataset['rtss'])

        dicom_tree_rtss = DicomTree(filepaths['rtss'])
        patient_dict_container.set("dict_dicom_tree_rtss",
                                   dicom_tree_rtss.dict)

        patient_dict_container.set(
            "list_roi_numbers",
            ordered_list_rois(patient_dict_container.get("rois")))
        patient_dict_container.set("selected_rois", [])

        patient_dict_container.set("dict_polygons", {})

    # Set RTDOSE attributes
    if patient_dict_container.has_modality("rtdose"):
        dicom_tree_rtdose = DicomTree(filepaths['rtdose'])
        patient_dict_container.set("dict_dicom_tree_rtdose",
                                   dicom_tree_rtdose.dict)

        patient_dict_container.set("dose_pixluts", get_dose_pixluts(dataset))

        patient_dict_container.set("selected_doses", [])
        patient_dict_container.set(
            "rx_dose_in_cgray",
            1)  # This will be overwritten if an RTPLAN is present.

    # Set RTPLAN attributes
    if patient_dict_container.has_modality("rtplan"):
        # the TargetPrescriptionDose is type 3 (optional), so it may not be there
        # However, it is preferable to the sum of the beam doses
        # DoseReferenceStructureType is type 1 (value is mandatory),
        # but it can have a value of ORGAN_AT_RISK rather than TARGET
        # in which case there will *not* be a TargetPrescriptionDose
        # and even if it is TARGET, that's no guarantee that TargetPrescriptionDose
        # will be encoded and have a value
        rx_dose_in_cgray = calculate_rx_dose_in_cgray(dataset["rtplan"])
        patient_dict_container.set("rx_dose_in_cgray", rx_dose_in_cgray)

        dicom_tree_rtplan = DicomTree(filepaths['rtplan'])
        patient_dict_container.set("dict_dicom_tree_rtplan",
                                   dicom_tree_rtplan.dict)
示例#5
0
    def setup_ui(self, main_window_instance):
        self.main_window_instance = main_window_instance
        self.call_class = MainPageCallClass()
        self.add_on_options_controller = AddOptions(self)
        patient_dict_container = PatientDictContainer()

        ##########################################
        #  IMPLEMENTATION OF THE MAIN PAGE VIEW  #
        ##########################################
        if platform.system() == 'Darwin':
            self.stylesheet_path = "src/res/stylesheet.qss"
        else:
            self.stylesheet_path = "src/res/stylesheet-win-linux.qss"
        stylesheet = open(resource_path(self.stylesheet_path)).read()
        window_icon = QIcon()
        window_icon.addPixmap(
            QPixmap(resource_path("src/res/images/icon.ico")), QIcon.Normal,
            QIcon.Off)
        self.main_window_instance.setMinimumSize(1080, 700)
        self.main_window_instance.setObjectName("MainOnkoDicomWindowInstance")
        self.main_window_instance.setWindowIcon(window_icon)
        self.main_window_instance.setStyleSheet(stylesheet)

        self.central_widget = QtWidgets.QWidget()
        self.central_widget_layout = QtWidgets.QVBoxLayout()

        self.patient_bar = PatientBar()

        splitter = QtWidgets.QSplitter(QtCore.Qt.Horizontal)

        # Left panel contains stuctures tab, isodoses tab, and structure information
        self.left_panel = QtWidgets.QTabWidget()
        self.left_panel.setMinimumWidth(300)
        self.left_panel.setMaximumWidth(500)

        # Add structures tab to left panel
        if patient_dict_container.has_modality("rtss"):
            self.structures_tab = StructureTab()
            self.structures_tab.request_update_structures.connect(
                self.update_views)
            self.left_panel.addTab(self.structures_tab, "Structures")

        if patient_dict_container.has_modality("rtdose"):
            self.isodoses_tab = IsodoseTab()
            self.isodoses_tab.request_update_isodoses.connect(
                self.update_views)
            self.left_panel.addTab(self.isodoses_tab, "Isodoses")

        # Hide left panel if no rtss or rtdose
        if not patient_dict_container.has_modality(
                "rtss") and not patient_dict_container.has_modality("rtdose"):
            self.left_panel.hide()

        # Right panel contains the different tabs of DICOM view, DVH, clinical data, DICOM tree
        self.right_panel = QtWidgets.QTabWidget()

        # Add DICOM view to right panel as a tab
        roi_color_dict = self.structures_tab.color_dict if hasattr(
            self, 'structures_tab') else None
        iso_color_dict = self.isodoses_tab.color_dict if hasattr(
            self, 'isodoses_tab') else None
        self.dicom_view = DicomView(roi_color=roi_color_dict,
                                    iso_color=iso_color_dict)
        self.right_panel.addTab(self.dicom_view, "DICOM View")

        # Add DVH tab to right panel as a tab
        if patient_dict_container.has_modality(
                "rtss") and patient_dict_container.has_modality("rtdose"):
            self.dvh_tab = DVHTab()
            self.right_panel.addTab(self.dvh_tab, "DVH")

        self.dicom_tree = DicomTreeView()
        self.right_panel.addTab(self.dicom_tree, "DICOM Tree")

        # Create Clinical Data tab
        # TODO refactor the entire Clinical Data form/display class
        # As they currently stand, they are given the right tab widget, and make direct modifications to the tab.
        # This class should be refactored in the same way as the rest of the main window's components, i.e. the Clinical
        # Data should be a child of QWidget that can exist independently of OnkoDICOM. This class would differ from most
        # other main window components in that rather than interacting with the PatientDictContainer as its model, it
        # would use the patient's ClinicalData csv file as the model (which means that the QWidget would theoretically
        # easily exist outside OnkoDICOM).
        # There are two classes: one for displaying the clinical data, and another for modifying the clinical data.
        # The check below determines whether there already exists a clinical data csv for the patient, and loads either
        # the data display or the data form depending on what exists.
        reg = '/CSV/ClinicalData*[.csv]'
        if not glob.glob(patient_dict_container.path + reg):
            self.call_class.display_cd_form(self.right_panel,
                                            patient_dict_container.path)
        else:
            self.call_class.display_cd_dat(self.right_panel,
                                           patient_dict_container.path)

        splitter.addWidget(self.left_panel)
        splitter.addWidget(self.right_panel)

        # Create footer
        self.footer = QtWidgets.QWidget()
        self.create_footer()

        # Set layout
        self.central_widget_layout.addWidget(self.patient_bar)
        self.central_widget_layout.addWidget(splitter)
        self.central_widget_layout.addWidget(self.footer)

        self.central_widget.setLayout(self.central_widget_layout)
        self.main_window_instance.setCentralWidget(self.central_widget)

        # Create actions and set menu and tool bars
        self.action_handler = ActionHandler(self)
        self.menubar = MenuBar(self.action_handler)
        self.main_window_instance.setMenuBar(self.menubar)
        self.toolbar = Toolbar(self.action_handler)
        self.main_window_instance.addToolBar(QtCore.Qt.TopToolBarArea,
                                             self.toolbar)
        self.main_window_instance.setWindowTitle("OnkoDICOM")
示例#6
0
class StructureTab(QtWidgets.QWidget):

    request_update_structures = QtCore.pyqtSignal()

    def __init__(self):
        QtWidgets.QWidget.__init__(self)
        self.patient_dict_container = PatientDictContainer()
        self.rois = self.patient_dict_container.get("rois")
        self.color_dict = self.init_color_roi()
        self.patient_dict_container.set("roi_color_dict", self.color_dict)

        self.structure_tab_layout = QtWidgets.QVBoxLayout()

        self.roi_delete_handler = ROIDelOption(self.structure_modified)
        self.roi_draw_handler = ROIDrawOption(self.structure_modified)

        # Create scrolling area widget to contain the content.
        self.scroll_area = QtWidgets.QScrollArea()
        self.scroll_area.setWidgetResizable(True)

        self.scroll_area_content = QtWidgets.QWidget(self.scroll_area)
        self.scroll_area.ensureWidgetVisible(self.scroll_area_content)

        # Create layout for checkboxes and colour squares
        self.layout_content = QtWidgets.QVBoxLayout(self.scroll_area_content)
        self.layout_content.setContentsMargins(0, 0, 0, 0)
        self.layout_content.setSpacing(0)
        self.layout_content.setAlignment(QtCore.Qt.AlignTop)

        # Create list of standard organ and volume names
        self.standard_organ_names = []
        self.standard_volume_names = []
        self.init_standard_names()

        # Create StructureWidget objects
        self.update_content()

        # Create ROI manipulation buttons
        self.button_roi_draw = QtWidgets.QPushButton()
        self.button_roi_delete = QtWidgets.QPushButton()
        self.roi_buttons = QtWidgets.QWidget()
        self.init_roi_buttons()

        # Set layout
        self.structure_tab_layout.addWidget(self.scroll_area)
        self.structure_tab_layout.addWidget(self.roi_buttons)
        self.setLayout(self.structure_tab_layout)

    def init_color_roi(self):
        """
        Create a dictionary containing the colors for each structure.
        :return: Dictionary where the key is the ROI number and the value a QColor object.
        """
        roi_color = dict()

        roi_contour_info = self.patient_dict_container.get(
            "dict_dicom_tree_rtss")['ROI Contour Sequence']

        if len(roi_contour_info) > 0:
            for item, roi_dict in roi_contour_info.items():
                # Note: the keys of roiContourInfo are "item 0", "item 1", etc.
                # As all the ROI structures are identified by the ROI numbers in the whole code,
                # we get the ROI number 'roi_id' by using the member 'list_roi_numbers'
                id = item.split()[1]
                roi_id = self.patient_dict_container.get("list_roi_numbers")[
                    int(id)]

                if 'ROI Display Color' in roi_contour_info[item]:
                    RGB_list = roi_contour_info[item]['ROI Display Color'][0]
                    red = RGB_list[0]
                    green = RGB_list[1]
                    blue = RGB_list[2]
                else:
                    seed(1)
                    red = randint(0, 255)
                    green = randint(0, 255)
                    blue = randint(0, 255)

                roi_color[roi_id] = QtGui.QColor(red, green, blue)

        return roi_color

    def init_standard_names(self):
        """
        Create two lists containing standard organ and standard volume names as set by the Add-On options.
        """
        with open(resource_path('src/data/csv/organName.csv'), 'r') as f:
            self.standard_organ_names = []

            csv_input = csv.reader(f)
            header = next(f)  # Ignore the "header" of the column
            for row in csv_input:
                self.standard_organ_names.append(row[0])

        with open(resource_path('src/data/csv/volumeName.csv'), 'r') as f:
            self.standard_volume_names = []

            csv_input = csv.reader(f)
            header = next(f)  # Ignore the "header" of the column
            for row in csv_input:
                self.standard_volume_names.append(row[1])

    def init_roi_buttons(self):
        icon_roi_delete = QtGui.QIcon()
        icon_roi_delete.addPixmap(
            QtGui.QPixmap(
                resource_path('src/res/images/btn-icons/delete_icon.png')),
            QtGui.QIcon.Normal, QtGui.QIcon.On)

        icon_roi_draw = QtGui.QIcon()
        icon_roi_draw.addPixmap(
            QtGui.QPixmap(
                resource_path('src/res/images/btn-icons/draw_icon.png')),
            QtGui.QIcon.Normal, QtGui.QIcon.On)

        #self.button_roi_delete.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon)
        self.button_roi_delete.setIcon(icon_roi_delete)
        self.button_roi_delete.setText("Delete ROI")
        self.button_roi_delete.clicked.connect(self.roi_delete_clicked)

        #self.button_roi_draw.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon)
        self.button_roi_draw.setIcon(icon_roi_draw)
        self.button_roi_draw.setText("Draw ROI")
        self.button_roi_draw.clicked.connect(self.roi_draw_clicked)

        layout_roi_buttons = QtWidgets.QHBoxLayout(self.roi_buttons)
        layout_roi_buttons.setContentsMargins(0, 0, 0, 0)
        layout_roi_buttons.addWidget(self.button_roi_draw)
        layout_roi_buttons.addWidget(self.button_roi_delete)

    def update_content(self):
        """
        Add the contents (color square and checkbox) in the scrolling area widget.
        """
        # Clear the children
        for i in reversed(range(self.layout_content.count())):
            self.layout_content.itemAt(i).widget().setParent(None)

        row = 0
        for roi_id, roi_dict in self.rois.items():
            # Creates a widget representing each ROI
            structure = StructureWidget(roi_id, self.color_dict[roi_id],
                                        roi_dict['name'], self)
            structure.structure_renamed.connect(self.structure_modified)
            self.layout_content.addWidget(structure)
            row += 1

        self.scroll_area.setStyleSheet(
            "QScrollArea {background-color: #ffffff; border-style: none;}")
        self.scroll_area_content.setStyleSheet(
            "QWidget {background-color: #ffffff; border-style: none;}")

        self.scroll_area.setWidget(self.scroll_area_content)

    def roi_delete_clicked(self):
        self.roi_delete_handler.show_roi_delete_options()

    def roi_draw_clicked(self):
        self.roi_draw_handler.show_roi_draw_options()

    def structure_modified(self, changes):
        """
        Executes when a structure is renamed/deleted. Displays indicator that structure has changed.
        changes is a tuple of (new_dataset, description_of_changes)
        description_of_changes follows the format {"type_of_change": value_of_change}.
        Examples: {"rename": ["TOOTH", "TEETH"]} represents that the TOOTH structure has been renamed to TEETH.
        {"delete": ["TEETH", "MAXILLA"]} represents that the TEETH and MAXILLA structures have been deleted.
        {"draw": "AORTA"} represents that a new structure AORTA has been drawn.
        """

        new_dataset = changes[0]
        change_description = changes[1]

        # If this is the first time the RTSS has been modified, create a modified indicator giving the user the option
        # to save their new file.
        if self.patient_dict_container.get("rtss_modified") is False:
            self.show_modified_indicator()

        # If this is the first change made to the RTSS file, update the dataset with the new one so that OnkoDICOM
        # starts working off this dataset rather than the original RTSS file.
        self.patient_dict_container.set("rtss_modified", True)
        self.patient_dict_container.set("dataset_rtss", new_dataset)

        # Refresh ROIs in main page
        self.patient_dict_container.set("rois",
                                        ImageLoading.get_roi_info(new_dataset))
        self.rois = self.patient_dict_container.get("rois")
        contour_data = ImageLoading.get_raw_contour_data(new_dataset)
        self.patient_dict_container.set("raw_contour", contour_data[0])
        self.patient_dict_container.set("num_points", contour_data[1])
        pixluts = ImageLoading.get_pixluts(self.patient_dict_container.dataset)
        self.patient_dict_container.set("pixluts", pixluts)
        self.patient_dict_container.set(
            "list_roi_numbers",
            ordered_list_rois(self.patient_dict_container.get("rois")))
        self.patient_dict_container.set("selected_rois", [])
        self.patient_dict_container.set("dict_polygons", {})

        if "draw" in change_description:
            dicom_tree_rtss = DicomTree(None)
            dicom_tree_rtss.dataset = new_dataset
            dicom_tree_rtss.dict = dicom_tree_rtss.dataset_to_dict(
                dicom_tree_rtss.dataset)
            self.patient_dict_container.set("dict_dicom_tree_rtss",
                                            dicom_tree_rtss.dict)
            self.color_dict = self.init_color_roi()
            self.patient_dict_container.set("roi_color_dict", self.color_dict)
            if self.patient_dict_container.has_attribute("raw_dvh"):
                # DVH will be outdated once changes to it are made, and recalculation will be required.
                self.patient_dict_container.set("dvh_outdated", True)

        if self.patient_dict_container.has_modality("raw_dvh"):
            # Rename structures in DVH list
            if "rename" in changes[1]:
                new_raw_dvh = self.patient_dict_container.get("raw_dvh")
                for key, dvh in new_raw_dvh.items():
                    if dvh.name == change_description["rename"][0]:
                        dvh.name = change_description["rename"][1]
                        break

                self.patient_dict_container.set("raw_dvh", new_raw_dvh)

            # Remove structures from DVH list - the only visible effect of this section is the exported DVH csv
            if "delete" in changes[1]:
                list_of_deleted = []
                new_raw_dvh = self.patient_dict_container.get("raw_dvh")
                for key, dvh in new_raw_dvh.items():
                    if dvh.name in change_description["delete"]:
                        list_of_deleted.append(key)
                for key in list_of_deleted:
                    new_raw_dvh.pop(key)
                self.patient_dict_container.set("raw_dvh", new_raw_dvh)

        # Refresh ROIs in DVH tab and DICOM View
        self.request_update_structures.emit()

        # Refresh structure tab
        self.update_content()

    def show_modified_indicator(self):
        self.modified_indicator_widget = QtWidgets.QWidget()
        self.modified_indicator_widget.setContentsMargins(8, 5, 8, 5)
        modified_indicator_layout = QtWidgets.QHBoxLayout()
        modified_indicator_layout.setAlignment(QtCore.Qt.AlignLeft)

        modified_indicator_icon = QtWidgets.QLabel()
        modified_indicator_icon.setPixmap(
            QtGui.QPixmap(
                resource_path("src/res/images/btn-icons/alert_icon.png")))
        modified_indicator_layout.addWidget(modified_indicator_icon)

        modified_indicator_text = QtWidgets.QLabel(
            "Structures have been modified")
        modified_indicator_text.setStyleSheet("color: red")
        modified_indicator_layout.addWidget(modified_indicator_text)

        self.modified_indicator_widget.setLayout(modified_indicator_layout)
        self.modified_indicator_widget.mouseReleaseEvent = self.save_new_rtss  # When the widget is clicked, save the rtss

        # Temporarily remove the ROI modify buttons, add this indicator, then add them back again.
        # This ensure that the modifier appears above the ROI modify buttons.
        self.structure_tab_layout.removeWidget(self.roi_buttons)
        self.structure_tab_layout.addWidget(self.modified_indicator_widget)
        self.structure_tab_layout.addWidget(self.roi_buttons)

    def structure_checked(self, state, roi_id):
        """
        Function triggered when the checkbox of a structure is checked / unchecked.
        Update the list of selected structures.
        Update the plot of the DVH and the DICOM view.

        :param state: True if the checkbox is checked, False otherwise.
        :param roi_id: ROI number
        """

        selected_rois = self.patient_dict_container.get("selected_rois")
        if state:
            selected_rois.append(roi_id)
        else:
            selected_rois.remove(roi_id)

        self.patient_dict_container.set("selected_rois", selected_rois)

        self.request_update_structures.emit()

    def save_new_rtss(self, event=None):
        rtss_directory = str(Path(
            self.patient_dict_container.get("file_rtss")))

        confirm_save = QtWidgets.QMessageBox.information(
            self, "Confirmation",
            "Are you sure you want to save the modified RTSTRUCT file? This will "
            "overwrite the existing file. This is not reversible.",
            QtWidgets.QMessageBox.Yes, QtWidgets.QMessageBox.No)

        if confirm_save == QtWidgets.QMessageBox.Yes:
            self.patient_dict_container.get("dataset_rtss").save_as(
                rtss_directory)
            QtWidgets.QMessageBox.about(self.parentWidget(), "File saved",
                                        "The RTSTRUCT file has been saved.")
            self.patient_dict_container.set("rtss_modified", False)
            self.modified_indicator_widget.setParent(None)
示例#7
0
    def setup_central_widget(self):
        patient_dict_container = PatientDictContainer()
        self.central_widget = QtWidgets.QWidget()
        self.central_widget_layout = QVBoxLayout()

        self.patient_bar = PatientBar()

        splitter = QtWidgets.QSplitter(QtCore.Qt.Horizontal)

        # Left panel contains stuctures tab, isodoses tab,
        # and structure information
        self.left_panel = QtWidgets.QTabWidget()
        self.left_panel.setMinimumWidth(300)
        self.left_panel.setMaximumWidth(500)

        # Add structures tab to left panel
        if not hasattr(self, 'structures_tab'):
            self.structures_tab = StructureTab()
            self.structures_tab.request_update_structures.connect(
                self.update_views)
        else:
            self.structures_tab.update_ui()
        self.left_panel.addTab(self.structures_tab, "Structures")

        if patient_dict_container.has_modality("rtdose"):
            self.isodoses_tab = IsodoseTab()
            self.isodoses_tab.request_update_isodoses.connect(
                self.update_views)
            self.isodoses_tab.request_update_ui.connect(
                self.structures_tab.fixed_container_structure_modified)
            self.left_panel.addTab(self.isodoses_tab, "Isodoses")
        elif hasattr(self, 'isodoses_tab'):
            del self.isodoses_tab

        # Right panel contains the different tabs of DICOM view, DVH,
        # clinical data, DICOM tree
        self.right_panel = QtWidgets.QTabWidget()

        # Create a Dicom View containing single-slice and 3-slice views
        self.dicom_view = DicomStackedWidget(self.format_data)

        roi_color_dict = self.structures_tab.color_dict if hasattr(
            self, 'structures_tab') else None
        iso_color_dict = self.isodoses_tab.color_dict if hasattr(
            self, 'isodoses_tab') else None
        self.dicom_single_view = DicomAxialView(
            roi_color=roi_color_dict, iso_color=iso_color_dict)
        self.dicom_axial_view = DicomAxialView(
            is_four_view=True, roi_color=roi_color_dict, iso_color=iso_color_dict,
            metadata_formatted=True, cut_line_color=QtGui.QColor(255, 0, 0))
        self.dicom_sagittal_view = DicomSagittalView(
            roi_color=roi_color_dict, iso_color=iso_color_dict,
            cut_line_color=QtGui.QColor(0, 255, 0))
        self.dicom_coronal_view = DicomCoronalView(
            roi_color=roi_color_dict, iso_color=iso_color_dict,
            cut_line_color=QtGui.QColor(0, 0, 255))
        self.three_dimension_view = DicomView3D()

        # Rescale the size of the scenes inside the 3-slice views
        self.dicom_axial_view.zoom = INITIAL_FOUR_VIEW_ZOOM
        self.dicom_sagittal_view.zoom = INITIAL_FOUR_VIEW_ZOOM
        self.dicom_coronal_view.zoom = INITIAL_FOUR_VIEW_ZOOM
        self.dicom_axial_view.update_view(zoom_change=True)
        self.dicom_sagittal_view.update_view(zoom_change=True)
        self.dicom_coronal_view.update_view(zoom_change=True)

        self.dicom_four_views = QWidget()
        self.dicom_four_views_layout = QGridLayout()
        for i in range(2):
            self.dicom_four_views_layout.setColumnStretch(i, 1)
            self.dicom_four_views_layout.setRowStretch(i, 1)
        self.dicom_four_views_layout.addWidget(self.dicom_axial_view, 0, 0)
        self.dicom_four_views_layout.addWidget(self.dicom_sagittal_view, 0, 1)
        self.dicom_four_views_layout.addWidget(self.dicom_coronal_view, 1, 0)
        self.dicom_four_views_layout.addWidget(self.three_dimension_view, 1, 1)
        self.dicom_four_views.setLayout(self.dicom_four_views_layout)

        self.dicom_view.addWidget(self.dicom_four_views)
        self.dicom_view.addWidget(self.dicom_single_view)
        self.dicom_view.setCurrentWidget(self.dicom_single_view)

        # Add DICOM View to right panel as a tab
        self.right_panel.addTab(self.dicom_view, "DICOM View")

        # Add PETVT View to right panel as a tab
        self.pet_ct_tab = PetCtView()
        self.right_panel.addTab(self.pet_ct_tab, "PET/CT View")

        # Add DVH tab to right panel as a tab
        if patient_dict_container.has_modality("rtdose"):
            self.dvh_tab = DVHTab()
            self.right_panel.addTab(self.dvh_tab, "DVH")
        elif hasattr(self, 'dvh_tab'):
            del self.dvh_tab

        # Add DICOM Tree View tab
        self.dicom_tree = DicomTreeView()
        self.right_panel.addTab(self.dicom_tree, "DICOM Tree")

        # Connect SUV2ROI signal to handler function
        self.dicom_single_view.suv2roi_signal.connect(self.perform_suv2roi)

        # Add clinical data tab
        self.call_class.display_clinical_data(self.right_panel)

        splitter.addWidget(self.left_panel)
        splitter.addWidget(self.right_panel)

        # Create footer
        self.footer = QtWidgets.QWidget()
        self.create_footer()

        # Set layout
        self.central_widget_layout.addWidget(self.patient_bar)
        self.central_widget_layout.addWidget(splitter)
        self.central_widget_layout.addWidget(self.footer)

        self.central_widget.setLayout(self.central_widget_layout)
        self.main_window_instance.setCentralWidget(self.central_widget)
示例#8
0
class DicomTreeView(QtWidgets.QWidget):

    def __init__(self):
        QtWidgets.QWidget.__init__(self)
        self.patient_dict_container = PatientDictContainer()
        self.pixmaps = self.patient_dict_container.get("pixmaps")

        self.dicom_tree_layout = QtWidgets.QVBoxLayout()
        self.dicom_tree_layout.setContentsMargins(0, 0, 0, 0)

        self.selector = self.create_selector_combobox()

        self.tree_view = QtWidgets.QTreeView()
        self.model_tree = QtGui.QStandardItemModel(0, 5)
        self.init_headers_tree()
        self.tree_view.setModel(self.model_tree)
        self.init_parameters_tree()

        self.dicom_tree_layout.addWidget(self.selector, QtCore.Qt.AlignLeft | QtCore.Qt.AlignLeft)
        self.dicom_tree_layout.addWidget(self.tree_view)
        self.setLayout(self.dicom_tree_layout)

    def init_headers_tree(self):
        self.model_tree.setHeaderData(0, QtCore.Qt.Horizontal, "Name")
        self.model_tree.setHeaderData(1, QtCore.Qt.Horizontal, "Value")
        self.model_tree.setHeaderData(2, QtCore.Qt.Horizontal, "Tag")
        self.model_tree.setHeaderData(3, QtCore.Qt.Horizontal, "VM")
        self.model_tree.setHeaderData(4, QtCore.Qt.Horizontal, "VR")

    def init_parameters_tree(self):
        self.tree_view.header().resizeSection(0, 250)
        self.tree_view.header().resizeSection(1, 350)
        self.tree_view.header().resizeSection(2, 100)
        self.tree_view.header().resizeSection(3, 50)
        self.tree_view.header().resizeSection(4, 50)
        self.tree_view.header().setSectionResizeMode(QtWidgets.QHeaderView.Interactive)
        self.tree_view.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers | QtWidgets.QAbstractItemView.NoEditTriggers)
        self.tree_view.setAlternatingRowColors(True)
        self.tree_view.expandAll()

    def create_selector_combobox(self):
        combobox = QtWidgets.QComboBox()
        combobox.setFocusPolicy(QtCore.Qt.NoFocus)
        combobox.addItem("Select a DICOM dataset...")

        # determines which files are included
        self.special_files = []

        if self.patient_dict_container.has_modality("rtss"):
            combobox.addItem("RT Structure Set")
            self.special_files.append("rtss")

        if self.patient_dict_container.has_modality("rtdose"):
            combobox.addItem("RT Dose")
            self.special_files.append("rtdose")

        if self.patient_dict_container.has_modality("rtplan"):
            combobox.addItem("RT Plan")
            self.special_files.append("rtplan")

        for i in range(len(self.pixmaps)):
            combobox.addItem("Image Slice " + str(i + 1))

        combobox.activated.connect(self.item_selected)
        combobox.setFixedSize(QtCore.QSize(200, 31))
        combobox.setObjectName("DicomTreeviewComboBox")
        return combobox

    def item_selected(self, index):
        if index <= len(self.special_files) and index != 0:
            self.update_tree(False, 0, self.special_files[index-1])
        elif index > len(self.special_files):
            self.update_tree(True, index - len(self.special_files) - 1, "")

    def update_tree(self, image_slice, id, name):
        """
        Update the DICOM Tree view.
        :param image_slice: Boolean indicating if it is an image slice or not
        :param id: ID for the selected file
        :param name: Name of the selected dataset if not an image file
        :return:
        """
        self.model_tree.clear()

        if image_slice:
            filename = self.patient_dict_container.filepaths[id]
            dicom_tree_slice = DicomTree(filename)
            dict_tree = dicom_tree_slice.dict

        elif name == "rtdose":
            dict_tree = self.patient_dict_container.get("dict_dicom_tree_rtdose")

        elif name == "rtss":
            dict_tree = self.patient_dict_container.get("dict_dicom_tree_rtss")

        elif name == "rtplan":
            dict_tree = self.patient_dict_container.get("dict_dicom_tree_rtplan")

        else:
            dict_tree = None
            print("Error filename in update_tree function")

        parent_item = self.model_tree.invisibleRootItem()
        self.recurse_build_model(dict_tree, parent_item)
        self.init_headers_tree()
        self.tree_view.setModel(self.model_tree)
        self.init_parameters_tree()
        self.dicom_tree_layout.addWidget(self.tree_view)

    def recurse_build_model(self, dict_tree, parent):
        """
        Update recursively the model used for the DICOM Tree view
        :param dict_tree: The dictionary to be displayed
        :param parent: Parent node of the tree
        :return:
        """
        for key in dict_tree:
            value = dict_tree[key]
            # If the value is a dictionary
            if isinstance(value, type(dict_tree)):
                # Recurse until leaf
                item_child = QtGui.QStandardItem(key)
                parent.appendRow(self.recurse_build_model(value, item_child))
            else:
                # If the value is a simple item, append it
                item = [QtGui.QStandardItem(key),
                        QtGui.QStandardItem(str(value[0])),
                        QtGui.QStandardItem(str(value[1])),
                        QtGui.QStandardItem(str(value[2])),
                        QtGui.QStandardItem(str(value[3]))]
                parent.appendRow(item)
        return parent
示例#9
0
def create_initial_model_batch():
    """
    This function initializes all the attributes in the PatientDictContainer
    required for the operation of batch processing. It is a modified version
    of create_initial_model. This function only sets RTSS values in the
    PatientDictContainer if an RTSS exists. If one does not exist it will only
    be created if needed, whereas the original create_initial_model assumes
    that one is always created. This function also does not set SR attributes
    in the PatientDictContainer, as SRs are only needed for SR2CSV functions,
    which do not require the use of the PatientDictContainer.
    """
    ##############################
    #  LOAD PATIENT INFORMATION  #
    ##############################
    patient_dict_container = PatientDictContainer()

    dataset = patient_dict_container.dataset
    filepaths = patient_dict_container.filepaths
    patient_dict_container.set("rtss_modified", False)

    if 'WindowWidth' in dataset[0]:
        if isinstance(dataset[0].WindowWidth, pydicom.valuerep.DSfloat):
            window = int(dataset[0].WindowWidth)
        elif isinstance(dataset[0].WindowWidth, pydicom.multival.MultiValue):
            window = int(dataset[0].WindowWidth[1])
    else:
        window = int(400)

    if 'WindowCenter' in dataset[0]:
        if isinstance(dataset[0].WindowCenter, pydicom.valuerep.DSfloat):
            level = int(dataset[0].WindowCenter)
        elif isinstance(dataset[0].WindowCenter, pydicom.multival.MultiValue):
            level = int(dataset[0].WindowCenter[1])
    else:
        level = int(800)

    patient_dict_container.set("window", window)
    patient_dict_container.set("level", level)

    # Check to see if the imageWindowing.csv file exists
    if os.path.exists(data_path('imageWindowing.csv')):
        # If it exists, read data from file into the self.dict_windowing
        # variable
        dict_windowing = {}
        with open(data_path('imageWindowing.csv'), "r") \
                as fileInput:
            next(fileInput)
            dict_windowing["Normal"] = [window, level]
            for row in fileInput:
                # Format: Organ - Scan - Window - Level
                items = [item for item in row.split(',')]
                dict_windowing[items[0]] = [int(items[2]), int(items[3])]
    else:
        # If csv does not exist, initialize dictionary with default values
        dict_windowing = {
            "Normal": [window, level],
            "Lung": [1600, -300],
            "Bone": [1400, 700],
            "Brain": [160, 950],
            "Soft Tissue": [400, 800],
            "Head and Neck": [275, 900]
        }

    patient_dict_container.set("dict_windowing", dict_windowing)

    pixel_values = convert_raw_data(dataset)
    # Calculate the ratio between x axis and y axis of 3 views
    pixmap_aspect = {}
    pixel_spacing = dataset[0].PixelSpacing
    slice_thickness = dataset[0].SliceThickness
    pixmap_aspect["axial"] = pixel_spacing[1] / pixel_spacing[0]
    pixmap_aspect["sagittal"] = pixel_spacing[1] / slice_thickness
    pixmap_aspect["coronal"] = slice_thickness / pixel_spacing[0]
    pixmaps_axial, pixmaps_coronal, pixmaps_sagittal = \
        get_pixmaps(pixel_values, window, level, pixmap_aspect)

    patient_dict_container.set("pixmaps_axial", pixmaps_axial)
    patient_dict_container.set("pixmaps_coronal", pixmaps_coronal)
    patient_dict_container.set("pixmaps_sagittal", pixmaps_sagittal)
    patient_dict_container.set("pixel_values", pixel_values)
    patient_dict_container.set("pixmap_aspect", pixmap_aspect)

    basic_info = get_basic_info(dataset[0])
    patient_dict_container.set("basic_info", basic_info)

    patient_dict_container.set("dict_uid", dict_instance_uid(dataset))

    # Set RTSS attributes
    if patient_dict_container.has_modality("rtss"):
        patient_dict_container.set("file_rtss", filepaths['rtss'])
        patient_dict_container.set("dataset_rtss", dataset['rtss'])
        dict_raw_contour_data, dict_numpoints = \
            ImageLoading.get_raw_contour_data(dataset['rtss'])
        patient_dict_container.set("raw_contour", dict_raw_contour_data)
        dicom_tree_rtss = DicomTree(filepaths['rtss'])
        patient_dict_container.set("dict_dicom_tree_rtss",
                                   dicom_tree_rtss.dict)

        patient_dict_container.set(
            "list_roi_numbers",
            ordered_list_rois(patient_dict_container.get("rois")))
        patient_dict_container.set("selected_rois", [])

        patient_dict_container.set("dict_polygons_axial", {})
        patient_dict_container.set("dict_polygons_sagittal", {})
        patient_dict_container.set("dict_polygons_coronal", {})

    # Set RTDOSE attributes
    if patient_dict_container.has_modality("rtdose"):
        dicom_tree_rtdose = DicomTree(filepaths['rtdose'])
        patient_dict_container.set("dict_dicom_tree_rtdose",
                                   dicom_tree_rtdose.dict)

        patient_dict_container.set("dose_pixluts", get_dose_pixluts(dataset))

        patient_dict_container.set("selected_doses", [])

        # overwritten if RTPLAN is present.
        patient_dict_container.set("rx_dose_in_cgray", 1)

    # Set RTPLAN attributes
    if patient_dict_container.has_modality("rtplan"):
        # the TargetPrescriptionDose is type 3 (optional), so it may not be
        # there However, it is preferable to the sum of the beam doses
        # DoseReferenceStructureType is type 1 (value is mandatory), but it
        # can have a value of ORGAN_AT_RISK rather than TARGET in which case
        # there will *not* be a TargetPrescriptionDose and even if it is
        # TARGET, that's no guarantee that TargetPrescriptionDose will be
        # encoded and have a value
        rx_dose_in_cgray = calculate_rx_dose_in_cgray(dataset["rtplan"])
        patient_dict_container.set("rx_dose_in_cgray", rx_dose_in_cgray)

        dicom_tree_rtplan = DicomTree(filepaths['rtplan'])
        patient_dict_container.set("dict_dicom_tree_rtplan",
                                   dicom_tree_rtplan.dict)
示例#10
0
def create_initial_model():
    """
    This function initializes all the attributes in the PatientDictContainer
    model required for the operation of the main window. This should be
    called before the main window's components are constructed, but after
    the initial values of the PatientDictContainer instance are set (i.e.
    dataset and filepaths).
    """
    ##############################
    #  LOAD PATIENT INFORMATION  #
    ##############################
    patient_dict_container = PatientDictContainer()

    dataset = patient_dict_container.dataset
    filepaths = patient_dict_container.filepaths
    patient_dict_container.set("rtss_modified", False)

    # Determine if dataset is CT for aditional rescaling
    is_ct = False
    if dataset[0].Modality == "CT":
        is_ct = True

    if 'WindowWidth' in dataset[0]:
        if isinstance(dataset[0].WindowWidth, pydicom.valuerep.DSfloat):
            window = int(dataset[0].WindowWidth)
        elif isinstance(dataset[0].WindowWidth, pydicom.multival.MultiValue):
            window = int(dataset[0].WindowWidth[1])
    else:
        window = int(400)

    if 'WindowCenter' in dataset[0]:
        if isinstance(dataset[0].WindowCenter, pydicom.valuerep.DSfloat):
            level = int(dataset[0].WindowCenter) - window / 2
        elif isinstance(dataset[0].WindowCenter, pydicom.multival.MultiValue):
            level = int(dataset[0].WindowCenter[1]) - window / 2
        if is_ct:
            level += CT_RESCALE_INTERCEPT
    else:
        level = int(800)

    patient_dict_container.set("window", window)
    patient_dict_container.set("level", level)

    # Check to see if the imageWindowing.csv file exists
    if os.path.exists(data_path('imageWindowing.csv')):
        # If it exists, read data from file into the self.dict_windowing
        # variable
        dict_windowing = {}
        with open(data_path('imageWindowing.csv'), "r") \
                as fileInput:
            next(fileInput)
            dict_windowing["Normal"] = [window, level]
            for row in fileInput:
                # Format: Organ - Scan - Window - Level
                items = [item for item in row.split(',')]
                dict_windowing[items[0]] = [int(items[2]), int(items[3])]
    else:
        # If csv does not exist, initialize dictionary with default values
        dict_windowing = {
            "Normal": [window, level],
            "Lung": [1600, -300],
            "Bone": [1400, 700],
            "Brain": [160, 950],
            "Soft Tissue": [400, 800],
            "Head and Neck": [275, 900]
        }

    patient_dict_container.set("dict_windowing", dict_windowing)

    if not patient_dict_container.has_attribute("scaled"):
        patient_dict_container.set("scaled", True)
        pixel_values = convert_raw_data(dataset, False, is_ct)
    else:
        pixel_values = convert_raw_data(dataset, True)

    # Calculate the ratio between x axis and y axis of 3 views
    pixmap_aspect = {}
    pixel_spacing = dataset[0].PixelSpacing
    slice_thickness = dataset[0].SliceThickness
    pixmap_aspect["axial"] = pixel_spacing[1] / pixel_spacing[0]
    pixmap_aspect["sagittal"] = pixel_spacing[1] / slice_thickness
    pixmap_aspect["coronal"] = slice_thickness / pixel_spacing[0]
    pixmaps_axial, pixmaps_coronal, pixmaps_sagittal = \
        get_pixmaps(pixel_values, window, level, pixmap_aspect)

    patient_dict_container.set("pixmaps_axial", pixmaps_axial)
    patient_dict_container.set("pixmaps_coronal", pixmaps_coronal)
    patient_dict_container.set("pixmaps_sagittal", pixmaps_sagittal)
    patient_dict_container.set("pixel_values", pixel_values)
    patient_dict_container.set("pixmap_aspect", pixmap_aspect)

    basic_info = get_basic_info(dataset[0])
    patient_dict_container.set("basic_info", basic_info)

    patient_dict_container.set("dict_uid", dict_instance_uid(dataset))

    # Set RTSS attributes
    patient_dict_container.set("file_rtss", filepaths['rtss'])
    patient_dict_container.set("dataset_rtss", dataset['rtss'])
    dict_raw_contour_data, dict_numpoints = \
        ImageLoading.get_raw_contour_data(dataset['rtss'])
    patient_dict_container.set("raw_contour", dict_raw_contour_data)

    # dict_dicom_tree_rtss will be set in advance if the program
    # generates a new rtss through the execution of
    # ROI.create_initial_rtss_from_ct(...)
    if patient_dict_container.get("dict_dicom_tree_rtss") is None:
        dicom_tree_rtss = DicomTree(filepaths['rtss'])
        patient_dict_container.set("dict_dicom_tree_rtss",
                                   dicom_tree_rtss.dict)

    patient_dict_container.set(
        "list_roi_numbers",
        ordered_list_rois(patient_dict_container.get("rois")))
    patient_dict_container.set("selected_rois", [])

    patient_dict_container.set("dict_polygons_axial", {})
    patient_dict_container.set("dict_polygons_sagittal", {})
    patient_dict_container.set("dict_polygons_coronal", {})

    # Set RTDOSE attributes
    if patient_dict_container.has_modality("rtdose"):
        dicom_tree_rtdose = DicomTree(filepaths['rtdose'])
        patient_dict_container.set("dict_dicom_tree_rtdose",
                                   dicom_tree_rtdose.dict)

        patient_dict_container.set("dose_pixluts", get_dose_pixluts(dataset))

        patient_dict_container.set("selected_doses", [])

        # overwritten if RTPLAN is present.
        patient_dict_container.set("rx_dose_in_cgray", 1)

    # Set RTPLAN attributes
    if patient_dict_container.has_modality("rtplan"):
        # the TargetPrescriptionDose is type 3 (optional), so it may not be
        # there However, it is preferable to the sum of the beam doses
        # DoseReferenceStructureType is type 1 (value is mandatory), but it
        # can have a value of ORGAN_AT_RISK rather than TARGET in which case
        # there will *not* be a TargetPrescriptionDose and even if it is
        # TARGET, that's no guarantee that TargetPrescriptionDose will be
        # encoded and have a value
        rx_dose_in_cgray = calculate_rx_dose_in_cgray(dataset["rtplan"])
        patient_dict_container.set("rx_dose_in_cgray", rx_dose_in_cgray)

        dicom_tree_rtplan = DicomTree(filepaths['rtplan'])
        patient_dict_container.set("dict_dicom_tree_rtplan",
                                   dicom_tree_rtplan.dict)

    # Set SR attributes
    if patient_dict_container.has_modality("sr-cd"):
        dicom_tree_sr_clinical_data = DicomTree(filepaths['sr-cd'])
        patient_dict_container.set("dict_dicom_tree_sr_cd",
                                   dicom_tree_sr_clinical_data.dict)

    if patient_dict_container.has_modality("sr-rad"):
        dicom_tree_sr_pyrad = DicomTree(filepaths['sr-rad'])
        patient_dict_container.set("dict_dicom_tree_sr_pyrad",
                                   dicom_tree_sr_pyrad.dict)