Skip to content

Commit

Permalink
GBM postop 1p-5p support, added BrainGrid features (#77)
Browse files Browse the repository at this point in the history
* Enabling the use of all 5 GBM postop segmentation models, based on the provided inputs.

* Added support for BrainGrid features

[skip ci]
  • Loading branch information
dbouget authored Jun 7, 2024
1 parent fed761a commit de39253
Show file tree
Hide file tree
Showing 7 changed files with 323 additions and 221 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

from gui.UtilsWidgets.CustomQGroupBox.QCollapsibleWidget import QCollapsibleWidget
from utils.software_config import SoftwareConfigResources
from utils.data_structures.UserPreferencesStructure import UserPreferencesStructure
from gui.UtilsWidgets.CustomQDialog.SavePatientChangesDialog import SavePatientChangesDialog


Expand Down Expand Up @@ -35,6 +36,7 @@ def __set_interface(self):
self.__set_resectability_part()
self.__set_cortical_structures_part()
self.__set_subcortical_structures_part()
self.__set_braingrid_structures_part()
self.layout.addStretch(1)

def __set_volumes_part(self):
Expand Down Expand Up @@ -179,6 +181,16 @@ def __set_subcortical_structures_part(self):
self.subcorticalstructures_collapsiblegroupbox.content_layout.setSpacing(0)
self.layout.addWidget(self.subcorticalstructures_collapsiblegroupbox)

def __set_braingrid_structures_part(self):
self.braingridstructures_collapsiblegroupbox = QCollapsibleWidget("BrainGrid structures")
self.braingridstructures_collapsiblegroupbox.set_icon_filenames(expand_fn=os.path.join(os.path.dirname(os.path.realpath(__file__)),
'../../Images/collapsed_icon.png'),
collapse_fn=os.path.join(os.path.dirname(os.path.realpath(__file__)),
'../../Images/uncollapsed_icon.png'))
self.braingridstructures_collapsiblegroupbox.content_layout.setContentsMargins(20, 0, 20, 0)
self.braingridstructures_collapsiblegroupbox.content_layout.setSpacing(0)
self.layout.addWidget(self.braingridstructures_collapsiblegroupbox)

def __set_layout_dimensions(self):
self.original_space_volume_header_label.setFixedHeight(20)
self.original_space_volume_label.setFixedHeight(20)
Expand Down Expand Up @@ -232,13 +244,19 @@ def __set_layout_dimensions(self):
self.subcorticalstructures_collapsiblegroupbox.header.title_label.setFixedHeight(35)
self.subcorticalstructures_collapsiblegroupbox.header.background_label.setFixedHeight(40)

self.braingridstructures_collapsiblegroupbox.header.setFixedHeight(40)
self.braingridstructures_collapsiblegroupbox.header.set_icon_size(QSize(35, 35))
self.braingridstructures_collapsiblegroupbox.header.title_label.setFixedHeight(35)
self.braingridstructures_collapsiblegroupbox.header.background_label.setFixedHeight(40)

def __set_connections(self):
self.volumes_collapsiblegroupbox.toggled.connect(self.on_size_request)
self.laterality_collapsiblegroupbox.toggled.connect(self.on_size_request)
self.resectability_collapsiblegroupbox.toggled.connect(self.on_size_request)
self.multifocality_collapsiblegroupbox.toggled.connect(self.on_size_request)
self.corticalstructures_collapsiblegroupbox.toggled.connect(self.on_size_request)
self.subcorticalstructures_collapsiblegroupbox.toggled.connect(self.on_size_request)
self.braingridstructures_collapsiblegroupbox.toggled.connect(self.on_size_request)

def set_stylesheets(self, selected: bool) -> None:
software_ss = SoftwareConfigResources.getInstance().stylesheet_components
Expand Down Expand Up @@ -539,6 +557,33 @@ def set_stylesheets(self, selected: bool) -> None:
}""")
self.subcorticalstructures_collapsiblegroupbox.content_widget.setStyleSheet("QWidget{background-color:rgb(254,254,254);}")

###################################### BRAINGRID STRUCTURES GROUPBOX #########################################
self.braingridstructures_collapsiblegroupbox.header.background_label.setStyleSheet("""
QLabel{
background-color:rgb(248, 248, 248);
border-width: 1px;
border-style: solid;
border-color: black rgb(248, 248, 248) black rgb(248, 248, 248);
border-radius: 2px;
}""")
self.braingridstructures_collapsiblegroupbox.header.title_label.setStyleSheet("""
QLabel{
background-color:rgb(248, 248, 248);
color: """ + font_color + """;
text-align:left;
font:bold;
font-size:14px;
padding-left:20px;
padding-right:20px;
border: none;
}""")
self.braingridstructures_collapsiblegroupbox.header.icon_label.setStyleSheet("""
QLabel{
border: none;
padding-left:20px;
}""")
self.braingridstructures_collapsiblegroupbox.content_widget.setStyleSheet("QWidget{background-color:rgb(254,254,254);}")

def adjustSize(self):
pass

Expand Down Expand Up @@ -746,6 +791,90 @@ def populate_from_report(self) -> None:
self.subcorticalstructures_collapsiblegroupbox.content_layout.addLayout(lay)
self.subcorticalstructures_collapsiblegroupbox.adjustSize()

# BrainGrid structures
self.braingridstructures_collapsiblegroupbox.clear_content_layout()
if UserPreferencesStructure.getInstance().compute_braingrid_structures:
lay = QHBoxLayout()
label_header = QLabel("Infiltration count:")
label_header.setStyleSheet("""
QLabel{
font-size:13px;
color: rgba(67, 88, 90, 1);
border-style: none;
}""")
label = QLabel("{}".format(str(report_json['Main']['Total']['BrainGrid']["Infiltration count"])))
label_header.setFixedHeight(20)
label_header.setFixedWidth(190)
label.setFixedHeight(20)
label.setFixedWidth(80)
label.setAlignment(Qt.AlignRight)
label.setStyleSheet("""
QLabel{
color: rgba(67, 88, 90, 1);
text-align:right;
font:semibold;
font-size:13px;
}""")
lay.addWidget(label_header)
lay.addWidget(label)
lay.addStretch(1)
self.braingridstructures_collapsiblegroupbox.content_layout.addLayout(lay)
for atlas in UserPreferencesStructure.getInstance().braingrid_structures_list: # report_json['Main']['Total']['BrainGrid']
sorted_overlaps = dict(sorted(report_json['Main']['Total']['BrainGrid'][atlas].items(), key=lambda item: item[1], reverse=True))
label = QLabel("{} atlas".format(atlas))
label.setFixedHeight(20)
label.setStyleSheet("""
QLabel{
color: """ + software_ss["Color7"] + """;
text-align:left;
font:bold;
font-size:14px;
}""")
line_label = QLabel()
line_label.setFixedHeight(3)
line_label.setStyleSheet("QLabel{background-color: rgb(214, 214, 214);}")
if list(report_json['Main']['Total']['BrainGrid'].keys()).index(atlas) != 0:
upper_line_label = QLabel()
upper_line_label.setFixedHeight(3)
upper_line_label.setStyleSheet("QLabel{background-color: rgb(214, 214, 214);}")
self.braingridstructures_collapsiblegroupbox.content_layout.addWidget(upper_line_label)
self.braingridstructures_collapsiblegroupbox.content_layout.addWidget(label)
self.braingridstructures_collapsiblegroupbox.content_layout.addWidget(line_label)
for struct, val in sorted_overlaps.items():
if val >= 1.0:
lay = QHBoxLayout()
struct_display_name = struct.replace('_', ' ').replace('-', ' ')
label_header = QLineEdit("{} ".format(struct_display_name))
label_header.setReadOnly(True)
label_header.setCursorPosition(0)
label_header.home(True)
label_header.setStyleSheet("""
QLineEdit{
font-size:13px;
color: rgba(67, 88, 90, 1);
border-style: none;
}""")
label = QLabel("{:.2f} %".format(val))
label_header.setFixedHeight(20)
label_header.setFixedWidth(190)
label.setFixedHeight(20)
label.setFixedWidth(80)
label.setAlignment(Qt.AlignRight)
label.setStyleSheet("""
QLabel{
color: rgba(67, 88, 90, 1);
text-align:right;
font:semibold;
font-size:13px;
}""")
lay.addWidget(label_header)
# lay.addStretch(1)
lay.addWidget(label)
lay.addStretch(1)
self.braingridstructures_collapsiblegroupbox.content_layout.addLayout(lay)

self.braingridstructures_collapsiblegroupbox.adjustSize()

self.adjustSize()

def on_size_request(self):
Expand Down
72 changes: 72 additions & 0 deletions gui/UtilsWidgets/CustomQDialog/SoftwareSettingsDialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -321,10 +321,44 @@ def __set_processing_reporting_options_interface(self):
self.processing_options_subcorticalstructures_selection_layout.addWidget(self.subcorticalstructures_bcb_checkbox)
self.processing_options_subcorticalstructures_selection_layout.addWidget(self.subcorticalstructures_bcb_label)
self.processing_options_subcorticalstructures_selection_layout.addStretch(1)
self.subcorticalstructures_braingrid_label = QLabel("BrainGrid")
self.subcorticalstructures_braingrid_label.setToolTip("From the BrainGrid research, a total of 20 unique structures with left and right disambiguation.")
self.subcorticalstructures_braingrid_checkbox = QCheckBox()
self.subcorticalstructures_braingrid_checkbox.setChecked("BrainGrid" in UserPreferencesStructure.getInstance().subcortical_structures_list if UserPreferencesStructure.getInstance().subcortical_structures_list != None else False)
self.subcorticalstructures_braingrid_checkbox.setEnabled(UserPreferencesStructure.getInstance().compute_subcortical_structures)
self.processing_options_subcorticalstructures_selection_layout.addWidget(self.subcorticalstructures_braingrid_checkbox)
self.processing_options_subcorticalstructures_selection_layout.addWidget(self.subcorticalstructures_braingrid_label)
self.processing_options_subcorticalstructures_selection_layout.addStretch(1)
self.processing_reporting_subcortical_groupboxlayout.addLayout(self.processing_options_subcorticalstructures_selection_layout)
self.processing_reporting_subcortical_groupbox.setLayout(self.processing_reporting_subcortical_groupboxlayout)
self.processing_reporting_options_base_layout.addWidget(self.processing_reporting_subcortical_groupbox)

self.processing_reporting_braingrid_groupbox = QGroupBox()
self.processing_reporting_braingrid_groupbox.setTitle("BrainGrid structures")
self.processing_reporting_braingrid_groupboxlayout = QVBoxLayout()

self.processing_options_compute_braingridstructures_layout = QHBoxLayout()
self.processing_options_compute_braingridstructures_label = QLabel("Report BrainGrid structures")
self.processing_options_compute_braingridstructures_label.setToolTip("Tick the box in order to include BrainGrid structures related features in the standardized report.\n")
self.processing_options_compute_braingridstructures_checkbox = QCheckBox()
self.processing_options_compute_braingridstructures_checkbox.setChecked(UserPreferencesStructure.getInstance().compute_braingrid_structures)
self.processing_options_compute_braingridstructures_layout.addWidget(self.processing_options_compute_braingridstructures_checkbox)
self.processing_options_compute_braingridstructures_layout.addWidget(self.processing_options_compute_braingridstructures_label)
self.processing_options_compute_braingridstructures_layout.addStretch(1)
self.processing_reporting_braingrid_groupboxlayout.addLayout(self.processing_options_compute_braingridstructures_layout)
self.processing_options_braingridstructures_selection_layout = QHBoxLayout()
self.braingridstructures_voxels_label = QLabel("Voxels")
self.braingridstructures_voxels_label.setToolTip("From the BrainGrid research, super-voxels brain parcellation.")
self.braingridstructures_voxels_checkbox = QCheckBox()
self.braingridstructures_voxels_checkbox.setChecked("Voxels" in UserPreferencesStructure.getInstance().braingrid_structures_list if UserPreferencesStructure.getInstance().braingrid_structures_list != None else False)
self.braingridstructures_voxels_checkbox.setEnabled(UserPreferencesStructure.getInstance().compute_braingrid_structures)
self.processing_options_braingridstructures_selection_layout.addWidget(self.braingridstructures_voxels_checkbox)
self.processing_options_braingridstructures_selection_layout.addWidget(self.braingridstructures_voxels_label)
self.processing_options_braingridstructures_selection_layout.addStretch(1)
self.processing_reporting_braingrid_groupboxlayout.addLayout(self.processing_options_braingridstructures_selection_layout)
self.processing_reporting_braingrid_groupbox.setLayout(self.processing_reporting_braingrid_groupboxlayout)
self.processing_reporting_options_base_layout.addWidget(self.processing_reporting_braingrid_groupbox)

self.processing_reporting_options_base_layout.addStretch(1)
self.processing_reporting_options_widget.setLayout(self.processing_reporting_options_base_layout)
self.options_stackedwidget.addWidget(self.processing_reporting_options_widget)
Expand Down Expand Up @@ -402,6 +436,9 @@ def __set_connections(self):
self.corticalstructures_harvardoxford_checkbox.stateChanged.connect(self.__on_corticalstructure_harvardoxford_status_changed)
self.processing_options_compute_subcorticalstructures_checkbox.stateChanged.connect(self.__on_compute_subcorticalstructures_status_changed)
self.subcorticalstructures_bcb_checkbox.stateChanged.connect(self.__on_subcorticalstructure_bcb_status_changed)
self.subcorticalstructures_braingrid_checkbox.stateChanged.connect(self.__on_subcorticalstructure_braingrid_status_changed)
self.processing_options_compute_braingridstructures_checkbox.stateChanged.connect(self.__on_compute_braingridstructures_status_changed)
self.braingridstructures_voxels_checkbox.stateChanged.connect(self.__on_braingridstructure_voxels_status_changed)
self.dark_mode_checkbox.stateChanged.connect(self.__on_dark_mode_status_changed)
self.exit_accept_pushbutton.clicked.connect(self.__on_exit_accept_clicked)
self.exit_cancel_pushbutton.clicked.connect(self.__on_exit_cancel_clicked)
Expand Down Expand Up @@ -750,9 +787,13 @@ def __on_compute_subcorticalstructures_status_changed(self, state):
if state:
self.subcorticalstructures_bcb_checkbox.setEnabled(True)
self.subcorticalstructures_bcb_label.setEnabled(True)
self.subcorticalstructures_braingrid_checkbox.setEnabled(True)
self.subcorticalstructures_braingrid_label.setEnabled(True)
else:
self.subcorticalstructures_bcb_checkbox.setEnabled(False)
self.subcorticalstructures_bcb_label.setEnabled(False)
self.subcorticalstructures_braingrid_checkbox.setEnabled(False)
self.subcorticalstructures_braingrid_label.setEnabled(False)

def __on_subcorticalstructure_bcb_status_changed(self, state):
structs = UserPreferencesStructure.getInstance().subcortical_structures_list
Expand All @@ -765,6 +806,37 @@ def __on_subcorticalstructure_bcb_status_changed(self, state):
structs.remove("BCB")
UserPreferencesStructure.getInstance().subcortical_structures_list = structs

def __on_subcorticalstructure_braingrid_status_changed(self, state):
structs = UserPreferencesStructure.getInstance().subcortical_structures_list
if state:
if structs is None:
structs = ["BrainGrid"]
else:
structs.append("BrainGrid")
else:
structs.remove("BrainGrid")
UserPreferencesStructure.getInstance().subcortical_structures_list = structs

def __on_compute_braingridstructures_status_changed(self, state):
UserPreferencesStructure.getInstance().compute_braingrid_structures = self.processing_options_compute_braingridstructures_checkbox.isChecked()
if state:
self.braingridstructures_voxels_checkbox.setEnabled(True)
self.braingridstructures_voxels_label.setEnabled(True)
else:
self.braingridstructures_voxels_checkbox.setEnabled(False)
self.braingridstructures_voxels_label.setEnabled(False)

def __on_braingridstructure_voxels_status_changed(self, state):
structs = UserPreferencesStructure.getInstance().braingrid_structures_list
if state:
if structs is None:
structs = ["Voxels"]
else:
structs.append("Voxels")
else:
structs.remove("Voxels")
UserPreferencesStructure.getInstance().braingrid_structures_list = structs

def __on_dark_mode_status_changed(self, state):
# @TODO. Would have to bounce back to the QApplication class, to trigger a global setStyleSheet on-the-fly?
SoftwareConfigResources.getInstance().set_dark_mode_state(state)
Expand Down
2 changes: 2 additions & 0 deletions utils/backend_logic.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ def run_pipeline(task: str, model_name: str, patient_parameters: PatientParamete
rads_config.set('Neuro', 'cortical_features', ",".join(UserPreferencesStructure.getInstance().cortical_structures_list))
if UserPreferencesStructure.getInstance().compute_subcortical_structures:
rads_config.set('Neuro', 'subcortical_features', ",".join(UserPreferencesStructure.getInstance().subcortical_structures_list))
if UserPreferencesStructure.getInstance().compute_braingrid_structures:
rads_config.set('Neuro', 'braingrid_features', ",".join(UserPreferencesStructure.getInstance().braingrid_structures_list))
rads_config_filename = os.path.join(patient_parameters.output_folder, 'rads_config.ini')
with open(rads_config_filename, 'w') as outfile:
rads_config.write(outfile)
Expand Down
6 changes: 5 additions & 1 deletion utils/data_structures/AtlasStructure.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,11 @@ def __init_from_scratch(self):
elif "Harvard" in self._unique_id:
self._display_name = "Harvard-Oxford"
elif "BCB" in self._unique_id:
self._display_name = "BCB group"
self._display_name = "BCB WM"
elif "Voxels" in self._unique_id:
self._display_name = "BrainGrid Voxels"
elif "BrainGrid" in self._unique_id:
self._display_name = "BrainGrid WM"
elif "MNI" in self._unique_id:
self._display_name = "MNI group"

Expand Down
Loading

0 comments on commit de39253

Please sign in to comment.