Skip to content

Commit

Permalink
Including study loading integration test and resources. Trying to run…
Browse files Browse the repository at this point in the history
… on MacOS [skip ci]
  • Loading branch information
dbouget committed Oct 4, 2024
1 parent ba80c41 commit a351438
Show file tree
Hide file tree
Showing 7 changed files with 118 additions and 75 deletions.
8 changes: 8 additions & 0 deletions .github/workflows/build_macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,14 @@ jobs:
pip install matplotlib==3.3.4
pip install --force-reinstall --no-cache-dir pyside6
- name: Integration tests
env:
DISPLAY: ':99.0'
run: |
pip install pytest-qt pytest-cov
/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -screen 0 1920x1200x24 -ac +extension GLX
pytest --cov=gui ${{github.workspace}}/integration_tests
- name: Build software
run: |
pip install pyinstaller==5.13.2
Expand Down
5 changes: 2 additions & 3 deletions gui/RaidionicsMainWindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -468,10 +468,9 @@ def __on_patient_selected(self, patient_uid: str) -> None:
Internal unique identifier for the patient that should be visualized.
"""
SoftwareConfigResources.getInstance().set_active_patient(patient_uid=patient_uid)
self.__on_single_patient_clicked()
self.single_patient_widget.on_patient_selected(patient_uid)

SoftwareConfigResources.getInstance().set_active_patient(patient_uid=patient_uid)

def __on_community_action_triggered(self):
popup = ResearchCommunityDialog(self)
Expand Down Expand Up @@ -510,7 +509,7 @@ def __on_save_file_triggered(self):
SoftwareConfigResources.getInstance().get_active_study().save()

def __on_download_example_data(self):
QDesktopServices.openUrl(QUrl("https://drive.google.com/file/d/1W3klW_F7Rfge9-utczz9qp7uWh-pVPS1/view?usp=sharing"))
QDesktopServices.openUrl(QUrl("https://github.com/raidionics/Raidionics-models/releases/download/v1.3.0-rc/Samples-Raidionics-ApprovedExample-v1.3.zip"))

def on_process_log_message(self, log_msg: str) -> None:
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -232,8 +232,11 @@ def on_external_patient_selection(self, patient_id):
When the patient selection has been requested from a module (e.g. study) outside the single-use mode.
"""
self.__on_patient_selection(True, patient_id)
self.patient_results_widgets[patient_id].manual_header_pushbutton_clicked(True)
self.adjustSize() # To trigger a proper redrawing after the previous call
# Next two lines are not the cleanest, but it seems to work. @TODO. Have to improve this part.
self.patient_results_widgets[patient_id].header.expand()
self.patient_results_widgets[patient_id].set_stylesheets(True)
# To trigger a proper redrawing after the previous call
self.adjustSize()

def on_process_started(self):
self.bottom_add_patient_pushbutton.setEnabled(False)
Expand Down Expand Up @@ -313,7 +316,6 @@ def __on_patient_selection(self, state: bool, widget_id: str) -> None:
if not state:
return

# @TODO. The following should be disabled if viewing a patient coming from the Study widget... has to be adjusted
if SoftwareConfigResources.getInstance().get_active_patient_uid() != None and SoftwareConfigResources.getInstance().get_active_patient_uid() == widget_id:
return

Expand Down
2 changes: 2 additions & 0 deletions gui/SinglePatientComponent/SinglePatientWidget.py
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,8 @@ def on_reload_interface(self) -> None:

def on_patient_selected(self, patient_name):
self.results_panel.on_external_patient_selection(patient_name)
self.center_panel.on_patient_selected(patient_name)
self.layers_panel.on_patient_selected(patient_name)

def on_single_patient_clicked(self, patient_name):
# @TODO. Renaming to do, confusing name since it adds a new patient...
Expand Down
88 changes: 88 additions & 0 deletions integration_tests/batch_study_loading_study_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import os
import shutil
from time import sleep

import requests
import zipfile

import pytest
from PySide6.QtCore import Qt

from gui.RaidionicsMainWindow import RaidionicsMainWindow
from gui.UtilsWidgets.CustomQDialog.ImportDataQDialog import ImportDataQDialog
from utils.software_config import SoftwareConfigResources
from utils.data_structures.UserPreferencesStructure import UserPreferencesStructure

def_loc = UserPreferencesStructure.getInstance().user_home_location

@pytest.fixture
def test_location():
test_loc = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'integrationtests')
UserPreferencesStructure.getInstance().user_home_location = test_loc
if os.path.exists(test_loc):
shutil.rmtree(test_loc)
os.makedirs(test_loc)
return test_loc

@pytest.fixture
def test_data_folder():
test_data_url = 'https://github.com/raidionics/Raidionics-models/releases/download/v1.3.0-rc/Samples-Raidionics-ApprovedExample-v1.3.zip'
test_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'integrationtests')
test_data_dir = os.path.join(test_dir, 'ApprovedExample')
if os.path.exists(test_data_dir) and len(os.listdir(test_data_dir)) > 0:
return test_data_dir

