API Reference

Mirror control

Control over mirrors is provided through the Mirror class. Instances of this class are available by default as:

import bluelake as bl

bl.mirror1.move_to(x=1, y=2)

# Note: this line will fail on dual-trap systems:
bl.mirror3.move_to(x=0, y=0)

# Additional mirrors are defined in bluelake:
# (depending on actual availability of the hardware on your C-Trap)
bl.mirror4
bl.mirror12
bl.mirror34
class Mirror(device, id)

Control interface for a mirror

is_busy()

Is the mirror currenty executing a move?

Returns:
bool
move_by(dx=0, dy=0, speed=1)

Move the mirror relative to the current position.

The rest of the automation script is not executed until the mirror has finished the move.

Parameters:
dx, dyfloat

How much to move the mirror, in micrometers. Any of the axes can be omitted, in which case the mirror does not move in that direction.

speedfloat

Total speed of the move, in um/s (i.e, magnitude of the velocity vector). Note: The actual speed of the mirror depends on the accuracy of the steering device. Only for the high-resolution Mirror 1 can an accurate motion in X/Y be guaranteed. If no speed is given, it will default to 1.0um/s. If 0 is given, the device will move with its maximum speed.

move_to(waypoint=None, x=None, y=None, speed=None)

Move the mirror to the given coordinates.

The rest of the automation script is not executed until the mirror has finished the move.

This function is only available for mirrors that have absolute position control, such as the high-resolution Mirror 1 on C-Trap systems.

Parameters:
waypointOptional[str]

Name of a previously stored waypoint. Should exactly match the name of the waypoint as entered in the Bluelake user interface.

x, yOptional[float]

Instead of giving a waypoint, this function can also be called with a set of destination coordinates, in micrometers. Any of the axes can be omitted, in which case the trap does not move in that direction.

speedOptional[float]

Total speed of the move, in um/s (i.e, magnitude of the velocity vector). Note: The actual speed depends on the accuracy of the steering device. Only for the high-resolution Mirror 1 can an accurate motion in X/Y be guaranteed. If no speed is given, either the waypoint speed will be used, or it will default to 1.0um/s for coordinate parameters. If 0 is given, the device will move with its maximum speed.

Examples

mirror1.move_to('start position')
mirror1.move_to(x=1, y=2, speed=10)
start_moving_by(dx=0, dy=0, speed=1)

Start moving the mirror relative to the current position.

The function only sends the move command to the mirror. It does not wait for the move to finish.

Parameters:
dx, dyfloat

How much to move the mirror, in micrometers. Any of the axes can be omitted, in which case the mirror does not move in that direction.

speedfloat

Total speed of the move, in um/s (i.e, magnitude of the velocity vector). Note: The actual speed of the mirror depends on the accuracy of the steering device. Only for the high-resolution Mirror 1 can an accurate motion in X/Y be guaranteed. If no speed is given, it will default to 1.0um/s. If 0 is given, the device will move with its maximum speed.

start_moving_to(waypoint=None, x=None, y=None, speed=None)

Start moving the mirror to the given coordinates.

The function only sends the move command to the mirror. It does not wait for the move to finish.

This function is only available for mirrors that have absolute position control, such as the high-resolution Mirror 1 on C-Trap systems.

Parameters:
waypointOptional[str]

Name of a previously stored waypoint. Should exactly match the name of the waypoint as entered in the Bluelake user interface.

x, yOptional[float]

Instead of giving a waypoint, this function can also be called with a set of destination coordinates, in micrometers. Any of the axes can be omitted, in which case the trap does not move in that direction.

speedOptional[float]

Total speed of the move, in um/s (i.e, magnitude of the velocity vector). Note: The actual speed depends on the accuracy of the steering device. Only for the high-resolution Mirror 1 can an accurate motion in X/Y be guaranteed. If no speed is given, either the waypoint speed will be used, or it will default to 1.0um/s for coordinate parameters. If 0 is given, the device will move with its maximum speed.

start_oscillation(axis, amplitude, frequency, reset_position=False)

Start sinusoidal oscillation of the mirror

This function starts sinusoidal motion of the mirror along the given axis. Note that availability of oscillation depends on the mirror: not all mirror hardware supports this feature.

To stop the oscillation, simply call stop.

NOTE: For frequencies above 0.075 Hz, this motion is precisely timed (in hardware). Lower frequencies are typically software-timed, and therefore subject to jitter.

NOTE: For higher frequencies, the oscillation might not reach the specified amplitude due to the device response time and inertia.

Parameters:
axisstr

Which axis to oscillate: ‘X’ or ‘Y’.

amplitudefloat

Oscillation amplitude, in micrometers.

frequencyfloat

Oscillation frequency, in hertz.

reset_positionbool

Go back to the starting position when the oscillation is stopped (False by default)

Examples

import bluelake as bl

# When oscillating the mirrors, we advise using the `try`/`finally` construct which
# makes sure that the oscillation terminates if the script is stopped manually.
try:
    bl.mirror1.start_oscillation(axis='X', amplitude=5.0, frequency=1.0)
    bl.pause(10)  # Oscillate for 10 seconds
finally:
    bl.mirror1.stop()
stop()

Stop all movement of the mirror immediately.

property analog_calibration: PointXY

Analog calibration of the mirror (V to um conversion)

property digital_calibration: PointXY

Digital calibration of the mirror (rad to um conversion)

property motion_limits: LimitsXY

Motion limits of the mirror

This function is only available for mirrors that have absolute position control, such as the high-resolution Trap 1 on C-Trap systems.

Examples

from bluelake import mirror1
limits = mirror1.motion_limits

# Print coordinates
print(limits.lower.x)
print(limits.upper.y)
property position: PointXY

Current absolute position (um) of the mirror

This property is only available for mirrors that have absolute position control, such as the high-resolution Trap 1 on C-Trap systems.

Examples

from bluelake import mirror1
current_position = mirror1.position
x, y = mirror1.position

# All these lines print the x coordinate
print(current_position.x)
print(current_position[0])
print(x)
class PointXY(x: Any, y: Any)

