Esempio n. 1
0
    def create_change_default_directory_frame(self):
        config = Configuration()
        default_directory = None
        try:
            default_directory = config.get_default_directory()
        except SqlError:
            config.set_up_config_db()
            QtWidgets.QMessageBox.critical(
                self.window, "Config file error",
                """Failed to access configuration file.
                \nConfiguration file recreated with no default directory.
                \nPlease update your default directory.""")

        self.window.change_default_directory_frame = QtWidgets.QFrame()
        self.window.change_default_directory_frame.setVisible(False)
        self.change_default_directory_vertical_layout = QtWidgets.QVBoxLayout()
        self.change_default_directory_prompt = QtWidgets.QLabel()
        self.change_default_directory_prompt.setAlignment(QtCore.Qt.AlignLeft)
        self.change_default_directory_prompt.setVisible(True)
        self.change_default_directory_prompt.setText(
            "Default directory's path:")
        self.change_default_directory_vertical_layout.addWidget(
            self.change_default_directory_prompt)
        # Create a horizontal box to hold the input box for the
        # directory and the choose button
        self.change_default_directory_input_horizontal_box = \
            QtWidgets.QHBoxLayout()

        # Create a textbox to contain the path to the directory that
        # contains the DICOM files
        self.change_default_directory_input_box = \
            UIChangeDefaultDirDragAndDropEvent(self)
        self.change_default_directory_input_box.setCursorPosition(0)
        self.change_default_directory_input_box.setText(default_directory)
        self.change_default_directory_input_horizontal_box.addWidget(
            self.change_default_directory_input_box)

        # Create a choose button to open the file dialog
        self.change_default_directory_button = QtWidgets.QPushButton()
        self.change_default_directory_button.setText("Change")
        self.change_default_directory_button.resize(
            self.change_default_directory_button.sizeHint().width(),
            self.change_default_directory_input_box.height())
        self.change_default_directory_button.setCursor(
            QtGui.QCursor(QtCore.Qt.PointingHandCursor))
        self.change_default_directory_input_horizontal_box.addWidget(
            self.change_default_directory_button)
        self.change_default_directory_button.clicked.connect(
            self.change_button_clicked)

        # Create a widget to hold the input fields
        self.change_default_directory_input_widget = QtWidgets.QWidget()
        self.change_default_directory_input_horizontal_box.setStretch(0, 4)
        self.change_default_directory_input_widget.setLayout(
            self.change_default_directory_input_horizontal_box)
        self.change_default_directory_vertical_layout.addWidget(
            self.change_default_directory_input_widget, 1, QtCore.Qt.AlignTop)

        self.window.change_default_directory_frame.setLayout(
            self.change_default_directory_vertical_layout)
Esempio n. 2
0
def init_first_time_window_config(request):
    configuration = Configuration('TestFirstTimeWelcomeWindow.db')
    db_file_path = os.environ['USER_HIDDEN'] + 'TestFirstTimeWelcomeWindow.db'
    configuration.set_db_file_path(db_file_path)

    def tear_down():
        if os.path.isfile(db_file_path):
            os.remove(db_file_path)

    request.addfinalizer(tear_down)
def test_get_default_directory(init_sqlite_config):
    configuration = Configuration()
    new_default_dir = "/home/test/dir"
    # Insert new default dir
    init_sqlite_config.execute("""INSERT INTO configuration (id, default_dir) 
                                    VALUES (1, "%s");""" % new_default_dir)
    init_sqlite_config.commit()

    # Get default dir from configuration object
    result = configuration.get_default_directory()

    # Compare the value returned from get_default_directory() and the value from database
    assert result == new_default_dir
def test_update_default_directory(init_sqlite_config):
    configuration = Configuration()
    new_default_dir = "/home/test/dir"
    # Update default_dir with configuration object
    configuration.update_default_directory(new_default_dir)

    # Select default dir from the database
    cursor = init_sqlite_config.cursor()
    cursor.execute("SELECT default_dir FROM CONFIGURATION WHERE id = 1")
    record = cursor.fetchone()

    # Check if the value from database is equal to the one that we want to update into
    assert record[0] == new_default_dir
