opentrons 8.6.0__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 +557 -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 +187 -0
- opentrons/drivers/asyncio/communication/errors.py +88 -0
- opentrons/drivers/asyncio/communication/serial_connection.py +557 -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/scripts/update_module_fw.py +274 -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 +276 -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 +1186 -0
- opentrons/motion_planning/__init__.py +32 -0
- opentrons/motion_planning/adjacent_slots_getters.py +168 -0
- opentrons/motion_planning/deck_conflict.py +501 -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 +400 -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 +1027 -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 +1006 -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 +3272 -0
- opentrons/protocol_api/labware.py +1579 -0
- opentrons/protocol_api/module_contexts.py +1447 -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 +339 -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 +350 -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 +68 -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 +1164 -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 +2408 -0
- opentrons/protocol_engine/state/inner_well_math_utils.py +548 -0
- opentrons/protocol_engine/state/labware.py +1432 -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 +1515 -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 +310 -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 +310 -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 +852 -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.0.dist-info/METADATA +37 -0
- opentrons-8.6.0.dist-info/RECORD +601 -0
- opentrons-8.6.0.dist-info/WHEEL +4 -0
- opentrons-8.6.0.dist-info/entry_points.txt +3 -0
- opentrons-8.6.0.dist-info/licenses/LICENSE +202 -0
|
@@ -0,0 +1,686 @@
|
|
|
1
|
+
"""Gantry movement wrapper for hardware and simulation based movement."""
|
|
2
|
+
from logging import getLogger
|
|
3
|
+
from opentrons.config.types import OT3Config
|
|
4
|
+
from functools import partial
|
|
5
|
+
from typing import Optional, List, Dict, Tuple
|
|
6
|
+
from typing_extensions import Protocol as TypingProtocol
|
|
7
|
+
|
|
8
|
+
from opentrons.types import Point, Mount, MountType
|
|
9
|
+
|
|
10
|
+
from opentrons.hardware_control import HardwareControlAPI
|
|
11
|
+
from opentrons.hardware_control.types import Axis as HardwareAxis, CriticalPoint
|
|
12
|
+
from opentrons.hardware_control.motion_utilities import (
|
|
13
|
+
target_axis_map_from_relative,
|
|
14
|
+
target_axis_map_from_absolute,
|
|
15
|
+
)
|
|
16
|
+
from opentrons_shared_data.errors.exceptions import PositionUnknownError
|
|
17
|
+
|
|
18
|
+
from opentrons.motion_planning import Waypoint
|
|
19
|
+
|
|
20
|
+
from ..state.state import StateView
|
|
21
|
+
from ..types import MotorAxis, CurrentWell
|
|
22
|
+
from ..errors import MustHomeError, InvalidAxisForRobotType
|
|
23
|
+
|
|
24
|
+
log = getLogger(__name__)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
_MOTOR_AXIS_TO_HARDWARE_AXIS: Dict[MotorAxis, HardwareAxis] = {
|
|
28
|
+
MotorAxis.X: HardwareAxis.X,
|
|
29
|
+
MotorAxis.Y: HardwareAxis.Y,
|
|
30
|
+
MotorAxis.LEFT_Z: HardwareAxis.Z,
|
|
31
|
+
MotorAxis.RIGHT_Z: HardwareAxis.A,
|
|
32
|
+
MotorAxis.LEFT_PLUNGER: HardwareAxis.B,
|
|
33
|
+
MotorAxis.RIGHT_PLUNGER: HardwareAxis.C,
|
|
34
|
+
MotorAxis.EXTENSION_Z: HardwareAxis.Z_G,
|
|
35
|
+
MotorAxis.EXTENSION_JAW: HardwareAxis.G,
|
|
36
|
+
MotorAxis.AXIS_96_CHANNEL_CAM: HardwareAxis.Q,
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
_MOTOR_AXIS_TO_HARDWARE_MOUNT: Dict[MotorAxis, Mount] = {
|
|
40
|
+
MotorAxis.LEFT_Z: Mount.LEFT,
|
|
41
|
+
MotorAxis.RIGHT_Z: Mount.RIGHT,
|
|
42
|
+
MotorAxis.EXTENSION_Z: Mount.EXTENSION,
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
_HARDWARE_MOUNT_MOTOR_AXIS_TO: Dict[Mount, MotorAxis] = {
|
|
46
|
+
Mount.LEFT: MotorAxis.LEFT_Z,
|
|
47
|
+
Mount.RIGHT: MotorAxis.RIGHT_Z,
|
|
48
|
+
Mount.EXTENSION: MotorAxis.EXTENSION_Z,
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
_HARDWARE_AXIS_TO_MOTOR_AXIS: Dict[HardwareAxis, MotorAxis] = {
|
|
52
|
+
HardwareAxis.X: MotorAxis.X,
|
|
53
|
+
HardwareAxis.Y: MotorAxis.Y,
|
|
54
|
+
HardwareAxis.Z: MotorAxis.LEFT_Z,
|
|
55
|
+
HardwareAxis.A: MotorAxis.RIGHT_Z,
|
|
56
|
+
HardwareAxis.B: MotorAxis.LEFT_PLUNGER,
|
|
57
|
+
HardwareAxis.C: MotorAxis.RIGHT_PLUNGER,
|
|
58
|
+
HardwareAxis.P_L: MotorAxis.LEFT_PLUNGER,
|
|
59
|
+
HardwareAxis.P_R: MotorAxis.RIGHT_PLUNGER,
|
|
60
|
+
HardwareAxis.Z_L: MotorAxis.LEFT_Z,
|
|
61
|
+
HardwareAxis.Z_R: MotorAxis.RIGHT_Z,
|
|
62
|
+
HardwareAxis.Z_G: MotorAxis.EXTENSION_Z,
|
|
63
|
+
HardwareAxis.G: MotorAxis.EXTENSION_JAW,
|
|
64
|
+
HardwareAxis.Q: MotorAxis.AXIS_96_CHANNEL_CAM,
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
# The height of the bottom of the pipette nozzle at home position without any tips.
|
|
69
|
+
# We rely on this being the same for every OT-3 pipette.
|
|
70
|
+
#
|
|
71
|
+
# We found this number by peeking at the height that OT3Simulator returns for these pipettes:
|
|
72
|
+
# * Flex Single- and 8-Channel P50
|
|
73
|
+
# * Flex Single-, 8-, and 96-channel P1000
|
|
74
|
+
#
|
|
75
|
+
# That OT3Simulator return value is what Protocol Engine uses for simulation when Protocol Engine
|
|
76
|
+
# is configured to not virtualize pipettes, so this number should match it.
|
|
77
|
+
VIRTUAL_MAX_OT3_HEIGHT = 248.0
|
|
78
|
+
# This number was found by using the longest pipette's P1000V2 default configuration values.
|
|
79
|
+
VIRTUAL_MAX_OT2_HEIGHT = 268.14
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class GantryMover(TypingProtocol):
|
|
83
|
+
"""Abstract class for gantry movement handler."""
|
|
84
|
+
|
|
85
|
+
async def get_position(
|
|
86
|
+
self,
|
|
87
|
+
pipette_id: str,
|
|
88
|
+
current_well: Optional[CurrentWell] = None,
|
|
89
|
+
fail_on_not_homed: bool = False,
|
|
90
|
+
) -> Point:
|
|
91
|
+
"""Get the current position of the gantry."""
|
|
92
|
+
...
|
|
93
|
+
|
|
94
|
+
async def get_position_from_mount(
|
|
95
|
+
self,
|
|
96
|
+
mount: Mount,
|
|
97
|
+
critical_point: Optional[CriticalPoint] = None,
|
|
98
|
+
fail_on_not_homed: bool = False,
|
|
99
|
+
) -> Point:
|
|
100
|
+
"""Get the current position of the gantry based on the given mount."""
|
|
101
|
+
...
|
|
102
|
+
|
|
103
|
+
def get_max_travel_z(self, pipette_id: str) -> float:
|
|
104
|
+
"""Get the maximum allowed z-height for pipette movement."""
|
|
105
|
+
...
|
|
106
|
+
|
|
107
|
+
def get_max_travel_z_from_mount(self, mount: MountType) -> float:
|
|
108
|
+
"""Get the maximum allowed z-height for mount movement."""
|
|
109
|
+
...
|
|
110
|
+
|
|
111
|
+
async def move_axes(
|
|
112
|
+
self,
|
|
113
|
+
axis_map: Dict[MotorAxis, float],
|
|
114
|
+
critical_point: Optional[Dict[MotorAxis, float]] = None,
|
|
115
|
+
speed: Optional[float] = None,
|
|
116
|
+
relative_move: bool = False,
|
|
117
|
+
expect_stalls: bool = False,
|
|
118
|
+
) -> Dict[MotorAxis, float]:
|
|
119
|
+
"""Move a set of axes a given distance."""
|
|
120
|
+
...
|
|
121
|
+
|
|
122
|
+
async def move_to(
|
|
123
|
+
self, pipette_id: str, waypoints: List[Waypoint], speed: Optional[float]
|
|
124
|
+
) -> Point:
|
|
125
|
+
"""Move the hardware gantry to a waypoint."""
|
|
126
|
+
...
|
|
127
|
+
|
|
128
|
+
async def move_mount_to(
|
|
129
|
+
self, mount: Mount, waypoints: List[Waypoint], speed: Optional[float]
|
|
130
|
+
) -> Point:
|
|
131
|
+
"""Move the provided hardware mount to a waypoint."""
|
|
132
|
+
...
|
|
133
|
+
|
|
134
|
+
async def move_relative(
|
|
135
|
+
self,
|
|
136
|
+
pipette_id: str,
|
|
137
|
+
delta: Point,
|
|
138
|
+
speed: Optional[float],
|
|
139
|
+
) -> Point:
|
|
140
|
+
"""Move the hardware gantry in a relative direction by delta."""
|
|
141
|
+
...
|
|
142
|
+
|
|
143
|
+
async def home(self, axes: Optional[List[MotorAxis]]) -> None:
|
|
144
|
+
"""Home the gantry."""
|
|
145
|
+
...
|
|
146
|
+
|
|
147
|
+
async def retract_axis(self, axis: MotorAxis) -> None:
|
|
148
|
+
"""Retract the specified axis to its home position."""
|
|
149
|
+
...
|
|
150
|
+
|
|
151
|
+
async def prepare_for_mount_movement(self, mount: Mount) -> None:
|
|
152
|
+
"""Retract the 'idle' mount if necessary."""
|
|
153
|
+
...
|
|
154
|
+
|
|
155
|
+
def motor_axis_to_hardware_axis(self, motor_axis: MotorAxis) -> HardwareAxis:
|
|
156
|
+
"""Transform an engine motor axis into a hardware axis."""
|
|
157
|
+
...
|
|
158
|
+
|
|
159
|
+
def pick_mount_from_axis_map(self, axis_map: Dict[MotorAxis, float]) -> Mount:
|
|
160
|
+
"""Find a mount axis in the axis_map if it exists otherwise default to left mount."""
|
|
161
|
+
...
|
|
162
|
+
|
|
163
|
+
def motor_axes_to_present_hardware_axes(
|
|
164
|
+
self, motor_axes: List[MotorAxis]
|
|
165
|
+
) -> List[HardwareAxis]:
|
|
166
|
+
"""Transform a list of engine axes into a list of hardware axes, filtering out non-present axes."""
|
|
167
|
+
...
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
class HardwareGantryMover(GantryMover):
|
|
171
|
+
"""Hardware API based gantry movement handler."""
|
|
172
|
+
|
|
173
|
+
def __init__(self, hardware_api: HardwareControlAPI, state_view: StateView) -> None:
|
|
174
|
+
self._hardware_api = hardware_api
|
|
175
|
+
self._state_view = state_view
|
|
176
|
+
|
|
177
|
+
def motor_axes_to_present_hardware_axes(
|
|
178
|
+
self, motor_axes: List[MotorAxis]
|
|
179
|
+
) -> List[HardwareAxis]:
|
|
180
|
+
"""Get hardware axes from engine axes while filtering out non-present axes."""
|
|
181
|
+
return [
|
|
182
|
+
self.motor_axis_to_hardware_axis(motor_axis)
|
|
183
|
+
for motor_axis in motor_axes
|
|
184
|
+
if self._hardware_api.axis_is_present(
|
|
185
|
+
self.motor_axis_to_hardware_axis(motor_axis)
|
|
186
|
+
)
|
|
187
|
+
]
|
|
188
|
+
|
|
189
|
+
def motor_axis_to_hardware_axis(self, motor_axis: MotorAxis) -> HardwareAxis:
|
|
190
|
+
"""Transform an engine motor axis into a hardware axis."""
|
|
191
|
+
return _MOTOR_AXIS_TO_HARDWARE_AXIS[motor_axis]
|
|
192
|
+
|
|
193
|
+
def _hardware_axis_to_motor_axis(self, motor_axis: HardwareAxis) -> MotorAxis:
|
|
194
|
+
"""Transform an hardware axis into a engine motor axis."""
|
|
195
|
+
return _HARDWARE_AXIS_TO_MOTOR_AXIS[motor_axis]
|
|
196
|
+
|
|
197
|
+
def _convert_axis_map_for_hw(
|
|
198
|
+
self, axis_map: Dict[MotorAxis, float]
|
|
199
|
+
) -> Dict[HardwareAxis, float]:
|
|
200
|
+
"""Transform an engine motor axis map to a hardware axis map."""
|
|
201
|
+
return {_MOTOR_AXIS_TO_HARDWARE_AXIS[ax]: dist for ax, dist in axis_map.items()}
|
|
202
|
+
|
|
203
|
+
def _critical_point_for(
|
|
204
|
+
self, mount: Mount, cp_override: Optional[Dict[MotorAxis, float]] = None
|
|
205
|
+
) -> Point:
|
|
206
|
+
if cp_override:
|
|
207
|
+
return Point(
|
|
208
|
+
x=cp_override[MotorAxis.X],
|
|
209
|
+
y=cp_override[MotorAxis.Y],
|
|
210
|
+
z=cp_override[_HARDWARE_MOUNT_MOTOR_AXIS_TO[mount]],
|
|
211
|
+
)
|
|
212
|
+
else:
|
|
213
|
+
return self._hardware_api.critical_point_for(mount)
|
|
214
|
+
|
|
215
|
+
def _get_gantry_offsets_for_robot_type(
|
|
216
|
+
self,
|
|
217
|
+
) -> Tuple[Point, Point, Optional[Point]]:
|
|
218
|
+
if isinstance(self._hardware_api.config, OT3Config):
|
|
219
|
+
return (
|
|
220
|
+
Point(*self._hardware_api.config.left_mount_offset),
|
|
221
|
+
Point(*self._hardware_api.config.right_mount_offset),
|
|
222
|
+
Point(*self._hardware_api.config.gripper_mount_offset),
|
|
223
|
+
)
|
|
224
|
+
else:
|
|
225
|
+
return (
|
|
226
|
+
Point(*self._hardware_api.config.left_mount_offset),
|
|
227
|
+
Point(0, 0, 0),
|
|
228
|
+
None,
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
def pick_mount_from_axis_map(self, axis_map: Dict[MotorAxis, float]) -> Mount:
|
|
232
|
+
"""Find a mount axis in the axis_map if it exists otherwise default to left mount."""
|
|
233
|
+
found_mount = Mount.LEFT
|
|
234
|
+
mounts = list(_MOTOR_AXIS_TO_HARDWARE_MOUNT.keys())
|
|
235
|
+
for k in axis_map.keys():
|
|
236
|
+
if k in mounts:
|
|
237
|
+
found_mount = _MOTOR_AXIS_TO_HARDWARE_MOUNT[k]
|
|
238
|
+
break
|
|
239
|
+
return found_mount
|
|
240
|
+
|
|
241
|
+
async def get_position(
|
|
242
|
+
self,
|
|
243
|
+
pipette_id: str,
|
|
244
|
+
current_well: Optional[CurrentWell] = None,
|
|
245
|
+
fail_on_not_homed: bool = False,
|
|
246
|
+
) -> Point:
|
|
247
|
+
"""Get the current position of the gantry.
|
|
248
|
+
|
|
249
|
+
Args:
|
|
250
|
+
pipette_id: Pipette ID to get location data for.
|
|
251
|
+
current_well: Optional parameter for getting pipette location data, effects critical point.
|
|
252
|
+
fail_on_not_homed: Raise PositionUnknownError if gantry position is not known.
|
|
253
|
+
"""
|
|
254
|
+
pipette_location = self._state_view.motion.get_pipette_location(
|
|
255
|
+
pipette_id=pipette_id,
|
|
256
|
+
current_location=current_well,
|
|
257
|
+
)
|
|
258
|
+
point = await self.get_position_from_mount(
|
|
259
|
+
mount=pipette_location.mount.to_hw_mount(),
|
|
260
|
+
critical_point=pipette_location.critical_point,
|
|
261
|
+
fail_on_not_homed=fail_on_not_homed,
|
|
262
|
+
)
|
|
263
|
+
return point
|
|
264
|
+
|
|
265
|
+
async def get_position_from_mount(
|
|
266
|
+
self,
|
|
267
|
+
mount: Mount,
|
|
268
|
+
critical_point: Optional[CriticalPoint] = None,
|
|
269
|
+
fail_on_not_homed: bool = False,
|
|
270
|
+
) -> Point:
|
|
271
|
+
"""Get the current position of the gantry based on the mount.
|
|
272
|
+
|
|
273
|
+
Args:
|
|
274
|
+
mount: The mount to get the position for.
|
|
275
|
+
critical_point: Optional parameter for getting instrument location data, effects critical point.
|
|
276
|
+
fail_on_not_homed: Raise PositionUnknownError if gantry position is not known.
|
|
277
|
+
"""
|
|
278
|
+
try:
|
|
279
|
+
point = await self._hardware_api.gantry_position(
|
|
280
|
+
mount=mount,
|
|
281
|
+
critical_point=critical_point,
|
|
282
|
+
fail_on_not_homed=fail_on_not_homed,
|
|
283
|
+
)
|
|
284
|
+
return point
|
|
285
|
+
except PositionUnknownError as e:
|
|
286
|
+
raise MustHomeError(message=str(e), wrapping=[e])
|
|
287
|
+
|
|
288
|
+
def get_max_travel_z(self, pipette_id: str) -> float:
|
|
289
|
+
"""Get the maximum allowed z-height for pipette movement.
|
|
290
|
+
|
|
291
|
+
Args:
|
|
292
|
+
pipette_id: Pipette ID to get max travel z-height for.
|
|
293
|
+
"""
|
|
294
|
+
mount = self._state_view.pipettes.get_mount(pipette_id)
|
|
295
|
+
return self.get_max_travel_z_from_mount(mount=mount)
|
|
296
|
+
|
|
297
|
+
def get_max_travel_z_from_mount(self, mount: MountType) -> float:
|
|
298
|
+
"""Get the maximum allowed z-height for any mount movement.
|
|
299
|
+
|
|
300
|
+
Args:
|
|
301
|
+
mount: Mount to get max travel z-height for.
|
|
302
|
+
"""
|
|
303
|
+
return self._hardware_api.get_instrument_max_height(mount=mount.to_hw_mount())
|
|
304
|
+
|
|
305
|
+
async def move_to(
|
|
306
|
+
self, pipette_id: str, waypoints: List[Waypoint], speed: Optional[float]
|
|
307
|
+
) -> Point:
|
|
308
|
+
"""Move the hardware gantry to a waypoint."""
|
|
309
|
+
assert len(waypoints) > 0, "Must have at least one waypoint"
|
|
310
|
+
|
|
311
|
+
hw_mount = self._state_view.pipettes.get_mount(pipette_id).to_hw_mount()
|
|
312
|
+
|
|
313
|
+
for waypoint in waypoints:
|
|
314
|
+
await self._hardware_api.move_to(
|
|
315
|
+
mount=hw_mount,
|
|
316
|
+
abs_position=waypoint.position,
|
|
317
|
+
critical_point=waypoint.critical_point,
|
|
318
|
+
speed=speed,
|
|
319
|
+
)
|
|
320
|
+
|
|
321
|
+
return waypoints[-1].position
|
|
322
|
+
|
|
323
|
+
async def move_mount_to(
|
|
324
|
+
self, mount: Mount, waypoints: List[Waypoint], speed: Optional[float]
|
|
325
|
+
) -> Point:
|
|
326
|
+
"""Move the given hardware mount to a waypoint."""
|
|
327
|
+
assert len(waypoints) > 0, "Must have at least one waypoint"
|
|
328
|
+
for waypoint in waypoints:
|
|
329
|
+
log.info(f"The current waypoint moving is {waypoint}")
|
|
330
|
+
await self._hardware_api.move_to(
|
|
331
|
+
mount=mount,
|
|
332
|
+
abs_position=waypoint.position,
|
|
333
|
+
critical_point=waypoint.critical_point,
|
|
334
|
+
speed=speed,
|
|
335
|
+
)
|
|
336
|
+
|
|
337
|
+
return waypoints[-1].position
|
|
338
|
+
|
|
339
|
+
async def move_axes(
|
|
340
|
+
self,
|
|
341
|
+
axis_map: Dict[MotorAxis, float],
|
|
342
|
+
critical_point: Optional[Dict[MotorAxis, float]] = None,
|
|
343
|
+
speed: Optional[float] = None,
|
|
344
|
+
relative_move: bool = False,
|
|
345
|
+
expect_stalls: bool = False,
|
|
346
|
+
) -> Dict[MotorAxis, float]:
|
|
347
|
+
"""Move a set of axes a given distance.
|
|
348
|
+
|
|
349
|
+
Args:
|
|
350
|
+
axis_map: The mapping of axes to command.
|
|
351
|
+
critical_point: A critical point override for axes
|
|
352
|
+
speed: Optional speed parameter for the move.
|
|
353
|
+
relative_move: Whether the axis map needs to be converted from a relative to absolute move.
|
|
354
|
+
expect_stalls: Whether it is expected that the move triggers a stall error.
|
|
355
|
+
"""
|
|
356
|
+
try:
|
|
357
|
+
pos_hw = self._convert_axis_map_for_hw(axis_map)
|
|
358
|
+
mount = self.pick_mount_from_axis_map(axis_map)
|
|
359
|
+
if relative_move:
|
|
360
|
+
current_position = await self._hardware_api.current_position(
|
|
361
|
+
mount, refresh=True
|
|
362
|
+
)
|
|
363
|
+
log.info(f"The current position of the robot is: {current_position}.")
|
|
364
|
+
converted_current_position_deck = (
|
|
365
|
+
self._hardware_api.get_deck_from_machine(current_position)
|
|
366
|
+
)
|
|
367
|
+
log.info(f"The current position of the robot is: {current_position}.")
|
|
368
|
+
|
|
369
|
+
pos_hw = target_axis_map_from_relative(pos_hw, current_position)
|
|
370
|
+
log.info(
|
|
371
|
+
f"The absolute position is: {pos_hw} and hw pos map is {pos_hw}."
|
|
372
|
+
)
|
|
373
|
+
log.info(f"The calculated move {pos_hw} and {mount}")
|
|
374
|
+
(
|
|
375
|
+
left_offset,
|
|
376
|
+
right_offset,
|
|
377
|
+
gripper_offset,
|
|
378
|
+
) = self._get_gantry_offsets_for_robot_type()
|
|
379
|
+
absolute_pos = target_axis_map_from_absolute(
|
|
380
|
+
mount,
|
|
381
|
+
pos_hw,
|
|
382
|
+
partial(self._critical_point_for, cp_override=critical_point),
|
|
383
|
+
left_mount_offset=left_offset,
|
|
384
|
+
right_mount_offset=right_offset,
|
|
385
|
+
gripper_mount_offset=gripper_offset,
|
|
386
|
+
)
|
|
387
|
+
log.info(f"The prepped abs {absolute_pos}")
|
|
388
|
+
await self._hardware_api.move_axes(
|
|
389
|
+
position=absolute_pos,
|
|
390
|
+
speed=speed,
|
|
391
|
+
expect_stalls=expect_stalls,
|
|
392
|
+
)
|
|
393
|
+
|
|
394
|
+
except PositionUnknownError as e:
|
|
395
|
+
raise MustHomeError(message=str(e), wrapping=[e])
|
|
396
|
+
|
|
397
|
+
current_position = await self._hardware_api.current_position(
|
|
398
|
+
mount, refresh=True
|
|
399
|
+
)
|
|
400
|
+
converted_current_position_deck = self._hardware_api.get_deck_from_machine(
|
|
401
|
+
current_position
|
|
402
|
+
)
|
|
403
|
+
return {
|
|
404
|
+
self._hardware_axis_to_motor_axis(ax): pos
|
|
405
|
+
for ax, pos in converted_current_position_deck.items()
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
async def move_relative(
|
|
409
|
+
self,
|
|
410
|
+
pipette_id: str,
|
|
411
|
+
delta: Point,
|
|
412
|
+
speed: Optional[float],
|
|
413
|
+
) -> Point:
|
|
414
|
+
"""Move the hardware gantry in a relative direction by delta.
|
|
415
|
+
|
|
416
|
+
Args:
|
|
417
|
+
pipette_id: Not used in hardware implementation.
|
|
418
|
+
delta: Relative X/Y/Z distance to move gantry.
|
|
419
|
+
speed: Optional speed parameter for the move.
|
|
420
|
+
"""
|
|
421
|
+
pipette_location = self._state_view.motion.get_pipette_location(
|
|
422
|
+
pipette_id=pipette_id,
|
|
423
|
+
)
|
|
424
|
+
critical_point = pipette_location.critical_point
|
|
425
|
+
hw_mount = pipette_location.mount.to_hw_mount()
|
|
426
|
+
try:
|
|
427
|
+
await self._hardware_api.move_rel(
|
|
428
|
+
mount=hw_mount,
|
|
429
|
+
delta=delta,
|
|
430
|
+
fail_on_not_homed=True,
|
|
431
|
+
speed=speed,
|
|
432
|
+
)
|
|
433
|
+
point = await self._hardware_api.gantry_position(
|
|
434
|
+
mount=hw_mount,
|
|
435
|
+
critical_point=critical_point,
|
|
436
|
+
fail_on_not_homed=True,
|
|
437
|
+
)
|
|
438
|
+
except PositionUnknownError as e:
|
|
439
|
+
raise MustHomeError(message=str(e), wrapping=[e])
|
|
440
|
+
|
|
441
|
+
return point
|
|
442
|
+
|
|
443
|
+
async def home(self, axes: Optional[List[MotorAxis]]) -> None:
|
|
444
|
+
"""Home the gantry."""
|
|
445
|
+
# TODO(mc, 2022-12-01): this is overly complicated
|
|
446
|
+
# https://opentrons.atlassian.net/browse/RET-1287
|
|
447
|
+
if axes is None:
|
|
448
|
+
await self._hardware_api.home()
|
|
449
|
+
elif axes == [MotorAxis.LEFT_PLUNGER]:
|
|
450
|
+
await self._hardware_api.home_plunger(Mount.LEFT)
|
|
451
|
+
elif axes == [MotorAxis.RIGHT_PLUNGER]:
|
|
452
|
+
await self._hardware_api.home_plunger(Mount.RIGHT)
|
|
453
|
+
elif axes == [MotorAxis.LEFT_Z, MotorAxis.LEFT_PLUNGER]:
|
|
454
|
+
await self._hardware_api.home_z(Mount.LEFT)
|
|
455
|
+
await self._hardware_api.home_plunger(Mount.LEFT)
|
|
456
|
+
elif axes == [MotorAxis.RIGHT_Z, MotorAxis.RIGHT_PLUNGER]:
|
|
457
|
+
await self._hardware_api.home_z(Mount.RIGHT)
|
|
458
|
+
await self._hardware_api.home_plunger(Mount.RIGHT)
|
|
459
|
+
else:
|
|
460
|
+
hardware_axes = [_MOTOR_AXIS_TO_HARDWARE_AXIS[a] for a in axes]
|
|
461
|
+
if self._state_view.config.robot_type == "OT-2 Standard" and any(
|
|
462
|
+
axis not in HardwareAxis.ot2_axes() for axis in hardware_axes
|
|
463
|
+
):
|
|
464
|
+
raise InvalidAxisForRobotType(
|
|
465
|
+
f"{axes} includes axes that are not valid for OT-2 Standard robot type"
|
|
466
|
+
)
|
|
467
|
+
# Hardware API will raise error if invalid axes are passed for the type of robot
|
|
468
|
+
await self._hardware_api.home(axes=hardware_axes)
|
|
469
|
+
|
|
470
|
+
async def retract_axis(self, axis: MotorAxis) -> None:
|
|
471
|
+
"""Retract specified axis."""
|
|
472
|
+
hardware_axis = _MOTOR_AXIS_TO_HARDWARE_AXIS[axis]
|
|
473
|
+
if (
|
|
474
|
+
self._state_view.config.robot_type == "OT-2 Standard"
|
|
475
|
+
and hardware_axis not in HardwareAxis.ot2_axes()
|
|
476
|
+
):
|
|
477
|
+
raise InvalidAxisForRobotType(
|
|
478
|
+
f"{axis} is not valid for OT-2 Standard robot type"
|
|
479
|
+
)
|
|
480
|
+
await self._hardware_api.retract_axis(axis=hardware_axis)
|
|
481
|
+
|
|
482
|
+
async def prepare_for_mount_movement(self, mount: Mount) -> None:
|
|
483
|
+
"""Retract the 'idle' mount if necessary."""
|
|
484
|
+
await self._hardware_api.prepare_for_mount_movement(mount)
|
|
485
|
+
|
|
486
|
+
|
|
487
|
+
class VirtualGantryMover(GantryMover):
|
|
488
|
+
"""State store based gantry movement handler for simulation/analysis."""
|
|
489
|
+
|
|
490
|
+
def __init__(self, state_view: StateView) -> None:
|
|
491
|
+
self._state_view = state_view
|
|
492
|
+
|
|
493
|
+
def motor_axis_to_hardware_axis(self, motor_axis: MotorAxis) -> HardwareAxis:
|
|
494
|
+
"""Transform an engine motor axis into a hardware axis."""
|
|
495
|
+
return _MOTOR_AXIS_TO_HARDWARE_AXIS[motor_axis]
|
|
496
|
+
|
|
497
|
+
def pick_mount_from_axis_map(self, axis_map: Dict[MotorAxis, float]) -> Mount:
|
|
498
|
+
"""Find a mount axis in the axis_map if it exists otherwise default to left mount."""
|
|
499
|
+
found_mount = Mount.LEFT
|
|
500
|
+
mounts = list(_MOTOR_AXIS_TO_HARDWARE_MOUNT.keys())
|
|
501
|
+
for k in axis_map.keys():
|
|
502
|
+
if k in mounts:
|
|
503
|
+
found_mount = _MOTOR_AXIS_TO_HARDWARE_MOUNT[k]
|
|
504
|
+
break
|
|
505
|
+
return found_mount
|
|
506
|
+
|
|
507
|
+
async def get_position(
|
|
508
|
+
self,
|
|
509
|
+
pipette_id: str,
|
|
510
|
+
current_well: Optional[CurrentWell] = None,
|
|
511
|
+
fail_on_not_homed: bool = False,
|
|
512
|
+
) -> Point:
|
|
513
|
+
"""Get the current position of the gantry.
|
|
514
|
+
|
|
515
|
+
Args:
|
|
516
|
+
pipette_id: Pipette ID to get position for.
|
|
517
|
+
current_well: Not used in virtual implementation.
|
|
518
|
+
fail_on_not_homed: Not used in virtual implementation.
|
|
519
|
+
"""
|
|
520
|
+
origin_deck_point = self._state_view.pipettes.get_deck_point(pipette_id)
|
|
521
|
+
if origin_deck_point is not None:
|
|
522
|
+
origin = Point(
|
|
523
|
+
x=origin_deck_point.x, y=origin_deck_point.y, z=origin_deck_point.z
|
|
524
|
+
)
|
|
525
|
+
else:
|
|
526
|
+
origin = Point(x=0, y=0, z=0)
|
|
527
|
+
return origin
|
|
528
|
+
|
|
529
|
+
async def get_position_from_mount(
|
|
530
|
+
self,
|
|
531
|
+
mount: Mount,
|
|
532
|
+
critical_point: Optional[CriticalPoint] = None,
|
|
533
|
+
fail_on_not_homed: bool = False,
|
|
534
|
+
) -> Point:
|
|
535
|
+
"""Get the current position of the gantry based on the mount.
|
|
536
|
+
|
|
537
|
+
Args:
|
|
538
|
+
mount: The mount to get the position for.
|
|
539
|
+
critical_point: Optional parameter for getting instrument location data, effects critical point.
|
|
540
|
+
fail_on_not_homed: Raise PositionUnknownError if gantry position is not known.
|
|
541
|
+
"""
|
|
542
|
+
pipette = self._state_view.pipettes.get_by_mount(MountType[mount.name])
|
|
543
|
+
origin_deck_point = (
|
|
544
|
+
self._state_view.pipettes.get_deck_point(pipette.id) if pipette else None
|
|
545
|
+
)
|
|
546
|
+
if origin_deck_point is not None:
|
|
547
|
+
origin = Point(
|
|
548
|
+
x=origin_deck_point.x, y=origin_deck_point.y, z=origin_deck_point.z
|
|
549
|
+
)
|
|
550
|
+
else:
|
|
551
|
+
origin = Point(x=0, y=0, z=0)
|
|
552
|
+
return origin
|
|
553
|
+
|
|
554
|
+
def get_max_travel_z(self, pipette_id: str) -> float:
|
|
555
|
+
"""Get the maximum allowed z-height for pipette movement.
|
|
556
|
+
|
|
557
|
+
Args:
|
|
558
|
+
pipette_id: Pipette ID to get instrument height and tip length for.
|
|
559
|
+
"""
|
|
560
|
+
if self._state_view.config.robot_type == "OT-2 Standard":
|
|
561
|
+
instrument_height = self._state_view.pipettes.get_instrument_max_height_ot2(
|
|
562
|
+
pipette_id
|
|
563
|
+
)
|
|
564
|
+
else:
|
|
565
|
+
instrument_height = VIRTUAL_MAX_OT3_HEIGHT
|
|
566
|
+
|
|
567
|
+
tip = self._state_view.pipettes.get_attached_tip(pipette_id=pipette_id)
|
|
568
|
+
tip_length = tip.length if tip is not None else 0
|
|
569
|
+
return instrument_height - tip_length
|
|
570
|
+
|
|
571
|
+
def get_max_travel_z_from_mount(self, mount: MountType) -> float:
|
|
572
|
+
"""Get the maximum allowed z-height for mount."""
|
|
573
|
+
pipette = self._state_view.pipettes.get_by_mount(mount)
|
|
574
|
+
if self._state_view.config.robot_type == "OT-2 Standard":
|
|
575
|
+
instrument_height = (
|
|
576
|
+
self._state_view.pipettes.get_instrument_max_height_ot2(pipette.id)
|
|
577
|
+
if pipette
|
|
578
|
+
else VIRTUAL_MAX_OT2_HEIGHT
|
|
579
|
+
)
|
|
580
|
+
else:
|
|
581
|
+
instrument_height = VIRTUAL_MAX_OT3_HEIGHT
|
|
582
|
+
if pipette:
|
|
583
|
+
tip = self._state_view.pipettes.get_attached_tip(pipette_id=pipette.id)
|
|
584
|
+
tip_length = tip.length if tip is not None else 0.0
|
|
585
|
+
else:
|
|
586
|
+
tip_length = 0.0
|
|
587
|
+
return instrument_height - tip_length
|
|
588
|
+
|
|
589
|
+
async def move_axes(
|
|
590
|
+
self,
|
|
591
|
+
axis_map: Dict[MotorAxis, float],
|
|
592
|
+
critical_point: Optional[Dict[MotorAxis, float]] = None,
|
|
593
|
+
speed: Optional[float] = None,
|
|
594
|
+
relative_move: bool = False,
|
|
595
|
+
expect_stalls: bool = False,
|
|
596
|
+
) -> Dict[MotorAxis, float]:
|
|
597
|
+
"""Move the give axes map. No-op in virtual implementation."""
|
|
598
|
+
mount = self.pick_mount_from_axis_map(axis_map)
|
|
599
|
+
current_position = await self.get_position_from_mount(mount)
|
|
600
|
+
updated_position = {}
|
|
601
|
+
if relative_move:
|
|
602
|
+
updated_position[MotorAxis.X] = (
|
|
603
|
+
axis_map.get(MotorAxis.X, 0.0) + current_position[0]
|
|
604
|
+
)
|
|
605
|
+
updated_position[MotorAxis.Y] = (
|
|
606
|
+
axis_map.get(MotorAxis.Y, 0.0) + current_position[1]
|
|
607
|
+
)
|
|
608
|
+
if mount == Mount.RIGHT:
|
|
609
|
+
updated_position[MotorAxis.RIGHT_Z] = (
|
|
610
|
+
axis_map.get(MotorAxis.RIGHT_Z, 0.0) + current_position[2]
|
|
611
|
+
)
|
|
612
|
+
elif mount == Mount.EXTENSION:
|
|
613
|
+
updated_position[MotorAxis.EXTENSION_Z] = (
|
|
614
|
+
axis_map.get(MotorAxis.EXTENSION_Z, 0.0) + current_position[2]
|
|
615
|
+
)
|
|
616
|
+
else:
|
|
617
|
+
updated_position[MotorAxis.LEFT_Z] = (
|
|
618
|
+
axis_map.get(MotorAxis.LEFT_Z, 0.0) + current_position[2]
|
|
619
|
+
)
|
|
620
|
+
else:
|
|
621
|
+
critical_point = critical_point or {}
|
|
622
|
+
updated_position = {
|
|
623
|
+
ax: pos - critical_point.get(ax, 0.0) for ax, pos in axis_map.items()
|
|
624
|
+
}
|
|
625
|
+
return updated_position
|
|
626
|
+
|
|
627
|
+
async def move_mount_to(
|
|
628
|
+
self, mount: Mount, waypoints: List[Waypoint], speed: Optional[float]
|
|
629
|
+
) -> Point:
|
|
630
|
+
"""Move the hardware mount to a waypoint. No-op in virtual implementation."""
|
|
631
|
+
assert len(waypoints) > 0, "Must have at least one waypoint"
|
|
632
|
+
return waypoints[-1].position
|
|
633
|
+
|
|
634
|
+
async def move_to(
|
|
635
|
+
self, pipette_id: str, waypoints: List[Waypoint], speed: Optional[float]
|
|
636
|
+
) -> Point:
|
|
637
|
+
"""Move the hardware gantry to a waypoint. No-op in virtual implementation."""
|
|
638
|
+
assert len(waypoints) > 0, "Must have at least one waypoint"
|
|
639
|
+
return waypoints[-1].position
|
|
640
|
+
|
|
641
|
+
async def move_relative(
|
|
642
|
+
self,
|
|
643
|
+
pipette_id: str,
|
|
644
|
+
delta: Point,
|
|
645
|
+
speed: Optional[float],
|
|
646
|
+
) -> Point:
|
|
647
|
+
"""Move the hardware gantry in a relative direction by delta.
|
|
648
|
+
|
|
649
|
+
Args:
|
|
650
|
+
pipette_id: Pipette ID to get position of for virtual move.
|
|
651
|
+
delta: Relative X/Y/Z distance to move gantry.
|
|
652
|
+
speed: Not used in virtual implementation.
|
|
653
|
+
"""
|
|
654
|
+
origin = await self.get_position(pipette_id)
|
|
655
|
+
return origin + delta
|
|
656
|
+
|
|
657
|
+
async def home(self, axes: Optional[List[MotorAxis]]) -> None:
|
|
658
|
+
"""Home the gantry. No-op in virtual implementation."""
|
|
659
|
+
pass
|
|
660
|
+
|
|
661
|
+
async def retract_axis(self, axis: MotorAxis) -> None:
|
|
662
|
+
"""Retract the specified axis. No-op in virtual implementation."""
|
|
663
|
+
pass
|
|
664
|
+
|
|
665
|
+
async def prepare_for_mount_movement(self, mount: Mount) -> None:
|
|
666
|
+
"""Retract the 'idle' mount if necessary."""
|
|
667
|
+
pass
|
|
668
|
+
|
|
669
|
+
def motor_axes_to_present_hardware_axes(
|
|
670
|
+
self, motor_axes: List[MotorAxis]
|
|
671
|
+
) -> List[HardwareAxis]:
|
|
672
|
+
"""Get present hardware axes from a list of engine axes. In simulation, all axes are present."""
|
|
673
|
+
return [
|
|
674
|
+
self.motor_axis_to_hardware_axis(motor_axis) for motor_axis in motor_axes
|
|
675
|
+
]
|
|
676
|
+
|
|
677
|
+
|
|
678
|
+
def create_gantry_mover(
|
|
679
|
+
state_view: StateView, hardware_api: HardwareControlAPI
|
|
680
|
+
) -> GantryMover:
|
|
681
|
+
"""Create a gantry mover."""
|
|
682
|
+
return (
|
|
683
|
+
HardwareGantryMover(hardware_api=hardware_api, state_view=state_view)
|
|
684
|
+
if state_view.config.use_virtual_pipettes is False
|
|
685
|
+
else VirtualGantryMover(state_view=state_view)
|
|
686
|
+
)
|