A named tuple that represents per-axis quantities in xy-space

MotionLimits

alias of LimitsXY

class MCLSmoothMotion(mcl_smooth_motion_impl)

DAQ-based smooth motion for the MCL NanoDrive

is_moving()

Returns whether a move is currently in progress or not

move_along_path(points)

Move along a path given by a sequence of points

Moving in this way eliminates the DAQ buffer lag which would normally be present between individual moves.

Parameters:
pointslist of tuple(x, y, speed) with:
x, yfloat

Destination coordinates, in micrometers

speedfloat

Speed of the move between points, in um/s.

A list that describes points on path.

Examples

import bluelake as bl

bl.mcl_smooth_motion.move_along_path([(0.1, 1.2, 3.0), (1.1, 2.2, 1.0)])
move_by(dx=0.0, dy=0.0, speed=1.0)

Move relative to the current position

The movement is clipped (separately for each axis) to the smooth motion range.

Parameters:
dx, dyfloat

How much to move relative to current position, in micrometers

speedOptional[float]

Speed of the move, in um/s.

Examples

import bluelake as bl

bl.mcl_smooth_motion.move_by(dx=1.0, dy=1.0, speed=1.0)
move_to(x, y, speed=1.0)

Move to an absolute position within the smooth motion range

Parameters:
x, yfloat

Destination coordinates, in micrometers

speedOptional[float]

Speed of the move, in um/s.

Examples

import bluelake as bl

bl.mcl_smooth_motion.move_to(x=1.0, y=1.0, speed=1.0)
reset()

Reset the smooth motion voltage offset to zero

The smooth motion works by applying a voltage offset with respect to the MCL’s current USB position. This resets the offset to zero.

Equivalent to .move_to(x=0.0, y=0.0, speed=0.0).

start_moving_along_path(points)

Start moving along a path given by a sequence of points

Moving in this way eliminates the DAQ buffer lag which would normally be present between individual moves. The function only sends the move command to the mirror. It does not wait for the move to finish.

Parameters:
pointslist of tuple(x, y, speed) with:
x, yfloat

Destination coordinates, in micrometers

speedfloat

Speed of the move between points, in um/s.

A list that describes points on path.

Examples

import bluelake as bl

bl.mcl_smooth_motion.start_moving_along_path([(0.1, 1.2, 3.0), (1.1, 2.2, 1.0)])
start_moving_by(dx=0.0, dy=0.0, speed=1.0)

Start moving relative to the current position

The movement is clipped (separately for each axis) to the smooth motion range. The function only sends the move command to the mirror. It does not wait for the move to finish.

Parameters:
dx, dyfloat

How much to move relative to current position, in micrometers

speedOptional[float]

Speed of the move, in um/s.

Examples

import bluelake as bl

bl.mcl_smooth_motion.start_moving_by(dx=1.0, dy=1.0, speed=1.0)
start_moving_to(x, y, speed=1.0)

Start moving to an absolute position within the smooth motion range

The function only sends the move command to the mirror. It does not wait for the move to finish.

Parameters:
x, yfloat

Destination coordinates, in micrometers

speedOptional[float]

Speed of the move, in um/s.

Examples

import bluelake as bl

bl.mcl_smooth_motion.start_moving_to(x=1.0, y=1.0, speed=1.0)
start_oscillation(amplitude, frequency, axis)

Start oscillating of the prescribed amplitude and frequency on the given channel. Oscillations will persist indefinitely. This implementation makes the AO signal oscillate. The AO can be connected to the (MCL) nanostage analog input to perform active calibration using analog signals instead of digital control via the MCL controller. The function only sends the move command to analog output. It does not wait for the move to finish.

Parameters:
:param amplitude: oscillation amplitude in microns.
:param frequency: oscillation frequency in Hertz
:param axis: oscillation axis. options: “x”, “y”

Examples

import bluelake as bl bl.mcl_smooth_motion.start_oscillation(amplitude, frequency, axis)

stop()

Stop any motion

This is equivalent to reset. Added for consistency with the rest of the steering API.

wait()

Wait until the current move in progress is finished

property position: Point

The current position within the smooth motion range

Telescope control

Control over telescopes is provided through the Telescope class. Instances of this class are available by default as:

import bluelake as bl

bl.telescope12.move_to(z=1)

# Additional telescopes are defined in bluelake:
# (depending on actual availability of the hardware on your C-Trap)
bl.telescope34
class Telescope(device, id)

Control interface for a telescope

is_busy()

Is the telescope currenty executing a move?

Returns:
bool
move_by(dz=0, speed=1)

Move the telescope relative to the current position.

The rest of the automation script is not executed until the telescope has finished the move.

Parameters:
dzfloat

How much to move the telescope, in micrometers.

speedfloat

Total speed of the move, in um/s (i.e, magnitude of the velocity vector). Note: The actual speed depends on the accuracy of the steering device. Only for the high-resolution Mirror 1 can an accurate motion in X/Y be guaranteed. If no speed is given, it will default to 1.0um/s. If 0 is given, the device will move with its maximum speed.

move_to(waypoint=None, z=None, speed=None)

Move the telescope to the given coordinates.

The rest of the automation script is not executed until the telescope has finished the move.

Parameters:
waypointOptional[str]

Name of a previously stored waypoint. Should exactly match the name of the waypoint as entered in the Bluelake user interface.

zOptional[float]

Instead of giving a waypoint, this function can also be called with a set of destination coordinates, in micrometers.

speedOptional[float]

Total speed of the move, in um/s (i.e, magnitude of the velocity vector). Note: The actual speed depends on the accuracy of the steering device. Only for the high-resolution Mirror 1 can an accurate motion in X/Y be guaranteed. If no speed is given, either the waypoint speed will be used, or it will default to 1.0um/s for coordinate parameters. If 0 is given, the device will move with its maximum speed.

Examples

telescope12.move_to('start position')
telescope12.move_to(z=1, speed=10)
start_moving_by(dz=0, speed=1)

Start moving the telescope relative to the current position.