archive_dl_dest = os.path.join(test_dir, 'raidionics_resources.zip')
headers = {}
response = requests.get(test_data_url, headers=headers, stream=True)
response.raise_for_status()
if response.status_code == requests.codes.ok:
with open(archive_dl_dest, "wb") as f:
for chunk in response.iter_content(chunk_size=1048576):
f.write(chunk)
with zipfile.ZipFile(archive_dl_dest, 'r') as zip_ref:
zip_ref.extractall(test_dir)
return test_data_dir


@pytest.fixture
def window():
"""
"""
window = RaidionicsMainWindow()
return window

"""
Remaining tests to add:
* Import patient and jump to patient view and assert that the MRIs are correctly displayed (not working now)
"""


def test_study_reloading(qtbot, test_location, test_data_folder, window):
"""
Creation of a new empty patient.
"""
qtbot.addWidget(window)

# Entering the batch study widget view
qtbot.mouseClick(window.welcome_widget.left_panel_multiple_patients_pushbutton, Qt.MouseButton.LeftButton)

# Importing existing study from Add study > Existing study (*.sraidionics)
# window.batch_study_widget.results_panel.add_existing_study_actionadd_raidionics_patient_action.trigger() <= Cannot use the actual pushbutton action as it would open the QDialog...
raidionics_filename = os.path.join(test_data_folder, 'Raidionics', "studies", "study1", "study1_study.sraidionics")
window.batch_study_widget.import_data_dialog.reset()
window.batch_study_widget.import_data_dialog.set_parsing_filter("study")
window.batch_study_widget.import_data_dialog.setup_interface_from_files([raidionics_filename])
window.batch_study_widget.import_data_dialog.__on_exit_accept_clicked()
sleep(10)
assert len(list(SoftwareConfigResources.getInstance().get_active_study().included_patients_uids.keys())) == 2

def test_cleanup(window):
if window.logs_thread.isRunning():
window.logs_thread.stop()
sleep(2)
UserPreferencesStructure.getInstance().user_home_location = def_loc
test_loc = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'integrationtests')
if os.path.exists(test_loc):
shutil.rmtree(test_loc)
8 changes: 8 additions & 0 deletions integration_tests/single_patient_empty_patient_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,13 @@ def window():
return window


""" Remaining tests to add
# * Loading data from DICOM folder (must add a DICOM folder in the test data package
# * Adding extra MRI volume from the same DICOM folder afterwards
# * Open a new DICOM folder
# * Delete an image
"""

def test_empty_patient_creation(qtbot, test_location, window):
"""
Creation of a new empty patient.
Expand Down Expand Up @@ -185,6 +192,7 @@ def test_empty_patient_timestamp_data_inclusion(qtbot, test_location, test_data_
# Saving the latest modifications to the patient on disk by pressing the disk icon
qtbot.mouseClick(window.single_patient_widget.results_panel.get_patient_results_widget_by_index(0).save_patient_pushbutton, Qt.MouseButton.LeftButton)


def test_cleanup(window):
"""
To delete the temporary resources needed for running the different tests and to prevent Core dumped error when
Expand Down
74 changes: 5 additions & 69 deletions integration_tests/single_patient_patient_loading_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ def window():
window = RaidionicsMainWindow()
return window

""" Remaining tests to add:
# * Changing display space from Patient to MNI and back
# * Changing the parent MRI for annotation files
# * Deleting an annotation
"""

