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,231 @@
|
|
|
1
|
+
"""Utility functions for transfer_liquid, consolidate_liquid and distribute_liquid"""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from typing import Literal, Sequence, List, Optional, TYPE_CHECKING
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
|
|
7
|
+
from opentrons.protocol_engine.errors import (
|
|
8
|
+
LiquidHeightUnknownError,
|
|
9
|
+
IncompleteLabwareDefinitionError,
|
|
10
|
+
)
|
|
11
|
+
from opentrons.protocol_engine.state._well_math import (
|
|
12
|
+
wells_covered_by_pipette_configuration,
|
|
13
|
+
)
|
|
14
|
+
from opentrons.types import NozzleMapInterface, NozzleConfigurationType
|
|
15
|
+
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
|
+
from logging import Logger
|
|
18
|
+
from opentrons.types import Location
|
|
19
|
+
from opentrons.protocol_api.core.engine import WellCore
|
|
20
|
+
from opentrons.protocol_api.labware import Well, Labware
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@dataclass
|
|
24
|
+
class LocationCheckDescriptors:
|
|
25
|
+
location_type: Literal["submerge start", "retract end"]
|
|
26
|
+
pipetting_action: Literal["aspirate", "dispense"]
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def raise_if_location_inside_liquid(
|
|
30
|
+
location: Location,
|
|
31
|
+
well_core: WellCore,
|
|
32
|
+
location_check_descriptors: LocationCheckDescriptors,
|
|
33
|
+
logger: Logger,
|
|
34
|
+
) -> None:
|
|
35
|
+
"""Raise an error if the location in question would be inside the liquid.
|
|
36
|
+
|
|
37
|
+
This checker will raise an error if we can find the liquid height
|
|
38
|
+
AND the location in question is below this height.
|
|
39
|
+
|
|
40
|
+
If we can't find the liquid height, then we simply log the details and no error is raised.
|
|
41
|
+
"""
|
|
42
|
+
try:
|
|
43
|
+
liquid_height_from_bottom = well_core.current_liquid_height()
|
|
44
|
+
except (IncompleteLabwareDefinitionError, LiquidHeightUnknownError):
|
|
45
|
+
# IncompleteLabwareDefinitionError is raised when there's no inner geometry
|
|
46
|
+
# defined for the well. So, we can't find the liquid height even if liquid volume is known.
|
|
47
|
+
# LiquidHeightUnknownError is raised when we don't have liquid volume info
|
|
48
|
+
# and no probing has been done either.
|
|
49
|
+
liquid_height_from_bottom = None
|
|
50
|
+
if isinstance(liquid_height_from_bottom, (int, float)):
|
|
51
|
+
if liquid_height_from_bottom + well_core.get_bottom(0).z > location.point.z:
|
|
52
|
+
raise RuntimeError(
|
|
53
|
+
f"{location_check_descriptors.location_type.capitalize()} location {location} is"
|
|
54
|
+
f" inside the liquid in well {well_core.get_display_name()} when it should be outside"
|
|
55
|
+
f"(above) the liquid."
|
|
56
|
+
)
|
|
57
|
+
else:
|
|
58
|
+
# We could raise an error here but that would restrict the use of
|
|
59
|
+
# liquid classes-based transfer to only when LPD is enabled or when liquids are
|
|
60
|
+
# loaded in protocols using `load_liquid`. This can be quite restrictive
|
|
61
|
+
# so we will not raise but just log the details.
|
|
62
|
+
logger.info(
|
|
63
|
+
f"Could not verify height of liquid in well {well_core.get_display_name()}, either"
|
|
64
|
+
f" because the liquid in this well has not been probed or"
|
|
65
|
+
f" liquid was not loaded in this well using `load_liquid` or"
|
|
66
|
+
f" inner geometry is not available for the target well."
|
|
67
|
+
f" Proceeding without verifying if {location_check_descriptors.location_type}"
|
|
68
|
+
f" location is outside the liquid."
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def group_wells_for_multi_channel_transfer(
|
|
73
|
+
targets: Sequence[Well],
|
|
74
|
+
nozzle_map: NozzleMapInterface,
|
|
75
|
+
target_name: Literal["source", "destination"],
|
|
76
|
+
) -> List[Well]:
|
|
77
|
+
"""Takes a list of wells and a nozzle map and returns a list of target wells to address every well given
|
|
78
|
+
|
|
79
|
+
This currently only supports 8-tip columns, 12-tip rows and full 96-channel configurations,
|
|
80
|
+
and only is used for 96 and 384 well plates. This assumes the wells are being given in a
|
|
81
|
+
contiguous order (or every other for 384), and will raise if a well is found that does not overlap
|
|
82
|
+
with the first target well given for a sequence, or if not all wells are given for that sequence.
|
|
83
|
+
"""
|
|
84
|
+
configuration = nozzle_map.configuration
|
|
85
|
+
active_nozzles = nozzle_map.tip_count
|
|
86
|
+
|
|
87
|
+
if (
|
|
88
|
+
(
|
|
89
|
+
(
|
|
90
|
+
configuration == NozzleConfigurationType.COLUMN
|
|
91
|
+
or configuration == NozzleConfigurationType.FULL
|
|
92
|
+
)
|
|
93
|
+
and active_nozzles == 8
|
|
94
|
+
)
|
|
95
|
+
or (configuration == NozzleConfigurationType.ROW and active_nozzles == 12)
|
|
96
|
+
or active_nozzles == 96
|
|
97
|
+
):
|
|
98
|
+
return _group_wells_for_nozzle_configuration(
|
|
99
|
+
list(targets), nozzle_map, target_name
|
|
100
|
+
)
|
|
101
|
+
else:
|
|
102
|
+
raise ValueError(
|
|
103
|
+
"Unsupported nozzle configuration for well grouping. Set group_wells to False"
|
|
104
|
+
" to only target wells with the primary nozzle for this configuration."
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def _group_wells_for_nozzle_configuration( # noqa: C901
|
|
109
|
+
targets: List[Well],
|
|
110
|
+
nozzle_map: NozzleMapInterface,
|
|
111
|
+
target_name: Literal["source", "destination"],
|
|
112
|
+
) -> List[Well]:
|
|
113
|
+
"""Groups wells together for a column, row, or full 96 configuration and returns a reduced list of target wells."""
|
|
114
|
+
grouped_wells = []
|
|
115
|
+
active_wells_covered: List[str] = []
|
|
116
|
+
active_labware: Optional[Labware] = None
|
|
117
|
+
alternate_384_well_coverage_count = 0
|
|
118
|
+
labware_format: Optional[str] = None
|
|
119
|
+
|
|
120
|
+
# We are assuming the wells are ordered A1, B1, C1... A2, B2, C2..., for columns and
|
|
121
|
+
# A1, A2, A3... B1, B2, B3 for rows. So if the active nozzle is on H row/12 column,
|
|
122
|
+
# reverse the list so the correct primary nozzle is chosen
|
|
123
|
+
reverse_lookup = (
|
|
124
|
+
nozzle_map.starting_nozzle == "H12"
|
|
125
|
+
or (
|
|
126
|
+
nozzle_map.configuration == NozzleConfigurationType.COLUMN
|
|
127
|
+
and nozzle_map.starting_nozzle == "H1"
|
|
128
|
+
)
|
|
129
|
+
or (
|
|
130
|
+
nozzle_map.configuration == NozzleConfigurationType.ROW
|
|
131
|
+
and nozzle_map.starting_nozzle == "A12"
|
|
132
|
+
)
|
|
133
|
+
)
|
|
134
|
+
if reverse_lookup:
|
|
135
|
+
targets.reverse()
|
|
136
|
+
|
|
137
|
+
for well in targets:
|
|
138
|
+
# If we have wells that are covered by the pipette's nozzles while primary nozzle is over
|
|
139
|
+
# a target well that aren't accounted for, check if the current well is in that list
|
|
140
|
+
if active_wells_covered:
|
|
141
|
+
if well.parent != active_labware:
|
|
142
|
+
raise ValueError(
|
|
143
|
+
f"Could not group {target_name} wells to match pipette's nozzle configuration. Ensure that the"
|
|
144
|
+
" wells are ordered correctly (e.g. rows() for a row layout or columns() for a column layout), or"
|
|
145
|
+
" set group_wells to False to only target wells with the primary nozzle."
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
if well.well_name in active_wells_covered:
|
|
149
|
+
active_wells_covered.remove(well.well_name)
|
|
150
|
+
# If it's a 384 well plate, contiguous wells are not covered by the pipette targeting the
|
|
151
|
+
# initial target well. To support these kinds of transfers given a list of contiguous wells,
|
|
152
|
+
# allow another target well (or up to 4 total for a full 96-tip config) and add those wells
|
|
153
|
+
# to the list of covered wells
|
|
154
|
+
elif labware_format == "384Standard" and (
|
|
155
|
+
alternate_384_well_coverage_count == 0
|
|
156
|
+
or (
|
|
157
|
+
nozzle_map.tip_count == 96 and alternate_384_well_coverage_count < 3
|
|
158
|
+
)
|
|
159
|
+
):
|
|
160
|
+
active_wells_covered.extend(
|
|
161
|
+
list(
|
|
162
|
+
wells_covered_by_pipette_configuration(
|
|
163
|
+
nozzle_map, # type: ignore[arg-type]
|
|
164
|
+
well.well_name,
|
|
165
|
+
labware_wells_by_column=[
|
|
166
|
+
[labware_well.well_name for labware_well in column]
|
|
167
|
+
for column in well.parent.columns()
|
|
168
|
+
],
|
|
169
|
+
)
|
|
170
|
+
)
|
|
171
|
+
)
|
|
172
|
+
active_wells_covered.remove(well.well_name)
|
|
173
|
+
grouped_wells.append(well)
|
|
174
|
+
alternate_384_well_coverage_count += 1
|
|
175
|
+
else:
|
|
176
|
+
raise ValueError(
|
|
177
|
+
f"Could not group {target_name} wells to match pipette's nozzle configuration. Ensure that the"
|
|
178
|
+
" wells are ordered correctly (e.g. rows() for a row layout or columns() for a column layout), or"
|
|
179
|
+
" set group_wells to False to only target wells with the primary nozzle."
|
|
180
|
+
)
|
|
181
|
+
# If we have no active wells covered to account for, add a new target well and list of covered wells to check
|
|
182
|
+
else:
|
|
183
|
+
# If the labware is not a 96 or 384 well plate, add this well to the final result and move on to the next
|
|
184
|
+
labware_format = well.parent.parameters["format"]
|
|
185
|
+
if labware_format != "96Standard" and labware_format != "384Standard":
|
|
186
|
+
grouped_wells.append(well)
|
|
187
|
+
continue
|
|
188
|
+
|
|
189
|
+
active_wells_covered = list(
|
|
190
|
+
wells_covered_by_pipette_configuration(
|
|
191
|
+
nozzle_map, # type: ignore[arg-type]
|
|
192
|
+
well.well_name,
|
|
193
|
+
labware_wells_by_column=[
|
|
194
|
+
[labware_well.well_name for labware_well in column]
|
|
195
|
+
for column in well.parent.columns()
|
|
196
|
+
],
|
|
197
|
+
)
|
|
198
|
+
)
|
|
199
|
+
active_wells_covered.remove(well.well_name)
|
|
200
|
+
grouped_wells.append(well)
|
|
201
|
+
active_labware = well.parent
|
|
202
|
+
alternate_384_well_coverage_count = 0
|
|
203
|
+
|
|
204
|
+
if active_wells_covered:
|
|
205
|
+
raise ValueError(
|
|
206
|
+
f"Pipette will access {target_name} wells not provided in the liquid handling command."
|
|
207
|
+
f" Set group_wells to False or include these wells: {active_wells_covered}"
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
# If we reversed the lookup of wells, reverse the grouped wells we will return
|
|
211
|
+
if reverse_lookup:
|
|
212
|
+
grouped_wells.reverse()
|
|
213
|
+
|
|
214
|
+
return grouped_wells
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
def check_current_volume_before_dispensing(
|
|
218
|
+
current_volume: float,
|
|
219
|
+
dispense_volume: float,
|
|
220
|
+
) -> None:
|
|
221
|
+
"""Check if the current volume is valid for dispensing the dispense volume."""
|
|
222
|
+
if current_volume < dispense_volume:
|
|
223
|
+
# Although this should never happen, we can get into an unexpected state
|
|
224
|
+
# following error recovery and not have the expected amount of liquid in the tip.
|
|
225
|
+
# If this happens, we want to raise a useful error so the user can understand
|
|
226
|
+
# the cause of the problem. If we don't make this check for current volume,
|
|
227
|
+
# an unhelpful error might get raised when a '..byVolume' property encounters
|
|
228
|
+
# a negative volume (current_volume - dispense_volume).
|
|
229
|
+
raise RuntimeError(
|
|
230
|
+
f"Cannot dispense {dispense_volume}uL when the tip has only {current_volume}uL."
|
|
231
|
+
)
|
|
File without changes
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
from opentrons.config import get_opentrons_path
|
|
4
|
+
|
|
5
|
+
OPENTRONS_NAMESPACE = "opentrons"
|
|
6
|
+
CUSTOM_NAMESPACE = "custom_beta"
|
|
7
|
+
STANDARD_DEFS_PATH = Path("labware/definitions")
|
|
8
|
+
USER_DEFS_PATH = get_opentrons_path("labware_user_definitions_dir_v2")
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
from typing import Sequence, Dict, Optional, Any
|
|
2
|
+
|
|
3
|
+
from opentrons_shared_data.robot.types import RobotType
|
|
4
|
+
from opentrons_shared_data.errors import ErrorCodes
|
|
5
|
+
from opentrons_shared_data.errors.exceptions import EnumeratedError
|
|
6
|
+
|
|
7
|
+
from opentrons.config import feature_flags
|
|
8
|
+
|
|
9
|
+
from opentrons.protocol_reader.protocol_source import (
|
|
10
|
+
ProtocolConfig,
|
|
11
|
+
PythonProtocolConfig,
|
|
12
|
+
JsonProtocolConfig,
|
|
13
|
+
)
|
|
14
|
+
from opentrons.protocols.api_support.types import APIVersion
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# TODO(mm, 2023-05-10): Deduplicate these constants with
|
|
18
|
+
# opentrons.protocol_engine.types.DeckType and consider moving to shared-data.
|
|
19
|
+
SHORT_TRASH_DECK = "ot2_short_trash"
|
|
20
|
+
STANDARD_OT2_DECK = "ot2_standard"
|
|
21
|
+
STANDARD_OT3_DECK = "ot3_standard"
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
LOAD_FIXED_TRASH_GATE_VERSION_PYTHON = APIVersion(2, 15)
|
|
25
|
+
LOAD_FIXED_TRASH_GATE_VERSION_JSON = 7
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class NoTrashDefinedError(EnumeratedError):
|
|
29
|
+
"""
|
|
30
|
+
Error raised when a protocol attempts to automatically access a trash bin without one being loaded.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
def __init__(
|
|
34
|
+
self,
|
|
35
|
+
message: Optional[str] = None,
|
|
36
|
+
detail: Optional[Dict[str, Any]] = None,
|
|
37
|
+
wrapping: Optional[Sequence[EnumeratedError]] = None,
|
|
38
|
+
) -> None:
|
|
39
|
+
"""Build a ProtocolEngineError."""
|
|
40
|
+
super().__init__(
|
|
41
|
+
code=ErrorCodes.GENERAL_ERROR,
|
|
42
|
+
message=message,
|
|
43
|
+
detail=detail,
|
|
44
|
+
wrapping=wrapping,
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def should_load_fixed_trash_labware_for_python_protocol(
|
|
49
|
+
api_version: APIVersion,
|
|
50
|
+
) -> bool:
|
|
51
|
+
"""Whether to automatically load the fixed trash as a labware for a Python protocol at protocol start."""
|
|
52
|
+
return api_version <= LOAD_FIXED_TRASH_GATE_VERSION_PYTHON
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def should_load_fixed_trash_area_for_python_protocol(
|
|
56
|
+
api_version: APIVersion, robot_type: RobotType
|
|
57
|
+
) -> bool:
|
|
58
|
+
"""Whether to automatically load the fixed trash addressable area for OT-2 protocols on 2.16 and above."""
|
|
59
|
+
return (
|
|
60
|
+
api_version > LOAD_FIXED_TRASH_GATE_VERSION_PYTHON
|
|
61
|
+
and robot_type == "OT-2 Standard"
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def should_load_fixed_trash(protocol_config: ProtocolConfig) -> bool:
|
|
66
|
+
"""Decide whether to automatically load fixed trash labware on the deck based on version."""
|
|
67
|
+
load_fixed_trash = False
|
|
68
|
+
if isinstance(protocol_config, PythonProtocolConfig):
|
|
69
|
+
return should_load_fixed_trash_labware_for_python_protocol(
|
|
70
|
+
protocol_config.api_version
|
|
71
|
+
)
|
|
72
|
+
# TODO(jbl 2023-10-27), when schema v8 is out, use a new deck version field to support fixed trash protocols
|
|
73
|
+
elif isinstance(protocol_config, JsonProtocolConfig):
|
|
74
|
+
load_fixed_trash = (
|
|
75
|
+
protocol_config.schema_version <= LOAD_FIXED_TRASH_GATE_VERSION_JSON
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
return load_fixed_trash
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def guess_from_global_config() -> str:
|
|
82
|
+
"""Return the deck type that the host device physically has.
|
|
83
|
+
|
|
84
|
+
This only makes sense when the software is running on a real robot.
|
|
85
|
+
|
|
86
|
+
When simulating or analyzing a protocol, especially off-robot, don't use this, because it may
|
|
87
|
+
not match the protocol's declared robot type. Use `for_analysis` instead.
|
|
88
|
+
"""
|
|
89
|
+
if feature_flags.enable_ot3_hardware_controller():
|
|
90
|
+
return STANDARD_OT3_DECK
|
|
91
|
+
elif feature_flags.short_fixed_trash():
|
|
92
|
+
return SHORT_TRASH_DECK
|
|
93
|
+
else:
|
|
94
|
+
return STANDARD_OT2_DECK
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def for_simulation(robot_type: RobotType) -> str:
|
|
98
|
+
"""Return the deck type that should be used for simulating and analyzing a protocol.
|
|
99
|
+
|
|
100
|
+
Params:
|
|
101
|
+
robot_type: The robot type that the protocol is meant to run on.
|
|
102
|
+
"""
|
|
103
|
+
if robot_type == "OT-2 Standard":
|
|
104
|
+
# OT-2 protocols don't have a way of defining whether they're meant to run on a short-trash
|
|
105
|
+
# or standard deck. So when we're simulating an OT-2 protocol, we need to make an
|
|
106
|
+
# arbitrary choice for which deck type to use.
|
|
107
|
+
return STANDARD_OT2_DECK
|
|
108
|
+
elif robot_type == "OT-3 Standard":
|
|
109
|
+
# OT-3s currently only have a single deck type.
|
|
110
|
+
return STANDARD_OT3_DECK
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from .types import APIVersion
|
|
2
|
+
|
|
3
|
+
MAX_SUPPORTED_VERSION = APIVersion(2, 25)
|
|
4
|
+
"""The maximum supported protocol API version in this release."""
|
|
5
|
+
|
|
6
|
+
MIN_SUPPORTED_VERSION = APIVersion(2, 0)
|
|
7
|
+
"""The minimum supported protocol API version in this release, across all robot types."""
|
|
8
|
+
|
|
9
|
+
MIN_SUPPORTED_VERSION_FOR_FLEX = APIVersion(2, 15)
|
|
10
|
+
"""The minimum protocol API version supported by the Opentrons Flex.
|
|
11
|
+
|
|
12
|
+
It's an infrastructural requirement for this to be at least newer than 2.14. Before then,
|
|
13
|
+
the protocol API is backed by the legacy non-Protocol-engine backend, which is not prepared to
|
|
14
|
+
handle anything but OT-2s.
|
|
15
|
+
|
|
16
|
+
The additional bump to 2.15 is because that's what we tested on, and because it adds all the
|
|
17
|
+
Flex-specific features.
|
|
18
|
+
"""
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import Optional, Any
|
|
3
|
+
|
|
4
|
+
from opentrons_shared_data.labware.types import (
|
|
5
|
+
LabwareDefinition2 as LabwareDefinition2Dict,
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
from opentrons import types
|
|
9
|
+
from opentrons.calibration_storage.helpers import uri_from_definition
|
|
10
|
+
from opentrons.calibration_storage.types import TipLengthCalNotFound
|
|
11
|
+
from opentrons.hardware_control.dev_types import PipetteDict
|
|
12
|
+
|
|
13
|
+
# TODO (lc 09-26-2022) We should conditionally import ot2 or ot3 calibration
|
|
14
|
+
from opentrons.hardware_control.instruments.ot2 import (
|
|
15
|
+
instrument_calibration as instr_cal,
|
|
16
|
+
)
|
|
17
|
+
from opentrons.protocol_api.labware import Labware
|
|
18
|
+
from opentrons.protocols.api_support.types import APIVersion
|
|
19
|
+
from opentrons_shared_data.protocol.types import (
|
|
20
|
+
LiquidHandlingCommand,
|
|
21
|
+
BlowoutLocation,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def validate_blowout_location(
|
|
26
|
+
api_version: APIVersion,
|
|
27
|
+
liquid_handling_command: LiquidHandlingCommand,
|
|
28
|
+
blowout_location: Optional[Any],
|
|
29
|
+
) -> None:
|
|
30
|
+
"""Validate the blowout location."""
|
|
31
|
+
if blowout_location and api_version < APIVersion(2, 8):
|
|
32
|
+
raise ValueError(
|
|
33
|
+
"Cannot specify blowout location when using api"
|
|
34
|
+
+ " version below 2.8, current version is {api_version}".format(
|
|
35
|
+
api_version=api_version
|
|
36
|
+
)
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
elif liquid_handling_command == "consolidate" and blowout_location == "source well":
|
|
40
|
+
raise ValueError("blowout location for consolidate cannot be source well")
|
|
41
|
+
elif (
|
|
42
|
+
liquid_handling_command == "distribute"
|
|
43
|
+
and blowout_location == "destination well"
|
|
44
|
+
):
|
|
45
|
+
raise ValueError("blowout location for distribute cannot be destination well")
|
|
46
|
+
elif (
|
|
47
|
+
liquid_handling_command == "transfer"
|
|
48
|
+
and blowout_location
|
|
49
|
+
and blowout_location not in [location.value for location in BlowoutLocation]
|
|
50
|
+
):
|
|
51
|
+
raise ValueError(
|
|
52
|
+
"blowout location should be either 'source well', "
|
|
53
|
+
+ " 'destination well', or 'trash'"
|
|
54
|
+
+ f" but it is {blowout_location}"
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def tip_length_for(
|
|
59
|
+
pipette: PipetteDict, tip_rack_definition: LabwareDefinition2Dict
|
|
60
|
+
) -> float:
|
|
61
|
+
"""Get the tip length, including overlap, for a tip from this rack"""
|
|
62
|
+
try:
|
|
63
|
+
return instr_cal.load_tip_length_for_pipette(
|
|
64
|
+
pipette["pipette_id"], tip_rack_definition
|
|
65
|
+
).tip_length
|
|
66
|
+
except TipLengthCalNotFound:
|
|
67
|
+
tip_overlap = pipette["tip_overlap"].get(
|
|
68
|
+
uri_from_definition(tip_rack_definition),
|
|
69
|
+
pipette["tip_overlap"]["default"],
|
|
70
|
+
)
|
|
71
|
+
tip_length = tip_rack_definition["parameters"]["tipLength"]
|
|
72
|
+
return tip_length - tip_overlap
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
VALID_PIP_TIPRACK_VOL = {
|
|
76
|
+
"FLEX": {"p50": [50], "p200": [50, 200], "p1000": [50, 200, 1000]},
|
|
77
|
+
"OT2": {
|
|
78
|
+
"p10": [10, 20],
|
|
79
|
+
"p20": [10, 20],
|
|
80
|
+
"p50": [50, 200, 300],
|
|
81
|
+
"p300": [200, 300],
|
|
82
|
+
"p1000": [1000],
|
|
83
|
+
},
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def validate_tiprack(
|
|
88
|
+
instrument_name: str, tip_rack: Labware, log: logging.Logger
|
|
89
|
+
) -> None:
|
|
90
|
+
"""Validate a tiprack logging a warning message."""
|
|
91
|
+
if not tip_rack.is_tiprack:
|
|
92
|
+
raise ValueError(f"Labware {tip_rack.load_name} is not a tip rack.")
|
|
93
|
+
|
|
94
|
+
# TODO AA 2020-06-24 - we should instead add the acceptable Opentrons
|
|
95
|
+
# tipracks to the pipette as a refactor
|
|
96
|
+
if tip_rack.uri.startswith("opentrons/"):
|
|
97
|
+
tiprack_vol = tip_rack.wells()[0].max_volume
|
|
98
|
+
instr_metadata = instrument_name.split("_")
|
|
99
|
+
gen_lookup = (
|
|
100
|
+
"FLEX" if ("flex" in instr_metadata or "96" in instr_metadata) else "OT2"
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
# TODO (spp, 2025-01-30): do what AA's note above says or at least,
|
|
104
|
+
# fetch the 'pip_type' below from the 'model' field in pipette definitions
|
|
105
|
+
# so that we don't have to figure it out from pipette names
|
|
106
|
+
if instrument_name.split("_")[0] == "flex":
|
|
107
|
+
# Flex's API load names have the format 'flex_1channel_1000'
|
|
108
|
+
# From API v2.23 on, this is the name returned by InstrumentContext.name
|
|
109
|
+
pip_type = "p" + instrument_name.split("_")[2]
|
|
110
|
+
else:
|
|
111
|
+
# Until API v2.23, InstrumentContext.name returned the engine-specific names
|
|
112
|
+
# of Flex pipettes. These names, as well as OT2 pipette names,
|
|
113
|
+
# have the format- 'p1000_single_gen2' or 'p1000_single_flex'
|
|
114
|
+
pip_type = instrument_name.split("_")[0]
|
|
115
|
+
valid_vols = VALID_PIP_TIPRACK_VOL[gen_lookup][pip_type]
|
|
116
|
+
if tiprack_vol not in valid_vols:
|
|
117
|
+
log.warning(
|
|
118
|
+
f"The pipette {instrument_name} and its tip rack {tip_rack.load_name}"
|
|
119
|
+
" appear to be mismatched. Please check your protocol."
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def validate_takes_liquid(
|
|
124
|
+
location: types.Location, reject_module: bool, reject_adapter: bool
|
|
125
|
+
) -> None:
|
|
126
|
+
"""Validate that a location is a valid liquid handling target.
|
|
127
|
+
|
|
128
|
+
Args:
|
|
129
|
+
location: target location.
|
|
130
|
+
reject_module: if set to True, disallow liquid handling directly to module
|
|
131
|
+
reject_adapter: if set to True, check that labware is not an adapter
|
|
132
|
+
|
|
133
|
+
Raises:
|
|
134
|
+
ValueError: the given location is not a valid liquid handling target.
|
|
135
|
+
"""
|
|
136
|
+
labware = None
|
|
137
|
+
|
|
138
|
+
if location.labware.is_labware:
|
|
139
|
+
labware = location.labware.as_labware()
|
|
140
|
+
|
|
141
|
+
if location.labware.is_well:
|
|
142
|
+
labware = location.labware.as_well().parent
|
|
143
|
+
|
|
144
|
+
if location.labware.is_module and reject_module:
|
|
145
|
+
raise ValueError("Cannot aspirate/dispense directly to a module")
|
|
146
|
+
|
|
147
|
+
if labware is not None and labware.is_tiprack:
|
|
148
|
+
raise ValueError("Cannot aspirate/dispense to a tip rack")
|
|
149
|
+
|
|
150
|
+
if reject_adapter and (labware is not None and labware.is_adapter):
|
|
151
|
+
raise ValueError("Cannot aspirate/dispense to an adapter")
|