The function only sends the move command to the telescope. It does not wait for the move to finish.

Parameters:
dzfloat

How much to move the telescope, in micrometers.

speedfloat

Total speed of the move, in um/s (i.e, magnitude of the velocity vector). Note: The actual speed depends on the accuracy of the steering device. Only for the high-resolution Mirror 1 can an accurate motion in X/Y be guaranteed. If no speed is given, it will default to 1.0um/s. If 0 is given, the device will move with its maximum speed.

start_moving_to(waypoint=None, z=None, speed=None)

Start moving the telescope to the given coordinates.

The function only sends the move command to the telescope. It does not wait for the move to finish.

Parameters:
waypointOptional[str]

Name of a previously stored waypoint. Should exactly match the name of the waypoint as entered in the Bluelake user interface.

zOptional[float]

Instead of giving a waypoint, this function can also be called with a set of destination coordinates, in micrometers.

speedOptional[float]

Total speed of the move, in um/s (i.e, magnitude of the velocity vector). Note: The actual speed depends on the accuracy of the steering device. Only for the high-resolution Mirror 1 can an accurate motion in X/Y be guaranteed. If no speed is given, either the waypoint speed will be used, or it will default to 1.0um/s for coordinate parameters. If 0 is given, the device will move with its maximum speed.

stop()

Stop all movement of the telescope immediately.

property motion_limits: LimitsXY

Motion limits of the telescope

Examples

from bluelake import telescope12
limits = telescope12.motion_limits

# Print coordinates
print(limits.lower.z)
print(limits.upper.z)
property position: PointZ

Current absolute position (um) of the telescope

Examples

from bluelake import telescope12
current_position = telescope12.position

# These two lines both print the z coordinate
print(current_position.z)
print(current_position[0])
class PointZ(z: Any)

A named tuple that represents per-axis quantities in z-space

Nanostage control

Control of the nanostage is provided through the Nanostage class. An instance of this class is available by default as:

# (depending on actual availability of the hardware on your C-Trap)
import bluelake as bl

bl.nanostage.move_to(x=1, x=2, x=3)
class Nanostage(device, id)

Control interface for the nanostage

is_busy()

Is the nanostage currenty executing a move?

Returns:
bool
move_by(dx=0, dy=0, dz=0, speed=1)

Move the nanostage relative to the current position.

The rest of the automation script is not executed until the nanostage has finished the move.

Parameters:
dx, dy, dzOptional[float]

How much to move the nanostage, in micrometers. Any of the axes can be omitted, in which case the nanostage does not move in that direction.

speedfloat

Total speed of the move, in um/s (i.e, magnitude of the velocity vector). If no speed is given, it will default to 1.0um/s. If 0 is given, the device will move with its maximum speed.

move_to(waypoint=None, x=None, y=None, z=None, speed=None)

Move the nanostage to the given coordinates.

The rest of the automation script is not executed until the nanostage has finished the move.

Parameters:
waypointOptional[str]

Name of a previously stored waypoint. Should exactly match the name of the waypoint as entered in the Bluelake user interface. If the given name matches both an XY and a Z waypoint, an XYZ movement will be executed.

x, y, zOptional[float]

Instead of giving a waypoint, this function can also be called with a set of destination coordinates, in micrometers. Any of the axes can be omitted, in which case the nanostage does not move in that direction.

speedfloat

Total speed of the move, in um/s (i.e, magnitude of the velocity vector). If no speed is given, either the waypoint speed will be used, or it will default to 1.0um/s for coordinate parameters. For XYZ movement, the speed of the XY waypoint will be used. If 0 is given, the device will move with its maximum speed.

Examples

nanostage.move_to('start position')
nanostage.move_to(x=1, y=2, z=3, speed=10)
start_moving_by(dx=0, dy=0, dz=0, speed=1)

Start moving the nanostage relative to the current position.

The function only sends the move command to the nanostage. It does not wait for the move to finish.

Parameters:
dx, dy, dzOptional[float]

How much to move the nanostage, in micrometers. Any of the axes can be omitted, in which case the nanostage does not move in that direction.

speedfloat

Total speed of the move, in um/s (i.e, magnitude of the velocity vector). If no speed is given, it will default to 1.0um/s. If 0 is given, the device will move with its maximum speed.

start_moving_to(waypoint=None, x=None, y=None, z=None, speed=None)

Start moving the nanostage to the given coordinates.

The function only sends the move command to the nanostage. It does not wait for the move to finish.

Parameters:
waypointOptional[str]

Name of a previously stored waypoint. Should exactly match the name of the waypoint as entered in the Bluelake user interface. If the given name matches both an XY and a Z waypoint, an XYZ movement will be executed.

x, y, zOptional[float]

Instead of giving a waypoint, this function can also be called with a set of destination coordinates, in micrometers. Any of the axes can be omitted, in which case the nanostage does not move in that direction.

speedfloat

Total speed of the move, in um/s (i.e, magnitude of the velocity vector). If no speed is given, either the waypoint speed will be used, or it will default to 1.0um/s for coordinate parameters. For XYZ movement, the speed of the XY waypoint will be used. If 0 is given, the device will move with its maximum speed.

start_oscillation(axis, amplitude, frequency, reset_position=False)

Start sinusoidal oscillation of the nanostage

This function starts sinusoidal motion of the nanostage along the given axis. Note that availability of oscillation depends on the hardware: not all nanostages supports this feature.

To stop the oscillation, simply call stop.

NOTE: For frequencies above 0.075 Hz, this motion is precisely timed (in hardware). Lower frequencies are typically software-timed, and therefore subject to jitter.

NOTE: For higher frequencies, the oscillation might not reach the specified amplitude due to the device response time and inertia.

Parameters:
axisstr

Which axis to oscillate: ‘X’ or ‘Y’.

amplitudefloat

Oscillation amplitude, in micrometers.

frequencyfloat

Oscillation frequency, in hertz.

reset_positionbool

Go back to the starting position when the oscillation is stopped (False by default)

Examples

import bluelake as bl

