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,819 @@
|
|
|
1
|
+
"""Equipment command side-effect logic."""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import Optional, overload, List
|
|
5
|
+
|
|
6
|
+
from opentrons_shared_data.labware.labware_definition import LabwareDefinition
|
|
7
|
+
from opentrons_shared_data.pipette.types import PipetteNameType
|
|
8
|
+
|
|
9
|
+
from opentrons.calibration_storage.helpers import uri_from_details
|
|
10
|
+
from opentrons.types import MountType
|
|
11
|
+
from opentrons.hardware_control import HardwareControlAPI
|
|
12
|
+
from opentrons.hardware_control.modules import (
|
|
13
|
+
AbstractModule,
|
|
14
|
+
MagDeck,
|
|
15
|
+
HeaterShaker,
|
|
16
|
+
TempDeck,
|
|
17
|
+
Thermocycler,
|
|
18
|
+
AbsorbanceReader,
|
|
19
|
+
FlexStacker,
|
|
20
|
+
)
|
|
21
|
+
from opentrons.hardware_control.nozzle_manager import NozzleMap
|
|
22
|
+
from opentrons.protocol_engine.state.module_substates import (
|
|
23
|
+
MagneticModuleId,
|
|
24
|
+
HeaterShakerModuleId,
|
|
25
|
+
TemperatureModuleId,
|
|
26
|
+
ThermocyclerModuleId,
|
|
27
|
+
AbsorbanceReaderId,
|
|
28
|
+
FlexStackerId,
|
|
29
|
+
)
|
|
30
|
+
from ..errors import (
|
|
31
|
+
FailedToLoadPipetteError,
|
|
32
|
+
LabwareDefinitionDoesNotExistError,
|
|
33
|
+
ModuleNotAttachedError,
|
|
34
|
+
)
|
|
35
|
+
from ..resources import (
|
|
36
|
+
LabwareDataProvider,
|
|
37
|
+
ModuleDataProvider,
|
|
38
|
+
ModelUtils,
|
|
39
|
+
pipette_data_provider,
|
|
40
|
+
)
|
|
41
|
+
from ..state.state import StateStore
|
|
42
|
+
from ..state.modules import HardwareModule
|
|
43
|
+
from ..types import (
|
|
44
|
+
LabwareLocation,
|
|
45
|
+
DeckSlotLocation,
|
|
46
|
+
LabwareOffset,
|
|
47
|
+
ModuleModel,
|
|
48
|
+
ModuleDefinition,
|
|
49
|
+
AddressableAreaLocation,
|
|
50
|
+
LoadedLabware,
|
|
51
|
+
OnLabwareLocation,
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@dataclass(frozen=True)
|
|
56
|
+
class LoadedLabwareData:
|
|
57
|
+
"""The result of a load labware procedure."""
|
|
58
|
+
|
|
59
|
+
labware_id: str
|
|
60
|
+
definition: LabwareDefinition
|
|
61
|
+
offsetId: Optional[str]
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@dataclass(frozen=True)
|
|
65
|
+
class ReloadedLabwareData:
|
|
66
|
+
"""The result of a reload labware procedure."""
|
|
67
|
+
|
|
68
|
+
location: LabwareLocation
|
|
69
|
+
offsetId: Optional[str]
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
@dataclass(frozen=True)
|
|
73
|
+
class LoadedPipetteData:
|
|
74
|
+
"""The result of a load pipette procedure."""
|
|
75
|
+
|
|
76
|
+
pipette_id: str
|
|
77
|
+
serial_number: str
|
|
78
|
+
static_config: pipette_data_provider.LoadedStaticPipetteData
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
@dataclass(frozen=True)
|
|
82
|
+
class LoadedModuleData:
|
|
83
|
+
"""The result of a load module procedure."""
|
|
84
|
+
|
|
85
|
+
module_id: str
|
|
86
|
+
serial_number: Optional[str]
|
|
87
|
+
definition: ModuleDefinition
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
@dataclass(frozen=True)
|
|
91
|
+
class LoadedConfigureForVolumeData:
|
|
92
|
+
"""The result of a load liquid class procedure."""
|
|
93
|
+
|
|
94
|
+
pipette_id: str
|
|
95
|
+
serial_number: str
|
|
96
|
+
volume: float
|
|
97
|
+
static_config: pipette_data_provider.LoadedStaticPipetteData
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
@dataclass(frozen=True)
|
|
101
|
+
class LoadedLabwarePoolData:
|
|
102
|
+
"""The result of loading a labware pool with details for batch loads and location sequencing."""
|
|
103
|
+
|
|
104
|
+
primary_labware: LoadedLabware
|
|
105
|
+
adapter_labware: Optional[LoadedLabware] = None
|
|
106
|
+
lid_labware: Optional[LoadedLabware] = None
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
class EquipmentHandler:
|
|
110
|
+
"""Implementation logic for labware, pipette, and module loading."""
|
|
111
|
+
|
|
112
|
+
_hardware_api: HardwareControlAPI
|
|
113
|
+
_state_store: StateStore
|
|
114
|
+
_labware_data_provider: LabwareDataProvider
|
|
115
|
+
_module_data_provider: ModuleDataProvider
|
|
116
|
+
_model_utils: ModelUtils
|
|
117
|
+
_virtual_pipette_data_provider: pipette_data_provider.VirtualPipetteDataProvider
|
|
118
|
+
|
|
119
|
+
def __init__(
|
|
120
|
+
self,
|
|
121
|
+
hardware_api: HardwareControlAPI,
|
|
122
|
+
state_store: StateStore,
|
|
123
|
+
labware_data_provider: Optional[LabwareDataProvider] = None,
|
|
124
|
+
module_data_provider: Optional[ModuleDataProvider] = None,
|
|
125
|
+
model_utils: Optional[ModelUtils] = None,
|
|
126
|
+
virtual_pipette_data_provider: Optional[
|
|
127
|
+
pipette_data_provider.VirtualPipetteDataProvider
|
|
128
|
+
] = None,
|
|
129
|
+
) -> None:
|
|
130
|
+
"""Initialize an EquipmentHandler instance."""
|
|
131
|
+
self._hardware_api = hardware_api
|
|
132
|
+
self._state_store = state_store
|
|
133
|
+
self._labware_data_provider = labware_data_provider or LabwareDataProvider()
|
|
134
|
+
self._module_data_provider = module_data_provider or ModuleDataProvider()
|
|
135
|
+
self._model_utils = model_utils or ModelUtils()
|
|
136
|
+
self._virtual_pipette_data_provider = (
|
|
137
|
+
virtual_pipette_data_provider
|
|
138
|
+
or pipette_data_provider.VirtualPipetteDataProvider()
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
async def load_definition_for_details(
|
|
142
|
+
self, load_name: str, namespace: str, version: int
|
|
143
|
+
) -> tuple[LabwareDefinition, str]:
|
|
144
|
+
"""Load the definition for a labware from the parameters passed for it to a command.
|
|
145
|
+
|
|
146
|
+
Args:
|
|
147
|
+
load_name: The labware's load name.
|
|
148
|
+
namespace: The labware's namespace.
|
|
149
|
+
version: The labware's version.
|
|
150
|
+
|
|
151
|
+
Returns:
|
|
152
|
+
A tuple of the loaded LabwareDefinition object and its definition URI.
|
|
153
|
+
"""
|
|
154
|
+
definition_uri = uri_from_details(
|
|
155
|
+
load_name=load_name,
|
|
156
|
+
namespace=namespace,
|
|
157
|
+
version=version,
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
try:
|
|
161
|
+
# Try to use existing definition in state.
|
|
162
|
+
return (
|
|
163
|
+
self._state_store.labware.get_definition_by_uri(definition_uri),
|
|
164
|
+
definition_uri,
|
|
165
|
+
)
|
|
166
|
+
except LabwareDefinitionDoesNotExistError:
|
|
167
|
+
definition = await self._labware_data_provider.get_labware_definition(
|
|
168
|
+
load_name=load_name,
|
|
169
|
+
namespace=namespace,
|
|
170
|
+
version=version,
|
|
171
|
+
)
|
|
172
|
+
return definition, definition_uri
|
|
173
|
+
|
|
174
|
+
async def load_labware_from_definition(
|
|
175
|
+
self,
|
|
176
|
+
definition: LabwareDefinition,
|
|
177
|
+
location: LabwareLocation,
|
|
178
|
+
labware_id: Optional[str],
|
|
179
|
+
labware_pending_load: dict[str, LoadedLabware] | None = None,
|
|
180
|
+
) -> LoadedLabwareData:
|
|
181
|
+
"""Load labware from already-found definition."""
|
|
182
|
+
definition_uri = uri_from_details(
|
|
183
|
+
load_name=definition.parameters.loadName,
|
|
184
|
+
namespace=definition.namespace,
|
|
185
|
+
version=definition.version,
|
|
186
|
+
)
|
|
187
|
+
return await self._load_labware_from_def_and_uri(
|
|
188
|
+
definition, definition_uri, location, labware_id, labware_pending_load
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
async def _load_labware_from_def_and_uri(
|
|
192
|
+
self,
|
|
193
|
+
definition: LabwareDefinition,
|
|
194
|
+
definition_uri: str,
|
|
195
|
+
location: LabwareLocation,
|
|
196
|
+
labware_id: str | None,
|
|
197
|
+
labware_pending_load: dict[str, LoadedLabware] | None,
|
|
198
|
+
) -> LoadedLabwareData:
|
|
199
|
+
labware_id = (
|
|
200
|
+
labware_id if labware_id is not None else self._model_utils.generate_id()
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
# Allow propagation of ModuleNotLoadedError.
|
|
204
|
+
offset_id = self.find_applicable_labware_offset_id(
|
|
205
|
+
labware_definition_uri=definition_uri,
|
|
206
|
+
labware_location=location,
|
|
207
|
+
labware_pending_load=labware_pending_load,
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
return LoadedLabwareData(
|
|
211
|
+
labware_id=labware_id, definition=definition, offsetId=offset_id
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
async def load_labware_pool_from_definitions(
|
|
215
|
+
self,
|
|
216
|
+
pool_primary_definition: LabwareDefinition,
|
|
217
|
+
pool_adapter_definition: Optional[LabwareDefinition],
|
|
218
|
+
pool_lid_definition: Optional[LabwareDefinition],
|
|
219
|
+
location: LabwareLocation,
|
|
220
|
+
primary_id: Optional[str],
|
|
221
|
+
adapter_id: Optional[str],
|
|
222
|
+
lid_id: Optional[str],
|
|
223
|
+
) -> LoadedLabwarePoolData:
|
|
224
|
+
"""Load a pool of labware from already-found definitions."""
|
|
225
|
+
adapter_labware: LoadedLabware | None = None
|
|
226
|
+
lid_labware: LoadedLabware | None = None
|
|
227
|
+
adapter_lw = None
|
|
228
|
+
labware_by_id: dict[str, LoadedLabware] = {}
|
|
229
|
+
if pool_adapter_definition is not None:
|
|
230
|
+
adapter_location = location
|
|
231
|
+
adapter_lw = await self.load_labware_from_definition(
|
|
232
|
+
definition=pool_adapter_definition,
|
|
233
|
+
location=adapter_location,
|
|
234
|
+
labware_id=adapter_id,
|
|
235
|
+
labware_pending_load=labware_by_id,
|
|
236
|
+
)
|
|
237
|
+
adapter_uri = str(
|
|
238
|
+
uri_from_details(
|
|
239
|
+
namespace=adapter_lw.definition.namespace,
|
|
240
|
+
load_name=adapter_lw.definition.parameters.loadName,
|
|
241
|
+
version=adapter_lw.definition.version,
|
|
242
|
+
)
|
|
243
|
+
)
|
|
244
|
+
adapter_labware = LoadedLabware.model_construct(
|
|
245
|
+
id=adapter_lw.labware_id,
|
|
246
|
+
location=adapter_location,
|
|
247
|
+
loadName=adapter_lw.definition.parameters.loadName,
|
|
248
|
+
definitionUri=adapter_uri,
|
|
249
|
+
offsetId=None,
|
|
250
|
+
)
|
|
251
|
+
labware_by_id[adapter_labware.id] = adapter_labware
|
|
252
|
+
|
|
253
|
+
primary_location: LabwareLocation = (
|
|
254
|
+
location
|
|
255
|
+
if adapter_lw is None
|
|
256
|
+
else OnLabwareLocation(labwareId=adapter_lw.labware_id)
|
|
257
|
+
)
|
|
258
|
+
loaded_labware = await self.load_labware_from_definition(
|
|
259
|
+
definition=pool_primary_definition,
|
|
260
|
+
location=primary_location,
|
|
261
|
+
labware_id=primary_id,
|
|
262
|
+
labware_pending_load={lw_id: lw for lw_id, lw in labware_by_id.items()},
|
|
263
|
+
)
|
|
264
|
+
primary_uri = str(
|
|
265
|
+
uri_from_details(
|
|
266
|
+
namespace=loaded_labware.definition.namespace,
|
|
267
|
+
load_name=loaded_labware.definition.parameters.loadName,
|
|
268
|
+
version=loaded_labware.definition.version,
|
|
269
|
+
)
|
|
270
|
+
)
|
|
271
|
+
primary_labware = LoadedLabware.model_construct(
|
|
272
|
+
id=loaded_labware.labware_id,
|
|
273
|
+
location=primary_location,
|
|
274
|
+
loadName=loaded_labware.definition.parameters.loadName,
|
|
275
|
+
definitionUri=primary_uri,
|
|
276
|
+
)
|
|
277
|
+
labware_by_id[primary_labware.id] = primary_labware
|
|
278
|
+
|
|
279
|
+
# If there is a lid load it
|
|
280
|
+
if pool_lid_definition is not None:
|
|
281
|
+
lid_location = OnLabwareLocation(labwareId=loaded_labware.labware_id)
|
|
282
|
+
lid_lw = await self.load_labware_from_definition(
|
|
283
|
+
definition=pool_lid_definition,
|
|
284
|
+
location=lid_location,
|
|
285
|
+
labware_id=lid_id,
|
|
286
|
+
labware_pending_load={lw_id: lw for lw_id, lw in labware_by_id.items()},
|
|
287
|
+
)
|
|
288
|
+
lid_uri = str(
|
|
289
|
+
uri_from_details(
|
|
290
|
+
namespace=lid_lw.definition.namespace,
|
|
291
|
+
load_name=lid_lw.definition.parameters.loadName,
|
|
292
|
+
version=lid_lw.definition.version,
|
|
293
|
+
)
|
|
294
|
+
)
|
|
295
|
+
lid_labware = LoadedLabware.model_construct(
|
|
296
|
+
id=lid_lw.labware_id,
|
|
297
|
+
location=lid_location,
|
|
298
|
+
loadName=lid_lw.definition.parameters.loadName,
|
|
299
|
+
definitionUri=lid_uri,
|
|
300
|
+
offsetId=None,
|
|
301
|
+
)
|
|
302
|
+
labware_by_id[lid_labware.id] = lid_labware
|
|
303
|
+
return LoadedLabwarePoolData(
|
|
304
|
+
primary_labware=primary_labware,
|
|
305
|
+
adapter_labware=adapter_labware,
|
|
306
|
+
lid_labware=lid_labware,
|
|
307
|
+
)
|
|
308
|
+
|
|
309
|
+
async def load_labware(
|
|
310
|
+
self,
|
|
311
|
+
load_name: str,
|
|
312
|
+
namespace: str,
|
|
313
|
+
version: int,
|
|
314
|
+
location: LabwareLocation,
|
|
315
|
+
labware_id: Optional[str],
|
|
316
|
+
) -> LoadedLabwareData:
|
|
317
|
+
"""Load labware by assigning an identifier and pulling required data.
|
|
318
|
+
|
|
319
|
+
Args:
|
|
320
|
+
load_name: The labware's load name.
|
|
321
|
+
namespace: The labware's namespace.
|
|
322
|
+
version: The labware's version.
|
|
323
|
+
location: The deck location at which labware is placed.
|
|
324
|
+
labware_id: An optional identifier to assign the labware. If None, an
|
|
325
|
+
identifier will be generated.
|
|
326
|
+
|
|
327
|
+
Raises:
|
|
328
|
+
ModuleNotLoadedError: If `location` references a module ID
|
|
329
|
+
that doesn't point to a valid loaded module.
|
|
330
|
+
|
|
331
|
+
Returns:
|
|
332
|
+
A LoadedLabwareData object.
|
|
333
|
+
"""
|
|
334
|
+
definition, definition_uri = await self.load_definition_for_details(
|
|
335
|
+
load_name, namespace, version
|
|
336
|
+
)
|
|
337
|
+
return await self._load_labware_from_def_and_uri(
|
|
338
|
+
definition, definition_uri, location, labware_id, None
|
|
339
|
+
)
|
|
340
|
+
|
|
341
|
+
async def reload_labware(self, labware_id: str) -> ReloadedLabwareData:
|
|
342
|
+
"""Reload an already-loaded labware. This cannot change the labware location.
|
|
343
|
+
|
|
344
|
+
Args:
|
|
345
|
+
labware_id: The ID of the already-loaded labware.
|
|
346
|
+
|
|
347
|
+
Raises:
|
|
348
|
+
LabwareNotLoadedError: If `labware_id` does not reference a loaded labware.
|
|
349
|
+
|
|
350
|
+
"""
|
|
351
|
+
location = self._state_store.labware.get_location(labware_id)
|
|
352
|
+
definition_uri = self._state_store.labware.get_definition_uri(labware_id)
|
|
353
|
+
offset_id = self.find_applicable_labware_offset_id(
|
|
354
|
+
labware_definition_uri=definition_uri,
|
|
355
|
+
labware_location=location,
|
|
356
|
+
)
|
|
357
|
+
|
|
358
|
+
return ReloadedLabwareData(location=location, offsetId=offset_id)
|
|
359
|
+
|
|
360
|
+
async def load_pipette(
|
|
361
|
+
self,
|
|
362
|
+
pipette_name: PipetteNameType,
|
|
363
|
+
mount: MountType,
|
|
364
|
+
pipette_id: Optional[str],
|
|
365
|
+
tip_overlap_version: Optional[str],
|
|
366
|
+
) -> LoadedPipetteData:
|
|
367
|
+
"""Ensure the requested pipette is attached.
|
|
368
|
+
|
|
369
|
+
Args:
|
|
370
|
+
pipette_name: The pipette name.
|
|
371
|
+
mount: The mount on which pipette must be attached.
|
|
372
|
+
pipette_id: An optional identifier to assign the pipette. If None, an
|
|
373
|
+
identifier will be generated.
|
|
374
|
+
tip_overlap_version: An optional specifier for the version of tip overlap data to use.
|
|
375
|
+
If None, defaults to v0. Does not need to be format checked - this function does it.
|
|
376
|
+
|
|
377
|
+
Returns:
|
|
378
|
+
A LoadedPipetteData object.
|
|
379
|
+
"""
|
|
380
|
+
# TODO (spp, 2023-05-10): either raise error if using MountType.EXTENSION in
|
|
381
|
+
# load pipettes command, or change the mount type used to be a restricted
|
|
382
|
+
# PipetteMountType which has only pipette mounts and not the extension mount.
|
|
383
|
+
use_virtual_pipettes = self._state_store.config.use_virtual_pipettes
|
|
384
|
+
|
|
385
|
+
pipette_name_value = (
|
|
386
|
+
pipette_name.value
|
|
387
|
+
if isinstance(pipette_name, PipetteNameType)
|
|
388
|
+
else pipette_name
|
|
389
|
+
)
|
|
390
|
+
sanitized_overlap_version = (
|
|
391
|
+
pipette_data_provider.validate_and_default_tip_overlap_version(
|
|
392
|
+
tip_overlap_version
|
|
393
|
+
)
|
|
394
|
+
)
|
|
395
|
+
|
|
396
|
+
pipette_id = pipette_id or self._model_utils.generate_id()
|
|
397
|
+
if not use_virtual_pipettes:
|
|
398
|
+
cache_request = {mount.to_hw_mount(): pipette_name_value}
|
|
399
|
+
|
|
400
|
+
# TODO(mc, 2022-12-09): putting the other pipette in the cache request
|
|
401
|
+
# is only to support protocol analysis, since the hardware simulator
|
|
402
|
+
# does not cache requested virtual instruments. Remove per
|
|
403
|
+
# https://opentrons.atlassian.net/browse/RLIQ-258
|
|
404
|
+
other_mount = mount.other_mount()
|
|
405
|
+
other_pipette = self._state_store.pipettes.get_by_mount(other_mount)
|
|
406
|
+
if other_pipette is not None:
|
|
407
|
+
cache_request[other_mount.to_hw_mount()] = (
|
|
408
|
+
other_pipette.pipetteName.value
|
|
409
|
+
if isinstance(other_pipette.pipetteName, PipetteNameType)
|
|
410
|
+
else other_pipette.pipetteName
|
|
411
|
+
)
|
|
412
|
+
|
|
413
|
+
# TODO(mc, 2020-10-18): calling `cache_instruments` mirrors the
|
|
414
|
+
# behavior of protocol_context.load_instrument, and is used here as a
|
|
415
|
+
# pipette existence check
|
|
416
|
+
try:
|
|
417
|
+
await self._hardware_api.cache_instruments(cache_request)
|
|
418
|
+
except RuntimeError as e:
|
|
419
|
+
raise FailedToLoadPipetteError(str(e)) from e
|
|
420
|
+
|
|
421
|
+
pipette_dict = self._hardware_api.get_attached_instrument(
|
|
422
|
+
mount.to_hw_mount()
|
|
423
|
+
)
|
|
424
|
+
|
|
425
|
+
serial_number = pipette_dict["pipette_id"]
|
|
426
|
+
static_pipette_config = pipette_data_provider.get_pipette_static_config(
|
|
427
|
+
pipette_dict=pipette_dict, tip_overlap_version=sanitized_overlap_version
|
|
428
|
+
)
|
|
429
|
+
|
|
430
|
+
else:
|
|
431
|
+
serial_number = self._model_utils.generate_id(prefix="fake-serial-number-")
|
|
432
|
+
static_pipette_config = (
|
|
433
|
+
self._virtual_pipette_data_provider.get_virtual_pipette_static_config(
|
|
434
|
+
pipette_name=pipette_name_value,
|
|
435
|
+
pipette_id=pipette_id,
|
|
436
|
+
tip_overlap_version=sanitized_overlap_version,
|
|
437
|
+
)
|
|
438
|
+
)
|
|
439
|
+
serial = serial_number or ""
|
|
440
|
+
return LoadedPipetteData(
|
|
441
|
+
pipette_id=pipette_id,
|
|
442
|
+
serial_number=serial,
|
|
443
|
+
static_config=static_pipette_config,
|
|
444
|
+
)
|
|
445
|
+
|
|
446
|
+
async def load_magnetic_block(
|
|
447
|
+
self,
|
|
448
|
+
model: ModuleModel,
|
|
449
|
+
location: AddressableAreaLocation,
|
|
450
|
+
module_id: Optional[str],
|
|
451
|
+
) -> LoadedModuleData:
|
|
452
|
+
"""Ensure the required magnetic block is attached.
|
|
453
|
+
|
|
454
|
+
Args:
|
|
455
|
+
model: The model name of the module.
|
|
456
|
+
location: The deck location of the module
|
|
457
|
+
module_id: Optional ID assigned to the module.
|
|
458
|
+
If None, an ID will be generated.
|
|
459
|
+
|
|
460
|
+
Returns:
|
|
461
|
+
A LoadedModuleData object.
|
|
462
|
+
|
|
463
|
+
Raises:
|
|
464
|
+
ModuleAlreadyPresentError: A module of a different type is already
|
|
465
|
+
assigned to the requested location.
|
|
466
|
+
"""
|
|
467
|
+
assert ModuleModel.is_magnetic_block(
|
|
468
|
+
model
|
|
469
|
+
), f"Expected Magnetic block and got {model.name}"
|
|
470
|
+
definition = self._module_data_provider.get_definition(model)
|
|
471
|
+
return LoadedModuleData(
|
|
472
|
+
module_id=self._model_utils.ensure_id(module_id),
|
|
473
|
+
serial_number=None,
|
|
474
|
+
definition=definition,
|
|
475
|
+
)
|
|
476
|
+
|
|
477
|
+
async def load_module(
|
|
478
|
+
self,
|
|
479
|
+
model: ModuleModel,
|
|
480
|
+
location: AddressableAreaLocation,
|
|
481
|
+
module_id: Optional[str],
|
|
482
|
+
) -> LoadedModuleData:
|
|
483
|
+
"""Ensure the required module is attached.
|
|
484
|
+
|
|
485
|
+
Args:
|
|
486
|
+
model: The model name of the module.
|
|
487
|
+
location: The deck location of the module
|
|
488
|
+
module_id: Optional ID assigned to the module.
|
|
489
|
+
If None, an ID will be generated.
|
|
490
|
+
|
|
491
|
+
Returns:
|
|
492
|
+
A LoadedModuleData object.
|
|
493
|
+
|
|
494
|
+
Raises:
|
|
495
|
+
ModuleNotAttachedError: A not-yet-assigned module matching the requested
|
|
496
|
+
parameters could not be found in the attached modules list.
|
|
497
|
+
ModuleAlreadyPresentError: A module of a different type is already
|
|
498
|
+
assigned to the requested location.
|
|
499
|
+
"""
|
|
500
|
+
# TODO(mc, 2022-02-09): validate module location given deck definition
|
|
501
|
+
use_virtual_modules = self._state_store.config.use_virtual_modules
|
|
502
|
+
|
|
503
|
+
if not use_virtual_modules:
|
|
504
|
+
attached_modules = [
|
|
505
|
+
HardwareModule(
|
|
506
|
+
serial_number=hw_mod.device_info["serial"],
|
|
507
|
+
definition=self._module_data_provider.get_definition(
|
|
508
|
+
ModuleModel(hw_mod.model())
|
|
509
|
+
),
|
|
510
|
+
)
|
|
511
|
+
for hw_mod in self._hardware_api.attached_modules
|
|
512
|
+
]
|
|
513
|
+
|
|
514
|
+
serial_number_at_locaiton = self._state_store.geometry._addressable_areas.get_fixture_serial_from_deck_configuration_by_addressable_area(
|
|
515
|
+
addressable_area_name=location.addressableAreaName
|
|
516
|
+
)
|
|
517
|
+
cutout_id = self._state_store.geometry._addressable_areas.get_cutout_id_by_deck_slot_name(
|
|
518
|
+
slot_name=self._state_store.geometry._addressable_areas.get_addressable_area_base_slot(
|
|
519
|
+
location.addressableAreaName
|
|
520
|
+
)
|
|
521
|
+
)
|
|
522
|
+
|
|
523
|
+
attached_module = self._state_store.modules.select_hardware_module_to_load(
|
|
524
|
+
model=model,
|
|
525
|
+
location=cutout_id,
|
|
526
|
+
attached_modules=attached_modules,
|
|
527
|
+
expected_serial_number=serial_number_at_locaiton,
|
|
528
|
+
)
|
|
529
|
+
|
|
530
|
+
else:
|
|
531
|
+
attached_module = HardwareModule(
|
|
532
|
+
serial_number=self._model_utils.generate_id(
|
|
533
|
+
prefix="fake-serial-number-"
|
|
534
|
+
),
|
|
535
|
+
definition=self._module_data_provider.get_definition(model),
|
|
536
|
+
)
|
|
537
|
+
|
|
538
|
+
return LoadedModuleData(
|
|
539
|
+
module_id=self._model_utils.ensure_id(module_id),
|
|
540
|
+
serial_number=attached_module.serial_number,
|
|
541
|
+
definition=attached_module.definition,
|
|
542
|
+
)
|
|
543
|
+
|
|
544
|
+
async def load_lids(
|
|
545
|
+
self,
|
|
546
|
+
load_name: str,
|
|
547
|
+
namespace: str,
|
|
548
|
+
version: int,
|
|
549
|
+
location: LabwareLocation,
|
|
550
|
+
quantity: int,
|
|
551
|
+
labware_ids: Optional[List[str]] = None,
|
|
552
|
+
) -> List[LoadedLabwareData]:
|
|
553
|
+
"""Load one or many lid labware by assigning an identifier and pulling required data.
|
|
554
|
+
|
|
555
|
+
Args:
|
|
556
|
+
load_name: The lid labware's load name.
|
|
557
|
+
namespace: The lid labware's namespace.
|
|
558
|
+
version: The lid labware's version.
|
|
559
|
+
location: The deck location at which lid(s) will be placed.
|
|
560
|
+
quantity: The quantity of lids to load at a location.
|
|
561
|
+
labware_ids: An optional list of identifiers to assign the labware. If None,
|
|
562
|
+
an identifier will be generated.
|
|
563
|
+
|
|
564
|
+
Raises:
|
|
565
|
+
ModuleNotLoadedError: If `location` references a module ID
|
|
566
|
+
that doesn't point to a valid loaded module.
|
|
567
|
+
|
|
568
|
+
Returns:
|
|
569
|
+
A list of LoadedLabwareData objects.
|
|
570
|
+
"""
|
|
571
|
+
definition_uri = uri_from_details(
|
|
572
|
+
load_name=load_name,
|
|
573
|
+
namespace=namespace,
|
|
574
|
+
version=version,
|
|
575
|
+
)
|
|
576
|
+
try:
|
|
577
|
+
# Try to use existing definition in state.
|
|
578
|
+
definition = self._state_store.labware.get_definition_by_uri(definition_uri)
|
|
579
|
+
except LabwareDefinitionDoesNotExistError:
|
|
580
|
+
definition = await self._labware_data_provider.get_labware_definition(
|
|
581
|
+
load_name=load_name,
|
|
582
|
+
namespace=namespace,
|
|
583
|
+
version=version,
|
|
584
|
+
)
|
|
585
|
+
|
|
586
|
+
stack_limit = definition.stackLimit if definition.stackLimit is not None else 1
|
|
587
|
+
if quantity > stack_limit:
|
|
588
|
+
raise ValueError(
|
|
589
|
+
f"Requested quantity {quantity} is greater than the stack limit of {stack_limit} provided by definition for {load_name}."
|
|
590
|
+
)
|
|
591
|
+
|
|
592
|
+
is_deck_slot_compatible = (
|
|
593
|
+
True
|
|
594
|
+
if definition.parameters.isDeckSlotCompatible is None
|
|
595
|
+
else definition.parameters.isDeckSlotCompatible
|
|
596
|
+
)
|
|
597
|
+
|
|
598
|
+
if isinstance(location, DeckSlotLocation) and not is_deck_slot_compatible:
|
|
599
|
+
raise ValueError(
|
|
600
|
+
f"Lid Labware {load_name} cannot be loaded onto a Deck Slot."
|
|
601
|
+
)
|
|
602
|
+
|
|
603
|
+
load_labware_data_list: list[LoadedLabwareData] = []
|
|
604
|
+
ids: list[str] = []
|
|
605
|
+
if labware_ids is not None:
|
|
606
|
+
if len(labware_ids) < quantity:
|
|
607
|
+
raise ValueError(
|
|
608
|
+
f"Requested quantity {quantity} is greater than the number of labware lid IDs provided for {load_name}."
|
|
609
|
+
)
|
|
610
|
+
ids = labware_ids
|
|
611
|
+
else:
|
|
612
|
+
for i in range(quantity):
|
|
613
|
+
ids.append(self._model_utils.generate_id())
|
|
614
|
+
for id in ids:
|
|
615
|
+
load_labware_data_list.append(
|
|
616
|
+
LoadedLabwareData(
|
|
617
|
+
labware_id=id,
|
|
618
|
+
definition=definition,
|
|
619
|
+
offsetId=None,
|
|
620
|
+
)
|
|
621
|
+
)
|
|
622
|
+
|
|
623
|
+
return load_labware_data_list
|
|
624
|
+
|
|
625
|
+
async def configure_for_volume(
|
|
626
|
+
self, pipette_id: str, volume: float, tip_overlap_version: Optional[str]
|
|
627
|
+
) -> LoadedConfigureForVolumeData:
|
|
628
|
+
"""Ensure the requested volume can be configured for the given pipette.
|
|
629
|
+
|
|
630
|
+
Args:
|
|
631
|
+
pipette_id: The identifier for the pipette.
|
|
632
|
+
volume: The volume to configure the pipette for
|
|
633
|
+
|
|
634
|
+
Returns:
|
|
635
|
+
A LoadedConfiguredVolumeData object.
|
|
636
|
+
"""
|
|
637
|
+
use_virtual_pipettes = self._state_store.config.use_virtual_pipettes
|
|
638
|
+
sanitized_overlap_version = (
|
|
639
|
+
pipette_data_provider.validate_and_default_tip_overlap_version(
|
|
640
|
+
tip_overlap_version
|
|
641
|
+
)
|
|
642
|
+
)
|
|
643
|
+
|
|
644
|
+
if not use_virtual_pipettes:
|
|
645
|
+
mount = self._state_store.pipettes.get_mount(pipette_id).to_hw_mount()
|
|
646
|
+
|
|
647
|
+
await self._hardware_api.configure_for_volume(mount, volume)
|
|
648
|
+
pipette_dict = self._hardware_api.get_attached_instrument(mount)
|
|
649
|
+
|
|
650
|
+
serial_number = pipette_dict["pipette_id"]
|
|
651
|
+
static_pipette_config = pipette_data_provider.get_pipette_static_config(
|
|
652
|
+
pipette_dict=pipette_dict, tip_overlap_version=sanitized_overlap_version
|
|
653
|
+
)
|
|
654
|
+
|
|
655
|
+
else:
|
|
656
|
+
model = self._state_store.pipettes.get_model_name(pipette_id)
|
|
657
|
+
self._virtual_pipette_data_provider.configure_virtual_pipette_for_volume(
|
|
658
|
+
pipette_id, volume, model
|
|
659
|
+
)
|
|
660
|
+
|
|
661
|
+
serial_number = self._model_utils.generate_id(prefix="fake-serial-number-")
|
|
662
|
+
static_pipette_config = self._virtual_pipette_data_provider.get_virtual_pipette_static_config_by_model_string(
|
|
663
|
+
pipette_model_string=model,
|
|
664
|
+
pipette_id=pipette_id,
|
|
665
|
+
tip_overlap_version=sanitized_overlap_version,
|
|
666
|
+
)
|
|
667
|
+
|
|
668
|
+
return LoadedConfigureForVolumeData(
|
|
669
|
+
pipette_id=pipette_id,
|
|
670
|
+
serial_number=serial_number,
|
|
671
|
+
volume=volume,
|
|
672
|
+
static_config=static_pipette_config,
|
|
673
|
+
)
|
|
674
|
+
|
|
675
|
+
async def configure_nozzle_layout(
|
|
676
|
+
self,
|
|
677
|
+
pipette_id: str,
|
|
678
|
+
primary_nozzle: Optional[str] = None,
|
|
679
|
+
front_right_nozzle: Optional[str] = None,
|
|
680
|
+
back_left_nozzle: Optional[str] = None,
|
|
681
|
+
) -> NozzleMap:
|
|
682
|
+
"""Ensure the requested nozzle layout is compatible with the current pipette.
|
|
683
|
+
|
|
684
|
+
Args:
|
|
685
|
+
pipette_id: The identifier for the pipette.
|
|
686
|
+
primary_nozzle: The nozzle which will be used as the
|
|
687
|
+
front_right_nozzle
|
|
688
|
+
back_left_nozzle
|
|
689
|
+
|
|
690
|
+
Returns:
|
|
691
|
+
A NozzleMap object or None.
|
|
692
|
+
"""
|
|
693
|
+
use_virtual_pipettes = self._state_store.config.use_virtual_pipettes
|
|
694
|
+
|
|
695
|
+
if not use_virtual_pipettes:
|
|
696
|
+
mount = self._state_store.pipettes.get_mount(pipette_id).to_hw_mount()
|
|
697
|
+
|
|
698
|
+
await self._hardware_api.update_nozzle_configuration_for_mount(
|
|
699
|
+
mount,
|
|
700
|
+
back_left_nozzle if back_left_nozzle else primary_nozzle,
|
|
701
|
+
front_right_nozzle if front_right_nozzle else primary_nozzle,
|
|
702
|
+
primary_nozzle if back_left_nozzle else None,
|
|
703
|
+
)
|
|
704
|
+
pipette_dict = self._hardware_api.get_attached_instrument(mount)
|
|
705
|
+
nozzle_map = pipette_dict["current_nozzle_map"]
|
|
706
|
+
|
|
707
|
+
else:
|
|
708
|
+
model = self._state_store.pipettes.get_model_name(pipette_id)
|
|
709
|
+
self._virtual_pipette_data_provider.configure_virtual_pipette_nozzle_layout(
|
|
710
|
+
pipette_id,
|
|
711
|
+
model,
|
|
712
|
+
back_left_nozzle if back_left_nozzle else primary_nozzle,
|
|
713
|
+
front_right_nozzle if front_right_nozzle else primary_nozzle,
|
|
714
|
+
primary_nozzle if back_left_nozzle else None,
|
|
715
|
+
)
|
|
716
|
+
nozzle_map = (
|
|
717
|
+
self._virtual_pipette_data_provider.get_nozzle_layout_for_pipette(
|
|
718
|
+
pipette_id
|
|
719
|
+
)
|
|
720
|
+
)
|
|
721
|
+
|
|
722
|
+
return nozzle_map
|
|
723
|
+
|
|
724
|
+
@overload
|
|
725
|
+
def get_module_hardware_api(
|
|
726
|
+
self,
|
|
727
|
+
module_id: MagneticModuleId,
|
|
728
|
+
) -> Optional[MagDeck]:
|
|
729
|
+
...
|
|
730
|
+
|
|
731
|
+
@overload
|
|
732
|
+
def get_module_hardware_api(
|
|
733
|
+
self,
|
|
734
|
+
module_id: HeaterShakerModuleId,
|
|
735
|
+
) -> Optional[HeaterShaker]:
|
|
736
|
+
...
|
|
737
|
+
|
|
738
|
+
@overload
|
|
739
|
+
def get_module_hardware_api(
|
|
740
|
+
self,
|
|
741
|
+
module_id: TemperatureModuleId,
|
|
742
|
+
) -> Optional[TempDeck]:
|
|
743
|
+
...
|
|
744
|
+
|
|
745
|
+
@overload
|
|
746
|
+
def get_module_hardware_api(
|
|
747
|
+
self,
|
|
748
|
+
module_id: ThermocyclerModuleId,
|
|
749
|
+
) -> Optional[Thermocycler]:
|
|
750
|
+
...
|
|
751
|
+
|
|
752
|
+
@overload
|
|
753
|
+
def get_module_hardware_api(
|
|
754
|
+
self,
|
|
755
|
+
module_id: AbsorbanceReaderId,
|
|
756
|
+
) -> Optional[AbsorbanceReader]:
|
|
757
|
+
...
|
|
758
|
+
|
|
759
|
+
@overload
|
|
760
|
+
def get_module_hardware_api(
|
|
761
|
+
self,
|
|
762
|
+
module_id: FlexStackerId,
|
|
763
|
+
) -> Optional[FlexStacker]:
|
|
764
|
+
...
|
|
765
|
+
|
|
766
|
+
def get_module_hardware_api(self, module_id: str) -> Optional[AbstractModule]:
|
|
767
|
+
"""Get the hardware API for a given module."""
|
|
768
|
+
use_virtual_modules = self._state_store.config.use_virtual_modules
|
|
769
|
+
if use_virtual_modules:
|
|
770
|
+
return None
|
|
771
|
+
|
|
772
|
+
attached_modules = self._hardware_api.attached_modules
|
|
773
|
+
serial_number = self._state_store.modules.get_serial_number(module_id)
|
|
774
|
+
for mod in attached_modules:
|
|
775
|
+
if mod.device_info["serial"] == serial_number:
|
|
776
|
+
return mod
|
|
777
|
+
|
|
778
|
+
raise ModuleNotAttachedError(
|
|
779
|
+
f'No module attached with serial number "{serial_number}"'
|
|
780
|
+
f' for module ID "{module_id}".'
|
|
781
|
+
)
|
|
782
|
+
|
|
783
|
+
def find_applicable_labware_offset_id(
|
|
784
|
+
self,
|
|
785
|
+
labware_definition_uri: str,
|
|
786
|
+
labware_location: LabwareLocation,
|
|
787
|
+
labware_pending_load: dict[str, LoadedLabware] | None = None,
|
|
788
|
+
) -> str | None:
|
|
789
|
+
"""Figure out what offset would apply to a labware in the given location.
|
|
790
|
+
|
|
791
|
+
Raises:
|
|
792
|
+
ModuleNotLoadedError: If `labware_location` references a module ID
|
|
793
|
+
that doesn't point to a valid loaded module.
|
|
794
|
+
|
|
795
|
+
Returns:
|
|
796
|
+
The ID of the labware offset that will apply,
|
|
797
|
+
or None if no labware offset will apply.
|
|
798
|
+
"""
|
|
799
|
+
labware_offset_location = (
|
|
800
|
+
self._state_store.geometry.get_projected_offset_location(
|
|
801
|
+
labware_location, labware_pending_load
|
|
802
|
+
)
|
|
803
|
+
)
|
|
804
|
+
|
|
805
|
+
if labware_offset_location is None:
|
|
806
|
+
# No offset for off-deck location.
|
|
807
|
+
# Returning None instead of raising an exception allows loading a labware
|
|
808
|
+
# with 'offDeck' as valid location.
|
|
809
|
+
# Also allows using `moveLabware` with 'offDeck' location.
|
|
810
|
+
return None
|
|
811
|
+
offset = self._state_store.labware.find_applicable_labware_offset(
|
|
812
|
+
definition_uri=labware_definition_uri,
|
|
813
|
+
location=labware_offset_location,
|
|
814
|
+
)
|
|
815
|
+
return self._get_id_from_offset(offset)
|
|
816
|
+
|
|
817
|
+
@staticmethod
|
|
818
|
+
def _get_id_from_offset(labware_offset: Optional[LabwareOffset]) -> Optional[str]:
|
|
819
|
+
return None if labware_offset is None else labware_offset.id
|