Feat: Setup dose/Ang
CI / lint (push) Skipped
CI / test (3.12) (push) Skipped
CI / test (3.13) (push) Skipped
CI / test-with-beamline-plugins (pxi_bec) (push) Skipped
CI / test-with-beamline-plugins (pxii_bec) (push) Skipped
CI / test-with-beamline-plugins (pxiii_bec) (push) Skipped
CI / lint (pull_request) Failing after 43s
CI / test (3.12) (pull_request) Successful in 1m12s
CI / test (3.14) (pull_request) Successful in 1m15s
CI / test (3.13) (pull_request) Successful in 1m20s
CI / test-with-beamline-plugins (pxi_bec) (pull_request) Successful in 1m20s
CI / test-with-beamline-plugins (pxii_bec) (pull_request) Successful in 1m29s
CI / test-with-beamline-plugins (pxiii_bec) (pull_request) Successful in 1m35s
CI / test-with-coverage (pull_request) Successful in 1m44s
CI / coverage-analysis (pull_request) Failing after 3s

This commit is contained in:
2026-09-14 16:44:09 +02:00
parent b17b38adfe
commit 4ce7692e86
+8 -23
View File
@@ -27,16 +27,6 @@ logger = setup_logger(LOGGER_NAME)
# absorb more than this, so use RADDOSE-3D for those.
KDOSE_1A_PH_UM2_GY = 2000.0
# Howells et al. put the half-dose at 10 MGy per A of resolution; we budget
# half of that, so the target resolution keeps roughly 70% of its intensity.
CRYO_DOSE_PER_ANGSTROM_MGY = 10.0
# Above the glass transition the crystal dies ~2 orders of magnitude faster.
# Owen et al. measured D(1/2) ~ 0.38 MGy at room temperature and Holton's
# lifetime calculator defaults to 0.2 MGy; 0.1 MGy/A with the same safety
# factor sits just below both.
RT_DOSE_PER_ANGSTROM_MGY = 0.1
DOSE_SAFETY_FACTOR = 2.0
# Protein-solvent glass transition. Warkentin & Thorne fit two Arrhenius
# regimes either side of ~200 K: below it damage is athermal (Ea ~ 1 kJ/mol),
# above it diffusion-dominated (Ea ~ 18 kJ/mol) and the cryo budget no longer
@@ -120,7 +110,6 @@ class SimpleRotationSettingsPanel(QWidget):
self.dtz = 120
self.image_time_s = 0.1
self._d = None
self._temperature = 100
self._omega = 0
self.total_time_s = 0
self.parameters = SimpleScanParameters()
@@ -178,13 +167,13 @@ class SimpleRotationSettingsPanel(QWidget):
self._layout.addWidget(QLabel("°", parent=self), 3, 4)
self.image_angle_enter.newValue.connect(self.set_image_angle)
self._layout.addWidget(QLabel("Temperature", parent=self), 4, 0)
self.temp_enter = NumberLineEdit(
80, 330, decimals=2, default=100.0, parent=self, track_pending=True
self._layout.addWidget(QLabel("Dose 1 Å res.", parent=self), 4, 0)
self.dose_ang_enter = NumberLineEdit(
0.01, 20.0, decimals=2, default=5.0, parent=self, track_pending=True
)
self._layout.addWidget(self.temp_enter, 4, 1, 1, 3)
self._layout.addWidget(QLabel("K", parent=self), 4, 4)
self.temp_enter.newValue.connect(self.set_temperature)
self._layout.addWidget(self.dose_ang_enter, 4, 1, 1, 3)
self._layout.addWidget(QLabel("MGy/Å", parent=self), 4, 4)
self.dose_ang_enter.newValue.connect(self.set_dose_ang)
# Run + Abort directly under the last configurable row; the read-only
# block below is reference info, not something to scroll past to act.
@@ -342,7 +331,7 @@ class SimpleRotationSettingsPanel(QWidget):
self.update_calculated_labels()
@Slot(float)
def set_temperature(self, v: float):
def set_dose_ang(self, v: float):
self.update_calculated_labels()
@Slot(float)
@@ -438,11 +427,7 @@ class SimpleRotationSettingsPanel(QWidget):
else:
self.dose_rate_MGy_s = 0.0
if self.temp_enter.value > GLASS_TRANSITION_K:
dose_per_angstrom = RT_DOSE_PER_ANGSTROM_MGY
else:
dose_per_angstrom = CRYO_DOSE_PER_ANGSTROM_MGY
self.target_dose_MGy = dose_per_angstrom * d_tar / DOSE_SAFETY_FACTOR
self.target_dose_MGy = self.dose_ang_enter.value * d_tar
self.n_images = max(1, round(total_angle / image_angle))