# When oscillating the nanostage, we advise using the `try`/`finally` construct which
# makes sure that the oscillation terminates if the script is stopped manually.
try:
    bl.nanostage.start_oscillation(axis='X', amplitude=5.0, frequency=1.0)
    bl.pause(10)  # Oscillate for 10 seconds
finally:
    bl.nanostage.stop()
stop()

Stop all movement of the nanostage immediately.

property analog_calibration: PointXYZ

Analog calibration of the nanostage (V to um conversion) per axis

property motion_limits: LimitsXY

Motion limits of the nanostage

Examples

from bluelake import nanostage
limits = nanostage.motion_limits

# Print coordinates
print(limits.lower.x)
print(limits.upper.z)
property position: PointXYZ

Current absolute position (um) of the nanostage

Examples

from bluelake import nanostage
current_position = nanostage.position

# These two lines both print the y coordinate
print(current_position.y)
print(current_position[1])
class PointXYZ(x: Any, y: Any, z: Any)

A named tuple that represents per-axis quantities in xyz-space

Shutter control

Control of the shutters is provided through the Shutters class. An instance of it is available as:

import bluelake as bl

bl.shutters.clear(1, 2, delay_ms=100)
class Shutters(impl)
clear(*shutters, delay_ms=500)

Close and re-open the shutters for the given traps after a given delay.

Parameters:
delay_msint

For how long to close the shutter, in milliseconds.

Note: There is a built-in safeguard that will re-open the shutters after some time to prevent damage to the system. The shutters can therefore re-open before the provided delay has expired if they are open for too long. This is to prevent the shutters from remaining closed indefinitely.

*shuttersTuple[int]

The trap shutters to close and re-open. These match the shutters as seen in Bluelake.

Examples

To close shutters 1, 2, and 4 and open them again after 1000ms:

shutters.clear(1, 2, 4, delay_ms=1000)
close(*shutters)

Close the shutters for the given traps

Note: There is a built-in safeguard that will re-open the shutters after some time to prevent damage to the system. This is to prevent the shutters from remaining closed indefinitely.

Parameters:
*shuttersTuple[int]

The trap shutters to close. These match the shutters as seen in Bluelake.

Examples

To close shutters 1, 2, and 4:

shutters.close(1, 2, 4)
open(*shutters)

Open the shutters for the given traps

Parameters:
*shuttersTuple[int]

The trap shutters to open. These match the shutters as seen in Bluelake.

Examples

To open shutters 1, and 3:

shutters.open(1, 3)

Stage control

Navigation within the flow cell is done through bluelake.microstage, an instance of the Microstage class:

import bluelake as bl

bl.microstage.move_to('My favorite point')
class Microstage(stage_impl, profile_manager_impl)

Control interface for the microstage

move_by(dx=0, dy=0, speed=1)

Move the microstage relative to the current position.

The rest of the automation script is not executed until the microstage has finished the move.

Parameters:
dx, dyfloat

How much to move the stage, in millimeters. Any of the axes can be omitted, in which case the stage does not move in that direction.

speedfloat

Total speed of the move, in mm/s (i.e, magnitude of the velocity vector). If no speed is given, it will default to 1 mm/s.

move_to(waypoint=None, x=None, y=None, speed=None)

Move the microstage to the given coordinates.

The rest of the automation script is not executed until the microstage has finished the move.

Parameters:
waypointOptional[str]

Name of a previously stored waypoint. Should exactly match the name of the waypoint as entered in the Bluelake user interface.

x, yOptional[float]

Instead of giving a waypoint, this function can also be called with a set of destination coordinates, in millimeters. Any of the axes can be omitted, in which case the stage does not move in that direction.

speedfloat

Total speed of the move, in mm/s (i.e, magnitude of the velocity vector). If no speed is given, it will default to 1 mm/s.

start_moving_by(dx=0, dy=0, speed=1)

Start moving the microstage relative to the current position.

The function only sends the move command to the microstage. It does not wait for the move to finish.

Parameters:
dx, dyfloat

How much to move the stage, in millimeters. Any of the axes can be omitted, in which case the stage does not move in that direction.

speedfloat

Total speed of the move, in mm/s (i.e, magnitude of the velocity vector). If no speed is given, it will default to 1 mm/s.

start_moving_to(waypoint=None, x=None, y=None, speed=None)

Start moving the microstage to the absolute position in space.

The function only sends the move command to the microstage. It does not wait for the move to finish.

Parameters:
waypointOptional[str]

Name of a previously stored waypoint. Should exactly match the name of the waypoint as entered in the Bluelake user interface.

x, yOptional[float]

Instead of giving a waypoint, this function can also be called with a set of destination coordinates, in millimeters. Any of the axes can be omitted, in which case the stage does not move in that direction.

speedfloat

Total speed of the move, in mm/s (i.e, magnitude of the velocity vector). If no speed is given, it will default to 1 mm/s.

stop()

Stop the current move of the microstage.

property is_homed: bool

Is the microstage homed

property is_moving: bool

Is the microstage currently moving.

property max_move_speed: float

Maximum configured movement speed

property position: Tuple[float, float]

Current absolute position of the microstage in mm.

Fluidics control

bluelake.fluidics can be used to control the microfluidics channel valves and pressure:

import bluelake as bl

bl.fluidics.open(1, 2, 3, 6)
bl.fluidics.increase_pressure()
bl.fluidics.stop_flow()
class Fluidics(pressure_box_impl, valves_impl)

Microfluidics control

close(*valves)

Close the valves with the given numbers.

Parameters:
*valvesTuple[int]

The numbers of the valves to open. These match the numbers as seen in the Bluelake user interface. The first valve has number 1.

Examples

To close valves 1, 2, 3, and 6:

fluidics.close(1, 2, 3, 6)
decrease_pressure()

Decrease the pressure by one step.

Acts just like the “-” button in the user interface.

increase_pressure()

Increase the pressure by one step.

Acts just like the “+” button in the user interface.

open(*valves)

Open the valves with the given numbers.

Parameters:
*valvesTuple[int]

