Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Atlas space display #82

Merged
merged 7 commits into from
Sep 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/build_macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ env:
jobs:
build:
name: Build packages
runs-on: macos-11
runs-on: macos-12
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.8
Expand Down Expand Up @@ -72,8 +72,8 @@ jobs:
- name: Make installer
run: |
git clone https://github.com/dbouget/quickpkg.git
quickpkg/quickpkg dist/Raidionics.app --output Raidionics-1.2.3-macOS.pkg
cp -r Raidionics-1.2.3-macOS.pkg dist/Raidionics-1.2.3-macOS-x86_64.pkg
quickpkg/quickpkg dist/Raidionics.app --output Raidionics-1.2.4-macOS.pkg
cp -r Raidionics-1.2.4-macOS.pkg dist/Raidionics-1.2.4-macOS-x86_64.pkg

- name: Upload package
uses: actions/upload-artifact@v4
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/build_macos_arm.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
cd tmp
python3 -m virtualenv -p python3 venv --clear
source venv/bin/activate
python3 -m pip install wheel setuptools
python3 -m pip install wheel setuptools==69.5.1
deactivate

- name: Install dependencies
Expand Down Expand Up @@ -67,8 +67,8 @@ jobs:
- name: Make installer
run: |
git clone https://github.com/dbouget/quickpkg.git
quickpkg/quickpkg dist/Raidionics.app --output Raidionics-1.2.3-macOS.pkg
cp -r Raidionics-1.2.3-macOS.pkg dist/Raidionics-1.2.3-macOS-arm64.pkg
quickpkg/quickpkg dist/Raidionics.app --output Raidionics-1.2.4-macOS.pkg
cp -r Raidionics-1.2.4-macOS.pkg dist/Raidionics-1.2.4-macOS-arm64.pkg

- name: Upload package
uses: actions/upload-artifact@v4
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/build_ubuntu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ jobs:
cp -r dist/Raidionics assets/Raidionics_ubuntu/usr/local/bin
dpkg-deb --build --root-owner-group assets/Raidionics_ubuntu
ls -la
cp -r assets/Raidionics_ubuntu.deb dist/Raidionics-1.2.3-ubuntu.deb
cp -r assets/Raidionics_ubuntu.deb dist/Raidionics-1.2.4-ubuntu.deb

- name: Upload package
uses: actions/upload-artifact@v4
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/build_windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ jobs:
- name: Make installer
run: |
makensis.exe assets/Raidionics.nsi
cp -r assets/Raidionics-1.2.3-win.exe dist/Raidionics-1.2.3-win.exe
cp -r assets/Raidionics-1.2.4-win.exe dist/Raidionics-1.2.4-win.exe

- name: Upload package
uses: actions/upload-artifact@v4
Expand Down
2 changes: 1 addition & 1 deletion assets/Raidionics.nsi
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
!define COMP_NAME "SINTEF"
!define VERSION "1.2.2"
!define DESCRIPTION "Application"
!define INSTALLER_NAME "Raidionics-1.2.3-win.exe"
!define INSTALLER_NAME "Raidionics-1.2.4-win.exe"
!define MAIN_APP_EXE "Raidionics.exe"
!define INSTALL_TYPE "SetShellVarContext current"
!define REG_ROOT "HKLM"
Expand Down
2 changes: 1 addition & 1 deletion assets/main.spec
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ if sys.platform == "darwin":
'CFBundleIdentifier': 'Raidionics',
'CFBundleInfoDictionaryVersion': '6.0',
'CFBundleName': 'Raidionics',
'CFBundleVersion': '1.2.3',
'CFBundleVersion': '1.2.4',
'CFBundlePackageType': 'APPL',
'LSBackgroundOnly': 'false',
},
Expand Down
2 changes: 1 addition & 1 deletion assets/main_arm.spec
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ if sys.platform == "darwin":
'CFBundleIdentifier': 'Raidionics',
'CFBundleInfoDictionaryVersion': '6.0',
'CFBundleName': 'Raidionics',
'CFBundleVersion': '1.2.3',
'CFBundleVersion': '1.2.4',
'CFBundlePackageType': 'APPL',
'LSBackgroundOnly': 'false',
},
Expand Down
37 changes: 33 additions & 4 deletions gui/RaidionicsMainWindow.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import sys, os
from PySide6.QtWidgets import QApplication, QLabel, QMainWindow, QMenuBar, QMessageBox,\
QHBoxLayout, QVBoxLayout, QStackedWidget, QSizePolicy
QHBoxLayout, QVBoxLayout, QStackedWidget, QSizePolicy, QDialog, QErrorMessage
from PySide6.QtCore import QUrl, QSize, QThread, Signal, Qt
from PySide6.QtGui import QIcon, QDesktopServices, QCloseEvent, QAction
import traceback
Expand All @@ -9,9 +9,13 @@
import numpy as np
import logging
import warnings

