To review later: simple parameter calculation #154

Open
opened 2026-08-20 20:57:08 +02:00 by duan_j · 0 comments
Owner

Why resolution/distance changes the measurement time
The "Simple" tab (smart_rotation_panel.py:17, class SimpleRotationSettingsPanel) is dose-driven, not time-driven. It has no exposure-time input and no editable detector distance — both are outputs computed from one input, the visible resolution, inside update_calculated_labels() (smart_rotation_panel.py:305-408):

d_vis = visible_res − 0.2 # fudge factor, line 315
d_tar = 1 / (1/d_vis + 0.1) # "Target resolution", line 318

target_dose = 10 · d_tar / 2 # cryo; 0.1·d_tar/2 if T > 250 K (lines 344-347)
dose_rate = flux / (beam_x·beam_y·2000/λ²) / 1e6 # flux HARD-CODED 2.5e11, line 308
total_time = target_dose / dose_rate # line 353 ← resolution → time
image_time = total_time / round(total_angle / image_angle) # line 362

dtz = detector_radius / tan(2·asin(λ/(2·d_tar))) # line 369 → aarecommon calc_dtz_mm
So the target dose budget is linear in the target d-spacing (a scaled Garman limit: 10 MGy at 2 Å). Coarser resolution → bigger allowed dose → longer total time, and simultaneously → larger detector distance via Bragg. Distance and time are siblings of the same variable d_tar, not cause and effect. If the computed frame time drops below the 1.1 ms detector floor, time is pinned and transmission is attenuated instead (lines 363-367).

Since dtz is a read-only label on this tab, "changing detector distance changes the time" happens two ways: editing resolution recomputes both together, and there's a feedback loop — after each raster the server stores the best observed spot resolution (raster/service.py:646), and the panel's 500 ms status tick writes it back into the resolution field and recomputes (smart_rotation_panel.py:236-244). The Rotation/Raster tabs don't do any of this — there dtz↔resolution are two views of one editable quantity and time is plain (total_angle/image_angle)·image_time.

Where it goes: "Run rotation" builds a RotationScanRequest(dtz, exp_time_s, steps, transmission) (lines 410-423) that physically moves the detector (daq.py:1960-1970); every recompute also pushes SimpleScanParameters → Redis auto_params, but automation calls get_collection_params(prefer_smart=False) so database params win and Simple values are only the fallback.

Defects noticed en route (noted, not touched): flux hard-coded at 2.5e11 while the label shows live flux, so the computed time is wrong whenever they differ; line 80 wires visible_res_enter to set_total_angle (Total-angle edits have no direct recompute trigger); the crystal-size-corrected dose rate is display-only while time uses the uncorrected one; self.transmission uninitialized → AttributeError if "Run rotation" is clicked before the first DAQ status; the alert-colored dtz label shows the unclamped value while the clamped dtz_min is what's sent; and number_line_edit.py:102 is a no-op (saved_value = saved_value) that currently protects a user-typed resolution from being stomped by the 2 Hz tick — fixing it naively would break manual entry. Full trace with all line references is in the plan file.

Why resolution/distance changes the measurement time The "Simple" tab ([smart_rotation_panel.py:17](vscode-webview://09ggectpopmdshokud1cf86qv465sntdnkmqnldktqdp6p5s3al4/src/aare/gui/panels/smart_rotation_panel.py#L17), class SimpleRotationSettingsPanel) is dose-driven, not time-driven. It has no exposure-time input and no editable detector distance — both are outputs computed from one input, the visible resolution, inside update_calculated_labels() ([smart_rotation_panel.py:305-408](vscode-webview://09ggectpopmdshokud1cf86qv465sntdnkmqnldktqdp6p5s3al4/src/aare/gui/panels/smart_rotation_panel.py#L305-L408)): d_vis = visible_res − 0.2 # fudge factor, line 315 d_tar = 1 / (1/d_vis + 0.1) # "Target resolution", line 318 target_dose = 10 · d_tar / 2 # cryo; 0.1·d_tar/2 if T > 250 K (lines 344-347) dose_rate = flux / (beam_x·beam_y·2000/λ²) / 1e6 # flux HARD-CODED 2.5e11, line 308 total_time = target_dose / dose_rate # line 353 ← resolution → time image_time = total_time / round(total_angle / image_angle) # line 362 dtz = detector_radius / tan(2·asin(λ/(2·d_tar))) # line 369 → aarecommon calc_dtz_mm So the target dose budget is linear in the target d-spacing (a scaled Garman limit: 10 MGy at 2 Å). Coarser resolution → bigger allowed dose → longer total time, and simultaneously → larger detector distance via Bragg. Distance and time are siblings of the same variable d_tar, not cause and effect. If the computed frame time drops below the 1.1 ms detector floor, time is pinned and transmission is attenuated instead (lines 363-367). Since dtz is a read-only label on this tab, "changing detector distance changes the time" happens two ways: editing resolution recomputes both together, and there's a feedback loop — after each raster the server stores the best observed spot resolution ([raster/service.py:646](vscode-webview://09ggectpopmdshokud1cf86qv465sntdnkmqnldktqdp6p5s3al4/src/aare/daq/operations/raster/service.py#L646)), and the panel's 500 ms status tick writes it back into the resolution field and recomputes ([smart_rotation_panel.py:236-244](vscode-webview://09ggectpopmdshokud1cf86qv465sntdnkmqnldktqdp6p5s3al4/src/aare/gui/panels/smart_rotation_panel.py#L236-L244)). The Rotation/Raster tabs don't do any of this — there dtz↔resolution are two views of one editable quantity and time is plain (total_angle/image_angle)·image_time. Where it goes: "Run rotation" builds a RotationScanRequest(dtz, exp_time_s, steps, transmission) (lines 410-423) that physically moves the detector ([daq.py:1960-1970](vscode-webview://09ggectpopmdshokud1cf86qv465sntdnkmqnldktqdp6p5s3al4/src/aare/daq/daq.py#L1960-L1970)); every recompute also pushes SimpleScanParameters → Redis auto_params, but automation calls get_collection_params(prefer_smart=False) so database params win and Simple values are only the fallback. Defects noticed en route (noted, not touched): flux hard-coded at 2.5e11 while the label shows live flux, so the computed time is wrong whenever they differ; line 80 wires visible_res_enter to set_total_angle (Total-angle edits have no direct recompute trigger); the crystal-size-corrected dose rate is display-only while time uses the uncorrected one; self.transmission uninitialized → AttributeError if "Run rotation" is clicked before the first DAQ status; the alert-colored dtz label shows the unclamped value while the clamped dtz_min is what's sent; and [number_line_edit.py:102](vscode-webview://09ggectpopmdshokud1cf86qv465sntdnkmqnldktqdp6p5s3al4/src/aare/gui/widgets/number_line_edit.py#L102) is a no-op (saved_value = saved_value) that currently protects a user-typed resolution from being stomped by the 2 Hz tick — fixing it naively would break manual entry. Full trace with all line references is in the plan file.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mx/AareDAQ#154