The numbers of the valves to open. These match the numbers as seen in the Bluelake user interface. The first valve has number 1.

Examples

To open valves 1, 2, 3, and 6:

fluidics.open(1, 2, 3, 6)
set_pressure(target_bar, deviation_bar=0.05, timeout_seconds=20, settle_time_seconds=0.5)

Set the pressure to target_bar with a tolerance of deviation_bar

The function waits until the target has been reached. The behavior is nearly identical to the graphical user interface with the exception that target_bar=0 is implemented in terms of start_venting() to speed things up.

Parameters:
target_barfloat

The target pressure, in bar. Maximum is 3 bar.

deviation_barfloat

The allowed deviation from the target. Setting this value too low will cause the pressure box to adjust the pressure too frequently which could end up negatively affecting the experiment as via pressure waves that can be seen in the force measurement. The default value is meant to provide a balance between target accuracy and pressure stability.

timeout_secondsfloat
settle_time_seconds: float

Amount of time required for the pressure to stay within the required deviation before returning.

start_flush(target_bar)

Open all valves and set the pressure to target_bar with a tolerance of 0.05 bar

Calling this method is equivalent to calling fluidics.open(1, 2, 3, 4, 5, 6) followed by fluidics.set_pressure(target_bar).

start_venting()

Start venting the pressure.

This function returns immediately, but it may take several seconds for the pressure box to completely vent.

stop_flow()

Close all valves and vent the pressure

Calling this method is equivalent to calling fluidics.close(1, 2, 3, 4, 5, 6) followed by fluidics.start_venting().

property has_flow

Are any of the valves open?

property is_pressurized: bool

Is the current pressure lower than the vent pressure.

property pressure: float

The current pressure, in bar.

Power control

Power settings can be changed through the following objects that are defined in the bluelake module:

import bluelake as bl

# Trapping laser
print(bl.power.trapping_laser)  # power in %
bl.power.trapping_laser = 50    # set to 50% power

# Power modulation (availability varies per system)
print(bl.power.overall_trapping_power)
print(bl.power.qtrap_split)
print(bl.power.trap1_split)

# Bright-field LED
bl.power.bright_field_led = 50
print(bl.power.bright_field_led)

Camera

class Camera(recorder_impl, camera_impl, backend_impl, camera_name)

Represents one of the microscope cameras

Instances of this class are available by default as brightfield, moon, and zfinder:

import bluelake as bl

bl.brightfield.start_recording("D:\\", seconds=15)
bl.moon.take_snapshot("D:\\moon.tiff")
bl.zfinder.start_recording("D:\\folder", frames=150)

Depending on the hardware configuration of your C-Trap, you may also have irm and widefield.

pull_snapshot() Image

Record a single frame and return it as an Image

set_sensor_settings(framerate_hz=None, exposure_time_ms=None, roi=None, gain_percent=None, pixel_clock_mhz=None)

Change camera sensor settings

For example:

bl.brightfield.set_sensor_settings(framerate_hz=100)  # only changes one setting
bl.brightfield.set_sensor_settings(framerate_hz=60, exposure_time_ms=1.2)  # changes two
bl.brightfield.set_sensor_settings(exposure_time_ms=2.5)  # keeps previous framerate

print(bl.brightfield.sensor.settings)  # see the applied settings

Unspecified arguments will remain unchanged. However, do note that not all combinations of values are possible. For example, it’s impossible to support a framerate of 100 Hz (10 ms frametime) with an exposure of 20 ms (larger than frametime). If an impossible combination is given, the settings will automatically be scaled to the closest possible values.

Internally, the settings are applied in the following order:

  1. Gain (on camera’s that have it, see Sensor.Settings.gain_percent)

  2. ROI

  3. Pixel clock (on camera’s that have it, see Sensor.Settings.pixel_clock_mhz)

  4. Exposure time

  5. Framerate

This applies to synchronized cameras (brightfield, widefield/TIRF, IRM). On free-running diagnostic cameras (moon, z-finder) the framerate is set before the exposure time. This order defines how the camera will resolve conflicting values: the setting nearer the top take priority and influence the bounds of the following settings.

Additionally, most values cannot be set with infinite precision. For example, calling camera.set_sensor_settings(framerate_hz=100) may actually set camera.sensor.settings.framerate_hz == 99.98.

If you need to be sure of the applied settings, do check the returned Sensor.settings after calling .set_sensor_settings():

settings = bl.brightfield.set_sensor_settings(framerate_hz=100)
print(settings.framerate_hz)  # prints 99.98, for example

# Alternatively, check the settings without changing them
print(bl.brightfield.sensor.settings.framerate_hz)
Parameters:
framerate_hzOptional[float]

The number of frames per second that are being acquired

exposure_time_msOptional[float]

The amount of time within a frame that the sensor is exposed to light (in milliseconds)

roiOptional[Region]

The ROI (region of interest) in pixels

gain_percentOptional[float]

The amplification of the sensor signal: see Sensor.Settings.gain_percent

pixel_clock_mhzOptional[float]

See Sensor.Settings.pixel_clock_mhz

Returns:
Sensor.Settings

The actual applied settings after they are constrained to possible values.

start_recording(export_path, frames=None, seconds=None)

Start recording from this camera.

When either frames or seconds is specified, the recording stops after the specified number of frames or seconds was recorded. Otherwise, it will continue until stop_recording() is called.

Blocking until the recording is done can be accomplished by calling .wait() on the returned object:

brightfield.start_recording("D:\\", seconds=2).wait()

You can also do something else between starting the recording and waiting for it to finish:

recording = brightfield.start_recording("D:\\", frames=460)
... # do other things
recording.wait()
Parameters:
export_pathstr

Either a directory or a full file path. If it’s a directory (e.g. D:\\folder) the recording will be saved there with an auto-generated name (timestamp + camera name). If it’s a full file path (e.g. D:\\folder\\experiment.tiff) that exact filename will be used. If a file with that name already exists, it will not be overwritten. A file with a sequential suffix will be created (e.g. experiment 2.tiff).

framesOptional[int]

The number of frames to record. Cannot be used at the same time as seconds.

