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,73 @@
|
|
|
1
|
+
"""Validation file for labware role and location checking functions."""
|
|
2
|
+
|
|
3
|
+
from opentrons_shared_data.labware.labware_definition import (
|
|
4
|
+
LabwareDefinition,
|
|
5
|
+
LabwareRole,
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def is_flex_trash(load_name: str) -> bool:
|
|
10
|
+
"""Check if a labware is a large trash."""
|
|
11
|
+
return load_name == "opentrons_1_trash_3200ml_fixed"
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def is_absorbance_reader_lid(load_name: str) -> bool:
|
|
15
|
+
"""Check if a labware is an absorbance reader lid."""
|
|
16
|
+
return load_name == "opentrons_flex_lid_absorbance_plate_reader_module"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def is_lid_stack(load_name: str) -> bool:
|
|
20
|
+
"""Check if a labware object is a system lid stack object."""
|
|
21
|
+
return load_name == "protocol_engine_lid_stack_object"
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def validate_definition_is_labware(definition: LabwareDefinition) -> bool:
|
|
25
|
+
"""Validate that one of the definition's allowed roles is `labware`.
|
|
26
|
+
|
|
27
|
+
An empty `allowedRoles` is equivalent to `labware` being the only allowed role.
|
|
28
|
+
"""
|
|
29
|
+
return not definition.allowedRoles or LabwareRole.labware in definition.allowedRoles
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def validate_definition_is_adapter(definition: LabwareDefinition) -> bool:
|
|
33
|
+
"""Validate that one of the definition's allowed roles is `adapter`."""
|
|
34
|
+
return LabwareRole.adapter in definition.allowedRoles
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def validate_definition_is_lid(definition: LabwareDefinition) -> bool:
|
|
38
|
+
"""Validate that one of the definition's allowed roles is `lid`."""
|
|
39
|
+
return LabwareRole.lid in definition.allowedRoles
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def validate_definition_is_system(definition: LabwareDefinition) -> bool:
|
|
43
|
+
"""Validate that one of the definition's allowed roles is `system`."""
|
|
44
|
+
return LabwareRole.system in definition.allowedRoles
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def validate_labware_can_be_stacked(
|
|
48
|
+
top_labware_definition: LabwareDefinition, below_labware_load_name: str
|
|
49
|
+
) -> bool:
|
|
50
|
+
"""Validate that the labware being loaded onto is in the above labware's stackingOffsetWithLabware definition."""
|
|
51
|
+
return (
|
|
52
|
+
below_labware_load_name in top_labware_definition.stackingOffsetWithLabware
|
|
53
|
+
or (
|
|
54
|
+
"default" in top_labware_definition.stackingOffsetWithLabware
|
|
55
|
+
and top_labware_definition.compatibleParentLabware is None
|
|
56
|
+
)
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def validate_labware_can_be_ondeck(definition: LabwareDefinition) -> bool:
|
|
61
|
+
"""Validate that the labware being loaded onto the deck can sit in a slot."""
|
|
62
|
+
return (
|
|
63
|
+
definition.parameters.quirks is None
|
|
64
|
+
or "stackingOnly" not in definition.parameters.quirks
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def validate_gripper_compatible(definition: LabwareDefinition) -> bool:
|
|
69
|
+
"""Validate that the labware definition does not have a quirk disallowing movement with gripper."""
|
|
70
|
+
return (
|
|
71
|
+
definition.parameters.quirks is None
|
|
72
|
+
or "gripperIncompatible" not in definition.parameters.quirks
|
|
73
|
+
)
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""Unique ID generation provider."""
|
|
2
|
+
from datetime import datetime, timezone
|
|
3
|
+
from uuid import uuid4
|
|
4
|
+
from typing import Optional
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class ModelUtils:
|
|
8
|
+
"""Common resource model utilities provider."""
|
|
9
|
+
|
|
10
|
+
@staticmethod
|
|
11
|
+
def generate_id(prefix: str = "") -> str:
|
|
12
|
+
"""Generate a unique identifier.
|
|
13
|
+
|
|
14
|
+
Uses UUIDv4 for safety in a multiprocessing environment.
|
|
15
|
+
|
|
16
|
+
Params:
|
|
17
|
+
prefix: Prepended to the UUIDv4.
|
|
18
|
+
"""
|
|
19
|
+
return prefix + str(uuid4())
|
|
20
|
+
|
|
21
|
+
@staticmethod
|
|
22
|
+
def ensure_id(maybe_id: Optional[str] = None) -> str:
|
|
23
|
+
"""Generate a unique identifier only if the given input is None.
|
|
24
|
+
|
|
25
|
+
Uses UUIDv4 for safety in a multiprocessing environment.
|
|
26
|
+
"""
|
|
27
|
+
return maybe_id if maybe_id is not None else ModelUtils.generate_id()
|
|
28
|
+
|
|
29
|
+
@staticmethod
|
|
30
|
+
def get_timestamp() -> datetime:
|
|
31
|
+
"""Get a timestamp of the current time."""
|
|
32
|
+
return datetime.now(tz=timezone.utc)
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"""Module data resource provider."""
|
|
2
|
+
from typing import Dict
|
|
3
|
+
from opentrons.hardware_control.modules.module_calibration import (
|
|
4
|
+
load_all_module_calibrations,
|
|
5
|
+
)
|
|
6
|
+
from opentrons_shared_data.module import load_definition
|
|
7
|
+
|
|
8
|
+
from opentrons.types import DeckSlotName
|
|
9
|
+
from ..types import (
|
|
10
|
+
ModuleModel,
|
|
11
|
+
ModuleDefinition,
|
|
12
|
+
ModuleOffsetVector,
|
|
13
|
+
ModuleOffsetData,
|
|
14
|
+
DeckSlotLocation,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class ModuleDataProvider:
|
|
19
|
+
"""Module data provider."""
|
|
20
|
+
|
|
21
|
+
@staticmethod
|
|
22
|
+
def get_definition(model: ModuleModel) -> ModuleDefinition:
|
|
23
|
+
"""Get the module definition."""
|
|
24
|
+
data = load_definition(model_or_loadname=model.value, version="3")
|
|
25
|
+
return ModuleDefinition.model_validate(data)
|
|
26
|
+
|
|
27
|
+
@staticmethod
|
|
28
|
+
def load_module_calibrations() -> Dict[str, ModuleOffsetData]:
|
|
29
|
+
"""Load the module calibration offsets."""
|
|
30
|
+
module_calibrations: Dict[str, ModuleOffsetData] = dict()
|
|
31
|
+
calibration_data = load_all_module_calibrations()
|
|
32
|
+
for calibration in calibration_data:
|
|
33
|
+
# NOTE module_id is really the module serial number, change this
|
|
34
|
+
module_calibrations[calibration.module_id] = ModuleOffsetData(
|
|
35
|
+
moduleOffsetVector=ModuleOffsetVector(
|
|
36
|
+
x=calibration.offset.x,
|
|
37
|
+
y=calibration.offset.y,
|
|
38
|
+
z=calibration.offset.z,
|
|
39
|
+
),
|
|
40
|
+
location=DeckSlotLocation(
|
|
41
|
+
slotName=DeckSlotName.from_primitive(calibration.slot),
|
|
42
|
+
),
|
|
43
|
+
)
|
|
44
|
+
return module_calibrations
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""Validation file for protocol engine commandsot."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
from opentrons.protocol_engine.errors import HardwareNotSupportedError
|
|
6
|
+
from opentrons.hardware_control.protocols.types import FlexRobotType
|
|
7
|
+
|
|
8
|
+
from opentrons.hardware_control import HardwareControlAPI, OT3HardwareControlAPI
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def ensure_ot3_hardware(
|
|
12
|
+
hardware_api: HardwareControlAPI,
|
|
13
|
+
error_msg: Optional[str] = None,
|
|
14
|
+
) -> OT3HardwareControlAPI:
|
|
15
|
+
"""Validate that the HardwareControlAPI is of OT-3 instance."""
|
|
16
|
+
if hardware_api.get_robot_type() == FlexRobotType:
|
|
17
|
+
return hardware_api # type: ignore
|
|
18
|
+
|
|
19
|
+
raise HardwareNotSupportedError(
|
|
20
|
+
error_msg or "This command is supported by OT-3 only."
|
|
21
|
+
)
|
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
"""Pipette config data providers."""
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
from typing import Dict, Optional, Sequence
|
|
4
|
+
import re
|
|
5
|
+
|
|
6
|
+
from opentrons_shared_data.pipette.types import PipetteName, PipetteModel
|
|
7
|
+
from opentrons_shared_data.pipette import (
|
|
8
|
+
pipette_load_name_conversions as pipette_load_name,
|
|
9
|
+
load_data as load_pipette_data,
|
|
10
|
+
types as pip_types,
|
|
11
|
+
pipette_definition,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
from opentrons.hardware_control.dev_types import PipetteDict
|
|
15
|
+
from opentrons.hardware_control.nozzle_manager import (
|
|
16
|
+
NozzleConfigurationManager,
|
|
17
|
+
NozzleMap,
|
|
18
|
+
)
|
|
19
|
+
from opentrons_shared_data.errors.exceptions import MissingConfigurationData
|
|
20
|
+
|
|
21
|
+
from ..errors.exceptions import InvalidLoadPipetteSpecsError
|
|
22
|
+
from ..types import FlowRates
|
|
23
|
+
from ...types import Point
|
|
24
|
+
|
|
25
|
+
_TIP_OVERLAP_VERSION_RE = re.compile(r"^v\d+$")
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def validate_and_default_tip_overlap_version(version_spec: Optional[str]) -> str:
|
|
29
|
+
"""Validate and sanitize tip overlap versions for later consumption.
|
|
30
|
+
|
|
31
|
+
Something that comes out of this function will be of the correct format, but a given kind of
|
|
32
|
+
pipette may not have this version of data.
|
|
33
|
+
"""
|
|
34
|
+
if version_spec is None:
|
|
35
|
+
return f"v{pipette_definition.TIP_OVERLAP_VERSION_MAXIMUM}"
|
|
36
|
+
valid = _TIP_OVERLAP_VERSION_RE.match(version_spec)
|
|
37
|
+
if not valid:
|
|
38
|
+
raise InvalidLoadPipetteSpecsError(
|
|
39
|
+
f"Tip overlap version specification {version_spec} is invalid."
|
|
40
|
+
)
|
|
41
|
+
try:
|
|
42
|
+
_ = int(version_spec[1:])
|
|
43
|
+
except ValueError:
|
|
44
|
+
raise InvalidLoadPipetteSpecsError(
|
|
45
|
+
f"Tip overlap version specification {version_spec} is invalid."
|
|
46
|
+
)
|
|
47
|
+
return version_spec
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@dataclass(frozen=True)
|
|
51
|
+
class LoadedStaticPipetteData:
|
|
52
|
+
"""Static pipette config data for load pipette."""
|
|
53
|
+
|
|
54
|
+
model: str
|
|
55
|
+
display_name: str
|
|
56
|
+
min_volume: float
|
|
57
|
+
max_volume: float
|
|
58
|
+
channels: int
|
|
59
|
+
home_position: float
|
|
60
|
+
nozzle_offset_z: float
|
|
61
|
+
flow_rates: FlowRates
|
|
62
|
+
tip_configuration_lookup_table: Dict[
|
|
63
|
+
float, pipette_definition.SupportedTipsDefinition
|
|
64
|
+
]
|
|
65
|
+
nominal_tip_overlap: Dict[str, float]
|
|
66
|
+
nozzle_map: NozzleMap
|
|
67
|
+
back_left_corner_offset: Point
|
|
68
|
+
front_right_corner_offset: Point
|
|
69
|
+
pipette_lld_settings: Optional[Dict[str, Dict[str, float]]]
|
|
70
|
+
plunger_positions: Dict[str, float]
|
|
71
|
+
shaft_ul_per_mm: float
|
|
72
|
+
available_sensors: pipette_definition.AvailableSensorDefinition
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class VirtualPipetteDataProvider:
|
|
76
|
+
"""Provide pipette data without requiring hardware control."""
|
|
77
|
+
|
|
78
|
+
def __init__(self) -> None:
|
|
79
|
+
"""Build a VirtualPipetteDataProvider."""
|
|
80
|
+
self._liquid_class_by_id: Dict[str, pip_types.LiquidClasses] = {}
|
|
81
|
+
self._nozzle_manager_layout_by_id: Dict[str, NozzleConfigurationManager] = {}
|
|
82
|
+
|
|
83
|
+
def configure_virtual_pipette_nozzle_layout(
|
|
84
|
+
self,
|
|
85
|
+
pipette_id: str,
|
|
86
|
+
pipette_model_string: str,
|
|
87
|
+
back_left_nozzle: Optional[str] = None,
|
|
88
|
+
front_right_nozzle: Optional[str] = None,
|
|
89
|
+
starting_nozzle: Optional[str] = None,
|
|
90
|
+
) -> None:
|
|
91
|
+
"""Emulate update_nozzle_configuration_for_mount."""
|
|
92
|
+
if pipette_id not in self._nozzle_manager_layout_by_id:
|
|
93
|
+
config = self._get_virtual_pipette_full_config_by_model_string(
|
|
94
|
+
pipette_model_string
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
valid_nozzle_maps = load_pipette_data.load_valid_nozzle_maps(
|
|
98
|
+
config.pipette_type,
|
|
99
|
+
config.channels,
|
|
100
|
+
config.version,
|
|
101
|
+
pip_types.PipetteOEMType.OT,
|
|
102
|
+
)
|
|
103
|
+
new_nozzle_manager = NozzleConfigurationManager.build_from_config(
|
|
104
|
+
config, valid_nozzle_maps
|
|
105
|
+
)
|
|
106
|
+
if back_left_nozzle and front_right_nozzle:
|
|
107
|
+
new_nozzle_manager.update_nozzle_configuration(
|
|
108
|
+
back_left_nozzle, front_right_nozzle, starting_nozzle
|
|
109
|
+
)
|
|
110
|
+
self._nozzle_manager_layout_by_id[pipette_id] = new_nozzle_manager
|
|
111
|
+
elif back_left_nozzle and front_right_nozzle:
|
|
112
|
+
# Need to make sure that we pass all the right nozzles here.
|
|
113
|
+
self._nozzle_manager_layout_by_id[pipette_id].update_nozzle_configuration(
|
|
114
|
+
back_left_nozzle, front_right_nozzle, starting_nozzle
|
|
115
|
+
)
|
|
116
|
+
else:
|
|
117
|
+
self._nozzle_manager_layout_by_id[
|
|
118
|
+
pipette_id
|
|
119
|
+
].reset_to_default_configuration()
|
|
120
|
+
|
|
121
|
+
def configure_virtual_pipette_for_volume(
|
|
122
|
+
self, pipette_id: str, volume: float, pipette_model_string: str
|
|
123
|
+
) -> None:
|
|
124
|
+
"""Emulate configure_for_volume with the same logic for changing modes."""
|
|
125
|
+
if pipette_id not in self._liquid_class_by_id:
|
|
126
|
+
self._liquid_class_by_id[pipette_id] = pip_types.LiquidClasses.default
|
|
127
|
+
pipette_model = pipette_load_name.convert_pipette_model(
|
|
128
|
+
PipetteModel(pipette_model_string)
|
|
129
|
+
)
|
|
130
|
+
config = load_pipette_data.load_definition(
|
|
131
|
+
pipette_model.pipette_type,
|
|
132
|
+
pipette_model.pipette_channels,
|
|
133
|
+
pipette_model.pipette_version,
|
|
134
|
+
pipette_model.oem_type,
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
liquid_class = pipette_definition.liquid_class_for_volume_between_default_and_defaultlowvolume(
|
|
138
|
+
volume, self._liquid_class_by_id[pipette_id], config.liquid_properties
|
|
139
|
+
)
|
|
140
|
+
self._liquid_class_by_id[pipette_id] = liquid_class
|
|
141
|
+
|
|
142
|
+
def get_nozzle_layout_for_pipette(self, pipette_id: str) -> NozzleMap:
|
|
143
|
+
"""Get the current nozzle layout stored for a virtual pipette."""
|
|
144
|
+
return self._nozzle_manager_layout_by_id[pipette_id].current_configuration
|
|
145
|
+
|
|
146
|
+
def get_virtual_pipette_static_config_by_model_string(
|
|
147
|
+
self, pipette_model_string: str, pipette_id: str, tip_overlap_version: str
|
|
148
|
+
) -> LoadedStaticPipetteData:
|
|
149
|
+
"""Get the config of a pipette when you know its model string (e.g. from state)."""
|
|
150
|
+
pipette_model = pipette_load_name.convert_pipette_model(
|
|
151
|
+
PipetteModel(pipette_model_string)
|
|
152
|
+
)
|
|
153
|
+
return self._get_virtual_pipette_static_config_by_model(
|
|
154
|
+
pipette_model, pipette_id, tip_overlap_version
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
def _get_virtual_pipette_full_config_by_model_string(
|
|
158
|
+
self, pipette_model_string: str
|
|
159
|
+
) -> pipette_definition.PipetteConfigurations:
|
|
160
|
+
"""Get the full pipette config from a model string."""
|
|
161
|
+
pipette_model = pipette_load_name.convert_pipette_model(
|
|
162
|
+
PipetteModel(pipette_model_string)
|
|
163
|
+
)
|
|
164
|
+
return load_pipette_data.load_definition(
|
|
165
|
+
pipette_model.pipette_type,
|
|
166
|
+
pipette_model.pipette_channels,
|
|
167
|
+
pipette_model.pipette_version,
|
|
168
|
+
pipette_model.oem_type,
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
def _get_virtual_pipette_static_config_by_model( # noqa: C901
|
|
172
|
+
self,
|
|
173
|
+
pipette_model: pipette_definition.PipetteModelVersionType,
|
|
174
|
+
pipette_id: str,
|
|
175
|
+
tip_overlap_version: str,
|
|
176
|
+
) -> LoadedStaticPipetteData:
|
|
177
|
+
if pipette_id not in self._liquid_class_by_id:
|
|
178
|
+
self._liquid_class_by_id[pipette_id] = pip_types.LiquidClasses.default
|
|
179
|
+
|
|
180
|
+
liquid_class = self._liquid_class_by_id[pipette_id]
|
|
181
|
+
config = load_pipette_data.load_definition(
|
|
182
|
+
pipette_model.pipette_type,
|
|
183
|
+
pipette_model.pipette_channels,
|
|
184
|
+
pipette_model.pipette_version,
|
|
185
|
+
pipette_model.oem_type,
|
|
186
|
+
)
|
|
187
|
+
try:
|
|
188
|
+
tip_type = pip_types.PipetteTipType(
|
|
189
|
+
config.liquid_properties[liquid_class].max_volume
|
|
190
|
+
)
|
|
191
|
+
except ValueError:
|
|
192
|
+
tip_type = pipette_definition.default_tip_for_liquid_class(
|
|
193
|
+
config.liquid_properties[liquid_class]
|
|
194
|
+
)
|
|
195
|
+
tip_configuration = config.liquid_properties[liquid_class].supported_tips[
|
|
196
|
+
tip_type
|
|
197
|
+
]
|
|
198
|
+
valid_nozzle_maps = load_pipette_data.load_valid_nozzle_maps(
|
|
199
|
+
pipette_model.pipette_type,
|
|
200
|
+
pipette_model.pipette_channels,
|
|
201
|
+
pipette_model.pipette_version,
|
|
202
|
+
pipette_model.oem_type,
|
|
203
|
+
)
|
|
204
|
+
if pipette_id not in self._nozzle_manager_layout_by_id:
|
|
205
|
+
nozzle_manager = NozzleConfigurationManager.build_from_config(
|
|
206
|
+
config, valid_nozzle_maps
|
|
207
|
+
)
|
|
208
|
+
else:
|
|
209
|
+
nozzle_manager = self._nozzle_manager_layout_by_id[pipette_id]
|
|
210
|
+
|
|
211
|
+
tip_overlap_dict_for_tip_type = None
|
|
212
|
+
for configuration in (
|
|
213
|
+
config.pick_up_tip_configurations.press_fit,
|
|
214
|
+
config.pick_up_tip_configurations.cam_action,
|
|
215
|
+
):
|
|
216
|
+
if not config:
|
|
217
|
+
continue
|
|
218
|
+
|
|
219
|
+
approved_map = None
|
|
220
|
+
for map_key in valid_nozzle_maps.maps.keys():
|
|
221
|
+
if valid_nozzle_maps.maps[map_key] == list(
|
|
222
|
+
nozzle_manager.current_configuration.map_store.keys()
|
|
223
|
+
):
|
|
224
|
+
approved_map = map_key
|
|
225
|
+
if approved_map is None:
|
|
226
|
+
raise MissingConfigurationData(
|
|
227
|
+
message="Virtual Static Nozzle Configuration does not match any approved map layout for the current pipette."
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
if configuration is not None:
|
|
231
|
+
try:
|
|
232
|
+
tip_overlap_dict_for_tip_type = (
|
|
233
|
+
get_latest_tip_overlap_before_version(
|
|
234
|
+
configuration.configuration_by_nozzle_map[
|
|
235
|
+
nozzle_manager.current_configuration.valid_map_key
|
|
236
|
+
][tip_type.name].versioned_tip_overlap_dictionary,
|
|
237
|
+
tip_overlap_version,
|
|
238
|
+
)
|
|
239
|
+
)
|
|
240
|
+
break
|
|
241
|
+
except KeyError:
|
|
242
|
+
try:
|
|
243
|
+
default = configuration.configuration_by_nozzle_map[
|
|
244
|
+
nozzle_manager.current_configuration.valid_map_key
|
|
245
|
+
].get("default")
|
|
246
|
+
if default is not None:
|
|
247
|
+
tip_overlap_dict_for_tip_type = (
|
|
248
|
+
get_latest_tip_overlap_before_version(
|
|
249
|
+
default.versioned_tip_overlap_dictionary,
|
|
250
|
+
tip_overlap_version,
|
|
251
|
+
)
|
|
252
|
+
)
|
|
253
|
+
break
|
|
254
|
+
except KeyError:
|
|
255
|
+
tip_overlap_dict_for_tip_type = None
|
|
256
|
+
if tip_overlap_dict_for_tip_type is None:
|
|
257
|
+
raise ValueError(
|
|
258
|
+
"Virtual Static Nozzle Configuration does not have a valid pick up tip configuration."
|
|
259
|
+
)
|
|
260
|
+
|
|
261
|
+
pip_back_left = config.pipette_bounding_box_offsets.back_left_corner
|
|
262
|
+
pip_front_right = config.pipette_bounding_box_offsets.front_right_corner
|
|
263
|
+
plunger_positions = config.plunger_positions_configurations[liquid_class]
|
|
264
|
+
return LoadedStaticPipetteData(
|
|
265
|
+
model=str(pipette_model),
|
|
266
|
+
display_name=config.display_name,
|
|
267
|
+
min_volume=config.liquid_properties[liquid_class].min_volume,
|
|
268
|
+
max_volume=config.liquid_properties[liquid_class].max_volume,
|
|
269
|
+
channels=config.channels,
|
|
270
|
+
home_position=config.mount_configurations.homePosition,
|
|
271
|
+
nozzle_offset_z=config.nozzle_offset[2],
|
|
272
|
+
tip_configuration_lookup_table={
|
|
273
|
+
k.value: v
|
|
274
|
+
for k, v in config.liquid_properties[
|
|
275
|
+
liquid_class
|
|
276
|
+
].supported_tips.items()
|
|
277
|
+
},
|
|
278
|
+
flow_rates=FlowRates(
|
|
279
|
+
default_blow_out=tip_configuration.default_blowout_flowrate.values_by_api_level,
|
|
280
|
+
default_aspirate=tip_configuration.default_aspirate_flowrate.values_by_api_level,
|
|
281
|
+
default_dispense=tip_configuration.default_dispense_flowrate.values_by_api_level,
|
|
282
|
+
),
|
|
283
|
+
nominal_tip_overlap=tip_overlap_dict_for_tip_type,
|
|
284
|
+
nozzle_map=nozzle_manager.current_configuration,
|
|
285
|
+
back_left_corner_offset=Point(
|
|
286
|
+
pip_back_left[0], pip_back_left[1], pip_back_left[2]
|
|
287
|
+
),
|
|
288
|
+
front_right_corner_offset=Point(
|
|
289
|
+
pip_front_right[0], pip_front_right[1], pip_front_right[2]
|
|
290
|
+
),
|
|
291
|
+
pipette_lld_settings=config.lld_settings,
|
|
292
|
+
plunger_positions={
|
|
293
|
+
"top": plunger_positions.top,
|
|
294
|
+
"bottom": plunger_positions.bottom,
|
|
295
|
+
"blow_out": plunger_positions.blow_out,
|
|
296
|
+
"drop_tip": plunger_positions.drop_tip,
|
|
297
|
+
},
|
|
298
|
+
shaft_ul_per_mm=config.shaft_ul_per_mm,
|
|
299
|
+
available_sensors=config.available_sensors
|
|
300
|
+
or pipette_definition.AvailableSensorDefinition(sensors=[]),
|
|
301
|
+
)
|
|
302
|
+
|
|
303
|
+
def get_virtual_pipette_static_config(
|
|
304
|
+
self, pipette_name: PipetteName, pipette_id: str, tip_overlap_version: str
|
|
305
|
+
) -> LoadedStaticPipetteData:
|
|
306
|
+
"""Get the config for a virtual pipette, given only the pipette name."""
|
|
307
|
+
pipette_model = pipette_load_name.convert_pipette_name(pipette_name)
|
|
308
|
+
return self._get_virtual_pipette_static_config_by_model(
|
|
309
|
+
pipette_model, pipette_id, tip_overlap_version
|
|
310
|
+
)
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
def get_pipette_static_config(
|
|
314
|
+
pipette_dict: PipetteDict, tip_overlap_version: str
|
|
315
|
+
) -> LoadedStaticPipetteData:
|
|
316
|
+
"""Get the config for a pipette, given the state/config object from the HW API."""
|
|
317
|
+
back_left_offset = pipette_dict["pipette_bounding_box_offsets"].back_left_corner
|
|
318
|
+
front_right_offset = pipette_dict["pipette_bounding_box_offsets"].front_right_corner
|
|
319
|
+
available_sensors = (
|
|
320
|
+
pipette_dict["available_sensors"]
|
|
321
|
+
if "available_sensors" in pipette_dict.keys()
|
|
322
|
+
else pipette_definition.AvailableSensorDefinition(sensors=[])
|
|
323
|
+
)
|
|
324
|
+
return LoadedStaticPipetteData(
|
|
325
|
+
model=pipette_dict["model"],
|
|
326
|
+
display_name=pipette_dict["display_name"],
|
|
327
|
+
min_volume=pipette_dict["min_volume"],
|
|
328
|
+
max_volume=pipette_dict["max_volume"],
|
|
329
|
+
channels=pipette_dict["channels"],
|
|
330
|
+
flow_rates=FlowRates(
|
|
331
|
+
default_blow_out=pipette_dict["default_blow_out_flow_rates"],
|
|
332
|
+
default_aspirate=pipette_dict["default_aspirate_flow_rates"],
|
|
333
|
+
default_dispense=pipette_dict["default_dispense_flow_rates"],
|
|
334
|
+
),
|
|
335
|
+
tip_configuration_lookup_table={
|
|
336
|
+
k.value: v for k, v in pipette_dict["supported_tips"].items()
|
|
337
|
+
},
|
|
338
|
+
nominal_tip_overlap=get_latest_tip_overlap_before_version(
|
|
339
|
+
pipette_dict["versioned_tip_overlap"], tip_overlap_version
|
|
340
|
+
),
|
|
341
|
+
# TODO(mc, 2023-02-28): these two values are not present in PipetteDict
|
|
342
|
+
# https://opentrons.atlassian.net/browse/RCORE-655
|
|
343
|
+
home_position=0,
|
|
344
|
+
nozzle_offset_z=0,
|
|
345
|
+
nozzle_map=pipette_dict["current_nozzle_map"],
|
|
346
|
+
back_left_corner_offset=Point(
|
|
347
|
+
back_left_offset[0], back_left_offset[1], back_left_offset[2]
|
|
348
|
+
),
|
|
349
|
+
front_right_corner_offset=Point(
|
|
350
|
+
front_right_offset[0], front_right_offset[1], front_right_offset[2]
|
|
351
|
+
),
|
|
352
|
+
pipette_lld_settings=pipette_dict["lld_settings"],
|
|
353
|
+
plunger_positions=pipette_dict["plunger_positions"],
|
|
354
|
+
shaft_ul_per_mm=pipette_dict["shaft_ul_per_mm"],
|
|
355
|
+
available_sensors=available_sensors,
|
|
356
|
+
)
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
def get_latest_tip_overlap_before_version(
|
|
360
|
+
overlap: Dict[str, Dict[str, float]], version: str
|
|
361
|
+
) -> Dict[str, float]:
|
|
362
|
+
"""Get the latest tip overlap definitions that are equal or older than the version."""
|
|
363
|
+
# TODO: make this less awful
|
|
364
|
+
def _numeric(versionstr: str) -> int:
|
|
365
|
+
return int(versionstr[1:])
|
|
366
|
+
|
|
367
|
+
def _latest(versions: Sequence[int], target: int) -> int:
|
|
368
|
+
last = 0
|
|
369
|
+
for version in versions:
|
|
370
|
+
if version > target:
|
|
371
|
+
return last
|
|
372
|
+
last = version
|
|
373
|
+
return last
|
|
374
|
+
|
|
375
|
+
numeric_target = _numeric(version)
|
|
376
|
+
numeric_versions = sorted([_numeric(k) for k in overlap.keys()])
|
|
377
|
+
found_numeric_version = _latest(numeric_versions, numeric_target)
|
|
378
|
+
found_version = f"v{found_numeric_version}"
|
|
379
|
+
return overlap[found_version]
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"""Convert deck slots into the preferred style for a robot.
|
|
2
|
+
|
|
3
|
+
The deck slots on an OT-2 are labeled like "1", "2", ..., and on an OT-3 they're labeled like
|
|
4
|
+
"D1," "D2", ....
|
|
5
|
+
|
|
6
|
+
When Protocol Engine takes a deck slot as input, we generally want it to accept either style
|
|
7
|
+
of label. This helps make protocols more portable across robot types.
|
|
8
|
+
|
|
9
|
+
But, Protocol Engine should then immediately convert it to the "correct" style for the robot that
|
|
10
|
+
it's controlling or simulating. This makes it simpler to consume the robot's HTTP API,
|
|
11
|
+
and it makes it easier for us to reason about Protocol Engine's internal state.
|
|
12
|
+
|
|
13
|
+
This module does that conversion, for any Protocol Engine input that contains a reference to a
|
|
14
|
+
deck slot.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from typing import Any, Callable, Dict, Type
|
|
18
|
+
|
|
19
|
+
from opentrons_shared_data.robot.types import RobotType
|
|
20
|
+
|
|
21
|
+
from . import commands
|
|
22
|
+
from .types import (
|
|
23
|
+
OFF_DECK_LOCATION,
|
|
24
|
+
SYSTEM_LOCATION,
|
|
25
|
+
DeckSlotLocation,
|
|
26
|
+
LoadableLabwareLocation,
|
|
27
|
+
AddressableAreaLocation,
|
|
28
|
+
ModuleLocation,
|
|
29
|
+
OnLabwareLocation,
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def standardize_command(
|
|
34
|
+
original: commands.CommandCreate, robot_type: RobotType
|
|
35
|
+
) -> commands.CommandCreate:
|
|
36
|
+
"""Convert any deck slots in the given `CommandCreate` to match the given robot type."""
|
|
37
|
+
try:
|
|
38
|
+
standardize = _standardize_command_functions[type(original)]
|
|
39
|
+
except KeyError:
|
|
40
|
+
return original
|
|
41
|
+
else:
|
|
42
|
+
return standardize(original, robot_type)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
# Command-specific standardization:
|
|
46
|
+
#
|
|
47
|
+
# Our use of .copy(update=...) in these implementations, instead of .construct(...), is a tradeoff.
|
|
48
|
+
# .construct() would give us better type-checking for the fields that we set,
|
|
49
|
+
# but .copy(update=...) avoids the hazard of forgetting to set fields that have defaults.
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def _standardize_load_labware(
|
|
53
|
+
original: commands.LoadLabwareCreate, robot_type: RobotType
|
|
54
|
+
) -> commands.LoadLabwareCreate:
|
|
55
|
+
params = original.params.model_copy(
|
|
56
|
+
update={
|
|
57
|
+
"location": _standardize_labware_location(
|
|
58
|
+
original.params.location, robot_type
|
|
59
|
+
)
|
|
60
|
+
}
|
|
61
|
+
)
|
|
62
|
+
return original.model_copy(update={"params": params})
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def _standardize_load_module(
|
|
66
|
+
original: commands.LoadModuleCreate, robot_type: RobotType
|
|
67
|
+
) -> commands.LoadModuleCreate:
|
|
68
|
+
params = original.params.model_copy(
|
|
69
|
+
update={
|
|
70
|
+
"location": _standardize_deck_slot_location(
|
|
71
|
+
original.params.location, robot_type
|
|
72
|
+
)
|
|
73
|
+
}
|
|
74
|
+
)
|
|
75
|
+
return original.model_copy(update={"params": params})
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def _standardize_move_labware(
|
|
79
|
+
original: commands.MoveLabwareCreate, robot_type: RobotType
|
|
80
|
+
) -> commands.MoveLabwareCreate:
|
|
81
|
+
params = original.params.model_copy(
|
|
82
|
+
update={
|
|
83
|
+
"newLocation": _standardize_labware_location(
|
|
84
|
+
original.params.newLocation, robot_type
|
|
85
|
+
)
|
|
86
|
+
}
|
|
87
|
+
)
|
|
88
|
+
return original.model_copy(update={"params": params})
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
_standardize_command_functions: Dict[
|
|
92
|
+
Type[commands.CommandCreate], Callable[[Any, RobotType], commands.CommandCreate]
|
|
93
|
+
] = {
|
|
94
|
+
commands.LoadLabwareCreate: _standardize_load_labware,
|
|
95
|
+
commands.LoadModuleCreate: _standardize_load_module,
|
|
96
|
+
commands.MoveLabwareCreate: _standardize_move_labware,
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
# Helpers:
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def _standardize_labware_location(
|
|
104
|
+
original: LoadableLabwareLocation, robot_type: RobotType
|
|
105
|
+
) -> LoadableLabwareLocation:
|
|
106
|
+
if isinstance(original, DeckSlotLocation):
|
|
107
|
+
return _standardize_deck_slot_location(original, robot_type)
|
|
108
|
+
elif (
|
|
109
|
+
isinstance(
|
|
110
|
+
original,
|
|
111
|
+
(
|
|
112
|
+
ModuleLocation,
|
|
113
|
+
OnLabwareLocation,
|
|
114
|
+
AddressableAreaLocation,
|
|
115
|
+
),
|
|
116
|
+
)
|
|
117
|
+
or original == OFF_DECK_LOCATION
|
|
118
|
+
or original == SYSTEM_LOCATION
|
|
119
|
+
):
|
|
120
|
+
return original
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def _standardize_deck_slot_location(
|
|
124
|
+
original: DeckSlotLocation, robot_type: RobotType
|
|
125
|
+
) -> DeckSlotLocation:
|
|
126
|
+
return original.model_copy(
|
|
127
|
+
update={"slotName": original.slotName.to_equivalent_for_robot_type(robot_type)}
|
|
128
|
+
)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Protocol engine state module."""
|