You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现Opentrons移液高度计算公式遍历数值列表?

解决Opentrons移液体积列表的高度追踪报错问题

问题背景

我定义了计算试管剩余溶液高度的公式,希望让吸头随移液后的剩余量自动下降。单个体积移液时功能正常,但传入数值列表时持续报错。

报错信息

ValueError [line 76]: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

原代码

from opentrons import protocol_api
import math
import numpy as np

# metadata
metadata = {
    'protocolName': '2.27.23 - Highthroughput synthesis of Cs3Sb2X9',
    'apiLevel': '2.13'}

def run(protocol: protocol_api.ProtocolContext):
    #labware
    right_tiprack= protocol.load_labware('opentrons_96_tiprack_300ul', '1')
   
    left_tiprack= protocol.load_labware('opentrons_96_tiprack_20ul','5')
    left_tiprack_two= protocol.load_labware('opentrons_96_tiprack_20ul','4')
    
    tuberack= protocol.load_labware('opentrons_15_tuberack_nest_15ml_conical','8')
    
    #plates
    Cs_OPA_plate= protocol.load_labware('corning_96_wellplate_360ul_flat', '6')
    
    
    final_two_plate = protocol.load_labware('corning_96_wellplate_360ul_flat', '3')
    temp_mod = protocol.load_module('temperature module', '9')
    final_one_plate = temp_mod.load_labware('corning_96_wellplate_360ul_flat')
    temp_mod.set_temperature(70)  
    # Volume to transfer from each well
   
    #Depth of tube 117.50 mm
    #diameter of tube 14.90 mm
    Sb = tuberack.wells_by_name()['A1']
    tol = tuberack.wells_by_name()['B1']
    Cs = tuberack.wells_by_name()['C1']
    
    #Change to the amount of solution using in mL
    volume_of_sb_tube_in_ml: float = 2
    volume_of_tol_tube_in_ml:float= 13
    Volume_of_Cs_tube_in_ml: float = 1
    
    #pipette
    
    right_pipette = protocol.load_instrument('p300_single_gen2', 'right', tip_racks=[right_tiprack])
    left_pipette= protocol.load_instrument('p20_multi_gen2','left',tip_racks=[left_tiprack,left_tiprack_two])
    
    # calculation of 15 ml tube intiial heights
    def calc_initial_15(vol):
        dh = -(15.9- vol)*1000/(math.pi*(7.45**2))- 8
        return dh
    
    Sb_intial= calc_initial_15(volume_of_sb_tube_in_ml)
    Toluene_initial= calc_initial_15(volume_of_tol_tube_in_ml)
    Cs_initial= calc_initial_15(Volume_of_Cs_tube_in_ml)
    
    heights = {
        'Sb':Sb_intial,
        'tol': Toluene_initial,
        'Cs': Cs_initial
       
    }
    
    #Def for all, mix step for dilution, dilution, lower pipette for mixing, change for distrubute pick up/drop tip,
    def height_track15_tol(reagent):
        nonlocal heights
       
        
        dh = [vol/(math.pi*(7.45**2)) for vol in volume_amount]
        dh=np.array(dh)
        if heights[reagent] - dh < -116:
            heights[reagent] = -116
        else:
            heights[reagent] -= dh
  
    for well_name_tol in ['B1','C1','D1','E1','F1','G1','H1']:
         volume_amount= np.array([150,225,263,282,290,295,297])
        height_track15_tol('tol')
        h = heights['tol']
        right_pipette.pick_up_tip()
        right_pipette.transfer([150,225,263,282,290,295,297], 
                                   tol.top(h), 
                                   [Cs_OPA_plate.wells_by_name()[well_name_tol]], new_tip='never', touch_tip= True)
        right_pipette.drop_tip()

问题分析

  1. 数组真值判断歧义:height_track15_tol函数中,heights[reagent]是单个浮点数,dh是numpy数组,两者相减得到数组后直接用< -116判断,Python无法确定是要判断数组中所有元素还是任意元素满足条件,因此报错。
  2. 循环逻辑错误:每次循环都重新定义volume_amount为完整数组,且处理后heights['tol']会变成数组,而Opentrons的top()方法只接受单个数值作为高度参数,后续移液操作会失效。
  3. 移液逻辑不匹配:单个吸头一次只能移液一个体积值,传入列表的方式不符合p300_single_gen2的操作逻辑。