secondsOptional[float]

The time in seconds for which to record. Cannot be used at the same time as frames.

stop_recording()

Stop any recording that may be in progress.

take_snapshot(export_path)

Record a single frame.

This function returns only after the snapshot has been saved. It’s equivalent to:

camera.start_recording(export_path, frames=1).wait()
Parameters:
export_pathstr

Same rules as for Camera.start_recording().

property is_recording: bool

Is the camera currently recording?

property pixel_size_um: Size

The width and height of a single pixel in micrometers

property sensor: Sensor

Information about the current state of the camera sensor – see Sensor

property tracker: Tracker

Information about bead tracking – see Tracker

class Sensor(camera_impl, pixel_size_um)

The current state of the camera sensor returned by Camera.sensor

Attributes:
settingsSettings
limitsLimits
class Limits(impl, pixel_size_um)

The limits of the values that can be given to Camera.set_sensor_settings()

Note that the limits change depending on the current settings. E.g. increasing the exposure time will reduce the upper bound of the framerate.

Attributes:
framerate_hz, exposure_time_ms, gain_percent, pixel_clock_mhzBounds

Value bounds the corresponding fields in Settings

sensor_sizeSize

The width and height of the camera sensor in pixels, i.e. the max size of the ROI

sensor_size_umSize

Like .sensor_size but in micrometers

class Settings(impl, pixel_size_um)
Attributes:
framerate_hzfloat

The number of frames per second that are being acquired

exposure_time_msfloat

The amount of time within a frame that the sensor is exposed to light (in milliseconds)

roiRegion

The ROI (region of interest) in pixels

roi_umRegion

Like .roi but in micrometers

gain_percentOptional[float]

Amplification of the signal from the camera sensor in percent (0 to 100%). On cameras that manage it automatically (widefield/TIRF), this field will be None.

pixel_clock_mhzOptional[float]

The speed in MHz that the pixel data is read out from the sensor. A higher pixel clock allows higher framerates. Only some cameras require this setting to be managed manually by the user: bright-field, moon, z-finder. On cameras that manage it automatically, this field will be None: IRM, widefield/TIRF.

class Tracker(impl)

Bead tracking functionality for cameras.

property enabled: bool

Is bead tracking enabled?

property mode: str

Specified modes of bead tracking. Available modes are:

Modes when enabled:
  • “dual” (default mode)

Q-Trap-only modes:
  • “quad_x”

  • “quad_plus”

  • “quad_horizontal”

  • “quad_vertical”

Mode when disabled:
  • “disabled” (default mode)

property roi: Region

The region of the frame used to perform bead tracking.

Perform bead tracking on a sub-region of the frame can significantly improve performance of the tracking.

property templates: list[Template]

Bead tracking templates – see Template

property threshold: float

The template matching confidence threshold for bead tracking, in percent.

class Template(index, impl)

Information about a bead tracking template

update()

Updates the bead tracking template in-place for the given index.

property bead_diameter: float

Bead diameter (um) for this bead template

property image: Image

Template image.

property rect: Region

The region of the frame used as a template under the given index.

class Background(background_impl, recorder_impl)

Image preprocessing functionality for cameras.

For a given camera, e.g. Brightfield::

import bluelake as bl

