I’m testing a very simple method that uses the 50 uL tips, which I haven’t yet used with PLR. I don’t know that the 50 uL tips is the issue, but it is the only thing new I’m doing relative to any other actions I’ve done without similar issues. I can also change the method to use 1000 uL tips and it works fine.
Here is a compressed set of relevant commands I’m using:
tip_car = TIP_CAR_480_A00(name='tip_carrier')
tip_car[0] = TIP_50ul_L(name='tips_01')
lh.deck.assign_child_resource(tip_car, rails=1)
premix_car = PLT_CAR_L5AC_A00(name='premix_carrier')
premix_car[0] = Cos_96_PCR(name='premix_plate')
lh.deck.assign_child_resource(premix_car, rails=7)
await lh.pick_up_tips96(lh.get_resource('tips_01'))
await lh.aspirate_plate(lh.get_resource('premix_plate'), volume=15)
...
It will pick up tips just fine, but when it goes to aspirate, I get a parameter out of range error. The only parameter I’m passing is the volume, but the volumes I’m using should work fine with the 50 uL tip. I’ll note that I tried several different volumes between 5 and 25 uL with no effect:
---------------------------------------------------------------------------
STARFirmwareError Traceback (most recent call last)
Cell In[15], line 2
1 #await lh.aspirate_plate(lh.get_resource('premix_plate'), volume=premix_vol, flow_rates=aspirate_speed)
----> 2 await lh.aspirate_plate(lh.get_resource('premix_plate'), volume=15)
File ~/Documents/Lab/PyLabRobot/pylabrobot/pylabrobot/liquid_handling/liquid_handler.py:1259, in LiquidHandler.aspirate_plate(self, plate, volume, flow_rate, end_delay, blow_out_air_volume, **backend_kwargs)
1257 well.tracker.rollback()
1258 channel.get_tip().tracker.rollback()
-> 1259 self._trigger_callback(
1260 "aspirate_plate",
1261 liquid_handler=self,
1262 aspiration=aspiration_plate,
1263 error=error,
1264 **backend_kwargs,
1265 )
1266 else:
1267 for channel, well in zip(self.head96.values(), plate.get_all_items()):
File ~/Documents/Lab/PyLabRobot/pylabrobot/pylabrobot/liquid_handling/liquid_handler.py:1654, in LiquidHandler._trigger_callback(self, method_name, error, *args, **kwargs)
1652 callback(self, *args, error=error, **kwargs)
1653 elif error is not None:
-> 1654 raise error
File ~/Documents/Lab/PyLabRobot/pylabrobot/pylabrobot/liquid_handling/liquid_handler.py:1253, in LiquidHandler.aspirate_plate(self, plate, volume, flow_rate, end_delay, blow_out_air_volume, **backend_kwargs)
1241 aspiration_plate = AspirationPlate(
1242 resource=plate,
1243 volume=volume,
(...)
1249 liquids=cast(List[List[Tuple[Optional[Liquid], float]]], all_liquids) # stupid
1250 )
1252 try:
-> 1253 await self.backend.aspirate96(aspiration=aspiration_plate, **backend_kwargs)
1254 except Exception as error: # pylint: disable=broad-except
1255 for channel, well in zip(self.head96.values(), plate.get_all_items()):
File ~/Documents/Lab/PyLabRobot/pylabrobot/pylabrobot/liquid_handling/backends/hamilton/STAR.py:61, in need_iswap_parked.<locals>.wrapper(self, *args, **kwargs)
58 if self.iswap_installed and not self.iswap_parked:
59 await self.park_iswap()
---> 61 result = await method(self, *args, **kwargs) # pylint: disable=not-callable
63 return result
File ~/Documents/Lab/PyLabRobot/pylabrobot/pylabrobot/liquid_handling/backends/hamilton/STAR.py:2150, in STAR.aspirate96(self, aspiration, jet, blow_out, use_lld, liquid_height, air_transport_retract_dist, hlc, aspiration_type, minimum_traverse_height_at_beginning_of_a_command, minimal_end_height, lld_search_height, maximum_immersion_depth, tube_2nd_section_height_measured_from_zm, tube_2nd_section_ratio, immersion_depth, immersion_depth_direction, liquid_surface_sink_distance_at_the_end_of_aspiration, transport_air_volume, pre_wetting_volume, gamma_lld_sensitivity, swap_speed, settling_time, homogenization_volume, homogenization_cycles, homogenization_position_from_liquid_surface, surface_following_distance_during_homogenization, speed_of_homogenization, limit_curve_index)
2134 pull_out_distance_to_take_transport_air_in_function_without_lld = \
2135 int(air_transport_retract_dist * 10)
2137 # Was this ever true? Just copied it over from pyhamilton. Could have something to do with
2138 # the liquid classes and whether blow_out mode is enabled.
2139 # # Unfortunately, `blow_out_air_volume` does not work correctly, so instead we aspirate air
(...)
2147 # aspiration_volumes=int(blow_out_air_volume * 10)
2148 # )
-> 2150 return await self.aspirate_core_96(
2151 x_position=int(position.x * 10),
2152 x_direction=0,
2153 y_positions=int(position.y * 10),
2154 aspiration_type=aspiration_type,
2155
2156 minimum_traverse_height_at_beginning_of_a_command=
2157 minimum_traverse_height_at_beginning_of_a_command,
2158 minimal_end_height=minimal_end_height,
2159 lld_search_height=lld_search_height,
2160 liquid_surface_at_function_without_lld=liquid_surface_at_function_without_lld,
2161 pull_out_distance_to_take_transport_air_in_function_without_lld=
2162 pull_out_distance_to_take_transport_air_in_function_without_lld,
2163 maximum_immersion_depth=maximum_immersion_depth,
2164 tube_2nd_section_height_measured_from_zm=tube_2nd_section_height_measured_from_zm,
2165 tube_2nd_section_ratio=tube_2nd_section_ratio,
2166 immersion_depth=immersion_depth,
2167 immersion_depth_direction=immersion_depth_direction,
2168 liquid_surface_sink_distance_at_the_end_of_aspiration=
2169 liquid_surface_sink_distance_at_the_end_of_aspiration,
2170 aspiration_volumes=aspiration_volumes,
2171 aspiration_speed=flow_rate,
2172 transport_air_volume=transport_air_volume,
2173 blow_out_air_volume=blow_out_air_volume,
2174 pre_wetting_volume=pre_wetting_volume,
2175 lld_mode=int(use_lld),
2176 gamma_lld_sensitivity=gamma_lld_sensitivity,
2177 swap_speed=swap_speed,
2178 settling_time=settling_time,
2179 homogenization_volume=homogenization_volume,
2180 homogenization_cycles=homogenization_cycles,
2181 homogenization_position_from_liquid_surface=
2182 homogenization_position_from_liquid_surface,
2183 surface_following_distance_during_homogenization=
2184 surface_following_distance_during_homogenization,
2185 speed_of_homogenization=speed_of_homogenization,
2186 channel_pattern=channel_pattern,
2187 limit_curve_index=limit_curve_index,
2188 tadm_algorithm=False,
2189 recording_mode=0,
2190 )
File ~/Documents/Lab/PyLabRobot/pylabrobot/pylabrobot/liquid_handling/backends/hamilton/STAR.py:5026, in STAR.aspirate_core_96(self, aspiration_type, x_position, x_direction, y_positions, minimum_traverse_height_at_beginning_of_a_command, minimal_end_height, lld_search_height, liquid_surface_at_function_without_lld, pull_out_distance_to_take_transport_air_in_function_without_lld, maximum_immersion_depth, tube_2nd_section_height_measured_from_zm, tube_2nd_section_ratio, immersion_depth, immersion_depth_direction, liquid_surface_sink_distance_at_the_end_of_aspiration, aspiration_volumes, aspiration_speed, transport_air_volume, blow_out_air_volume, pre_wetting_volume, lld_mode, gamma_lld_sensitivity, swap_speed, settling_time, homogenization_volume, homogenization_cycles, homogenization_position_from_liquid_surface, surface_following_distance_during_homogenization, speed_of_homogenization, channel_pattern, limit_curve_index, tadm_algorithm, recording_mode)
5023 channel_pattern_bin_str = reversed(["1" if x else "0" for x in channel_pattern])
5024 channel_pattern_hex = hex(int("".join(channel_pattern_bin_str), 2)).upper()[2:]
-> 5026 return await self.send_command(
5027 module="C0",
5028 command="EA",
5029 aa=aspiration_type,
5030 xs=f"{x_position:05}",
5031 xd=x_direction,
5032 yh=f"{y_positions:04}",
5033 zh=f"{minimum_traverse_height_at_beginning_of_a_command:04}",
5034 ze=f"{minimal_end_height:04}",
5035 lz=f"{lld_search_height:04}",
5036 zt=f"{liquid_surface_at_function_without_lld:04}",
5037 pp=f"{pull_out_distance_to_take_transport_air_in_function_without_lld:04}",
5038 zm=f"{maximum_immersion_depth:04}",
5039 zv=f"{tube_2nd_section_height_measured_from_zm:04}",
5040 zq=f"{tube_2nd_section_ratio:05}",
5041 iw=f"{immersion_depth:03}",
5042 ix=immersion_depth_direction,
5043 fh=f"{liquid_surface_sink_distance_at_the_end_of_aspiration:03}",
5044 af=f"{aspiration_volumes:05}",
5045 ag=f"{aspiration_speed:04}",
5046 vt=f"{transport_air_volume:03}",
5047 bv=f"{blow_out_air_volume:05}",
5048 wv=f"{pre_wetting_volume:05}",
5049 cm=lld_mode,
5050 cs=gamma_lld_sensitivity,
5051 bs=f"{swap_speed:04}",
5052 wh=f"{settling_time:02}",
5053 hv=f"{homogenization_volume:05}",
5054 hc=f"{homogenization_cycles:02}",
5055 hp=f"{homogenization_position_from_liquid_surface:03}",
5056 mj=f"{surface_following_distance_during_homogenization:03}",
5057 hs=f"{speed_of_homogenization:04}",
5058 cw=channel_pattern_hex,
5059 cr=f"{limit_curve_index:03}",
5060 cj=tadm_algorithm,
5061 cx=recording_mode,
5062 )
File ~/Documents/Lab/PyLabRobot/pylabrobot/pylabrobot/liquid_handling/backends/hamilton/base.py:193, in HamiltonLiquidHandler.send_command(self, module, command, tip_pattern, write_timeout, read_timeout, wait, fmt, **kwargs)
171 """ Send a firmware command to the Hamilton machine.
172
173 Args:
(...)
188 A dictionary containing the parsed response, or None if no response was read within `timeout`.
189 """
191 cmd, id_ = self._assemble_command(module=module, command=command, tip_pattern=tip_pattern,
192 **kwargs)
--> 193 resp = await self._write_and_read_command(id_=id_, cmd=cmd, write_timeout=write_timeout,
194 read_timeout=read_timeout, wait=wait)
195 if resp is not None and fmt is not None:
196 return self._parse_response(resp, fmt)
File ~/Documents/Lab/PyLabRobot/pylabrobot/pylabrobot/liquid_handling/backends/hamilton/base.py:220, in HamiltonLiquidHandler._write_and_read_command(self, id_, cmd, write_timeout, read_timeout, wait)
218 fut = loop.create_future()
219 self._start_reading(id_, loop, fut, cmd, read_timeout)
--> 220 result = await fut
221 return cast(str, result)
File ~/Documents/Lab/PyLabRobot/pylabrobot/pylabrobot/liquid_handling/backends/hamilton/base.py:293, in HamiltonLiquidHandler._continuously_read(self)
291 if response_id == id_:
292 try:
--> 293 self.check_fw_string_error(resp)
294 except Exception as e: # pylint: disable=broad-exception-caught
295 loop.call_soon_threadsafe(fut.set_exception, e)
File ~/Documents/Lab/PyLabRobot/pylabrobot/pylabrobot/liquid_handling/backends/hamilton/STAR.py:1181, in STAR.check_fw_string_error(self, resp)
1172 if error.message == "Unknown parameter":
1173 # temp. disabled until we figure out how to handle async in parse response (the
1174 # background thread does not have an event loop, and I'm not sure if it should.)
(...)
1177
1178 # pylint: disable=unnecessary-dict-index-lookup
1179 he[module_name].message += " (call lh.backend.request_name_of_last_faulty_parameter)"
-> 1181 raise he
STARFirmwareError: STARFirmwareError(errors={'CoRe 96 Head': CommandSyntaxError('Parameter out of range')}, raw_response=C0EAid0007er99/00 H001/32)