Esempio n. 5
0
def init_sqlite_config(request):
    configuration = Configuration('TestSqliteConfig.db')
    db_file_path = os.environ['USER_HIDDEN'] + 'TestSqliteConfig.db'
    configuration.set_db_file_path(db_file_path)
    connection = sqlite3.connect(db_file_path)

    def tear_down():
        connection.close()
        if os.path.isfile(db_file_path):
            os.remove(db_file_path)

    request.addfinalizer(tear_down)
    return connection
    def save_options(self):
        """
        Saves options selected in the first time welcome window.
        """
        self.filepath = self.first_time_welcome_input_box.text()
        self.csv_path = self.clinical_data_csv_input_box.text()
        if self.filepath == "" and self.csv_path == "":
            QMessageBox.about(self, "Unable to proceed",
                              "No directories selected.")
        elif not os.path.exists(self.filepath) or not \
                os.path.exists(self.csv_path):
            QMessageBox.about(self, "Unable to proceed",
                              "Directories do not exist")
        else:
            config = Configuration()
            try:
                config.update_default_directory(self.filepath)

                # Update CSV path if it exists
                if self.csv_path != "" and os.path.exists(self.csv_path):
                    config.update_clinical_data_csv_dir(self.csv_path)
            except SqlError:
                config.set_up_config_db()
                QMessageBox.critical(
                    self, "Config file error",
                    "Failed to access configuration file.\nPlease try again.")
            else:
                self.configured.emit(self.filepath)
def test_error_handling(init_sqlite_config):
    # Drop database file to reproduce SQL error
    configuration = Configuration()
    cursor = init_sqlite_config.cursor()

    # Lock the database to trigger SqlError
    cursor.execute("""PRAGMA locking_mode = EXCLUSIVE;""")
    cursor.execute("""BEGIN EXCLUSIVE;""")
    with pytest.raises(SqlError):
        configuration.get_default_directory()
    with pytest.raises(SqlError):
        configuration.update_default_directory('')
Esempio n. 8
0
def init_config(request):
    configuration = Configuration('TestConfig.db')
    db_file_path = os.environ['USER_HIDDEN'] + 'TestConfig.db'
    configuration.set_db_file_path(db_file_path)
    connection = sqlite3.connect(db_file_path)
    configuration.update_default_directory("../testdata/DICOM-RT-TEST")

    def tear_down():
        connection.close()
        if os.path.isfile(db_file_path):
            os.remove(db_file_path)

    request.addfinalizer(tear_down)
    return connection
Esempio n. 9
0
def init_config(request):
    configuration = Configuration('TestConfig.db')
    db_file_path = Path(
        os.environ['USER_ONKODICOM_HIDDEN']).joinpath('TestConfig.db')
    configuration.set_db_file_path(db_file_path)
    connection = sqlite3.connect(db_file_path)
    configuration.update_default_directory(Path.cwd().joinpath(
        'test', 'testdata'))

    def tear_down():
        connection.close()
        if os.path.isfile(db_file_path):
            os.remove(db_file_path)

    request.addfinalizer(tear_down)
    return connection
 def save_default_dir(self):
     self.filepath = self.first_time_welcome_input_box.text()
     if self.filepath == "":
         QMessageBox.about(self, "Unable to proceed",
                           "No directory selected.")
     elif not os.path.exists(self.filepath):
         QMessageBox.about(self, "Unable to proceed",
                           "Directory does not exist")
     else:
         config = Configuration()
         try:
             config.update_default_directory(self.filepath)
         except SqlError:
             config.set_up_config_db()
             QMessageBox.critical(
                 self, "Config file error",
                 "Failed to access configuration file.\nPlease try again.")
         else:
             self.configured.emit(self.filepath)