bl.brightfield._background.set_subtraction_settings(frames=2, frames_to_average=4) bl.brightfield._background.acquire() bl.brightfield._background.enable_subtraction(True) bl.brightfield.start_recording(“D:", frames=2).wait() … bl.brightfield._background.enable_subtraction(False)

acquire()

Acquire the background image of the current camera

enable_subtraction(set_enabled)

Enable/Disable background subtraction for subsequent recordings.

Parameters:
set_enabled: bool

Determine whether the subsequent recordings will perform background subtraction.

set_subtraction_settings(frames=None, radius=None, frames_to_average=None)

Set desired background image settings

Parameters:
frames: int

The number of frames from which the background image is created.

radius: float

The radius used to evaluate the positions that the nanostage can move to during background image acquisition.

frames_to_average: int

The minimum number of frames from which a background image can be obtained, e.g. frames_to_average = 10 means an image will only be produced after the first 10 frames have been obtained.

property has_background: bool

Has the background image been acquired?

property is_subtraction_enabled: bool

Is subtraction enabled?

class Size(width: float, height: float)

A size described by ‘width’ and ‘height’

class Region(x: float, y: float, width: float, height: float)

A region described by an offset of ‘x’, ‘y’ and a size of ‘width’, ‘height’

class Bounds(lower: float, upper: float)

The lower and upper bounds of possible values

class Image(matrix: numpy.ndarray, timestamp: int, timedelta: int)

Pixel matrix, timestamp (since epoch), and timedelta nanoseconds from last frame

Timeline

Access to data from the timeline is provided through the bluelake.timeline object, an instance of the Timeline class described below.

Index timeline to gain access to individual channels:

import bluelake as bl

force_channel = bl.timeline["Force HF"]["Force 1x"]

The first index is the name of a channel group; the second index is the name of a channel within the group. Group and channel names match the ones displayed in the Bluelake user interface.

The above code snippet sets the force_channel variable to an instance of the Channel class described below. We can now, for instance, check the latest force value that has been measured using:

print(force_channel.latest_value)
class Timeline(impl)

Access to data from the timeline

__getitem__(s)

Return a Group from the timeline

add_note(name, text, export=False, filepath='')

Creates a Note item on the timeline

Parameters:
namestr

Name of the note

textOptional[str]

Content of the note

exportbool

If True, the marker will also be exported immediately.

filepathstr

The exact path where the exported file should be created. If empty, the path will be auto-generated just like exporting in the UI.

export(filepath, start, stop, everything=False)

Export channel data to HDF5

By default, only the channels which are selected in the Bluelake user interface will be exported.

Parameters:
filepathstr

Path to an HDF5 file where the data should be exported. The file is created, or overwritten if it already exists.

start, stopint

The time range to export (64-bit integer timestamps, in nanoseconds; see also start_time and current_time). stop cannot be bigger than current_time.

everythingOptional[bool]

Off by default. If enabled, all of the available timeline channels will be exported, regardless of the selection in Bluelake’s user interface.

keys()

List of available groups in the timeline

mark_begin(name)

Start a marked section on the timeline

Be sure to pair each call to mark_begin with a call to mark_end.

Parameters:
nameOptional[str]

Name of the marked section

mark_end(export=False, filepath='', channels=[])

End a marked section on the timeline.

See also mark_begin.

Parameters:
exportbool

If True, the marker will also be exported immediately.

filepathstr

The exact path where the exported file should be created. If empty, the path will be auto-generated just like exporting in the UI.

channelslist

List of the channels to be exported (only applicable if export is True). If empty, the channels selected in the user interface will be exported.

Returns:
Tuple[int, int]

The (start, stop) timestamps of the created marker.

Raises:
RuntimeError if a marker is not in progress (i.e. no previous matching mark_begin call)
RuntimeError if one of more selected channels are not available on the timeline

Examples

# End the marker without exporting
timeline.mark_begin("marker 1")
...
timeline.mark_end()

# End the marker and export it with an auto-generated name
timeline.mark_begin("marker 2")
...
timeline.mark_end(export=True)

# End the marker and export with a specific name
timeline.mark_begin("marker 3")
...
timeline.mark_end(export=True, filepath="D:/path/to/folder/file_name.h5")

# Select the timeline channels to export
timeline.mark_begin("marker 4")
...
timeline.mark_end(export=True, channels=["Force LF/Trap 1", "Force LF/Trap 2"])

# In all cases `.mark_end()` returns a (start, stop) pair of timestamps
timeline.mark_begin("marker 5")
...
start, stop = timeline.mark_end()

# Make sure a marker gets an end, even if the script is aborted
timeline.mark_begin("marker 6")
try:
  # ... do something else
  pause(2.0)
finally:
  # This always ends the marker, even if the script is aborted with
  # the "Stop" button
  timeline.mark_end()
property current_time

The time at which the latest timeline data was measured

A 64-bit integer timestamp with nanosecond resolution.

property start_time

The time at which the current session was started

A 64-bit integer timestamp with nanosecond resolution.

class Group

A group of timeline channels

__getitem__(item)

Return a Channel from the timeline

keys()

List of available channels within the group

class Channel

An individual timeline channel

__getitem__(item)

Return a slice of data

property group_name

Name of the containing channel group

property latest_value

The latest available data value in this channel

property spec

Detailed Spec of the timeline channel’s properties, units, etc.

class Spec

Detailed description of a timeline channel

property sample_rate

Sample rate of the channel’s data, in hertz

property unit

Units in which the channel’s values are measured

Confocal

For C-Trap systems that feature a confocal scanner, a bluelake.confocal object is available. Through this instance of the Scanner class described below, simple automation of confocal scans can be done.

class Scanner(impl)
abort_scan()

Abort any confocal scan that is currently in progress

start_scan(preset_name=None)

Start a confocal scan, using the current scan settings or based on a preset

If a scan is already in progress an exception is raised. If no preset is given, start a new confocal scan, using the settings from Bluelake’s user interface. Otherwise, start the named preset.

Parameters:
preset_nameOptional[str]

Name of a confocal scan preset, as previously created in the Bluelake user interface, if the preset is not available an exception is raised.

wait(*, progress: int | None = None)

Wait until the current confocal scan finishes or reaches a certain percentage progress

property is_continuous

Is the selected preset a continuous scan?

property is_scanning

Is the scanner currently scanning?

property progress

Percentage of the current scan already completed. On continuous scans progress is always zero.

Excitation

For systems that feature an excitation module, a bluelake.excitation object is available which allows control over lasers of various wavelengths:

import bluelake as bl

# To turn on a laser
bl.excitation.red_laser.set_powered_on(True)

# To turn on a laser and wait for it to warm up
bl.excitation.red_laser.set_powered_on(True, wait_for_warmup=True)

# To set a power level
bl.excitation.red_laser.power_level = 75

# To manipulate a laser shutter
bl.excitation.red_laser.shutter.open()
bl.excitation.red_laser.shutter.close()

# To manipulate a laser shutter without waiting for confirmation that shutter is in desired state
bl.excitation.red_laser.shutter.open(wait_for_confirmation=False)
bl.excitation.red_laser.shutter.close(wait_for_confirmation=False)

# Depending on your C-Trap's build configuration, the following excitation lasers can as well be accessed:
bl.excitation.green_laser
bl.excitation.blue_laser
bl.excitation.violet_laser
class ExcitationLaser(impl, config)
Attributes:
shutterShutter
set_powered_on(value, wait_for_warmup=False)

Power the laser on or off.

Parameters:
valuebool

To power on the laser pass True, to power off False

wait_for_warmupbool

Pass True to have this function block until the laser has warmed up.

property has_interlock_tripped: bool

Opening the C-Trap lid trips the laser interlock and prevents it from powering on

property is_emission_enabled: bool

Is light being emitted by the laser?

This checks sufficient conditions for the laser to emit (power level > 0%, not warming up, no interlock tripped), but closed shutters could still prevent the light from reaching the target even when is_emission_enabled is True.

property is_powered_on: bool

Is the laser powered on?

property is_warming_up: bool

Is the laser is still warming up?

property power_level: float

The power level of the laser in percent.

class ExcitationLaser.Shutter(impl, name)
close(wait_for_confirmation=True)

Close the laser shutter to stop emission.

Parameters:
wait_for_confirmationbool

It takes the shutter a few hundred milliseconds to open/close. Pass False to make this function return immediately when the signal is sent but without waiting for confirmation that the shutter has changed to the desired state.

open(wait_for_confirmation=True)

Open the laser shutter to allow emission.

Parameters:
wait_for_confirmationbool

It takes the shutter a few hundred milliseconds to open/close. Pass False to make this function return immediately when the signal is sent but without waiting for confirmation that the shutter has changed to the desired state.

property is_open: bool

Is the laser shutter currently open?

Focus Lock

For systems that have focus lock, a bluelake.focus_lock object is available, which allows start/stopping it and checking its state.

class FocusLock(impl)

Control interface for Focus Lock

start()

Starts the focus lock. The current Z position will be the target.

stop()

Stops the focus lock.

property enabled

Is the focus lock enabled?

Force feedback

Force feedback is responsible for keeping the selected force stable at certain target value by using a PID loop to correct the position of steering device. Trap 1 should be used to achieve the best performance:

import bluelake as bl

try:
    bl.force_feedback.set_device("1")
    bl.force_feedback.set_detector("Trap 2") # Force detector
    bl.force_feedback.set_target(30)
    bl.force_feedback.enabled = True
    bl.pause(1)
finally:
    bl.force_feedback.enabled = False
class ForceFeedback(impl)

Force feedback interface

set_angle(angle)

Set the angle of the force feedback.

Angle has different meaning depending on the selected mode: In set_lock_motion_angle, it defines the direction in which the controlled device can move. In set_lock_force_angle, it defines the direction of the resulting force vector.

Parameters:
anglefloat

Angle between ±180° with 0/180° being horizontal and ±90° vertical.

set_detector(detector)

Set which force detector to use a the signal to feedback on.

Parameters:
detectorstr

Name of the force detector (e.g “Trap 1”, “Trap 2”).

Raises

ValueError if the detector does not exist.

set_device(device)

Set the device to be moved to execute the force feedback.

Parameters:
devicestr

Name of the device to move (e.g. “Nanostage” or “1” for Trap 1).

Raises

ValueError if the device does not exist.

set_frequency(frequency)

Set the frequency (Hz) of the force feedback loop.

The frequency is automatically adjusted to match the closest multiple of the force acquisition block size (ms). The minimum frequency is 1/block size

Parameters:
frequencyfloat

Requested frequency in Hz.

Returns:
actual_frequencyfloat

Actual frequency that the force feedback will run at.

Raises:
ValueError if the frequency is zero or negative.
set_lock_motion_angle()

Set the force feedback loop in locked motion angle mode.

In this mode the corrective movements are calculated conjointly for the X and Y axis. This means that the trap will only move over the line at the angle set by set_angle to keep a constant force on this axis, which prioritizes a constant angle between two traps with all corrective movements exerted over a fixed line.

set_lock_motion_force()

Set the force feedback loop in locked force angle mode.

In this the corrective movements are calculated separately for the X and Y axis. This means that in this mode the trap can move freely to keep a constant force vector of the given target source at the angle set by set_angle with respect to the target trap, which prioritizes a constant force between traps in a specific direction.

set_pid_settings(kp, ki, kd, max_step, reversed)

Set the parameters for the PID loop

Parameters:
kpfloat

The proportional gain in nm / pN. It determines *how much* the difference between the set target force and the measured force affects the corrective force.

kifloat

The integral gain in (nm / pN) / s. It determines how much the response increases *over time* when the corrective movements do not bring the target force correctly to its target.

kdfloat

The derivative gain in (nm / pN) * s. It determines *how strongly* a change in difference between the set target force and the measured force affects the corrective force.

max_stepfloat

Max step size (nm): The maximum displacement in nm exerted in a single corrective step * In Lock angle of: Force this means the maximum displacement in one step on both the X and Y axis. * In Lock angle of: Distance this means the maximum displacement in one step over the line described by Direction (deg).

reversed

Reverse motion Enabling this setting reverses the output of the PID loop.

set_target(target)

Set the force feedback setpoint in pN.

Parameters:
targetfloat

Force setpoint in pN for the force feedback loop.

property enabled: bool

Indicates the state of the force feedback.

Raises:
RuntimeError

If force feedback is already enabled.

Examples

force_feedback.enabled = True
...
force_feedback.enabled = False

Digital Outputs

Interface to control digital output lines of the C-Trap data acquisition (DAQ) platform. Useful for integration with other instruments:

import bluelake as bl

print(bl.daq.digital_output.keys())  # list all the available digital outputs

do = bl.daq.digital_outputs["digital_output_name"]
do.set_high()
bl.pause(1)  # set the output high for one second
do.set_low()

Warning

Please contact LUMICKS customer support before using this feature to make sure that the selected digital output is available and does not interfere with the instrument’s normal operation.

class DAQ(impl)
property digital_outputs: dict

The available digital outputs

class DO(daq, channel)
set_high()

Set this digital output to high.

It takes at least 400ms for the value to change due to the DAQ scheduling delay.

Returns:
Timestamp

DAQ timestamp of when the value will be set to high.

set_low()

Set this digital output to low.

It takes at least 400ms for the value to change due to the DAQ scheduling delay.

Returns:
Timestamp

DAQ timestamp of when the channel will be set to low.

Active Trap Stabilization (ATS)

Interface to control the ATS feature (if available on the system).

class ATS(impl)

Active Trap Stabilization (ATS) interface

property enabled: bool

Indicates the state of ATS.

Examples

ats.enabled = True
...
ats.enabled = False

Miscellaneous

pause(secs, delta_secs=0.1)

Delay execution for a given number of seconds

The argument may be a floating point number for subsecond precision.

reset_force()

Set forces to zero. Calibrate force offsets for all channels to zero force.

get_force_calibration()

Return the current force calibration for each force channel

The available parameters match the ones available in the force calibration UI.

Examples

cal = bluelake.get_force_calibration()
response = cal["Force 1x"]["Response (pN/V)"]
offset = cal["Force 1x"]["Offset (pN)"]
stiffness = cal["Force 1x"]["kappa (pN/nm)"]

print(cal)  # see available force channels and parameters for each channel
print(cal["Force 1x"])  # see all parameters just for this channel
class PiezoTracker(impl)
property enabled: bool

Indicates the state of the piezo tracking

Raises:
RuntimeError

If piezo tracking is already enabled

Examples

piezo_tracker.enabled = True
...
piezo_tracker.enabled = False
class Calibration(quadratic_factor: float, factor: float, offset: float)

Represents a quadratic calibration