修正方案

调整为逐个处理每个移液体积,确保高度始终是单个浮点数,同时匹配单通道移液器的操作逻辑:

from opentrons import protocol_api
import math
import numpy as np

# metadata
metadata = {
    'protocolName': '2.27.23 - Highthroughput synthesis of Cs3Sb2X9',
    'apiLevel': '2.13'}

def run(protocol: protocol_api.ProtocolContext):
    #labware
    right_tiprack= protocol.load_labware('opentrons_96_tiprack_300ul', '1')
   
    left_tiprack= protocol.load_labware('opentrons_96_tiprack_20ul','5')
    left_tiprack_two= protocol.load_labware('opentrons_96_tiprack_20ul','4')
    
    tuberack= protocol.load_labware('opentrons_15_tuberack_nest_15ml_conical','8')
    
    #plates
    Cs_OPA_plate= protocol.load_labware('corning_96_wellplate_360ul_flat', '6')
    
    final_two_plate = protocol.load_labware('corning_96_wellplate_360ul_flat', '3')
    temp_mod = protocol.load_module('temperature module', '9')
    final_one_plate = temp_mod.load_labware('corning_96_wellplate_360ul_flat')
    temp_mod.set_temperature(70)  
    # Volume to transfer from each well
   
    #Depth of tube 117.50 mm
    #diameter of tube 14.90 mm
    Sb = tuberack.wells_by_name()['A1']
    tol = tuberack.wells_by_name()['B1']
    Cs = tuberack.wells_by_name()['C1']
    
    #Change to the amount of solution using in mL
    volume_of_sb_tube_in_ml: float = 2
    volume_of_tol_tube_in_ml:float= 13
    Volume_of_Cs_tube_in_ml: float = 1
    
    #pipette
    right_pipette = protocol.load_instrument('p300_single_gen2', 'right', tip_racks=[right_tiprack])
    left_pipette= protocol.load_instrument('p20_multi_gen2','left',tip_racks=[left_tiprack,left_tiprack_two])
    
    # calculation of 15 ml tube initial heights
    def calc_initial_15(vol):
        # 转换为微升计算,减去底部8mm的死区
        dh = -(15.9 - vol)*1000/(math.pi*(7.45**2)) - 8
        return dh
    
    Sb_intial= calc_initial_15(volume_of_sb_tube_in_ml)
    Toluene_initial= calc_initial_15(volume_of_tol_tube_in_ml)
    Cs_initial= calc_initial_15(Volume_of_Cs_tube_in_ml)
    
    heights = {
        'Sb':Sb_intial,
        'tol': Toluene_initial,
        'Cs': Cs_initial
    }
    
    # 追踪15ml试管的液面高度,接收单个体积值
    def update_height_15ml(reagent, transfer_vol):
        nonlocal heights
        # 计算体积对应的高度变化(微升转毫米)
        dh = transfer_vol/(math.pi*(7.45**2))
        # 更新高度,最低到-116mm(避免吸头碰到管底)
        new_height = heights[reagent] - dh
        heights[reagent] = max(new_height, -116)
    
    # 定义体积列表和对应的孔位
    volume_list = [150,225,263,282,290,295,297]
    well_list = ['B1','C1','D1','E1','F1','G1','H1']
    
    # 逐个处理移液操作
    for vol, well_name in zip(volume_list, well_list):
        update_height_15ml('tol', vol)
        current_height = heights['tol']
        right_pipette.pick_up_tip()
        right_pipette.transfer(vol, 
                               tol.top(current_height), 
                               Cs_OPA_plate.wells_by_name()[well_name], 
                               new_tip='never', 
                               touch_tip=True)
        right_pipette.drop_tip()

关键修改点

  • 将height_track15_tol改为update_height_15ml,接收单个移液体积,处理单个数值计算,避免数组操作
  • 用zip配对体积列表和孔位列表,逐个执行移液,符合单通道移液器的操作逻辑
  • 使用max(new_height, -116)替代条件判断,简化高度限制逻辑,确保高度始终是单个浮点数
  • 移除冗余的数组定义,让代码逻辑更清晰

内容的提问来源于stack exchange,提问作者Sheryl Sanchez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 09:17:08