AMS-BP 0.3.1__py3-none-any.whl → 0.4.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- AMS_BP/__init__.py +1 -1
- AMS_BP/configio/configmodels.py +26 -12
- AMS_BP/configio/convertconfig.py +508 -632
- AMS_BP/gui/README.md +77 -0
- AMS_BP/gui/__init__.py +0 -0
- AMS_BP/gui/assets/__init__.py +0 -0
- AMS_BP/gui/assets/drawing.svg +107 -0
- AMS_BP/gui/configuration_window.py +333 -0
- AMS_BP/gui/help_docs/__init__.py +0 -0
- AMS_BP/gui/help_docs/cell_help.md +45 -0
- AMS_BP/gui/help_docs/channels_help.md +78 -0
- AMS_BP/gui/help_docs/condensate_help.md +59 -0
- AMS_BP/gui/help_docs/detector_help.md +57 -0
- AMS_BP/gui/help_docs/experiment_help.md +92 -0
- AMS_BP/gui/help_docs/fluorophore_help.md +128 -0
- AMS_BP/gui/help_docs/general_help.md +43 -0
- AMS_BP/gui/help_docs/global_help.md +47 -0
- AMS_BP/gui/help_docs/laser_help.md +76 -0
- AMS_BP/gui/help_docs/molecule_help.md +78 -0
- AMS_BP/gui/help_docs/output_help.md +5 -0
- AMS_BP/gui/help_docs/psf_help.md +51 -0
- AMS_BP/gui/help_window.py +26 -0
- AMS_BP/gui/logging_window.py +93 -0
- AMS_BP/gui/main.py +255 -0
- AMS_BP/gui/sim_worker.py +58 -0
- AMS_BP/gui/template_window_selection.py +100 -0
- AMS_BP/gui/widgets/__init__.py +0 -0
- AMS_BP/gui/widgets/camera_config_widget.py +213 -0
- AMS_BP/gui/widgets/cell_config_widget.py +225 -0
- AMS_BP/gui/widgets/channel_config_widget.py +307 -0
- AMS_BP/gui/widgets/condensate_config_widget.py +341 -0
- AMS_BP/gui/widgets/experiment_config_widget.py +259 -0
- AMS_BP/gui/widgets/flurophore_config_widget.py +513 -0
- AMS_BP/gui/widgets/general_config_widget.py +47 -0
- AMS_BP/gui/widgets/global_config_widget.py +142 -0
- AMS_BP/gui/widgets/laser_config_widget.py +255 -0
- AMS_BP/gui/widgets/molecule_config_widget.py +714 -0
- AMS_BP/gui/widgets/output_config_widget.py +61 -0
- AMS_BP/gui/widgets/psf_config_widget.py +128 -0
- AMS_BP/gui/widgets/utility_widgets/__init__.py +0 -0
- AMS_BP/gui/widgets/utility_widgets/scinotation_widget.py +21 -0
- AMS_BP/gui/widgets/utility_widgets/spectrum_widget.py +115 -0
- AMS_BP/logging/__init__.py +0 -0
- AMS_BP/logging/logutil.py +83 -0
- AMS_BP/logging/setup_run_directory.py +35 -0
- AMS_BP/{run_cell_simulation.py → main_cli.py} +27 -72
- AMS_BP/optics/filters/filters.py +2 -0
- AMS_BP/resources/template_configs/metadata_configs.json +20 -0
- AMS_BP/resources/template_configs/sim_config.toml +408 -0
- AMS_BP/resources/template_configs/twocolor_widefield_timeseries_live.toml +399 -0
- AMS_BP/resources/template_configs/twocolor_widefield_zstack_fixed.toml +406 -0
- AMS_BP/resources/template_configs/twocolor_widefield_zstack_live.toml +408 -0
- AMS_BP/run_sim_util.py +76 -0
- {ams_bp-0.3.1.dist-info → ams_bp-0.4.0.dist-info}/METADATA +46 -27
- ams_bp-0.4.0.dist-info/RECORD +103 -0
- ams_bp-0.4.0.dist-info/entry_points.txt +2 -0
- ams_bp-0.3.1.dist-info/RECORD +0 -55
- ams_bp-0.3.1.dist-info/entry_points.txt +0 -2
- {ams_bp-0.3.1.dist-info → ams_bp-0.4.0.dist-info}/WHEEL +0 -0
- {ams_bp-0.3.1.dist-info → ams_bp-0.4.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,213 @@
|
|
1
|
+
from pathlib import Path
|
2
|
+
|
3
|
+
from pydantic import ValidationError
|
4
|
+
from PyQt6.QtWidgets import (
|
5
|
+
QComboBox,
|
6
|
+
QDoubleSpinBox,
|
7
|
+
QFormLayout,
|
8
|
+
QHBoxLayout,
|
9
|
+
QMessageBox,
|
10
|
+
QPushButton,
|
11
|
+
QSpinBox,
|
12
|
+
QVBoxLayout,
|
13
|
+
QWidget,
|
14
|
+
)
|
15
|
+
|
16
|
+
from .utility_widgets.spectrum_widget import SpectrumEditorDialog
|
17
|
+
|
18
|
+
|
19
|
+
class CameraConfigWidget(QWidget):
|
20
|
+
def __init__(self):
|
21
|
+
super().__init__()
|
22
|
+
layout = QVBoxLayout()
|
23
|
+
form = QFormLayout()
|
24
|
+
|
25
|
+
self.validate_button = QPushButton("Validate")
|
26
|
+
self.validate_button.clicked.connect(self.validate)
|
27
|
+
layout.addWidget(self.validate_button)
|
28
|
+
|
29
|
+
# Camera type (Only "CMOS" is available)
|
30
|
+
self.camera_type = QComboBox()
|
31
|
+
self.camera_type.addItems(["CMOS"])
|
32
|
+
form.addRow("Camera Type:", self.camera_type)
|
33
|
+
|
34
|
+
# Pixel count (width and height)
|
35
|
+
self.pixel_width = QSpinBox()
|
36
|
+
self.pixel_width.setRange(1, 10000)
|
37
|
+
self.pixel_height = QSpinBox()
|
38
|
+
self.pixel_height.setRange(1, 10000)
|
39
|
+
form.addRow(
|
40
|
+
"Pixel Count (Width x Height):",
|
41
|
+
self._hbox([self.pixel_width, self.pixel_height]),
|
42
|
+
)
|
43
|
+
|
44
|
+
# Pixel detector size
|
45
|
+
self.pixel_detector_size = QDoubleSpinBox()
|
46
|
+
self.pixel_detector_size.setRange(0, 100)
|
47
|
+
form.addRow("Pixel Detector Size (µm):", self.pixel_detector_size)
|
48
|
+
|
49
|
+
# Magnification
|
50
|
+
self.magnification = QSpinBox()
|
51
|
+
self.magnification.setRange(1, 100)
|
52
|
+
form.addRow("Magnification:", self.magnification)
|
53
|
+
|
54
|
+
# Dark current
|
55
|
+
self.dark_current = QDoubleSpinBox()
|
56
|
+
self.dark_current.setRange(0, 1000)
|
57
|
+
form.addRow("Dark Current (electrons/pixel/sec):", self.dark_current)
|
58
|
+
|
59
|
+
# Readout noise
|
60
|
+
self.readout_noise = QDoubleSpinBox()
|
61
|
+
self.readout_noise.setRange(0, 1000)
|
62
|
+
form.addRow("Readout Noise (electrons RMS):", self.readout_noise)
|
63
|
+
|
64
|
+
# Bit depth
|
65
|
+
self.bit_depth = QSpinBox()
|
66
|
+
self.bit_depth.setRange(8, 16)
|
67
|
+
form.addRow("Bit Depth:", self.bit_depth)
|
68
|
+
|
69
|
+
# Sensitivity
|
70
|
+
self.sensitivity = QDoubleSpinBox()
|
71
|
+
self.sensitivity.setRange(0, 100)
|
72
|
+
form.addRow("Sensitivity (electrons/ADU):", self.sensitivity)
|
73
|
+
|
74
|
+
# Base ADU
|
75
|
+
self.base_adu = QSpinBox()
|
76
|
+
self.base_adu.setRange(0, 65535)
|
77
|
+
form.addRow("Base ADU:", self.base_adu)
|
78
|
+
|
79
|
+
# Binning size
|
80
|
+
self.binning_size = QSpinBox()
|
81
|
+
self.binning_size.setRange(1, 10)
|
82
|
+
form.addRow("Binning Size:", self.binning_size)
|
83
|
+
|
84
|
+
# Quantum efficiency
|
85
|
+
self.quantum_efficiency_button = QPushButton("Edit Quantum Efficiency")
|
86
|
+
self.quantum_efficiency_button.clicked.connect(self.edit_quantum_efficiency)
|
87
|
+
form.addRow("Quantum Efficiency:", self.quantum_efficiency_button)
|
88
|
+
|
89
|
+
layout.addLayout(form)
|
90
|
+
self.setLayout(layout)
|
91
|
+
|
92
|
+
def _hbox(self, widgets):
|
93
|
+
box = QHBoxLayout()
|
94
|
+
for w in widgets:
|
95
|
+
box.addWidget(w)
|
96
|
+
container = QWidget()
|
97
|
+
container.setLayout(box)
|
98
|
+
return container
|
99
|
+
|
100
|
+
def edit_quantum_efficiency(self):
|
101
|
+
# Open the SpectrumEditorDialog for editing quantum efficiency
|
102
|
+
dialog = SpectrumEditorDialog(
|
103
|
+
parent=self,
|
104
|
+
wavelengths=[], # Pass an empty list or preloaded wavelengths
|
105
|
+
intensities=[], # Pass an empty list or preloaded intensities
|
106
|
+
intensity_name="QE",
|
107
|
+
)
|
108
|
+
|
109
|
+
if dialog.exec():
|
110
|
+
# Handle the updated quantum efficiency data (wavelengths, intensities)
|
111
|
+
self.quantum_efficiency_data = {
|
112
|
+
"wavelengths": dialog.wavelengths,
|
113
|
+
"quantum_efficiency": dialog.intensities,
|
114
|
+
}
|
115
|
+
# You can now use this data wherever needed, e.g., saving or validation
|
116
|
+
|
117
|
+
def validate(self) -> bool:
|
118
|
+
from ...configio.convertconfig import create_quantum_efficiency_from_config
|
119
|
+
from ...optics.camera.detectors import (
|
120
|
+
CMOSDetector,
|
121
|
+
)
|
122
|
+
|
123
|
+
try:
|
124
|
+
data = self.get_data()
|
125
|
+
|
126
|
+
# Convert QE before passing
|
127
|
+
qe = create_quantum_efficiency_from_config(data["quantum_efficiency"])
|
128
|
+
|
129
|
+
# Prepare CMOS-specific parameters only (drop "type" and "quantum_efficiency")
|
130
|
+
camera_data = {
|
131
|
+
k: v for k, v in data.items() if k not in {"type", "quantum_efficiency"}
|
132
|
+
}
|
133
|
+
camera_data["pixel_size"] = (
|
134
|
+
camera_data["pixel_detector_size"] / camera_data["magnification"]
|
135
|
+
)
|
136
|
+
|
137
|
+
# Attempt to construct the detector
|
138
|
+
detector = CMOSDetector(**camera_data)
|
139
|
+
|
140
|
+
# If no exception, validation is successful
|
141
|
+
QMessageBox.information(
|
142
|
+
self, "Validation Successful", "Camera parameters are valid."
|
143
|
+
)
|
144
|
+
return True
|
145
|
+
|
146
|
+
except ValidationError as e:
|
147
|
+
QMessageBox.critical(self, "Validation Error", str(e))
|
148
|
+
return False
|
149
|
+
except Exception as e:
|
150
|
+
QMessageBox.critical(self, "Validation Error", str(e))
|
151
|
+
return False
|
152
|
+
|
153
|
+
def get_data(self):
|
154
|
+
camera_data = {
|
155
|
+
"type": self.camera_type.currentText(),
|
156
|
+
"pixel_count": [self.pixel_width.value(), self.pixel_height.value()],
|
157
|
+
"pixel_detector_size": self.pixel_detector_size.value(),
|
158
|
+
"magnification": self.magnification.value(),
|
159
|
+
"dark_current": self.dark_current.value(),
|
160
|
+
"readout_noise": self.readout_noise.value(),
|
161
|
+
"bit_depth": self.bit_depth.value(),
|
162
|
+
"sensitivity": self.sensitivity.value(),
|
163
|
+
"base_adu": self.base_adu.value(),
|
164
|
+
"binning_size": self.binning_size.value(),
|
165
|
+
"quantum_efficiency": convert_dict_to_2_list(
|
166
|
+
self.quantum_efficiency_data
|
167
|
+
), # Use edited data here
|
168
|
+
}
|
169
|
+
return camera_data
|
170
|
+
|
171
|
+
def set_data(self, data: dict):
|
172
|
+
# Camera type
|
173
|
+
camera_type = data.get("type", "CMOS")
|
174
|
+
idx = self.camera_type.findText(camera_type)
|
175
|
+
if idx >= 0:
|
176
|
+
self.camera_type.setCurrentIndex(idx)
|
177
|
+
|
178
|
+
# Pixel count
|
179
|
+
pixel_count = data.get("pixel_count", [512, 512])
|
180
|
+
if len(pixel_count) == 2:
|
181
|
+
self.pixel_width.setValue(pixel_count[0])
|
182
|
+
self.pixel_height.setValue(pixel_count[1])
|
183
|
+
|
184
|
+
self.pixel_detector_size.setValue(data.get("pixel_detector_size", 6.5))
|
185
|
+
self.magnification.setValue(data.get("magnification", 60))
|
186
|
+
self.dark_current.setValue(data.get("dark_current", 1.0))
|
187
|
+
self.readout_noise.setValue(data.get("readout_noise", 1.0))
|
188
|
+
self.bit_depth.setValue(data.get("bit_depth", 16))
|
189
|
+
self.sensitivity.setValue(data.get("sensitivity", 0.5))
|
190
|
+
self.base_adu.setValue(data.get("base_adu", 100))
|
191
|
+
self.binning_size.setValue(data.get("binning_size", 1))
|
192
|
+
|
193
|
+
# Quantum efficiency
|
194
|
+
raw_qe = data.get("quantum_efficiency", [])
|
195
|
+
wavelengths = [pair[0] for pair in raw_qe]
|
196
|
+
efficiencies = [pair[1] for pair in raw_qe]
|
197
|
+
self.quantum_efficiency_data = {
|
198
|
+
"wavelengths": wavelengths,
|
199
|
+
"quantum_efficiency": efficiencies,
|
200
|
+
}
|
201
|
+
|
202
|
+
def get_help_path(self) -> Path:
|
203
|
+
return Path(__file__).parent.parent / "help_docs" / "detector_help.md"
|
204
|
+
|
205
|
+
|
206
|
+
def convert_dict_to_2_list(dict_c):
|
207
|
+
wl_qe = []
|
208
|
+
wl = dict_c["wavelengths"]
|
209
|
+
qe = dict_c["quantum_efficiency"]
|
210
|
+
for i in range(len(wl)):
|
211
|
+
lista = [wl[i], qe[i]]
|
212
|
+
wl_qe.append(lista)
|
213
|
+
return wl_qe
|
@@ -0,0 +1,225 @@
|
|
1
|
+
from pathlib import Path
|
2
|
+
|
3
|
+
from pydantic import ValidationError
|
4
|
+
from PyQt6.QtWidgets import (
|
5
|
+
QComboBox,
|
6
|
+
QDoubleSpinBox,
|
7
|
+
QFormLayout,
|
8
|
+
QHBoxLayout,
|
9
|
+
QMessageBox,
|
10
|
+
QPushButton,
|
11
|
+
QStackedWidget,
|
12
|
+
QVBoxLayout,
|
13
|
+
QWidget,
|
14
|
+
)
|
15
|
+
|
16
|
+
|
17
|
+
class CellConfigWidget(QWidget):
|
18
|
+
def __init__(self):
|
19
|
+
super().__init__()
|
20
|
+
layout = QVBoxLayout()
|
21
|
+
form = QFormLayout()
|
22
|
+
|
23
|
+
self.validate_button = QPushButton("Validate")
|
24
|
+
self.validate_button.clicked.connect(self.validate)
|
25
|
+
layout.addWidget(self.validate_button)
|
26
|
+
|
27
|
+
self.cell_type = QComboBox()
|
28
|
+
self.cell_type.addItems(
|
29
|
+
["SphericalCell", "RodCell", "RectangularCell", "OvoidCell"]
|
30
|
+
)
|
31
|
+
self.cell_type.currentIndexChanged.connect(self.update_params)
|
32
|
+
form.addRow("Cell Type:", self.cell_type)
|
33
|
+
|
34
|
+
self.param_stack = QStackedWidget()
|
35
|
+
self.param_widgets = {
|
36
|
+
"SphericalCell": self.make_spherical_widget(),
|
37
|
+
"RodCell": self.make_rod_widget(),
|
38
|
+
"RectangularCell": self.make_rect_widget(),
|
39
|
+
"OvoidCell": self.make_ovoid_widget(),
|
40
|
+
}
|
41
|
+
|
42
|
+
for widget in self.param_widgets.values():
|
43
|
+
self.param_stack.addWidget(widget)
|
44
|
+
|
45
|
+
layout.addLayout(form)
|
46
|
+
layout.addWidget(self.param_stack)
|
47
|
+
self.setLayout(layout)
|
48
|
+
|
49
|
+
def validate(self) -> bool:
|
50
|
+
from ...cells import create_cell
|
51
|
+
from ...configio.configmodels import CellParameters
|
52
|
+
|
53
|
+
try:
|
54
|
+
data = self.get_data()
|
55
|
+
|
56
|
+
# Validate the Pydantic model first
|
57
|
+
cell_params = CellParameters(**data)
|
58
|
+
|
59
|
+
# Try creating the cell with backend logic
|
60
|
+
create_cell(cell_params.cell_type, cell_params.params)
|
61
|
+
|
62
|
+
# Success
|
63
|
+
QMessageBox.information(
|
64
|
+
self, "Validation Successful", "Cell parameters are valid."
|
65
|
+
)
|
66
|
+
return True
|
67
|
+
|
68
|
+
except ValidationError as e:
|
69
|
+
QMessageBox.critical(self, "Validation Error", str(e))
|
70
|
+
return False
|
71
|
+
except Exception as e:
|
72
|
+
QMessageBox.critical(self, "Validation Error", str(e))
|
73
|
+
return False
|
74
|
+
|
75
|
+
def update_params(self, index):
|
76
|
+
self.param_stack.setCurrentIndex(index)
|
77
|
+
|
78
|
+
def make_spherical_widget(self):
|
79
|
+
widget = QWidget()
|
80
|
+
form = QFormLayout()
|
81
|
+
self.center_s = [QDoubleSpinBox() for _ in range(3)]
|
82
|
+
for c in self.center_s:
|
83
|
+
c.setRange(0, 1e5)
|
84
|
+
self.radius_s = QDoubleSpinBox()
|
85
|
+
self.radius_s.setRange(0, 1e4)
|
86
|
+
form.addRow("Center (x,y,z):", self._hbox(self.center_s))
|
87
|
+
form.addRow("Radius:", self.radius_s)
|
88
|
+
widget.setLayout(form)
|
89
|
+
return widget
|
90
|
+
|
91
|
+
def make_rod_widget(self):
|
92
|
+
widget = QWidget()
|
93
|
+
form = QFormLayout()
|
94
|
+
self.center_r = [QDoubleSpinBox() for _ in range(3)]
|
95
|
+
self.direction_r = [QDoubleSpinBox() for _ in range(3)]
|
96
|
+
self.height_r = QDoubleSpinBox()
|
97
|
+
self.radius_r = QDoubleSpinBox()
|
98
|
+
for w in self.center_r + self.direction_r:
|
99
|
+
w.setRange(0, 1e5)
|
100
|
+
form.addRow("Center:", self._hbox(self.center_r))
|
101
|
+
form.addRow("Direction:", self._hbox(self.direction_r))
|
102
|
+
form.addRow("Height:", self.height_r)
|
103
|
+
form.addRow("Radius:", self.radius_r)
|
104
|
+
widget.setLayout(form)
|
105
|
+
return widget
|
106
|
+
|
107
|
+
def make_rect_widget(self):
|
108
|
+
widget = QWidget()
|
109
|
+
form = QFormLayout()
|
110
|
+
self.bounds = [QDoubleSpinBox() for _ in range(6)]
|
111
|
+
for b in self.bounds:
|
112
|
+
b.setRange(0, 1e5)
|
113
|
+
form.addRow("Bounds [xmin,xmax,ymin,ymax,zmin,zmax]:", self._hbox(self.bounds))
|
114
|
+
widget.setLayout(form)
|
115
|
+
return widget
|
116
|
+
|
117
|
+
def make_ovoid_widget(self):
|
118
|
+
widget = QWidget()
|
119
|
+
form = QFormLayout()
|
120
|
+
self.center_o = [QDoubleSpinBox() for _ in range(3)]
|
121
|
+
self.xradius = QDoubleSpinBox()
|
122
|
+
self.yradius = QDoubleSpinBox()
|
123
|
+
self.zradius = QDoubleSpinBox()
|
124
|
+
for c in self.center_o:
|
125
|
+
c.setRange(0, 1e5)
|
126
|
+
form.addRow("Center:", self._hbox(self.center_o))
|
127
|
+
form.addRow("X Radius:", self.xradius)
|
128
|
+
form.addRow("Y Radius:", self.yradius)
|
129
|
+
form.addRow("Z Radius:", self.zradius)
|
130
|
+
widget.setLayout(form)
|
131
|
+
return widget
|
132
|
+
|
133
|
+
def _hbox(self, widgets):
|
134
|
+
box = QHBoxLayout()
|
135
|
+
for w in widgets:
|
136
|
+
box.addWidget(w)
|
137
|
+
container = QWidget()
|
138
|
+
container.setLayout(box)
|
139
|
+
return container
|
140
|
+
|
141
|
+
def get_data(self):
|
142
|
+
ctype = self.cell_type.currentText()
|
143
|
+
if ctype == "SphericalCell":
|
144
|
+
return {
|
145
|
+
"cell_type": ctype,
|
146
|
+
"params": {
|
147
|
+
"center": [s.value() for s in self.center_s],
|
148
|
+
"radius": self.radius_s.value(),
|
149
|
+
},
|
150
|
+
}
|
151
|
+
elif ctype == "RodCell":
|
152
|
+
return {
|
153
|
+
"cell_type": ctype,
|
154
|
+
"params": {
|
155
|
+
"center": [s.value() for s in self.center_r],
|
156
|
+
"direction": [s.value() for s in self.direction_r],
|
157
|
+
"height": self.height_r.value(),
|
158
|
+
"radius": self.radius_r.value(),
|
159
|
+
},
|
160
|
+
}
|
161
|
+
elif ctype == "RectangularCell":
|
162
|
+
return {
|
163
|
+
"cell_type": ctype,
|
164
|
+
"params": {"bounds": [b.value() for b in self.bounds]},
|
165
|
+
}
|
166
|
+
elif ctype == "OvoidCell":
|
167
|
+
return {
|
168
|
+
"cell_type": ctype,
|
169
|
+
"params": {
|
170
|
+
"center": [s.value() for s in self.center_o],
|
171
|
+
"xradius": self.xradius.value(),
|
172
|
+
"yradius": self.yradius.value(),
|
173
|
+
"zradius": self.zradius.value(),
|
174
|
+
},
|
175
|
+
}
|
176
|
+
else:
|
177
|
+
return {"cell_type": ctype, "params": {}}
|
178
|
+
|
179
|
+
def set_data(self, data: dict):
|
180
|
+
try:
|
181
|
+
cell_type = data.get("cell_type", "RodCell")
|
182
|
+
self.cell_type.setCurrentText(cell_type)
|
183
|
+
|
184
|
+
params = data.get("params", {})
|
185
|
+
|
186
|
+
if cell_type == "SphericalCell":
|
187
|
+
center = params.get("center", [0, 0, 0])
|
188
|
+
radius = params.get("radius", 1.0)
|
189
|
+
for i, val in enumerate(center):
|
190
|
+
self.center_s[i].setValue(val)
|
191
|
+
self.radius_s.setValue(radius)
|
192
|
+
|
193
|
+
elif cell_type == "RodCell":
|
194
|
+
center = params.get("center", [0, 0, 0])
|
195
|
+
direction = params.get("direction", [1, 0, 0])
|
196
|
+
height = params.get("height", 1.0)
|
197
|
+
radius = params.get("radius", 0.5)
|
198
|
+
for i, val in enumerate(center):
|
199
|
+
self.center_r[i].setValue(val)
|
200
|
+
for i, val in enumerate(direction):
|
201
|
+
self.direction_r[i].setValue(val)
|
202
|
+
self.height_r.setValue(height)
|
203
|
+
self.radius_r.setValue(radius)
|
204
|
+
|
205
|
+
elif cell_type == "RectangularCell":
|
206
|
+
bounds = params.get("bounds", [0, 10, 0, 10, 0, 10])
|
207
|
+
for i, val in enumerate(bounds):
|
208
|
+
self.bounds[i].setValue(val)
|
209
|
+
|
210
|
+
elif cell_type == "OvoidCell":
|
211
|
+
center = params.get("center", [0, 0, 0])
|
212
|
+
xr = params.get("xradius", 1.0)
|
213
|
+
yr = params.get("yradius", 1.0)
|
214
|
+
zr = params.get("zradius", 1.0)
|
215
|
+
for i, val in enumerate(center):
|
216
|
+
self.center_o[i].setValue(val)
|
217
|
+
self.xradius.setValue(xr)
|
218
|
+
self.yradius.setValue(yr)
|
219
|
+
self.zradius.setValue(zr)
|
220
|
+
|
221
|
+
except Exception as e:
|
222
|
+
print(f"[CellConfigWidget] Failed to load data: {e}")
|
223
|
+
|
224
|
+
def get_help_path(self) -> Path:
|
225
|
+
return Path(__file__).parent.parent / "help_docs" / "cell_help.md"
|