from utils.data_structures.UserPreferencesStructure import UserPreferencesStructure

warnings.simplefilter(action='ignore', category=FutureWarning)

from utils.software_config import SoftwareConfigResources
from gui.LogReaderThread import LogReaderThread
from gui.WelcomeWidget import WelcomeWidget
from gui.SinglePatientComponent.SinglePatientWidget import SinglePatientWidget
from gui.StudyBatchComponent.StudyBatchWidget import StudyBatchWidget
Expand Down Expand Up @@ -39,7 +43,7 @@ def stop(self):


class RaidionicsMainWindow(QMainWindow):

reload_interface = Signal()
new_patient_clicked = Signal(str) # Internal unique_id of the clicked patient

def __init__(self, application, *args, **kwargs):
Expand All @@ -49,6 +53,8 @@ def __init__(self, application, *args, **kwargs):
self.app.setWindowIcon(QIcon(os.path.join(os.path.dirname(os.path.realpath(__file__)),
'Images/raidionics-icon.png')))
self.app.setStyle("Fusion") # @TODO: Should we remove Fusion style? Looks strange on macOS
self.logs_thread = LogReaderThread()
self.logs_thread.start()
self.__set_interface()
self.__set_layouts()
self.__set_stylesheet()
Expand Down Expand Up @@ -80,6 +86,7 @@ def __on_exit_software(self) -> None:
"""
Mirroring of the closeEvent, for when the user press the Quit action in the main menu.
"""
self.logs_thread.stop()
if not SoftwareConfigResources.getInstance().is_patient_list_empty()\
and SoftwareConfigResources.getInstance().get_active_patient().has_unsaved_changes():
dialog = SavePatientChangesDialog()
Expand Down Expand Up @@ -322,6 +329,7 @@ def __set_inner_widget_connections(self):
def __cross_widgets_connections(self):
self.welcome_widget.left_panel_single_patient_pushbutton.clicked.connect(self.__on_single_patient_clicked)
self.new_patient_clicked.connect(self.single_patient_widget.on_single_patient_clicked)
self.reload_interface.connect(self.single_patient_widget.on_reload_interface)

self.welcome_widget.left_panel_multiple_patients_pushbutton.clicked.connect(self.__on_study_batch_clicked)
self.welcome_widget.community_clicked.connect(self.__on_community_action_triggered)
Expand All @@ -344,6 +352,8 @@ def __cross_widgets_connections(self):
self.batch_study_widget.patient_report_imported.connect(self.single_patient_widget.patient_report_imported)
self.batch_study_widget.patient_radiological_sequences_imported.connect(self.single_patient_widget.patient_radiological_sequences_imported)

self.logs_thread.message.connect(self.on_process_log_message)

def __set_menubar_connections(self):
self.home_action.triggered.connect(self.__on_home_clicked)
self.single_use_action.triggered.connect(self.__on_single_patient_clicked)
Expand Down Expand Up @@ -427,9 +437,15 @@ def __on_study_batch_clicked(self):
self.adjustSize()

def __on_settings_preferences_clicked(self):
patient_space = UserPreferencesStructure.getInstance().display_space
diag = SoftwareSettingsDialog(self)
diag.exec_()

# Reloading the interface is mainly meant to perform a visual refreshment based on the latest user display choices
# For now: changing the display space for viewing a patient images.
if UserPreferencesStructure.getInstance().display_space != patient_space:
self.reload_interface.emit()

