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,116 @@
|
|
|
1
|
+
"""Customize the ProtocolEngine to monitor and control legacy (APIv2) protocols."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import asyncio
|
|
5
|
+
from contextlib import ExitStack
|
|
6
|
+
from typing import Optional
|
|
7
|
+
|
|
8
|
+
from opentrons.legacy_commands.types import CommandMessage as LegacyCommand
|
|
9
|
+
from opentrons.legacy_broker import LegacyBroker
|
|
10
|
+
from opentrons.protocol_api.core.legacy.load_info import LoadInfo
|
|
11
|
+
from opentrons.protocol_engine import AbstractPlugin, actions as pe_actions
|
|
12
|
+
from opentrons.util.broker import ReadOnlyBroker
|
|
13
|
+
|
|
14
|
+
from .legacy_command_mapper import LegacyCommandMapper
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class LegacyContextPlugin(AbstractPlugin):
|
|
18
|
+
"""A ProtocolEngine plugin to monitor and control an APIv2 protocol.
|
|
19
|
+
|
|
20
|
+
In the legacy ProtocolContext, protocol execution is accomplished
|
|
21
|
+
by direct communication with the HardwareControlAPI, as opposed to an
|
|
22
|
+
intermediate layer like the ProtocolEngine. This plugin wraps up
|
|
23
|
+
and hides this behavior, so the ProtocolEngine can monitor
|
|
24
|
+
the run of a legacy protocol without affecting the execution of
|
|
25
|
+
the protocol commands themselves.
|
|
26
|
+
|
|
27
|
+
This plugin allows a ProtocolEngine to subscribe to what is being done with the
|
|
28
|
+
legacy ProtocolContext, and insert matching commands into ProtocolEngine state for
|
|
29
|
+
purely progress-tracking purposes.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
def __init__(
|
|
33
|
+
self,
|
|
34
|
+
engine_loop: asyncio.AbstractEventLoop,
|
|
35
|
+
broker: LegacyBroker,
|
|
36
|
+
equipment_broker: ReadOnlyBroker[LoadInfo],
|
|
37
|
+
legacy_command_mapper: Optional[LegacyCommandMapper] = None,
|
|
38
|
+
) -> None:
|
|
39
|
+
"""Initialize the plugin with its dependencies."""
|
|
40
|
+
self._engine_loop = engine_loop
|
|
41
|
+
|
|
42
|
+
self._broker = broker
|
|
43
|
+
self._equipment_broker = equipment_broker
|
|
44
|
+
self._legacy_command_mapper = legacy_command_mapper or LegacyCommandMapper()
|
|
45
|
+
|
|
46
|
+
self._subscription_exit_stack: Optional[ExitStack] = None
|
|
47
|
+
|
|
48
|
+
def setup(self) -> None:
|
|
49
|
+
"""Set up the plugin.
|
|
50
|
+
|
|
51
|
+
Subscribe to the APIv2 context's message brokers to be informed
|
|
52
|
+
of the APIv2 protocol's activity.
|
|
53
|
+
"""
|
|
54
|
+
# Subscribe to activity on the APIv2 context,
|
|
55
|
+
# and arrange to unsubscribe when this plugin is torn down.
|
|
56
|
+
# Use an exit stack so if any part of this setup fails,
|
|
57
|
+
# we clean up the parts that succeeded in reverse order.
|
|
58
|
+
with ExitStack() as exit_stack:
|
|
59
|
+
command_broker_unsubscribe = self._broker.subscribe(
|
|
60
|
+
topic="command",
|
|
61
|
+
handler=self._handle_legacy_command,
|
|
62
|
+
)
|
|
63
|
+
exit_stack.callback(command_broker_unsubscribe)
|
|
64
|
+
|
|
65
|
+
exit_stack.enter_context(
|
|
66
|
+
self._equipment_broker.subscribed(
|
|
67
|
+
callback=self._handle_equipment_loaded
|
|
68
|
+
)
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
# All subscriptions succeeded.
|
|
72
|
+
# Save the exit stack so our teardown method can use it later
|
|
73
|
+
# to clean up these subscriptions.
|
|
74
|
+
self._subscription_exit_stack = exit_stack.pop_all()
|
|
75
|
+
|
|
76
|
+
# todo(mm, 2024-08-21): This no longer needs to be async.
|
|
77
|
+
async def teardown(self) -> None:
|
|
78
|
+
"""Tear down the plugin, undoing the work done in `setup()`.
|
|
79
|
+
|
|
80
|
+
Called by Protocol Engine.
|
|
81
|
+
At this point, the APIv2 protocol script must have exited.
|
|
82
|
+
"""
|
|
83
|
+
if self._subscription_exit_stack is not None:
|
|
84
|
+
self._subscription_exit_stack.close()
|
|
85
|
+
self._subscription_exit_stack = None
|
|
86
|
+
|
|
87
|
+
def handle_action(self, action: pe_actions.Action) -> None:
|
|
88
|
+
"""React to a ProtocolEngine action."""
|
|
89
|
+
# TODO(jbl 2022-07-06) handle_action stub should be completely removed
|
|
90
|
+
pass
|
|
91
|
+
|
|
92
|
+
def _handle_legacy_command(self, command: LegacyCommand) -> None:
|
|
93
|
+
"""Handle a command reported by the legacy APIv2 protocol.
|
|
94
|
+
|
|
95
|
+
Used as a broker callback, so this will run in the APIv2 protocol's thread.
|
|
96
|
+
"""
|
|
97
|
+
pe_actions = self._legacy_command_mapper.map_command(command=command)
|
|
98
|
+
future = asyncio.run_coroutine_threadsafe(
|
|
99
|
+
self._dispatch_action_list(pe_actions), self._engine_loop
|
|
100
|
+
)
|
|
101
|
+
future.result()
|
|
102
|
+
|
|
103
|
+
def _handle_equipment_loaded(self, load_info: LoadInfo) -> None:
|
|
104
|
+
"""Handle an equipment load reported by the legacy APIv2 protocol.
|
|
105
|
+
|
|
106
|
+
Used as a broker callback, so this will run in the APIv2 protocol's thread.
|
|
107
|
+
"""
|
|
108
|
+
pe_actions = self._legacy_command_mapper.map_equipment_load(load_info=load_info)
|
|
109
|
+
future = asyncio.run_coroutine_threadsafe(
|
|
110
|
+
self._dispatch_action_list(pe_actions), self._engine_loop
|
|
111
|
+
)
|
|
112
|
+
future.result()
|
|
113
|
+
|
|
114
|
+
async def _dispatch_action_list(self, actions: list[pe_actions.Action]) -> None:
|
|
115
|
+
for action in actions:
|
|
116
|
+
self.dispatch(action)
|
|
@@ -0,0 +1,530 @@
|
|
|
1
|
+
"""Protocol run control and management."""
|
|
2
|
+
import asyncio
|
|
3
|
+
from typing import List, NamedTuple, Optional, Union
|
|
4
|
+
|
|
5
|
+
from abc import ABC, abstractmethod
|
|
6
|
+
|
|
7
|
+
import anyio
|
|
8
|
+
|
|
9
|
+
from opentrons.hardware_control import HardwareControlAPI
|
|
10
|
+
from opentrons import protocol_reader
|
|
11
|
+
from opentrons.legacy_broker import LegacyBroker
|
|
12
|
+
from opentrons.protocol_api import ParameterContext
|
|
13
|
+
from opentrons.protocol_api.core.legacy.load_info import LoadInfo
|
|
14
|
+
from opentrons.protocol_engine.commands.command import CommandStatus
|
|
15
|
+
from opentrons.protocol_engine.error_recovery_policy import ErrorRecoveryType
|
|
16
|
+
from opentrons.protocol_reader import (
|
|
17
|
+
ProtocolSource,
|
|
18
|
+
JsonProtocolConfig,
|
|
19
|
+
PythonProtocolConfig,
|
|
20
|
+
)
|
|
21
|
+
from opentrons.protocol_engine import (
|
|
22
|
+
ProtocolEngine,
|
|
23
|
+
StateSummary,
|
|
24
|
+
Command,
|
|
25
|
+
commands as pe_commands,
|
|
26
|
+
)
|
|
27
|
+
from opentrons.protocol_engine.types import CommandAnnotation
|
|
28
|
+
from opentrons.protocols.parse import PythonParseMode
|
|
29
|
+
from opentrons.util.async_helpers import asyncio_yield
|
|
30
|
+
from opentrons.util.broker import Broker
|
|
31
|
+
|
|
32
|
+
from .task_queue import TaskQueue
|
|
33
|
+
from .json_file_reader import JsonFileReader
|
|
34
|
+
from .json_translator import JsonTranslator
|
|
35
|
+
from .legacy_context_plugin import LegacyContextPlugin
|
|
36
|
+
from .python_protocol_wrappers import (
|
|
37
|
+
LEGACY_PYTHON_API_VERSION_CUTOFF,
|
|
38
|
+
LEGACY_JSON_SCHEMA_VERSION_CUTOFF,
|
|
39
|
+
PythonAndLegacyFileReader,
|
|
40
|
+
ProtocolContextCreator,
|
|
41
|
+
PythonProtocolExecutor,
|
|
42
|
+
)
|
|
43
|
+
from ..protocol_engine.errors import ProtocolCommandFailedError
|
|
44
|
+
from ..protocol_engine.types import (
|
|
45
|
+
PostRunHardwareState,
|
|
46
|
+
DeckConfigurationType,
|
|
47
|
+
RunTimeParameter,
|
|
48
|
+
PrimitiveRunTimeParamValuesType,
|
|
49
|
+
CSVRuntimeParamPaths,
|
|
50
|
+
)
|
|
51
|
+
from ..protocols.types import PythonProtocol
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class RunResult(NamedTuple):
|
|
55
|
+
"""Result data from a run, pulled from the ProtocolEngine."""
|
|
56
|
+
|
|
57
|
+
commands: List[Command]
|
|
58
|
+
state_summary: StateSummary
|
|
59
|
+
parameters: List[RunTimeParameter]
|
|
60
|
+
command_annotations: List[CommandAnnotation]
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class AbstractRunner(ABC):
|
|
64
|
+
"""An interface to manage and control a protocol run.
|
|
65
|
+
|
|
66
|
+
A Runner is primarily responsible for feeding a ProtocolEngine
|
|
67
|
+
with commands and control signals. These commands and signals are
|
|
68
|
+
generated by protocol files, hardware signals, or externally via
|
|
69
|
+
the HTTP robot-server.
|
|
70
|
+
|
|
71
|
+
A Runner controls a single run. Once the run is finished,
|
|
72
|
+
you will need a new Runner to do another run.
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
def __init__(self, protocol_engine: ProtocolEngine) -> None:
|
|
76
|
+
self._protocol_engine = protocol_engine
|
|
77
|
+
self._broker = LegacyBroker()
|
|
78
|
+
|
|
79
|
+
# TODO(mm, 2023-10-03): `LegacyBroker` is specific to Python protocols and JSON protocols ≤v5.
|
|
80
|
+
# We'll need to extend this in order to report progress from newer JSON protocols.
|
|
81
|
+
#
|
|
82
|
+
# TODO(mm, 2023-10-04): When we switch this to return a new `Broker` instead of a
|
|
83
|
+
# `LegacyBroker`, we should annotate the return type as a `ReadOnlyBroker`.
|
|
84
|
+
@property
|
|
85
|
+
def broker(self) -> LegacyBroker:
|
|
86
|
+
"""Return a broker that you can subscribe to in order to monitor protocol progress.
|
|
87
|
+
|
|
88
|
+
Currently, this only returns messages for `PythonAndLegacyRunner`.
|
|
89
|
+
Otherwise, it's a no-op.
|
|
90
|
+
"""
|
|
91
|
+
return self._broker
|
|
92
|
+
|
|
93
|
+
@property
|
|
94
|
+
def run_time_parameters(self) -> List[RunTimeParameter]:
|
|
95
|
+
"""Parameter definitions defined by protocol, if any. Currently only for python protocols."""
|
|
96
|
+
return []
|
|
97
|
+
|
|
98
|
+
@property
|
|
99
|
+
def command_annotations(self) -> List[CommandAnnotation]:
|
|
100
|
+
"""Command annotations defined by protocol, if any. Currently only for json protocols."""
|
|
101
|
+
return []
|
|
102
|
+
|
|
103
|
+
def was_started(self) -> bool:
|
|
104
|
+
"""Whether the run has been started.
|
|
105
|
+
|
|
106
|
+
This value is latched; once it is True, it will never become False.
|
|
107
|
+
"""
|
|
108
|
+
return self._protocol_engine.state_view.commands.has_been_played()
|
|
109
|
+
|
|
110
|
+
def play(self, deck_configuration: Optional[DeckConfigurationType] = None) -> None:
|
|
111
|
+
"""Start or resume the run."""
|
|
112
|
+
# todo(mm, 2024-07-09): The deck configuration is set at the same time here for
|
|
113
|
+
# historical reasons. It's unsafe to change the deck configuration mid-run
|
|
114
|
+
# and we're relying on the caller to not do that.
|
|
115
|
+
self._protocol_engine.set_deck_configuration(deck_configuration)
|
|
116
|
+
self._protocol_engine.play()
|
|
117
|
+
|
|
118
|
+
def pause(self) -> None:
|
|
119
|
+
"""Pause the run."""
|
|
120
|
+
self._protocol_engine.request_pause()
|
|
121
|
+
|
|
122
|
+
async def stop(self) -> None:
|
|
123
|
+
"""Stop (cancel) the run."""
|
|
124
|
+
if self.was_started():
|
|
125
|
+
await self._protocol_engine.request_stop()
|
|
126
|
+
else:
|
|
127
|
+
await self._protocol_engine.finish(
|
|
128
|
+
drop_tips_after_run=False,
|
|
129
|
+
set_run_status=False,
|
|
130
|
+
post_run_hardware_state=PostRunHardwareState.STAY_ENGAGED_IN_PLACE,
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
def resume_from_recovery(self, reconcile_false_positive: bool) -> None:
|
|
134
|
+
"""See `ProtocolEngine.resume_from_recovery()`."""
|
|
135
|
+
self._protocol_engine.resume_from_recovery(reconcile_false_positive)
|
|
136
|
+
|
|
137
|
+
@abstractmethod
|
|
138
|
+
async def run(
|
|
139
|
+
self,
|
|
140
|
+
deck_configuration: DeckConfigurationType,
|
|
141
|
+
protocol_source: Optional[ProtocolSource] = None,
|
|
142
|
+
run_time_param_values: Optional[PrimitiveRunTimeParamValuesType] = None,
|
|
143
|
+
) -> RunResult:
|
|
144
|
+
"""Run a given protocol to completion."""
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
class PythonAndLegacyRunner(AbstractRunner):
|
|
148
|
+
"""Protocol runner implementation for Python protocols, and JSON protocols ≤v5."""
|
|
149
|
+
|
|
150
|
+
def __init__(
|
|
151
|
+
self,
|
|
152
|
+
protocol_engine: ProtocolEngine,
|
|
153
|
+
hardware_api: HardwareControlAPI,
|
|
154
|
+
task_queue: Optional[TaskQueue] = None,
|
|
155
|
+
python_and_legacy_file_reader: Optional[PythonAndLegacyFileReader] = None,
|
|
156
|
+
protocol_context_creator: Optional[ProtocolContextCreator] = None,
|
|
157
|
+
python_protocol_executor: Optional[PythonProtocolExecutor] = None,
|
|
158
|
+
post_run_hardware_state: PostRunHardwareState = PostRunHardwareState.HOME_AND_STAY_ENGAGED,
|
|
159
|
+
drop_tips_after_run: bool = True,
|
|
160
|
+
) -> None:
|
|
161
|
+
"""Initialize the PythonAndLegacyRunner with its dependencies."""
|
|
162
|
+
super().__init__(protocol_engine)
|
|
163
|
+
self._hardware_api = hardware_api
|
|
164
|
+
self._protocol_file_reader = (
|
|
165
|
+
python_and_legacy_file_reader or PythonAndLegacyFileReader()
|
|
166
|
+
)
|
|
167
|
+
self._protocol_context_creator = (
|
|
168
|
+
protocol_context_creator
|
|
169
|
+
or ProtocolContextCreator(
|
|
170
|
+
hardware_api=hardware_api,
|
|
171
|
+
protocol_engine=protocol_engine,
|
|
172
|
+
)
|
|
173
|
+
)
|
|
174
|
+
self._protocol_executor = python_protocol_executor or PythonProtocolExecutor()
|
|
175
|
+
# TODO(mc, 2022-01-11): replace task queue with specific implementations
|
|
176
|
+
# of runner interface
|
|
177
|
+
self._task_queue = task_queue or TaskQueue()
|
|
178
|
+
self._task_queue.set_cleanup_func(
|
|
179
|
+
func=protocol_engine.finish,
|
|
180
|
+
drop_tips_after_run=drop_tips_after_run,
|
|
181
|
+
post_run_hardware_state=post_run_hardware_state,
|
|
182
|
+
)
|
|
183
|
+
self._parameter_context: Optional[ParameterContext] = None
|
|
184
|
+
|
|
185
|
+
@property
|
|
186
|
+
def run_time_parameters(self) -> List[RunTimeParameter]:
|
|
187
|
+
"""Parameter definitions defined by protocol, if any."""
|
|
188
|
+
if self._parameter_context is not None:
|
|
189
|
+
return self._parameter_context.export_parameters_for_analysis()
|
|
190
|
+
return []
|
|
191
|
+
|
|
192
|
+
async def load(
|
|
193
|
+
self,
|
|
194
|
+
protocol_source: ProtocolSource,
|
|
195
|
+
python_parse_mode: PythonParseMode,
|
|
196
|
+
run_time_param_values: Optional[PrimitiveRunTimeParamValuesType],
|
|
197
|
+
run_time_param_paths: Optional[CSVRuntimeParamPaths],
|
|
198
|
+
) -> None:
|
|
199
|
+
"""Load a Python or JSONv5(& older) ProtocolSource into managed ProtocolEngine."""
|
|
200
|
+
labware_definitions = await protocol_reader.extract_labware_definitions(
|
|
201
|
+
protocol_source=protocol_source
|
|
202
|
+
)
|
|
203
|
+
for definition in labware_definitions:
|
|
204
|
+
# Assume adding a labware definition is fast and there are not many labware
|
|
205
|
+
# definitions, so we don't need to yield here.
|
|
206
|
+
self._protocol_engine.add_labware_definition(definition)
|
|
207
|
+
|
|
208
|
+
# fixme(mm, 2022-12-23): This does I/O and compute-bound parsing that will block
|
|
209
|
+
# the event loop. Jira RSS-165.
|
|
210
|
+
protocol = self._protocol_file_reader.read(
|
|
211
|
+
protocol_source, labware_definitions, python_parse_mode
|
|
212
|
+
)
|
|
213
|
+
if isinstance(protocol, PythonProtocol):
|
|
214
|
+
self._parameter_context = ParameterContext(api_version=protocol.api_level)
|
|
215
|
+
run_time_parameters_with_overrides = (
|
|
216
|
+
self._protocol_executor.extract_run_parameters(
|
|
217
|
+
protocol=protocol,
|
|
218
|
+
parameter_context=self._parameter_context,
|
|
219
|
+
run_time_param_overrides=run_time_param_values,
|
|
220
|
+
run_time_param_file_overrides=run_time_param_paths,
|
|
221
|
+
)
|
|
222
|
+
)
|
|
223
|
+
else:
|
|
224
|
+
run_time_parameters_with_overrides = None
|
|
225
|
+
equipment_broker = None
|
|
226
|
+
|
|
227
|
+
if protocol.api_level < LEGACY_PYTHON_API_VERSION_CUTOFF:
|
|
228
|
+
equipment_broker = Broker[LoadInfo]()
|
|
229
|
+
self._protocol_engine.add_plugin(
|
|
230
|
+
LegacyContextPlugin(
|
|
231
|
+
engine_loop=asyncio.get_running_loop(),
|
|
232
|
+
broker=self._broker,
|
|
233
|
+
equipment_broker=equipment_broker,
|
|
234
|
+
)
|
|
235
|
+
)
|
|
236
|
+
self._hardware_api.should_taskify_movement_execution(taskify=True)
|
|
237
|
+
else:
|
|
238
|
+
self._hardware_api.should_taskify_movement_execution(taskify=False)
|
|
239
|
+
|
|
240
|
+
context = self._protocol_context_creator.create(
|
|
241
|
+
protocol=protocol,
|
|
242
|
+
broker=self._broker,
|
|
243
|
+
equipment_broker=equipment_broker,
|
|
244
|
+
)
|
|
245
|
+
initial_home_command = pe_commands.HomeCreate(
|
|
246
|
+
# this command homes all axes, including pipette plunger and gripper jaw
|
|
247
|
+
params=pe_commands.HomeParams(axes=None)
|
|
248
|
+
)
|
|
249
|
+
|
|
250
|
+
async def run_func() -> None:
|
|
251
|
+
await self._protocol_engine.add_and_execute_command(
|
|
252
|
+
request=initial_home_command
|
|
253
|
+
)
|
|
254
|
+
await self._protocol_executor.execute(
|
|
255
|
+
protocol=protocol,
|
|
256
|
+
context=context,
|
|
257
|
+
run_time_parameters_with_overrides=run_time_parameters_with_overrides,
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
self._task_queue.set_run_func(run_func)
|
|
261
|
+
|
|
262
|
+
async def run( # noqa: D102
|
|
263
|
+
self,
|
|
264
|
+
deck_configuration: DeckConfigurationType,
|
|
265
|
+
protocol_source: Optional[ProtocolSource] = None,
|
|
266
|
+
run_time_param_values: Optional[PrimitiveRunTimeParamValuesType] = None,
|
|
267
|
+
run_time_param_paths: Optional[CSVRuntimeParamPaths] = None,
|
|
268
|
+
python_parse_mode: PythonParseMode = PythonParseMode.NORMAL,
|
|
269
|
+
) -> RunResult:
|
|
270
|
+
# TODO(mc, 2022-01-11): move load to runner creation, remove from `run`
|
|
271
|
+
# currently `protocol_source` arg is only used by tests & protocol analyzer
|
|
272
|
+
if protocol_source:
|
|
273
|
+
await self.load(
|
|
274
|
+
protocol_source=protocol_source,
|
|
275
|
+
python_parse_mode=python_parse_mode,
|
|
276
|
+
run_time_param_values=run_time_param_values,
|
|
277
|
+
run_time_param_paths=run_time_param_paths,
|
|
278
|
+
)
|
|
279
|
+
|
|
280
|
+
self.play(deck_configuration=deck_configuration)
|
|
281
|
+
self._task_queue.start()
|
|
282
|
+
await self._task_queue.join()
|
|
283
|
+
|
|
284
|
+
run_data = self._protocol_engine.state_view.get_summary()
|
|
285
|
+
commands = self._protocol_engine.state_view.commands.get_all()
|
|
286
|
+
parameters = self.run_time_parameters
|
|
287
|
+
return RunResult(
|
|
288
|
+
commands=commands,
|
|
289
|
+
state_summary=run_data,
|
|
290
|
+
parameters=parameters,
|
|
291
|
+
command_annotations=[],
|
|
292
|
+
)
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
class JsonRunner(AbstractRunner):
|
|
296
|
+
"""Protocol runner implementation for json protocols."""
|
|
297
|
+
|
|
298
|
+
def __init__(
|
|
299
|
+
self,
|
|
300
|
+
protocol_engine: ProtocolEngine,
|
|
301
|
+
hardware_api: HardwareControlAPI,
|
|
302
|
+
task_queue: Optional[TaskQueue] = None,
|
|
303
|
+
json_file_reader: Optional[JsonFileReader] = None,
|
|
304
|
+
json_translator: Optional[JsonTranslator] = None,
|
|
305
|
+
post_run_hardware_state: PostRunHardwareState = PostRunHardwareState.HOME_AND_STAY_ENGAGED,
|
|
306
|
+
drop_tips_after_run: bool = True,
|
|
307
|
+
) -> None:
|
|
308
|
+
"""Initialize the JsonRunner with its dependencies."""
|
|
309
|
+
super().__init__(protocol_engine)
|
|
310
|
+
self._protocol_engine = protocol_engine
|
|
311
|
+
self._json_file_reader = json_file_reader or JsonFileReader()
|
|
312
|
+
self._json_translator = json_translator or JsonTranslator()
|
|
313
|
+
# TODO(mc, 2022-01-11): replace task queue with specific implementations
|
|
314
|
+
# of runner interface
|
|
315
|
+
self._task_queue = (
|
|
316
|
+
task_queue or TaskQueue()
|
|
317
|
+
) # cleanup_func=protocol_engine.finish))
|
|
318
|
+
self._task_queue.set_cleanup_func(
|
|
319
|
+
func=protocol_engine.finish,
|
|
320
|
+
drop_tips_after_run=drop_tips_after_run,
|
|
321
|
+
post_run_hardware_state=post_run_hardware_state,
|
|
322
|
+
)
|
|
323
|
+
|
|
324
|
+
hardware_api.should_taskify_movement_execution(taskify=False)
|
|
325
|
+
self._queued_commands: List[pe_commands.CommandCreate] = []
|
|
326
|
+
self._command_annotations: List[CommandAnnotation] = []
|
|
327
|
+
|
|
328
|
+
@property
|
|
329
|
+
def command_annotations(self) -> List[CommandAnnotation]:
|
|
330
|
+
"""Command annotations defined by protocol, if any."""
|
|
331
|
+
return self._command_annotations
|
|
332
|
+
|
|
333
|
+
async def load(self, protocol_source: ProtocolSource) -> None:
|
|
334
|
+
"""Load a JSONv6+ ProtocolSource into managed ProtocolEngine."""
|
|
335
|
+
labware_definitions = await protocol_reader.extract_labware_definitions(
|
|
336
|
+
protocol_source=protocol_source
|
|
337
|
+
)
|
|
338
|
+
for definition in labware_definitions:
|
|
339
|
+
# Assume adding a labware definition is fast and there are not many labware
|
|
340
|
+
# definitions, so we don't need to yield here.
|
|
341
|
+
self._protocol_engine.add_labware_definition(definition)
|
|
342
|
+
|
|
343
|
+
protocol = await anyio.to_thread.run_sync(
|
|
344
|
+
self._json_file_reader.read,
|
|
345
|
+
protocol_source,
|
|
346
|
+
)
|
|
347
|
+
|
|
348
|
+
commands = await anyio.to_thread.run_sync(
|
|
349
|
+
self._json_translator.translate_commands,
|
|
350
|
+
protocol,
|
|
351
|
+
)
|
|
352
|
+
|
|
353
|
+
# Add commands and liquids to the ProtocolEngine.
|
|
354
|
+
#
|
|
355
|
+
# We yield on every iteration so that loading large protocols doesn't block the
|
|
356
|
+
# event loop. With a 24-step 10k-command protocol (See RQA-443), adding all the
|
|
357
|
+
# commands can take 3 to 7 seconds.
|
|
358
|
+
#
|
|
359
|
+
# It wouldn't be safe to do this in a worker thread because each addition
|
|
360
|
+
# invokes the ProtocolEngine's ChangeNotifier machinery, which is not
|
|
361
|
+
# thread-safe.
|
|
362
|
+
liquids = await anyio.to_thread.run_sync(
|
|
363
|
+
self._json_translator.translate_liquids, protocol
|
|
364
|
+
)
|
|
365
|
+
for liquid in liquids:
|
|
366
|
+
self._protocol_engine.add_liquid(
|
|
367
|
+
id=liquid.id,
|
|
368
|
+
name=liquid.displayName,
|
|
369
|
+
description=liquid.description,
|
|
370
|
+
color=liquid.displayColor,
|
|
371
|
+
)
|
|
372
|
+
await asyncio_yield()
|
|
373
|
+
|
|
374
|
+
self._command_annotations = await anyio.to_thread.run_sync(
|
|
375
|
+
self._json_translator.translate_command_annotations,
|
|
376
|
+
protocol,
|
|
377
|
+
)
|
|
378
|
+
|
|
379
|
+
initial_home_command = pe_commands.HomeCreate(
|
|
380
|
+
params=pe_commands.HomeParams(axes=None)
|
|
381
|
+
)
|
|
382
|
+
# this command homes all axes, including pipette plugner and gripper jaw
|
|
383
|
+
self._protocol_engine.add_command(request=initial_home_command)
|
|
384
|
+
|
|
385
|
+
self._queued_commands = commands
|
|
386
|
+
|
|
387
|
+
self._task_queue.set_run_func(func=self._add_and_execute_commands)
|
|
388
|
+
|
|
389
|
+
async def run( # noqa: D102
|
|
390
|
+
self,
|
|
391
|
+
deck_configuration: DeckConfigurationType,
|
|
392
|
+
protocol_source: Optional[ProtocolSource] = None,
|
|
393
|
+
run_time_param_values: Optional[PrimitiveRunTimeParamValuesType] = None,
|
|
394
|
+
) -> RunResult:
|
|
395
|
+
# TODO(mc, 2022-01-11): move load to runner creation, remove from `run`
|
|
396
|
+
# currently `protocol_source` arg is only used by tests
|
|
397
|
+
if protocol_source:
|
|
398
|
+
await self.load(protocol_source)
|
|
399
|
+
|
|
400
|
+
self.play(deck_configuration=deck_configuration)
|
|
401
|
+
self._task_queue.start()
|
|
402
|
+
await self._task_queue.join()
|
|
403
|
+
|
|
404
|
+
run_data = self._protocol_engine.state_view.get_summary()
|
|
405
|
+
commands = self._protocol_engine.state_view.commands.get_all()
|
|
406
|
+
return RunResult(
|
|
407
|
+
commands=commands,
|
|
408
|
+
state_summary=run_data,
|
|
409
|
+
parameters=[],
|
|
410
|
+
command_annotations=self._command_annotations,
|
|
411
|
+
)
|
|
412
|
+
|
|
413
|
+
async def _add_and_execute_commands(self) -> None:
|
|
414
|
+
for command_request in self._queued_commands:
|
|
415
|
+
# todo(mm, 2024-07-05): This logic to handle the various command execution
|
|
416
|
+
# outcomes mirrors PAPI's ChildThreadTransport. Simplify or deduplicate it.
|
|
417
|
+
executed_command = (
|
|
418
|
+
await self._protocol_engine.add_and_execute_command_wait_for_recovery(
|
|
419
|
+
command_request
|
|
420
|
+
)
|
|
421
|
+
)
|
|
422
|
+
if executed_command.error is not None:
|
|
423
|
+
error_recovery_type = (
|
|
424
|
+
self._protocol_engine.state_view.commands.get_error_recovery_type(
|
|
425
|
+
executed_command.id
|
|
426
|
+
)
|
|
427
|
+
)
|
|
428
|
+
error_should_fail_run = (
|
|
429
|
+
error_recovery_type == ErrorRecoveryType.FAIL_RUN
|
|
430
|
+
)
|
|
431
|
+
if error_should_fail_run:
|
|
432
|
+
raise ProtocolCommandFailedError(
|
|
433
|
+
original_error=executed_command.error,
|
|
434
|
+
message=f"{executed_command.error.errorType}: {executed_command.error.detail}",
|
|
435
|
+
)
|
|
436
|
+
elif executed_command.status == CommandStatus.QUEUED:
|
|
437
|
+
# This can happen if another task stops the ProtocolEngine before
|
|
438
|
+
# the ProtocolEngine gets around to executing this command.
|
|
439
|
+
# See docs on add_and_execute_command_wait_for_recovery().
|
|
440
|
+
break
|
|
441
|
+
|
|
442
|
+
|
|
443
|
+
class LiveRunner(AbstractRunner):
|
|
444
|
+
"""Protocol runner implementation for live http protocols."""
|
|
445
|
+
|
|
446
|
+
def __init__(
|
|
447
|
+
self,
|
|
448
|
+
protocol_engine: ProtocolEngine,
|
|
449
|
+
hardware_api: HardwareControlAPI,
|
|
450
|
+
task_queue: Optional[TaskQueue] = None,
|
|
451
|
+
) -> None:
|
|
452
|
+
"""Initialize the LiveRunner with its dependencies."""
|
|
453
|
+
super().__init__(protocol_engine)
|
|
454
|
+
self._protocol_engine = protocol_engine
|
|
455
|
+
# TODO(mc, 2022-01-11): replace task queue with specific implementations
|
|
456
|
+
# of runner interface
|
|
457
|
+
self._hardware_api = hardware_api
|
|
458
|
+
self._task_queue = task_queue or TaskQueue()
|
|
459
|
+
self._task_queue.set_cleanup_func(func=protocol_engine.finish)
|
|
460
|
+
|
|
461
|
+
self._hardware_api.should_taskify_movement_execution(taskify=False)
|
|
462
|
+
|
|
463
|
+
# TODO(tz, 6-10-2024): explore moving this method into the constructor.
|
|
464
|
+
def prepare(self) -> None:
|
|
465
|
+
"""Set the task queue to wait until all commands are executed."""
|
|
466
|
+
self._task_queue.set_run_func(func=self._protocol_engine.wait_until_complete)
|
|
467
|
+
|
|
468
|
+
async def run( # noqa: D102
|
|
469
|
+
self,
|
|
470
|
+
deck_configuration: DeckConfigurationType,
|
|
471
|
+
protocol_source: Optional[ProtocolSource] = None,
|
|
472
|
+
run_time_param_values: Optional[PrimitiveRunTimeParamValuesType] = None,
|
|
473
|
+
) -> RunResult:
|
|
474
|
+
assert protocol_source is None
|
|
475
|
+
await self._hardware_api.home()
|
|
476
|
+
self.play(deck_configuration=deck_configuration)
|
|
477
|
+
self._task_queue.start()
|
|
478
|
+
await self._task_queue.join()
|
|
479
|
+
|
|
480
|
+
run_data = self._protocol_engine.state_view.get_summary()
|
|
481
|
+
commands = self._protocol_engine.state_view.commands.get_all()
|
|
482
|
+
return RunResult(
|
|
483
|
+
commands=commands,
|
|
484
|
+
state_summary=run_data,
|
|
485
|
+
parameters=[],
|
|
486
|
+
command_annotations=[],
|
|
487
|
+
)
|
|
488
|
+
|
|
489
|
+
|
|
490
|
+
AnyRunner = Union[PythonAndLegacyRunner, JsonRunner, LiveRunner]
|
|
491
|
+
|
|
492
|
+
|
|
493
|
+
def create_protocol_runner(
|
|
494
|
+
protocol_engine: ProtocolEngine,
|
|
495
|
+
hardware_api: HardwareControlAPI,
|
|
496
|
+
protocol_config: Union[JsonProtocolConfig, PythonProtocolConfig],
|
|
497
|
+
task_queue: Optional[TaskQueue] = None,
|
|
498
|
+
json_file_reader: Optional[JsonFileReader] = None,
|
|
499
|
+
json_translator: Optional[JsonTranslator] = None,
|
|
500
|
+
python_and_legacy_file_reader: Optional[PythonAndLegacyFileReader] = None,
|
|
501
|
+
protocol_context_creator: Optional[ProtocolContextCreator] = None,
|
|
502
|
+
python_protocol_executor: Optional[PythonProtocolExecutor] = None,
|
|
503
|
+
post_run_hardware_state: PostRunHardwareState = PostRunHardwareState.HOME_AND_STAY_ENGAGED,
|
|
504
|
+
drop_tips_after_run: bool = True,
|
|
505
|
+
) -> Union[JsonRunner, PythonAndLegacyRunner]:
|
|
506
|
+
"""Create a protocol runner."""
|
|
507
|
+
if (
|
|
508
|
+
isinstance(protocol_config, JsonProtocolConfig)
|
|
509
|
+
and protocol_config.schema_version >= LEGACY_JSON_SCHEMA_VERSION_CUTOFF
|
|
510
|
+
):
|
|
511
|
+
return JsonRunner(
|
|
512
|
+
protocol_engine=protocol_engine,
|
|
513
|
+
hardware_api=hardware_api,
|
|
514
|
+
json_file_reader=json_file_reader,
|
|
515
|
+
json_translator=json_translator,
|
|
516
|
+
task_queue=task_queue,
|
|
517
|
+
post_run_hardware_state=post_run_hardware_state,
|
|
518
|
+
drop_tips_after_run=drop_tips_after_run,
|
|
519
|
+
)
|
|
520
|
+
else:
|
|
521
|
+
return PythonAndLegacyRunner(
|
|
522
|
+
protocol_engine=protocol_engine,
|
|
523
|
+
hardware_api=hardware_api,
|
|
524
|
+
task_queue=task_queue,
|
|
525
|
+
python_and_legacy_file_reader=python_and_legacy_file_reader,
|
|
526
|
+
protocol_context_creator=protocol_context_creator,
|
|
527
|
+
python_protocol_executor=python_protocol_executor,
|
|
528
|
+
post_run_hardware_state=post_run_hardware_state,
|
|
529
|
+
drop_tips_after_run=drop_tips_after_run,
|
|
530
|
+
)
|