Example #1
0
    def __init__(self, *args, **kwargs):
        super(CalculateDVHProgressWindow, self).__init__(*args, **kwargs)
        layout = QtWidgets.QVBoxLayout()
        text = QtWidgets.QLabel(
            "Calculating DVHs... (This may take several minutes)")
        layout.addWidget(text)
        self.setWindowTitle("Please wait...")
        self.setLayout(layout)

        self.threadpool = QtCore.QThreadPool()
        self.patient_dict_container = PatientDictContainer()

        dataset_rtss = self.patient_dict_container.dataset["rtss"]
        dataset_rtdose = self.patient_dict_container.dataset["rtdose"]
        rois = self.patient_dict_container.get("rois")

        dict_thickness = ImageLoading.get_thickness_dict(
            dataset_rtss, self.patient_dict_container.dataset)

        interrupt_flag = threading.Event()
        fork_safe_platforms = ['Linux']
        if platform.system() in fork_safe_platforms:
            worker = Worker(ImageLoading.multi_calc_dvh, dataset_rtss,
                            dataset_rtdose, rois, dict_thickness)
        else:
            worker = Worker(ImageLoading.calc_dvhs, dataset_rtss,
                            dataset_rtdose, rois, dict_thickness,
                            interrupt_flag)

        worker.signals.result.connect(self.dvh_calculated)

        self.threadpool.start(worker)
    def load_patient_files(self, path, progress_callback,
                           search_complete_callback):
        """
        Load the patient files from directory.
        """
        # Set the interrup flag
        self.interrupt_flag.set()

        # Release the current thread, and create new threadpool
        self.threadpool.releaseThread()
        self.threadpool = QThreadPool()

        # Clear the interrupt flag
        self.interrupt_flag.clear()

        # Create new worker
        worker = Worker(DICOMDirectorySearch.get_dicom_structure,
                        path,
                        self.interrupt_flag,
                        progress_callback=True)

        # Connect callbacks
        worker.signals.result.connect(search_complete_callback)
        worker.signals.progress.connect(progress_callback)

        # Start the worker
        self.threadpool.start(worker)
Example #3
0
    def scan_directory_for_patient(self):
        # Reset tree view header and last patient
        self.open_patient_window_patients_tree.setHeaderLabels([""])
        self.last_patient = None
        self.filepath = self.open_patient_directory_input_box.text()
        # Proceed if a folder was selected
        if self.filepath != "":
            # Update the QTreeWidget to reflect data being loaded
            # First, clear the widget of any existing data
            self.open_patient_window_patients_tree.clear()

            # Next, update the tree widget
            self.open_patient_window_patients_tree.addTopLevelItem(
                QTreeWidgetItem(["Loading selected directory..."]))

            # The choose button is disabled until the thread finishes executing
            self.open_patient_directory_choose_button.setEnabled(False)

            # Reveals the Stop Search button for the duration of the search
            self.open_patient_window_stop_button.setVisible(True)

            # The interrupt flag is then un-set if a previous search has been stopped.
            self.interrupt_flag.clear()

            # Then, create a new thread that will load the selected folder
            worker = Worker(DICOMDirectorySearch.get_dicom_structure,
                            self.filepath,
                            self.interrupt_flag,
                            progress_callback=True)
            worker.signals.result.connect(self.on_search_complete)
            worker.signals.progress.connect(self.search_progress)

            # Execute the thread
            self.threadpool.start(worker)
Example #4
0
 def start_deleting(self, dataset_rtss, rois_to_delete):
     """
     Creates a thread that generates the new dataset object.
     :param dataset_rtss: Dataset of RTSS
     :param rois_to_delete: List of ROI names to be deleted
     """
     worker = Worker(ROI.delete_list_of_rois, dataset_rtss, rois_to_delete)
     worker.signals.result.connect(self.roi_deleted)
     self.threadpool.start(worker)
Example #5
0
    def start_loading(self, selected_files):
        image_loader = ImageLoader(selected_files)

        worker = Worker(image_loader.load, self.interrupt_flag)
        worker.signals.result.connect(self.on_finish)
        worker.signals.error.connect(self.on_error)
        worker.signals.progress.connect(self.update_progress)

        self.threadpool.start(worker)
Example #6
0
 def start_renaming(self, dataset_rtss, roi_id, new_name):
     """
     Creates a thread that generates the new dataset object.
     :param dataset_rtss: Dataset of RTSS.
     :param roi_id: ID of the ROI to be renamed.
     :param new_name: The name the ROI will be changed to.
     """
     worker = Worker(ROI.rename_roi, dataset_rtss, roi_id, new_name)
     worker.signals.result.connect(self.roi_renamed)
     self.threadpool.start(worker)
 def start_saving(self, dataset_rtss, roi_name, roi_list):
     """
     Creates a thread that generates the new dataset object.
     :param dataset_rtss: dataset of RTSS
     :param roi_name: ROIName
     :param roi_list: list of contours to be saved
     """
     worker = Worker(ROI.create_roi, dataset_rtss, roi_name, roi_list)
     worker.signals.result.connect(self.roi_saved)
     self.threadpool.start(worker)
Example #8
0
    def start_loading(self, selected_files):
        image_loader = ImageLoader(selected_files, self)
        image_loader.signal_request_calc_dvh.connect(self.prompt_calc_dvh)

        worker = Worker(image_loader.load,
                        self.interrupt_flag,
                        progress_callback=True)
        worker.signals.result.connect(self.on_finish)
        worker.signals.error.connect(self.on_error)
        worker.signals.progress.connect(self.update_progress)

        self.threadpool.start(worker)
