添加切换枪头方法,添加mock振荡与加热方法

This commit is contained in:
zhangshixiang
2025-12-16 11:19:13 +08:00
parent 8ba911bb55
commit 44fc80c70f
3 changed files with 150 additions and 26 deletions

View File

@@ -433,6 +433,12 @@ class PRCXI9300Handler(LiquidHandlerAbstract):
async def move_to(self, well: Well, dis_to_top: float = 0, channel: int = 0):
return await super().move_to(well, dis_to_top, channel)
async def shaker_action(self, time: int, frequency: float):
return await self._unilabos_backend.shaker_action(time, frequency)
async def heater_action(self, temperature: float, time: int):
return await self._unilabos_backend.heater_action(temperature, time)
class PRCXI9300Backend(LiquidHandlerBackend):
"""PRCXI 9300 的后端实现,继承自 LiquidHandlerBackend。
@@ -474,6 +480,15 @@ class PRCXI9300Backend(LiquidHandlerBackend):
self._num_channels = channel_num
self._execute_setup = setup
self.debug = debug
self.axis = "Left"
async def shaker_action(self, time: int, frequency: float):
print(f"\n\nShaker action: time={time}, frequency={frequency}\n\n")
# return await self.api_client.shaker_action(time, frequency)
async def heater_action(self, temperature: float, time: int):
print(f"\n\nHeater action: temperature={temperature}, time={time}\n\n")
# return await self.api_client.heater_action(temperature, time)
def post_init(self, ros_node: BaseROS2DeviceNode):
self._ros_node = ros_node
@@ -555,7 +570,18 @@ class PRCXI9300Backend(LiquidHandlerBackend):
async def pick_up_tips(self, ops: List[Pickup], use_channels: List[int] = None):
"""Pick up tips from the specified resource."""
# INSERT_YOUR_CODE
# Ensure use_channels is converted to a list of ints if it's an array
if hasattr(use_channels, 'tolist'):
_use_channels = use_channels.tolist()
else:
_use_channels = list(use_channels) if use_channels is not None else None
if _use_channels == [0]:
axis = "Left"
elif _use_channels == [1]:
axis = "Right"
else:
raise ValueError("Invalid use channels: " + str(_use_channels))
plate_indexes = []
for op in ops:
plate = op.resource.parent
@@ -585,6 +611,7 @@ class PRCXI9300Backend(LiquidHandlerBackend):
hole_row = tipspot_index % 8 + 1
step = self.api_client.Load(
axis=axis,
dosage=0,
plate_no=PlateNo,
is_whole_plate=False,
@@ -599,13 +626,23 @@ class PRCXI9300Backend(LiquidHandlerBackend):
async def drop_tips(self, ops: List[Drop], use_channels: List[int] = None):
"""Pick up tips from the specified resource."""
if hasattr(use_channels, 'tolist'):
_use_channels = use_channels.tolist()
else:
_use_channels = list(use_channels) if use_channels is not None else None
if _use_channels == [0]:
axis = "Left"
elif _use_channels == [1]:
axis = "Right"
else:
raise ValueError("Invalid use channels: " + str(_use_channels))
# 检查trash #
if ops[0].resource.name == "trash":
PlateNo = ops[0].resource.parent.children.index(ops[0].resource) + 1
step = self.api_client.UnLoad(
axis=axis,
dosage=0,
plate_no=PlateNo,
is_whole_plate=False,
@@ -648,6 +685,7 @@ class PRCXI9300Backend(LiquidHandlerBackend):
hole_row = tipspot_index % 8 + 1
step = self.api_client.UnLoad(
axis=axis,
dosage=0,
plate_no=PlateNo,
is_whole_plate=False,
@@ -714,7 +752,16 @@ class PRCXI9300Backend(LiquidHandlerBackend):
async def aspirate(self, ops: List[SingleChannelAspiration], use_channels: List[int] = None):
"""Aspirate liquid from the specified resources."""
if hasattr(use_channels, 'tolist'):
_use_channels = use_channels.tolist()
else:
_use_channels = list(use_channels) if use_channels is not None else None
if _use_channels == [0]:
axis = "Left"
elif _use_channels == [1]:
axis = "Right"
else:
raise ValueError("Invalid use channels: " + str(_use_channels))
plate_indexes = []
for op in ops:
plate = op.resource.parent
@@ -747,6 +794,7 @@ class PRCXI9300Backend(LiquidHandlerBackend):
hole_row = tipspot_index % 8 + 1
step = self.api_client.Imbibing(
axis=axis,
dosage=int(volumes[0]),
plate_no=PlateNo,
is_whole_plate=False,
@@ -761,7 +809,16 @@ class PRCXI9300Backend(LiquidHandlerBackend):
async def dispense(self, ops: List[SingleChannelDispense], use_channels: List[int] = None):
"""Dispense liquid into the specified resources."""
if hasattr(use_channels, 'tolist'):
_use_channels = use_channels.tolist()
else:
_use_channels = list(use_channels) if use_channels is not None else None
if _use_channels == [0]:
axis = "Left"
elif _use_channels == [1]:
axis = "Right"
else:
raise ValueError("Invalid use channels: " + str(_use_channels))
plate_indexes = []
for op in ops:
plate = op.resource.parent
@@ -795,6 +852,7 @@ class PRCXI9300Backend(LiquidHandlerBackend):
hole_row = tipspot_index % 8 + 1
step = self.api_client.Tapping(
axis=axis,
dosage=int(volumes[0]),
plate_no=PlateNo,
is_whole_plate=False,
@@ -1000,9 +1058,10 @@ class PRCXI9300Api:
assist_fun4: str = "",
assist_fun5: str = "",
liquid_method: str = "NormalDispense",
axis: str = "Left",
) -> Dict[str, Any]:
return {
"StepAxis": self.axis,
"StepAxis": axis,
"Function": "Load",
"DosageNum": dosage,
"PlateNo": plate_no,
@@ -1038,9 +1097,10 @@ class PRCXI9300Api:
assist_fun4: str = "",
assist_fun5: str = "",
liquid_method: str = "NormalDispense",
) -> Dict[str, Any]:
axis: str = "Left",
) -> Dict[str, Any]:
return {
"StepAxis": self.axis,
"StepAxis": axis,
"Function": "Imbibing",
"DosageNum": dosage,
"PlateNo": plate_no,
@@ -1076,9 +1136,10 @@ class PRCXI9300Api:
assist_fun4: str = "",
assist_fun5: str = "",
liquid_method: str = "NormalDispense",
axis: str = "Left",
) -> Dict[str, Any]:
return {
"StepAxis": self.axis,
"StepAxis": axis,
"Function": "Tapping",
"DosageNum": dosage,
"PlateNo": plate_no,
@@ -1114,9 +1175,10 @@ class PRCXI9300Api:
assist_fun4: str = "",
assist_fun5: str = "",
liquid_method: str = "NormalDispense",
) -> Dict[str, Any]:
axis: str = "Left",
) -> Dict[str, Any]:
return {
"StepAxis": self.axis,
"StepAxis": axis,
"Function": "Blending",
"DosageNum": dosage,
"PlateNo": plate_no,
@@ -1152,9 +1214,10 @@ class PRCXI9300Api:
assist_fun4: str = "",
assist_fun5: str = "",
liquid_method: str = "NormalDispense",
axis: str = "Left",
) -> Dict[str, Any]:
return {
"StepAxis": self.axis,
"StepAxis": axis,
"Function": "UnLoad",
"DosageNum": dosage,
"PlateNo": plate_no,

View File

@@ -4500,6 +4500,9 @@ liquid_handler:
simulator:
default: false
type: boolean
total_height:
default: 310
type: number
required:
- backend
- deck
@@ -7553,6 +7556,35 @@ liquid_handler.prcxi:
title: custom_delay参数
type: object
type: UniLabJsonCommandAsync
auto-heater_action:
feedback: {}
goal: {}
goal_default:
temperature: null
time: null
handles: {}
placeholder_keys: {}
result: {}
schema:
description: ''
properties:
feedback: {}
goal:
properties:
temperature:
type: number
time:
type: integer
required:
- temperature
- time
type: object
result: {}
required:
- goal
title: heater_action参数
type: object
type: UniLabJsonCommandAsync
auto-iter_tips:
feedback: {}
goal: {}
@@ -7694,6 +7726,35 @@ liquid_handler.prcxi:
title: set_group参数
type: object
type: UniLabJsonCommand
auto-shaker_action:
feedback: {}
goal: {}
goal_default:
frequency: null
time: null
handles: {}
placeholder_keys: {}
result: {}
schema:
description: ''
properties:
feedback: {}
goal:
properties:
frequency:
type: number
time:
type: integer
required:
- time
- frequency
type: object
result: {}
required:
- goal
title: shaker_action参数
type: object
type: UniLabJsonCommandAsync
auto-touch_tip:
feedback: {}
goal: {}

View File

@@ -21,7 +21,7 @@
"_resource_type": "unilabos.devices.liquid_handling.prcxi.prcxi:PRCXI9300Deck",
"_resource_child_name": "PRCXI_Deck"
},
"host": "192.168.1.201",
"host": "10.20.30.184",
"port": 9999,
"debug": false,
"setup": true,
@@ -29,7 +29,7 @@
"timeout": 10,
"matrix_id": "5de524d0-3f95-406c-86dd-f83626ebc7cb",
"simulator": false,
"channel_num": 1
"channel_num": 2
},
"data": {
"reset_ok": true
@@ -9964,8 +9964,8 @@
},
{
"id": "container_for_nothing3",
"name": "container_for_nothing3",
"id": "emptyT3",
"name": "emptyT3",
"children": [],
"parent": "PRCXI_Deck",
@@ -9996,8 +9996,8 @@
},
{
"id": "container_for_nothing4",
"name": "container_for_nothing4",
"id": "emptyT4",
"name": "emptyT4",
"children": [],
"parent": "PRCXI_Deck",
@@ -19806,8 +19806,8 @@
},
{
"id": "container_for_nothing7",
"name": "container_for_nothing7",
"id": "emptyT7",
"name": "emptyT7",
"children": [],
"parent": "PRCXI_Deck",
@@ -19837,8 +19837,8 @@
"data": {}
},
{
"id": "container_for_nothing8",
"name": "container_for_nothing8",
"id": "emptyT8",
"name": "emptyT8",
"children": [],
"parent": "PRCXI_Deck",
@@ -28015,8 +28015,8 @@
},
{
"id": "container_for_nothing11",
"name": "container_for_nothing11",
"id": "emptyT11",
"name": "emptyT11",
"children": [],
"parent": "PRCXI_Deck",
@@ -28046,8 +28046,8 @@
"data": {}
},
{
"id": "container_for_nothing12",
"name": "container_for_nothing12",
"id": "emptyT12",
"name": "emptyT12",
"children": [],
"parent": "PRCXI_Deck",