This commit is contained in:
Guangxin Zhang
2025-07-19 00:09:59 +08:00
parent a95e4d446b
commit 736f55765b
3 changed files with 13746 additions and 160 deletions

13533
deck.json Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -590,14 +590,14 @@ class LiquidHandlerAbstract(LiquidHandlerMiddleware):
else: else:
# 首先应该对任务分组然后每次1个/8个进行操作处理 # 首先应该对任务分组然后每次1个/8个进行操作处理
if len(use_channels) == 1 and self.backend.num_channels == 1: if len(use_channels) == 1 and self.backend.num_channels == 1:
for _ in range(len(sources)):
tip = [] tip = []
for _ in range(len(use_channels)): for __ in range(len(use_channels)):
tip.extend(next(self.current_tip)) tip.extend(next(self.current_tip))
await self.pick_up_tips(tip) await self.pick_up_tips(tip)
for _ in range(len(waste_liquid)):
await self.aspirate( await self.aspirate(
resources=sources, resources=[sources[_]],
vols=[vols[_]], vols=[vols[_]],
use_channels=use_channels, use_channels=use_channels,
flow_rates=[flow_rates[0]] if flow_rates else None, flow_rates=[flow_rates[0]] if flow_rates else None,
@@ -608,8 +608,9 @@ class LiquidHandlerAbstract(LiquidHandlerMiddleware):
) )
if delays is not None: if delays is not None:
await self.custom_delay(seconds=delays[0]) await self.custom_delay(seconds=delays[0])
await self.dispense( await self.dispense(
resources=[waste_liquid[_]], resources=[waste_liquid],
vols=[vols[_]], vols=[vols[_]],
use_channels=use_channels, use_channels=use_channels,
flow_rates=[flow_rates[1]] if flow_rates else None, flow_rates=[flow_rates[1]] if flow_rates else None,
@@ -706,9 +707,9 @@ class LiquidHandlerAbstract(LiquidHandlerMiddleware):
mix_liquid_height: Optional[float] = None, mix_liquid_height: Optional[float] = None,
none_keys: List[str] = [], none_keys: List[str] = [],
): ):
"""A complete *add* (aspirate reagent → dispense into targets) operation.""" # """A complete *add* (aspirate reagent → dispense into targets) operation."""
try: # # try:
if is_96_well: if is_96_well:
pass # This mode is not verified. pass # This mode is not verified.
else: else:
@@ -720,9 +721,9 @@ class LiquidHandlerAbstract(LiquidHandlerMiddleware):
tip = [] tip = []
for _ in range(len(use_channels)): for _ in range(len(use_channels)):
tip.extend(next(self.current_tip)) tip.extend(next(self.current_tip))
await self.pick_up_tips(tip) await self.pick_up_tips(tip)
for _ in range(len(targets)): for _ in range(len(targets)):
print(use_channels, reagent_sources)
await self.aspirate( await self.aspirate(
resources=reagent_sources, resources=reagent_sources,
vols=[asp_vols[_]], vols=[asp_vols[_]],
@@ -733,6 +734,7 @@ class LiquidHandlerAbstract(LiquidHandlerMiddleware):
blow_out_air_volume=[blow_out_air_volume[0]] if blow_out_air_volume else None, blow_out_air_volume=[blow_out_air_volume[0]] if blow_out_air_volume else None,
spread=spread, spread=spread,
) )
if delays is not None: if delays is not None:
await self.custom_delay(seconds=delays[0]) await self.custom_delay(seconds=delays[0])
await self.dispense( await self.dispense(
@@ -749,7 +751,7 @@ class LiquidHandlerAbstract(LiquidHandlerMiddleware):
if delays is not None: if delays is not None:
await self.custom_delay(seconds=delays[1]) await self.custom_delay(seconds=delays[1])
await self.mix( await self.mix(
targets=targets[_], targets=[targets[_]],
mix_time=mix_time, mix_time=mix_time,
mix_vol=mix_vol, mix_vol=mix_vol,
offsets=offsets if offsets else None, offsets=offsets if offsets else None,
@@ -759,7 +761,7 @@ class LiquidHandlerAbstract(LiquidHandlerMiddleware):
if delays is not None: if delays is not None:
await self.custom_delay(seconds=delays[1]) await self.custom_delay(seconds=delays[1])
await self.touch_tip(targets[_]) await self.touch_tip(targets[_])
await self.discard_tips()
elif len(use_channels) == 8: elif len(use_channels) == 8:
# 对于8个的情况需要判断此时任务是不是能被8通道移液站来成功处理 # 对于8个的情况需要判断此时任务是不是能被8通道移液站来成功处理
@@ -825,9 +827,9 @@ class LiquidHandlerAbstract(LiquidHandlerMiddleware):
await self.discard_tips() await self.discard_tips()
except Exception as e: # except Exception as e:
traceback.print_exc() # traceback.print_exc()
raise RuntimeError(f"Liquid addition failed: {e}") from e # raise RuntimeError(f"Liquid addition failed: {e}") from e
# --------------------------------------------------------------- # ---------------------------------------------------------------
# TRANSFER LIQUID ------------------------------------------------ # TRANSFER LIQUID ------------------------------------------------
@@ -872,7 +874,7 @@ class LiquidHandlerAbstract(LiquidHandlerMiddleware):
Set *True* to use the 96channel head. Set *True* to use the 96channel head.
""" """
try:
if is_96_well: if is_96_well:
pass # This mode is not verified. pass # This mode is not verified.
else: else:
@@ -881,14 +883,14 @@ class LiquidHandlerAbstract(LiquidHandlerMiddleware):
# 首先应该对任务分组然后每次1个/8个进行操作处理 # 首先应该对任务分组然后每次1个/8个进行操作处理
if len(use_channels) == 1: if len(use_channels) == 1:
for _ in range(len(targets)):
tip = [] tip = []
for _ in range(len(use_channels)): for ___ in range(len(use_channels)):
tip.extend(next(self.current_tip)) tip.extend(next(self.current_tip))
await self.pick_up_tips(tip) await self.pick_up_tips(tip)
for _ in range(len(targets)):
await self.aspirate( await self.aspirate(
resources=sources, resources=[sources[_]],
vols=[asp_vols[_]], vols=[asp_vols[_]],
use_channels=use_channels, use_channels=use_channels,
flow_rates=[asp_flow_rates[0]] if asp_flow_rates else None, flow_rates=[asp_flow_rates[0]] if asp_flow_rates else None,
@@ -912,7 +914,7 @@ class LiquidHandlerAbstract(LiquidHandlerMiddleware):
if delays is not None: if delays is not None:
await self.custom_delay(seconds=delays[1]) await self.custom_delay(seconds=delays[1])
await self.mix( await self.mix(
targets=targets[_], targets=[targets[_]],
mix_time=mix_times, mix_time=mix_times,
mix_vol=mix_vol, mix_vol=mix_vol,
offsets=offsets if offsets else None, offsets=offsets if offsets else None,
@@ -989,9 +991,9 @@ class LiquidHandlerAbstract(LiquidHandlerMiddleware):
await self.touch_tip(current_targets) await self.touch_tip(current_targets)
await self.discard_tips() await self.discard_tips()
except Exception as e: # except Exception as e:
traceback.print_exc() # traceback.print_exc()
raise RuntimeError(f"Liquid addition failed: {e}") from e # raise RuntimeError(f"Liquid addition failed: {e}") from e
# --------------------------------------------------------------- # ---------------------------------------------------------------

View File

@@ -433,10 +433,14 @@ class PRCXI9300Backend(LiquidHandlerBackend):
plate_indexes = [] plate_indexes = []
for op in ops: for op in ops:
plate = op.resource.parent.parent plate = op.resource.parent
deck = plate.parent deck = plate.parent
plate_index = deck.children.index(plate) plate_index = deck.children.index(plate)
print(f"Plate index: {plate_index}, Plate name: {plate.name}")
print(f"Number of children in deck: {len(deck.children)}")
plate_indexes.append(plate_index) plate_indexes.append(plate_index)
if len(set(plate_indexes)) != 1: if len(set(plate_indexes)) != 1:
raise ValueError("All pickups must be from the same plate. Found different plates: " + str(plate_indexes)) raise ValueError("All pickups must be from the same plate. Found different plates: " + str(plate_indexes))
@@ -447,7 +451,8 @@ class PRCXI9300Backend(LiquidHandlerBackend):
tip_columns.append(tipspot_index // 8) tip_columns.append(tipspot_index // 8)
if len(set(tip_columns)) != 1: if len(set(tip_columns)) != 1:
raise ValueError("All pickups must be from the same tip column. Found different columns: " + str(tip_columns)) raise ValueError("All pickups must be from the same tip column. Found different columns: " + str(tip_columns))
# print('111'*99)
# print(plate_indexes[0])
PlateNo = plate_indexes[0] + 1 PlateNo = plate_indexes[0] + 1
hole_col = tip_columns[0] + 1 hole_col = tip_columns[0] + 1
@@ -485,7 +490,7 @@ class PRCXI9300Backend(LiquidHandlerBackend):
plate_indexes = [] plate_indexes = []
for op in ops: for op in ops:
plate = op.resource.parent.parent plate = op.resource.parent
deck = plate.parent deck = plate.parent
plate_index = deck.children.index(plate) plate_index = deck.children.index(plate)
plate_indexes.append(plate_index) plate_indexes.append(plate_index)
@@ -532,11 +537,10 @@ class PRCXI9300Backend(LiquidHandlerBackend):
"""Mix liquid in the specified resources.""" """Mix liquid in the specified resources."""
plate_indexes = [] plate_indexes = []
for op in targets: for op in targets:
deck = op.parent.parent.parent deck = op.parent.parent
plate = op.parent.parent plate = op.parent
plate_index = deck.children.index(plate) plate_index = deck.children.index(plate)
plate_indexes.append(plate_index) plate_indexes.append(plate_index)
@@ -577,7 +581,7 @@ class PRCXI9300Backend(LiquidHandlerBackend):
plate_indexes = [] plate_indexes = []
for op in ops: for op in ops:
plate = op.resource.parent.parent plate = op.resource.parent
deck = plate.parent deck = plate.parent
plate_index = deck.children.index(plate) plate_index = deck.children.index(plate)
plate_indexes.append(plate_index) plate_indexes.append(plate_index)
@@ -617,7 +621,7 @@ class PRCXI9300Backend(LiquidHandlerBackend):
plate_indexes = [] plate_indexes = []
for op in ops: for op in ops:
plate = op.resource.parent.parent plate = op.resource.parent
deck = plate.parent deck = plate.parent
plate_index = deck.children.index(plate) plate_index = deck.children.index(plate)
plate_indexes.append(plate_index) plate_indexes.append(plate_index)
@@ -1244,7 +1248,7 @@ if __name__ == "__main__":
handler = PRCXI9300Handler(deck=deck, host="10.181.102.13", port=9999, handler = PRCXI9300Handler(deck=deck, host="10.181.102.13", port=9999,
timeout=10.0, setup=False, debug=False, timeout=10.0, setup=False, debug=False,
matrix_id="fd383e6d-2d0e-40b5-9c01-1b2870b1f1b1", matrix_id="fd383e6d-2d0e-40b5-9c01-1b2870b1f1b1",
channel_num=1) channel_num=1, axis="Right") # Initialize the handler with the deck and host settings
handler.set_tiprack([plate8]) # Set the tip rack for the handler handler.set_tiprack([plate8]) # Set the tip rack for the handler
asyncio.run(handler.setup()) # Initialize the handler and setup the connection asyncio.run(handler.setup()) # Initialize the handler and setup the connection
@@ -1262,32 +1266,79 @@ if __name__ == "__main__":
print(plate11.get_well(0).tracker.get_used_volume()) print(plate11.get_well(0).tracker.get_used_volume())
asyncio.run(handler.create_protocol(protocol_name="Test Protocol")) # Initialize the backend and setup the connection asyncio.run(handler.create_protocol(protocol_name="Test Protocol")) # Initialize the backend and setup the connection
print(plate8.children[3])
asyncio.run(handler.pick_up_tips([plate8.children[3]],[0])) # asyncio.run(handler.pick_up_tips([plate8.children[8]],[0]))
asyncio.run(handler.aspirate([plate11.children[0]],[10], [0])) # print(plate8.children[8])
asyncio.run(handler.dispense([plate1.children[3]],[10],[0])) # # asyncio.run(handler.run_protocol())
asyncio.run(handler.mix([plate1.children[3]], mix_time=3, mix_vol=5, height_to_bottom=0.5, offsets=Coordinate(0, 0, 0), mix_rate=100)) # asyncio.run(handler.aspirate([plate11.children[0]],[10], [0]))
asyncio.run(handler.discard_tips()) # print(plate11.children[0])
# # asyncio.run(handler.run_protocol())
# asyncio.run(handler.dispense([plate1.children[0]],[10],[0]))
# print(plate1.children[0])
# # asyncio.run(handler.run_protocol())
# asyncio.run(handler.mix([plate1.children[0]], mix_time=3, mix_vol=5, height_to_bottom=0.5, offsets=Coordinate(0, 0, 0), mix_rate=100))
# print(plate1.children[0])
# asyncio.run(handler.discard_tips())
# asyncio.run(handler.add_liquid(
# asp_vols=[10]*2,
# dis_vols=[10]*2,
# reagent_sources=[plate11.children[0]],
# targets=plate11.children[-2:],
# use_channels=[0],
# flow_rates=[None] * 4,
# offsets=[Coordinate(0, 0, 0)] * 4,
# liquid_height=[None] * 2,
# blow_out_air_volume=[None] * 2,
# delays=None,
# mix_time=3,
# mix_vol=5,
# spread="wide",
# ))
# asyncio.run(handler.transfer_liquid(
# asp_vols=[10]*2,
# dis_vols=[10]*2,
# sources=plate11.children[:2],
# targets=plate11.children[-2:],
# use_channels=[0],
# offsets=[Coordinate(0, 0, 0)] * 4,
# liquid_height=[None] * 2,
# blow_out_air_volume=[None] * 2,
# delays=None,
# mix_times=3,
# mix_vol=5,
# spread="wide",
# tip_racks=[plate8]
# ))
asyncio.run(handler.remove_liquid(
vols=[10]*2,
sources=plate11.children[:2],
waste_liquid=plate11.children[43],
use_channels=[0],
offsets=[Coordinate(0, 0, 0)] * 4,
liquid_height=[None] * 2,
blow_out_air_volume=[None] * 2,
delays=None,
spread="wide"
))
asyncio.run(handler.run_protocol())
# asyncio.run(handler.discard_tips()) # asyncio.run(handler.discard_tips())
# asyncio.run(handler.mix(well_containers.children[:8 # asyncio.run(handler.mix(well_containers.children[:8
# ], mix_time=3, mix_vol=50, height_to_bottom=0.5, offsets=Coordinate(0, 0, 0), mix_rate=100)) # ], mix_time=3, mix_vol=50, height_to_bottom=0.5, offsets=Coordinate(0, 0, 0), mix_rate=100))
#print(json.dumps(handler._unilabos_backend.steps_todo_list, indent=2)) # Print matrix info #print(json.dumps(handler._unilabos_backend.steps_todo_list, indent=2)) # Print matrix info
# asyncio.run(handler.add_liquid(
# asp_vols=[100]*16,
# dis_vols=[100]*16,
# reagent_sources=final_plate_2.children[-16:],
# targets=final_plate_2.children[:16],
# use_channels=[0, 1, 2, 3, 4, 5, 6, 7],
# flow_rates=[None] * 32,
# offsets=[Coordinate(0, 0, 0)] * 32,
# liquid_height=[None] * 16,
# blow_out_air_volume=[None] * 16,
# delays=None,
# mix_time=3,
# mix_vol=50,
# spread="wide",
# ))
# asyncio.run(handler.remove_liquid( # asyncio.run(handler.remove_liquid(
# vols=[100]*16, # vols=[100]*16,