Skip to content

Commit e09e853

Browse files
authored
add make_space param to position_channels_in_y_direction (#369)
1 parent 5fdc7a9 commit e09e853

File tree

2 files changed

+45
-37
lines changed

2 files changed

+45
-37
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
147147
- `with_trash96` on `HamiltonSTARDeck` so there is more fine grained control (https://github.com/PyLabRobot/pylabrobot/pull/347)
148148
- add `STAR.{get_channels_z_positions, position_channels_in_z_direction}` (https://github.com/PyLabRobot/pylabrobot/pull/356)
149149
- `STAR.step_off_foil` (https://github.com/PyLabRobot/pylabrobot/pull/357)
150+
- `make_space` param to `position_channels_in_y_direction` (https://github.com/PyLabRobot/pylabrobot/pull/369)
150151

151152
### Deprecated
152153

pylabrobot/liquid_handling/backends/hamilton/STAR.py

Lines changed: 44 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -7511,12 +7511,17 @@ async def get_channels_y_positions(self) -> Dict[int, float]:
75117511

75127512
return {channel_idx: y for channel_idx, y in enumerate(y_positions)}
75137513

7514-
async def position_channels_in_y_direction(self, ys: Dict[int, float]):
7514+
async def position_channels_in_y_direction(self, ys: Dict[int, float], make_space=True):
75157515
"""position all channels simultaneously in the Y direction.
75167516
75177517
Args:
75187518
ys: A dictionary mapping channel index to the desired Y position in mm. The channel index is
7519-
0-indexed from the back.
7519+
0-indexed from the back.
7520+
make_space: If True, the channels will be moved to ensure they are at least 9mm apart and in
7521+
descending order, after the channels in `ys` have been put at the desired locations. Note
7522+
that an error may still be raised, if there is insufficient space to move the channels or
7523+
if the requested locations are not valid. Set this to False if you wan to aviod inadvertently
7524+
moving other channels.
75207525
"""
75217526

75227527
# check that the locations of channels after the move will be at least 9mm apart, and in
@@ -7525,6 +7530,37 @@ async def position_channels_in_y_direction(self, ys: Dict[int, float]):
75257530

75267531
for channel_idx, y in ys.items():
75277532
channel_locations[channel_idx] = y
7533+
7534+
if make_space:
7535+
# For the channels to the back of `back_channel`, make sure the space between them is
7536+
# >=9mm. We start with the channel closest to `back_channel`, and make sure the
7537+
# channel behind it is at least 9mm, updating if needed. Iterating from the front (closest
7538+
# to `back_channel`) to the back (channel 0), all channels are put at the correct location.
7539+
# This order matters because the channel in front of any channel may have been moved in the
7540+
# previous iteration.
7541+
# Note that if a channel is already spaced at >=9mm, it is not moved.
7542+
use_channels = list(ys.keys())
7543+
back_channel = min(use_channels)
7544+
for channel_idx in range(back_channel, 0, -1):
7545+
if (channel_locations[channel_idx - 1] - channel_locations[channel_idx]) < 9:
7546+
channel_locations[channel_idx - 1] = channel_locations[channel_idx] + 9
7547+
7548+
# Similarly for the channels to the front of `front_channel`, make sure they are all
7549+
# spaced >=9mm apart. This time, we iterate from back (closest to `front_channel`)
7550+
# to the front (lh.backend.num_channels - 1), and put each channel >=9mm before the
7551+
# one behind it.
7552+
front_channel = max(use_channels)
7553+
for channel_idx in range(front_channel, self.num_channels - 1):
7554+
if (channel_locations[channel_idx] - channel_locations[channel_idx + 1]) < 9:
7555+
channel_locations[channel_idx + 1] = channel_locations[channel_idx] - 9
7556+
7557+
# Quick checks before movement.
7558+
if channel_locations[0] > 650:
7559+
raise ValueError("Channel 0 would hit the back of the robot")
7560+
7561+
if channel_locations[self.num_channels - 1] < 6:
7562+
raise ValueError("Channel N would hit the front of the robot")
7563+
75287564
if not all(
75297565
channel_locations[i] - channel_locations[i + 1] >= 9
75307566
for i in range(len(channel_locations) - 1)
@@ -7595,43 +7631,14 @@ async def step_off_foil(
75957631
back_location = well.get_absolute_location("c", "b", "t")
75967632
front_location = well.get_absolute_location("c", "f", "t")
75977633

7598-
# The y positions may cause a crash if the channel in front of `front_channel`
7599-
# or to the back of `back_channel` are still within the space that the front&back
7600-
# channel will span above the plate. To check, we request the current y locations
7601-
# of all channels, and update it with the locations we computed above. Then,
7602-
# we correct any potential error.
7603-
channel_locations = await self.get_channels_y_positions()
7604-
channel_locations[front_channel] = front_location.y + move_inwards
7605-
channel_locations[back_channel] = back_location.y + move_inwards
7606-
7607-
# For the channels to the back of `back_channel`, make sure the space between them is
7608-
# >=9mm. We start with the channel closest to `back_channel`, and make sure the
7609-
# channel behind it is at least 9mm, updating if needed. Iterating from the front (closest
7610-
# to `back_channel`) to the back (channel 0), all channels are put at the correct location.
7611-
# This order matters because the channel in front of any channel may have been moved in the
7612-
# previous iteration.
7613-
# Note that if a channel is already spaced at >=9mm, it is not moved.
7614-
for channel_idx in range(back_channel, 0, -1):
7615-
if (channel_locations[channel_idx - 1] - channel_locations[channel_idx]) < 9:
7616-
channel_locations[channel_idx - 1] = channel_locations[channel_idx] + 9
7617-
7618-
# Similarly for the channels to the front of `front_channel`, make sure they are all
7619-
# spaced >=9mm apart. This time, we iterate from back (closest to `front_channel`)
7620-
# to the front (lh.backend.num_channels - 1), and put each channel >=9mm before the
7621-
# one behind it.
7622-
for channel_idx in range(front_channel, self.num_channels - 1):
7623-
if (channel_locations[channel_idx] - channel_locations[channel_idx + 1]) < 9:
7624-
channel_locations[channel_idx + 1] = channel_locations[channel_idx] - 9
7625-
7626-
# Quick checks before movement.
7627-
assert channel_locations[0] <= 650, "Channel 0 would hit the back of the robot"
7628-
assert (
7629-
channel_locations[self.num_channels - 1] >= 6
7630-
), "Channel N would hit the front of the robot"
7631-
76327634
try:
76337635
# Then move all channels in the y-space simultaneously.
7634-
await self.position_channels_in_y_direction(channel_locations)
7636+
await self.position_channels_in_y_direction(
7637+
{
7638+
front_channel: front_location.y + move_inwards,
7639+
back_channel: back_location.y - move_inwards,
7640+
}
7641+
)
76357642

76367643
await self.move_channel_z(front_channel, front_location.z)
76377644
await self.move_channel_z(back_channel, back_location.z)

0 commit comments

Comments
 (0)