Esempio n. 11
0
    def import_clinical_data(self):
        """
        Attempt to import clinical data from the CSV stored in the
        program's settings database.
        """
        # Return if there is no RTDOSE in the dataset
        patient_dict_container = PatientDictContainer()
        if 'rtdose' not in list(patient_dict_container.dataset.keys()):
            message = "No RTDOSE found. Clinical data is only imported for " \
                      "datasets that include an RTDOSE."
            attrib = QtWidgets.QTableWidgetItem("Warning")
            value = QtWidgets.QTableWidgetItem(message)
            self.table_cd.insertRow(0)
            self.table_cd.setItem(0, 0, attrib)
            self.table_cd.setItem(0, 1, value)
            return

        # Return if data has been imported from DICOM SR
        if self.table_populated:
            return

        # Clear data dictionary and table
        self.data_dict = {}
        self.clear_table()

        # Current patient's ID
        patient_id = patient_dict_container.dataset[0].PatientID

        # Try get the clinical data CSV file path
        try:
            config = Configuration()
            file_path = config.get_clinical_data_csv_dir()
        except SqlError:
            # Write warning to table
            message = "Failed to access configuration file."
            attrib = QtWidgets.QTableWidgetItem("Warning")
            value = QtWidgets.QTableWidgetItem(message)
            self.table_cd.insertRow(0)
            self.table_cd.setItem(0, 0, attrib)
            self.table_cd.setItem(0, 1, value)
            return

        # Get CSV data
        if file_path == "" or file_path is None \
                or not os.path.exists(file_path):
            # Clear table
            self.clear_table()

            # Write warning to table
            message = "Clinical data CSV could not be found."
            attrib = QtWidgets.QTableWidgetItem("Warning")
            value = QtWidgets.QTableWidgetItem(message)
            self.table_cd.insertRow(0)
            self.table_cd.setItem(0, 0, attrib)
            self.table_cd.setItem(0, 1, value)
            return

        with open(file_path, newline="") as stream:
            data = list(csv.reader(stream))

        # See if CSV data matches patient ID
        patient_in_file = False
        row_num = 0
        for i, row in enumerate(data):
            if row[0] == patient_id:
                patient_in_file = True
                row_num = i
                break

        # Return if patient's data not in the CSV file
        if not patient_in_file:
            # Clear table
            self.clear_table()

            # Write warning to table
            message = "Patient clinical data not found in CSV."
            attrib = QtWidgets.QTableWidgetItem("Warning")
            value = QtWidgets.QTableWidgetItem(message)
            self.table_cd.insertRow(0)
            self.table_cd.setItem(0, 0, attrib)
            self.table_cd.setItem(0, 1, value)
            return

        # Put patient data into dictionary
        headings = data[0]
        attribs = data[row_num]
        for i, heading in enumerate(headings):
            self.data_dict[heading] = attribs[i]

        # Update table
        self.populate_table()

        # Save clinical data to DICOM SR
        self.save_clinical_data()
Esempio n. 12
0
    os.environ["QT_AUTO_SCREEN_SCALE_FACTOR"] = "1"
    app = QtWidgets.QApplication(sys.argv)

    print("PDPI: " + str(app.primaryScreen().physicalDotsPerInch()))

    # Set the font to Segoe UI, 9, when in windows OS
    if platform.system() == 'Windows':
        f = QFont("Segoe UI", 9)
        app.setFont(f)
    elif platform.system() == 'Darwin':
        f = QFont("Helvetica Neue", 13)
        app.setFont(f)

    if len(sys.argv) > 1:
        controller = Controller(default_directory=sys.argv[1])
        controller.show_open_patient()
    else:
        # Get the default DICOM directory from SQLite database
        # stored in a hidden directory in the user home directory
        configuration = Configuration()
        default_dir = configuration.get_default_directory()
        if default_dir is None:
            controller = Controller()
            controller.show_first_time_welcome()
        else:
            controller = Controller(default_directory=default_dir)
            controller.show_welcome()

    sys.exit(app.exec_())
