def create_save_button(self): """ Create Save Button. """ self.Save_button = QtWidgets.QPushButton(self.scrollAreaWidgetContents) self.Save_button.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) icon_save = QtGui.QIcon() icon_save.addPixmap( QtGui.QPixmap(resource_path('res/images/btn-icons/save_icon.png')), QtGui.QIcon.Normal, QtGui.QIcon.On ) self.Save_button.setIcon(icon_save)
def init_transfer_arrow_buttons(self): """ Initialize the layout for arrow buttons """ self.transfer_all_rois_to_patient_B_button = QPushButton() self.transfer_all_rois_to_patient_B_button.setObjectName( "ROITransferToBButton") transfer_all_rois_to_patient_B_icon = QtGui.QIcon() transfer_all_rois_to_patient_B_icon.addPixmap( QtGui.QPixmap( resource_path('res/images/btn-icons/forward_slide_icon.png')), QtGui.QIcon.Normal, QtGui.QIcon.On) self.transfer_all_rois_to_patient_B_button \ .setIcon(transfer_all_rois_to_patient_B_icon) self.transfer_all_rois_to_patient_B_button.clicked.connect( self.transfer_all_rois_to_patient_B_button_clicked) self.transfer_roi_window_grid_layout.addWidget( self.transfer_all_rois_to_patient_B_button, 1, 1) self.transfer_all_rois_to_patient_A_button = QPushButton() self.transfer_all_rois_to_patient_A_button.setObjectName( "ROITransferToAButton") self.transfer_all_rois_to_patient_A_button.setMaximumWidth(100) transfer_all_rois_to_patient_A_icon = QtGui.QIcon() transfer_all_rois_to_patient_A_icon.addPixmap( QtGui.QPixmap( resource_path('res/images/btn-icons/backward_slide_icon.png')), QtGui.QIcon.Normal, QtGui.QIcon.On) self.transfer_all_rois_to_patient_A_button \ .setIcon(transfer_all_rois_to_patient_A_icon) self.transfer_all_rois_to_patient_A_button.clicked.connect( self.transfer_all_rois_to_patient_A_button_clicked) self.transfer_roi_window_grid_layout.addWidget( self.transfer_all_rois_to_patient_A_button, 2, 1)
def __init__(self): cwd = os.getcwd() current_os = platform.system() path_to_fonts = cwd if(current_os == 'Windows'): path_to_fonts += '\\res\\fonts\\' else: path_to_fonts += '/res/fonts/' path_to_fonts += current_os print(" *** Importing fonts: *** ") for root, dirs, files in os.walk(path_to_fonts): for font_file in files: QtGui.QFontDatabase.addApplicationFont(resource_path(os.path.join(root, font_file))) print("Added font: " + font_file) print(" *** Imported fonts *** \n\n\n")
def __init__(self): """ Initialise the class """ QtWidgets.QWidget.__init__(self) # Create the main layout self.main_layout = QtWidgets.QVBoxLayout() # Get the stylesheet if platform.system() == 'Darwin': self.stylesheet_path = "res/stylesheet.qss" else: self.stylesheet_path = "res/stylesheet-win-linux.qss" self.stylesheet = open(resource_path(self.stylesheet_path)).read() self.create_table_view() self.create_buttons() self.setLayout(self.main_layout)
def __init__(self): QtWidgets.QWidget.__init__(self) # Create class attributes self.data_dict = {} self.table_populated = False # Create the main layout self.main_layout = QtWidgets.QVBoxLayout() # Get the stylesheet if platform.system() == 'Darwin': self.stylesheet_path = "res/stylesheet.qss" else: self.stylesheet_path = "res/stylesheet-win-linux.qss" self.stylesheet = open(resource_path(self.stylesheet_path)).read() self.create_cd_table() self.setLayout(self.main_layout) self.import_clinical_data()
def __init__(self): """ Initialise the class. """ QtWidgets.QWidget.__init__(self) # Create the main layout self.main_layout = QtWidgets.QVBoxLayout() # Get the stylesheet if platform.system() == 'Darwin': self.stylesheet_path = "res/stylesheet.qss" else: self.stylesheet_path = "res/stylesheet-win-linux.qss" self.stylesheet = open(resource_path(self.stylesheet_path)).read() label = QtWidgets.QLabel( "Please choose the location for the resulting CSV file:") label.setStyleSheet(self.stylesheet) self.directory_layout = QtWidgets.QFormLayout() # Directory text box self.directory_input = QtWidgets.QLineEdit("No directory selected") self.directory_input.setStyleSheet(self.stylesheet) self.directory_input.setEnabled(False) # Change button self.change_button = QtWidgets.QPushButton("Change") self.change_button.setMaximumWidth(100) self.change_button.clicked.connect(self.show_file_browser) self.change_button.setObjectName("NormalButton") self.change_button.setStyleSheet(self.stylesheet) self.directory_layout.addWidget(label) self.directory_layout.addRow(self.directory_input) self.directory_layout.addRow(self.change_button) self.main_layout.addLayout(self.directory_layout) self.setLayout(self.main_layout)
def isodose_display(self): """ Display isodoses on the DICOM Image. """ slider_id = self.slider.value() curr_slice_uid = self.patient_dict_container.get("dict_uid")[slider_id] z = self.patient_dict_container.dataset[slider_id].ImagePositionPatient[2] dataset_rtdose = self.patient_dict_container.dataset['rtdose'] grid = get_dose_grid(dataset_rtdose, float(z)) if not (grid == []): # sort selected_doses in ascending order so that the high dose isodose washes # paint over the lower dose isodose washes for sd in sorted(self.patient_dict_container.get("selected_doses")): dose_level = sd * self.patient_dict_container.get("rx_dose_in_cgray") / \ (dataset_rtdose.DoseGridScaling * 10000) contours = measure.find_contours(grid, dose_level) polygons = self.calc_dose_polygon( self.patient_dict_container.get("dose_pixluts")[curr_slice_uid], contours) brush_color = self.iso_color[sd] with open(resource_path('data/line&fill_configuration'), 'r') as stream: elements = stream.readlines() if len(elements) > 0: iso_line = int(elements[2].replace('\n', '')) iso_opacity = int(elements[3].replace('\n', '')) line_width = float(elements[4].replace('\n', '')) else: iso_line = 2 iso_opacity = 5 line_width = 2.0 stream.close() iso_opacity = int((iso_opacity / 100) * 255) brush_color.setAlpha(iso_opacity) pen_color = QtGui.QColor(brush_color.red(), brush_color.green(), brush_color.blue()) pen = self.get_qpen(pen_color, iso_line, line_width) for i in range(len(polygons)): self.scene.addPolygon(polygons[i], pen, QtGui.QBrush(brush_color))
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 | QtCore.Qt.AlignLeft) modified_indicator_icon = QtWidgets.QLabel() modified_indicator_icon.setPixmap(QtGui.QPixmap(resource_path("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 display_outdated_indicator(self): self.modified_indicator_widget = QtWidgets.QWidget() self.modified_indicator_widget.setContentsMargins(8, 5, 8, 5) #self.modified_indicator_widget.setFixedHeight(35) 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( "Contours have been modified since DVH calculation. Some DVHs may " "now be out of date.") modified_indicator_text.setStyleSheet("color: red") modified_indicator_layout.addWidget(modified_indicator_text) self.modified_indicator_widget.setLayout(modified_indicator_layout) self.dvh_tab_layout.addWidget(self.modified_indicator_widget, QtCore.Qt.AlignTop)
def __init__(self, standard_name, volume_name): super(Dialog_Volume, self).__init__() # Passing the current values if it is an existing option or empty if its a new one self.standard_name = standard_name self.volume_name = volume_name # Creating the UI components self.setWindowIcon( QtGui.QIcon( resource_path("src/res/images/btn-icons/onkodicom_icon.png"))) button_box = QDialogButtonBox( QDialogButtonBox.Ok | QDialogButtonBox.Cancel, self) self.standard_name_text = QLineEdit() self.standard_name_text.setText(self.standard_name) self.volume = QLineEdit() self.volume.setText(self.volume_name) layout = QFormLayout(self) layout.addRow(QLabel("Standard Name:"), self.standard_name_text) layout.addRow(QLabel("Volume Name:"), self.volume) layout.addWidget(button_box) button_box.accepted.connect(self.accepting) button_box.rejected.connect(self.reject) self.setWindowTitle("Standard Volume Names")
def __init__(self): """ Initialise the class """ QtWidgets.QWidget.__init__(self) # Create the main layout self.main_layout = QtWidgets.QVBoxLayout() # Get the stylesheet if platform.system() == 'Darwin': self.stylesheet_path = "res/stylesheet.qss" else: self.stylesheet_path = "res/stylesheet-win-linux.qss" self.stylesheet = open(resource_path(self.stylesheet_path)).read() # Class variables self.organ_names = [] self.organ_names_lowercase = [] self.volume_prefixes = [] self.get_standard_names() self.create_table_view() self.setLayout(self.main_layout)
def setup_ui(self, delete_roi_window_instance, regions_of_interest, dataset_rtss, deleting_rois_structure_tuple): # Initialise the 2 lists for containing the ROI(s) that we are going to keep and delete respectively self.regions_of_interest_to_keep = [] self.regions_of_interest_to_delete = [] # This is for holding the original list of ROI(s) self.regions_of_interest_list = regions_of_interest # This is for holding the DICOM dataset of that specific patient self.dataset_rtss = dataset_rtss # Assigning new tuple for holding the deleting ROI(s) self.deleting_rois_structure_tuple = deleting_rois_structure_tuple # Initialise a DeleteROIWindow 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) delete_roi_window_instance.setObjectName("DeleteRoiWindowInstance") delete_roi_window_instance.setWindowIcon(window_icon) delete_roi_window_instance.resize(800, 606) # Create a vertical box to hold all widgets self.delete_roi_window_instance_vertical_box = QVBoxLayout() self.delete_roi_window_instance_vertical_box.setObjectName("DeleteRoiWindowInstanceVerticalBox") # Create a label for holding the window's title self.delete_roi_window_title = QLabel() self.delete_roi_window_title.setObjectName("DeleteRoiWindowTitle") self.delete_roi_window_title.setProperty("QLabelClass", "window-title") self.delete_roi_window_title.setAlignment(Qt.AlignLeft) self.delete_roi_window_instance_vertical_box.addWidget(self.delete_roi_window_title) # Create a label for holding the instruction of how to delete the ROIs self.delete_roi_window_instruction = QLabel() self.delete_roi_window_instruction.setObjectName("DeleteRoiWindowInstruction") self.delete_roi_window_instruction.setAlignment(Qt.AlignCenter) self.delete_roi_window_instance_vertical_box.addWidget(self.delete_roi_window_instruction) # Create a horizontal box for holding the 2 lists and the move left, move right buttons self.delete_roi_window_keep_and_delete_box = QHBoxLayout() self.delete_roi_window_keep_and_delete_box.setObjectName("DeleteRoiWindowKeepAndDeleteBox") # ================================= KEEP BOX ================================= # Create a vertical box for holding the label and the tree view for holding the ROIs that we are keeping self.delete_roi_window_keep_vertical_box = QVBoxLayout() self.delete_roi_window_keep_vertical_box.setObjectName("DeleteRoiWindowKeepVerticalBox") # Create a label for the tree view with the list of ROIs to keep self.delete_roi_window_keep_tree_view_label = QLabel() self.delete_roi_window_keep_tree_view_label.setObjectName("DeleteRoiWindowKeepTreeViewLabel") self.delete_roi_window_keep_tree_view_label.setProperty("QLabelClass", ["tree-view-label", "tree-view-label-keep-delete"]) self.delete_roi_window_keep_tree_view_label.setAlignment(Qt.AlignCenter) self.delete_roi_window_keep_tree_view_label.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)) self.delete_roi_window_keep_tree_view_label.resize(self.delete_roi_window_keep_tree_view_label.sizeHint().width(), self.delete_roi_window_keep_tree_view_label.sizeHint().height()) self.delete_roi_window_keep_vertical_box.addWidget(self.delete_roi_window_keep_tree_view_label) # Create a tree view for containing the list of ROIs to keep self.delete_roi_window_keep_tree_view = QTreeWidget() self.delete_roi_window_keep_tree_view.setObjectName("DeleteRoiWindowKeepTreeView") self.delete_roi_window_keep_tree_view.setHeaderHidden(True) self.delete_roi_window_keep_tree_view.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)) self.delete_roi_window_keep_tree_view.resize( self.delete_roi_window_keep_tree_view.sizeHint().width(), self.delete_roi_window_keep_tree_view.sizeHint().height()) self.delete_roi_window_keep_vertical_box.addWidget(self.delete_roi_window_keep_tree_view) self.delete_roi_window_keep_vertical_box.setStretch(1, 4) # Create a widget to hold the keep vertical box self.delete_roi_window_keep_widget = QWidget() self.delete_roi_window_keep_widget.setObjectName("DeleteRoiWindowKeepWidget") self.delete_roi_window_keep_widget.setLayout(self.delete_roi_window_keep_vertical_box) self.delete_roi_window_keep_and_delete_box.addStretch(1) self.delete_roi_window_keep_and_delete_box.addWidget(self.delete_roi_window_keep_widget) # ================================= KEEP BOX ================================= # ================================= MOVE LEFT/RIGHT BOX ================================= # Create a vertical box for holding the 2 buttons for moving left and right self.delete_roi_window_move_left_right_vertical_box = QVBoxLayout() self.delete_roi_window_move_left_right_vertical_box.setObjectName("DeleteRoiWindowMoveLeftRightVerticalBox") # Create Move Right Button / Delete Button self.move_right_button = QPushButton() self.move_right_button.setObjectName("MoveRightButton") self.move_right_button.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)) self.move_right_button.resize(self.move_right_button.sizeHint().width(), self.move_right_button.sizeHint().height()) self.move_right_button.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) self.move_right_button.clicked.connect(self.move_right_button_onClicked) self.move_right_button.setProperty("QPushButtonClass", "fail-button") self.delete_roi_window_move_left_right_vertical_box.addStretch(1) self.delete_roi_window_move_left_right_vertical_box.addWidget(self.move_right_button) # Create Move Left Button / Keep Button self.move_left_button = QPushButton() self.move_left_button.setObjectName("MoveLeftButton") self.move_left_button.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)) self.move_left_button.resize(self.move_left_button.sizeHint().width(), self.move_left_button.sizeHint().height()) self.move_left_button.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) self.move_left_button.clicked.connect(self.move_left_button_onClicked) self.move_left_button.setProperty("QPushButtonClass", "success-button") self.delete_roi_window_move_left_right_vertical_box.addWidget(self.move_left_button) self.delete_roi_window_move_left_right_vertical_box.addStretch(1) # Create a widget for holding the 2 buttons self.delete_roi_window_move_left_right_widget = QWidget() self.delete_roi_window_move_left_right_widget.setObjectName("DeleteRoiWindowMoveLeftRightWidget") self.delete_roi_window_move_left_right_widget.setLayout(self.delete_roi_window_move_left_right_vertical_box) self.delete_roi_window_keep_and_delete_box.addWidget(self.delete_roi_window_move_left_right_widget) # ================================= MOVE LEFT/RIGHT BOX ================================= # ================================= DELETE BOX ================================= # Create a vertical box for holding the label and the tree view for holding the ROIs that we are deleting self.delete_roi_window_delete_vertical_box = QVBoxLayout() self.delete_roi_window_delete_vertical_box.setObjectName("DeleteRoiWindowDeleteVerticalBox") # Create a label for the tree view with the list of ROIs to delete self.delete_roi_window_delete_tree_view_label = QLabel() self.delete_roi_window_delete_tree_view_label.setObjectName("DeleteRoiWindowDeleteTreeViewLabel") self.delete_roi_window_delete_tree_view_label.setProperty("QLabelClass", ["tree-view-label", "tree-view-label-keep-delete"]) self.delete_roi_window_delete_tree_view_label.setAlignment(Qt.AlignCenter) self.delete_roi_window_delete_tree_view_label.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)) self.delete_roi_window_delete_tree_view_label.resize( self.delete_roi_window_delete_tree_view_label.sizeHint().width(), self.delete_roi_window_delete_tree_view_label.sizeHint().height()) self.delete_roi_window_delete_vertical_box.addWidget(self.delete_roi_window_delete_tree_view_label) # Create a tree view for containing the list of ROIs to delete self.delete_roi_window_delete_tree_view = QTreeWidget() self.delete_roi_window_delete_tree_view.setObjectName("DeleteRoiWindowDeleteTreeView") self.delete_roi_window_delete_tree_view.setHeaderHidden(True) self.delete_roi_window_delete_tree_view.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)) self.delete_roi_window_delete_tree_view.resize( self.delete_roi_window_delete_tree_view.sizeHint().width(), self.delete_roi_window_delete_tree_view.sizeHint().height()) self.delete_roi_window_delete_vertical_box.addWidget(self.delete_roi_window_delete_tree_view) self.delete_roi_window_delete_vertical_box.setStretch(1, 4) # Create a widget to hold the delete vertical box self.delete_roi_window_delete_widget = QWidget() self.delete_roi_window_delete_widget.setObjectName("DeleteRoiWindowDeleteWidget") self.delete_roi_window_delete_widget.setLayout(self.delete_roi_window_delete_vertical_box) self.delete_roi_window_keep_and_delete_box.addWidget(self.delete_roi_window_delete_widget) self.delete_roi_window_keep_and_delete_box.addStretch(1) self.delete_roi_window_keep_and_delete_box.setStretch(1, 4) self.delete_roi_window_keep_and_delete_box.setStretch(3, 4) # ================================= DELETE BOX ================================= # Create a widget to hold the keep and delete box self.delete_roi_window_keep_and_delete_widget = QWidget() self.delete_roi_window_keep_and_delete_widget.setObjectName("DeleteRoiWindowKeepAndDeleteWidget") self.delete_roi_window_keep_and_delete_widget.setLayout(self.delete_roi_window_keep_and_delete_box) self.delete_roi_window_instance_vertical_box.addWidget(self.delete_roi_window_keep_and_delete_widget) # Create a horizontal box to hold 2 action buttons for this window self.delete_roi_window_action_buttons_box = QHBoxLayout() self.delete_roi_window_action_buttons_box.setObjectName("DeleteRoiWindowActionButtonsBox") # Create the cancel button self.delete_roi_window_cancel_button = QPushButton() self.delete_roi_window_cancel_button.setObjectName("DeleteRoiWindowCancelButton") self.delete_roi_window_cancel_button.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)) self.delete_roi_window_cancel_button.resize(self.delete_roi_window_cancel_button.sizeHint().width(), self.delete_roi_window_cancel_button.sizeHint().height()) self.delete_roi_window_cancel_button.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) self.delete_roi_window_cancel_button.clicked.connect(self.on_cancel_button_clicked) self.delete_roi_window_cancel_button.setProperty("QPushButtonClass", "fail-button") self.delete_roi_window_action_buttons_box.addStretch(1) self.delete_roi_window_action_buttons_box.addWidget(self.delete_roi_window_cancel_button) # Create the confirm button self.delete_roi_window_confirm_button = QPushButton() self.delete_roi_window_confirm_button.setObjectName("DeleteRoiWindowConfirmButton") self.delete_roi_window_confirm_button.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)) self.delete_roi_window_confirm_button.resize(self.delete_roi_window_confirm_button.sizeHint().width(), self.delete_roi_window_confirm_button.sizeHint().height()) self.delete_roi_window_confirm_button.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) self.delete_roi_window_confirm_button.clicked.connect(self.confirm_button_onClicked) self.delete_roi_window_confirm_button.setEnabled(False) self.delete_roi_window_confirm_button.setProperty("QPushButtonClass", "success-button") self.delete_roi_window_action_buttons_box.addWidget(self.delete_roi_window_confirm_button) # Create a widget to hold the action buttons self.delete_roi_window_action_buttons_widget = QWidget() self.delete_roi_window_action_buttons_widget.setObjectName("DeleteRoiWindowActionButtonsWidget") self.delete_roi_window_action_buttons_widget.setLayout(self.delete_roi_window_action_buttons_box) self.delete_roi_window_instance_vertical_box.addWidget(self.delete_roi_window_action_buttons_widget) # Set text for all attributes self.retranslate_ui(delete_roi_window_instance) # Create a central widget to hold the vertical layout box self.delete_roi_window_instance_central_widget = QWidget() self.delete_roi_window_instance_central_widget.setObjectName("DeleteRoiWindowInstanceCentralWidget") self.delete_roi_window_instance_central_widget.setLayout(self.delete_roi_window_instance_vertical_box) self.delete_roi_window_instance_vertical_box.setStretch(2, 4) # Set the central widget for the main window and style the window delete_roi_window_instance.setCentralWidget(self.delete_roi_window_instance_central_widget) delete_roi_window_instance.setStyleSheet(stylesheet) # Load the ROIs in self.display_rois_in_listViewKeep() # Set the selection mode to multi so that we can select multiple ROIs to delete self.delete_roi_window_keep_tree_view.setSelectionMode(QAbstractItemView.MultiSelection) self.delete_roi_window_delete_tree_view.setSelectionMode(QAbstractItemView.MultiSelection) QtCore.QMetaObject.connectSlotsByName(delete_roi_window_instance)
def setup_ui(self, welcome_window_instance): if platform.system() == 'Darwin': self.stylesheet_path = "res/stylesheet.qss" else: self.stylesheet_path = "res/stylesheet-win-linux.qss" stylesheet = open(resource_path(self.stylesheet_path)).read() window_icon = QtGui.QIcon() window_icon.addPixmap(QtGui.QPixmap(resource_path("res/images/icon.ico")), QtGui.QIcon.Normal, QtGui.QIcon.Off) # adding icon welcome_window_instance.setObjectName("WelcomeWindowInstance") welcome_window_instance.setWindowIcon(window_icon) welcome_window_instance.setFixedSize(840, 530) # Set a vertical layout to manage layout in a vertical manner self.window_vertical_layout_box = QtWidgets.QVBoxLayout() self.window_vertical_layout_box.setObjectName("WindowVerticalLayoutBox") # Set up the Logo Holder for the Welcome Window self.logo_holder = QtWidgets.QHBoxLayout() self.welcome_window_logo = QtWidgets.QLabel() self.welcome_window_logo.setPixmap(QtGui.QPixmap(resource_path("res/images/image.png"))) self.welcome_window_logo.setScaledContents(True) self.welcome_window_logo.setObjectName("WelcomeWindowLogo") self.welcome_window_logo.setFixedSize(480, 260) self.logo_holder.addWidget(self.welcome_window_logo) self.window_vertical_layout_box.addStretch(1) self.window_vertical_layout_box.addLayout(self.logo_holder) # Set up the Label for the Welcome Window self.welcome_window_label = QtWidgets.QLabel() self.welcome_window_label.setObjectName("WelcomeWindowLabel") # welcome_window_label_font = QtGui.QFont(FontService.get_instance().font_family(), 18) # welcome_window_label_font.setBold(True) # self.welcome_window_label.setFont(welcome_window_label_font) self.welcome_window_label.setAlignment(Qt.AlignCenter) self.window_vertical_layout_box.addWidget(self.welcome_window_label) # Set up the Slogan for the Welcome Window self.welcome_window_slogan = QtWidgets.QLabel() self.welcome_window_slogan.setObjectName("WelcomeWindowSlogan") # welcome_window_slogan_font = QtGui.QFont(FontService.get_instance().font_family(), 12) # self.welcome_window_slogan.setFont(welcome_window_slogan_font) self.welcome_window_slogan.setAlignment(Qt.AlignCenter) self.window_vertical_layout_box.addWidget(self.welcome_window_slogan) # button to open a patient self.open_patient_button = QtWidgets.QPushButton() self.open_patient_button.setObjectName("OpenPatientButton") self.open_patient_button.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) self.open_patient_button.setSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum) self.open_patient_button.resize(480, 261) # Button to start batch processing self.open_batch_button = QtWidgets.QPushButton() self.open_batch_button.setObjectName("OpenBatchProcessingButton") self.open_batch_button.setCursor( QtGui.QCursor(QtCore.Qt.PointingHandCursor)) self.open_batch_button.setSizePolicy( QtWidgets.QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)) self.open_batch_button.resize(480, 261) # Setup button layout - empty QLabels to align buttons nicely self.buttons_holder = QtWidgets.QGridLayout() self.buttons_holder.addWidget(QtWidgets.QLabel(), 1, 0, 1, 1) self.buttons_holder.addWidget(self.open_patient_button, 1, 1, 2, 1) self.buttons_holder.addWidget(QtWidgets.QLabel(), 1, 3, 1, 1) self.buttons_holder.addWidget(QtWidgets.QLabel(), 3, 0, 1, 1) self.buttons_holder.addWidget(self.open_batch_button, 3, 1, 2, 1) self.buttons_holder.addWidget(QtWidgets.QLabel(), 3, 3, 1, 1) self.window_vertical_layout_box.addStretch(1) self.window_vertical_layout_box.addLayout(self.buttons_holder) self.window_vertical_layout_box.addStretch(1) self.welcome_window_instance_central_widget = QtWidgets.QWidget() self.welcome_window_instance_central_widget.setLayout(self.window_vertical_layout_box) welcome_window_instance.setCentralWidget(self.welcome_window_instance_central_widget) welcome_window_instance.setStyleSheet(stylesheet) self.retranslate_ui(welcome_window_instance) QtCore.QMetaObject.connectSlotsByName(welcome_window_instance)
def setup_ui(self, batch_window_instance): """ Sets up the UI for the batch processing window. """ # Get the appropriate stylesheet if platform.system() == 'Darwin': self.stylesheet_path = "res/stylesheet.qss" else: self.stylesheet_path = "res/stylesheet-win-linux.qss" self.stylesheet = open(resource_path(self.stylesheet_path)).read() # Create class variables self.file_path = "Select file path..." # Label font label_font = QtGui.QFont() label_font.setPixelSize(14) # Set the window icon window_icon = QtGui.QIcon() window_icon.addPixmap( QtGui.QPixmap(resource_path("res/images/icon.ico")), QtGui.QIcon.Normal, QtGui.QIcon.Off) # Set window properties batch_window_instance.setObjectName("BatchWindowInstance") batch_window_instance.setWindowIcon(window_icon) batch_window_instance.setWindowTitle("Batch Processing") batch_window_instance.resize(840, 530) # == Directory widgets # Directory label dir_label_text = "Select directory to perform batch processing on:" self.dir_info_label = QtWidgets.QLabel(dir_label_text) self.dir_info_label.setFont(label_font) # Directory line edit self.directory_input = QtWidgets.QLineEdit() self.directory_input.setText(self.file_path) self.directory_input.textChanged.connect(self.line_edit_changed) self.directory_input.setStyleSheet(self.stylesheet) # Label to display file search status self.search_progress_label = QtWidgets.QLabel("No directory is " "currently selected.") self.search_progress_label.setFont(label_font) # Browse button self.browse_button = QtWidgets.QPushButton("Change") self.browse_button.setObjectName("NormalButton") self.browse_button.setStyleSheet(self.stylesheet) # == Tab widgets # Tab widget self.tab_widget = CheckableTabWidget() self.tab_widget.tabBar().setObjectName("batch-tabs") self.tab_widget.setStyleSheet(self.stylesheet) # Tabs self.iso2roi_tab = ISO2ROIOptions() self.suv2roi_tab = SUV2ROIOptions() self.dvh2csv_tab = DVH2CSVOptions() self.pyrad2csv_tab = PyRad2CSVOptions() self.pyrad2pyradSR_tab = Pyrad2PyradSROptions() self.csv2clinicaldatasr_tab = CSV2ClinicalDataSROptions() self.clinicaldatasr2csv_tab = ClinicalDataSR2CSVOptions() self.batchnamecleaning_tab = ROINameCleaningOptions() self.batchname2fma_tab = ROIName2FMAIDOptions() # Add tabs to tab widget self.tab_widget.addTab(self.iso2roi_tab, "ISO2ROI") self.tab_widget.addTab(self.suv2roi_tab, "SUV2ROI") self.tab_widget.addTab(self.dvh2csv_tab, "DVH2CSV") self.tab_widget.addTab(self.pyrad2csv_tab, "PyRad2CSV") self.tab_widget.addTab(self.pyrad2pyradSR_tab, "Pyrad2Pyrad-SR") self.tab_widget.addTab(self.csv2clinicaldatasr_tab, "CSV2ClinicalData-SR") self.tab_widget.addTab(self.clinicaldatasr2csv_tab, "ClinicalData-SR2CSV") self.tab_widget.addTab(self.batchnamecleaning_tab, "ROI Name Cleaning") self.tab_widget.addTab(self.batchname2fma_tab, "ROI Name to FMA ID") # == Bottom widgets # Info text info_text = "Batch Processing will be performed on datasets in the " info_text += "selected directory." self.info_label = QtWidgets.QLabel(info_text) self.info_label.setFont(label_font) # Back button self.back_button = QtWidgets.QPushButton("Exit") self.back_button.setObjectName("BatchExitButton") self.back_button.setMaximumWidth(80) self.back_button.setStyleSheet(self.stylesheet) self.back_button.setProperty("QPushButtonClass", "fail-button") # Begin button self.begin_button = QtWidgets.QPushButton("Begin") self.begin_button.setObjectName("BeginButton") self.begin_button.setMaximumWidth(100) self.begin_button.setStyleSheet(self.stylesheet) self.begin_button.setProperty("QPushButtonClass", "success-button") self.begin_button.setEnabled(False) # == Set layout # Create layouts self.layout = QtWidgets.QVBoxLayout() self.directory_layout = QtWidgets.QGridLayout() self.middle_layout = QtWidgets.QVBoxLayout() self.bottom_layout = QtWidgets.QGridLayout() # Add top text self.layout.addWidget(self.dir_info_label) # Add directory widgets self.directory_layout.addWidget(self.directory_input) self.directory_layout.addWidget(self.browse_button, 0, 1) self.directory_layout.addWidget(self.search_progress_label, 1, 0) self.layout.addLayout(self.directory_layout) # Add middle widgets (patient count, tabs) self.middle_layout.addWidget(self.tab_widget) self.layout.addLayout(self.middle_layout) # Add bottom widgets (buttons) self.bottom_layout.addWidget(self.info_label, 0, 0, 2, 4) self.bottom_layout.addWidget(self.back_button, 2, 2, 1, 1) self.bottom_layout.addWidget(self.begin_button, 2, 3, 1, 1) self.layout.addLayout(self.bottom_layout) # Connect buttons to functions self.browse_button.clicked.connect(self.show_file_browser) self.begin_button.clicked.connect(self.confirm_button_clicked) self.back_button.clicked.connect( lambda: QtCore.QCoreApplication.exit(0)) # Set window layout batch_window_instance.setLayout(self.layout) # Create batch processing controller, enable the processing self.batch_processing_controller = BatchProcessingController()
import csv from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5.QtCore import QDate from PyQt5.QtWidgets import QCompleter from country_list import countries_for_language from src.Controller.PathHandler import resource_path # Load the list of countries countries = dict(countries_for_language('en')) data = [] for i, v in enumerate(countries): data.append(countries[v]) # reading the csv files containing the available diseases with open(resource_path('src/data/ICD10_Topography.csv'), 'r') as f: reader = csv.reader(f) icd = list(reader) icd.pop(0) with open(resource_path('src/data/ICD10_Topography_C.csv'), 'r') as f: reader = csv.reader(f) icdc = list(reader) icdc.pop(0) with open(resource_path('src/data/ICD10_Morphology.csv'), 'r') as f: reader = csv.reader(f) hist = list(reader) hist.pop(0) # Creating the arrays containing the above data and formatting them appropriately new_icd = [] new_hist = []
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)
def init_layout(self): """ Initialize the layout for the DICOM View tab. Add the view widget and the slider in the layout. Add the whole container 'tab2_view' as a tab in the main page. """ # Initialise a DrawROIWindow if platform.system() == 'Darwin': self.stylesheet_path = "res/stylesheet.qss" else: self.stylesheet_path = "res/stylesheet-win-linux.qss" stylesheet = open(resource_path(self.stylesheet_path)).read() window_icon = QIcon() window_icon.addPixmap(QPixmap(resource_path("res/images/icon.ico")), QIcon.Normal, QIcon.Off) self.draw_roi_window_instance.setObjectName("DrawRoiWindowInstance") self.draw_roi_window_instance.setWindowIcon(window_icon) # Creating a form box to hold all buttons and input fields self.draw_roi_window_input_container_box = QFormLayout() self.draw_roi_window_input_container_box. \ setObjectName("DrawRoiWindowInputContainerBox") self.draw_roi_window_input_container_box. \ setLabelAlignment(Qt.AlignLeft) # Create a label for denoting the ROI name self.roi_name_label = QLabel() self.roi_name_label.setObjectName("ROINameLabel") self.roi_name_line_edit = QLineEdit() # Create an input box for ROI name self.roi_name_line_edit.setObjectName("ROINameLineEdit") self.roi_name_line_edit.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) self.roi_name_line_edit.resize( self.roi_name_line_edit.sizeHint().width(), self.roi_name_line_edit.sizeHint().height()) self.roi_name_line_edit.setEnabled(False) self.draw_roi_window_input_container_box. \ addRow(self.roi_name_label, self.roi_name_line_edit) # Create horizontal box to store image slice number and backward, # forward buttons self.image_slice_number_box = QHBoxLayout() self.image_slice_number_box.setObjectName("ImageSliceNumberBox") # Create a label for denoting the Image Slice Number self.image_slice_number_label = QLabel() self.image_slice_number_label.setObjectName("ImageSliceNumberLabel") self.image_slice_number_box.addWidget(self.image_slice_number_label) # Create a line edit for containing the image slice number self.image_slice_number_line_edit = QLineEdit() self.image_slice_number_line_edit. \ setObjectName("ImageSliceNumberLineEdit") self.image_slice_number_line_edit. \ setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) self.image_slice_number_line_edit.resize( self.image_slice_number_line_edit.sizeHint().width(), self.image_slice_number_line_edit.sizeHint().height()) self.image_slice_number_line_edit.setCursorPosition(0) self.image_slice_number_line_edit.setEnabled(False) self.image_slice_number_box. \ addWidget(self.image_slice_number_line_edit) # Create a button to move backward to the previous image self.image_slice_number_move_backward_button = QPushButton() self.image_slice_number_move_backward_button. \ setObjectName("ImageSliceNumberMoveBackwardButton") self.image_slice_number_move_backward_button.setSizePolicy( QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)) self.image_slice_number_move_backward_button.resize(QSize(24, 24)) self.image_slice_number_move_backward_button.clicked. \ connect(self.onBackwardClicked) icon_move_backward = QtGui.QIcon() icon_move_backward.addPixmap( QtGui.QPixmap( resource_path('res/images/btn-icons/backward_slide_icon.png'))) self.image_slice_number_move_backward_button.setIcon( icon_move_backward) self.image_slice_number_box. \ addWidget(self.image_slice_number_move_backward_button) # Create a button to move forward to the next image self.image_slice_number_move_forward_button = QPushButton() self.image_slice_number_move_forward_button. \ setObjectName("ImageSliceNumberMoveForwardButton") self.image_slice_number_move_forward_button.setSizePolicy( QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)) self.image_slice_number_move_forward_button.resize(QSize(24, 24)) self.image_slice_number_move_forward_button.clicked. \ connect(self.onForwardClicked) icon_move_forward = QtGui.QIcon() icon_move_forward.addPixmap( QtGui.QPixmap( resource_path('res/images/btn-icons/forward_slide_icon.png'))) self.image_slice_number_move_forward_button.setIcon(icon_move_forward) self.image_slice_number_box. \ addWidget(self.image_slice_number_move_forward_button) self.draw_roi_window_input_container_box. \ addRow(self.image_slice_number_box) # Create a horizontal box for containing the zoom function self.draw_roi_window_viewport_zoom_box = QHBoxLayout() self.draw_roi_window_viewport_zoom_box.setObjectName( "DrawRoiWindowViewportZoomBox") # Create a label for zooming self.draw_roi_window_viewport_zoom_label = QLabel() self.draw_roi_window_viewport_zoom_label. \ setObjectName("DrawRoiWindowViewportZoomLabel") # Create an input box for zoom factor self.draw_roi_window_viewport_zoom_input = QLineEdit() self.draw_roi_window_viewport_zoom_input. \ setObjectName("DrawRoiWindowViewportZoomInput") self.draw_roi_window_viewport_zoom_input. \ setText("{:.2f}".format(self.zoom * 100) + "%") self.draw_roi_window_viewport_zoom_input.setCursorPosition(0) self.draw_roi_window_viewport_zoom_input.setEnabled(False) self.draw_roi_window_viewport_zoom_input. \ setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) self.draw_roi_window_viewport_zoom_input.resize( self.draw_roi_window_viewport_zoom_input.sizeHint().width(), self.draw_roi_window_viewport_zoom_input.sizeHint().height()) # Create 2 buttons for zooming in and out # Zoom In Button self.draw_roi_window_viewport_zoom_in_button = QPushButton() self.draw_roi_window_viewport_zoom_in_button. \ setObjectName("DrawRoiWindowViewportZoomInButton") self.draw_roi_window_viewport_zoom_in_button.setSizePolicy( QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)) self.draw_roi_window_viewport_zoom_in_button.resize(QSize(24, 24)) self.draw_roi_window_viewport_zoom_in_button. \ setProperty("QPushButtonClass", "zoom-button") icon_zoom_in = QtGui.QIcon() icon_zoom_in.addPixmap( QtGui.QPixmap( resource_path('res/images/btn-icons/zoom_in_icon.png'))) self.draw_roi_window_viewport_zoom_in_button.setIcon(icon_zoom_in) self.draw_roi_window_viewport_zoom_in_button.clicked. \ connect(self.onZoomInClicked) # Zoom Out Button self.draw_roi_window_viewport_zoom_out_button = QPushButton() self.draw_roi_window_viewport_zoom_out_button. \ setObjectName("DrawRoiWindowViewportZoomOutButton") self.draw_roi_window_viewport_zoom_out_button.setSizePolicy( QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)) self.draw_roi_window_viewport_zoom_out_button.resize(QSize(24, 24)) self.draw_roi_window_viewport_zoom_out_button. \ setProperty("QPushButtonClass", "zoom-button") icon_zoom_out = QtGui.QIcon() icon_zoom_out.addPixmap( QtGui.QPixmap( resource_path('res/images/btn-icons/zoom_out_icon.png'))) self.draw_roi_window_viewport_zoom_out_button.setIcon(icon_zoom_out) self.draw_roi_window_viewport_zoom_out_button.clicked. \ connect(self.onZoomOutClicked) self.draw_roi_window_viewport_zoom_box. \ addWidget(self.draw_roi_window_viewport_zoom_label) self.draw_roi_window_viewport_zoom_box. \ addWidget(self.draw_roi_window_viewport_zoom_input) self.draw_roi_window_viewport_zoom_box. \ addWidget(self.draw_roi_window_viewport_zoom_out_button) self.draw_roi_window_viewport_zoom_box. \ addWidget(self.draw_roi_window_viewport_zoom_in_button) self.draw_roi_window_input_container_box. \ addRow(self.draw_roi_window_viewport_zoom_box) self.init_cursor_radius_change_box() # Create field to toggle two options: Keep empty pixel or fill empty # pixel when using draw cursor self.toggle_keep_empty_pixel_box = QHBoxLayout() self.toggle_keep_empty_pixel_label = QLabel() self.toggle_keep_empty_pixel_label. \ setObjectName("ToggleKeepEmptyPixelLabel") # Create input for min pixel size self.toggle_keep_empty_pixel_combo_box = QComboBox() self.toggle_keep_empty_pixel_combo_box.addItems(["Off", "On"]) self.toggle_keep_empty_pixel_combo_box.setCurrentIndex(0) self.toggle_keep_empty_pixel_combo_box.setEnabled(False) self.toggle_keep_empty_pixel_combo_box. \ setObjectName("ToggleKeepEmptyPixelComboBox") self.toggle_keep_empty_pixel_combo_box. \ setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) self.toggle_keep_empty_pixel_combo_box.resize( self.toggle_keep_empty_pixel_combo_box.sizeHint().width(), self.toggle_keep_empty_pixel_combo_box.sizeHint().height()) self.toggle_keep_empty_pixel_combo_box.currentIndexChanged.connect( self.toggle_keep_empty_pixel_box_index_changed) self.toggle_keep_empty_pixel_box. \ addWidget(self.toggle_keep_empty_pixel_label) self.toggle_keep_empty_pixel_box. \ addWidget(self.toggle_keep_empty_pixel_combo_box) self.draw_roi_window_input_container_box. \ addRow(self.toggle_keep_empty_pixel_box) # Create a horizontal box for transect and draw button self.draw_roi_window_transect_draw_box = QHBoxLayout() self.draw_roi_window_transect_draw_box. \ setObjectName("DrawRoiWindowTransectDrawBox") # Create a transect button self.image_slice_number_transect_button = QPushButton() self.image_slice_number_transect_button. \ setObjectName("ImageSliceNumberTransectButton") self.image_slice_number_transect_button.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Minimum)) self.image_slice_number_transect_button.resize( self.image_slice_number_transect_button.sizeHint().width(), self.image_slice_number_transect_button.sizeHint().height()) self.image_slice_number_transect_button.clicked. \ connect(self.transect_handler) icon_transect = QtGui.QIcon() icon_transect.addPixmap( QtGui.QPixmap( resource_path('res/images/btn-icons/transect_icon.png'))) self.image_slice_number_transect_button.setIcon(icon_transect) self.draw_roi_window_transect_draw_box. \ addWidget(self.image_slice_number_transect_button) # Create a bounding box button self.image_slice_number_box_draw_button = QPushButton() self.image_slice_number_box_draw_button. \ setObjectName("ImageSliceNumberBoxDrawButton") self.image_slice_number_box_draw_button.setSizePolicy( QSizePolicy.MinimumExpanding, QSizePolicy.Minimum) self.image_slice_number_box_draw_button.resize( self.image_slice_number_box_draw_button.sizeHint().width(), self.image_slice_number_box_draw_button.sizeHint().height()) self.image_slice_number_box_draw_button.clicked. \ connect(self.onBoxDrawClicked) icon_box_draw = QtGui.QIcon() icon_box_draw.addPixmap( QtGui.QPixmap( resource_path('res/images/btn-icons/draw_bound_icon.png'))) self.image_slice_number_box_draw_button.setIcon(icon_box_draw) self.draw_roi_window_transect_draw_box. \ addWidget(self.image_slice_number_box_draw_button) # Create a draw button self.image_slice_number_draw_button = QPushButton() self.image_slice_number_draw_button. \ setObjectName("ImageSliceNumberDrawButton") self.image_slice_number_draw_button.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Minimum)) self.image_slice_number_draw_button.resize( self.image_slice_number_draw_button.sizeHint().width(), self.image_slice_number_draw_button.sizeHint().height()) self.image_slice_number_draw_button.clicked.connect(self.onDrawClicked) icon_draw = QtGui.QIcon() icon_draw.addPixmap( QtGui.QPixmap(resource_path('res/images/btn-icons/draw_icon.png'))) self.image_slice_number_draw_button.setIcon(icon_draw) self.draw_roi_window_transect_draw_box. \ addWidget(self.image_slice_number_draw_button) self.draw_roi_window_input_container_box. \ addRow(self.draw_roi_window_transect_draw_box) # Create a contour preview button self.row_preview_layout = QtWidgets.QHBoxLayout() self.button_contour_preview = QtWidgets.QPushButton("Preview contour") self.button_contour_preview.clicked.connect(self.onPreviewClicked) self.row_preview_layout.addWidget(self.button_contour_preview) self.draw_roi_window_input_container_box. \ addRow(self.row_preview_layout) icon_preview = QtGui.QIcon() icon_preview.addPixmap( QtGui.QPixmap( resource_path('res/images/btn-icons/preview_icon.png'))) self.button_contour_preview.setIcon(icon_preview) # Create input line edit for alpha value self.label_alpha_value = QtWidgets.QLabel("Alpha value:") self.input_alpha_value = QtWidgets.QLineEdit("0.2") self.input_alpha_value. \ setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Minimum) self.input_alpha_value.resize( self.input_alpha_value.sizeHint().width(), self.input_alpha_value.sizeHint().height()) self.input_alpha_value.setValidator( QRegularExpressionValidator( QRegularExpression("^[0-9]*[.]?[0-9]*$"))) self.draw_roi_window_input_container_box. \ addRow(self.label_alpha_value, self.input_alpha_value) # Create a label for denoting the max internal hole size self.internal_hole_max_label = QLabel() self.internal_hole_max_label.setObjectName("InternalHoleLabel") # Create input for max internal hole size self.internal_hole_max_line_edit = QLineEdit() self.internal_hole_max_line_edit.setObjectName("InternalHoleInput") self.internal_hole_max_line_edit. \ setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Minimum) self.internal_hole_max_line_edit.resize( self.internal_hole_max_line_edit.sizeHint().width(), self.internal_hole_max_line_edit.sizeHint().height()) self.internal_hole_max_line_edit.setValidator( QRegularExpressionValidator( QRegularExpression("^[0-9]*[.]?[0-9]*$"))) self.draw_roi_window_input_container_box.addRow( self.internal_hole_max_label, self.internal_hole_max_line_edit) # Create a label for denoting the isthmus width size self.isthmus_width_max_label = QLabel() self.isthmus_width_max_label.setObjectName("IsthmusWidthLabel") # Create input for max isthmus width size self.isthmus_width_max_line_edit = QLineEdit() self.isthmus_width_max_line_edit.setObjectName("IsthmusWidthInput") self.isthmus_width_max_line_edit.setSizePolicy( QSizePolicy.MinimumExpanding, QSizePolicy.Minimum) self.isthmus_width_max_line_edit.resize( self.isthmus_width_max_line_edit.sizeHint().width(), self.isthmus_width_max_line_edit.sizeHint().height()) self.isthmus_width_max_line_edit.setValidator( QRegularExpressionValidator( QRegularExpression("^[0-9]*[.]?[0-9]*$"))) self.draw_roi_window_input_container_box.addRow( self.isthmus_width_max_label, self.isthmus_width_max_line_edit) # Create a label for denoting the minimum pixel density self.min_pixel_density_label = QLabel() self.min_pixel_density_label.setObjectName("MinPixelDensityLabel") # Create input for min pixel size self.min_pixel_density_line_edit = QLineEdit() self.min_pixel_density_line_edit.setObjectName("MinPixelDensityInput") self.min_pixel_density_line_edit.setSizePolicy( QSizePolicy.MinimumExpanding, QSizePolicy.Minimum) self.min_pixel_density_line_edit.resize( self.min_pixel_density_line_edit.sizeHint().width(), self.min_pixel_density_line_edit.sizeHint().height()) self.min_pixel_density_line_edit.setValidator( QRegularExpressionValidator( QRegularExpression("^[0-9]*[.]?[0-9]*$"))) self.draw_roi_window_input_container_box.addRow( self.min_pixel_density_label, self.min_pixel_density_line_edit) # Create a label for denoting the minimum pixel density self.max_pixel_density_label = QLabel() self.max_pixel_density_label.setObjectName("MaxPixelDensityLabel") # Create input for min pixel size self.max_pixel_density_line_edit = QLineEdit() self.max_pixel_density_line_edit.setObjectName("MaxPixelDensityInput") self.max_pixel_density_line_edit. \ setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Minimum) self.max_pixel_density_line_edit.resize( self.max_pixel_density_line_edit.sizeHint().width(), self.max_pixel_density_line_edit.sizeHint().height()) self.max_pixel_density_line_edit.setValidator( QRegularExpressionValidator( QRegularExpression("^[0-9]*[.]?[0-9]*$"))) self.draw_roi_window_input_container_box.addRow( self.max_pixel_density_label, self.max_pixel_density_line_edit) # Create a button to clear the draw self.draw_roi_window_instance_action_reset_button = QPushButton() self.draw_roi_window_instance_action_reset_button. \ setObjectName("DrawRoiWindowInstanceActionClearButton") self.draw_roi_window_instance_action_reset_button.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Minimum)) reset_button = self.draw_roi_window_instance_action_reset_button self.draw_roi_window_instance_action_reset_button.resize( reset_button.sizeHint().width(), reset_button.sizeHint().height()) self.draw_roi_window_instance_action_reset_button.clicked. \ connect(self.onResetClicked) self.draw_roi_window_instance_action_reset_button. \ setProperty("QPushButtonClass", "fail-button") icon_clear_roi_draw = QtGui.QIcon() icon_clear_roi_draw.addPixmap( QtGui.QPixmap( resource_path('res/images/btn-icons/reset_roi_draw_icon.png'))) self.draw_roi_window_instance_action_reset_button. \ setIcon(icon_clear_roi_draw) self.draw_roi_window_input_container_box. \ addRow(self.draw_roi_window_instance_action_reset_button) # Create a horizontal box for saving and cancel the drawing self.draw_roi_window_cancel_save_box = QHBoxLayout() self.draw_roi_window_cancel_save_box. \ setObjectName("DrawRoiWindowCancelSaveBox") # Create an exit button to cancel the drawing # Add a button to go back/exit from the application self.draw_roi_window_instance_cancel_button = QPushButton() self.draw_roi_window_instance_cancel_button. \ setObjectName("DrawRoiWindowInstanceCancelButton") self.draw_roi_window_instance_cancel_button.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Minimum)) self.draw_roi_window_instance_cancel_button.resize( self.draw_roi_window_instance_cancel_button.sizeHint().width(), self.draw_roi_window_instance_cancel_button.sizeHint().height()) self.draw_roi_window_instance_cancel_button. \ setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) self.draw_roi_window_instance_cancel_button.clicked. \ connect(self.onCancelButtonClicked) self.draw_roi_window_instance_cancel_button. \ setProperty("QPushButtonClass", "fail-button") icon_cancel = QtGui.QIcon() icon_cancel.addPixmap( QtGui.QPixmap( resource_path('res/images/btn-icons/cancel_icon.png'))) self.draw_roi_window_instance_cancel_button.setIcon(icon_cancel) self.draw_roi_window_cancel_save_box. \ addWidget(self.draw_roi_window_instance_cancel_button) # Create a save button to save all the changes self.draw_roi_window_instance_save_button = QPushButton() self.draw_roi_window_instance_save_button. \ setObjectName("DrawRoiWindowInstanceSaveButton") self.draw_roi_window_instance_save_button.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Minimum)) self.draw_roi_window_instance_save_button.resize( self.draw_roi_window_instance_save_button.sizeHint().width(), self.draw_roi_window_instance_save_button.sizeHint().height()) self.draw_roi_window_instance_save_button. \ setProperty("QPushButtonClass", "success-button") icon_save = QtGui.QIcon() icon_save.addPixmap( QtGui.QPixmap(resource_path('res/images/btn-icons/save_icon.png'))) self.draw_roi_window_instance_save_button.setIcon(icon_save) self.draw_roi_window_instance_save_button.clicked. \ connect(self.onSaveClicked) self.draw_roi_window_cancel_save_box. \ addWidget(self.draw_roi_window_instance_save_button) self.draw_roi_window_input_container_box. \ addRow(self.draw_roi_window_cancel_save_box) # Creating a horizontal box to hold the ROI view and slider self.draw_roi_window_instance_view_box = QHBoxLayout() self.draw_roi_window_instance_view_box. \ setObjectName("DrawRoiWindowInstanceViewBox") # Add View and Slider into horizontal box self.draw_roi_window_instance_view_box.addWidget(self.dicom_view) # Create a widget to hold the image slice box self.draw_roi_window_instance_view_widget = QWidget() self.draw_roi_window_instance_view_widget.setObjectName( "DrawRoiWindowInstanceActionWidget") self.draw_roi_window_instance_view_widget.setLayout( self.draw_roi_window_instance_view_box) # Create a horizontal box for containing the input fields and the # viewport self.draw_roi_window_main_box = QHBoxLayout() self.draw_roi_window_main_box.setObjectName("DrawRoiWindowMainBox") self.draw_roi_window_main_box. \ addLayout(self.draw_roi_window_input_container_box, 1) self.draw_roi_window_main_box. \ addWidget(self.draw_roi_window_instance_view_widget, 11) # Create a new central widget to hold the vertical box layout self.draw_roi_window_instance_central_widget = QWidget() self.draw_roi_window_instance_central_widget. \ setObjectName("DrawRoiWindowInstanceCentralWidget") self.draw_roi_window_instance_central_widget.setLayout( self.draw_roi_window_main_box) self.retranslate_ui(self.draw_roi_window_instance) self.draw_roi_window_instance.setStyleSheet(stylesheet) self.draw_roi_window_instance. \ setCentralWidget(self.draw_roi_window_instance_central_widget) QtCore.QMetaObject.connectSlotsByName(self.draw_roi_window_instance)
def __init__(self, moving=False): QtWidgets.QWidget.__init__(self) self.patient_dict_container = PatientDictContainer() self.moving_dict_container = MovingDictContainer() 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) self.structure_tab_layout = QtWidgets.QVBoxLayout() self.roi_delete_handler = ROIDelOption( self.fixed_container_structure_modified) self.roi_draw_handler = ROIDrawOption( self.fixed_container_structure_modified) self.roi_manipulate_handler = ROIManipulateOption( self.fixed_container_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 | 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 a modified indicator 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 | QtCore.Qt.AlignLeft) modified_indicator_icon = QtWidgets.QLabel() modified_indicator_icon.setPixmap( QtGui.QPixmap( resource_path("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_to_fixed_image_set self.modified_indicator_widget.setVisible(False) # Create ROI manipulation buttons self.button_roi_manipulate = QtWidgets.QPushButton() 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.modified_indicator_widget) self.structure_tab_layout.addWidget(self.roi_buttons) self.setLayout(self.structure_tab_layout)
def accepting(self): # starting save # Saving the Windowing options with open(resource_path("src/data/csv/imageWindowing.csv"), "w", newline="") as stream: writer = csv.writer(stream) writer.writerow(["Organ", "Scan", "Window", "Level"]) for row in range(self.table_view.rowCount()): rowdata = [] for column in range(self.table_view.columnCount()): item = self.table_view.item(row, column) if item is not None: rowdata.append(item.text()) else: rowdata.append("") writer.writerow(rowdata) # saving the Standard Organ names with open(resource_path("src/data/csv/organName.csv"), "w", newline="") as stream: writer = csv.writer(stream) writer.writerow(["Standard Name", "FMA ID", "Organ", "Url"]) for row in range(self.table_organ.rowCount()): rowdata = [] for column in range(self.table_organ.columnCount()): item = self.table_organ.item(row, column) if item is not None: rowdata.append(item.text()) else: rowdata.append("") writer.writerow(rowdata) # Saving the Standard Volume Names with open(resource_path("src/data/csv/volumeName.csv"), "w", newline="") as stream: writer = csv.writer(stream) for row in range(self.table_volume.rowCount()): rowdata = [] for column in range(self.table_volume.columnCount()): item = self.table_volume.item(row, column) if item is not None: rowdata.append(item.text()) else: rowdata.append("") writer.writerow(rowdata) # saves the new ROI from Isodoses, To Do in the future # with open('src/data/csv/isodoseRoi.csv', 'w') as stream: # writer = csv.writer(stream) # for row in range(self.table_roi.rowCount()): # rowdata = [] # for column in range(self.table_roi.columnCount()): # item = self.table_roi.item(row, column) # if item is not None: # rowdata.append(item.text()) # else: # rowdata.append('') # writer.writerow(rowdata) # save configuration file with open(resource_path("src/data/line&fill_configuration"), "w") as stream: stream.write(str(self.line_style_ROI.currentIndex())) stream.write("\n") stream.write(str(self.opacity_ROI.value())) stream.write("\n") stream.write(str(self.line_style_ISO.currentIndex())) stream.write("\n") stream.write(str(self.opacity_ISO.value())) stream.write("\n") stream.write(str(self.line_width.currentText())) stream.write("\n") stream.close() # Close the Add-On Options Window after saving if hasattr(self.window, 'structures_tab'): self.window.structures_tab.init_standard_names() self.window.structures_tab.update_content() self.close()
def __init__(self, standard_volume_names, standard_organ_names, rtss, roi_id, roi_name, rename_signal, suggested_text="", *args, **kwargs): super(RenameROIWindow, self).__init__(*args, **kwargs) 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() self.setStyleSheet(stylesheet) self.standard_volume_names = standard_volume_names self.standard_organ_names = standard_organ_names self.rtss = rtss self.roi_id = roi_id self.roi_name = roi_name self.rename_signal = rename_signal self.suggested_text = suggested_text self.setWindowTitle("Rename Region of Interest") self.setMinimumSize(300, 90) self.icon = QtGui.QIcon() self.icon.addPixmap(QtGui.QPixmap(resource_path("src/res/images/icon.ico")), QtGui.QIcon.Normal, QtGui.QIcon.Off) # adding icon self.setWindowIcon(self.icon) self.explanation_text = QLabel("Enter a new name:") self.input_field = QLineEdit() self.input_field.setText(self.suggested_text) self.input_field.textChanged.connect(self.on_text_edited) self.feedback_text = QLabel() self.button_area = QWidget() self.cancel_button = QPushButton("Cancel") self.cancel_button.clicked.connect(self.close) self.rename_button = QPushButton("Rename") self.rename_button.clicked.connect(self.on_rename_clicked) self.button_layout = QHBoxLayout() self.button_layout.addWidget(self.cancel_button) self.button_layout.addWidget(self.rename_button) self.button_area.setLayout(self.button_layout) self.list_label = QLabel() self.list_label.setText("List of Standard Region of Interests") # Populating the table of ROIs self.list_of_ROIs = QListWidget() self.list_of_ROIs.addItem("------------Standard Organ Names------------") for organ in self.standard_organ_names: self.list_of_ROIs.addItem(organ) self.list_of_ROIs.addItem("------------Standard Volume Names------------") for volume in self.standard_volume_names: self.list_of_ROIs.addItem(volume) self.list_of_ROIs.clicked.connect(self.on_ROI_clicked) self.layout = QVBoxLayout() self.layout.addWidget(self.explanation_text) self.layout.addWidget(self.input_field) self.layout.addWidget(self.feedback_text) self.layout.addWidget(self.button_area) self.layout.addWidget(self.list_label) self.layout.addWidget(self.list_of_ROIs) self.setLayout(self.layout)
def init_metadata(self): """ Create and place metadata on the view widget. """ # Position of the labels on the DICOM view. self.label_image_id.setAlignment(QtCore.Qt.AlignTop | QtCore.Qt.AlignTop) self.label_image_pos.setAlignment(QtCore.Qt.AlignTop | QtCore.Qt.AlignTop) self.label_wl.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignRight) self.label_image_size.setAlignment(QtCore.Qt.AlignBottom | QtCore.Qt.AlignBottom) self.label_zoom.setAlignment(QtCore.Qt.AlignBottom | QtCore.Qt.AlignBottom) self.label_patient_pos.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignRight) # SUV2ROI button (only when PET is opened) patient_dict_container = PatientDictContainer() datasets = patient_dict_container.dataset pet_opened = False for ds in datasets: if datasets[ds].SOPClassUID == "1.2.840.10008.5.1.4.1.1.128": pet_opened = True break if pet_opened: icon_suv2roi = QtGui.QIcon() icon_suv2roi.addPixmap( QtGui.QPixmap( resource_path("res/images/btn-icons/suv2roi.png")), QtGui.QIcon.Normal, QtGui.QIcon.On) self.button_suv2roi.setObjectName("SUV2ROI_Button") self.button_suv2roi.setIcon(icon_suv2roi) self.button_suv2roi.setToolTip("Convert SUVs to ROIs") self.button_suv2roi.setFixedSize(50, 50) self.button_suv2roi.setCursor( QtGui.QCursor(QtCore.Qt.PointingHandCursor)) self.button_suv2roi.clicked.connect(self.suv2roi_handler) # Set all labels to white stylesheet = "QLabel { color : white; }" self.format_metadata_labels(stylesheet) # The following layout was originally accomplished using a QGridLayout with QSpaceItems to anchor the labels # to the corners of the DICOM view. This caused a reintroduction of the tedious memory issues that were fixed # with the restructure. The following was rewritten to not use QSpaceItems because they, for reasons unknown, # caused a memory leak resulting in the entire patient dictionary not being cleared from memory correctly, # leaving hundreds of additional megabytes unused in memory each time a new patient was opened. # Create a widget to contain the two top-left labels top_left_widget = QtWidgets.QWidget() top_left = QtWidgets.QVBoxLayout(top_left_widget) top_left.addWidget(self.label_image_id, QtCore.Qt.AlignTop | QtCore.Qt.AlignTop) top_left.addWidget(self.label_image_pos, QtCore.Qt.AlignTop | QtCore.Qt.AlignTop) # Create a widget to contain the top-right label top_right_widget = QtWidgets.QWidget() top_right = QtWidgets.QVBoxLayout(top_right_widget) top_right.addWidget(self.label_wl, QtCore.Qt.AlignTop | QtCore.Qt.AlignTop) # Create a widget to contain the two top widgets top_widget = QtWidgets.QWidget() top = QtWidgets.QHBoxLayout(top_widget) # Set margin for axial view if self.metadata_formatted: top_widget.setFixedHeight(50) top_widget.setContentsMargins(0, 0, 0, 0) top.setContentsMargins(0, 0, 0, 0) top.setSpacing(0) else: top_widget.setFixedHeight(100) top.addWidget(top_left_widget, QtCore.Qt.AlignLeft | QtCore.Qt.AlignLeft) top.addWidget(top_right_widget, QtCore.Qt.AlignRight | QtCore.Qt.AlignRight) # Create a widget to contain the two bottom-left labels bottom_left_widget = QtWidgets.QWidget() bottom_left = QtWidgets.QVBoxLayout(bottom_left_widget) bottom_left.addWidget(self.label_image_size, QtCore.Qt.AlignBottom | QtCore.Qt.AlignBottom) bottom_left.addWidget(self.label_zoom, QtCore.Qt.AlignBottom | QtCore.Qt.AlignBottom) # Create a widget to contain the two bottom-right widgets bottom_right_widget = QtWidgets.QWidget() bottom_right = QtWidgets.QVBoxLayout(bottom_right_widget) bottom_right.setAlignment(QtCore.Qt.AlignRight) bottom_right.addWidget(self.label_patient_pos, QtCore.Qt.AlignBottom | QtCore.Qt.AlignBottom) # Add the SUV2ROI button if PET opened and in single view if pet_opened and not self.is_four_view: bottom_right_button_layout = \ QtWidgets.QHBoxLayout(bottom_right_widget) bottom_right_button_layout.addStretch(1) bottom_right_button_layout.addWidget(self.button_suv2roi) bottom_right.addLayout(bottom_right_button_layout) # Create a widget to contain the two bottom widgets bottom_widget = QtWidgets.QWidget() bottom = QtWidgets.QHBoxLayout(bottom_widget) # Set margin for axial view if self.metadata_formatted: bottom_widget.setFixedHeight(50) bottom_widget.setContentsMargins(0, 0, 0, 0) bottom.setContentsMargins(0, 0, 0, 0) bottom.setSpacing(0) else: bottom_widget.setFixedHeight(100) bottom.addWidget(bottom_left_widget, QtCore.Qt.AlignLeft | QtCore.Qt.AlignLeft) bottom.addWidget(bottom_right_widget, QtCore.Qt.AlignRight | QtCore.Qt.AlignRight) # Add the bottom and top widgets to the view self.metadata_layout.addWidget(top_widget, QtCore.Qt.AlignTop | QtCore.Qt.AlignTop) self.metadata_layout.addStretch() self.metadata_layout.addWidget( bottom_widget, QtCore.Qt.AlignBottom | QtCore.Qt.AlignBottom)
def prompt_calc_dvh(self): """ Prompt for DVH calculation. """ if platform.system() == "Linux": choice = \ QtWidgets.QMessageBox.question( self, "Calculate DVHs?", "Would you like to (re)calculate DVHs?", QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No) if choice == QtWidgets.QMessageBox.Yes: progress_window = \ CalculateDVHProgressWindow( self, QtCore.Qt.WindowTitleHint | QtCore.Qt.WindowCloseButtonHint) progress_window.signal_dvh_calculated.connect( self.dvh_calculation_finished) self.patient_dict_container.set("dvh_outdated", False) progress_window.exec_() self.export_rtdose() else: stylesheet_path = "" # Select appropriate style sheet if platform.system() == 'Darwin': stylesheet_path = Path.cwd().joinpath('res', 'stylesheet.qss') else: stylesheet_path = Path.cwd().joinpath( 'res', 'stylesheet-win-linux.qss') # Create a message box and add attributes mb = QtWidgets.QMessageBox() mb.setIcon(QtWidgets.QMessageBox.Question) mb.setWindowTitle("Calculate DVHs?") mb.setText("Would you like to (re)calculate DVHs?") button_no = QtWidgets.QPushButton("No") button_yes = QtWidgets.QPushButton("Yes") """ We want the buttons 'No' & 'Yes' to be displayed in that exact order. QMessageBox displays buttons in respect to their assigned roles. (0 first, then 0 and so on) 'AcceptRole' is 0 and 'RejectRole' is 1 thus by counterintuitively assigning 'No' to 'AcceptRole' and 'Yes' to 'RejectRole' the buttons are positioned as desired. """ mb.addButton(button_no, QtWidgets.QMessageBox.AcceptRole) mb.addButton(button_yes, QtWidgets.QMessageBox.RejectRole) # Apply stylesheet to the message box and add icon to the window mb.setStyleSheet(open(stylesheet_path).read()) mb.setWindowIcon( QtGui.QIcon( resource_path(Path.cwd().joinpath('res', 'images', 'btn-icons', 'onkodicom_icon.png')))) mb.exec_() if mb.clickedButton() == button_yes: progress_window = CalculateDVHProgressWindow( self, QtCore.Qt.WindowTitleHint | QtCore.Qt.WindowCloseButtonHint) progress_window.signal_dvh_calculated.connect( self.dvh_calculation_finished) self.patient_dict_container.set("dvh_outdated", False) progress_window.exec_() self.export_rtdose()
def __init__(self, existing_rtss, parent=None): QDialog.__init__(self, parent=parent) if platform.system() == 'Darwin': self.stylesheet_path = "res/stylesheet.qss" else: self.stylesheet_path = "res/stylesheet-win-linux.qss" stylesheet = open(resource_path(self.stylesheet_path)).read() self.setStyleSheet(stylesheet) self.setWindowTitle("Multiple RTSTRUCTs detected!") self.setMinimumSize(350, 180) self.icon = QtGui.QIcon() self.icon.addPixmap( QtGui.QPixmap(resource_path("res/images/icon.ico")), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.setWindowIcon(self.icon) self.explanation_text = QLabel("Multiple RTSTRUCTs attached to the " "selected image set have been " "identified." "\nPlease select 1 " "RTSTRUCTs to continue!") # Create scrolling area widget to contain the content. self.scroll_area = QScrollArea() self.scroll_area.setWidgetResizable(True) self.scroll_area_content = QWidget(self.scroll_area) self.scroll_area.ensureWidgetVisible(self.scroll_area_content) # Create layout for checkboxes self.layout_content = QVBoxLayout(self.scroll_area_content) self.layout_content.setContentsMargins(5, 5, 5, 5) self.layout_content.setSpacing(0) self.layout_content.setAlignment(QtCore.Qt.AlignTop | QtCore.Qt.AlignTop) # Add all the attached RTSSs as checkboxes self.checkbox_group = QButtonGroup() self.checkbox_group.setExclusive(True) for i in range(len(existing_rtss)): checkbox = QCheckBox() checkbox.rtss = existing_rtss[i] rtss = dcmread(checkbox.rtss.get_files()[0]) checkbox.setFocusPolicy(QtCore.Qt.NoFocus) checkbox.setText("Series: %s (%s, %s %s)" % ( checkbox.rtss.series_description, checkbox.rtss.get_series_type(), len(rtss.StructureSetROISequence), "ROIs" if len(rtss.StructureSetROISequence) > 1 else "ROI" )) self.checkbox_group.addButton(checkbox) self.layout_content.addWidget(checkbox) self.checkbox_group.buttonClicked.connect(self.on_checkbox_clicked) # Create a cancel button self.cancel_button = QPushButton("Cancel") self.cancel_button.clicked.connect(self.on_cancel_clicked) # Create a continue button self.continue_button = QPushButton("Continue Process") self.continue_button.setDisabled(True) self.continue_button.clicked.connect(self.on_continue_clicked) # Create a widget to contain cancel and continue buttons self.button_area = QWidget() self.button_layout = QHBoxLayout() self.button_layout.addWidget(self.cancel_button) self.button_layout.addWidget(self.continue_button) self.button_area.setLayout(self.button_layout) # Add all components to a vertical layout self.layout = QVBoxLayout() self.layout.addWidget(self.explanation_text) self.layout.addWidget(self.scroll_area) self.layout.addWidget(self.button_area) self.setLayout(self.layout)
def __init__(self, main_page): self.__main_page = main_page self.patient_dict_container = PatientDictContainer() self.is_four_view = False self.has_image_registration_single = False self.has_image_registration_four = False ############################## # Init all actions and icons # ############################## # Open patient self.icon_open = QtGui.QIcon() self.icon_open.addPixmap( QtGui.QPixmap( resource_path( "res/images/btn-icons/open_patient_purple_icon.png")), QtGui.QIcon.Normal, QtGui.QIcon.On) self.action_open = QtGui.QAction() self.action_open.setIcon(self.icon_open) self.action_open.setText("Open new patient") self.action_open.setIconVisibleInMenu(True) # Save RTSTRUCT changes action self.icon_save_structure = QtGui.QIcon() self.icon_save_structure.addPixmap( QtGui.QPixmap( resource_path( "res/images/btn-icons/save_all_purple_icon.png")), QtGui.QIcon.Normal, QtGui.QIcon.On) self.action_save_structure = QtGui.QAction() self.action_save_structure.setIcon(self.icon_save_structure) self.action_save_structure.setText("Save RTSTRUCT changes") self.action_save_structure.setIconVisibleInMenu(True) self.action_save_structure.triggered.connect(self.save_struct_handler) # Save as Anonymous Action self.icon_save_as_anonymous = QtGui.QIcon() self.icon_save_as_anonymous.addPixmap( QtGui.QPixmap( resource_path( "res/images/btn-icons/anonlock_purple_icon.png")), QtGui.QIcon.Normal, QtGui.QIcon.On) self.action_save_as_anonymous = QtGui.QAction() self.action_save_as_anonymous.setIcon(self.icon_save_as_anonymous) self.action_save_as_anonymous.setText("Save as Anonymous") self.action_save_as_anonymous.triggered.connect( self.anonymization_handler) # Exit action self.action_exit = QtGui.QAction() self.action_exit.setText("Exit") self.action_exit.triggered.connect(self.action_exit_handler) # Zoom Out Action self.icon_zoom_out = QtGui.QIcon() self.icon_zoom_out.addPixmap( QtGui.QPixmap( resource_path( "res/images/btn-icons/zoom_out_purple_icon.png")), QtGui.QIcon.Normal, QtGui.QIcon.On) self.action_zoom_out = QtGui.QAction() self.action_zoom_out.setIcon(self.icon_zoom_out) self.action_zoom_out.setIconVisibleInMenu(True) self.action_zoom_out.setText("Zoom Out") self.action_zoom_out.triggered.connect(self.zoom_out_handler) # Zoom In Action self.icon_zoom_in = QtGui.QIcon() self.icon_zoom_in.addPixmap( QtGui.QPixmap( resource_path("res/images/btn-icons/zoom_in_purple_icon.png")), QtGui.QIcon.Normal, QtGui.QIcon.On) self.action_zoom_in = QtGui.QAction() self.action_zoom_in.setIcon(self.icon_zoom_in) self.action_zoom_in.setIconVisibleInMenu(True) self.action_zoom_in.setText("Zoom In") self.action_zoom_in.triggered.connect(self.zoom_in_handler) # Transect Action self.icon_transect = QtGui.QIcon() self.icon_transect.addPixmap( QtGui.QPixmap( resource_path( "res/images/btn-icons/transect_purple_icon.png")), QtGui.QIcon.Normal, QtGui.QIcon.On) self.action_transect = QtGui.QAction() self.action_transect.setIcon(self.icon_transect) self.action_transect.setIconVisibleInMenu(True) self.action_transect.setText("Transect") self.action_transect.triggered.connect(self.transect_handler) # Add-On Options Action self.icon_add_ons = QtGui.QIcon() self.icon_add_ons.addPixmap( QtGui.QPixmap( resource_path( "res/images/btn-icons/management_purple_icon.png")), QtGui.QIcon.Normal, QtGui.QIcon.On) self.action_add_ons = QtGui.QAction() self.action_add_ons.setIcon(self.icon_add_ons) self.action_add_ons.setIconVisibleInMenu(True) self.action_add_ons.setText("Add-On Options") self.action_add_ons.triggered.connect(self.add_on_options_handler) # Switch to Single View Action self.icon_one_view = QtGui.QIcon() self.icon_one_view.addPixmap( QtGui.QPixmap( resource_path( "res/images/btn-icons/axial_view_purple_icon.png")), QtGui.QIcon.Normal, QtGui.QIcon.On) self.action_one_view = QtGui.QAction() self.action_one_view.setIcon(self.icon_one_view) self.action_one_view.setIconVisibleInMenu(True) self.action_one_view.setText("One View") self.action_one_view.triggered.connect(self.one_view_handler) # Switch to 4 Views Action self.icon_four_views = QtGui.QIcon() self.icon_four_views.addPixmap( QtGui.QPixmap( resource_path( "res/images/btn-icons/four_views_purple_icon.png")), QtGui.QIcon.Normal, QtGui.QIcon.On) self.action_four_views = QtGui.QAction() self.action_four_views.setIcon(self.icon_four_views) self.action_four_views.setIconVisibleInMenu(True) self.action_four_views.setText("Four Views") self.action_four_views.triggered.connect(self.four_views_handler) # Show cut lines self.icon_cut_lines = QtGui.QIcon() self.icon_cut_lines.addPixmap( QtGui.QPixmap( resource_path( "res/images/btn-icons/cut_line_purple_icon.png")), QtGui.QIcon.Normal, QtGui.QIcon.On) self.action_show_cut_lines = QtGui.QAction() self.action_show_cut_lines.setIcon(self.icon_cut_lines) self.action_show_cut_lines.setIconVisibleInMenu(True) self.action_show_cut_lines.setText("Show Cut Lines") self.action_show_cut_lines.triggered.connect(self.cut_lines_handler) # Export Pyradiomics Action self.action_pyradiomics_export = QtGui.QAction() self.action_pyradiomics_export.setText("Export Pyradiomics") self.action_pyradiomics_export.triggered.connect( self.pyradiomics_export_handler) # Export DVH Action self.action_dvh_export = QtGui.QAction() self.action_dvh_export.setText("Export DVH") self.action_dvh_export.triggered.connect(self.export_dvh_handler) # Create Windowing menu self.icon_windowing = QtGui.QIcon() self.icon_windowing.addPixmap( QtGui.QPixmap( resource_path( "res/images/btn-icons/windowing_purple_icon.png")), QtGui.QIcon.Normal, QtGui.QIcon.On) self.menu_windowing = QtWidgets.QMenu() self.init_windowing_menu() self.windowing_window = Windowing(self) self.windowing_window.done_signal.connect(self.update_views) # Create Export menu self.icon_export = QtGui.QIcon() self.icon_export.addPixmap( QtGui.QPixmap( resource_path("res/images/btn-icons/export_purple_icon.png")), QtGui.QIcon.Normal, QtGui.QIcon.On, ) self.menu_export = QtWidgets.QMenu() self.menu_export.setTitle("Export") self.menu_export.addAction(self.action_pyradiomics_export) self.menu_export.addAction(self.action_dvh_export) # Image Fusion Action self.icon_image_fusion = QtGui.QIcon() self.icon_image_fusion.addPixmap( QtGui.QPixmap( resource_path( "res/images/btn-icons/image_fusion_purple_icon.png")), QtGui.QIcon.Normal, QtGui.QIcon.On) self.action_image_fusion = QtGui.QAction() self.action_image_fusion.setIcon(self.icon_image_fusion) self.action_image_fusion.setIconVisibleInMenu(True) self.action_image_fusion.setText("Image Fusion")
def __init__(self): QtWidgets.QWidget.__init__(self) self.setObjectName("PatientBar") self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) patient_dict_container = PatientDictContainer() self.basic_info = patient_dict_container.get("basic_info") # Init layout self.patient_bar_layout = QHBoxLayout() self.patient_bar_layout.setObjectName("PatientBarLayout") self.patient_bar_layout.setSpacing(0) # Create patient icon self.patient_bar_icon = QLabel() self.patient_bar_icon.setObjectName("PatientBarIcon") self.patient_bar_icon.setText("") self.patient_bar_icon.setPixmap( QtGui.QPixmap( resource_path("src/res/images/btn-icons/patient.png"))) # Create patient name self.patient_bar_name_info = QLabel() self.patient_bar_name_info.setObjectName("PatientBarNameInfo") self.patient_bar_name_info.setText(self.basic_info['name']) self.patient_bar_name_info.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) self.patient_bar_name_info.resize( self.patient_bar_name_info.sizeHint().width(), self.patient_bar_name_info.sizeHint().height()) self.patient_bar_name_info.setProperty("PatientBarClass", "value") self.patient_bar_name_info_label = QLabel() self.patient_bar_name_info_label.setObjectName( "PatientBarNameInfoLabel") self.patient_bar_name_info_label.setText("Name:") self.patient_bar_name_info_label.setSizePolicy( QSizePolicy.MinimumExpanding, QSizePolicy.Minimum) self.patient_bar_name_info_label.resize( self.patient_bar_name_info_label.sizeHint().width(), self.patient_bar_name_info_label.sizeHint().height()) self.patient_bar_name_info_label.setProperty("PatientBarClass", "label") # # Create patient ID self.patient_bar_id_info = QLabel() self.patient_bar_id_info.setObjectName("PatientBarIdInfo") self.patient_bar_id_info.setText(self.basic_info['id']) self.patient_bar_id_info.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) self.patient_bar_id_info.resize( self.patient_bar_id_info.sizeHint().width(), self.patient_bar_id_info.sizeHint().height()) self.patient_bar_id_info.setProperty("PatientBarClass", "value") self.patient_bar_id_info_label = QLabel() self.patient_bar_id_info_label.setObjectName("PatientBarIdInfoLabel") self.patient_bar_id_info_label.setText("ID:") self.patient_bar_id_info_label.setSizePolicy( QSizePolicy.MinimumExpanding, QSizePolicy.Minimum) self.patient_bar_id_info_label.resize( self.patient_bar_id_info_label.sizeHint().width(), self.patient_bar_id_info_label.sizeHint().height()) self.patient_bar_id_info_label.setProperty("PatientBarClass", "label") # # Create patient gender self.patient_bar_gender_info = QLabel() self.patient_bar_gender_info.setObjectName("PatientBarGenderInfo") self.patient_bar_gender_info.setText(self.basic_info['gender']) self.patient_bar_gender_info.setSizePolicy( QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) self.patient_bar_gender_info.resize( self.patient_bar_gender_info.sizeHint().width(), self.patient_bar_gender_info.sizeHint().height()) self.patient_bar_gender_info.setProperty("PatientBarClass", "value") self.patient_bar_gender_info_label = QLabel() self.patient_bar_gender_info_label.setObjectName( "PatientBarGenderInfoLabel") self.patient_bar_gender_info_label.setText("Gender:") self.patient_bar_gender_info_label.setSizePolicy( QSizePolicy.MinimumExpanding, QSizePolicy.Minimum) self.patient_bar_gender_info_label.resize( self.patient_bar_gender_info_label.sizeHint().width(), self.patient_bar_gender_info_label.sizeHint().height()) self.patient_bar_gender_info_label.setProperty("PatientBarClass", "label") # # Create patient DOB self.patient_bar_dob_info = QLabel() self.patient_bar_dob_info.setObjectName("PatientBarDobInfo") self.patient_bar_dob_info.setText(self.basic_info['dob']) self.patient_bar_dob_info.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) self.patient_bar_dob_info.resize( self.patient_bar_dob_info.sizeHint().width(), self.patient_bar_dob_info.sizeHint().height()) self.patient_bar_dob_info.setProperty("PatientBarClass", "value") self.patient_bar_dob_info_label = QLabel() self.patient_bar_dob_info_label.setObjectName("PatientBarDobInfoLabel") self.patient_bar_dob_info_label.setText("DoB:") self.patient_bar_dob_info_label.setSizePolicy( QSizePolicy.MinimumExpanding, QSizePolicy.Minimum) self.patient_bar_dob_info_label.resize( self.patient_bar_dob_info_label.sizeHint().width(), self.patient_bar_dob_info_label.sizeHint().height()) self.patient_bar_dob_info_label.setProperty("PatientBarClass", "label") # # Set layout self.patient_bar_layout.addWidget(self.patient_bar_icon) self.patient_bar_layout.addWidget(self.patient_bar_name_info_label) self.patient_bar_layout.addWidget(self.patient_bar_name_info) self.patient_bar_layout.addWidget(self.patient_bar_id_info_label) self.patient_bar_layout.addWidget(self.patient_bar_id_info) self.patient_bar_layout.addWidget(self.patient_bar_gender_info_label) self.patient_bar_layout.addWidget(self.patient_bar_gender_info) self.patient_bar_layout.addWidget(self.patient_bar_dob_info_label) self.patient_bar_layout.addWidget(self.patient_bar_dob_info) self.setLayout(self.patient_bar_layout) self.resize(self.sizeHint().width(), self.sizeHint().height())
def setup_ui(self, open_patient_window_instance): if platform.system() == 'Darwin': self.stylesheet_path = "res/stylesheet.qss" else: self.stylesheet_path = "res/stylesheet-win-linux.qss" window_icon = QIcon() window_icon.addPixmap(QPixmap(resource_path("res/images/icon.ico")), QIcon.Normal, QIcon.Off) open_patient_window_instance.setObjectName("OpenPatientWindowInstance") open_patient_window_instance.setWindowIcon(window_icon) open_patient_window_instance.resize(840, 530) # Create a vertical box for containing the other elements and layouts self.open_patient_window_instance_vertical_box = QVBoxLayout() self.open_patient_window_instance_vertical_box.setObjectName( "OpenPatientWindowInstanceVerticalBox") # Create a label to prompt the user to enter the path to the directory that contains the DICOM files self.open_patient_directory_prompt = QLabel() self.open_patient_directory_prompt.setObjectName( "OpenPatientDirectoryPrompt") self.open_patient_directory_prompt.setAlignment(Qt.AlignLeft) self.open_patient_window_instance_vertical_box.addWidget( self.open_patient_directory_prompt) # Create a horizontal box to hold the input box for the directory and the choose button self.open_patient_directory_input_horizontal_box = QHBoxLayout() self.open_patient_directory_input_horizontal_box.setObjectName( "OpenPatientDirectoryInputHorizontalBox") # Create a textbox to contain the path to the directory that contains the DICOM files self.open_patient_directory_input_box = UIOpenPatientWindowDragAndDropEvent( self) self.open_patient_directory_input_box.setObjectName( "OpenPatientDirectoryInputBox") self.open_patient_directory_input_box.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)) self.open_patient_directory_input_box.returnPressed.connect( self.scan_directory_for_patient) self.open_patient_directory_input_horizontal_box.addWidget( self.open_patient_directory_input_box) # Create a choose button to open the file dialog self.open_patient_directory_choose_button = QPushButton() self.open_patient_directory_choose_button.setObjectName( "OpenPatientDirectoryChooseButton") self.open_patient_directory_choose_button.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)) self.open_patient_directory_choose_button.resize( self.open_patient_directory_choose_button.sizeHint().width(), self.open_patient_directory_input_box.height()) self.open_patient_directory_choose_button.setCursor( QtGui.QCursor(QtCore.Qt.PointingHandCursor)) self.open_patient_directory_input_horizontal_box.addWidget( self.open_patient_directory_choose_button) self.open_patient_directory_choose_button.clicked.connect( self.choose_button_clicked) # Create a widget to hold the input fields self.open_patient_directory_input_widget = QWidget() self.open_patient_directory_input_horizontal_box.setStretch(0, 4) self.open_patient_directory_input_widget.setLayout( self.open_patient_directory_input_horizontal_box) self.open_patient_window_instance_vertical_box.addWidget( self.open_patient_directory_input_widget) # Create a horizontal box to hold the stop button and direction to the user on where to select the patient self.open_patient_appear_prompt_and_stop_horizontal_box = QHBoxLayout() self.open_patient_appear_prompt_and_stop_horizontal_box.setObjectName( "OpenPatientAppearPromptAndStopHorizontalBox") # Create a label to show direction on where the files will appear self.open_patient_directory_appear_prompt = QLabel() self.open_patient_directory_appear_prompt.setObjectName( "OpenPatientDirectoryAppearPrompt") self.open_patient_directory_appear_prompt.setAlignment(Qt.AlignLeft) self.open_patient_appear_prompt_and_stop_horizontal_box.addWidget( self.open_patient_directory_appear_prompt) self.open_patient_appear_prompt_and_stop_horizontal_box.addStretch(1) # Create a button to stop searching self.open_patient_window_stop_button = QPushButton() self.open_patient_window_stop_button.setObjectName( "OpenPatientWindowStopButton") self.open_patient_window_stop_button.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)) self.open_patient_window_stop_button.resize( self.open_patient_window_stop_button.sizeHint().width(), self.open_patient_window_stop_button.sizeHint().height()) self.open_patient_window_stop_button.setCursor( QtGui.QCursor(QtCore.Qt.PointingHandCursor)) self.open_patient_window_stop_button.clicked.connect( self.stop_button_clicked) self.open_patient_window_stop_button.setProperty( "QPushButtonClass", "fail-button") self.open_patient_window_stop_button.setVisible( False) # Button doesn't show until a search commences self.open_patient_appear_prompt_and_stop_horizontal_box.addWidget( self.open_patient_window_stop_button) # Create a widget to hold the layout self.open_patient_appear_prompt_and_stop_widget = QWidget() self.open_patient_appear_prompt_and_stop_widget.setLayout( self.open_patient_appear_prompt_and_stop_horizontal_box) self.open_patient_window_instance_vertical_box.addWidget( self.open_patient_appear_prompt_and_stop_widget) # Create a tree view list to list out all patients in the directory selected above self.open_patient_window_patients_tree = QTreeWidget() self.open_patient_window_patients_tree.setObjectName( "OpenPatientWindowPatientsTree") self.open_patient_window_patients_tree.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)) self.open_patient_window_patients_tree.resize( self.open_patient_window_patients_tree.sizeHint().width(), self.open_patient_window_patients_tree.sizeHint().height()) self.open_patient_window_patients_tree.setHeaderHidden(False) self.open_patient_window_patients_tree.setHeaderLabels([""]) self.open_patient_window_patients_tree.itemChanged.connect( self.tree_item_changed) self.open_patient_window_instance_vertical_box.addWidget( self.open_patient_window_patients_tree) self.last_patient = None # Create a label to show what would happen if they select the patient self.open_patient_directory_result_label = QtWidgets.QLabel() self.open_patient_directory_result_label.setObjectName( "OpenPatientDirectoryResultLabel") self.open_patient_directory_result_label.setAlignment(Qt.AlignLeft) self.open_patient_window_instance_vertical_box.addWidget( self.open_patient_directory_result_label) # Create a horizontal box to hold the Cancel and Open button self.open_patient_window_patient_open_actions_horizontal_box = QHBoxLayout( ) self.open_patient_window_patient_open_actions_horizontal_box.setObjectName( "OpenPatientWindowPatientOpenActionsHorizontalBox") self.open_patient_window_patient_open_actions_horizontal_box.addStretch( 1) # Add a button to go back/exit from the application self.open_patient_window_exit_button = QPushButton() self.open_patient_window_exit_button.setObjectName( "OpenPatientWindowExitButton") self.open_patient_window_exit_button.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)) self.open_patient_window_exit_button.resize( self.open_patient_window_stop_button.sizeHint().width(), self.open_patient_window_stop_button.sizeHint().height()) self.open_patient_window_exit_button.setCursor( QtGui.QCursor(QtCore.Qt.PointingHandCursor)) self.open_patient_window_exit_button.clicked.connect( self.exit_button_clicked) self.open_patient_window_exit_button.setProperty( "QPushButtonClass", "fail-button") self.open_patient_window_patient_open_actions_horizontal_box.addWidget( self.open_patient_window_exit_button) # Add a button to confirm opening of the patient self.open_patient_window_confirm_button = QPushButton() self.open_patient_window_confirm_button.setObjectName( "OpenPatientWindowConfirmButton") self.open_patient_window_confirm_button.setSizePolicy( QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)) self.open_patient_window_confirm_button.resize( self.open_patient_window_confirm_button.sizeHint().width(), self.open_patient_window_confirm_button.sizeHint().height()) self.open_patient_window_confirm_button.setCursor( QtGui.QCursor(QtCore.Qt.PointingHandCursor)) self.open_patient_window_confirm_button.setDisabled(True) self.open_patient_window_confirm_button.clicked.connect( self.confirm_button_clicked) self.open_patient_window_confirm_button.setProperty( "QPushButtonClass", "success-button") self.open_patient_window_patient_open_actions_horizontal_box.addWidget( self.open_patient_window_confirm_button) # Create a widget to house all of the actions button for open patient window self.open_patient_window_patient_open_actions_widget = QWidget() self.open_patient_window_patient_open_actions_widget.setLayout( self.open_patient_window_patient_open_actions_horizontal_box) self.open_patient_window_instance_vertical_box.addWidget( self.open_patient_window_patient_open_actions_widget) # Set the vertical box fourth element, the tree view, to stretch out as far as possible self.open_patient_window_instance_vertical_box.setStretch( 3, 4) # Stretch the treeview out as far as possible self.open_patient_window_instance_central_widget = QWidget() self.open_patient_window_instance_central_widget.setObjectName( "OpenPatientWindowInstanceCentralWidget") self.open_patient_window_instance_central_widget.setLayout( self.open_patient_window_instance_vertical_box) # Create threadpool for multithreading self.threadpool = QThreadPool() print("Multithreading with maximum %d threads" % self.threadpool.maxThreadCount()) # Create interrupt event for stopping the directory search self.interrupt_flag = threading.Event() # Bind all texts into the buttons and labels self.retranslate_ui(open_patient_window_instance) # Set the central widget, ready for display open_patient_window_instance.setCentralWidget( self.open_patient_window_instance_central_widget) # Set the current stylesheet to the instance and connect it back to the caller through slot _stylesheet = open(resource_path(self.stylesheet_path)).read() open_patient_window_instance.setStyleSheet(_stylesheet) QtCore.QMetaObject.connectSlotsByName(open_patient_window_instance)
def __init__(self, window): # initialization function super(AddOnOptions, self).__init__() # read configuration file for line and fill options with open(resource_path("src/data/line&fill_configuration"), "r") as stream: elements = stream.readlines() # if file is not empty, each line represents the last saved configuration in the given order if len(elements) > 0: roi_line = int(elements[0].replace("\n", "")) roi_opacity = int(elements[1].replace("\n", "")) iso_line = int(elements[2].replace("\n", "")) iso_opacity = int(elements[3].replace("\n", "")) line_width = float(elements[4].replace("\n", "")) else: # if file is empty for some reason, use the default measures below roi_line = 1 roi_opacity = 10 iso_line = 2 iso_opacity = 5 line_width = 2.0 stream.close() # initialise the UI self.window = window self.setup_ui(self, roi_line, roi_opacity, iso_line, iso_opacity, line_width) # this data is used to create the tree view of functionalities on the left of the window # each entrie will be used as a button to change the view on the right accordingly data = [ { "level": 0, "dbID": 442, "parent_ID": 6, "short_name": "User Options" }, { "level": 1, "dbID": 522, "parent_ID": 442, "short_name": "Image Windowing", }, { "level": 1, "dbID": 556, "parent_ID": 442, "short_name": "Standard Organ Names", }, { "level": 1, "dbID": 527, "parent_ID": 442, "short_name": "Standard Volume Names", }, # {'level': 1, 'dbID': 528, 'parent_ID': 442, 'short_name': 'Create ROI from Isodose'}, # extra option not fully supported { "level": 1, "dbID": 520, "parent_ID": 442, "short_name": "Patient ID - Hash ID", }, { "level": 1, "dbID": 523, "parent_ID": 442, "short_name": "Line & Fill configuration", }, ] # create a model for the tree view of options and attach the data self.model = QtGui.QStandardItemModel() self.treeList.setModel(self.model) self.importData(data) self.treeList.expandAll() # fill the corresponding tables with the corresponding data from the csv files self.fillTables() self.treeList.setEditTriggers(QtWidgets.QTreeView.NoEditTriggers ) # make the tree entries not editable # Functionalities of the Apply and Cancel button self.cancel_button.clicked.connect( self.close) # Close the window by discarding all changes self.apply_button.clicked.connect(self.accepting) # Connecting the functionalities of the view dependant buttons self.add_new_window.clicked.connect(self.new_windowing) self.add_standard_organ_name.clicked.connect(self.new_organ) self.add_standard_volume_name.clicked.connect(self.new_volume) # self.add_new_roi.clicked.connect(self.new_isodose) # extra functionality self.import_organ_csv.clicked.connect(self.import_organs) # adding the right click menus for each table self.table_view.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) self.table_view.customContextMenuRequested.connect( self.on_customContextMenuRequested_Window) self.table_organ.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) self.table_organ.customContextMenuRequested.connect( self.on_customContextMenuRequested_Organ) self.table_volume.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) self.table_volume.customContextMenuRequested.connect( self.on_customContextMenuRequested_Volume) # self.table_roi.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) # self.table_roi.customContextMenuRequested.connect(self.on_customContextMenuRequested_Roi) # making the URL column a double clicked link self.table_organ.itemDoubleClicked.connect(self.open_link)
def init_cursor_radius_change_box(self): """ function to init cursor radius change box """ # Create a horizontal box for containing the cursor radius changing # function self.draw_roi_window_cursor_radius_change_box = QHBoxLayout() self.draw_roi_window_cursor_radius_change_box.setObjectName( "DrawRoiWindowCursorRadiusChangeBox") # Create a label for cursor radius change self.draw_roi_window_cursor_radius_change_label = QLabel() self.draw_roi_window_cursor_radius_change_label.setObjectName( "DrawRoiWindowCursorRadiusChangeLabel") # Create an input box for cursor radius self.draw_roi_window_cursor_radius_change_input = QLineEdit() self.draw_roi_window_cursor_radius_change_input.setObjectName( "DrawRoiWindowCursorRadiusChangeInput") self.draw_roi_window_cursor_radius_change_input.setText(str(19)) self.draw_roi_window_cursor_radius_change_input.setCursorPosition(0) self.draw_roi_window_cursor_radius_change_input.setEnabled(False) self.draw_roi_window_cursor_radius_change_input.setSizePolicy( QSizePolicy.Minimum, QSizePolicy.Minimum) self.draw_roi_window_cursor_radius_change_input.resize( self.draw_roi_window_cursor_radius_change_input.sizeHint().width(), self.draw_roi_window_cursor_radius_change_input.sizeHint().height( )) # Create 2 buttons for increasing and reducing cursor radius # Increase Button self.draw_roi_window_cursor_radius_change_increase_button = \ QPushButton() self.draw_roi_window_cursor_radius_change_increase_button. \ setObjectName("DrawRoiWindowCursorRadiusIncreaseButton") self.draw_roi_window_cursor_radius_change_increase_button. \ setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)) self.draw_roi_window_cursor_radius_change_increase_button.resize( QSize(24, 24)) self.draw_roi_window_cursor_radius_change_increase_button.setProperty( "QPushButtonClass", "zoom-button") icon_zoom_in = QtGui.QIcon() icon_zoom_in.addPixmap( QtGui.QPixmap( resource_path('res/images/btn-icons/zoom_in_icon.png'))) self.draw_roi_window_cursor_radius_change_increase_button.setIcon( icon_zoom_in) self.draw_roi_window_cursor_radius_change_increase_button.clicked. \ connect(self.onRadiusIncreaseClicked) # Reduce Button self.draw_roi_window_cursor_radius_change_reduce_button = QPushButton() self.draw_roi_window_cursor_radius_change_reduce_button.setObjectName( "DrawRoiWindowCursorRadiusReduceButton") self.draw_roi_window_cursor_radius_change_reduce_button.setSizePolicy( QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)) self.draw_roi_window_cursor_radius_change_reduce_button.resize( QSize(24, 24)) self.draw_roi_window_cursor_radius_change_reduce_button.setProperty( "QPushButtonClass", "zoom-button") icon_zoom_out = QtGui.QIcon() icon_zoom_out.addPixmap( QtGui.QPixmap( resource_path('res/images/btn-icons/zoom_out_icon.png'))) self.draw_roi_window_cursor_radius_change_reduce_button.setIcon( icon_zoom_out) self.draw_roi_window_cursor_radius_change_reduce_button.clicked. \ connect(self.onRadiusReduceClicked) self.draw_roi_window_cursor_radius_change_box.addWidget( self.draw_roi_window_cursor_radius_change_label) self.draw_roi_window_cursor_radius_change_box.addWidget( self.draw_roi_window_cursor_radius_change_input) self.draw_roi_window_cursor_radius_change_box.addWidget( self.draw_roi_window_cursor_radius_change_reduce_button) self.draw_roi_window_cursor_radius_change_box.addWidget( self.draw_roi_window_cursor_radius_change_increase_button) self.draw_roi_window_input_container_box.addRow( self.draw_roi_window_cursor_radius_change_box) self.draw_roi_window_cursor_radius_change_increase_button.setEnabled( False) self.draw_roi_window_cursor_radius_change_reduce_button.setEnabled( False)
def fillTables(self): # Fill the Windowing table with open(resource_path("src/data/csv/imageWindowing.csv"), "r") as fileInput: next(fileInput) i = 0 for row in fileInput: items = [ QTableWidgetItem(str(item.replace("\n", ""))) for item in row.split(",") ] self.table_view.insertRow(i) self.table_view.setItem(i, 0, items[0]) self.table_view.setItem(i, 1, items[1]) self.table_view.setItem(i, 2, items[2]) self.table_view.setItem(i, 3, items[3]) i += 1 # organ names table with open(resource_path("src/data/csv/organName.csv"), "r") as fileInput: next(fileInput) i = 0 for row in fileInput: items = [ QTableWidgetItem(str(item.replace("\n", ""))) for item in row.split(",") ] self.table_organ.insertRow(i) self.table_organ.setItem(i, 0, items[0]) self.table_organ.setItem(i, 1, items[1]) self.table_organ.setItem(i, 2, items[2]) if len(items) > 3: self.table_organ.setItem(i, 3, items[3]) i += 1 # volume name table with open(resource_path("src/data/csv/volumeName.csv"), "r") as fileInput: i = 0 for row in fileInput: items = [ QTableWidgetItem(str(item.replace("\n", ""))) for item in row.split(",") ] self.table_volume.insertRow(i) self.table_volume.setItem(i, 0, items[0]) self.table_volume.setItem(i, 1, items[1]) i += 1 # roi isodose table, TO DO in the future # with open('src/data/csv/isodoseRoi.csv', "r") as fileInput: # i = 0; # for row in fileInput: # items = [ # QTableWidgetItem(str(item.replace('\n', ''))) # for item in row.split(',') # ] # self.table_roi.insertRow(i) # self.table_roi.setItem(i, 0, items[0]) # self.table_roi.setItem(i, 1, items[1]) # if len(items) > 2: # self.table_roi.setItem(i, 2, items[2]) # i += 1 # patient hash ID table, which is just for displaying all the patients anonymized byt the software since intallation with open(resource_path("src/data/csv/patientHash.csv"), "r") as fileInput: next(fileInput) i = 0 for row in fileInput: items = [ QTableWidgetItem(str(item.replace("\n", ""))) for item in row.split(",") ] if len(items) >= 2: self.table_Ids.insertRow(i) self.table_Ids.setItem(i, 0, items[0]) self.table_Ids.setItem(i, 1, items[1]) i += 1
def roi_display(self): """ Display ROI structures on the DICOM Image. """ slider_id = self.slider.value() curr_slice = self.patient_dict_container.get("dict_uid")[slider_id] selected_rois = self.patient_dict_container.get("selected_rois") rois = self.patient_dict_container.get("rois") selected_rois_name = [] for roi in selected_rois: selected_rois_name.append(rois[roi]['name']) for roi in selected_rois: roi_name = rois[roi]['name'] if roi_name not in self.patient_dict_container.get( "dict_polygons").keys(): new_dict_polygons = self.patient_dict_container.get( "dict_polygons") new_dict_polygons[roi_name] = {} dict_rois_contours = get_contour_pixel( self.patient_dict_container.get("raw_contour"), selected_rois_name, self.patient_dict_container.get("pixluts"), curr_slice) polygons = self.calc_roi_polygon(roi_name, curr_slice, dict_rois_contours) new_dict_polygons[roi_name][curr_slice] = polygons self.patient_dict_container.set("dict_polygons", new_dict_polygons) elif curr_slice not in self.patient_dict_container.get( "dict_polygons")[roi_name].keys(): new_dict_polygons = self.patient_dict_container.get( "dict_polygons") dict_rois_contours = get_contour_pixel( self.patient_dict_container.get("raw_contour"), selected_rois_name, self.patient_dict_container.get("pixluts"), curr_slice) polygons = self.calc_roi_polygon(roi_name, curr_slice, dict_rois_contours) new_dict_polygons[roi_name][curr_slice] = polygons self.patient_dict_container.set("dict_polygons", new_dict_polygons) else: polygons = self.patient_dict_container.get( "dict_polygons")[roi_name][curr_slice] color = self.patient_dict_container.get("roi_color_dict")[roi] with open(resource_path('src/data/line&fill_configuration'), 'r') as stream: elements = stream.readlines() if len(elements) > 0: roi_line = int(elements[0].replace('\n', '')) roi_opacity = int(elements[1].replace('\n', '')) line_width = float(elements[4].replace('\n', '')) else: roi_line = 1 roi_opacity = 10 line_width = 2.0 stream.close() roi_opacity = int((roi_opacity / 100) * 255) color.setAlpha(roi_opacity) pen = self.get_qpen(color, roi_line, line_width) for i in range(len(polygons)): self.scene.addPolygon(polygons[i], pen, QtGui.QBrush(color))