def test_worker_no_progress_callback(qtbot):
    """
    Testing for the progress_callback parameter not being present in the called function when no progress_callback
    """
    func_to_test = Mock()
    w = Worker(func_to_test, "test", 3)

    threadpool = QThreadPool()
    with qtbot.waitSignal(w.signals.finished) as blocker:
        threadpool.start(w)

    assert w.fn == func_to_test
    assert 'progress_callback' not in w.kwargs
    func_to_test.assert_called_with("test", 3)
Example #10
0
    def start(self, funct):
        """
        Function that executes 'funct' on new thread
        :param funct: function to execute.
        :param progress_callback: signal that receives the current
                                  progress of the loading.
        """
        self.interrupt_flag.clear()
        worker = Worker(funct, self.interrupt_flag, progress_callback=True)
        worker.signals.result.connect(self.on_finish)
        worker.signals.error.connect(self.on_error)
        worker.signals.progress.connect(self.update_progress)

        self.threadpool.start(worker)
        self.exec_()
def test_worker_progress_callback(qtbot):
    """
    Testing for the progress_callback parameter being present in the called function when progress_callback=True
    """
    func_to_test = Mock()
    w = Worker(func_to_test, "test", 3, progress_callback=True)

    # This starts the Worker in the threadpool and then blocks the test from progressing until the finished signal is
    # emitted. qtbot is a pytest fixture used to test PyQt5.
    threadpool = QThreadPool()
    with qtbot.waitSignal(w.signals.finished) as blocker:
        threadpool.start(w)

    assert w.fn == func_to_test
    assert w.kwargs['progress_callback'] is not None
    func_to_test.assert_called_with("test", 3, progress_callback=w.kwargs['progress_callback'])
def test_worker_result_signal(qtbot):
    """
    Testing return value of worker's called function through result signal.
    """
    func_to_test = Mock(return_value=5)
    func_result = Mock()

    w = Worker(func_to_test, "test", 3)
    w.signals.result.connect(func_result)

    threadpool = QThreadPool()
    with qtbot.waitSignal(w.signals.finished) as blocker:
        threadpool.start(w)

    func_to_test.assert_called_with("test", 3)
    func_result.assert_called_with(5)
Example #13
0
def test_worker_result_signal(qtbot, monkeypatch):
    """
    Testing return value of worker's called function through result signal.
    """
    thing = FakeClass()
    thing.func_to_test = Mock(return_value=5, unsafe=True)
    w = Worker(thing.func_to_test, "test", 3)

    with mock.patch.object(FakeClass, 'func_result',
                           wraps=thing.func_result) as mock_func_result:
        w.signals.result.connect(thing.func_result)
        threadpool = QThreadPool()
        with qtbot.waitSignal(w.signals.finished) as blocker:
            threadpool.start(w)

        thing.func_to_test.assert_called_with("test", 3)
        mock_func_result.assert_called_with(5)
def test_worker_error_signal(qtbot):
    """
    Testing return value of worker's called function through result signal.
    """
    func_to_test = Mock(side_effect=ValueError())
    func_error = MagicMock()

    w = Worker(func_to_test, "test", 3)
    w.signals.error.connect(func_error)

    threadpool = QThreadPool()
    with qtbot.waitSignal(w.signals.finished) as blocker:
        threadpool.start(w)

    kall = func_error.call_args
    args, kwargs = kall
    
    func_to_test.assert_called_with("test", 3)
    assert isinstance(args[0][1], ValueError)
Example #15
0
def test_worker_error_signal(qtbot):
    """
    Testing return value of worker's called function through result signal.
    """

    thing = FakeClass()
    thing.func_to_test = Mock(side_effect=ValueError())

    w = Worker(thing.func_to_test, "test", 3)

    with mock.patch.object(FakeClass, 'func_error', wraps=thing.func_error):
        w.signals.error.connect(thing.func_error)
        threadpool = QThreadPool()
        with qtbot.waitSignal(w.signals.finished) as blocker:
            threadpool.start(w)

        kall = thing.func_error.call_args
        args, kwargs = kall

        thing.func_to_test.assert_called_with("test", 3)
        assert isinstance(args[0][1], ValueError)
Example #16
0
    def choose_button_clicked(self):
        """
        Executes when the choose button is clicked.
        Gets filepath from the user and loads all files and subdirectories.
        """
        # Get folder path from pop up dialog box
        self.filepath = QtWidgets.QFileDialog.getExistingDirectory(
            None, 'Select patient folder...', '')
        self.path_text_browser.setText(self.filepath)

        # Proceed if a folder was selected
        if self.filepath != "":
            # Update the QTreeWidget to reflect data being loaded
            # First, clear the widget of any existing data
            self.tree_widget.clear()

            # Next, update the tree widget
            self.tree_widget.addTopLevelItem(
                QTreeWidgetItem(["Loading selected directory..."]))

            # The choose button is disabled until the thread finishes executing
            self.choose_button.setEnabled(False)

            # Reveals the Stop Search button for the duration of the search
            self.stop_button.setVisible(True)

            # The interrupt flag is then un-set if a previous search has been stopped.
            self.interrupt_flag.clear()

            # Then, create a new thread that will load the selected folder
            worker = Worker(DICOMDirectorySearch.get_dicom_structure,
                            self.filepath, self.interrupt_flag)
            worker.signals.result.connect(self.on_search_complete)
            worker.signals.progress.connect(self.search_progress)

            # Execute the thread
            self.threadpool.start(worker)