[{"data":1,"prerenderedAt":2935},["ShallowReactive",2],{"navigation":3,"\u002Foperate\u002Fconcepts\u002Fparameter-sets":822,"\u002Foperate\u002Fconcepts\u002Fparameter-sets-surround":2930},[4,88,171,427,491,597,634,713],{"title":5,"path":6,"stem":7,"children":8,"page":42},"Get Started","\u002Fget-started\u002F","01.get-started",[9,13,17,43,47,51],{"title":10,"path":11,"stem":12},"Welcome to UniteLabs","\u002Fget-started\u002Fwelcome\u002F","01.get-started\u002F00.welcome",{"title":14,"path":15,"stem":16},"How it works","\u002Fget-started\u002Fhow-it-works\u002F","01.get-started\u002F01.how-it-works",{"title":18,"path":19,"stem":20,"children":21,"page":42},"Use Cases","\u002Fget-started\u002Fuse-cases\u002F","01.get-started\u002F02.use-cases",[22,26,30,34,38],{"title":23,"path":24,"stem":25},"Instrument Control","\u002Fget-started\u002Fuse-cases\u002Flow-level-instrument-control\u002F","01.get-started\u002F02.use-cases\u002F10.low-level-instrument-control",{"title":27,"path":28,"stem":29},"Multi-device Control","\u002Fget-started\u002Fuse-cases\u002Fmulti-device-control\u002F","01.get-started\u002F02.use-cases\u002F20.multi-device-control",{"title":31,"path":32,"stem":33},"Workflow Orchestration","\u002Fget-started\u002Fuse-cases\u002Fworkflow-orchestration\u002F","01.get-started\u002F02.use-cases\u002F30.workflow-orchestration",{"title":35,"path":36,"stem":37},"Custom Apps and LIMS Integration","\u002Fget-started\u002Fuse-cases\u002Fcustom-apps-lims\u002F","01.get-started\u002F02.use-cases\u002F40.custom-apps-lims",{"title":39,"path":40,"stem":41},"Scale and Fleet Management","\u002Fget-started\u002Fuse-cases\u002Fscale-and-fleet\u002F","01.get-started\u002F02.use-cases\u002F50.scale-and-fleet",false,{"title":44,"path":45,"stem":46},"Lab as Code","\u002Fget-started\u002Fwhy-code\u002F","01.get-started\u002F03.why-code",{"title":48,"path":49,"stem":50},"Self-Paced Setup Guide","\u002Fget-started\u002Fself-onboarding\u002F","01.get-started\u002F05.self-onboarding",{"title":52,"path":53,"stem":54,"children":55,"page":42},"Setup","\u002Fget-started\u002Fsetup\u002F","01.get-started\u002F20.setup",[56,60,64,68,72,76,80,84],{"title":57,"path":58,"stem":59},"Get access","\u002Fget-started\u002Fsetup\u002Fget-access\u002F","01.get-started\u002F20.setup\u002F00.get-access",{"title":61,"path":62,"stem":63},"GroundControl","\u002Fget-started\u002Fsetup\u002Fgroundcontrol\u002F","01.get-started\u002F20.setup\u002F10.groundcontrol",{"title":65,"path":66,"stem":67},"Set up your development machine","\u002Fget-started\u002Fsetup\u002Fdeveloper-machine\u002F","01.get-started\u002F20.setup\u002F20.developer-machine",{"title":69,"path":70,"stem":71},"SDK installation","\u002Fget-started\u002Fsetup\u002Fsdk-installation\u002F","01.get-started\u002F20.setup\u002F30.sdk-installation",{"title":73,"path":74,"stem":75},"Connect to Platform","\u002Fget-started\u002Fsetup\u002Fconnect-to-platform\u002F","01.get-started\u002F20.setup\u002F40.connect-to-platform",{"title":77,"path":78,"stem":79},"Multi-device Networking","\u002Fget-started\u002Fsetup\u002Fmultiple-devices\u002F","01.get-started\u002F20.setup\u002F45.multiple-devices",{"title":81,"path":82,"stem":83},"UniteLabs Desktop","\u002Fget-started\u002Fsetup\u002Funitelabs-desktop\u002F","01.get-started\u002F20.setup\u002F70.unitelabs-desktop",{"title":85,"path":86,"stem":87},"Network requirements","\u002Fget-started\u002Fsetup\u002Fnetwork-requirements\u002F","01.get-started\u002F20.setup\u002F90.network-requirements",{"title":89,"path":90,"stem":91,"children":92,"page":42},"Integrate","\u002Fintegrate\u002F","02.integrate",[93,97,101,126,155],{"title":94,"path":95,"stem":96},"What is a connector?","\u002Fintegrate\u002Fwhat-is-a-connector\u002F","02.integrate\u002F00.what-is-a-connector",{"title":98,"path":99,"stem":100},"Calling a Connector","\u002Fintegrate\u002Fcontrol-with-code\u002F","02.integrate\u002F05.control-with-code",{"title":102,"path":103,"stem":104,"children":105,"page":42},"Concepts","\u002Fintegrate\u002Fconcepts\u002F","02.integrate\u002F10.concepts",[106,110,114,118,122],{"title":107,"path":108,"stem":109},"Connector","\u002Fintegrate\u002Fconcepts\u002Fconnector\u002F","02.integrate\u002F10.concepts\u002F10.connector",{"title":111,"path":112,"stem":113},"Module","\u002Fintegrate\u002Fconcepts\u002Fmodule\u002F","02.integrate\u002F10.concepts\u002F20.module",{"title":115,"path":116,"stem":117},"Action","\u002Fintegrate\u002Fconcepts\u002Faction\u002F","02.integrate\u002F10.concepts\u002F30.action",{"title":119,"path":120,"stem":121},"Subscription","\u002Fintegrate\u002Fconcepts\u002Fsubscription\u002F","02.integrate\u002F10.concepts\u002F40.subscription",{"title":123,"path":124,"stem":125},"Device","\u002Fintegrate\u002Fconcepts\u002Fdevice\u002F","02.integrate\u002F10.concepts\u002F50.device",{"title":127,"path":128,"stem":129,"children":130,"page":42},"Connect a device","\u002Fintegrate\u002Fconnect-a-device\u002F","02.integrate\u002F20.connect-a-device",[131,135,139,143,147,151],{"title":132,"path":133,"stem":134},"Connector Configuration","\u002Fintegrate\u002Fconnect-a-device\u002Fconnector-configuration\u002F","02.integrate\u002F20.connect-a-device\u002F10.connector-configuration",{"title":136,"path":137,"stem":138},"With an executable","\u002Fintegrate\u002Fconnect-a-device\u002Fwith-an-executable\u002F","02.integrate\u002F20.connect-a-device\u002F20.with-an-executable",{"title":140,"path":141,"stem":142},"From source","\u002Fintegrate\u002Fconnect-a-device\u002Ffrom-source\u002F","02.integrate\u002F20.connect-a-device\u002F30.from-source",{"title":144,"path":145,"stem":146},"Build your own","\u002Fintegrate\u002Fconnect-a-device\u002Fbuild-yourself\u002F","02.integrate\u002F20.connect-a-device\u002F40.build-yourself",{"title":148,"path":149,"stem":150},"Headless install","\u002Fintegrate\u002Fconnect-a-device\u002Fheadless-install\u002F","02.integrate\u002F20.connect-a-device\u002F50.headless-install",{"title":152,"path":153,"stem":154},"Raspberry Pi","\u002Fintegrate\u002Fconnect-a-device\u002Fraspberry-pi\u002F","02.integrate\u002F20.connect-a-device\u002F55.raspberry-pi",{"title":156,"path":157,"stem":158,"children":159,"page":42},"Use a connector","\u002Fintegrate\u002Fuse-a-connector\u002F","02.integrate\u002F30.use-a-connector",[160,163,167],{"title":61,"path":161,"stem":162},"\u002Fintegrate\u002Fuse-a-connector\u002Fgroundcontrol\u002F","02.integrate\u002F30.use-a-connector\u002F10.groundcontrol",{"title":164,"path":165,"stem":166},"Platform","\u002Fintegrate\u002Fuse-a-connector\u002Fplatform\u002F","02.integrate\u002F30.use-a-connector\u002F20.platform",{"title":168,"path":169,"stem":170},"UniteLabs SDK & REST API","\u002Fintegrate\u002Fuse-a-connector\u002Fpython\u002F","02.integrate\u002F30.use-a-connector\u002F30.python",{"title":172,"path":173,"stem":174,"children":175,"page":42},"Operate","\u002Foperate\u002F","03.operate",[176,179,183,227,300],{"title":172,"path":177,"stem":178},"\u002Foperate\u002Foverview\u002F","03.operate\u002F00.overview",{"title":180,"path":181,"stem":182},"Your First Protocol","\u002Foperate\u002Fyour-first-protocol\u002F","03.operate\u002F05.your-first-protocol",{"title":102,"path":184,"stem":185,"children":186,"page":42},"\u002Foperate\u002Fconcepts\u002F","03.operate\u002F10.concepts",[187,191,195,199,203,207,211,215,219,223],{"title":188,"path":189,"stem":190},"Liquid Handling","\u002Foperate\u002Fconcepts\u002Fliquid-handling\u002F","03.operate\u002F10.concepts\u002F10.liquid-handling",{"title":192,"path":193,"stem":194},"Modules","\u002Foperate\u002Fconcepts\u002Fmodules\u002F","03.operate\u002F10.concepts\u002F20.modules",{"title":196,"path":197,"stem":198},"Deck","\u002Foperate\u002Fconcepts\u002Fdeck\u002F","03.operate\u002F10.concepts\u002F30.deck",{"title":200,"path":201,"stem":202},"Labware","\u002Foperate\u002Fconcepts\u002Flabware\u002F","03.operate\u002F10.concepts\u002F40.labware",{"title":204,"path":205,"stem":206},"Liquids","\u002Foperate\u002Fconcepts\u002Fliquids\u002F","03.operate\u002F10.concepts\u002F50.liquids",{"title":208,"path":209,"stem":210},"Liquid Classes","\u002Foperate\u002Fconcepts\u002Fliquid-classes\u002F","03.operate\u002F10.concepts\u002F60.liquid-classes",{"title":212,"path":213,"stem":214},"Parameter Sets","\u002Foperate\u002Fconcepts\u002Fparameter-sets\u002F","03.operate\u002F10.concepts\u002F65.parameter-sets",{"title":216,"path":217,"stem":218},"Tips and Tip Tracking","\u002Foperate\u002Fconcepts\u002Ftips\u002F","03.operate\u002F10.concepts\u002F70.tips",{"title":220,"path":221,"stem":222},"Simulation","\u002Foperate\u002Fconcepts\u002Fsimulation\u002F","03.operate\u002F10.concepts\u002F80.simulation",{"title":224,"path":225,"stem":226},"Error Handling","\u002Foperate\u002Fconcepts\u002Ferror-handling\u002F","03.operate\u002F10.concepts\u002F90.error-handling",{"title":228,"path":229,"stem":230,"children":231,"page":42},"Guides","\u002Foperate\u002Fguides\u002F","03.operate\u002F20.guides",[232,261,273,297],{"title":200,"path":233,"stem":234,"children":235},"\u002Foperate\u002Fguides\u002Flabware\u002F","03.operate\u002F20.guides\u002F10.labware\u002Findex",[236,237,241,245,249,253,257],{"title":200,"path":233,"stem":234},{"title":238,"path":239,"stem":240},"Standard Labware","\u002Foperate\u002Fguides\u002Flabware\u002Fstandard-labware\u002F","03.operate\u002F20.guides\u002F10.labware\u002F05.standard-labware",{"title":242,"path":243,"stem":244},"Plates","\u002Foperate\u002Fguides\u002Flabware\u002Fplates\u002F","03.operate\u002F20.guides\u002F10.labware\u002F10.plates",{"title":246,"path":247,"stem":248},"Tips and Tip Racks","\u002Foperate\u002Fguides\u002Flabware\u002Ftips-and-racks\u002F","03.operate\u002F20.guides\u002F10.labware\u002F20.tips-and-racks",{"title":250,"path":251,"stem":252},"Tubes and Tube Racks","\u002Foperate\u002Fguides\u002Flabware\u002Ftubes-and-tube-racks\u002F","03.operate\u002F20.guides\u002F10.labware\u002F30.tubes-and-tube-racks",{"title":254,"path":255,"stem":256},"Troughs","\u002Foperate\u002Fguides\u002Flabware\u002Ftroughs\u002F","03.operate\u002F20.guides\u002F10.labware\u002F35.troughs",{"title":258,"path":259,"stem":260},"Carriers and Adapters","\u002Foperate\u002Fguides\u002Flabware\u002Fcarriers-and-adapters\u002F","03.operate\u002F20.guides\u002F10.labware\u002F40.carriers-and-adapters",{"title":196,"path":262,"stem":263,"children":264,"page":42},"\u002Foperate\u002Fguides\u002Fdeck\u002F","03.operate\u002F20.guides\u002F20.deck",[265,269],{"title":266,"path":267,"stem":268},"Building a Deck","\u002Foperate\u002Fguides\u002Fdeck\u002Fbuilding-a-deck\u002F","03.operate\u002F20.guides\u002F20.deck\u002F10.building-a-deck",{"title":270,"path":271,"stem":272},"Save\u002FLoad a Deck","\u002Foperate\u002Fguides\u002Fdeck\u002Fsave-load-deck\u002F","03.operate\u002F20.guides\u002F20.deck\u002F20.save-load-deck",{"title":274,"path":275,"stem":276,"children":277,"page":42},"Pipetting","\u002Foperate\u002Fguides\u002Fpipetting\u002F","03.operate\u002F20.guides\u002F30.pipetting",[278,282,286,290,293],{"title":279,"path":280,"stem":281},"Basic Pipetting","\u002Foperate\u002Fguides\u002Fpipetting\u002Fbasic-pipetting\u002F","03.operate\u002F20.guides\u002F30.pipetting\u002F10.basic-pipetting",{"title":283,"path":284,"stem":285},"Advanced Pipetting","\u002Foperate\u002Fguides\u002Fpipetting\u002Fadvanced-pipetting\u002F","03.operate\u002F20.guides\u002F30.pipetting\u002F20.advanced-pipetting",{"title":287,"path":288,"stem":289},"Tip Handling","\u002Foperate\u002Fguides\u002Fpipetting\u002Ftip-handling\u002F","03.operate\u002F20.guides\u002F30.pipetting\u002F30.tip-handling",{"title":208,"path":291,"stem":292},"\u002Foperate\u002Fguides\u002Fpipetting\u002Fliquid-classes\u002F","03.operate\u002F20.guides\u002F30.pipetting\u002F40.liquid-classes",{"title":294,"path":295,"stem":296},"Labware Transport","\u002Foperate\u002Fguides\u002Fpipetting\u002Flabware-transport\u002F","03.operate\u002F20.guides\u002F30.pipetting\u002F50.labware-transport",{"title":220,"path":298,"stem":299},"\u002Foperate\u002Fguides\u002Fsimulation\u002F","03.operate\u002F20.guides\u002F40.simulation",{"title":301,"path":302,"stem":303,"children":304,"page":42},"Liquid Handler Guides","\u002Foperate\u002Fdevices\u002F","03.operate\u002F30.devices",[305,346,371,388,405],{"title":306,"path":307,"stem":308,"children":309,"page":42},"Hamilton STAR","\u002Foperate\u002Fdevices\u002Fhamilton-star\u002F","03.operate\u002F30.devices\u002F10.hamilton-star",[310,314,318,322,326,330,334,338,342],{"title":311,"path":312,"stem":313},"Positioning & Movement","\u002Foperate\u002Fdevices\u002Fhamilton-star\u002Fpositioning\u002F","03.operate\u002F30.devices\u002F10.hamilton-star\u002F10.positioning",{"title":315,"path":316,"stem":317},"Gripper Module","\u002Foperate\u002Fdevices\u002Fhamilton-star\u002Fcore-gripper\u002F","03.operate\u002F30.devices\u002F10.hamilton-star\u002F20.core-gripper",{"title":319,"path":320,"stem":321},"iSWAP Module","\u002Foperate\u002Fdevices\u002Fhamilton-star\u002Fiswap\u002F","03.operate\u002F30.devices\u002F10.hamilton-star\u002F30.iswap",{"title":323,"path":324,"stem":325},"Using TADM","\u002Foperate\u002Fdevices\u002Fhamilton-star\u002Ftadm\u002F","03.operate\u002F30.devices\u002F10.hamilton-star\u002F40.tadm",{"title":327,"path":328,"stem":329},"Autoload Module","\u002Foperate\u002Fdevices\u002Fhamilton-star\u002Fautoload\u002F","03.operate\u002F30.devices\u002F10.hamilton-star\u002F50.autoload",{"title":331,"path":332,"stem":333},"Waste Block","\u002Foperate\u002Fdevices\u002Fhamilton-star\u002Fwaste-block\u002F","03.operate\u002F30.devices\u002F10.hamilton-star\u002F60.waste-block",{"title":335,"path":336,"stem":337},"Complex Mixing","\u002Foperate\u002Fdevices\u002Fhamilton-star\u002Fcomplex-mixing\u002F","03.operate\u002F30.devices\u002F10.hamilton-star\u002F66.complex-mixing",{"title":339,"path":340,"stem":341},"Teaching Gripper Paddle Positions","\u002Foperate\u002Fdevices\u002Fhamilton-star\u002Fgripper-positions\u002F","03.operate\u002F30.devices\u002F10.hamilton-star\u002F70.gripper-positions",{"title":343,"path":344,"stem":345},"Training a Custom Deck Position With the iSWAP","\u002Foperate\u002Fdevices\u002Fhamilton-star\u002Fcustom-deck-position\u002F","03.operate\u002F30.devices\u002F10.hamilton-star\u002F75.custom-deck-position",{"title":347,"path":348,"stem":349,"children":350,"page":42},"Hamilton Vantage","\u002Foperate\u002Fdevices\u002Fhamilton-vantage\u002F","03.operate\u002F30.devices\u002F20.hamilton-vantage",[351,355,359,363,367],{"title":352,"path":353,"stem":354},"Waste Configuration","\u002Foperate\u002Fdevices\u002Fhamilton-vantage\u002Fwaste-configuration\u002F","03.operate\u002F30.devices\u002F20.hamilton-vantage\u002F05.waste-configuration",{"title":356,"path":357,"stem":358},"Covers and Lights","\u002Foperate\u002Fdevices\u002Fhamilton-vantage\u002Fcovers-and-lights\u002F","03.operate\u002F30.devices\u002F20.hamilton-vantage\u002F10.covers-and-lights",{"title":360,"path":361,"stem":362},"IDL Module","\u002Foperate\u002Fdevices\u002Fhamilton-vantage\u002Fidl\u002F","03.operate\u002F30.devices\u002F20.hamilton-vantage\u002F20.idl",{"title":364,"path":365,"stem":366},"IPG Module","\u002Foperate\u002Fdevices\u002Fhamilton-vantage\u002Fipg\u002F","03.operate\u002F30.devices\u002F20.hamilton-vantage\u002F30.ipg",{"title":368,"path":369,"stem":370},"XL Pipettes","\u002Foperate\u002Fdevices\u002Fhamilton-vantage\u002Fxl-channels\u002F","03.operate\u002F30.devices\u002F20.hamilton-vantage\u002F40.xl-channels",{"title":372,"path":373,"stem":374,"children":375,"page":42},"Agilent Bravo","\u002Foperate\u002Fdevices\u002Fagilent-bravo\u002F","03.operate\u002F30.devices\u002F30.agilent-bravo",[376,379,382,385],{"title":287,"path":377,"stem":378},"\u002Foperate\u002Fdevices\u002Fagilent-bravo\u002Ftip-handling\u002F","03.operate\u002F30.devices\u002F30.agilent-bravo\u002F10.tip-handling",{"title":279,"path":380,"stem":381},"\u002Foperate\u002Fdevices\u002Fagilent-bravo\u002Fbasic-pipetting\u002F","03.operate\u002F30.devices\u002F30.agilent-bravo\u002F20.basic-pipetting",{"title":208,"path":383,"stem":384},"\u002Foperate\u002Fdevices\u002Fagilent-bravo\u002Fliquid-classes\u002F","03.operate\u002F30.devices\u002F30.agilent-bravo\u002F25.liquid-classes",{"title":315,"path":386,"stem":387},"\u002Foperate\u002Fdevices\u002Fagilent-bravo\u002Fusing-the-gripper\u002F","03.operate\u002F30.devices\u002F30.agilent-bravo\u002F30.using-the-gripper",{"title":389,"path":390,"stem":391,"children":392,"page":42},"Tecan FluentControl","\u002Foperate\u002Fdevices\u002Ftecan-fluentcontrol\u002F","03.operate\u002F30.devices\u002F40.tecan-fluentcontrol",[393,397,401],{"title":394,"path":395,"stem":396},"Connect & Run a Method","\u002Foperate\u002Fdevices\u002Ftecan-fluentcontrol\u002Fconnect-and-run\u002F","03.operate\u002F30.devices\u002F40.tecan-fluentcontrol\u002F10.connect-and-run",{"title":398,"path":399,"stem":400},"Sending XML Commands","\u002Foperate\u002Fdevices\u002Ftecan-fluentcontrol\u002Fsending-xml-commands\u002F","03.operate\u002F30.devices\u002F40.tecan-fluentcontrol\u002F20.sending-xml-commands",{"title":402,"path":403,"stem":404},"Full Workflow Example","\u002Foperate\u002Fdevices\u002Ftecan-fluentcontrol\u002Ffull-workflow-example\u002F","03.operate\u002F30.devices\u002F40.tecan-fluentcontrol\u002F30.full-workflow-example",{"title":406,"path":407,"stem":408,"children":409,"page":42},"Tecan Freedom EVO","\u002Foperate\u002Fdevices\u002Ftecan-freedom-evo\u002F","03.operate\u002F30.devices\u002F50.tecan-freedom-evo",[410,414,417,420,424],{"title":411,"path":412,"stem":413},"Deck & Carriers","\u002Foperate\u002Fdevices\u002Ftecan-freedom-evo\u002Fdeck-and-carriers\u002F","03.operate\u002F30.devices\u002F50.tecan-freedom-evo\u002F10.deck-and-carriers",{"title":287,"path":415,"stem":416},"\u002Foperate\u002Fdevices\u002Ftecan-freedom-evo\u002Ftip-handling\u002F","03.operate\u002F30.devices\u002F50.tecan-freedom-evo\u002F20.tip-handling",{"title":279,"path":418,"stem":419},"\u002Foperate\u002Fdevices\u002Ftecan-freedom-evo\u002Fbasic-pipetting\u002F","03.operate\u002F30.devices\u002F50.tecan-freedom-evo\u002F30.basic-pipetting",{"title":421,"path":422,"stem":423},"Using the Gripper (RoMa)","\u002Foperate\u002Fdevices\u002Ftecan-freedom-evo\u002Fusing-the-gripper\u002F","03.operate\u002F30.devices\u002F50.tecan-freedom-evo\u002F40.using-the-gripper",{"title":208,"path":425,"stem":426},"\u002Foperate\u002Fdevices\u002Ftecan-freedom-evo\u002Fliquid-classes\u002F","03.operate\u002F30.devices\u002F50.tecan-freedom-evo\u002F50.liquid-classes",{"title":428,"path":429,"stem":430,"children":431,"page":42},"Device Guides","\u002Fdevice-guides\u002F","06.device-guides",[432,435,448,465,478],{"title":428,"path":433,"stem":434},"\u002Fdevice-guides\u002Foverview\u002F","06.device-guides\u002F00.overview",{"title":436,"path":437,"stem":438,"children":439,"page":42},"Incubation","\u002Fdevice-guides\u002Fincubation\u002F","06.device-guides\u002F20.incubation",[440,444],{"title":441,"path":442,"stem":443},"Inheco ODTC","\u002Fdevice-guides\u002Fincubation\u002Finheco-odtc\u002F","06.device-guides\u002F20.incubation\u002F10.inheco-odtc",{"title":445,"path":446,"stem":447},"Inheco SCILA","\u002Fdevice-guides\u002Fincubation\u002Finheco-scila\u002F","06.device-guides\u002F20.incubation\u002F20.inheco-scila",{"title":449,"path":450,"stem":451,"children":452,"page":42},"Heater-Shakers","\u002Fdevice-guides\u002Fheater-shakers\u002F","06.device-guides\u002F30.heater-shakers",[453,457,461],{"title":454,"path":455,"stem":456},"Inheco Thermoshake","\u002Fdevice-guides\u002Fheater-shakers\u002Finheco-thermoshake\u002F","06.device-guides\u002F30.heater-shakers\u002F10.inheco-thermoshake",{"title":458,"path":459,"stem":460},"QInstruments Bioshake","\u002Fdevice-guides\u002Fheater-shakers\u002Fqinstruments-bioshake\u002F","06.device-guides\u002F30.heater-shakers\u002F20.qinstruments-bioshake",{"title":462,"path":463,"stem":464},"QInstruments ColdPlate","\u002Fdevice-guides\u002Fheater-shakers\u002Fqinstruments-coldplate\u002F","06.device-guides\u002F30.heater-shakers\u002F30.qinstruments-coldplate",{"title":466,"path":467,"stem":468,"children":469,"page":42},"Readers","\u002Fdevice-guides\u002Freaders\u002F","06.device-guides\u002F40.readers",[470,474],{"title":471,"path":472,"stem":473},"Agilent Biotek Gen5","\u002Fdevice-guides\u002Freaders\u002Fbiotek-gen5\u002F","06.device-guides\u002F40.readers\u002F10.biotek-gen5",{"title":475,"path":476,"stem":477},"Biotek Synergy H1","\u002Fdevice-guides\u002Freaders\u002Fbiotek-synergy-h1\u002F","06.device-guides\u002F40.readers\u002F20.biotek-synergy-H1",{"title":479,"path":480,"stem":481,"children":482,"page":42},"Tilt & Turn","\u002Fdevice-guides\u002Ftilt-and-turn\u002F","06.device-guides\u002F50.tilt-and-turn",[483,487],{"title":484,"path":485,"stem":486},"TurnStation","\u002Fdevice-guides\u002Ftilt-and-turn\u002Fqinstruments-turnstation\u002F","06.device-guides\u002F50.tilt-and-turn\u002F10.qinstruments-turnstation",{"title":488,"path":489,"stem":490},"TiltStation","\u002Fdevice-guides\u002Ftilt-and-turn\u002Fqinstruments-tiltstation\u002F","06.device-guides\u002F50.tilt-and-turn\u002F20.qinstruments-tiltstation",{"title":492,"path":493,"stem":494,"children":495,"page":42},"Automate","\u002Fautomate\u002F","07.automate",[496,500,504,508,557],{"title":497,"path":498,"stem":499},"What is a workflow?","\u002Fautomate\u002Fwhat-is-a-workflow\u002F","07.automate\u002F00.what-is-a-workflow",{"title":501,"path":502,"stem":503},"Workflow template","\u002Fautomate\u002Fworkflow-template\u002F","07.automate\u002F05.workflow-template",{"title":505,"path":506,"stem":507},"Your First Workflow","\u002Fautomate\u002Fyour-first-workflow\u002F","07.automate\u002F08.your-first-workflow",{"title":102,"pages":509,"path":519,"stem":520,"children":521,"page":42},[510,511,512,513,514,515,516,517,518],"workflow","phase","step","runs","input","artifacts","logs","human-in-the-loop","error-handling","\u002Fautomate\u002Fconcepts\u002F","07.automate\u002F10.concepts",[522,526,530,534,538,542,546,550,554],{"title":523,"path":524,"stem":525},"Workflow","\u002Fautomate\u002Fconcepts\u002Fworkflow\u002F","07.automate\u002F10.concepts\u002F10.workflow",{"title":527,"path":528,"stem":529},"Phase","\u002Fautomate\u002Fconcepts\u002Fphase\u002F","07.automate\u002F10.concepts\u002F20.phase",{"title":531,"path":532,"stem":533},"Step","\u002Fautomate\u002Fconcepts\u002Fstep\u002F","07.automate\u002F10.concepts\u002F30.step",{"title":535,"path":536,"stem":537},"Runs","\u002Fautomate\u002Fconcepts\u002Fruns\u002F","07.automate\u002F10.concepts\u002F40.runs",{"title":539,"path":540,"stem":541},"Input","\u002Fautomate\u002Fconcepts\u002Finput\u002F","07.automate\u002F10.concepts\u002F50.input",{"title":543,"path":544,"stem":545},"Artifacts","\u002Fautomate\u002Fconcepts\u002Fartifacts\u002F","07.automate\u002F10.concepts\u002F60.artifacts",{"title":547,"path":548,"stem":549},"Logs","\u002Fautomate\u002Fconcepts\u002Flogs\u002F","07.automate\u002F10.concepts\u002F70.logs",{"title":551,"path":552,"stem":553},"Human in the Loop","\u002Fautomate\u002Fconcepts\u002Fhuman-in-the-loop\u002F","07.automate\u002F10.concepts\u002F80.human-in-the-loop",{"title":224,"path":555,"stem":556},"\u002Fautomate\u002Fconcepts\u002Ferror-handling\u002F","07.automate\u002F10.concepts\u002F90.error-handling",{"title":228,"path":558,"stem":559,"children":560,"page":42},"\u002Fautomate\u002Fguides\u002F","07.automate\u002F25.guides",[561,565,569,573,577,581,585,589,593],{"title":562,"path":563,"stem":564},"Deploy a workflow","\u002Fautomate\u002Fguides\u002Fdeploy-a-workflow\u002F","07.automate\u002F25.guides\u002F30.deploy-a-workflow",{"title":566,"path":567,"stem":568},"Run a workflow","\u002Fautomate\u002Fguides\u002Frun-a-workflow\u002F","07.automate\u002F25.guides\u002F35.run-a-workflow",{"title":570,"path":571,"stem":572},"CI\u002FCD for workflows","\u002Fautomate\u002Fguides\u002Fcicd-for-workflows\u002F","07.automate\u002F25.guides\u002F40.cicd-for-workflows",{"title":574,"path":575,"stem":576},"HITL basics","\u002Fautomate\u002Fguides\u002Fbasic-hitl\u002F","07.automate\u002F25.guides\u002F50.basic-hitl",{"title":578,"path":579,"stem":580},"Slack notifications and operator confirmation","\u002Fautomate\u002Fguides\u002Fslack-notifications\u002F","07.automate\u002F25.guides\u002F52.slack-notifications",{"title":582,"path":583,"stem":584},"Typed operator inputs","\u002Fautomate\u002Fguides\u002Ftyped-operator-inputs\u002F","07.automate\u002F25.guides\u002F55.typed-operator-inputs",{"title":586,"path":587,"stem":588},"Error recovery","\u002Fautomate\u002Fguides\u002Fbasic-error-handling\u002F","07.automate\u002F25.guides\u002F60.basic-error-handling",{"title":590,"path":591,"stem":592},"Advanced error handling","\u002Fautomate\u002Fguides\u002Fadvanced-error-handling\u002F","07.automate\u002F25.guides\u002F70.advanced-error-handling",{"title":594,"path":595,"stem":596},"Workflows REST API","\u002Fautomate\u002Fguides\u002Fworkflows-api\u002F","07.automate\u002F25.guides\u002F80.workflows-api",{"title":598,"path":599,"stem":600,"children":601,"page":42},"Observe","\u002Fobserve\u002F","08.observe",[602,606,622],{"title":603,"path":604,"stem":605},"Overview","\u002Fobserve\u002Foverview\u002F","08.observe\u002F10.overview",{"title":102,"path":607,"stem":608,"children":609,"page":42},"\u002Fobserve\u002Fconcepts\u002F","08.observe\u002F20.concepts",[610,614,618],{"title":611,"path":612,"stem":613},"Object Storage","\u002Fobserve\u002Fconcepts\u002Fstorage\u002F","08.observe\u002F20.concepts\u002F10.storage",{"title":615,"path":616,"stem":617},"Secrets","\u002Fobserve\u002Fconcepts\u002Fsecrets\u002F","08.observe\u002F20.concepts\u002F20.secrets",{"title":619,"path":620,"stem":621},"Data sources","\u002Fobserve\u002Fconcepts\u002Fdata-sources\u002F","08.observe\u002F20.concepts\u002F30.data-sources",{"title":228,"path":623,"stem":624,"children":625,"page":42},"\u002Fobserve\u002Fguides\u002F","08.observe\u002F30.guides",[626,630],{"title":627,"path":628,"stem":629},"File System Connector","\u002Fobserve\u002Fguides\u002Ffilesystem-connector\u002F","08.observe\u002F30.guides\u002F10.filesystem-connector",{"title":631,"path":632,"stem":633},"Building an ETL","\u002Fobserve\u002Fguides\u002Fbuilding-an-etl\u002F","08.observe\u002F30.guides\u002F20.building-an-etl",{"title":635,"path":636,"stem":637,"children":638,"page":42},"Technical Reference","\u002Ftechnical-reference\u002F","10.technical-reference",[639,643,647,659,670,681,691,702],{"title":640,"path":641,"stem":642},"Introduction","\u002Ftechnical-reference\u002Fplatform-blueprint\u002F","10.technical-reference\u002F00.platform-blueprint",{"title":644,"path":645,"stem":646},"REST API","\u002Ftechnical-reference\u002Frest-api\u002F","10.technical-reference\u002F01.rest-api",{"title":61,"path":648,"stem":649,"children":650,"page":42},"\u002Ftechnical-reference\u002Fgroundcontrol\u002F","10.technical-reference\u002F10.groundcontrol",[651,655],{"title":652,"path":653,"stem":654},"Install & Setup","\u002Ftechnical-reference\u002Fgroundcontrol\u002Finstall\u002F","10.technical-reference\u002F10.groundcontrol\u002F10.install",{"title":656,"path":657,"stem":658},"Changelog","\u002Ftechnical-reference\u002Fgroundcontrol\u002Fchangelog\u002F","10.technical-reference\u002F10.groundcontrol\u002F20.changelog",{"title":660,"path":661,"stem":662,"children":663,"page":42},"UniteLabs SDK","\u002Ftechnical-reference\u002Fpython-sdk\u002F","10.technical-reference\u002F20.python-sdk",[664,667],{"title":652,"path":665,"stem":666},"\u002Ftechnical-reference\u002Fpython-sdk\u002Finstall\u002F","10.technical-reference\u002F20.python-sdk\u002F10.install",{"title":656,"path":668,"stem":669},"\u002Ftechnical-reference\u002Fpython-sdk\u002Fchangelog\u002F","10.technical-reference\u002F20.python-sdk\u002F20.changelog",{"title":671,"path":672,"stem":673,"children":674,"page":42},"Liquid Handling SDK","\u002Ftechnical-reference\u002Fpython-liquid-handling-sdk\u002F","10.technical-reference\u002F30.python-liquid-handling-sdk",[675,678],{"title":652,"path":676,"stem":677},"\u002Ftechnical-reference\u002Fpython-liquid-handling-sdk\u002Finstall\u002F","10.technical-reference\u002F30.python-liquid-handling-sdk\u002F10.install",{"title":656,"path":679,"stem":680},"\u002Ftechnical-reference\u002Fpython-liquid-handling-sdk\u002Fchangelog\u002F","10.technical-reference\u002F30.python-liquid-handling-sdk\u002F20.changelog",{"title":200,"path":682,"stem":683,"children":684,"page":42},"\u002Ftechnical-reference\u002Flabware\u002F","10.technical-reference\u002F40.labware",[685,688],{"title":652,"path":686,"stem":687},"\u002Ftechnical-reference\u002Flabware\u002Finstall\u002F","10.technical-reference\u002F40.labware\u002F10.install",{"title":656,"path":689,"stem":690},"\u002Ftechnical-reference\u002Flabware\u002Fchangelog\u002F","10.technical-reference\u002F40.labware\u002F20.changelog",{"title":692,"path":693,"stem":694,"children":695,"page":42},"Python Omnibus","\u002Ftechnical-reference\u002Fpython-omnibus\u002F","10.technical-reference\u002F50.python-omnibus",[696,699],{"title":652,"path":697,"stem":698},"\u002Ftechnical-reference\u002Fpython-omnibus\u002Finstall\u002F","10.technical-reference\u002F50.python-omnibus\u002F10.install",{"title":656,"path":700,"stem":701},"\u002Ftechnical-reference\u002Fpython-omnibus\u002Fchangelog\u002F","10.technical-reference\u002F50.python-omnibus\u002F20.changelog",{"title":703,"path":704,"stem":705,"children":706,"page":42},"Python CDK","\u002Ftechnical-reference\u002Fpython-cdk\u002F","10.technical-reference\u002F60.python-cdk",[707,710],{"title":652,"path":708,"stem":709},"\u002Ftechnical-reference\u002Fpython-cdk\u002Finstall\u002F","10.technical-reference\u002F60.python-cdk\u002F10.install",{"title":656,"path":711,"stem":712},"\u002Ftechnical-reference\u002Fpython-cdk\u002Fchangelog\u002F","10.technical-reference\u002F60.python-cdk\u002F20.changelog",{"title":714,"path":715,"stem":716,"children":717},"Connector Development (CDK)","\u002Fconnector-development\u002F","20.connector-development",[718,720,740,773,781,816],{"title":714,"path":715,"stem":719},"20.connector-development\u002Findex",{"title":721,"path":722,"stem":723,"children":724,"page":42},"Getting Started","\u002Fconnector-development\u002Fgetting-started\u002F","20.connector-development\u002F10.getting-started",[725,728,732,736],{"title":603,"path":726,"stem":727},"\u002Fconnector-development\u002Fgetting-started\u002Foverview\u002F","20.connector-development\u002F10.getting-started\u002F10.overview",{"title":729,"path":730,"stem":731},"What's new","\u002Fconnector-development\u002Fgetting-started\u002Fwhats-new\u002F","20.connector-development\u002F10.getting-started\u002F20.whats-new",{"title":733,"path":734,"stem":735},"Installation","\u002Fconnector-development\u002Fgetting-started\u002Finstallation\u002F","20.connector-development\u002F10.getting-started\u002F30.installation",{"title":737,"path":738,"stem":739},"Contributing","\u002Fconnector-development\u002Fgetting-started\u002Fcontributing\u002F","20.connector-development\u002F10.getting-started\u002F40.contributing",{"title":741,"path":742,"stem":743,"children":744,"page":42},"Tutorial","\u002Fconnector-development\u002Ftutorial\u002F","20.connector-development\u002F20.tutorial",[745,749,753,757,761,765,769],{"title":746,"path":747,"stem":748},"Walkthrough","\u002Fconnector-development\u002Ftutorial\u002Fwalkthrough\u002F","20.connector-development\u002F20.tutorial\u002F00.walkthrough",{"title":750,"path":751,"stem":752},"SiLA Endpoints","\u002Fconnector-development\u002Ftutorial\u002Fsila-endpoints\u002F","20.connector-development\u002F20.tutorial\u002F10.sila-endpoints",{"title":754,"path":755,"stem":756},"Data Endpoints","\u002Fconnector-development\u002Ftutorial\u002Fdata-endpoints\u002F","20.connector-development\u002F20.tutorial\u002F20.data-endpoints",{"title":758,"path":759,"stem":760},"Controls","\u002Fconnector-development\u002Ftutorial\u002Fcontrols\u002F","20.connector-development\u002F20.tutorial\u002F30.controls",{"title":762,"path":763,"stem":764},"SiLA Data Types","\u002Fconnector-development\u002Ftutorial\u002Fdata-types\u002F","20.connector-development\u002F20.tutorial\u002F40.data-types",{"title":766,"path":767,"stem":768},"Feature","\u002Fconnector-development\u002Ftutorial\u002Fconnector-structure\u002F","20.connector-development\u002F20.tutorial\u002F70.connector-structure",{"title":770,"path":771,"stem":772},"Hardware Communication","\u002Fconnector-development\u002Ftutorial\u002Fhardware-communication\u002F","20.connector-development\u002F20.tutorial\u002F90.hardware-communication",{"title":102,"path":774,"stem":775,"children":776,"page":42},"\u002Fconnector-development\u002Fconcepts\u002F","20.connector-development\u002F30.concepts",[777],{"title":778,"path":779,"stem":780},"SiLA","\u002Fconnector-development\u002Fconcepts\u002Fsila\u002F","20.connector-development\u002F30.concepts\u002Fsila",{"title":228,"path":782,"stem":783,"children":784,"page":42},"\u002Fconnector-development\u002Fguides\u002F","20.connector-development\u002F40.guides",[785,789,793,797,801,805,808,812],{"title":786,"path":787,"stem":788},"Configuration","\u002Fconnector-development\u002Fguides\u002Fconfiguration\u002F","20.connector-development\u002F40.guides\u002F20.configuration",{"title":790,"path":791,"stem":792},"Logging","\u002Fconnector-development\u002Fguides\u002Flogging\u002F","20.connector-development\u002F40.guides\u002F21.logging",{"title":794,"path":795,"stem":796},"Deployment","\u002Fconnector-development\u002Fguides\u002Fdeployment\u002F","20.connector-development\u002F40.guides\u002F30.deployment",{"title":798,"path":799,"stem":800},"Security","\u002Fconnector-development\u002Fguides\u002Fsecurity\u002F","20.connector-development\u002F40.guides\u002F40.security",{"title":802,"path":803,"stem":804},"Subscriptions","\u002Fconnector-development\u002Fguides\u002Fsubscriptions\u002F","20.connector-development\u002F40.guides\u002F45.subscriptions",{"title":224,"path":806,"stem":807},"\u002Fconnector-development\u002Fguides\u002Ferror-handling\u002F","20.connector-development\u002F40.guides\u002F50.error-handling",{"title":809,"path":810,"stem":811},"Serial Troubleshooting","\u002Fconnector-development\u002Fguides\u002Fserial-troubleshooting\u002F","20.connector-development\u002F40.guides\u002F70.serial-troubleshooting",{"title":813,"path":814,"stem":815},"Testing","\u002Fconnector-development\u002Fguides\u002Ftesting\u002F","20.connector-development\u002F40.guides\u002F80.testing",{"title":817,"path":818,"stem":819,"children":820},"References","\u002Fconnector-development\u002Freference\u002F","20.connector-development\u002F50.reference\u002Findex",[821],{"title":817,"path":818,"stem":819},{"id":823,"title":212,"body":824,"description":2923,"extension":2924,"links":2925,"meta":2926,"navigation":925,"path":2927,"seo":2928,"stem":214,"__hash__":2929},"docs\u002F03.operate\u002F10.concepts\u002F65.parameter-sets.md",{"type":825,"value":826,"toc":2899},"minimark",[827,831,854,859,876,879,1031,1062,1066,1076,1084,1094,1109,1117,1122,1172,1175,1348,1351,1356,1362,1400,1406,1409,1415,1419,1429,1480,1486,1492,1500,1516,1522,1579,1583,1586,1590,1593,1695,1698,1702,1705,1776,1779,1783,1789,1839,1842,1849,1865,1932,1944,1954,1975,1982,1987,2404,2421,2431,2435,2446,2526,2533,2638,2642,2645,2697,2711,2792,2800,2804,2865,2869,2895],[828,829,830],"p",{},"A parameter set is the pipetting recipe for a single step — how much, how deep, how fast, with which liquid class — expressed as a Python dataclass instead of a pile of keyword arguments. It exists so you can write the recipe once, keep it in version control, and hand the same object to a Hamilton MicrolabSTAR, a Tecan Freedom EVO, or an Agilent Bravo.",[828,832,833,834,838,839,842,843,846,847,846,850,853],{},"The device-independent sets ",[835,836,837],"code",{},"AspirateParameterSet"," and ",[835,840,841],{},"DispenseParameterSet"," describe what should happen. Each device has its own subclass — ",[835,844,845],{},"CoRe96AspirateParameterSet",", ",[835,848,849],{},"MCAAspirateParameterSet",[835,851,852],{},"BravoAspirateParameterSet"," — that adds the fields only that hardware has. When you pass a generic set to a pipetting method, the method converts it to its own subclass and rejects anything the hardware cannot express, rather than silently dropping it.",[855,856,858],"h2",{"id":857},"every-field-is-optional","Every field is optional",[828,860,861,864,865,867,868,871,872,875],{},[835,862,863],{},"MISSING"," is the default for every field. A ",[835,866,863],{}," field is not \"zero\" — it means \"decide this from the deck state at run time\". ",[835,869,870],{},"volume=MISSING"," resolves to the smaller of the tip's free volume and the source's available volume; ",[835,873,874],{},"liquid_class=MISSING"," resolves to the best match for the mounted tip and the tracked liquid.",[828,877,878],{},"That is what makes one recipe portable. You pin the values that must not drift and leave the rest to the device.",[880,881,886],"pre",{"className":882,"code":883,"language":884,"meta":885,"style":885},"language-python shiki shiki-themes github-light-high-contrast github-light-high-contrast github-dark-default","from unitelabs.liquid_handling import AspirateParameterSet, AspiratePipetteMode\nfrom unitelabs.labware import Vector\n\ntransfer = AspirateParameterSet(\n    volume=100,\n    pipette_mode=AspiratePipetteMode.SURFACE,\n    liquid_offset=1.0,\n    offset=Vector(x=0.5, y=0.5, z=0),\n)\n","python","",[835,887,888,907,920,927,939,955,971,984,1025],{"__ignoreMap":885},[889,890,893,897,901,904],"span",{"class":891,"line":892},"line",1,[889,894,896],{"class":895},"sxkbv","from",[889,898,900],{"class":899},"sc-9e"," unitelabs.liquid_handling ",[889,902,903],{"class":895},"import",[889,905,906],{"class":899}," AspirateParameterSet, AspiratePipetteMode\n",[889,908,910,912,915,917],{"class":891,"line":909},2,[889,911,896],{"class":895},[889,913,914],{"class":899}," unitelabs.labware ",[889,916,903],{"class":895},[889,918,919],{"class":899}," Vector\n",[889,921,923],{"class":891,"line":922},3,[889,924,926],{"emptyLinePlaceholder":925},true,"\n",[889,928,930,933,936],{"class":891,"line":929},4,[889,931,932],{"class":899},"transfer ",[889,934,935],{"class":895},"=",[889,937,938],{"class":899}," AspirateParameterSet(\n",[889,940,942,946,948,952],{"class":891,"line":941},5,[889,943,945],{"class":944},"sNqAu","    volume",[889,947,935],{"class":895},[889,949,951],{"class":950},"sOiAX","100",[889,953,954],{"class":899},",\n",[889,956,958,961,963,966,969],{"class":891,"line":957},6,[889,959,960],{"class":944},"    pipette_mode",[889,962,935],{"class":895},[889,964,965],{"class":899},"AspiratePipetteMode.",[889,967,968],{"class":950},"SURFACE",[889,970,954],{"class":899},[889,972,974,977,979,982],{"class":891,"line":973},7,[889,975,976],{"class":944},"    liquid_offset",[889,978,935],{"class":895},[889,980,981],{"class":950},"1.0",[889,983,954],{"class":899},[889,985,987,990,992,995,998,1000,1003,1005,1008,1010,1012,1014,1017,1019,1022],{"class":891,"line":986},8,[889,988,989],{"class":944},"    offset",[889,991,935],{"class":895},[889,993,994],{"class":899},"Vector(",[889,996,997],{"class":944},"x",[889,999,935],{"class":895},[889,1001,1002],{"class":950},"0.5",[889,1004,846],{"class":899},[889,1006,1007],{"class":944},"y",[889,1009,935],{"class":895},[889,1011,1002],{"class":950},[889,1013,846],{"class":899},[889,1015,1016],{"class":944},"z",[889,1018,935],{"class":895},[889,1020,1021],{"class":950},"0",[889,1023,1024],{"class":899},"),\n",[889,1026,1028],{"class":891,"line":1027},9,[889,1029,1030],{"class":899},")\n",[1032,1033,1036],"callout",{"color":1034,"icon":1035},"warning","i-heroicons-exclamation-triangle",[828,1037,1038,1039,1042,1043,1046,1047,1050,1051,838,1054,1057,1058,1061],{},"Use ",[835,1040,1041],{},"AspiratePipetteMode"," on an aspirate set and ",[835,1044,1045],{},"DispensePipetteMode"," on a dispense set. The base ",[835,1048,1049],{},"PipetteMode"," enum is accepted by the constructor but is not a member of either narrowed type, so ",[835,1052,1053],{},"dumps()",[835,1055,1056],{},"adopt()"," fail on it later with a ",[835,1059,1060],{},"TypeError",".",[855,1063,1065],{"id":1064},"the-four-stages","The four stages",[828,1067,1068,1069,838,1072,1075],{},"Every ",[835,1070,1071],{},"aspirate",[835,1073,1074],{},"dispense"," runs the same pipeline. Understanding where a call failed tells you what kind of problem you have.",[880,1077,1082],{"className":1078,"code":1080,"language":1081},[1079],"language-text","adopt          validate         compile          apply\n  │              │                │                │\ngeneric set    is this safe    device wire     update tracked\n→ device set   on this deck?   parameters      volumes\n  │              │                │                │\nValueError:    ValueError:     dict sent to    tips and wells\nfield not      warnings from   api.aspirate()  reflect the move\nrepresentable  the resolvers\n","text",[835,1083,1080],{"__ignoreMap":885},[828,1085,1086,1089,1090,1093],{},[835,1087,1088],{},"show_defaults"," is the introspection tool alongside this pipeline: it runs the same resolvers as ",[835,1091,1092],{},"compile"," but returns a parameter set instead of a wire dictionary, so you can see what the device decided.",[828,1095,1096,1097,1100,1101,1104,1105,1108],{},"The examples below use a ",[835,1098,1099],{},"Standard96Plate"," half-filled with water (150 µL per well, ~3.94 mm liquid height) on both a ",[835,1102,1103],{},"MicrolabSTARMock"," CO-RE 96 head with 300 µL tips and a ",[835,1106,1107],{},"TecanFreedomEvoMock"," MCA96 head with 200 µL tips.",[855,1110,1112,1113,1116],{"id":1111},"stage-1-adopt-does-this-device-have-these-knobs","Stage 1 — ",[835,1114,1115],{},"adopt",": does this device have these knobs?",[828,1118,1119,1121],{},[835,1120,1115],{}," is a serialization round trip: the source set is dumped to a dictionary and loaded into the target class. Fields with the same name and a compatible type carry over; fields the target does not declare raise. Unset fields stay unset, so the target's own defaulting still applies.",[880,1123,1125],{"className":882,"code":1124,"language":884,"meta":885,"style":885},"from unitelabs.liquid_handling.hamilton.modules.core96 import CoRe96AspirateParameterSet\nfrom unitelabs.liquid_handling.tecan.modules import MCAAspirateParameterSet\n\nCoRe96AspirateParameterSet.adopt(transfer)   # → CoRe96AspirateParameterSet\nMCAAspirateParameterSet.adopt(transfer)      # → MCAAspirateParameterSet\n",[835,1126,1127,1139,1151,1155,1164],{"__ignoreMap":885},[889,1128,1129,1131,1134,1136],{"class":891,"line":892},[889,1130,896],{"class":895},[889,1132,1133],{"class":899}," unitelabs.liquid_handling.hamilton.modules.core96 ",[889,1135,903],{"class":895},[889,1137,1138],{"class":899}," CoRe96AspirateParameterSet\n",[889,1140,1141,1143,1146,1148],{"class":891,"line":909},[889,1142,896],{"class":895},[889,1144,1145],{"class":899}," unitelabs.liquid_handling.tecan.modules ",[889,1147,903],{"class":895},[889,1149,1150],{"class":899}," MCAAspirateParameterSet\n",[889,1152,1153],{"class":891,"line":922},[889,1154,926],{"emptyLinePlaceholder":925},[889,1156,1157,1160],{"class":891,"line":929},[889,1158,1159],{"class":899},"CoRe96AspirateParameterSet.adopt(transfer)   ",[889,1161,1163],{"class":1162},"sIsDC","# → CoRe96AspirateParameterSet\n",[889,1165,1166,1169],{"class":891,"line":941},[889,1167,1168],{"class":899},"MCAAspirateParameterSet.adopt(transfer)      ",[889,1170,1171],{"class":1162},"# → MCAAspirateParameterSet\n",[828,1173,1174],{},"Both succeed, because every device set is a strict superset of the generic set:",[1176,1177,1178,1201],"table",{},[1179,1180,1181],"thead",{},[1182,1183,1184,1188,1192,1195,1198],"tr",{},[1185,1186,1187],"th",{},"Field",[1185,1189,1191],{"align":1190},"center","Generic",[1185,1193,1194],{"align":1190},"CO-RE 96",[1185,1196,1197],{"align":1190},"MCA96",[1185,1199,1200],{"align":1190},"Bravo",[1202,1203,1204,1242,1260,1275,1293,1309,1324],"tbody",{},[1182,1205,1206,1233,1236,1238,1240],{},[1207,1208,1209,846,1212,846,1215,846,1218,846,1221,846,1224,846,1227,846,1230],"td",{},[835,1210,1211],{},"pipette_mode",[835,1213,1214],{},"liquid_offset",[835,1216,1217],{},"follow_liquid",[835,1219,1220],{},"volume",[835,1222,1223],{},"liquid_class",[835,1225,1226],{},"offset",[835,1228,1229],{},"pull_out_distance",[835,1231,1232],{},"end_z_offset",[1207,1234,1235],{"align":1190},"✓",[1207,1237,1235],{"align":1190},[1207,1239,1235],{"align":1190},[1207,1241,1235],{"align":1190},[1182,1243,1244,1252,1254,1256,1258],{},[1207,1245,1246,846,1249],{},[835,1247,1248],{},"min_traverse_height",[835,1250,1251],{},"mixing",[1207,1253],{"align":1190},[1207,1255,1235],{"align":1190},[1207,1257,1235],{"align":1190},[1207,1259,1235],{"align":1190},[1182,1261,1262,1267,1269,1271,1273],{},[1207,1263,1264],{},[835,1265,1266],{},"well_offset",[1207,1268],{"align":1190},[1207,1270,1235],{"align":1190},[1207,1272],{"align":1190},[1207,1274,1235],{"align":1190},[1182,1276,1277,1285,1287,1289,1291],{},[1207,1278,1279,846,1282],{},[835,1280,1281],{},"lld_mode",[835,1283,1284],{},"tadm",[1207,1286],{"align":1190},[1207,1288,1235],{"align":1190},[1207,1290],{"align":1190},[1207,1292],{"align":1190},[1182,1294,1295,1300,1302,1305,1307],{},[1207,1296,1297],{},[835,1298,1299],{},"touch_side",[1207,1301],{"align":1190},[1207,1303,1304],{"align":1190},"✓ (dispense)",[1207,1306,1304],{"align":1190},[1207,1308,1304],{"align":1190},[1182,1310,1311,1316,1318,1320,1322],{},[1207,1312,1313],{},[835,1314,1315],{},"touch_side_direction",[1207,1317],{"align":1190},[1207,1319],{"align":1190},[1207,1321,1304],{"align":1190},[1207,1323],{"align":1190},[1182,1325,1326,1340,1342,1344,1346],{},[1207,1327,1328,846,1331,846,1334,846,1337],{},[835,1329,1330],{},"velocity",[835,1332,1333],{},"start_z_position",[835,1335,1336],{},"min_z_position",[835,1338,1339],{},"touch_tip_*",[1207,1341],{"align":1190},[1207,1343],{"align":1190},[1207,1345],{"align":1190},[1207,1347,1235],{"align":1190},[828,1349,1350],{},"Generic → device therefore always adopts. Device → device only adopts when the source left the target's missing fields unset.",[1352,1353,1355],"h3",{"id":1354},"failure-the-target-has-no-such-field","Failure: the target has no such field",[828,1357,1358,1359,1361],{},"The CO-RE 96 head has capacitive liquid-level detection; the MCA96 has none. A set that pins ",[835,1360,1281],{}," cannot be honoured on the EVO, so it is refused instead of quietly losing the safety behaviour you asked for.",[880,1363,1365],{"className":882,"code":1364,"language":884,"meta":885,"style":885},"star_set = CoRe96AspirateParameterSet(volume=50, lld_mode=True)\nMCAAspirateParameterSet.adopt(star_set)\n",[835,1366,1367,1395],{"__ignoreMap":885},[889,1368,1369,1372,1374,1377,1379,1381,1384,1386,1388,1390,1393],{"class":891,"line":892},[889,1370,1371],{"class":899},"star_set ",[889,1373,935],{"class":895},[889,1375,1376],{"class":899}," CoRe96AspirateParameterSet(",[889,1378,1220],{"class":944},[889,1380,935],{"class":895},[889,1382,1383],{"class":950},"50",[889,1385,846],{"class":899},[889,1387,1281],{"class":944},[889,1389,935],{"class":895},[889,1391,1392],{"class":950},"True",[889,1394,1030],{"class":899},[889,1396,1397],{"class":891,"line":909},[889,1398,1399],{"class":899},"MCAAspirateParameterSet.adopt(star_set)\n",[880,1401,1404],{"className":1402,"code":1403,"language":1081},[1079],"ValueError: Cannot adopt CoRe96AspirateParameterSet as MCAAspirateParameterSet:\nlld_mode: Unknown field.\n",[835,1405,1403],{"__ignoreMap":885},[828,1407,1408],{},"It fails in the other direction too — the MCA96 can pick the compass direction of its tip touch, the CO-RE 96 cannot:",[880,1410,1413],{"className":1411,"code":1412,"language":1081},[1079],"ValueError: Cannot adopt MCADispenseParameterSet as CoRe96DispenseParameterSet:\ntouch_side_direction: Unknown field.\n",[835,1414,1412],{"__ignoreMap":885},[1352,1416,1418],{"id":1417},"failure-the-liquid-class-belongs-to-another-vendor","Failure: the liquid class belongs to another vendor",[828,1420,1421,1422,1425,1426,1428],{},"Liquid classes are not portable — Hamilton models pipetting as plunger flow rates, the EVO as plunger speeds plus air gaps (see ",[1423,1424,208],"a",{"href":209},"). Each device set narrows the ",[835,1427,1223],{}," field to its own base class, so a foreign class is caught at adoption:",[880,1430,1432],{"className":882,"code":1431,"language":884,"meta":885,"style":885},"from unitelabs.labware.tecan import EvoLiquidClass\n\nevo_set = MCAAspirateParameterSet(volume=50, liquid_class=EvoLiquidClass())\nCoRe96AspirateParameterSet.adopt(evo_set)\n",[835,1433,1434,1446,1450,1475],{"__ignoreMap":885},[889,1435,1436,1438,1441,1443],{"class":891,"line":892},[889,1437,896],{"class":895},[889,1439,1440],{"class":899}," unitelabs.labware.tecan ",[889,1442,903],{"class":895},[889,1444,1445],{"class":899}," EvoLiquidClass\n",[889,1447,1448],{"class":891,"line":909},[889,1449,926],{"emptyLinePlaceholder":925},[889,1451,1452,1455,1457,1460,1462,1464,1466,1468,1470,1472],{"class":891,"line":922},[889,1453,1454],{"class":899},"evo_set ",[889,1456,935],{"class":895},[889,1458,1459],{"class":899}," MCAAspirateParameterSet(",[889,1461,1220],{"class":944},[889,1463,935],{"class":895},[889,1465,1383],{"class":950},[889,1467,846],{"class":899},[889,1469,1223],{"class":944},[889,1471,935],{"class":895},[889,1473,1474],{"class":899},"EvoLiquidClass())\n",[889,1476,1477],{"class":891,"line":929},[889,1478,1479],{"class":899},"CoRe96AspirateParameterSet.adopt(evo_set)\n",[880,1481,1484],{"className":1482,"code":1483,"language":1081},[1079],"ValueError: Cannot adopt MCAAspirateParameterSet as CoRe96AspirateParameterSet:\nliquid_class: Invalid type: EvoLiquidClass. No liquid class found.\n",[835,1485,1483],{"__ignoreMap":885},[828,1487,1488,1489,1491],{},"A generic set that leaves ",[835,1490,1223],{}," unset adopts everywhere and lets each device select its own. That is the portable choice.",[855,1493,1495,1496,1499],{"id":1494},"stage-2-validate-is-this-safe-on-this-deck-right-now","Stage 2 — ",[835,1497,1498],{},"validate",": is this safe on this deck right now?",[828,1501,1502,1504,1505,1507,1508,1511,1512,1515],{},[835,1503,1498],{}," runs ",[835,1506,1092],{}," with warnings captured. Every ",[835,1509,1510],{},"UserWarning"," a resolver emits becomes one line of a single ",[835,1513,1514],{},"ValueError","; other warning categories are ignored. It changes no state and touches no hardware, so it is safe to call in a dry run.",[828,1517,1518,1519,1521],{},"Pipetting methods call ",[835,1520,1498],{}," for you before compiling. Call it yourself when you want to check a set against a deck before committing to a run.",[880,1523,1525],{"className":882,"code":1524,"language":884,"meta":885,"style":885},"from unitelabs.liquid_handling.hamilton.modules.core96 import CoRe96Context\n\ncontext = CoRe96Context(module=star.core96, target=plate)\nassert CoRe96AspirateParameterSet.adopt(transfer).validate(context)  # True\n",[835,1526,1527,1538,1542,1568],{"__ignoreMap":885},[889,1528,1529,1531,1533,1535],{"class":891,"line":892},[889,1530,896],{"class":895},[889,1532,1133],{"class":899},[889,1534,903],{"class":895},[889,1536,1537],{"class":899}," CoRe96Context\n",[889,1539,1540],{"class":891,"line":909},[889,1541,926],{"emptyLinePlaceholder":925},[889,1543,1544,1547,1549,1552,1555,1557,1560,1563,1565],{"class":891,"line":922},[889,1545,1546],{"class":899},"context ",[889,1548,935],{"class":895},[889,1550,1551],{"class":899}," CoRe96Context(",[889,1553,1554],{"class":944},"module",[889,1556,935],{"class":895},[889,1558,1559],{"class":899},"star.core96, ",[889,1561,1562],{"class":944},"target",[889,1564,935],{"class":895},[889,1566,1567],{"class":899},"plate)\n",[889,1569,1570,1573,1576],{"class":891,"line":929},[889,1571,1572],{"class":895},"assert",[889,1574,1575],{"class":899}," CoRe96AspirateParameterSet.adopt(transfer).validate(context)  ",[889,1577,1578],{"class":1162},"# True\n",[1352,1580,1582],{"id":1581},"passing-on-both-machines","Passing on both machines",[828,1584,1585],{},"The recipe above validates on the CO-RE 96 and the MCA96 unchanged: 100 µL fits both the 300 µL and the 200 µL tip, the source has 150 µL, and a 1 mm surface offset is shallower than the 3.94 mm liquid column.",[1352,1587,1589],{"id":1588},"failing-on-both-with-different-reasoning","Failing on both, with different reasoning",[828,1591,1592],{},"Ask for a 100 mm immersion depth in a well holding 3.94 mm of liquid and both refuse — but each explains it in its own terms, because each resolver knows a different thing about the hardware:",[880,1594,1596],{"className":882,"code":1595,"language":884,"meta":885,"style":885},"deep = AspirateParameterSet(volume=50, pipette_mode=AspiratePipetteMode.SURFACE, liquid_offset=100)\n\nCoRe96AspirateParameterSet.adopt(deep).validate(star_context)\n# ValueError: Parameter set CoRe96AspirateParameterSet failed validation due to the\n# following warnings:\n#  - Provided liquid offset 100.0 would result in the pipette crashing into the\n#    labware bottom with a current liquid height of 3.94.\n\nMCAAspirateParameterSet.adopt(deep).validate(evo_context)\n# ValueError: Parameter set MCAAspirateParameterSet failed validation due to the\n# following warnings:\n#  - Liquid offset must be less than or equal to the liquid level\n#    3.942601642189242663732223653, received 100.0.\n",[835,1597,1598,1634,1638,1643,1648,1653,1658,1663,1667,1672,1678,1683,1689],{"__ignoreMap":885},[889,1599,1600,1603,1605,1608,1610,1612,1614,1616,1618,1620,1622,1624,1626,1628,1630,1632],{"class":891,"line":892},[889,1601,1602],{"class":899},"deep ",[889,1604,935],{"class":895},[889,1606,1607],{"class":899}," AspirateParameterSet(",[889,1609,1220],{"class":944},[889,1611,935],{"class":895},[889,1613,1383],{"class":950},[889,1615,846],{"class":899},[889,1617,1211],{"class":944},[889,1619,935],{"class":895},[889,1621,965],{"class":899},[889,1623,968],{"class":950},[889,1625,846],{"class":899},[889,1627,1214],{"class":944},[889,1629,935],{"class":895},[889,1631,951],{"class":950},[889,1633,1030],{"class":899},[889,1635,1636],{"class":891,"line":909},[889,1637,926],{"emptyLinePlaceholder":925},[889,1639,1640],{"class":891,"line":922},[889,1641,1642],{"class":899},"CoRe96AspirateParameterSet.adopt(deep).validate(star_context)\n",[889,1644,1645],{"class":891,"line":929},[889,1646,1647],{"class":1162},"# ValueError: Parameter set CoRe96AspirateParameterSet failed validation due to the\n",[889,1649,1650],{"class":891,"line":941},[889,1651,1652],{"class":1162},"# following warnings:\n",[889,1654,1655],{"class":891,"line":957},[889,1656,1657],{"class":1162},"#  - Provided liquid offset 100.0 would result in the pipette crashing into the\n",[889,1659,1660],{"class":891,"line":973},[889,1661,1662],{"class":1162},"#    labware bottom with a current liquid height of 3.94.\n",[889,1664,1665],{"class":891,"line":986},[889,1666,926],{"emptyLinePlaceholder":925},[889,1668,1669],{"class":891,"line":1027},[889,1670,1671],{"class":899},"MCAAspirateParameterSet.adopt(deep).validate(evo_context)\n",[889,1673,1675],{"class":891,"line":1674},10,[889,1676,1677],{"class":1162},"# ValueError: Parameter set MCAAspirateParameterSet failed validation due to the\n",[889,1679,1681],{"class":891,"line":1680},11,[889,1682,1652],{"class":1162},[889,1684,1686],{"class":891,"line":1685},12,[889,1687,1688],{"class":1162},"#  - Liquid offset must be less than or equal to the liquid level\n",[889,1690,1692],{"class":891,"line":1691},13,[889,1693,1694],{"class":1162},"#    3.942601642189242663732223653, received 100.0.\n",[828,1696,1697],{},"The CO-RE 96 message is framed around liquid-level detection; the MCA96 has none and reasons purely from container geometry and tracked volume. Same rejection, different physics.",[1352,1699,1701],{"id":1700},"failing-on-one-machine-only","Failing on one machine only",[828,1703,1704],{},"The MCA96 head has no jet mode. The CO-RE 96 does, so the same dispense recipe splits:",[880,1706,1708],{"className":882,"code":1707,"language":884,"meta":885,"style":885},"from unitelabs.liquid_handling import DispenseParameterSet, DispensePipetteMode\n\njet = DispenseParameterSet(volume=50, pipette_mode=DispensePipetteMode.JET)\n\nCoRe96DispenseParameterSet.adopt(jet).validate(star_context)   # True\nMCADispenseParameterSet.adopt(jet).validate(evo_context)\n# ValueError: JET mode is not supported by the MCA96 head; use SURFACE or BOTTOM.\n",[835,1709,1710,1721,1725,1755,1759,1766,1771],{"__ignoreMap":885},[889,1711,1712,1714,1716,1718],{"class":891,"line":892},[889,1713,896],{"class":895},[889,1715,900],{"class":899},[889,1717,903],{"class":895},[889,1719,1720],{"class":899}," DispenseParameterSet, DispensePipetteMode\n",[889,1722,1723],{"class":891,"line":909},[889,1724,926],{"emptyLinePlaceholder":925},[889,1726,1727,1730,1732,1735,1737,1739,1741,1743,1745,1747,1750,1753],{"class":891,"line":922},[889,1728,1729],{"class":899},"jet ",[889,1731,935],{"class":895},[889,1733,1734],{"class":899}," DispenseParameterSet(",[889,1736,1220],{"class":944},[889,1738,935],{"class":895},[889,1740,1383],{"class":950},[889,1742,846],{"class":899},[889,1744,1211],{"class":944},[889,1746,935],{"class":895},[889,1748,1749],{"class":899},"DispensePipetteMode.",[889,1751,1752],{"class":950},"JET",[889,1754,1030],{"class":899},[889,1756,1757],{"class":891,"line":929},[889,1758,926],{"emptyLinePlaceholder":925},[889,1760,1761,1764],{"class":891,"line":941},[889,1762,1763],{"class":899},"CoRe96DispenseParameterSet.adopt(jet).validate(star_context)   ",[889,1765,1578],{"class":1162},[889,1767,1768],{"class":891,"line":957},[889,1769,1770],{"class":899},"MCADispenseParameterSet.adopt(jet).validate(evo_context)\n",[889,1772,1773],{"class":891,"line":973},[889,1774,1775],{"class":1162},"# ValueError: JET mode is not supported by the MCA96 head; use SURFACE or BOTTOM.\n",[828,1777,1778],{},"Note the shape of that last error: it is raised directly by the resolver, not collected from a warning, so it carries no \"failed validation due to the following warnings\" preamble. A hard constraint aborts; a soft one is reported and clamped.",[1352,1780,1782],{"id":1781},"where-the-state-matters-more-than-the-recipe","Where the state matters more than the recipe",[828,1784,1785,1786,1788],{},"Two calls with an identical set can disagree, because ",[835,1787,1498],{}," reads live deck state. Asking for 5000 µL from a plate well passes — the resolver clamps the request to the 150 µL actually present, which fits the tip. Asking for the same 5000 µL from a trough fails, because a trough really can supply it and the 300 µL tip cannot hold it:",[880,1790,1792],{"className":882,"code":1791,"language":884,"meta":885,"style":885},"big = AspirateParameterSet(volume=5000)\n\nCoRe96AspirateParameterSet.adopt(big).validate(plate_context)   # True — clamped to 150 µL\nCoRe96AspirateParameterSet.adopt(big).validate(trough_context)\n# ValueError: ... Volume must be less than or equal to the free tip volume 300,\n# received 5000.0.\n",[835,1793,1794,1812,1816,1824,1829,1834],{"__ignoreMap":885},[889,1795,1796,1799,1801,1803,1805,1807,1810],{"class":891,"line":892},[889,1797,1798],{"class":899},"big ",[889,1800,935],{"class":895},[889,1802,1607],{"class":899},[889,1804,1220],{"class":944},[889,1806,935],{"class":895},[889,1808,1809],{"class":950},"5000",[889,1811,1030],{"class":899},[889,1813,1814],{"class":891,"line":909},[889,1815,926],{"emptyLinePlaceholder":925},[889,1817,1818,1821],{"class":891,"line":922},[889,1819,1820],{"class":899},"CoRe96AspirateParameterSet.adopt(big).validate(plate_context)   ",[889,1822,1823],{"class":1162},"# True — clamped to 150 µL\n",[889,1825,1826],{"class":891,"line":929},[889,1827,1828],{"class":899},"CoRe96AspirateParameterSet.adopt(big).validate(trough_context)\n",[889,1830,1831],{"class":891,"line":941},[889,1832,1833],{"class":1162},"# ValueError: ... Volume must be less than or equal to the free tip volume 300,\n",[889,1835,1836],{"class":891,"line":957},[889,1837,1838],{"class":1162},"# received 5000.0.\n",[828,1840,1841],{},"A set that validates against one deck says nothing about another. Pin the values that must stay constant.",[855,1843,1845,1846,1848],{"id":1844},"stage-3-show_defaults-what-did-the-device-decide","Stage 3 — ",[835,1847,1088],{},": what did the device decide?",[828,1850,1851,1853,1854,1856,1857,838,1859,1861,1862,1864],{},[835,1852,1088],{}," returns a copy of the set with every ",[835,1855,863],{}," field replaced by the value it would resolve to, and every field you set explicitly passed through its resolver so you see the effective value. It recurses into nested sets such as ",[835,1858,1251],{},[835,1860,1284],{},". Compare a field before and after: ",[835,1863,863],{}," before and populated after means it was inferred.",[880,1866,1868],{"className":882,"code":1867,"language":884,"meta":885,"style":885},"resolved = CoRe96AspirateParameterSet.adopt(transfer).show_defaults(star_context)\n\nresolved.lld_mode             # LLDMode.CAPACITIVE  ← inferred from SURFACE mode\nresolved.pull_out_distance    # Decimal('5')        ← Hamilton default\nresolved.min_traverse_height  # Decimal('245')      ← from the instrument configuration\nresolved.liquid_class         # HamiltonTip_10_CoRe96_Water_DispenseSurface_Empty\nresolved.mixing.cycles        # 0                   ← nested, resolved to \"no mixing\"\nresolved.volume               # Decimal('100.0')    ← you set this; unchanged\n",[835,1869,1870,1880,1884,1892,1900,1908,1916,1924],{"__ignoreMap":885},[889,1871,1872,1875,1877],{"class":891,"line":892},[889,1873,1874],{"class":899},"resolved ",[889,1876,935],{"class":895},[889,1878,1879],{"class":899}," CoRe96AspirateParameterSet.adopt(transfer).show_defaults(star_context)\n",[889,1881,1882],{"class":891,"line":909},[889,1883,926],{"emptyLinePlaceholder":925},[889,1885,1886,1889],{"class":891,"line":922},[889,1887,1888],{"class":899},"resolved.lld_mode             ",[889,1890,1891],{"class":1162},"# LLDMode.CAPACITIVE  ← inferred from SURFACE mode\n",[889,1893,1894,1897],{"class":891,"line":929},[889,1895,1896],{"class":899},"resolved.pull_out_distance    ",[889,1898,1899],{"class":1162},"# Decimal('5')        ← Hamilton default\n",[889,1901,1902,1905],{"class":891,"line":941},[889,1903,1904],{"class":899},"resolved.min_traverse_height  ",[889,1906,1907],{"class":1162},"# Decimal('245')      ← from the instrument configuration\n",[889,1909,1910,1913],{"class":891,"line":957},[889,1911,1912],{"class":899},"resolved.liquid_class         ",[889,1914,1915],{"class":1162},"# HamiltonTip_10_CoRe96_Water_DispenseSurface_Empty\n",[889,1917,1918,1921],{"class":891,"line":973},[889,1919,1920],{"class":899},"resolved.mixing.cycles        ",[889,1922,1923],{"class":1162},"# 0                   ← nested, resolved to \"no mixing\"\n",[889,1925,1926,1929],{"class":891,"line":986},[889,1927,1928],{"class":899},"resolved.volume               ",[889,1930,1931],{"class":1162},"# Decimal('100.0')    ← you set this; unchanged\n",[828,1933,1934,1935,1937,1938,1940,1941,1943],{},"The original is never mutated, and the result is always a fresh instance of the same class. Fields with no meaningful resolved form opt out and stay ",[835,1936,863],{},": ",[835,1939,1232],{}," everywhere (its resolver yields an absolute Z, not an offset) and ",[835,1942,1217],{}," on the Bravo (the head ignores it).",[828,1945,1946,1947,1949,1950,1953],{},"Resolution emits the same warnings as ",[835,1948,1092],{},", so wrap the call in ",[835,1951,1952],{},"warnings.catch_warnings"," if you want to inspect them rather than let them print.",[1032,1955,1958],{"color":1956,"icon":1957},"info","i-heroicons-information-circle",[828,1959,1960,1962,1963,1965,1966,838,1968,1971,1972,1974],{},[835,1961,1088],{}," currently raises ",[835,1964,1060],{}," on ",[835,1967,849],{},[835,1969,1970],{},"MCADispenseParameterSet",". Use ",[835,1973,1092],{}," to inspect resolved values on the EVO MCA96 in the meantime.",[855,1976,1978,1979,1981],{"id":1977},"stage-4-compile-the-wire-parameters","Stage 4 — ",[835,1980,1092],{},": the wire parameters",[828,1983,1984,1986],{},[835,1985,1092],{}," turns the resolved set into the keyword arguments for the device connector call. This is where the abstraction ends: the two heads share four keys out of roughly thirty.",[1988,1989,1990,2210],"tabs",{},[1991,1992,1994,1997],"div",{"label":1993},"Hamilton CO-RE 96",[828,1995,1996],{},"28 keys, framed as positions plus flow rates:",[880,1998,2000],{"className":882,"code":1999,"language":884,"meta":885,"style":885},"{\n    \"aspirate_location\": Vector(x=253.50, y=530.50, z=216.69),\n    \"immersion_depth\": Decimal(\"1.0\"),\n    \"liquid_volume\": Decimal(\"106.500\"),      # includes the liquid class's over-aspirate\n    \"lld_mode\": LLDMode.CAPACITIVE,\n    \"lld_sensitivity\": 4,\n    \"flow_rate\": Decimal(\"25\"),               # µL\u002Fs, from the liquid class\n    \"swap_speed\": Decimal(\"2\"),\n    \"settling_time\": Decimal(\"0\"),\n    \"min_z_position\": Decimal(\"212.75\"),\n    \"start_z_position\": Decimal(\"226.10\"),\n    \"end_z_position\": Decimal(\"245\"),\n    \"min_traverse_height\": Decimal(\"245\"),\n    \"tadm_mode\": TADMMode.OFF,\n    ...\n}\n",[835,2001,2002,2007,2043,2056,2072,2085,2097,2113,2125,2137,2149,2161,2173,2184,2198,2204],{"__ignoreMap":885},[889,2003,2004],{"class":891,"line":892},[889,2005,2006],{"class":899},"{\n",[889,2008,2009,2013,2016,2018,2020,2023,2025,2027,2029,2032,2034,2036,2038,2041],{"class":891,"line":909},[889,2010,2012],{"class":2011},"sCx38","    \"aspirate_location\"",[889,2014,2015],{"class":899},": Vector(",[889,2017,997],{"class":944},[889,2019,935],{"class":895},[889,2021,2022],{"class":950},"253.50",[889,2024,846],{"class":899},[889,2026,1007],{"class":944},[889,2028,935],{"class":895},[889,2030,2031],{"class":950},"530.50",[889,2033,846],{"class":899},[889,2035,1016],{"class":944},[889,2037,935],{"class":895},[889,2039,2040],{"class":950},"216.69",[889,2042,1024],{"class":899},[889,2044,2045,2048,2051,2054],{"class":891,"line":922},[889,2046,2047],{"class":2011},"    \"immersion_depth\"",[889,2049,2050],{"class":899},": Decimal(",[889,2052,2053],{"class":2011},"\"1.0\"",[889,2055,1024],{"class":899},[889,2057,2058,2061,2063,2066,2069],{"class":891,"line":929},[889,2059,2060],{"class":2011},"    \"liquid_volume\"",[889,2062,2050],{"class":899},[889,2064,2065],{"class":2011},"\"106.500\"",[889,2067,2068],{"class":899},"),      ",[889,2070,2071],{"class":1162},"# includes the liquid class's over-aspirate\n",[889,2073,2074,2077,2080,2083],{"class":891,"line":941},[889,2075,2076],{"class":2011},"    \"lld_mode\"",[889,2078,2079],{"class":899},": LLDMode.",[889,2081,2082],{"class":950},"CAPACITIVE",[889,2084,954],{"class":899},[889,2086,2087,2090,2092,2095],{"class":891,"line":957},[889,2088,2089],{"class":2011},"    \"lld_sensitivity\"",[889,2091,1937],{"class":899},[889,2093,2094],{"class":950},"4",[889,2096,954],{"class":899},[889,2098,2099,2102,2104,2107,2110],{"class":891,"line":973},[889,2100,2101],{"class":2011},"    \"flow_rate\"",[889,2103,2050],{"class":899},[889,2105,2106],{"class":2011},"\"25\"",[889,2108,2109],{"class":899},"),               ",[889,2111,2112],{"class":1162},"# µL\u002Fs, from the liquid class\n",[889,2114,2115,2118,2120,2123],{"class":891,"line":986},[889,2116,2117],{"class":2011},"    \"swap_speed\"",[889,2119,2050],{"class":899},[889,2121,2122],{"class":2011},"\"2\"",[889,2124,1024],{"class":899},[889,2126,2127,2130,2132,2135],{"class":891,"line":1027},[889,2128,2129],{"class":2011},"    \"settling_time\"",[889,2131,2050],{"class":899},[889,2133,2134],{"class":2011},"\"0\"",[889,2136,1024],{"class":899},[889,2138,2139,2142,2144,2147],{"class":891,"line":1674},[889,2140,2141],{"class":2011},"    \"min_z_position\"",[889,2143,2050],{"class":899},[889,2145,2146],{"class":2011},"\"212.75\"",[889,2148,1024],{"class":899},[889,2150,2151,2154,2156,2159],{"class":891,"line":1680},[889,2152,2153],{"class":2011},"    \"start_z_position\"",[889,2155,2050],{"class":899},[889,2157,2158],{"class":2011},"\"226.10\"",[889,2160,1024],{"class":899},[889,2162,2163,2166,2168,2171],{"class":891,"line":1685},[889,2164,2165],{"class":2011},"    \"end_z_position\"",[889,2167,2050],{"class":899},[889,2169,2170],{"class":2011},"\"245\"",[889,2172,1024],{"class":899},[889,2174,2175,2178,2180,2182],{"class":891,"line":1691},[889,2176,2177],{"class":2011},"    \"min_traverse_height\"",[889,2179,2050],{"class":899},[889,2181,2170],{"class":2011},[889,2183,1024],{"class":899},[889,2185,2187,2190,2193,2196],{"class":891,"line":2186},14,[889,2188,2189],{"class":2011},"    \"tadm_mode\"",[889,2191,2192],{"class":899},": TADMMode.",[889,2194,2195],{"class":950},"OFF",[889,2197,954],{"class":899},[889,2199,2201],{"class":891,"line":2200},15,[889,2202,2203],{"class":950},"    ...\n",[889,2205,2207],{"class":891,"line":2206},16,[889,2208,2209],{"class":899},"}\n",[1991,2211,2213,2216],{"label":2212},"Tecan EVO MCA96",[828,2214,2215],{},"27 keys, framed as a plunger program plus air gaps:",[880,2217,2219],{"className":882,"code":2218,"language":884,"meta":885,"style":885},"{\n    \"x\": Decimal(\"24.90\"), \"y\": Decimal(\"278.50\"), \"z\": Decimal(\"9.94\"),\n    \"plunger_movement\": Decimal(\"100.00\"),    # calibrated volume\n    \"aspirate_speed\": Decimal(\"50.0\"),        # µL\u002Fs, from the liquid class\n    \"aspirate_delay\": 500,\n    \"leading_air_gap\": Decimal(\"5.0\"),\n    \"leading_air_gap_speed\": Decimal(\"10.0\"),\n    \"trailing_air_gap\": Decimal(\"5.0\"),\n    \"system_trailing_air_gap\": Decimal(\"0.0\"),\n    \"relative_tracking_distance\": Decimal(\"2.63\"),\n    \"plunger_start_ramp\": 5760,\n    \"plunger_stop_ramp\": 16000,\n    \"z_retract\": Decimal(\"210\"),\n    ...\n}\n",[835,2220,2221,2225,2258,2274,2289,2301,2313,2325,2336,2348,2360,2372,2384,2396,2400],{"__ignoreMap":885},[889,2222,2223],{"class":891,"line":892},[889,2224,2006],{"class":899},[889,2226,2227,2230,2232,2235,2238,2241,2243,2246,2248,2251,2253,2256],{"class":891,"line":909},[889,2228,2229],{"class":2011},"    \"x\"",[889,2231,2050],{"class":899},[889,2233,2234],{"class":2011},"\"24.90\"",[889,2236,2237],{"class":899},"), ",[889,2239,2240],{"class":2011},"\"y\"",[889,2242,2050],{"class":899},[889,2244,2245],{"class":2011},"\"278.50\"",[889,2247,2237],{"class":899},[889,2249,2250],{"class":2011},"\"z\"",[889,2252,2050],{"class":899},[889,2254,2255],{"class":2011},"\"9.94\"",[889,2257,1024],{"class":899},[889,2259,2260,2263,2265,2268,2271],{"class":891,"line":922},[889,2261,2262],{"class":2011},"    \"plunger_movement\"",[889,2264,2050],{"class":899},[889,2266,2267],{"class":2011},"\"100.00\"",[889,2269,2270],{"class":899},"),    ",[889,2272,2273],{"class":1162},"# calibrated volume\n",[889,2275,2276,2279,2281,2284,2287],{"class":891,"line":929},[889,2277,2278],{"class":2011},"    \"aspirate_speed\"",[889,2280,2050],{"class":899},[889,2282,2283],{"class":2011},"\"50.0\"",[889,2285,2286],{"class":899},"),        ",[889,2288,2112],{"class":1162},[889,2290,2291,2294,2296,2299],{"class":891,"line":941},[889,2292,2293],{"class":2011},"    \"aspirate_delay\"",[889,2295,1937],{"class":899},[889,2297,2298],{"class":950},"500",[889,2300,954],{"class":899},[889,2302,2303,2306,2308,2311],{"class":891,"line":957},[889,2304,2305],{"class":2011},"    \"leading_air_gap\"",[889,2307,2050],{"class":899},[889,2309,2310],{"class":2011},"\"5.0\"",[889,2312,1024],{"class":899},[889,2314,2315,2318,2320,2323],{"class":891,"line":973},[889,2316,2317],{"class":2011},"    \"leading_air_gap_speed\"",[889,2319,2050],{"class":899},[889,2321,2322],{"class":2011},"\"10.0\"",[889,2324,1024],{"class":899},[889,2326,2327,2330,2332,2334],{"class":891,"line":986},[889,2328,2329],{"class":2011},"    \"trailing_air_gap\"",[889,2331,2050],{"class":899},[889,2333,2310],{"class":2011},[889,2335,1024],{"class":899},[889,2337,2338,2341,2343,2346],{"class":891,"line":1027},[889,2339,2340],{"class":2011},"    \"system_trailing_air_gap\"",[889,2342,2050],{"class":899},[889,2344,2345],{"class":2011},"\"0.0\"",[889,2347,1024],{"class":899},[889,2349,2350,2353,2355,2358],{"class":891,"line":1674},[889,2351,2352],{"class":2011},"    \"relative_tracking_distance\"",[889,2354,2050],{"class":899},[889,2356,2357],{"class":2011},"\"2.63\"",[889,2359,1024],{"class":899},[889,2361,2362,2365,2367,2370],{"class":891,"line":1680},[889,2363,2364],{"class":2011},"    \"plunger_start_ramp\"",[889,2366,1937],{"class":899},[889,2368,2369],{"class":950},"5760",[889,2371,954],{"class":899},[889,2373,2374,2377,2379,2382],{"class":891,"line":1685},[889,2375,2376],{"class":2011},"    \"plunger_stop_ramp\"",[889,2378,1937],{"class":899},[889,2380,2381],{"class":950},"16000",[889,2383,954],{"class":899},[889,2385,2386,2389,2391,2394],{"class":891,"line":1691},[889,2387,2388],{"class":2011},"    \"z_retract\"",[889,2390,2050],{"class":899},[889,2392,2393],{"class":2011},"\"210\"",[889,2395,1024],{"class":899},[889,2397,2398],{"class":891,"line":2186},[889,2399,2203],{"class":950},[889,2401,2402],{"class":891,"line":2200},[889,2403,2209],{"class":899},[828,2405,2406,2407,846,2409,846,2412,846,2415,2417,2418,2420],{},"Shared keys: ",[835,2408,1248],{},[835,2410,2411],{},"mix_cycles",[835,2413,2414],{},"mix_volume",[835,2416,1229],{},". Everything else is vendor vocabulary. Compiled dictionaries are not portable — the parameter set is the portable artifact, and ",[835,2419,1115],{}," is what makes it so.",[828,2422,2423,2424,2427,2428,2430],{},"After the connector call returns, ",[835,2425,2426],{},"apply"," writes the transfer back into the liquid model: the source well loses the volume, the tip gains it. That is what keeps a later ",[835,2429,1498],{}," on the same deck honest.",[855,2432,2434],{"id":2433},"broadcasting-to-independent-channels","Broadcasting to independent channels",[828,2436,2437,2438,2441,2442,2445],{},"The Hamilton channel arm pipettes each channel independently, so its sets are per-channel: scalars broadcast, lists must match the length of ",[835,2439,2440],{},"channels",". A generic set is spread identically across every selected channel by ",[835,2443,2444],{},"from_parameters",":",[880,2447,2449],{"className":882,"code":2448,"language":884,"meta":885,"style":885},"from unitelabs.liquid_handling.hamilton.modules.pipettes import (\n    ChannelsAspirateParameterSet,\n    ChannelsContext,\n)\n\nchannels_set = ChannelsAspirateParameterSet.from_parameters(transfer, channels=[0, 1, 2, 3])\nchannels_set.volume  # [100.0, 100.0, 100.0, 100.0]\n",[835,2450,2451,2463,2468,2473,2477,2481,2518],{"__ignoreMap":885},[889,2452,2453,2455,2458,2460],{"class":891,"line":892},[889,2454,896],{"class":895},[889,2456,2457],{"class":899}," unitelabs.liquid_handling.hamilton.modules.pipettes ",[889,2459,903],{"class":895},[889,2461,2462],{"class":899}," (\n",[889,2464,2465],{"class":891,"line":909},[889,2466,2467],{"class":899},"    ChannelsAspirateParameterSet,\n",[889,2469,2470],{"class":891,"line":922},[889,2471,2472],{"class":899},"    ChannelsContext,\n",[889,2474,2475],{"class":891,"line":929},[889,2476,1030],{"class":899},[889,2478,2479],{"class":891,"line":941},[889,2480,926],{"emptyLinePlaceholder":925},[889,2482,2483,2486,2488,2491,2493,2495,2498,2500,2502,2505,2507,2510,2512,2515],{"class":891,"line":957},[889,2484,2485],{"class":899},"channels_set ",[889,2487,935],{"class":895},[889,2489,2490],{"class":899}," ChannelsAspirateParameterSet.from_parameters(transfer, ",[889,2492,2440],{"class":944},[889,2494,935],{"class":895},[889,2496,2497],{"class":899},"[",[889,2499,1021],{"class":950},[889,2501,846],{"class":899},[889,2503,2504],{"class":950},"1",[889,2506,846],{"class":899},[889,2508,2509],{"class":950},"2",[889,2511,846],{"class":899},[889,2513,2514],{"class":950},"3",[889,2516,2517],{"class":899},"])\n",[889,2519,2520,2523],{"class":891,"line":973},[889,2521,2522],{"class":899},"channels_set.volume  ",[889,2524,2525],{"class":1162},"# [100.0, 100.0, 100.0, 100.0]\n",[828,2527,2528,2529,2532],{},"Passing the generic set straight to ",[835,2530,2531],{},"pipettes.aspirate"," does the same thing implicitly. Validation then runs per channel and names the offender:",[880,2534,2536],{"className":882,"code":2535,"language":884,"meta":885,"style":885},"uneven = ChannelsAspirateParameterSet(\n    channels=[0, 1, 2, 3],\n    volume=100,\n    liquid_offset=[1.0, 1.0, 100.0, 1.0],\n)\nuneven.validate(channels_context)\n# ValueError: Parameter set ChannelsAspirateParameterSet failed validation due to\n# the following warnings:\n#  - [CHANNEL 2]: Provided liquid offset 100.0 would result in the pipette crashing\n#    into the labware bottom with a current liquid height of 3.94.\n",[835,2537,2538,2548,2574,2584,2609,2613,2618,2623,2628,2633],{"__ignoreMap":885},[889,2539,2540,2543,2545],{"class":891,"line":892},[889,2541,2542],{"class":899},"uneven ",[889,2544,935],{"class":895},[889,2546,2547],{"class":899}," ChannelsAspirateParameterSet(\n",[889,2549,2550,2553,2555,2557,2559,2561,2563,2565,2567,2569,2571],{"class":891,"line":909},[889,2551,2552],{"class":944},"    channels",[889,2554,935],{"class":895},[889,2556,2497],{"class":899},[889,2558,1021],{"class":950},[889,2560,846],{"class":899},[889,2562,2504],{"class":950},[889,2564,846],{"class":899},[889,2566,2509],{"class":950},[889,2568,846],{"class":899},[889,2570,2514],{"class":950},[889,2572,2573],{"class":899},"],\n",[889,2575,2576,2578,2580,2582],{"class":891,"line":922},[889,2577,945],{"class":944},[889,2579,935],{"class":895},[889,2581,951],{"class":950},[889,2583,954],{"class":899},[889,2585,2586,2588,2590,2592,2594,2596,2598,2600,2603,2605,2607],{"class":891,"line":929},[889,2587,976],{"class":944},[889,2589,935],{"class":895},[889,2591,2497],{"class":899},[889,2593,981],{"class":950},[889,2595,846],{"class":899},[889,2597,981],{"class":950},[889,2599,846],{"class":899},[889,2601,2602],{"class":950},"100.0",[889,2604,846],{"class":899},[889,2606,981],{"class":950},[889,2608,2573],{"class":899},[889,2610,2611],{"class":891,"line":941},[889,2612,1030],{"class":899},[889,2614,2615],{"class":891,"line":957},[889,2616,2617],{"class":899},"uneven.validate(channels_context)\n",[889,2619,2620],{"class":891,"line":973},[889,2621,2622],{"class":1162},"# ValueError: Parameter set ChannelsAspirateParameterSet failed validation due to\n",[889,2624,2625],{"class":891,"line":986},[889,2626,2627],{"class":1162},"# the following warnings:\n",[889,2629,2630],{"class":891,"line":1027},[889,2631,2632],{"class":1162},"#  - [CHANNEL 2]: Provided liquid offset 100.0 would result in the pipette crashing\n",[889,2634,2635],{"class":891,"line":1674},[889,2636,2637],{"class":1162},"#    into the labware bottom with a current liquid height of 3.94.\n",[855,2639,2641],{"id":2640},"reusing-and-composing-sets","Reusing and composing sets",[828,2643,2644],{},"Parameter sets round-trip through plain dictionaries, so they can live in configuration files or a database next to the run that used them:",[880,2646,2648],{"className":882,"code":2647,"language":884,"meta":885,"style":885},"saved = transfer.dumps()\n# {'pipette_mode': 'SURFACE', 'liquid_offset': 1.0, 'volume': 100.0,\n#  'offset': {'x': '0.5', 'y': '0.5', 'z': '0'}}\n\nrestored = AspirateParameterSet.loads(saved)\nassert restored == transfer\n",[835,2649,2650,2660,2665,2670,2674,2684],{"__ignoreMap":885},[889,2651,2652,2655,2657],{"class":891,"line":892},[889,2653,2654],{"class":899},"saved ",[889,2656,935],{"class":895},[889,2658,2659],{"class":899}," transfer.dumps()\n",[889,2661,2662],{"class":891,"line":909},[889,2663,2664],{"class":1162},"# {'pipette_mode': 'SURFACE', 'liquid_offset': 1.0, 'volume': 100.0,\n",[889,2666,2667],{"class":891,"line":922},[889,2668,2669],{"class":1162},"#  'offset': {'x': '0.5', 'y': '0.5', 'z': '0'}}\n",[889,2671,2672],{"class":891,"line":929},[889,2673,926],{"emptyLinePlaceholder":925},[889,2675,2676,2679,2681],{"class":891,"line":941},[889,2677,2678],{"class":899},"restored ",[889,2680,935],{"class":895},[889,2682,2683],{"class":899}," AspirateParameterSet.loads(saved)\n",[889,2685,2686,2688,2691,2694],{"class":891,"line":957},[889,2687,1572],{"class":895},[889,2689,2690],{"class":899}," restored ",[889,2692,2693],{"class":895},"==",[889,2695,2696],{"class":899}," transfer\n",[828,2698,2699,2702,2703,2706,2707,2710],{},[835,2700,2701],{},"copy"," gives you a deep copy. ",[835,2704,2705],{},"update"," merges another set of the same class in place — by default the incoming values win; with ",[835,2708,2709],{},"missing_only=True"," only your unset fields are filled, which is how you layer a site-wide default under a step-specific override:",[880,2712,2714],{"className":882,"code":2713,"language":884,"meta":885,"style":885},"step = AspirateParameterSet(volume=100, liquid_offset=1.0)\nstep.update(AspirateParameterSet(liquid_offset=2.0, follow_liquid=True), missing_only=True)\n\nstep.liquid_offset   # 1.0   — yours was set, so it stands\nstep.follow_liquid   # True  — was MISSING, so the default filled it\n",[835,2715,2716,2741,2772,2776,2784],{"__ignoreMap":885},[889,2717,2718,2721,2723,2725,2727,2729,2731,2733,2735,2737,2739],{"class":891,"line":892},[889,2719,2720],{"class":899},"step ",[889,2722,935],{"class":895},[889,2724,1607],{"class":899},[889,2726,1220],{"class":944},[889,2728,935],{"class":895},[889,2730,951],{"class":950},[889,2732,846],{"class":899},[889,2734,1214],{"class":944},[889,2736,935],{"class":895},[889,2738,981],{"class":950},[889,2740,1030],{"class":899},[889,2742,2743,2746,2748,2750,2753,2755,2757,2759,2761,2763,2766,2768,2770],{"class":891,"line":909},[889,2744,2745],{"class":899},"step.update(AspirateParameterSet(",[889,2747,1214],{"class":944},[889,2749,935],{"class":895},[889,2751,2752],{"class":950},"2.0",[889,2754,846],{"class":899},[889,2756,1217],{"class":944},[889,2758,935],{"class":895},[889,2760,1392],{"class":950},[889,2762,2237],{"class":899},[889,2764,2765],{"class":944},"missing_only",[889,2767,935],{"class":895},[889,2769,1392],{"class":950},[889,2771,1030],{"class":899},[889,2773,2774],{"class":891,"line":922},[889,2775,926],{"emptyLinePlaceholder":925},[889,2777,2778,2781],{"class":891,"line":929},[889,2779,2780],{"class":899},"step.liquid_offset   ",[889,2782,2783],{"class":1162},"# 1.0   — yours was set, so it stands\n",[889,2785,2786,2789],{"class":891,"line":941},[889,2787,2788],{"class":899},"step.follow_liquid   ",[889,2790,2791],{"class":1162},"# True  — was MISSING, so the default filled it\n",[828,2793,2794,2796,2797,2799],{},[835,2795,2705],{}," requires the same class on both sides; use ",[835,2798,1115],{}," to cross device boundaries. Nested sets merge recursively, but lists and other containers are replaced wholesale rather than merged element-wise.",[855,2801,2803],{"id":2802},"practical-guidance","Practical guidance",[2805,2806,2807,2821,2830,2838,2848],"ul",{},[2808,2809,2810,2814,2815,2817,2818,2820],"li",{},[2811,2812,2813],"strong",{},"Keep protocol-level recipes generic."," Build ",[835,2816,837],{}," \u002F ",[835,2819,841],{}," and let each device adopt them. Reach for a device subclass only when you need a knob that exists on one machine.",[2808,2822,2823,2829],{},[2811,2824,2825,2826,2828],{},"Leave ",[835,2827,1223],{}," unset in portable sets."," It is the one field guaranteed not to travel.",[2808,2831,2832,2837],{},[2811,2833,2834,2835,1061],{},"Pin what must not drift, leave the rest ",[835,2836,863],{}," Resolvers read live deck state, so an unpinned value legitimately differs between runs.",[2808,2839,2840,2845,2846,1061],{},[2811,2841,2842,2844],{},[835,2843,1498],{}," early on a mock."," Every device ships one, so the whole pipeline up to the connector call runs without hardware. See ",[1423,2847,220],{"href":221},[2808,2849,2850,2864],{},[2811,2851,2852,2853,2855,2856,2858,2859,2855,2861,2863],{},"A ",[835,2854,1514],{}," from ",[835,2857,1115],{}," is a portability problem; a ",[835,2860,1514],{},[835,2862,1498],{}," is a deck problem."," The first needs a different recipe, the second needs a different deck state.",[855,2866,2868],{"id":2867},"where-to-go-next","Where to go next",[2805,2870,2871,2876,2881,2886],{},[2808,2872,2873,2875],{},[1423,2874,283],{"href":284}," — the procedural how-to, factory methods, and the Hamilton compiled-parameter reference",[2808,2877,2878,2880],{},[1423,2879,208],{"href":209}," — why the one field that does not travel does not travel",[2808,2882,2883,2885],{},[1423,2884,335],{"href":336}," — parameter sets that carry a list of alternating steps",[2808,2887,2888,838,2891,2894],{},[1423,2889,2890],{"href":418},"Tecan Freedom EVO Basic Pipetting",[1423,2892,2893],{"href":380},"Agilent Bravo Basic Pipetting"," — the per-device field references",[2896,2897,2898],"style",{},"html pre.shiki code .sxkbv, html code.shiki .sxkbv{--shiki-light:#A0111F;--shiki-default:#A0111F;--shiki-dark:#FF7B72}html pre.shiki code .sc-9e, html code.shiki .sc-9e{--shiki-light:#0E1116;--shiki-default:#0E1116;--shiki-dark:#E6EDF3}html pre.shiki code .sNqAu, html code.shiki .sNqAu{--shiki-light:#702C00;--shiki-default:#702C00;--shiki-dark:#FFA657}html pre.shiki code .sOiAX, html code.shiki .sOiAX{--shiki-light:#023B95;--shiki-default:#023B95;--shiki-dark:#79C0FF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sIsDC, html code.shiki .sIsDC{--shiki-light:#66707B;--shiki-default:#66707B;--shiki-dark:#8B949E}html pre.shiki code .sCx38, html code.shiki .sCx38{--shiki-light:#032563;--shiki-default:#032563;--shiki-dark:#A5D6FF}",{"title":885,"searchDepth":892,"depth":909,"links":2900},[2901,2902,2903,2908,2915,2917,2919,2920,2921,2922],{"id":857,"depth":909,"text":858},{"id":1064,"depth":909,"text":1065},{"id":1111,"depth":909,"text":2904,"children":2905},"Stage 1 — adopt: does this device have these knobs?",[2906,2907],{"id":1354,"depth":922,"text":1355},{"id":1417,"depth":922,"text":1418},{"id":1494,"depth":909,"text":2909,"children":2910},"Stage 2 — validate: is this safe on this deck right now?",[2911,2912,2913,2914],{"id":1581,"depth":922,"text":1582},{"id":1588,"depth":922,"text":1589},{"id":1700,"depth":922,"text":1701},{"id":1781,"depth":922,"text":1782},{"id":1844,"depth":909,"text":2916},"Stage 3 — show_defaults: what did the device decide?",{"id":1977,"depth":909,"text":2918},"Stage 4 — compile: the wire parameters",{"id":2433,"depth":909,"text":2434},{"id":2640,"depth":909,"text":2641},{"id":2802,"depth":909,"text":2803},{"id":2867,"depth":909,"text":2868},"How one device-independent pipetting recipe is adapted, validated, and compiled for each liquid handler.","md",null,{},"\u002Foperate\u002Fconcepts\u002Fparameter-sets",{"title":212,"description":2923},"kVjppFpFUZmq8zs93yC1iNWEKan8_o3_w3UPOhaj5z0",[2931,2933],{"title":208,"path":209,"stem":210,"description":2932,"children":-1},"Why pipetting needs a parameter model, and how Hamilton and Bravo diverge in how they express it.",{"title":216,"path":217,"stem":218,"description":2934,"children":-1},"How the SDK models tips as tracked, lifecycle-managed resources, and why independent-channel heads and monolithic 96-heads work differently.",1789663101390]