pytweezer.drivers.slm module

Meadowlark Blink Plus SLM driver.

Wraps the Blink C-wrapper SDK (a ctypes DLL) as a single-target device backend, so a Spatial Light Modulator is a first-class device: get_device("Rb SLM"). This replaces the old standalone ZMQ SLMServer.py — the point of making it a device is that a coordinator sharing its process (e.g. rearrangement) can call slm.update_mask(frame) directly, with no socket between the GPU-computed phasemask and the hardware.

The Blink DLL and LUT paths are Windows-only and specific to the SLM PC; they are loaded lazily in _connect(), so importing this module never requires the SDK to be present. Use SimulatedSLM (simulate: True) anywhere else.

Masks are uint8 arrays of shape (height, width) (or a flat height*width buffer) already mapped through the phase LUT by the caller; the hardware applies its own voltage LUT on top.

pytweezer.drivers.slm.DEFAULT_SDK_DLL = 'C:\\Program Files\\Meadowlark Optics\\Blink Plus\\SDK\\Blink_C_wrapper'

Defaults matching the lab’s Blink Plus install; overridable via config.

pytweezer.drivers.slm.MAX_PRELOAD_FRAMES = 752

Frames the 1024x1024 board’s on-board memory holds (manual S4.3.9).

class pytweezer.drivers.slm.SLM(sdk_dll='C:\\Program Files\\Meadowlark Optics\\Blink Plus\\SDK\\Blink_C_wrapper', lut_file='C:\\Program Files\\Meadowlark Optics\\Blink Plus\\LUT Files\\slm40_at852.LUT', board_number=1, timeout_ms=5000, wait_for_trigger=False, flip_immediate=False, output_pulse=False)[source]

Bases: object

Blink Plus SLM over its ctypes C-wrapper SDK.

The live hardware handle (the loaded DLL) lives on _lib; None means disconnected. One board only (board number defaults to 1).

Parameters:
  • sdk_dll (str)

  • lut_file (str | None)

  • board_number (int)

  • timeout_ms (int)

  • wait_for_trigger (bool)

  • flip_immediate (bool)

  • output_pulse (bool)

close()[source]
Return type:

None

get_dimensions()[source]
Return type:

dict

get_temperature()[source]
Return type:

float

is_connected()[source]
Return type:

bool

preload_image(mask_array, frame)[source]

Upload one mask into on-board frame slot frame.

Same destination as preload_sequence(), one frame at a time, so frames can be uploaded as they are generated instead of after the whole sequence exists. Does not display anything. Raises on failure.

Parameters:
Return type:

None

preload_sequence(mask_sequence)[source]

Upload a whole (n, H, W) sequence into the SLM’s on-board memory.

Does not display anything by itself (1024x1024 board only, up to 752 frames); the upload time is logged. Raises on failure.

Parameters:

mask_sequence (ndarray)

Return type:

None

run_sequence(mask_sequence, fps=1.0)[source]

Display each frame of a (n, H, W) sequence at fps (software timed).

Software-timed writes; for hardware-triggered playback use preload_sequence(), start_auto_increment(), and drive the SLM’s external trigger.

Parameters:
Return type:

None

set_wait_for_trigger(enabled)[source]

Turn external-trigger gating on or off at runtime.

With it on, an image is not displayed until a trigger falling edge arrives, and calls that load images (update_mask, preload_sequence) block until one does or timeout_ms expires. Preloading therefore has to happen with it off; turn it on only to clock a preloaded sequence out with start_auto_increment().

Parameters:

enabled (bool)

Return type:

None

start_auto_increment(list_length)[source]

Arm hardware auto-increment over a preloaded sequence.

After preload_sequence(), this makes the SLM listen for external triggers: frame 0 is live once armed, then each trigger advances to the next preloaded frame, looping back to frame 0 after the last one, until stop_auto_increment(). So an n-frame sequence needs n-1 triggers to end on the final frame; an n-th trigger wraps to frame 0.

1024x1024 board with firmware rev >= 2.4 only. Raises on failure.

Parameters:

list_length (int)

Return type:

None

stop_auto_increment()[source]

Stop hardware auto-increment (see start_auto_increment()).

Leaves whichever frame was last triggered live on the SLM. Raises on failure.

Return type:

None

update_mask(mask_array)[source]

Write one phase mask to the SLM (blocks until the write completes).

Raises RuntimeError if the DMA or write-complete handshake fails.

Parameters:

mask_array (ndarray)

Return type:

None

class pytweezer.drivers.slm.SimulatedSLM(width=1024, height=1024, depth=8, **_ignored)[source]

Bases: object

Synthetic SLM: remembers the last mask written and counts frames.

Interface-complete with SLM via simulate(), so anything the real driver adds is auto-stubbed. Fixed 1024x1024 8-bit geometry, matching the lab’s board.

Parameters:
close()[source]
Return type:

None

get_dimensions()[source]
Return type:

dict

get_temperature()[source]
Return type:

float

is_connected()[source]
Return type:

bool

preload_image(mask_array, frame)[source]
Parameters:
Return type:

None

preload_sequence(mask_sequence)[source]
Parameters:

mask_sequence (ndarray)

Return type:

None

run_sequence(mask_sequence, fps=1.0)[source]
Parameters:
Return type:

None

set_wait_for_trigger(enabled)[source]
Parameters:

enabled (bool)

Return type:

None

start_auto_increment(list_length)[source]
Parameters:

list_length (int)

Return type:

None

stop_auto_increment()[source]
Return type:

None

update_mask(mask_array)[source]
Parameters:

mask_array (ndarray)

Return type:

None