|
1 | 1 | # Standard library imports |
2 | 2 | from enum import Enum |
3 | 3 | from pathlib import Path |
| 4 | +import types |
4 | 5 | from typing import ( |
5 | 6 | List, |
6 | 7 | Optional, |
@@ -257,8 +258,8 @@ def setup(self) -> None: |
257 | 258 | self.abstract_apodization_method_definition_widget = OpenLIFUAbstractApodizationMethodDefinitionFormWidget() |
258 | 259 | replace_widget(self.ui.abstractApodizationMethodDefinitionWidgetPlaceholder, self.abstract_apodization_method_definition_widget, self.ui) |
259 | 260 |
|
260 | | - self.segmentation_method_definition_widget = OpenLIFUAbstractDataclassDefinitionFormWidget(cls=openlifu_lz().seg.SegmentationMethod, parent=self.ui.segmentationMethodDefinitionWidgetPlaceholder.parentWidget(), collapsible_title="Segmentation Method") |
261 | | - replace_widget(self.ui.segmentationMethodDefinitionWidgetPlaceholder, self.segmentation_method_definition_widget, self.ui) |
| 261 | + self.abstract_segmentation_method_definition_widget = OpenLIFUAbstractSegmentationMethodDefinitionFormWidget() |
| 262 | + replace_widget(self.ui.abstractSegmentationMethodDefinitionWidgetPlaceholder, self.abstract_segmentation_method_definition_widget, self.ui) |
262 | 263 |
|
263 | 264 | self.parameter_constraints_widget = OpenLIFUParameterConstraintsWidget() |
264 | 265 | replace_widget(self.ui.parameterConstraintsWidgetPlaceholder, self.parameter_constraints_widget, self.ui) |
@@ -301,7 +302,7 @@ def setup(self) -> None: |
301 | 302 | self.sim_setup_definition_widget.add_value_changed_signals(trigger_unsaved_changes) |
302 | 303 | self.abstract_delay_method_definition_widget.add_value_changed_signals(trigger_unsaved_changes) |
303 | 304 | self.abstract_apodization_method_definition_widget.add_value_changed_signals(trigger_unsaved_changes) |
304 | | - self.segmentation_method_definition_widget.add_value_changed_signals(trigger_unsaved_changes) |
| 305 | + self.abstract_segmentation_method_definition_widget.add_value_changed_signals(trigger_unsaved_changes) |
305 | 306 | self.parameter_constraints_widget.table.itemChanged.connect(lambda *_: trigger_unsaved_changes()) |
306 | 307 | self.target_constraints_widget.table.itemChanged.connect(lambda *_: trigger_unsaved_changes()) |
307 | 308 | self.solution_analysis_options_definition_widget.add_value_changed_signals(trigger_unsaved_changes) |
@@ -655,7 +656,7 @@ def updateProtocolDisplayFromProtocol(self, protocol: "openlifu.plan.Protocol"): |
655 | 656 | self.sim_setup_definition_widget.update_form_from_class(protocol.sim_setup) |
656 | 657 | self.abstract_delay_method_definition_widget.update_form_from_class(protocol.delay_method) |
657 | 658 | self.abstract_apodization_method_definition_widget.update_form_from_class(protocol.apod_method) |
658 | | - self.segmentation_method_definition_widget.update_form_from_class(protocol.seg_method) |
| 659 | + self.abstract_segmentation_method_definition_widget.update_form_from_class(protocol.seg_method) |
659 | 660 | self.parameter_constraints_widget.from_dict(protocol.param_constraints) |
660 | 661 | self.target_constraints_widget.from_list(protocol.target_constraints) |
661 | 662 | self.solution_analysis_options_definition_widget.update_form_from_class(protocol.analysis_options) |
@@ -694,7 +695,7 @@ def getProtocolFromGUI(self) -> "openlifu.plan.Protocol": |
694 | 695 | sim_setup = self.sim_setup_definition_widget.get_form_as_class() |
695 | 696 | delay_method = self.abstract_delay_method_definition_widget.get_form_as_class() |
696 | 697 | apodization_method = self.abstract_apodization_method_definition_widget.get_form_as_class() |
697 | | - segmentation_method = self.segmentation_method_definition_widget.get_form_as_class() |
| 698 | + segmentation_method = self.abstract_segmentation_method_definition_widget.get_form_as_class() |
698 | 699 | parameter_constraints = self.parameter_constraints_widget.to_dict() |
699 | 700 | target_constraints = self.target_constraints_widget.to_list() |
700 | 701 | solution_analysis_options = self.solution_analysis_options_definition_widget.get_form_as_class() |
@@ -737,7 +738,7 @@ def setProtocolEditorEnabled(self, enabled: bool) -> None: |
737 | 738 | self.sim_setup_definition_widget.setEnabled(enabled) |
738 | 739 | self.abstract_delay_method_definition_widget.setEnabled(enabled) |
739 | 740 | self.abstract_apodization_method_definition_widget.setEnabled(enabled) |
740 | | - self.segmentation_method_definition_widget.setEnabled(enabled) |
| 741 | + self.abstract_segmentation_method_definition_widget.setEnabled(enabled) |
741 | 742 | self.parameter_constraints_widget.setEnabled(enabled) |
742 | 743 | self.target_constraints_widget.setEnabled(enabled) |
743 | 744 | self.solution_analysis_options_definition_widget.setEnabled(enabled) |
@@ -926,7 +927,7 @@ def get_default_apodization_method(cls): |
926 | 927 |
|
927 | 928 | @classmethod |
928 | 929 | def get_default_segmentation_method(cls): |
929 | | - return openlifu_lz().seg.seg_methods.Water() |
| 930 | + return openlifu_lz().seg.seg_methods.UniformWater() |
930 | 931 |
|
931 | 932 | @classmethod |
932 | 933 | def get_default_parameter_constraints(cls): |
@@ -1061,6 +1062,81 @@ def __init__(self): |
1061 | 1062 | max_angle_spinbox = maxangle_definition_form_widget._field_widgets['max_angle'] |
1062 | 1063 | maxangle_definition_form_widget.modify_widget_spinbox(max_angle_spinbox, default_value=30, min_value=0, max_value=90) |
1063 | 1064 |
|
| 1065 | +def _get_form_as_segmentation_method(self): |
| 1066 | + """ |
| 1067 | + Custom replacement for get_form_as_class, used to override |
| 1068 | + widgets inside the segmentation method form. |
| 1069 | + """ |
| 1070 | + d = self.get_form_as_dict() |
| 1071 | + |
| 1072 | + # Remove ref_material if class is UniformWater or UniformTissue |
| 1073 | + if self._cls.__name__ in ["UniformWater", "UniformTissue"]: |
| 1074 | + d.pop("ref_material") |
| 1075 | + |
| 1076 | + return self._cls(**d) |
| 1077 | + |
| 1078 | +class OpenLIFUAbstractSegmentationMethodDefinitionFormWidget(OpenLIFUAbstractMultipleABCDefinitionFormWidget): |
| 1079 | + |
| 1080 | + |
| 1081 | + def __init__(self): |
| 1082 | + """ |
| 1083 | + Overwrite of __init__ that mimics most of super()'s behavior, except |
| 1084 | + accounts for the unique inheritance structure of SegmentationMethod. |
| 1085 | + """ |
| 1086 | + # ---- Begin constructor overwrite ---- |
| 1087 | + |
| 1088 | + cls_list = [openlifu_lz().seg.seg_methods.UniformSegmentation, openlifu_lz().seg.seg_methods.UniformTissue, openlifu_lz().seg.seg_methods.UniformWater] |
| 1089 | + is_collapsible = False |
| 1090 | + parent: Optional[qt.QWidget] = None |
| 1091 | + collapsible_title = "Segmentation Method" |
| 1092 | + custom_abc_title = "Segmentation Method" |
| 1093 | + |
| 1094 | + self.cls_list = cls_list |
| 1095 | + self.base_class_name = cls_list[0].__bases__[0].__name__ |
| 1096 | + self.custom_abc_title = self.base_class_name if custom_abc_title is None else custom_abc_title |
| 1097 | + |
| 1098 | + qt.QWidget.__init__(self, parent) |
| 1099 | + |
| 1100 | + top_level_layout = qt.QFormLayout(self) |
| 1101 | + |
| 1102 | + self.selector = qt.QComboBox() |
| 1103 | + self.forms = qt.QStackedWidget() |
| 1104 | + |
| 1105 | + for cls in cls_list: |
| 1106 | + self.selector.addItem(cls.__name__) |
| 1107 | + widget = OpenLIFUAbstractDataclassDefinitionFormWidget(cls, parent, is_collapsible, collapsible_title) |
| 1108 | + # Override get_form_as_class |
| 1109 | + widget.get_form_as_class = types.MethodType(_get_form_as_segmentation_method, widget) |
| 1110 | + self.forms.addWidget(widget) |
| 1111 | + |
| 1112 | + top_level_layout.addRow(qt.QLabel(f"{self.custom_abc_title} type"), self.selector) |
| 1113 | + top_level_layout.addRow(qt.QLabel(f"{self.custom_abc_title} options"), self.forms) |
| 1114 | + |
| 1115 | + # Connect combo box to setting the widget. Assumes indices match |
| 1116 | + self.selector.currentIndexChanged.connect(self._on_index_changed) |
| 1117 | + |
| 1118 | + # ---- Configure selector behavior ---- |
| 1119 | + |
| 1120 | + # Select UniformWater as the default |
| 1121 | + self.forms.setCurrentIndex(2) |
| 1122 | + |
| 1123 | + # ---- Configure UniformTissue editor ---- |
| 1124 | + |
| 1125 | + uniformtissue_definition_form_widget = self.forms.widget(1) |
| 1126 | + |
| 1127 | + # Disable editing the reference material |
| 1128 | + ref_material_line_edit = uniformtissue_definition_form_widget._field_widgets['ref_material'] |
| 1129 | + ref_material_line_edit.setEnabled(False) |
| 1130 | + |
| 1131 | + # ---- Configure UniformWater editor ---- |
| 1132 | + |
| 1133 | + uniformwater_definition_form_widget = self.forms.widget(2) |
| 1134 | + |
| 1135 | + # Disable editing the reference material |
| 1136 | + ref_material_line_edit = uniformwater_definition_form_widget._field_widgets['ref_material'] |
| 1137 | + ref_material_line_edit.setEnabled(False) |
| 1138 | + |
| 1139 | + |
1064 | 1140 | class OpenLIFUParameterConstraintsWidget(DictTableWidget): |
1065 | 1141 |
|
1066 | 1142 | class CreateParameterParameterConstraintDialog(qt.QDialog): |
|
0 commit comments