def test_patient_loading_from_files(qtbot, test_location, test_data_folder, window):
"""
Expand Down Expand Up @@ -126,75 +131,6 @@ def test_patient_loading_from_raidionics(qtbot, test_location, test_data_folder,
# Saving the latest modifications to the patient on disk by pressing the disk icon
qtbot.mouseClick(window.single_patient_widget.results_panel.get_patient_results_widget_by_index(0).save_patient_pushbutton, Qt.MouseButton.LeftButton)


# def test_annotation_loading(qtbot, test_location, test_data_folder, window):
# """
# Loading two annotation files for the patient, changing the parent radiological volume for both
# """
# qtbot.addWidget(window)
# # Entering the single patient widget view
# qtbot.mouseClick(window.welcome_widget.left_panel_single_patient_pushbutton, Qt.MouseButton.LeftButton)
#
# # Importing MRI files from Import patient > Other data type (*.nii)
# # window.single_patient_widget.results_panel.add_other_data_action.trigger() <= Cannot use the actual pushbutton action as it would open the QDialog...
# window.single_patient_widget.results_panel.on_add_new_empty_patient()
#
# # Loading the radiological volumes first
# flair_sample_mri_filename = os.path.join(test_data_folder, 'Raw', 'Case27-FLAIR.nii.gz')
# t1_sample_mri_filename = os.path.join(test_data_folder, 'Raw', 'Case27-T1.nii.gz')
# window.single_patient_widget.import_data_dialog.setup_interface_from_files([flair_sample_mri_filename, t1_sample_mri_filename])
# window.single_patient_widget.import_data_dialog.__on_exit_accept_clicked()
#
# window.single_patient_widget.import_data_dialog.reset()
# tumor_annotation_filename = os.path.join(test_data_folder, 'Raidionics', 'patients', 'patient0', 'PreOp', 'raw', 'Case27-T1_annotation-Tumor.nii.gz')
# brain_annotation_filename = os.path.join(test_data_folder, 'Raidionics', 'patients', 'patient0', 'PreOp', 'raw', 'Case27-T1_annotation-Brain.nii.gz')
# window.single_patient_widget.import_data_dialog.setup_interface_from_files(
# [brain_annotation_filename, tumor_annotation_filename])
# window.single_patient_widget.import_data_dialog.__on_exit_accept_clicked()
# assert len(list(SoftwareConfigResources.getInstance().get_active_patient().annotation_volumes.keys())) == 2
#
# # Changing the display name for the T1-CE MRI volume to case27-t1c
# window.single_patient_widget.layers_panel.timestamp_layer_widget.timestamps_widget[
# list(window.single_patient_widget.layers_panel.timestamp_layer_widget.timestamps_widget.keys())[
# 0]].volumes_collapsiblegroupbox.volumes_widget[
# list(window.single_patient_widget.layers_panel.timestamp_layer_widget.timestamps_widget[
# list(window.single_patient_widget.layers_panel.timestamp_layer_widget.timestamps_widget.keys())[
# 0]].volumes_collapsiblegroupbox.volumes_widget.keys())[0]].display_name_lineedit.setText("case27-t1c")
# qtbot.keyClick(window.single_patient_widget.layers_panel.timestamp_layer_widget.timestamps_widget[
# list(window.single_patient_widget.layers_panel.timestamp_layer_widget.timestamps_widget.keys())[
# 0]].volumes_collapsiblegroupbox.volumes_widget[
# list(window.single_patient_widget.layers_panel.timestamp_layer_widget.timestamps_widget[
# list(window.single_patient_widget.layers_panel.timestamp_layer_widget.timestamps_widget.keys())[
# 0]].volumes_collapsiblegroupbox.volumes_widget.keys())[0]].display_name_lineedit, Qt.Key_Enter)
#
# # Changing the display name for the FLAIR MRI volume to case27-flair
# window.single_patient_widget.layers_panel.timestamp_layer_widget.timestamps_widget[
# list(window.single_patient_widget.layers_panel.timestamp_layer_widget.timestamps_widget.keys())[
# 0]].volumes_collapsiblegroupbox.volumes_widget[
# list(window.single_patient_widget.layers_panel.timestamp_layer_widget.timestamps_widget[
# list(window.single_patient_widget.layers_panel.timestamp_layer_widget.timestamps_widget.keys())[
# 0]].volumes_collapsiblegroupbox.volumes_widget.keys())[1]].display_name_lineedit.setText("case27-flair")
# qtbot.keyClick(window.single_patient_widget.layers_panel.timestamp_layer_widget.timestamps_widget[
# list(window.single_patient_widget.layers_panel.timestamp_layer_widget.timestamps_widget.keys())[
# 0]].volumes_collapsiblegroupbox.volumes_widget[
# list(window.single_patient_widget.layers_panel.timestamp_layer_widget.timestamps_widget[
# list(window.single_patient_widget.layers_panel.timestamp_layer_widget.timestamps_widget.keys())[
# 0]].volumes_collapsiblegroupbox.volumes_widget.keys())[1]].display_name_lineedit, Qt.Key_Enter)
#
# # Changing the ownership to the brain annotation
# window.single_patient_widget.layers_panel.timestamp_layer_widget.timestamps_widget[
# list(window.single_patient_widget.layers_panel.timestamp_layer_widget.timestamps_widget.keys())[
# 0]].annotations_collapsiblegroupbox.volumes_widget[
# list(window.single_patient_widget.layers_panel.timestamp_layer_widget.timestamps_widget[
# list(window.single_patient_widget.layers_panel.timestamp_layer_widget.timestamps_widget.keys())[
# 0]].annotations_collapsiblegroupbox.volumes_widget.keys())[0]].parent_image_combobox.setCurrentIndex(1)
# assert len(SoftwareConfigResources.getInstance().get_active_patient().get_specific_annotations_for_mri(mri_volume_uid=SoftwareConfigResources.getInstance().get_active_patient().mri_volumes[SoftwareConfigResources.getInstance().get_active_patient().get_mri_by_display_name("case27-t1c")], annotation_class=AnnotationClassType.Brain)) == 1
#
# # Saving the latest modifications to the patient on disk by pressing the disk icon
# qtbot.mouseClick(window.single_patient_widget.results_panel.patient_results_widgets[
# list(window.single_patient_widget.results_panel.patient_results_widgets.keys())[
# 0]].save_patient_pushbutton, Qt.MouseButton.LeftButton)

def test_cleanup(window):
if window.logs_thread.isRunning():
window.logs_thread.stop()
Expand Down

0 comments on commit a351438

Please sign in to comment.