feat(lamni): add lamni_move_to_scan_center wrapper, document shift computation
- LamNI.lamni_move_to_scan_center(shift_x, shift_y, angle): thin client wrapper around scans.lamni_move_to_scan_center with the same parameters and docstring - user docs: describe how the per-projection shift is computed (base shift, x-ray eye fit, manual shift, correction tables) in the fine alignment section, and add a section on checking the x-ray eye correction with the eye still in Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016gUjUT2xCNpnBQkThn3CqP
This commit is contained in:
1 parent
b066b526c1
commit
af7878988e
2 files changed
+45
No files matched your search
@@ -733,6 +733,21 @@ class LamNI(TomoQueueMixin, LamNIAlignmentMixin, LamNIOpticsMixin, LamniGuiTools
|
||||
def lights_on(self):
|
||||
self.device_manager.devices.lsamx.controller.lights_on()
|
||||
|
||||
def lamni_move_to_scan_center(self, shift_x: float, shift_y: float, angle: float):
|
||||
"""
|
||||
LamNI scan to move the interferometer to the computed scan center based on the provided shift and angle.
|
||||
|
||||
Args:
|
||||
shift_x (float): Shift x.
|
||||
shift_y (float): Shift y.
|
||||
angle (float): Angle.
|
||||
|
||||
Returns:
|
||||
ScanReport
|
||||
"""
|
||||
scans = builtins.__dict__.get("scans")
|
||||
return scans.lamni_move_to_scan_center(shift_x=shift_x, shift_y=shift_y, angle=angle)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Global parameters (backed by BEC global vars)
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
@@ -67,6 +67,20 @@ To capture a single fresh frame without running the full alignment:
|
||||
`lamni.xrayeye_update_frame()`
|
||||
or with the shutter left open: `lamni.xrayeye_update_frame(keep_shutter_open=True)`
|
||||
|
||||
##### Checking the x-ray eye alignment with the eye still in
|
||||
|
||||
While the X-ray eye is still in, you can move the interferometer to the scan centre of any angle and look at where the sample ends up, without starting a scan:
|
||||
`lamni.lamni_move_to_scan_center(shift_x, shift_y, angle)`
|
||||
|
||||
This is the same move that the alignment procedure and every scan use to place the sample. `shift_x` and `shift_y` are the base shift in mm, i.e. the centre found with the first click at 0° (`lamni.tomo_fovx_offset`, `lamni.tomo_fovy_offset`), `angle` is the rotation angle in degrees. The shift is rotated with the angle using the LamNI geometry. The command does not rotate the sample itself and it returns a scan report, so add `.wait()` to block until the move is done.
|
||||
|
||||
Example, checking the correction at 90°:
|
||||
|
||||
1. `lamni.feedback_disable()` and rotate: `umv(dev.lsamrot, 90)`
|
||||
2. `lamni.lamni_move_to_scan_center(lamni.tomo_fovx_offset, lamni.tomo_fovy_offset, 90).wait()` (this re-enables the feedback)
|
||||
3. `lamni.xrayeye_update_frame(keep_shutter_open=True)` to look at the sample
|
||||
4. `lamni.lamni_compute_additional_correction_xeye_mu(90)` prints the correction (x and y, in mm) that the scan will add on top of this position. The sample should appear displaced from the FZP centre by the size of this correction, and the correction compensates for that displacement. A clearly different displacement means the fit is off, e.g. a bad click, and the alignment should be repeated.
|
||||
|
||||
* If slits were opened during alignment, close the slits: `slits` to around 0.3
|
||||
* `lamni.leye_out()` remove the X-ray eye and move the flight tube in
|
||||
* *possibly check slit1, idgap*
|
||||
@@ -75,6 +89,22 @@ or with the shutter left open: `lamni.xrayeye_update_frame(keep_shutter_open=Tru
|
||||
|
||||
The sample fine alignment can be obtained using ptychography. For this a short laminogram has to be recorded.
|
||||
|
||||
**How the shift at each projection angle is computed.** `lamni.tomo_scan_projection(angle)`, which is used by the alignment scan and by the laminography scan, combines several contributions. All are evaluated for the requested angle:
|
||||
|
||||
| Contribution | Source | Applied as |
|
||||
|---|---|---|
|
||||
| Base shift | first click (0°) of the x-ray eye alignment, stored as `lamni.tomo_fovx_offset` / `tomo_fovy_offset` | scan centre (`center_x`, `center_y`), rotated with the angle |
|
||||
| X-ray eye correction | sinusoidal fit `A·sin(angle + B) + C` of the 8 clicked positions, `lamni.lamni_compute_additional_correction_xeye_mu(angle)` | added to the shift |
|
||||
| Manual shift | `lamni.manual_shift_x` / `manual_shift_y`, constant for all angles | added to the shift |
|
||||
| Additional correction 1 | lookup table from the fine alignment, `lamni.read_additional_correction(file)` | subtracted from the shift |
|
||||
| Additional correction 2 | lookup table of the second iteration, `lamni.read_additional_correction_2(file)` | subtracted from the shift |
|
||||
|
||||
The shift is therefore `manual + x-ray eye − correction 1 − correction 2`, on top of the rotated base shift. The x-ray eye fit was measured after the base shift was applied, so the two do not count twice.
|
||||
|
||||
The correction tables are read from the files written by `BEC_ptycho_align`, with one shift per alignment angle. There is no interpolation: for each projection the entry with the closest angle is used. If a table has no data, it is skipped and `Not applying additional correction` is printed. Without an x-ray eye fit, `Not applying any X-ray eye correction` is printed. Each correction can be removed again with `lamni.reset_correction()`, `lamni.reset_correction_2()` and `lamni.reset_xray_eye_correction()`.
|
||||
|
||||
The alignment scan itself already uses the x-ray eye correction and any correction tables that are loaded. So the ptychographic alignment measures what is left over after those corrections, which is why a second iteration with `read_additional_correction_2()` is useful.
|
||||
|
||||
* `lamni.tomo_parameters()` adjust the ptychographic scan parameters for the alignment scan (FOV/step size/counting time) — `tomo_type` and number of projections are ignored, since the alignment scan always runs its own fixed 12 points spread evenly across the full 360 degrees, independent of the main tomogram's settings.
|
||||
* `lamni.tomo_alignment_scan()` perform the alignment scan. Requires x-ray-eye alignment to have already been done — it will abort with a message otherwise. Scan numbers, angles and the existing x-ray-eye-fit offset at each angle are written to `~/data/raw/logs/ptychotomoalign_scannum.txt` and also printed at the end.
|
||||
* Run `BEC_ptycho_align` (in Matlab, **force ptycho=1**, and **correct scan numbers**) using the printed/logged scan numbers.
|
||||
|
||||
Reference in new issue
Block a user