def __on_patient_selected(self, patient_uid: str) -> None:
"""
A patient has been selected in another module than the single patient one in order to be displayed.
Expand Down Expand Up @@ -463,9 +479,9 @@ def __on_help_action_triggered(self) -> None:
def __on_issues_action_triggered(self) -> None:
QDesktopServices.openUrl(QUrl("https://github.com/dbouget/Raidionics/issues"))

def __on_view_logs_triggered(self):
def __on_view_logs_triggered(self) -> None:
"""
@TODO. Should make a custom widget as text edit to see the content of the raidionics log file.
Opens up a pop-up dialog allowing to read through the log file.
"""
diag = LogsViewerDialog(self)
diag.exec_()
Expand All @@ -485,6 +501,19 @@ def __on_save_file_triggered(self):
def __on_download_example_data(self):
QDesktopServices.openUrl(QUrl("https://drive.google.com/file/d/1W3klW_F7Rfge9-utczz9qp7uWh-pVPS1/view?usp=sharing"))

def on_process_log_message(self, log_msg: str) -> None:
"""
Reading the log file on-the-fly to notify the user in case of software or processing issue to make them
aware of it (in case they don't have the reflex to check the log file).
"""
cases = ["[Software warning]", "[Software error]", "[Backend warning]", "[Backend error]"]
if True in [x in log_msg for x in cases]:
diag = QErrorMessage(self)
diag.setWindowTitle("Error or warning identified!")
diag.showMessage(log_msg + "\nPlease visit the log file (Settings > Logs)")
diag.setMinimumSize(QSize(400, 150))
diag.exec()

def standardOutputWritten(self, text):
"""
Redirecting standard output prints to the (correct) displayed widget
Expand Down
3 changes: 3 additions & 0 deletions gui/SinglePatientComponent/CentralAreaWidget.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@ def __set_layout_dimensions(self):
def get_widget_name(self):
return self.widget_name

def on_reload_interface(self):
self.display_area_widget.on_patient_selected()

def on_patient_selected(self, patient_uid):
self.patient_view_toggled.emit(patient_uid)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,14 @@ def on_patient_selected(self):

# Can only be 0 if the active patient is the default (and empty) temp patient created during initialization.
if self.current_patient_parameters.get_patient_mri_volumes_number() != 0:
self.displayed_image = self.current_patient_parameters.get_mri_by_uid(
self.current_patient_parameters.get_all_mri_volumes_uids()[0]).get_display_volume()
self.displayed_image_uid = self.current_patient_parameters.get_mri_by_uid(self.current_patient_parameters.get_all_mri_volumes_uids()[0]).unique_id
# If updating the central panel after selecting a different display space, the same image as currently
# visible should be updated.
if self.displayed_image_uid in self.current_patient_parameters.get_all_mri_volumes_uids():
self.displayed_image = self.current_patient_parameters.get_mri_by_uid(self.displayed_image_uid).get_display_volume()
else: # If an actual new patient selected, the first available image is displayed
self.displayed_image = self.current_patient_parameters.get_mri_by_uid(
self.current_patient_parameters.get_all_mri_volumes_uids()[0]).get_display_volume()
self.displayed_image_uid = self.current_patient_parameters.get_mri_by_uid(self.current_patient_parameters.get_all_mri_volumes_uids()[0]).unique_id
self.point_clicker_position = [int(self.displayed_image.shape[0] / 2),
int(self.displayed_image.shape[1] / 2),
int(self.displayed_image.shape[2] / 2)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,14 @@ def __set_stylesheets(self):
self.setStyleSheet("QGraphicsView{background-color:rgb(0,0,0);}")

def keyPressEvent(self, event) -> None:
"""
Shortcuts for displaying or hiding elements, only if there is an active patient.
S key: display or hide the tumor annotation.
"""
if event.key() == Qt.Key_S:
logging.info("Changing annotations display state.")
self.annotation_display_state_changed.emit()
if not SoftwareConfigResources.getInstance().is_patient_list_empty():
logging.info("Changing annotations display state.")
self.annotation_display_state_changed.emit()

def mousePressEvent(self, event):
"""
Expand Down
9 changes: 9 additions & 0 deletions gui/SinglePatientComponent/SinglePatientWidget.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,14 @@ def __on_patient_selected(self, patient_uid):
self.top_logo_panel_label_import_dicom_pushbutton.setEnabled(True)
self.top_logo_panel_statistics_pushbutton.setEnabled(True)

def on_reload_interface(self) -> None:
"""
In order to generate a new central panel, for example because the display space has changed.
"""
if not SoftwareConfigResources.getInstance().is_patient_list_empty():
SoftwareConfigResources.getInstance().get_active_patient().load_in_memory()
self.center_panel.on_reload_interface()

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

Expand All @@ -293,6 +301,7 @@ def on_process_finished(self) -> None:
self.results_panel.on_process_finished()
# Hides the process tracking to display back the layers interactor for viewing purposes.
self.right_panel_stackedwidget.setCurrentIndex(0)
self.center_panel.on_reload_interface()

def on_batch_process_started(self) -> None:
"""
Expand Down
1 change: 1 addition & 0 deletions gui/UtilsWidgets/CustomQDialog/LogsViewerDialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

class LogsViewerDialog(QDialog):

error_detected = Signal(str)
def __init__(self, parent=None):
super().__init__(parent)
self.setWindowTitle("Runtime logs")
Expand Down
Loading