diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000000..26d33521af
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000000..930c017364
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000000..105ce2da2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000000..addea05e43
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/pylabrobot.iml b/.idea/pylabrobot.iml
new file mode 100644
index 0000000000..ec63674cd7
--- /dev/null
+++ b/.idea/pylabrobot.iml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000000..35eb1ddfbb
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pylabrobot/liquid_handling/backends/tecan/EVO_backend.py b/pylabrobot/liquid_handling/backends/tecan/EVO_backend.py
index ecc8d29c84..03859bb9ac 100644
--- a/pylabrobot/liquid_handling/backends/tecan/EVO_backend.py
+++ b/pylabrobot/liquid_handling/backends/tecan/EVO_backend.py
@@ -10,6 +10,7 @@
Union,
)
+from pylabrobot.liquid_handling.utils import get_tight_single_resource_liquid_op_offsets
from pylabrobot.io.usb import USB
from pylabrobot.liquid_handling.backends.backend import (
LiquidHandlerBackend,
@@ -288,14 +289,20 @@ async def setup(self):
# Initialize plungers. Assumes wash station assigned at rail 1.
await self.liha.set_z_travel_height([self._z_range] * self.num_channels)
- await self.liha.position_absolute_all_axis(45, 1031, 90, [1200] * self.num_channels)
+ wash = self.deck.get_resource("wash_waste")
+ wash_offsets = get_tight_single_resource_liquid_op_offsets(wash, self.num_channels)
+ location = wash.get_absolute_location() + wash.center() + wash_offsets[0]
+ location.x = int(location.x * 10)
+ location.y = int((352 - location.y) * 10)
+ location.z = int(wash.get_size_z() * 10)
+ await self.liha.position_absolute_all_axis(location.x, location.y,90, [location.z] * self.num_channels)
await self.liha.initialize_plunger(self._bin_use_channels(list(range(self.num_channels))))
await self.liha.position_valve_logical([1] * self.num_channels)
await self.liha.move_plunger_relative([100] * self.num_channels)
await self.liha.position_valve_logical([0] * self.num_channels)
await self.liha.set_end_speed_plunger([1800] * self.num_channels)
await self.liha.move_plunger_relative([-100] * self.num_channels)
- await self.liha.position_absolute_all_axis(45, 1031, 90, [self._z_range] * self.num_channels)
+ await self.liha.position_absolute_all_axis(location.x, location.y, 90, [self._z_range] * self.num_channels)
async def setup_arm(self, module):
try:
@@ -459,7 +466,7 @@ async def dispense(self, ops: List[SingleChannelDispense], use_channels: List[in
x, _ = self._first_valid(x_positions)
y, yi = self._first_valid(y_positions)
assert x is not None and y is not None
- await self.liha.set_z_travel_height(z if z else self._z_range for z in z_positions["travel"])
+ await self.liha.set_z_travel_height([z if z else self._z_range for z in z_positions["travel"]])
await self.liha.position_absolute_all_axis(
x,
y - yi * ys,
@@ -487,6 +494,7 @@ async def pick_up_tips(self, ops: List[Pickup], use_channels: List[int]):
# Get positions including offsets
x_positions, y_positions, z_positions = self._liha_positions(ops, use_channels)
+ z_positions["start"] = [int(op.resource.parent.z_start) for op in ops if op.resource.parent.z_start] # directly get z_position from z_start to avoid tip length issue?
# move channels
ys = int(ops[0].resource.get_absolute_size_y() * 10)
@@ -678,8 +686,8 @@ def get_z_position(z, z_off, tip_length):
for i, (op, channel) in enumerate(zip(ops, use_channels)):
location = ops[i].resource.get_absolute_location() + op.resource.center()
- x_positions[channel] = int((location.x - 100 + op.offset.x) * 10)
- y_positions[channel] = int((346.5 - location.y + op.offset.y) * 10) # TODO: verify
+ x_positions[channel] = int((location.x + op.offset.x) * 10)
+ y_positions[channel] = int((352 - (location.y + op.offset.y)) * 10) # TODO: verify
par = ops[i].resource.parent
if not isinstance(par, (TecanPlate, TecanTipRack)):
@@ -692,12 +700,15 @@ def get_z_position(z, z_off, tip_length):
z_positions["start"][channel] = get_z_position(
par.z_start, par.get_absolute_location().z + op.offset.z, tip_length
)
+ # container.get_absolute_position(z="cavity_bottom") + lld_search_height
z_positions["dispense"][channel] = get_z_position(
par.z_dispense, par.get_absolute_location().z + op.offset.z, tip_length
)
+ # container.get_absolute_position(z="cavity_bottom") + liquid_height
z_positions["max"][channel] = get_z_position(
par.z_max, par.get_absolute_location().z + op.offset.z, tip_length
)
+ # container.get_absolute_position(z="cavity_bottom")
return x_positions, y_positions, z_positions
diff --git a/pylabrobot/resources/tecan/plate_carriers.py b/pylabrobot/resources/tecan/plate_carriers.py
index 4b7c1266ad..9db28d478a 100644
--- a/pylabrobot/resources/tecan/plate_carriers.py
+++ b/pylabrobot/resources/tecan/plate_carriers.py
@@ -554,7 +554,7 @@ def MP_4Pos_flat(name: str) -> TecanPlateCarrier:
size_y=380.0,
size_z=6.9,
off_x=11.0,
- off_y=51.0,
+ off_y=23.0,
roma_x=1835,
roma_y=388,
roma_z_safe=946,
diff --git a/pylabrobot/resources/tecan/tecan_decks.py b/pylabrobot/resources/tecan/tecan_decks.py
index 656314bba8..114555ecaa 100644
--- a/pylabrobot/resources/tecan/tecan_decks.py
+++ b/pylabrobot/resources/tecan/tecan_decks.py
@@ -135,15 +135,15 @@ def _coordinate_for_rails(self, rails: int, resource: Resource):
raise ValueError(f"Resource {resource} is not a Tecan resource.")
return Coordinate(
- (rails - 1) * _RAILS_WIDTH - resource.off_x + 100,
- resource.off_y + 345 - resource.get_absolute_size_y(),
+ 130 + (rails - 1) * _RAILS_WIDTH - resource.off_x,
+ resource.off_y,
0,
) # TODO: verify
def _rails_for_x_coordinate(self, x: float):
"""Convert an x coordinate to a rail identifier."""
- return round((x + _RAILS_WIDTH - 101) / _RAILS_WIDTH) + 1
+ return round((x + _RAILS_WIDTH - 130) / _RAILS_WIDTH) + 1
def summary(self) -> str:
"""Return a summary of the deck."""
diff --git a/pylabrobot/resources/tecan/tip_carriers.py b/pylabrobot/resources/tecan/tip_carriers.py
index 3c3a1c1fe4..971b9df20c 100644
--- a/pylabrobot/resources/tecan/tip_carriers.py
+++ b/pylabrobot/resources/tecan/tip_carriers.py
@@ -146,15 +146,15 @@ def DiTi_3Pos(name: str) -> TecanTipCarrier:
name=name,
size_x=149.0,
size_y=374.0,
- size_z=4.5,
- off_x=12.0,
- off_y=24.7,
+ size_z=123.2,
+ off_x=12,
+ off_y=60,
sites=create_homogeneous_resources(
klass=ResourceHolder,
locations=[
- Coordinate(13.3, 70.0, 4.5),
- Coordinate(13.3, 170.0, 4.5),
- Coordinate(13.3, 270.0, 4.5),
+ Coordinate(13.3, 13.4, 4.5),
+ Coordinate(13.3, 113.4, 4.5),
+ Coordinate(13.3, 213.4, 4.5),
],
resource_size_x=127.0,
resource_size_y=88.5,
diff --git a/pylabrobot/resources/tecan/tip_racks.py b/pylabrobot/resources/tecan/tip_racks.py
index e32b332dbc..bdb6ba1d19 100644
--- a/pylabrobot/resources/tecan/tip_racks.py
+++ b/pylabrobot/resources/tecan/tip_racks.py
@@ -1235,7 +1235,7 @@ def DiTi_1000ul_LiHa(name: str) -> TecanTipRack:
num_items_x=12,
num_items_y=8,
dx=7.7,
- dy=8.7,
+ dy=7.7,
dz=32.6,
item_dx=9.0,
item_dy=9.0,
diff --git a/pylabrobot/resources/tecan/wash.py b/pylabrobot/resources/tecan/wash.py
index 29af808690..1f0ded9854 100644
--- a/pylabrobot/resources/tecan/wash.py
+++ b/pylabrobot/resources/tecan/wash.py
@@ -46,14 +46,14 @@ def Wash_Station(name: str) -> TecanWashStation:
size_x=25.0,
size_y=390.0,
size_z=0.0,
+ off_y= -13,
off_x=12.5,
- off_y=24.7,
sites=create_resources(
klass=ResourceHolder,
locations=[
- Coordinate(12.2, 106.7, 0.0),
- Coordinate(11.0, 180.7, 0.0),
- Coordinate(12.2, 281.7, 0.0),
+ Coordinate(12.2, 107, 0.0),
+ Coordinate(11.0, 181, 0.0),
+ Coordinate(12.2, 282, 0.0),
],
resource_size_x=[
12.0,