Fast 3D + time imaging with hardware triggering¶
This notebook acquires a fast TZYX
data series.
The camera is run at reduced ROI
to achieve higher framerate
(here 200 frames per second).
Movement of the z stage is “sequenced” to speed up acquisition. The z stage advances to the next position in the sequence when a trigger from the camera is received. This eliminates delays due to software communication.
Here a piezo z stage from ASI Imaging is used. The stage is put in “Fast Sequencing” mode such that the position sequence is repeated if a trigger is received after the last position in the sequence has been reached. In this way the camera is run in “burst mode” for multiple z stack acquisitions without having to resend the sequence buffer.
A custom z position sequence representing a triangle waveform is used. This means that the stage will move from start_end_pos = -2.5
to mid_pos = 2.5
in steps of step_size = 0.25
and then back from mid_pos
to start_end_pos
in steps of -step_size
. This set of stage positions avoids the large jump from the end of the sequence back to the beginning of the sequence which may take more time to complete than a single step and may disturb the sample.
Using pycro-manager
this set of acquisition events is encoded as follows:
events = []
z_idx_ = z_idx.copy()
for i in range(num_time_points):
for j in z_idx_:
events.append({'axes': {'time':i, 'z': j}})
z_idx_.reverse()
[ ]:
import numpy as np
from pycromanager import Acquisition, Bridge
[ ]:
def upload_piezo_sequence(bridge, start_end_pos, mid_pos, step_size, relative=True):
"""
Upload a triangle waveform of z_stage positions and set the z_stage in UseFastSequence mode
:param bridge: pycro-manager java bridge
:type bridge: pycromanager.core.Bridge
:param start_end_pos: start and end position of triangle waveform
:type start_end_pos: float
:param mid_pos: mid position of the triangle waveform
:type mid_pos: float
:param step_size: z_stage step size
:type step_size: float
:param relative: set to False if given start_end_pos and mid_pos are absolute
:return: current z position and absolute positions of triangle waveform
"""
mmc = bridge.get_core()
z_stage = mmc.get_focus_device()
pos_sequence = np.hstack(
(
np.arange(start_end_pos, mid_pos + step_size, step_size),
np.arange(mid_pos, start_end_pos - step_size, -step_size),
)
)
z_pos = 0
if relative:
z_pos = mmc.get_position(z_stage)
pos_sequence += z_pos
# construct java object
positionJ = bridge.construct_java_object("mmcorej.DoubleVector")
for i in pos_sequence:
positionJ.add(float(i))
# send sequence to stage
mmc.set_property(z_stage, "UseSequence", "Yes")
mmc.set_property(z_stage, "UseFastSequence", "No")
mmc.load_stage_sequence(z_stage, positionJ)
mmc.set_property(z_stage, "UseFastSequence", "Armed")
return z_pos, pos_sequence
Construct java objects¶
[9]:
bridge = Bridge()
mmc = bridge.get_core()
mmStudio = bridge.get_studio()
Set acquisition parameters¶
[10]:
# Data set parameters
path = r"C:\test"
name = "pycromanager test"
# z stack parameters
start_end_pos = -2.5
mid_pos = 2.5
step_size = 0.25
relative = True
# time series parameters
duration = 2 # in seconds
exposure_time = 3 # in milliseconds
framerate = 200
# FOV parameters
ROI = [924, 770, 616, 514]
num_z_positions = int(abs(mid_pos - start_end_pos) / step_size + 1)
z_idx = list(range(num_z_positions))
num_time_points = np.ceil(duration * framerate / num_z_positions).astype(np.int)
Prepare for acquisition¶
[11]:
# setup cameras
mmc.set_exposure(exposure_time)
mmc.set_roi(*ROI)
mmc.set_property("Camera", "Framerate", framerate)
# setup z stage
z_stage = mmc.get_focus_device()
z_pos, pos_sequence = upload_piezo_sequence(
bridge, start_end_pos, mid_pos, step_size, relative
)
num_z_positions = len(pos_sequence)
# move to first position
mmc.set_position(z_stage, pos_sequence[0])
Generate events¶
[12]:
events = []
z_idx_ = z_idx.copy()
for i in range(num_time_points):
for j in z_idx_:
events.append({"axes": {"time": i, "z": j}})
z_idx_.reverse()
Acquire data¶
[13]:
with Acquisition(directory=path, name=name) as acq:
acq.acquire(events)
Reset¶
[14]:
# turn off sequencing
mmc.set_property(z_stage, "UseFastSequence", "No")
mmc.set_property(z_stage, "UseSequence", "No")
# move back to initial position
mmc.set_position(z_stage, z_pos)
bridge.close()