Hi everyone,
Is there already a way to perform a multi-channel aspiration from a multi-compartment reservoir plate?
Let’s say you have a reservoir with 6 compartments (‘A1’, ‘A2’, ‘A3’, ‘A4’, ‘A5’, ‘A6’). The power of a reservoir comes from being able to aspirate with all channels simultaneously.
However, when performing the following command…
positions = tip_50ul_00['A1', 'B1']
await lh.pick_up_tips(positions)
await lh.aspirate(Porvair_6x47_Reservoir_00['A1'], vols=[5, 5], use_channels=[0, 1],
swap_speed = 50, homogenization_speed = 20,
dispensation_speed_during_emptying_tip = 25,
)
…the following ValueError is raised…
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Cell In[65], line 1
----> 1 await lh.aspirate(Porvair_6x47_Reservoir_00['A1'], vols=[2.5, 2.5], use_channels=[0, 1],
2 swap_speed = 50, homogenization_speed = 20,
3 dispensation_speed_during_emptying_tip = 25,
4 )
File ~/pylabrobot/pylabrobot/machine.py:20, in need_setup_finished.<locals>.wrapper(self, *args, **kwargs)
18 if not self.setup_finished:
19 raise RuntimeError("The setup has not finished. See `setup`.")
---> 20 return await func(self, *args, **kwargs)
File ~/pylabrobot/pylabrobot/liquid_handling/liquid_handler.py:689, in LiquidHandler.aspirate(self, resources, vols, use_channels, flow_rates, end_delay, offsets, liquid_height, **backend_kwargs)
685 self._make_sure_channels_exist(use_channels)
687 offsets = expand(offsets, n)
--> 689 vols = expand(vols, n)
690 flow_rates = expand(flow_rates, n)
691 liquid_height = expand(liquid_height, n)
File ~/pylabrobot/pylabrobot/utils/list.py:54, in expand(list_or_item, n)
52 if isinstance(list_or_item, collections.abc.Sequence) and not isinstance(list_or_item, str):
53 if len(list_or_item) != n:
---> 54 raise ValueError(f"Expected list of length {n}, got {len(list_or_item)}.")
55 return list(list_or_item)
56 # cast to T to avoid mypy error (thinks it's a string). This can probably be written better.
ValueError: Expected list of length 1, got 2.
Creating offsets manually with…
offsets = Porvair_6x47_Reservoir_00.get_item('A1').get_2d_center_offsets(n=2)
…and handing them to the function as an argument raises the same error.
At the same time…
await lh.aspirate(Porvair_6x47_Reservoir_00.get_item('A1'), vols=[5, 5], use_channels=[0, 1],
swap_speed = 50, homogenization_speed = 20,
dispensation_speed_during_emptying_tip = 25,
)
…does enforce the aspiration but from a completely wrong position (outside of the well ‘A1’).
A quick way I can see to get around this is to define the reservoir instead as a 96-deepwell plate but that is not a permanent solution