opentrons 8.6.0a1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of opentrons might be problematic. Click here for more details.
- opentrons/__init__.py +150 -0
- opentrons/_version.py +34 -0
- opentrons/calibration_storage/__init__.py +54 -0
- opentrons/calibration_storage/deck_configuration.py +62 -0
- opentrons/calibration_storage/encoder_decoder.py +31 -0
- opentrons/calibration_storage/file_operators.py +142 -0
- opentrons/calibration_storage/helpers.py +103 -0
- opentrons/calibration_storage/ot2/__init__.py +34 -0
- opentrons/calibration_storage/ot2/deck_attitude.py +85 -0
- opentrons/calibration_storage/ot2/mark_bad_calibration.py +27 -0
- opentrons/calibration_storage/ot2/models/__init__.py +0 -0
- opentrons/calibration_storage/ot2/models/v1.py +149 -0
- opentrons/calibration_storage/ot2/pipette_offset.py +129 -0
- opentrons/calibration_storage/ot2/tip_length.py +281 -0
- opentrons/calibration_storage/ot3/__init__.py +31 -0
- opentrons/calibration_storage/ot3/deck_attitude.py +83 -0
- opentrons/calibration_storage/ot3/gripper_offset.py +156 -0
- opentrons/calibration_storage/ot3/models/__init__.py +0 -0
- opentrons/calibration_storage/ot3/models/v1.py +122 -0
- opentrons/calibration_storage/ot3/module_offset.py +138 -0
- opentrons/calibration_storage/ot3/pipette_offset.py +95 -0
- opentrons/calibration_storage/types.py +45 -0
- opentrons/cli/__init__.py +21 -0
- opentrons/cli/__main__.py +5 -0
- opentrons/cli/analyze.py +501 -0
- opentrons/config/__init__.py +631 -0
- opentrons/config/advanced_settings.py +871 -0
- opentrons/config/defaults_ot2.py +214 -0
- opentrons/config/defaults_ot3.py +499 -0
- opentrons/config/feature_flags.py +86 -0
- opentrons/config/gripper_config.py +55 -0
- opentrons/config/reset.py +203 -0
- opentrons/config/robot_configs.py +187 -0
- opentrons/config/types.py +183 -0
- opentrons/drivers/__init__.py +0 -0
- opentrons/drivers/absorbance_reader/__init__.py +11 -0
- opentrons/drivers/absorbance_reader/abstract.py +72 -0
- opentrons/drivers/absorbance_reader/async_byonoy.py +352 -0
- opentrons/drivers/absorbance_reader/driver.py +81 -0
- opentrons/drivers/absorbance_reader/hid_protocol.py +161 -0
- opentrons/drivers/absorbance_reader/simulator.py +84 -0
- opentrons/drivers/asyncio/__init__.py +0 -0
- opentrons/drivers/asyncio/communication/__init__.py +22 -0
- opentrons/drivers/asyncio/communication/async_serial.py +183 -0
- opentrons/drivers/asyncio/communication/errors.py +88 -0
- opentrons/drivers/asyncio/communication/serial_connection.py +552 -0
- opentrons/drivers/command_builder.py +102 -0
- opentrons/drivers/flex_stacker/__init__.py +13 -0
- opentrons/drivers/flex_stacker/abstract.py +214 -0
- opentrons/drivers/flex_stacker/driver.py +768 -0
- opentrons/drivers/flex_stacker/errors.py +68 -0
- opentrons/drivers/flex_stacker/simulator.py +309 -0
- opentrons/drivers/flex_stacker/types.py +367 -0
- opentrons/drivers/flex_stacker/utils.py +19 -0
- opentrons/drivers/heater_shaker/__init__.py +5 -0
- opentrons/drivers/heater_shaker/abstract.py +76 -0
- opentrons/drivers/heater_shaker/driver.py +204 -0
- opentrons/drivers/heater_shaker/simulator.py +94 -0
- opentrons/drivers/mag_deck/__init__.py +6 -0
- opentrons/drivers/mag_deck/abstract.py +44 -0
- opentrons/drivers/mag_deck/driver.py +208 -0
- opentrons/drivers/mag_deck/simulator.py +63 -0
- opentrons/drivers/rpi_drivers/__init__.py +33 -0
- opentrons/drivers/rpi_drivers/dev_types.py +94 -0
- opentrons/drivers/rpi_drivers/gpio.py +282 -0
- opentrons/drivers/rpi_drivers/gpio_simulator.py +127 -0
- opentrons/drivers/rpi_drivers/interfaces.py +15 -0
- opentrons/drivers/rpi_drivers/types.py +364 -0
- opentrons/drivers/rpi_drivers/usb.py +102 -0
- opentrons/drivers/rpi_drivers/usb_simulator.py +22 -0
- opentrons/drivers/serial_communication.py +151 -0
- opentrons/drivers/smoothie_drivers/__init__.py +4 -0
- opentrons/drivers/smoothie_drivers/connection.py +51 -0
- opentrons/drivers/smoothie_drivers/constants.py +121 -0
- opentrons/drivers/smoothie_drivers/driver_3_0.py +1933 -0
- opentrons/drivers/smoothie_drivers/errors.py +49 -0
- opentrons/drivers/smoothie_drivers/parse_utils.py +143 -0
- opentrons/drivers/smoothie_drivers/simulator.py +99 -0
- opentrons/drivers/smoothie_drivers/types.py +16 -0
- opentrons/drivers/temp_deck/__init__.py +10 -0
- opentrons/drivers/temp_deck/abstract.py +54 -0
- opentrons/drivers/temp_deck/driver.py +197 -0
- opentrons/drivers/temp_deck/simulator.py +57 -0
- opentrons/drivers/thermocycler/__init__.py +12 -0
- opentrons/drivers/thermocycler/abstract.py +99 -0
- opentrons/drivers/thermocycler/driver.py +395 -0
- opentrons/drivers/thermocycler/simulator.py +126 -0
- opentrons/drivers/types.py +107 -0
- opentrons/drivers/utils.py +222 -0
- opentrons/execute.py +742 -0
- opentrons/hardware_control/__init__.py +65 -0
- opentrons/hardware_control/__main__.py +77 -0
- opentrons/hardware_control/adapters.py +98 -0
- opentrons/hardware_control/api.py +1347 -0
- opentrons/hardware_control/backends/__init__.py +7 -0
- opentrons/hardware_control/backends/controller.py +400 -0
- opentrons/hardware_control/backends/errors.py +9 -0
- opentrons/hardware_control/backends/estop_state.py +164 -0
- opentrons/hardware_control/backends/flex_protocol.py +497 -0
- opentrons/hardware_control/backends/ot3controller.py +1930 -0
- opentrons/hardware_control/backends/ot3simulator.py +900 -0
- opentrons/hardware_control/backends/ot3utils.py +664 -0
- opentrons/hardware_control/backends/simulator.py +442 -0
- opentrons/hardware_control/backends/status_bar_state.py +240 -0
- opentrons/hardware_control/backends/subsystem_manager.py +431 -0
- opentrons/hardware_control/backends/tip_presence_manager.py +173 -0
- opentrons/hardware_control/backends/types.py +14 -0
- opentrons/hardware_control/constants.py +6 -0
- opentrons/hardware_control/dev_types.py +125 -0
- opentrons/hardware_control/emulation/__init__.py +0 -0
- opentrons/hardware_control/emulation/abstract_emulator.py +21 -0
- opentrons/hardware_control/emulation/app.py +56 -0
- opentrons/hardware_control/emulation/connection_handler.py +38 -0
- opentrons/hardware_control/emulation/heater_shaker.py +150 -0
- opentrons/hardware_control/emulation/magdeck.py +60 -0
- opentrons/hardware_control/emulation/module_server/__init__.py +8 -0
- opentrons/hardware_control/emulation/module_server/client.py +78 -0
- opentrons/hardware_control/emulation/module_server/helpers.py +130 -0
- opentrons/hardware_control/emulation/module_server/models.py +31 -0
- opentrons/hardware_control/emulation/module_server/server.py +110 -0
- opentrons/hardware_control/emulation/parser.py +74 -0
- opentrons/hardware_control/emulation/proxy.py +241 -0
- opentrons/hardware_control/emulation/run_emulator.py +68 -0
- opentrons/hardware_control/emulation/scripts/__init__.py +0 -0
- opentrons/hardware_control/emulation/scripts/run_app.py +54 -0
- opentrons/hardware_control/emulation/scripts/run_module_emulator.py +72 -0
- opentrons/hardware_control/emulation/scripts/run_smoothie.py +37 -0
- opentrons/hardware_control/emulation/settings.py +119 -0
- opentrons/hardware_control/emulation/simulations.py +133 -0
- opentrons/hardware_control/emulation/smoothie.py +192 -0
- opentrons/hardware_control/emulation/tempdeck.py +69 -0
- opentrons/hardware_control/emulation/thermocycler.py +128 -0
- opentrons/hardware_control/emulation/types.py +10 -0
- opentrons/hardware_control/emulation/util.py +38 -0
- opentrons/hardware_control/errors.py +43 -0
- opentrons/hardware_control/execution_manager.py +164 -0
- opentrons/hardware_control/instruments/__init__.py +5 -0
- opentrons/hardware_control/instruments/instrument_abc.py +39 -0
- opentrons/hardware_control/instruments/ot2/__init__.py +0 -0
- opentrons/hardware_control/instruments/ot2/instrument_calibration.py +152 -0
- opentrons/hardware_control/instruments/ot2/pipette.py +777 -0
- opentrons/hardware_control/instruments/ot2/pipette_handler.py +995 -0
- opentrons/hardware_control/instruments/ot3/__init__.py +0 -0
- opentrons/hardware_control/instruments/ot3/gripper.py +420 -0
- opentrons/hardware_control/instruments/ot3/gripper_handler.py +173 -0
- opentrons/hardware_control/instruments/ot3/instrument_calibration.py +214 -0
- opentrons/hardware_control/instruments/ot3/pipette.py +858 -0
- opentrons/hardware_control/instruments/ot3/pipette_handler.py +1030 -0
- opentrons/hardware_control/module_control.py +332 -0
- opentrons/hardware_control/modules/__init__.py +69 -0
- opentrons/hardware_control/modules/absorbance_reader.py +373 -0
- opentrons/hardware_control/modules/errors.py +7 -0
- opentrons/hardware_control/modules/flex_stacker.py +948 -0
- opentrons/hardware_control/modules/heater_shaker.py +426 -0
- opentrons/hardware_control/modules/lid_temp_status.py +35 -0
- opentrons/hardware_control/modules/magdeck.py +233 -0
- opentrons/hardware_control/modules/mod_abc.py +245 -0
- opentrons/hardware_control/modules/module_calibration.py +93 -0
- opentrons/hardware_control/modules/plate_temp_status.py +61 -0
- opentrons/hardware_control/modules/tempdeck.py +299 -0
- opentrons/hardware_control/modules/thermocycler.py +731 -0
- opentrons/hardware_control/modules/types.py +417 -0
- opentrons/hardware_control/modules/update.py +255 -0
- opentrons/hardware_control/modules/utils.py +73 -0
- opentrons/hardware_control/motion_utilities.py +318 -0
- opentrons/hardware_control/nozzle_manager.py +422 -0
- opentrons/hardware_control/ot3_calibration.py +1171 -0
- opentrons/hardware_control/ot3api.py +3227 -0
- opentrons/hardware_control/pause_manager.py +31 -0
- opentrons/hardware_control/poller.py +112 -0
- opentrons/hardware_control/protocols/__init__.py +106 -0
- opentrons/hardware_control/protocols/asyncio_configurable.py +11 -0
- opentrons/hardware_control/protocols/calibratable.py +45 -0
- opentrons/hardware_control/protocols/chassis_accessory_manager.py +90 -0
- opentrons/hardware_control/protocols/configurable.py +48 -0
- opentrons/hardware_control/protocols/event_sourcer.py +18 -0
- opentrons/hardware_control/protocols/execution_controllable.py +33 -0
- opentrons/hardware_control/protocols/flex_calibratable.py +96 -0
- opentrons/hardware_control/protocols/flex_instrument_configurer.py +52 -0
- opentrons/hardware_control/protocols/gripper_controller.py +55 -0
- opentrons/hardware_control/protocols/hardware_manager.py +51 -0
- opentrons/hardware_control/protocols/identifiable.py +16 -0
- opentrons/hardware_control/protocols/instrument_configurer.py +206 -0
- opentrons/hardware_control/protocols/liquid_handler.py +266 -0
- opentrons/hardware_control/protocols/module_provider.py +16 -0
- opentrons/hardware_control/protocols/motion_controller.py +243 -0
- opentrons/hardware_control/protocols/position_estimator.py +45 -0
- opentrons/hardware_control/protocols/simulatable.py +10 -0
- opentrons/hardware_control/protocols/stoppable.py +9 -0
- opentrons/hardware_control/protocols/types.py +27 -0
- opentrons/hardware_control/robot_calibration.py +224 -0
- opentrons/hardware_control/scripts/README.md +28 -0
- opentrons/hardware_control/scripts/__init__.py +1 -0
- opentrons/hardware_control/scripts/gripper_control.py +208 -0
- opentrons/hardware_control/scripts/ot3gripper +7 -0
- opentrons/hardware_control/scripts/ot3repl +7 -0
- opentrons/hardware_control/scripts/repl.py +187 -0
- opentrons/hardware_control/scripts/tc_control.py +97 -0
- opentrons/hardware_control/simulator_setup.py +260 -0
- opentrons/hardware_control/thread_manager.py +431 -0
- opentrons/hardware_control/threaded_async_lock.py +97 -0
- opentrons/hardware_control/types.py +792 -0
- opentrons/hardware_control/util.py +234 -0
- opentrons/legacy_broker.py +53 -0
- opentrons/legacy_commands/__init__.py +1 -0
- opentrons/legacy_commands/commands.py +483 -0
- opentrons/legacy_commands/helpers.py +153 -0
- opentrons/legacy_commands/module_commands.py +215 -0
- opentrons/legacy_commands/protocol_commands.py +54 -0
- opentrons/legacy_commands/publisher.py +155 -0
- opentrons/legacy_commands/robot_commands.py +51 -0
- opentrons/legacy_commands/types.py +1115 -0
- opentrons/motion_planning/__init__.py +32 -0
- opentrons/motion_planning/adjacent_slots_getters.py +168 -0
- opentrons/motion_planning/deck_conflict.py +396 -0
- opentrons/motion_planning/errors.py +35 -0
- opentrons/motion_planning/types.py +42 -0
- opentrons/motion_planning/waypoints.py +218 -0
- opentrons/ordered_set.py +138 -0
- opentrons/protocol_api/__init__.py +105 -0
- opentrons/protocol_api/_liquid.py +157 -0
- opentrons/protocol_api/_liquid_properties.py +814 -0
- opentrons/protocol_api/_nozzle_layout.py +31 -0
- opentrons/protocol_api/_parameter_context.py +300 -0
- opentrons/protocol_api/_parameters.py +31 -0
- opentrons/protocol_api/_transfer_liquid_validation.py +108 -0
- opentrons/protocol_api/_types.py +43 -0
- opentrons/protocol_api/config.py +23 -0
- opentrons/protocol_api/core/__init__.py +23 -0
- opentrons/protocol_api/core/common.py +33 -0
- opentrons/protocol_api/core/core_map.py +74 -0
- opentrons/protocol_api/core/engine/__init__.py +22 -0
- opentrons/protocol_api/core/engine/_default_labware_versions.py +179 -0
- opentrons/protocol_api/core/engine/deck_conflict.py +348 -0
- opentrons/protocol_api/core/engine/exceptions.py +19 -0
- opentrons/protocol_api/core/engine/instrument.py +2391 -0
- opentrons/protocol_api/core/engine/labware.py +238 -0
- opentrons/protocol_api/core/engine/load_labware_params.py +73 -0
- opentrons/protocol_api/core/engine/module_core.py +1025 -0
- opentrons/protocol_api/core/engine/overlap_versions.py +20 -0
- opentrons/protocol_api/core/engine/pipette_movement_conflict.py +358 -0
- opentrons/protocol_api/core/engine/point_calculations.py +64 -0
- opentrons/protocol_api/core/engine/protocol.py +1153 -0
- opentrons/protocol_api/core/engine/robot.py +139 -0
- opentrons/protocol_api/core/engine/stringify.py +74 -0
- opentrons/protocol_api/core/engine/transfer_components_executor.py +990 -0
- opentrons/protocol_api/core/engine/well.py +241 -0
- opentrons/protocol_api/core/instrument.py +459 -0
- opentrons/protocol_api/core/labware.py +151 -0
- opentrons/protocol_api/core/legacy/__init__.py +11 -0
- opentrons/protocol_api/core/legacy/_labware_geometry.py +37 -0
- opentrons/protocol_api/core/legacy/deck.py +369 -0
- opentrons/protocol_api/core/legacy/labware_offset_provider.py +108 -0
- opentrons/protocol_api/core/legacy/legacy_instrument_core.py +709 -0
- opentrons/protocol_api/core/legacy/legacy_labware_core.py +235 -0
- opentrons/protocol_api/core/legacy/legacy_module_core.py +592 -0
- opentrons/protocol_api/core/legacy/legacy_protocol_core.py +612 -0
- opentrons/protocol_api/core/legacy/legacy_well_core.py +162 -0
- opentrons/protocol_api/core/legacy/load_info.py +67 -0
- opentrons/protocol_api/core/legacy/module_geometry.py +547 -0
- opentrons/protocol_api/core/legacy/well_geometry.py +148 -0
- opentrons/protocol_api/core/legacy_simulator/__init__.py +16 -0
- opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +624 -0
- opentrons/protocol_api/core/legacy_simulator/legacy_protocol_core.py +85 -0
- opentrons/protocol_api/core/module.py +484 -0
- opentrons/protocol_api/core/protocol.py +311 -0
- opentrons/protocol_api/core/robot.py +51 -0
- opentrons/protocol_api/core/well.py +116 -0
- opentrons/protocol_api/core/well_grid.py +45 -0
- opentrons/protocol_api/create_protocol_context.py +177 -0
- opentrons/protocol_api/deck.py +223 -0
- opentrons/protocol_api/disposal_locations.py +244 -0
- opentrons/protocol_api/instrument_context.py +3212 -0
- opentrons/protocol_api/labware.py +1579 -0
- opentrons/protocol_api/module_contexts.py +1425 -0
- opentrons/protocol_api/module_validation_and_errors.py +61 -0
- opentrons/protocol_api/protocol_context.py +1688 -0
- opentrons/protocol_api/robot_context.py +303 -0
- opentrons/protocol_api/validation.py +761 -0
- opentrons/protocol_engine/__init__.py +155 -0
- opentrons/protocol_engine/actions/__init__.py +65 -0
- opentrons/protocol_engine/actions/action_dispatcher.py +30 -0
- opentrons/protocol_engine/actions/action_handler.py +13 -0
- opentrons/protocol_engine/actions/actions.py +302 -0
- opentrons/protocol_engine/actions/get_state_update.py +38 -0
- opentrons/protocol_engine/clients/__init__.py +5 -0
- opentrons/protocol_engine/clients/sync_client.py +174 -0
- opentrons/protocol_engine/clients/transports.py +197 -0
- opentrons/protocol_engine/commands/__init__.py +757 -0
- opentrons/protocol_engine/commands/absorbance_reader/__init__.py +61 -0
- opentrons/protocol_engine/commands/absorbance_reader/close_lid.py +154 -0
- opentrons/protocol_engine/commands/absorbance_reader/common.py +6 -0
- opentrons/protocol_engine/commands/absorbance_reader/initialize.py +151 -0
- opentrons/protocol_engine/commands/absorbance_reader/open_lid.py +154 -0
- opentrons/protocol_engine/commands/absorbance_reader/read.py +226 -0
- opentrons/protocol_engine/commands/air_gap_in_place.py +162 -0
- opentrons/protocol_engine/commands/aspirate.py +244 -0
- opentrons/protocol_engine/commands/aspirate_in_place.py +184 -0
- opentrons/protocol_engine/commands/aspirate_while_tracking.py +211 -0
- opentrons/protocol_engine/commands/blow_out.py +146 -0
- opentrons/protocol_engine/commands/blow_out_in_place.py +119 -0
- opentrons/protocol_engine/commands/calibration/__init__.py +60 -0
- opentrons/protocol_engine/commands/calibration/calibrate_gripper.py +166 -0
- opentrons/protocol_engine/commands/calibration/calibrate_module.py +117 -0
- opentrons/protocol_engine/commands/calibration/calibrate_pipette.py +96 -0
- opentrons/protocol_engine/commands/calibration/move_to_maintenance_position.py +156 -0
- opentrons/protocol_engine/commands/command.py +308 -0
- opentrons/protocol_engine/commands/command_unions.py +974 -0
- opentrons/protocol_engine/commands/comment.py +57 -0
- opentrons/protocol_engine/commands/configure_for_volume.py +108 -0
- opentrons/protocol_engine/commands/configure_nozzle_layout.py +115 -0
- opentrons/protocol_engine/commands/custom.py +67 -0
- opentrons/protocol_engine/commands/dispense.py +194 -0
- opentrons/protocol_engine/commands/dispense_in_place.py +179 -0
- opentrons/protocol_engine/commands/dispense_while_tracking.py +204 -0
- opentrons/protocol_engine/commands/drop_tip.py +232 -0
- opentrons/protocol_engine/commands/drop_tip_in_place.py +205 -0
- opentrons/protocol_engine/commands/flex_stacker/__init__.py +64 -0
- opentrons/protocol_engine/commands/flex_stacker/common.py +900 -0
- opentrons/protocol_engine/commands/flex_stacker/empty.py +293 -0
- opentrons/protocol_engine/commands/flex_stacker/fill.py +281 -0
- opentrons/protocol_engine/commands/flex_stacker/retrieve.py +339 -0
- opentrons/protocol_engine/commands/flex_stacker/set_stored_labware.py +328 -0
- opentrons/protocol_engine/commands/flex_stacker/store.py +326 -0
- opentrons/protocol_engine/commands/generate_command_schema.py +61 -0
- opentrons/protocol_engine/commands/get_next_tip.py +134 -0
- opentrons/protocol_engine/commands/get_tip_presence.py +87 -0
- opentrons/protocol_engine/commands/hash_command_params.py +38 -0
- opentrons/protocol_engine/commands/heater_shaker/__init__.py +102 -0
- opentrons/protocol_engine/commands/heater_shaker/close_labware_latch.py +83 -0
- opentrons/protocol_engine/commands/heater_shaker/deactivate_heater.py +82 -0
- opentrons/protocol_engine/commands/heater_shaker/deactivate_shaker.py +84 -0
- opentrons/protocol_engine/commands/heater_shaker/open_labware_latch.py +110 -0
- opentrons/protocol_engine/commands/heater_shaker/set_and_wait_for_shake_speed.py +125 -0
- opentrons/protocol_engine/commands/heater_shaker/set_target_temperature.py +90 -0
- opentrons/protocol_engine/commands/heater_shaker/wait_for_temperature.py +102 -0
- opentrons/protocol_engine/commands/home.py +100 -0
- opentrons/protocol_engine/commands/identify_module.py +86 -0
- opentrons/protocol_engine/commands/labware_handling_common.py +29 -0
- opentrons/protocol_engine/commands/liquid_probe.py +464 -0
- opentrons/protocol_engine/commands/load_labware.py +210 -0
- opentrons/protocol_engine/commands/load_lid.py +154 -0
- opentrons/protocol_engine/commands/load_lid_stack.py +272 -0
- opentrons/protocol_engine/commands/load_liquid.py +95 -0
- opentrons/protocol_engine/commands/load_liquid_class.py +144 -0
- opentrons/protocol_engine/commands/load_module.py +223 -0
- opentrons/protocol_engine/commands/load_pipette.py +167 -0
- opentrons/protocol_engine/commands/magnetic_module/__init__.py +32 -0
- opentrons/protocol_engine/commands/magnetic_module/disengage.py +97 -0
- opentrons/protocol_engine/commands/magnetic_module/engage.py +119 -0
- opentrons/protocol_engine/commands/move_labware.py +546 -0
- opentrons/protocol_engine/commands/move_relative.py +102 -0
- opentrons/protocol_engine/commands/move_to_addressable_area.py +176 -0
- opentrons/protocol_engine/commands/move_to_addressable_area_for_drop_tip.py +198 -0
- opentrons/protocol_engine/commands/move_to_coordinates.py +107 -0
- opentrons/protocol_engine/commands/move_to_well.py +119 -0
- opentrons/protocol_engine/commands/movement_common.py +338 -0
- opentrons/protocol_engine/commands/pick_up_tip.py +241 -0
- opentrons/protocol_engine/commands/pipetting_common.py +443 -0
- opentrons/protocol_engine/commands/prepare_to_aspirate.py +121 -0
- opentrons/protocol_engine/commands/pressure_dispense.py +155 -0
- opentrons/protocol_engine/commands/reload_labware.py +90 -0
- opentrons/protocol_engine/commands/retract_axis.py +75 -0
- opentrons/protocol_engine/commands/robot/__init__.py +70 -0
- opentrons/protocol_engine/commands/robot/close_gripper_jaw.py +96 -0
- opentrons/protocol_engine/commands/robot/common.py +18 -0
- opentrons/protocol_engine/commands/robot/move_axes_relative.py +101 -0
- opentrons/protocol_engine/commands/robot/move_axes_to.py +100 -0
- opentrons/protocol_engine/commands/robot/move_to.py +94 -0
- opentrons/protocol_engine/commands/robot/open_gripper_jaw.py +86 -0
- opentrons/protocol_engine/commands/save_position.py +109 -0
- opentrons/protocol_engine/commands/seal_pipette_to_tip.py +353 -0
- opentrons/protocol_engine/commands/set_rail_lights.py +67 -0
- opentrons/protocol_engine/commands/set_status_bar.py +89 -0
- opentrons/protocol_engine/commands/temperature_module/__init__.py +46 -0
- opentrons/protocol_engine/commands/temperature_module/deactivate.py +86 -0
- opentrons/protocol_engine/commands/temperature_module/set_target_temperature.py +97 -0
- opentrons/protocol_engine/commands/temperature_module/wait_for_temperature.py +104 -0
- opentrons/protocol_engine/commands/thermocycler/__init__.py +152 -0
- opentrons/protocol_engine/commands/thermocycler/close_lid.py +87 -0
- opentrons/protocol_engine/commands/thermocycler/deactivate_block.py +80 -0
- opentrons/protocol_engine/commands/thermocycler/deactivate_lid.py +80 -0
- opentrons/protocol_engine/commands/thermocycler/open_lid.py +87 -0
- opentrons/protocol_engine/commands/thermocycler/run_extended_profile.py +171 -0
- opentrons/protocol_engine/commands/thermocycler/run_profile.py +124 -0
- opentrons/protocol_engine/commands/thermocycler/set_target_block_temperature.py +140 -0
- opentrons/protocol_engine/commands/thermocycler/set_target_lid_temperature.py +100 -0
- opentrons/protocol_engine/commands/thermocycler/wait_for_block_temperature.py +93 -0
- opentrons/protocol_engine/commands/thermocycler/wait_for_lid_temperature.py +89 -0
- opentrons/protocol_engine/commands/touch_tip.py +189 -0
- opentrons/protocol_engine/commands/unsafe/__init__.py +161 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_blow_out_in_place.py +100 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_drop_tip_in_place.py +121 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_engage_axes.py +82 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_place_labware.py +208 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_stacker_close_latch.py +94 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_stacker_manual_retrieve.py +295 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_stacker_open_latch.py +91 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_stacker_prepare_shuttle.py +136 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_ungrip_labware.py +77 -0
- opentrons/protocol_engine/commands/unsafe/update_position_estimators.py +90 -0
- opentrons/protocol_engine/commands/unseal_pipette_from_tip.py +153 -0
- opentrons/protocol_engine/commands/verify_tip_presence.py +100 -0
- opentrons/protocol_engine/commands/wait_for_duration.py +76 -0
- opentrons/protocol_engine/commands/wait_for_resume.py +75 -0
- opentrons/protocol_engine/create_protocol_engine.py +193 -0
- opentrons/protocol_engine/engine_support.py +28 -0
- opentrons/protocol_engine/error_recovery_policy.py +81 -0
- opentrons/protocol_engine/errors/__init__.py +191 -0
- opentrons/protocol_engine/errors/error_occurrence.py +182 -0
- opentrons/protocol_engine/errors/exceptions.py +1308 -0
- opentrons/protocol_engine/execution/__init__.py +50 -0
- opentrons/protocol_engine/execution/command_executor.py +216 -0
- opentrons/protocol_engine/execution/create_queue_worker.py +102 -0
- opentrons/protocol_engine/execution/door_watcher.py +119 -0
- opentrons/protocol_engine/execution/equipment.py +819 -0
- opentrons/protocol_engine/execution/error_recovery_hardware_state_synchronizer.py +101 -0
- opentrons/protocol_engine/execution/gantry_mover.py +686 -0
- opentrons/protocol_engine/execution/hardware_stopper.py +147 -0
- opentrons/protocol_engine/execution/heater_shaker_movement_flagger.py +207 -0
- opentrons/protocol_engine/execution/labware_movement.py +297 -0
- opentrons/protocol_engine/execution/movement.py +349 -0
- opentrons/protocol_engine/execution/pipetting.py +607 -0
- opentrons/protocol_engine/execution/queue_worker.py +86 -0
- opentrons/protocol_engine/execution/rail_lights.py +25 -0
- opentrons/protocol_engine/execution/run_control.py +33 -0
- opentrons/protocol_engine/execution/status_bar.py +34 -0
- opentrons/protocol_engine/execution/thermocycler_movement_flagger.py +188 -0
- opentrons/protocol_engine/execution/thermocycler_plate_lifter.py +81 -0
- opentrons/protocol_engine/execution/tip_handler.py +550 -0
- opentrons/protocol_engine/labware_offset_standardization.py +194 -0
- opentrons/protocol_engine/notes/__init__.py +17 -0
- opentrons/protocol_engine/notes/notes.py +59 -0
- opentrons/protocol_engine/plugins.py +104 -0
- opentrons/protocol_engine/protocol_engine.py +683 -0
- opentrons/protocol_engine/resources/__init__.py +26 -0
- opentrons/protocol_engine/resources/deck_configuration_provider.py +232 -0
- opentrons/protocol_engine/resources/deck_data_provider.py +94 -0
- opentrons/protocol_engine/resources/file_provider.py +161 -0
- opentrons/protocol_engine/resources/fixture_validation.py +58 -0
- opentrons/protocol_engine/resources/labware_data_provider.py +106 -0
- opentrons/protocol_engine/resources/labware_validation.py +73 -0
- opentrons/protocol_engine/resources/model_utils.py +32 -0
- opentrons/protocol_engine/resources/module_data_provider.py +44 -0
- opentrons/protocol_engine/resources/ot3_validation.py +21 -0
- opentrons/protocol_engine/resources/pipette_data_provider.py +379 -0
- opentrons/protocol_engine/slot_standardization.py +128 -0
- opentrons/protocol_engine/state/__init__.py +1 -0
- opentrons/protocol_engine/state/_abstract_store.py +27 -0
- opentrons/protocol_engine/state/_axis_aligned_bounding_box.py +50 -0
- opentrons/protocol_engine/state/_labware_origin_math.py +636 -0
- opentrons/protocol_engine/state/_move_types.py +83 -0
- opentrons/protocol_engine/state/_well_math.py +193 -0
- opentrons/protocol_engine/state/addressable_areas.py +699 -0
- opentrons/protocol_engine/state/command_history.py +309 -0
- opentrons/protocol_engine/state/commands.py +1158 -0
- opentrons/protocol_engine/state/config.py +39 -0
- opentrons/protocol_engine/state/files.py +57 -0
- opentrons/protocol_engine/state/fluid_stack.py +138 -0
- opentrons/protocol_engine/state/geometry.py +2359 -0
- opentrons/protocol_engine/state/inner_well_math_utils.py +548 -0
- opentrons/protocol_engine/state/labware.py +1459 -0
- opentrons/protocol_engine/state/liquid_classes.py +82 -0
- opentrons/protocol_engine/state/liquids.py +73 -0
- opentrons/protocol_engine/state/module_substates/__init__.py +45 -0
- opentrons/protocol_engine/state/module_substates/absorbance_reader_substate.py +35 -0
- opentrons/protocol_engine/state/module_substates/flex_stacker_substate.py +112 -0
- opentrons/protocol_engine/state/module_substates/heater_shaker_module_substate.py +115 -0
- opentrons/protocol_engine/state/module_substates/magnetic_block_substate.py +17 -0
- opentrons/protocol_engine/state/module_substates/magnetic_module_substate.py +65 -0
- opentrons/protocol_engine/state/module_substates/temperature_module_substate.py +67 -0
- opentrons/protocol_engine/state/module_substates/thermocycler_module_substate.py +163 -0
- opentrons/protocol_engine/state/modules.py +1500 -0
- opentrons/protocol_engine/state/motion.py +373 -0
- opentrons/protocol_engine/state/pipettes.py +905 -0
- opentrons/protocol_engine/state/state.py +421 -0
- opentrons/protocol_engine/state/state_summary.py +36 -0
- opentrons/protocol_engine/state/tips.py +420 -0
- opentrons/protocol_engine/state/update_types.py +904 -0
- opentrons/protocol_engine/state/wells.py +290 -0
- opentrons/protocol_engine/types/__init__.py +308 -0
- opentrons/protocol_engine/types/automatic_tip_selection.py +39 -0
- opentrons/protocol_engine/types/command_annotations.py +53 -0
- opentrons/protocol_engine/types/deck_configuration.py +81 -0
- opentrons/protocol_engine/types/execution.py +96 -0
- opentrons/protocol_engine/types/hardware_passthrough.py +25 -0
- opentrons/protocol_engine/types/instrument.py +47 -0
- opentrons/protocol_engine/types/instrument_sensors.py +47 -0
- opentrons/protocol_engine/types/labware.py +131 -0
- opentrons/protocol_engine/types/labware_movement.py +22 -0
- opentrons/protocol_engine/types/labware_offset_location.py +111 -0
- opentrons/protocol_engine/types/labware_offset_vector.py +16 -0
- opentrons/protocol_engine/types/liquid.py +40 -0
- opentrons/protocol_engine/types/liquid_class.py +59 -0
- opentrons/protocol_engine/types/liquid_handling.py +13 -0
- opentrons/protocol_engine/types/liquid_level_detection.py +191 -0
- opentrons/protocol_engine/types/location.py +194 -0
- opentrons/protocol_engine/types/module.py +303 -0
- opentrons/protocol_engine/types/partial_tip_configuration.py +76 -0
- opentrons/protocol_engine/types/run_time_parameters.py +133 -0
- opentrons/protocol_engine/types/tip.py +18 -0
- opentrons/protocol_engine/types/util.py +21 -0
- opentrons/protocol_engine/types/well_position.py +124 -0
- opentrons/protocol_reader/__init__.py +37 -0
- opentrons/protocol_reader/extract_labware_definitions.py +66 -0
- opentrons/protocol_reader/file_format_validator.py +152 -0
- opentrons/protocol_reader/file_hasher.py +27 -0
- opentrons/protocol_reader/file_identifier.py +284 -0
- opentrons/protocol_reader/file_reader_writer.py +90 -0
- opentrons/protocol_reader/input_file.py +16 -0
- opentrons/protocol_reader/protocol_files_invalid_error.py +6 -0
- opentrons/protocol_reader/protocol_reader.py +188 -0
- opentrons/protocol_reader/protocol_source.py +124 -0
- opentrons/protocol_reader/role_analyzer.py +86 -0
- opentrons/protocol_runner/__init__.py +26 -0
- opentrons/protocol_runner/create_simulating_orchestrator.py +118 -0
- opentrons/protocol_runner/json_file_reader.py +55 -0
- opentrons/protocol_runner/json_translator.py +314 -0
- opentrons/protocol_runner/legacy_command_mapper.py +848 -0
- opentrons/protocol_runner/legacy_context_plugin.py +116 -0
- opentrons/protocol_runner/protocol_runner.py +530 -0
- opentrons/protocol_runner/python_protocol_wrappers.py +179 -0
- opentrons/protocol_runner/run_orchestrator.py +496 -0
- opentrons/protocol_runner/task_queue.py +95 -0
- opentrons/protocols/__init__.py +6 -0
- opentrons/protocols/advanced_control/__init__.py +0 -0
- opentrons/protocols/advanced_control/common.py +38 -0
- opentrons/protocols/advanced_control/mix.py +60 -0
- opentrons/protocols/advanced_control/transfers/__init__.py +0 -0
- opentrons/protocols/advanced_control/transfers/common.py +180 -0
- opentrons/protocols/advanced_control/transfers/transfer.py +972 -0
- opentrons/protocols/advanced_control/transfers/transfer_liquid_utils.py +231 -0
- opentrons/protocols/api_support/__init__.py +0 -0
- opentrons/protocols/api_support/constants.py +8 -0
- opentrons/protocols/api_support/deck_type.py +110 -0
- opentrons/protocols/api_support/definitions.py +18 -0
- opentrons/protocols/api_support/instrument.py +151 -0
- opentrons/protocols/api_support/labware_like.py +233 -0
- opentrons/protocols/api_support/tip_tracker.py +175 -0
- opentrons/protocols/api_support/types.py +32 -0
- opentrons/protocols/api_support/util.py +403 -0
- opentrons/protocols/bundle.py +89 -0
- opentrons/protocols/duration/__init__.py +4 -0
- opentrons/protocols/duration/errors.py +5 -0
- opentrons/protocols/duration/estimator.py +628 -0
- opentrons/protocols/execution/__init__.py +0 -0
- opentrons/protocols/execution/dev_types.py +181 -0
- opentrons/protocols/execution/errors.py +40 -0
- opentrons/protocols/execution/execute.py +84 -0
- opentrons/protocols/execution/execute_json_v3.py +275 -0
- opentrons/protocols/execution/execute_json_v4.py +359 -0
- opentrons/protocols/execution/execute_json_v5.py +28 -0
- opentrons/protocols/execution/execute_python.py +169 -0
- opentrons/protocols/execution/json_dispatchers.py +87 -0
- opentrons/protocols/execution/types.py +7 -0
- opentrons/protocols/geometry/__init__.py +0 -0
- opentrons/protocols/geometry/planning.py +297 -0
- opentrons/protocols/labware.py +312 -0
- opentrons/protocols/models/__init__.py +0 -0
- opentrons/protocols/models/json_protocol.py +679 -0
- opentrons/protocols/parameters/__init__.py +0 -0
- opentrons/protocols/parameters/csv_parameter_definition.py +77 -0
- opentrons/protocols/parameters/csv_parameter_interface.py +96 -0
- opentrons/protocols/parameters/exceptions.py +34 -0
- opentrons/protocols/parameters/parameter_definition.py +272 -0
- opentrons/protocols/parameters/types.py +17 -0
- opentrons/protocols/parameters/validation.py +267 -0
- opentrons/protocols/parse.py +671 -0
- opentrons/protocols/types.py +159 -0
- opentrons/py.typed +0 -0
- opentrons/resources/scripts/lpc21isp +0 -0
- opentrons/resources/smoothie-edge-8414642.hex +23010 -0
- opentrons/simulate.py +1065 -0
- opentrons/system/__init__.py +6 -0
- opentrons/system/camera.py +51 -0
- opentrons/system/log_control.py +59 -0
- opentrons/system/nmcli.py +856 -0
- opentrons/system/resin.py +24 -0
- opentrons/system/smoothie_update.py +15 -0
- opentrons/system/wifi.py +204 -0
- opentrons/tools/__init__.py +0 -0
- opentrons/tools/args_handler.py +22 -0
- opentrons/tools/write_pipette_memory.py +157 -0
- opentrons/types.py +618 -0
- opentrons/util/__init__.py +1 -0
- opentrons/util/async_helpers.py +166 -0
- opentrons/util/broker.py +84 -0
- opentrons/util/change_notifier.py +47 -0
- opentrons/util/entrypoint_util.py +278 -0
- opentrons/util/get_union_elements.py +26 -0
- opentrons/util/helpers.py +6 -0
- opentrons/util/linal.py +178 -0
- opentrons/util/logging_config.py +265 -0
- opentrons/util/logging_queue_handler.py +61 -0
- opentrons/util/performance_helpers.py +157 -0
- opentrons-8.6.0a1.dist-info/METADATA +37 -0
- opentrons-8.6.0a1.dist-info/RECORD +600 -0
- opentrons-8.6.0a1.dist-info/WHEEL +4 -0
- opentrons-8.6.0a1.dist-info/entry_points.txt +3 -0
- opentrons-8.6.0a1.dist-info/licenses/LICENSE +202 -0
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
"""Waypoint planning."""
|
|
2
|
+
from typing import List, Optional, Sequence, Tuple
|
|
3
|
+
from typing_extensions import Final
|
|
4
|
+
|
|
5
|
+
from opentrons.types import Point
|
|
6
|
+
from opentrons.hardware_control.types import CriticalPoint
|
|
7
|
+
|
|
8
|
+
from .types import Waypoint, MoveType, GripperMovementWaypointsWithJawStatus
|
|
9
|
+
from .errors import DestinationOutOfBoundsError, ArcOutOfBoundsError
|
|
10
|
+
from ..protocol_engine.types import LabwareMovementOffsetData
|
|
11
|
+
|
|
12
|
+
DEFAULT_GENERAL_ARC_Z_MARGIN: Final[float] = 10.0
|
|
13
|
+
DEFAULT_IN_LABWARE_ARC_Z_MARGIN: Final[float] = 5.0
|
|
14
|
+
MINIMUM_Z_MARGIN: Final[float] = 1.0
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def get_waypoints(
|
|
18
|
+
origin: Point,
|
|
19
|
+
dest: Point,
|
|
20
|
+
*,
|
|
21
|
+
max_travel_z: float,
|
|
22
|
+
min_travel_z: float,
|
|
23
|
+
move_type: MoveType = MoveType.GENERAL_ARC,
|
|
24
|
+
xy_waypoints: Sequence[Tuple[float, float]] = (),
|
|
25
|
+
origin_cp: Optional[CriticalPoint] = None,
|
|
26
|
+
dest_cp: Optional[CriticalPoint] = None,
|
|
27
|
+
) -> List[Waypoint]:
|
|
28
|
+
"""Get waypoints between an origin point and a destination point.
|
|
29
|
+
|
|
30
|
+
Given a move type and Z limits, which should be calculated according to
|
|
31
|
+
deck / labware / pipette geometry, creates waypoints with proper
|
|
32
|
+
z-clearances to move between `origin` and `dest`.
|
|
33
|
+
|
|
34
|
+
:param origin: The start point of the move.
|
|
35
|
+
:param dest: The end point of the move.
|
|
36
|
+
:param max_travel_z: The maximum allowed travel height of an arc move.
|
|
37
|
+
:param min_travel_z: The minimum allowed travel height of an arc move.
|
|
38
|
+
:param move_type: Direct move, in-labware arc, or general arc move type.
|
|
39
|
+
:param xy_waypoints: Extra XY destination waypoints to place in the path.
|
|
40
|
+
:param origin_cp: Pipette critical point override for origin waypoints.
|
|
41
|
+
:param dest_cp: Pipette critical point override for destination waypoints.
|
|
42
|
+
|
|
43
|
+
:returns: A list of :py:class:`.Waypoint` locations to move through.
|
|
44
|
+
"""
|
|
45
|
+
# NOTE(mm, 2022-06-22):
|
|
46
|
+
# This function is used by v6+ JSON protocols and v3+
|
|
47
|
+
# Python API protocols, but not v2 Python API protocols.
|
|
48
|
+
#
|
|
49
|
+
# To experiment with using this module in PAPIv2,
|
|
50
|
+
# flip the default of `use_experimental_waypoint_planning` to True
|
|
51
|
+
# in opentrons.protocols.geometry.planning.plan_moves
|
|
52
|
+
dest_waypoint = Waypoint(dest, dest_cp)
|
|
53
|
+
waypoints: List[Waypoint] = []
|
|
54
|
+
|
|
55
|
+
# a direct move can ignore all arc and waypoint planning
|
|
56
|
+
if move_type == MoveType.DIRECT:
|
|
57
|
+
# TODO(mm, 2022-06-17): This will not raise an out-of-bounds error
|
|
58
|
+
# even if the destination is far out of bounds. A protocol can run into this by
|
|
59
|
+
# doing a direct move to bad coordinates. Should we raise in that case?
|
|
60
|
+
return [dest_waypoint]
|
|
61
|
+
|
|
62
|
+
# ensure destination is not out of bounds
|
|
63
|
+
if dest.z + MINIMUM_Z_MARGIN > max_travel_z:
|
|
64
|
+
raise DestinationOutOfBoundsError(
|
|
65
|
+
origin=origin,
|
|
66
|
+
dest=dest,
|
|
67
|
+
clearance=MINIMUM_Z_MARGIN,
|
|
68
|
+
min_travel_z=min_travel_z,
|
|
69
|
+
max_travel_z=max_travel_z,
|
|
70
|
+
message="Destination out of bounds in the Z-axis",
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
# ensure that the passed in min_travel_z and max_travel_z are compatible
|
|
74
|
+
if min_travel_z + MINIMUM_Z_MARGIN > max_travel_z:
|
|
75
|
+
raise ArcOutOfBoundsError(
|
|
76
|
+
origin=origin,
|
|
77
|
+
dest=dest,
|
|
78
|
+
clearance=MINIMUM_Z_MARGIN,
|
|
79
|
+
min_travel_z=min_travel_z,
|
|
80
|
+
max_travel_z=max_travel_z,
|
|
81
|
+
message="Arc out of bounds in the Z-axis",
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
# set the z clearance according to the arc type
|
|
85
|
+
travel_z_margin = (
|
|
86
|
+
DEFAULT_GENERAL_ARC_Z_MARGIN
|
|
87
|
+
if move_type == MoveType.GENERAL_ARC
|
|
88
|
+
else DEFAULT_IN_LABWARE_ARC_Z_MARGIN
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
# set the actual travel z according to:
|
|
92
|
+
# use the max of min_travel_z with clearance or dest height
|
|
93
|
+
# if either of those exceed max_travel_z, just use max_travel_z
|
|
94
|
+
# if max_travel_z does not provide enough clearance, check above would
|
|
95
|
+
# raise an ArcOutOfBoundsError
|
|
96
|
+
# if origin.z is higher than the selected travel z, travel at origin.z instead
|
|
97
|
+
travel_z = max(
|
|
98
|
+
min(max_travel_z, max(min_travel_z + travel_z_margin, dest.z)),
|
|
99
|
+
origin.z,
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
# if origin.z isn't the travel height: add waypoint to move to origin.z
|
|
103
|
+
if travel_z > origin.z:
|
|
104
|
+
waypoints.append(Waypoint(origin._replace(z=travel_z), origin_cp))
|
|
105
|
+
|
|
106
|
+
# add any additional waypoints along with critical point blending
|
|
107
|
+
# see https://github.com/Opentrons/opentrons/pull/5662
|
|
108
|
+
# TODO(mc, 2020-11-05): if any critical point transitions can move in the
|
|
109
|
+
# Z axis, an extra waypoint for that transition will be needed
|
|
110
|
+
for x, y in xy_waypoints:
|
|
111
|
+
waypoints.append(Waypoint(Point(x=x, y=y, z=travel_z), dest_cp))
|
|
112
|
+
|
|
113
|
+
# if dest.z isn't the travel height: add waypoint to move to dest.z
|
|
114
|
+
# TODO(mc, 2020-11-05): if any critical point transitions can move in the
|
|
115
|
+
# Z axis, this conditional will need to be revised
|
|
116
|
+
if travel_z > dest.z:
|
|
117
|
+
waypoints.append(Waypoint(dest._replace(z=travel_z), dest_cp))
|
|
118
|
+
|
|
119
|
+
waypoints.append(dest_waypoint)
|
|
120
|
+
|
|
121
|
+
return waypoints
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def get_gripper_labware_movement_waypoints(
|
|
125
|
+
from_labware_center: Point,
|
|
126
|
+
to_labware_center: Point,
|
|
127
|
+
gripper_home_z: float,
|
|
128
|
+
offset_data: LabwareMovementOffsetData,
|
|
129
|
+
post_drop_slide_offset: Optional[Point],
|
|
130
|
+
gripper_home_z_offset: Optional[float] = None,
|
|
131
|
+
) -> List[GripperMovementWaypointsWithJawStatus]:
|
|
132
|
+
"""Get waypoints for moving labware using a gripper."""
|
|
133
|
+
pick_up_offset = offset_data.pickUpOffset
|
|
134
|
+
drop_offset = offset_data.dropOffset
|
|
135
|
+
|
|
136
|
+
pick_up_location = from_labware_center + Point(
|
|
137
|
+
pick_up_offset.x, pick_up_offset.y, pick_up_offset.z
|
|
138
|
+
)
|
|
139
|
+
drop_location = to_labware_center + Point(
|
|
140
|
+
drop_offset.x, drop_offset.y, drop_offset.z
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
gripper_max_z_home = gripper_home_z - (gripper_home_z_offset or 0)
|
|
144
|
+
|
|
145
|
+
post_drop_home_pos = Point(drop_location.x, drop_location.y, gripper_home_z)
|
|
146
|
+
|
|
147
|
+
waypoints_with_jaw_status = [
|
|
148
|
+
GripperMovementWaypointsWithJawStatus(
|
|
149
|
+
position=Point(pick_up_location.x, pick_up_location.y, gripper_home_z),
|
|
150
|
+
jaw_open=False,
|
|
151
|
+
dropping=False,
|
|
152
|
+
),
|
|
153
|
+
GripperMovementWaypointsWithJawStatus(
|
|
154
|
+
position=pick_up_location, jaw_open=True, dropping=False
|
|
155
|
+
),
|
|
156
|
+
# Gripper grips the labware here
|
|
157
|
+
GripperMovementWaypointsWithJawStatus(
|
|
158
|
+
position=Point(pick_up_location.x, pick_up_location.y, gripper_max_z_home),
|
|
159
|
+
jaw_open=False,
|
|
160
|
+
dropping=False,
|
|
161
|
+
),
|
|
162
|
+
GripperMovementWaypointsWithJawStatus(
|
|
163
|
+
position=Point(drop_location.x, drop_location.y, gripper_max_z_home),
|
|
164
|
+
jaw_open=False,
|
|
165
|
+
dropping=False,
|
|
166
|
+
),
|
|
167
|
+
GripperMovementWaypointsWithJawStatus(
|
|
168
|
+
position=drop_location, jaw_open=False, dropping=False
|
|
169
|
+
),
|
|
170
|
+
# Gripper ungrips here
|
|
171
|
+
GripperMovementWaypointsWithJawStatus(
|
|
172
|
+
position=post_drop_home_pos,
|
|
173
|
+
jaw_open=True,
|
|
174
|
+
dropping=True,
|
|
175
|
+
),
|
|
176
|
+
]
|
|
177
|
+
if post_drop_slide_offset is not None:
|
|
178
|
+
# IF it is specified, add one more step after homing the gripper
|
|
179
|
+
waypoints_with_jaw_status.append(
|
|
180
|
+
GripperMovementWaypointsWithJawStatus(
|
|
181
|
+
position=post_drop_home_pos + post_drop_slide_offset,
|
|
182
|
+
jaw_open=True,
|
|
183
|
+
dropping=False,
|
|
184
|
+
)
|
|
185
|
+
)
|
|
186
|
+
return waypoints_with_jaw_status
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def get_gripper_labware_placement_waypoints(
|
|
190
|
+
to_labware_center: Point,
|
|
191
|
+
gripper_home_z: float,
|
|
192
|
+
drop_offset: Optional[Point],
|
|
193
|
+
) -> List[GripperMovementWaypointsWithJawStatus]:
|
|
194
|
+
"""Get waypoints for placing labware using a gripper."""
|
|
195
|
+
drop_offset = drop_offset or Point()
|
|
196
|
+
|
|
197
|
+
drop_location = to_labware_center + Point(
|
|
198
|
+
drop_offset.x, drop_offset.y, drop_offset.z
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
post_drop_home_pos = Point(drop_location.x, drop_location.y, gripper_home_z)
|
|
202
|
+
|
|
203
|
+
return [
|
|
204
|
+
GripperMovementWaypointsWithJawStatus(
|
|
205
|
+
position=Point(drop_location.x, drop_location.y, gripper_home_z),
|
|
206
|
+
jaw_open=False,
|
|
207
|
+
dropping=False,
|
|
208
|
+
),
|
|
209
|
+
GripperMovementWaypointsWithJawStatus(
|
|
210
|
+
position=drop_location, jaw_open=False, dropping=False
|
|
211
|
+
),
|
|
212
|
+
# Gripper ungrips here
|
|
213
|
+
GripperMovementWaypointsWithJawStatus(
|
|
214
|
+
position=post_drop_home_pos,
|
|
215
|
+
jaw_open=True,
|
|
216
|
+
dropping=True,
|
|
217
|
+
),
|
|
218
|
+
]
|
opentrons/ordered_set.py
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
"""A set that preserves the order in which elements are added."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import (
|
|
6
|
+
Dict,
|
|
7
|
+
Generic,
|
|
8
|
+
Hashable,
|
|
9
|
+
Iterable,
|
|
10
|
+
Iterator,
|
|
11
|
+
Set,
|
|
12
|
+
TypeVar,
|
|
13
|
+
Union,
|
|
14
|
+
overload,
|
|
15
|
+
)
|
|
16
|
+
from typing_extensions import Literal
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
_SetElementT = TypeVar("_SetElementT", bound=Hashable)
|
|
20
|
+
|
|
21
|
+
_DefaultValueT = TypeVar("_DefaultValueT")
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class _NOT_SPECIFIED:
|
|
25
|
+
"""Value not specified sentinel."""
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
# Implemented as a standalone class for clarity.
|
|
29
|
+
# If this proves insufficient, we can get many methods for free
|
|
30
|
+
# by subclassing collections.abc.MutableSet.
|
|
31
|
+
class OrderedSet(Generic[_SetElementT]):
|
|
32
|
+
"""A set that preserves the order in which elements are added.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
source_iterable: An ordered iterable of initial elements.
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
def __init__(self, source_iterable: Iterable[_SetElementT] = tuple()) -> None:
|
|
39
|
+
self._elements: Dict[_SetElementT, Literal[True]] = {}
|
|
40
|
+
|
|
41
|
+
for element in source_iterable:
|
|
42
|
+
self.add(element)
|
|
43
|
+
|
|
44
|
+
def add(self, element: _SetElementT) -> None:
|
|
45
|
+
"""Add ``element`` to the set.
|
|
46
|
+
|
|
47
|
+
If ``element`` is already in the set, it is not added again,
|
|
48
|
+
and its existing position in the set is retained.
|
|
49
|
+
"""
|
|
50
|
+
self._elements[element] = True
|
|
51
|
+
|
|
52
|
+
def remove(self, element: _SetElementT) -> None:
|
|
53
|
+
"""Remove ``element`` from the set.
|
|
54
|
+
|
|
55
|
+
Raises:
|
|
56
|
+
KeyError: If ``element`` is not in the set.
|
|
57
|
+
"""
|
|
58
|
+
del self._elements[element]
|
|
59
|
+
|
|
60
|
+
def discard(self, element: _SetElementT) -> None:
|
|
61
|
+
"""Remove ``element`` from the set, if it is present."""
|
|
62
|
+
try:
|
|
63
|
+
self.remove(element)
|
|
64
|
+
except KeyError:
|
|
65
|
+
pass
|
|
66
|
+
|
|
67
|
+
def clear(self) -> None:
|
|
68
|
+
"""Remove all elements from the set."""
|
|
69
|
+
self._elements.clear()
|
|
70
|
+
|
|
71
|
+
@overload
|
|
72
|
+
def head(self) -> _SetElementT:
|
|
73
|
+
...
|
|
74
|
+
|
|
75
|
+
@overload
|
|
76
|
+
def head(
|
|
77
|
+
self, default_value: _DefaultValueT
|
|
78
|
+
) -> Union[_SetElementT, _DefaultValueT]:
|
|
79
|
+
...
|
|
80
|
+
|
|
81
|
+
def head(
|
|
82
|
+
self, default_value: Union[_DefaultValueT, _NOT_SPECIFIED] = _NOT_SPECIFIED()
|
|
83
|
+
) -> Union[_SetElementT, _DefaultValueT]:
|
|
84
|
+
"""Get the head (oldest-added element) of the set.
|
|
85
|
+
|
|
86
|
+
Args:
|
|
87
|
+
default_value: A value to return if set is empty.
|
|
88
|
+
|
|
89
|
+
Returns:
|
|
90
|
+
The head of the set, or the default value, if specified.
|
|
91
|
+
|
|
92
|
+
Raises:
|
|
93
|
+
IndexError: set is empty and default was not specified.
|
|
94
|
+
"""
|
|
95
|
+
try:
|
|
96
|
+
return next(iter(self._elements))
|
|
97
|
+
except StopIteration:
|
|
98
|
+
if isinstance(default_value, _NOT_SPECIFIED):
|
|
99
|
+
raise IndexError("Set is empty") from None
|
|
100
|
+
else:
|
|
101
|
+
return default_value
|
|
102
|
+
|
|
103
|
+
def __iter__(self) -> Iterator[_SetElementT]:
|
|
104
|
+
"""Enable iteration over all elements in the set.
|
|
105
|
+
|
|
106
|
+
Elements are returned in the order they were added, oldest first.
|
|
107
|
+
"""
|
|
108
|
+
return iter(self._elements)
|
|
109
|
+
|
|
110
|
+
def __len__(self) -> int:
|
|
111
|
+
"""Return the number of unique elements added to the set."""
|
|
112
|
+
return len(self._elements)
|
|
113
|
+
|
|
114
|
+
def __eq__(self, other: object) -> bool:
|
|
115
|
+
"""Return whether this set is equal to another object.
|
|
116
|
+
|
|
117
|
+
True if the other object is also an ordered set,
|
|
118
|
+
and it contains the same elements in the same order.
|
|
119
|
+
"""
|
|
120
|
+
if isinstance(other, OrderedSet):
|
|
121
|
+
return list(self) == list(other)
|
|
122
|
+
else:
|
|
123
|
+
return False
|
|
124
|
+
|
|
125
|
+
def __sub__(
|
|
126
|
+
self, other: Union[OrderedSet[_SetElementT], Set[_SetElementT]]
|
|
127
|
+
) -> OrderedSet[_SetElementT]:
|
|
128
|
+
"""Return this set, without any elements that appear in `other`.
|
|
129
|
+
|
|
130
|
+
The elements that aren't removed retain their original relative order.
|
|
131
|
+
"""
|
|
132
|
+
return OrderedSet(e for e in self if e not in other)
|
|
133
|
+
|
|
134
|
+
def __repr__(self) -> str: # noqa: D105
|
|
135
|
+
# Use repr() on the keys view in case it's super long and Python is smart
|
|
136
|
+
# enough to abbreviate it.
|
|
137
|
+
elements_str = repr(self._elements.keys())
|
|
138
|
+
return f"OrderedSet({elements_str})"
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"""protocol_api: The user-facing API for Opentrons OT-2 and Opentrons Flex protocols.
|
|
2
|
+
|
|
3
|
+
This package defines classes and functions for Python protocols to
|
|
4
|
+
control an OT-2 or Flex robot.
|
|
5
|
+
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from opentrons.protocols.api_support.definitions import (
|
|
9
|
+
MAX_SUPPORTED_VERSION,
|
|
10
|
+
MIN_SUPPORTED_VERSION,
|
|
11
|
+
MIN_SUPPORTED_VERSION_FOR_FLEX,
|
|
12
|
+
)
|
|
13
|
+
from opentrons.protocols.parameters.exceptions import (
|
|
14
|
+
RuntimeParameterRequired as RuntimeParameterRequiredError,
|
|
15
|
+
)
|
|
16
|
+
from opentrons.protocols.parameters.csv_parameter_interface import CSVParameter
|
|
17
|
+
|
|
18
|
+
from .protocol_context import ProtocolContext
|
|
19
|
+
from .deck import Deck
|
|
20
|
+
from .robot_context import RobotContext
|
|
21
|
+
from .instrument_context import InstrumentContext
|
|
22
|
+
from .labware import Labware, Well
|
|
23
|
+
from .module_contexts import (
|
|
24
|
+
ModuleContext,
|
|
25
|
+
ThermocyclerContext,
|
|
26
|
+
MagneticModuleContext,
|
|
27
|
+
TemperatureModuleContext,
|
|
28
|
+
HeaterShakerContext,
|
|
29
|
+
MagneticBlockContext,
|
|
30
|
+
AbsorbanceReaderContext,
|
|
31
|
+
FlexStackerContext,
|
|
32
|
+
)
|
|
33
|
+
from .disposal_locations import TrashBin, WasteChute
|
|
34
|
+
from ._liquid import Liquid, LiquidClass
|
|
35
|
+
from ._types import (
|
|
36
|
+
OFF_DECK,
|
|
37
|
+
PLUNGER_BLOWOUT,
|
|
38
|
+
PLUNGER_TOP,
|
|
39
|
+
PLUNGER_BOTTOM,
|
|
40
|
+
PLUNGER_DROPTIP,
|
|
41
|
+
ASPIRATE_ACTION,
|
|
42
|
+
DISPENSE_ACTION,
|
|
43
|
+
BLOWOUT_ACTION,
|
|
44
|
+
)
|
|
45
|
+
from ._nozzle_layout import (
|
|
46
|
+
COLUMN,
|
|
47
|
+
PARTIAL_COLUMN,
|
|
48
|
+
SINGLE,
|
|
49
|
+
ROW,
|
|
50
|
+
ALL,
|
|
51
|
+
)
|
|
52
|
+
from ._parameters import Parameters
|
|
53
|
+
from ._parameter_context import ParameterContext
|
|
54
|
+
|
|
55
|
+
from .create_protocol_context import (
|
|
56
|
+
create_protocol_context,
|
|
57
|
+
ProtocolEngineCoreRequiredError,
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
__all__ = [
|
|
61
|
+
"MAX_SUPPORTED_VERSION",
|
|
62
|
+
"MIN_SUPPORTED_VERSION",
|
|
63
|
+
"MIN_SUPPORTED_VERSION_FOR_FLEX",
|
|
64
|
+
"ProtocolContext",
|
|
65
|
+
"Deck",
|
|
66
|
+
"ModuleContext",
|
|
67
|
+
"RobotContext",
|
|
68
|
+
"InstrumentContext",
|
|
69
|
+
"TemperatureModuleContext",
|
|
70
|
+
"MagneticModuleContext",
|
|
71
|
+
"ThermocyclerContext",
|
|
72
|
+
"HeaterShakerContext",
|
|
73
|
+
"MagneticBlockContext",
|
|
74
|
+
"AbsorbanceReaderContext",
|
|
75
|
+
"FlexStackerContext",
|
|
76
|
+
"ParameterContext",
|
|
77
|
+
"Labware",
|
|
78
|
+
"TrashBin",
|
|
79
|
+
"WasteChute",
|
|
80
|
+
"Well",
|
|
81
|
+
"Liquid",
|
|
82
|
+
"LiquidClass",
|
|
83
|
+
"Parameters",
|
|
84
|
+
# Partial Tip types
|
|
85
|
+
"COLUMN",
|
|
86
|
+
"PARTIAL_COLUMN",
|
|
87
|
+
"SINGLE",
|
|
88
|
+
"ROW",
|
|
89
|
+
"ALL",
|
|
90
|
+
# Deck location types
|
|
91
|
+
"OFF_DECK",
|
|
92
|
+
# Pipette plunger types
|
|
93
|
+
"PLUNGER_BLOWOUT",
|
|
94
|
+
"PLUNGER_TOP",
|
|
95
|
+
"PLUNGER_BOTTOM",
|
|
96
|
+
"PLUNGER_DROPTIP",
|
|
97
|
+
"ASPIRATE_ACTION",
|
|
98
|
+
"DISPENSE_ACTION",
|
|
99
|
+
"BLOWOUT_ACTION",
|
|
100
|
+
"RuntimeParameterRequiredError",
|
|
101
|
+
"CSVParameter",
|
|
102
|
+
# For internal Opentrons use only:
|
|
103
|
+
"create_protocol_context",
|
|
104
|
+
"ProtocolEngineCoreRequiredError",
|
|
105
|
+
]
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import Optional, Dict, Union, TYPE_CHECKING, Tuple
|
|
5
|
+
|
|
6
|
+
from opentrons_shared_data.liquid_classes.liquid_class_definition import (
|
|
7
|
+
LiquidClassSchemaV1,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
from opentrons.protocols.advanced_control.transfers.common import (
|
|
11
|
+
NoLiquidClassPropertyError,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
from ._liquid_properties import (
|
|
15
|
+
TransferProperties,
|
|
16
|
+
build_transfer_properties,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
if TYPE_CHECKING:
|
|
20
|
+
from . import InstrumentContext, Labware
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@dataclass(frozen=True)
|
|
24
|
+
class Liquid:
|
|
25
|
+
"""A liquid to load into a well.
|
|
26
|
+
|
|
27
|
+
Attributes:
|
|
28
|
+
name: A human-readable name for the liquid.
|
|
29
|
+
description: An optional description.
|
|
30
|
+
display_color: An optional display color for the liquid.
|
|
31
|
+
|
|
32
|
+
.. versionadded:: 2.14
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
_id: str
|
|
36
|
+
name: str
|
|
37
|
+
description: Optional[str]
|
|
38
|
+
display_color: Optional[str]
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@dataclass
|
|
42
|
+
class LiquidClass:
|
|
43
|
+
"""A data class that contains properties of a specific class of liquids."""
|
|
44
|
+
|
|
45
|
+
_name: str
|
|
46
|
+
_display_name: str
|
|
47
|
+
_by_pipette_setting: Dict[str, Dict[str, TransferProperties]]
|
|
48
|
+
|
|
49
|
+
@classmethod
|
|
50
|
+
def create(cls, liquid_class_definition: LiquidClassSchemaV1) -> "LiquidClass":
|
|
51
|
+
"""Liquid class factory method."""
|
|
52
|
+
|
|
53
|
+
by_pipette_settings: Dict[str, Dict[str, TransferProperties]] = {}
|
|
54
|
+
for by_pipette in liquid_class_definition.byPipette:
|
|
55
|
+
tip_settings: Dict[str, TransferProperties] = {}
|
|
56
|
+
for tip_type in by_pipette.byTipType:
|
|
57
|
+
tip_settings[tip_type.tiprack] = build_transfer_properties(tip_type)
|
|
58
|
+
by_pipette_settings[by_pipette.pipetteModel] = tip_settings
|
|
59
|
+
|
|
60
|
+
return cls(
|
|
61
|
+
_name=liquid_class_definition.liquidClassName,
|
|
62
|
+
_display_name=liquid_class_definition.displayName,
|
|
63
|
+
_by_pipette_setting=by_pipette_settings,
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
@classmethod
|
|
67
|
+
def create_from(
|
|
68
|
+
cls,
|
|
69
|
+
name: str,
|
|
70
|
+
display_name: str,
|
|
71
|
+
by_pipette_setting: Dict[str, Dict[str, TransferProperties]],
|
|
72
|
+
) -> "LiquidClass":
|
|
73
|
+
"""Create a liquid class from the passed in args."""
|
|
74
|
+
return cls(
|
|
75
|
+
_name=name,
|
|
76
|
+
_display_name=display_name,
|
|
77
|
+
_by_pipette_setting=by_pipette_setting,
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
@property
|
|
81
|
+
def name(self) -> str:
|
|
82
|
+
return self._name
|
|
83
|
+
|
|
84
|
+
@property
|
|
85
|
+
def display_name(self) -> str:
|
|
86
|
+
return self._display_name
|
|
87
|
+
|
|
88
|
+
def update_for(
|
|
89
|
+
self,
|
|
90
|
+
pipette: Union[str, InstrumentContext],
|
|
91
|
+
tip_rack: Union[str, Labware],
|
|
92
|
+
transfer_properties: TransferProperties,
|
|
93
|
+
) -> None:
|
|
94
|
+
"""Update the transfer properties for the given pipette and tip combo.
|
|
95
|
+
|
|
96
|
+
If an entry does not exist, it will be created.
|
|
97
|
+
"""
|
|
98
|
+
pipette_name, tiprack_uri = self._get_pipette_and_tiprack_names(
|
|
99
|
+
pipette, tip_rack
|
|
100
|
+
)
|
|
101
|
+
try:
|
|
102
|
+
self._by_pipette_setting[pipette_name].update(
|
|
103
|
+
{tiprack_uri: transfer_properties}
|
|
104
|
+
)
|
|
105
|
+
except KeyError:
|
|
106
|
+
self._by_pipette_setting[pipette_name] = {tiprack_uri: transfer_properties}
|
|
107
|
+
|
|
108
|
+
def get_for(
|
|
109
|
+
self, pipette: Union[str, InstrumentContext], tip_rack: Union[str, Labware]
|
|
110
|
+
) -> TransferProperties:
|
|
111
|
+
"""Get liquid class transfer properties for the specified pipette and tip."""
|
|
112
|
+
pipette_name, tiprack_uri = self._get_pipette_and_tiprack_names(
|
|
113
|
+
pipette, tip_rack
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
try:
|
|
117
|
+
settings_for_pipette = self._by_pipette_setting[pipette_name]
|
|
118
|
+
except KeyError:
|
|
119
|
+
raise NoLiquidClassPropertyError(
|
|
120
|
+
f"No properties found for {pipette_name} in {self._name} liquid class"
|
|
121
|
+
)
|
|
122
|
+
try:
|
|
123
|
+
transfer_properties = settings_for_pipette[tiprack_uri]
|
|
124
|
+
except KeyError:
|
|
125
|
+
raise NoLiquidClassPropertyError(
|
|
126
|
+
f"No properties found for {tiprack_uri} for {pipette_name} in {self._name} liquid class"
|
|
127
|
+
)
|
|
128
|
+
return transfer_properties
|
|
129
|
+
|
|
130
|
+
@staticmethod
|
|
131
|
+
def _get_pipette_and_tiprack_names(
|
|
132
|
+
pipette: Union[str, InstrumentContext],
|
|
133
|
+
tip_rack: Union[str, Labware],
|
|
134
|
+
) -> Tuple[str, str]:
|
|
135
|
+
"""Return the pipette and tip rack name strings from the given pipette and tip rack."""
|
|
136
|
+
from . import InstrumentContext, Labware
|
|
137
|
+
|
|
138
|
+
if isinstance(pipette, InstrumentContext):
|
|
139
|
+
pipette_name = pipette.name
|
|
140
|
+
elif isinstance(pipette, str):
|
|
141
|
+
pipette_name = pipette
|
|
142
|
+
else:
|
|
143
|
+
raise ValueError(
|
|
144
|
+
f"{pipette} should either be an InstrumentContext object"
|
|
145
|
+
f" or a pipette name string."
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
if isinstance(tip_rack, Labware):
|
|
149
|
+
tiprack_uri = tip_rack.uri
|
|
150
|
+
elif isinstance(tip_rack, str):
|
|
151
|
+
tiprack_uri = tip_rack
|
|
152
|
+
else:
|
|
153
|
+
raise ValueError(
|
|
154
|
+
f"{tip_rack} should either be a tiprack Labware object"
|
|
155
|
+
f" or a tiprack URI string."
|
|
156
|
+
)
|
|
157
|
+
return pipette_name, tiprack_uri
|