Esempio n. 13
0
    def create_change_clinical_data_csv_frame(self):
        config = Configuration()
        csv_dir = None

        # Try get the clinical data CSV directory
        try:
            csv_dir = config.get_clinical_data_csv_dir()
        except SqlError:
            config.set_up_config_db()
            QtWidgets.QMessageBox.critical(
                self.window, "Config file error",
                """Failed to access configuration file.
                \nConfiguration file recreated with no default directory.
                \nPlease update your default directory.""")

        # Clinical data prompt text
        text = "Importing Clinical Data\n\nClinical data can be " \
               "automatically imported into the DICOM image set. This " \
               "requires a matching process which is strict (see the User " \
               "Manual). The three requirements are detailed below:\n\n1. " \
               "The Patient's Clinical Data must be stored in the Comma " \
               "Separated Values (CSV) format, which any spreadsheet " \
               "program can produce, including MS Excel.\n\n2. This CSV " \
               "file must contain the patient's identifier in the first " \
               "column, and that first column must be titled \"Patient_ID\"." \
               "\n\n3. The entry in the first CSV column [\"Patient_ID\"] " \
               "must match the patient identifier in the DICOM dataset.\n\n" \
               "4. The CSV file must contain the ICD10 code in the second " \
               "column, and that column must be named \"ICD10\"."

        # Create the frame
        self.window.clinical_data_csv_dir_frame = QtWidgets.QFrame()
        self.window.clinical_data_csv_dir_frame.setVisible(False)

        # Create the layout
        self.clinical_data_csv_layout = QtWidgets.QVBoxLayout()
        self.change_clinical_data_csv_dir_prompt = QtWidgets.QLabel()
        self.change_clinical_data_csv_dir_prompt.setAlignment(
            QtCore.Qt.AlignJustify)
        self.change_clinical_data_csv_dir_prompt.setVisible(True)
        self.change_clinical_data_csv_dir_prompt.setMaximumWidth(
            self.window.clinical_data_csv_dir_frame.width() - 10)
        self.change_clinical_data_csv_dir_prompt.setText(text)
        self.change_clinical_data_csv_dir_prompt.setWordWrap(True)
        self.clinical_data_csv_layout.addWidget(
            self.change_clinical_data_csv_dir_prompt)

        # Create a horizontal box to hold the input box for the
        # directory and the choose button
        self.clinical_data_csv_dir_input_layout = QtWidgets.QHBoxLayout()

        # Create a textbox to contain the path to the directory that
        # contains the DICOM files
        self.clinical_data_csv_dir_input_box = \
            UIChangeDefaultDirDragAndDropEvent(self)
        self.clinical_data_csv_dir_input_box.setCursorPosition(0)
        self.clinical_data_csv_dir_input_box.setText(csv_dir)
        self.clinical_data_csv_dir_input_layout.addWidget(
            self.clinical_data_csv_dir_input_box)

        # Create a choose button to open the file dialog
        self.clinical_data_csv_dir_button = QtWidgets.QPushButton()
        self.clinical_data_csv_dir_button.setText("Change")
        self.clinical_data_csv_dir_button.resize(
            self.clinical_data_csv_dir_button.sizeHint().width(),
            self.clinical_data_csv_dir_input_box.height())
        self.clinical_data_csv_dir_button.setCursor(
            QtGui.QCursor(QtCore.Qt.PointingHandCursor))
        self.clinical_data_csv_dir_button.clicked.connect(
            self.change_clinical_data_csv_button_clicked)
        self.clinical_data_csv_dir_input_layout.addWidget(
            self.clinical_data_csv_dir_button)

        # Create a widget to hold the input fields
        self.clinical_data_csv_dir_input_widget = QtWidgets.QWidget()
        self.clinical_data_csv_dir_input_widget.setLayout(
            self.clinical_data_csv_dir_input_layout)
        self.clinical_data_csv_layout.addWidget(
            self.clinical_data_csv_dir_input_widget)
        self.clinical_data_csv_layout.addStretch(1)

        # Set the frame's layout
        self.window.clinical_data_csv_dir_frame.setLayout(
            self.clinical_data_csv_layout)