diff --git a/gui/src/aaregui/panels/smart_rotation_panel.py b/gui/src/aaregui/panels/smart_rotation_panel.py
index 2acc0fae..5c765d87 100644
--- a/gui/src/aaregui/panels/smart_rotation_panel.py
+++ b/gui/src/aaregui/panels/smart_rotation_panel.py
@@ -1,3 +1,5 @@
+import math
+
from PySide6.QtCore import Slot, Qt, Signal
from PySide6.QtWidgets import QWidget, QGridLayout, QLabel, QFrame, QPushButton, QSpacerItem, QSizePolicy
@@ -14,6 +16,12 @@ class SimpleRotationSettingsPanel(QWidget):
super().__init__(parent)
+ self.xtal_size_dose_rate_MGy_s = None
+ self.xtal_x = None
+ self.xtal_y = None
+ self.xtal_z = None
+ self.target_dose_MGy = None
+ self.dose_rate_MGy_s = None
self._filename = ""
self.dtz = 120
self.n_images = None
@@ -21,6 +29,9 @@ class SimpleRotationSettingsPanel(QWidget):
self.image_time_s = None
self.image_angle = 0.2
self.__d = None
+ self._temperature = 100
+ self.__omega = 0
+ self._wilson_b = 0
self._layout = QGridLayout(self)
@@ -73,55 +84,201 @@ class SimpleRotationSettingsPanel(QWidget):
self._layout.addWidget(self.dtz_label, 6, 1, 1, 3)
self._layout.addWidget(QLabel("mm", parent=self), 6, 4)
+ self._layout.addWidget(QLabel("Target Dose", parent=self), 7, 0)
+ self.target_dose_label = QLabel(f"--", parent=self)
+ self.target_dose_label.setAlignment(Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter)
+ self._layout.addWidget(self.target_dose_label, 7, 1, 1, 3)
+ self._layout.addWidget(QLabel("MGy", parent=self), 7, 4)
+
+ self._layout.addWidget(QLabel("Calculated Dose Rate", parent=self), 8, 0)
+ self.calculated_dose_rate_label = QLabel(f"--", parent=self)
+ self.calculated_dose_rate_label.setAlignment(Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter)
+ self._layout.addWidget(self.calculated_dose_rate_label, 8, 1, 1, 3)
+ self._layout.addWidget(QLabel("MGy S^-1", parent=self), 8, 4)
+
+ self._layout.addWidget(QLabel("Temperature", parent=self), 9, 0)
+ self.temp_enter = NumberLineEdit(80, 330, decimals=2, default=100.0, parent=self)
+ self._layout.addWidget(self.temp_enter, 9, 1, 1, 3)
+ self._layout.addWidget(QLabel("K", parent=self), 9, 4)
+ self.temp_enter.newValue.connect(self.set_temperature)
+
+ self._layout.addWidget(QLabel("Start angle", parent=self), 10, 0)
+ self.start_angle = NumberLineEdit(-720, 720.0, 0.0, decimals=3, parent=self)
+ self._layout.addWidget(self.start_angle, 10, 1, 1, 3)
+ self._layout.addWidget(QLabel("°", parent=self), 10, 4)
+
+ self.omega_button = QPushButton("Ω")
+ self.omega_button.setFixedWidth(20)
+ self.omega_button.clicked.connect(self.update_omega_start)
+ self._layout.addWidget(self.omega_button, 10, 5)
+
+ self._layout.addWidget(QLabel("Wilson B Factor", parent=self), 11, 0)
+ self.wilson_b_label = QLabel(f"--", parent=self)
+ self.wilson_b_label.setAlignment(Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter)
+ self._layout.addWidget(self.wilson_b_label, 11, 1, 1, 3)
+ self._layout.addWidget(QLabel("Å^2", parent=self), 11, 4)
+
+ self._layout.addWidget(QLabel("Crystal Size x from Grid Scan", parent=self), 12, 0)
+ self.xtal_x_label = QLabel(f"--", parent=self)
+ self.xtal_x_label.setAlignment(Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter)
+ self._layout.addWidget(self.xtal_x_label, 12, 1, 1, 3)
+ self._layout.addWidget(QLabel("um", parent=self), 12, 4)
+
+ self._layout.addWidget(QLabel("Crystal Size y from Grid Scan", parent=self), 13, 0)
+ self.xtal_y_label = QLabel(f"--", parent=self)
+ self.xtal_y_label.setAlignment(Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter)
+ self._layout.addWidget(self.xtal_y_label, 13, 1, 1, 3)
+ self._layout.addWidget(QLabel("um", parent=self), 13, 4)
+
+ self._layout.addWidget(QLabel("Crystal Size z from Grid Scan", parent=self), 14, 0)
+ self.xtal_z_label = QLabel(f"--", parent=self)
+ self.xtal_z_label.setAlignment(Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter)
+ self._layout.addWidget(self.xtal_z_label, 14, 1, 1, 3)
+ self._layout.addWidget(QLabel("um", parent=self), 14, 4)
+
+ self._layout.addWidget(QLabel("Calculated Dose from crystal size", parent=self), 15, 0)
+ self.xtal_size_dose_label = QLabel(f"--", parent=self)
+ self.xtal_size_dose_label.setAlignment(Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter)
+ self._layout.addWidget(self.xtal_size_dose_label, 15, 1, 1, 3)
+ self._layout.addWidget(QLabel("MGy", parent=self), 15, 4)
+
+ self._layout.addWidget(QLabel("X-ray Wavelength", parent=self), 16, 0)
+ self.wavelength_label = QLabel("--", parent=self)
+ self.wavelength_label.setAlignment(Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter)
+ self._layout.addWidget(self.wavelength_label, 16, 1, 1, 3)
+ self._layout.addWidget(QLabel("Å", parent=self), 16, 4)
+
+ self._layout.addWidget(QLabel("Flux", parent=self), 17, 0)
+ self.flux_label = QLabel(f"--", parent=self)
+ self.flux_label.setAlignment(Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter)
+ self._layout.addWidget(self.flux_label, 17, 1, 1, 3)
+ self._layout.addWidget(QLabel("ph s^-1", parent=self), 17, 4)
+
+ self._layout.addWidget(QLabel("Beam Size", parent=self), 18, 0)
+ self.beam_size_label = QLabel(f"--", parent=self)
+ self.beam_size_label.setAlignment(Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter)
+ self._layout.addWidget(self.beam_size_label, 18, 1, 1, 3)
+ self._layout.addWidget(QLabel("um ^ 2", parent=self), 18, 4)
+
+ self._layout.addWidget(QLabel("Calculated Dose", parent=self), 19, 0)
+ self.calculated_dose_label = QLabel(f"--", parent=self)
+ self.calculated_dose_label.setAlignment(Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter)
+ self._layout.addWidget(self.calculated_dose_label, 19, 1, 1, 3)
+ self._layout.addWidget(QLabel("MGy", parent=self), 19, 4)
+
# add vertical stretch between detector distance and the run button
- self._layout.addItem(QSpacerItem(0, 0, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding), 7, 0, 1, 6)
+ self._layout.addItem(QSpacerItem(0, 0, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding), 20, 0, 1, 6)
# Run rotation button
self.run_rotation_button = QPushButton("Run rotation", parent=self)
self.run_rotation_button.setStyleSheet("color: rgb(78, 154, 6);")
- self._layout.addWidget(self.run_rotation_button, 8, 0, 1, 6)
+ self.run_rotation_button.clicked.connect(self.run_measurement)
+ self._layout.addWidget(self.run_rotation_button, 21, 0, 1, 6)
@Slot(DAQStatusModel)
def update_daq_status(self, s: DAQStatusModel):
self.__d = s
- best = getattr(s, "last_best_res", None)
- if best is not None:
+ best_res = s.last_best_res
+
+ if best_res is not None:
# clamp to control limits and update field; this will also trigger recalculation
lo, hi = 0.8, 10.0
- v = max(lo, min(hi, float(best)))
+ v = max(lo, min(hi, float(best_res)))
self.visible_res_enter.update_value(v)
self.set_visible_resolution(v)
+
+ best_b_factor = s.last_best_b_factor
+
+ if best_b_factor is not None:
+ self.wilson_b_label.setText(f"{best_b_factor:.2f}")
+
+ xtal_size = s.crystal_size
+ if xtal_size is not None:
+ # clamp to control limits and update field; this will also trigger recalculation
+ self.xtal_x = xtal_size.x
+ self.xtal_y = xtal_size.y
+ self.xtal_z = xtal_size.z
+ self.xtal_x_label.setText(f"{self.xtal_x:.2f}")
+ self.xtal_y_label.setText(f"{self.xtal_y:.2f}")
+ self.xtal_z_label.setText(f"{self.xtal_z:.2f}")
+
+ #self.omega.new_value(s.geom.omega_deg)
+ self.beam_size_label.setText(
+ f"{s.geom.beam_size_mm.x * 1000.0} x {s.geom.beam_size_mm.y * 1000.0}"
+ )
+ self.flux_label.setText(f"{(s.bl.flux_ph_s / 1e9):.2f}")
+ if s.diffraction.wavelength_angstrom is None:
+ self.wavelength_label.setText("N/A")
+ else:
+ self.wavelength_label.setText(f"{s.diffraction.wavelength_angstrom:.3f}")
self.update_calculated_labels()
@Slot(float)
def set_visible_resolution(self, v: float):
self.update_calculated_labels()
+ @Slot(float)
+ def set_temperature(self, v: float):
+ self.update_calculated_labels()
+
@Slot(str)
def update_filename(self, filename: str):
self._filename = filename
+ @Slot()
+ def update_omega_start(self):
+ self.start_angle.update_value(self.__omega)
+
def update_calculated_labels(self):
if self.__d is None:
return
- flux = 2.5e11
-
+ flux = 2.5e11 #TODO link flux
+ #TODO add start angle
+ #TODO link beam energy
+ #TODO read resolution estiamtion from jfjoch
total_angle = self.angular_range_enter.value
d_vis = self.visible_res_enter.value
d_tar = 1/(1/d_vis + 0.1)
self.target_res_label.setText(f"{d_tar:.2f}")
+ #self.wilson_b_label.setText("--")
Kdose = 2000 / (self.__d.diffraction.wavelength_angstrom**2)
- dose_rate_MGy_s = (flux / (self.__d.geom.beam_size_mm.x * 1000 * self.__d.geom.beam_size_mm.y * 1000 * Kdose)) / 1e6
- target_dose_MGy = 10 * d_tar / 2.0
- total_time_s = target_dose_MGy / dose_rate_MGy_s
+
+ beam_size_um_y = self.__d.geom.beam_size_mm.y * 1000
+ beam_size_um_x = self.__d.geom.beam_size_mm.x * 1000
+ self.dose_rate_MGy_s = (flux / (beam_size_um_x * beam_size_um_y * Kdose)) / 1e6
+ if self.xtal_y is None or self.xtal_z is None or beam_size_um_x is None or beam_size_um_y is None:
+ self.xtal_size_dose_rate_MGy_s = self.dose_rate_MGy_s
+
+ elif self.xtal_y > beam_size_um_y or self.xtal_z > beam_size_um_y :
+ multiplier_1 = max(self.xtal_y, beam_size_um_y)
+ multiplier_2 = max( self.xtal_z,beam_size_um_y)
+ new_beam_um_y = math.sqrt(multiplier_1*multiplier_2)
+ self.xtal_size_dose_rate_MGy_s = (flux / (beam_size_um_x * new_beam_um_y * Kdose)) / 1e6
+
+ else:
+ self.xtal_size_dose_rate_MGy_s = self.dose_rate_MGy_s
+
+ if self.temp_enter.value > 250:
+ self.target_dose_MGy = 0.1 * d_tar / 2.0 #TODO add user input
+ else:
+ self.target_dose_MGy = 10 * d_tar / 2.0
+
+ self.target_dose_label.setText(f"{self.target_dose_MGy:.2f}")
+ self.calculated_dose_rate_label.setText(f"{self.dose_rate_MGy_s:.2f}")
+ self.xtal_size_dose_label.setText(f"{self.xtal_size_dose_rate_MGy_s:.2f}")
+
+ total_time_s = self.target_dose_MGy / self.dose_rate_MGy_s
+
+ self.calculated_dose_label.setText(f"{self.xtal_size_dose_rate_MGy_s*total_time_s:.2f}")
+
self.image_angle = 0.2
self.image_angle_label.setText(f"{self.image_angle:.3f}")
self.n_images = total_angle / self.image_angle
self.image_time_s = total_time_s / self.n_images
if self.image_time_s < 0.01:
self.transmission = self.image_time_s / 0.01
- image_time_s = 0.01
+ self.image_time_s = 0.01
else:
self.transmission = 1.0
@@ -134,6 +291,7 @@ class SimpleRotationSettingsPanel(QWidget):
self.dtz_label.setText(f"""-""")
elif self.dtz < self.__d.bl.dtz_min:
self.dtz_label.setText(f"""{self.dtz:.2f}""")
+ self.dtz = self.__d.bl.dtz_min
else:
self.dtz_label.setText(f"{self.dtz:.2f}")