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,699 @@
|
|
|
1
|
+
"""Basic addressable area data state and store."""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from functools import cached_property
|
|
5
|
+
from typing import Dict, List, Optional, Set
|
|
6
|
+
|
|
7
|
+
from opentrons_shared_data.robot.types import RobotType, RobotDefinition
|
|
8
|
+
from opentrons_shared_data.deck.types import (
|
|
9
|
+
DeckDefinitionV5,
|
|
10
|
+
SlotDefV3,
|
|
11
|
+
CutoutFixture,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
from opentrons.types import Point, DeckSlotName
|
|
15
|
+
|
|
16
|
+
from ..errors import (
|
|
17
|
+
IncompatibleAddressableAreaError,
|
|
18
|
+
AreaNotInDeckConfigurationError,
|
|
19
|
+
SlotDoesNotExistError,
|
|
20
|
+
AddressableAreaDoesNotExistError,
|
|
21
|
+
CutoutDoesNotExistError,
|
|
22
|
+
)
|
|
23
|
+
from ..resources import deck_configuration_provider
|
|
24
|
+
from ..types import (
|
|
25
|
+
AddressableArea,
|
|
26
|
+
PotentialCutoutFixture,
|
|
27
|
+
DeckConfigurationType,
|
|
28
|
+
Dimensions,
|
|
29
|
+
)
|
|
30
|
+
from ..actions.get_state_update import get_state_updates
|
|
31
|
+
from ..actions import (
|
|
32
|
+
Action,
|
|
33
|
+
SetDeckConfigurationAction,
|
|
34
|
+
AddAddressableAreaAction,
|
|
35
|
+
)
|
|
36
|
+
from . import update_types
|
|
37
|
+
from .config import Config
|
|
38
|
+
from ._abstract_store import HasState, HandlesActions
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@dataclass
|
|
42
|
+
class AddressableAreaState:
|
|
43
|
+
"""State of all loaded addressable area resources."""
|
|
44
|
+
|
|
45
|
+
loaded_addressable_areas_by_name: Dict[str, AddressableArea]
|
|
46
|
+
"""The addressable areas that have been loaded so far.
|
|
47
|
+
|
|
48
|
+
When `use_simulated_deck_config` is `False`, these are the addressable areas that the
|
|
49
|
+
deck configuration provided.
|
|
50
|
+
|
|
51
|
+
When `use_simulated_deck_config` is `True`, these are the addressable areas that have been
|
|
52
|
+
referenced by the protocol so far.
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
potential_cutout_fixtures_by_cutout_id: Dict[str, Set[PotentialCutoutFixture]]
|
|
56
|
+
|
|
57
|
+
deck_definition: DeckDefinitionV5
|
|
58
|
+
|
|
59
|
+
deck_configuration: Optional[DeckConfigurationType]
|
|
60
|
+
"""The host robot's full deck configuration.
|
|
61
|
+
|
|
62
|
+
If `use_simulated_deck_config` is `True`, this is meaningless and this value is undefined.
|
|
63
|
+
In practice it will probably be `None` or `[]`.
|
|
64
|
+
|
|
65
|
+
If `use_simulated_deck_config` is `False`, this will be non-`None`.
|
|
66
|
+
"""
|
|
67
|
+
|
|
68
|
+
robot_type: RobotType
|
|
69
|
+
|
|
70
|
+
use_simulated_deck_config: bool
|
|
71
|
+
"""See `Config.use_simulated_deck_config`."""
|
|
72
|
+
|
|
73
|
+
"""Information about the current robot model."""
|
|
74
|
+
robot_definition: RobotDefinition
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
_OT2_ORDERED_SLOTS = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"]
|
|
78
|
+
_FLEX_ORDERED_SLOTS = [
|
|
79
|
+
"D1",
|
|
80
|
+
"D2",
|
|
81
|
+
"D3",
|
|
82
|
+
"C1",
|
|
83
|
+
"C2",
|
|
84
|
+
"C3",
|
|
85
|
+
"B1",
|
|
86
|
+
"B2",
|
|
87
|
+
"B3",
|
|
88
|
+
"A1",
|
|
89
|
+
"A2",
|
|
90
|
+
"A3",
|
|
91
|
+
]
|
|
92
|
+
_FLEX_ORDERED_STAGING_SLOTS = ["D4", "C4", "B4", "A4"]
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def _get_conflicting_addressable_areas_error_string(
|
|
96
|
+
potential_cutout_fixtures: Set[PotentialCutoutFixture],
|
|
97
|
+
loaded_addressable_areas: Dict[str, AddressableArea],
|
|
98
|
+
deck_definition: DeckDefinitionV5,
|
|
99
|
+
) -> str:
|
|
100
|
+
loaded_areas_on_cutout = set()
|
|
101
|
+
for fixture in potential_cutout_fixtures:
|
|
102
|
+
loaded_areas_on_cutout.update(
|
|
103
|
+
deck_configuration_provider.get_provided_addressable_area_names(
|
|
104
|
+
fixture.cutout_fixture_id,
|
|
105
|
+
fixture.cutout_id,
|
|
106
|
+
deck_definition,
|
|
107
|
+
)
|
|
108
|
+
)
|
|
109
|
+
loaded_areas_on_cutout.intersection_update(loaded_addressable_areas)
|
|
110
|
+
display_names = {
|
|
111
|
+
loaded_addressable_areas[area].display_name for area in loaded_areas_on_cutout
|
|
112
|
+
}
|
|
113
|
+
return ", ".join(display_names)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
class AddressableAreaStore(HasState[AddressableAreaState], HandlesActions):
|
|
117
|
+
"""Addressable area state container."""
|
|
118
|
+
|
|
119
|
+
_state: AddressableAreaState
|
|
120
|
+
|
|
121
|
+
def __init__(
|
|
122
|
+
self,
|
|
123
|
+
deck_configuration: DeckConfigurationType,
|
|
124
|
+
config: Config,
|
|
125
|
+
deck_definition: DeckDefinitionV5,
|
|
126
|
+
robot_definition: RobotDefinition,
|
|
127
|
+
) -> None:
|
|
128
|
+
"""Initialize an addressable area store and its state."""
|
|
129
|
+
if config.use_simulated_deck_config:
|
|
130
|
+
loaded_addressable_areas_by_name = {}
|
|
131
|
+
else:
|
|
132
|
+
loaded_addressable_areas_by_name = (
|
|
133
|
+
self._get_addressable_areas_from_deck_configuration(
|
|
134
|
+
deck_configuration,
|
|
135
|
+
deck_definition,
|
|
136
|
+
)
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
self._state = AddressableAreaState(
|
|
140
|
+
deck_configuration=deck_configuration,
|
|
141
|
+
loaded_addressable_areas_by_name=loaded_addressable_areas_by_name,
|
|
142
|
+
potential_cutout_fixtures_by_cutout_id={},
|
|
143
|
+
deck_definition=deck_definition,
|
|
144
|
+
robot_type=config.robot_type,
|
|
145
|
+
use_simulated_deck_config=config.use_simulated_deck_config,
|
|
146
|
+
robot_definition=robot_definition,
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
def handle_action(self, action: Action) -> None:
|
|
150
|
+
"""Modify state in reaction to an action."""
|
|
151
|
+
for state_update in get_state_updates(action):
|
|
152
|
+
if state_update.addressable_area_used != update_types.NO_CHANGE:
|
|
153
|
+
self._add_addressable_area(
|
|
154
|
+
state_update.addressable_area_used.addressable_area_name
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
if isinstance(action, AddAddressableAreaAction):
|
|
158
|
+
self._add_addressable_area(action.addressable_area_name)
|
|
159
|
+
elif isinstance(action, SetDeckConfigurationAction):
|
|
160
|
+
current_state = self._state
|
|
161
|
+
if (
|
|
162
|
+
action.deck_configuration is not None
|
|
163
|
+
and not self._state.use_simulated_deck_config
|
|
164
|
+
):
|
|
165
|
+
self._state.deck_configuration = action.deck_configuration
|
|
166
|
+
self._state.loaded_addressable_areas_by_name = (
|
|
167
|
+
self._get_addressable_areas_from_deck_configuration(
|
|
168
|
+
deck_config=action.deck_configuration,
|
|
169
|
+
deck_definition=current_state.deck_definition,
|
|
170
|
+
)
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
@staticmethod
|
|
174
|
+
def _get_addressable_areas_from_deck_configuration(
|
|
175
|
+
deck_config: DeckConfigurationType, deck_definition: DeckDefinitionV5
|
|
176
|
+
) -> Dict[str, AddressableArea]:
|
|
177
|
+
"""Return all addressable areas provided by the given deck configuration."""
|
|
178
|
+
addressable_areas = []
|
|
179
|
+
for cutout_id, cutout_fixture_id, opentrons_module_serial_number in deck_config:
|
|
180
|
+
provided_addressable_areas = (
|
|
181
|
+
deck_configuration_provider.get_provided_addressable_area_names(
|
|
182
|
+
cutout_fixture_id, cutout_id, deck_definition
|
|
183
|
+
)
|
|
184
|
+
)
|
|
185
|
+
cutout_position = deck_configuration_provider.get_cutout_position(
|
|
186
|
+
cutout_id, deck_definition
|
|
187
|
+
)
|
|
188
|
+
for addressable_area_name in provided_addressable_areas:
|
|
189
|
+
addressable_areas.append(
|
|
190
|
+
deck_configuration_provider.get_addressable_area_from_name(
|
|
191
|
+
addressable_area_name=addressable_area_name,
|
|
192
|
+
cutout_position=cutout_position,
|
|
193
|
+
deck_definition=deck_definition,
|
|
194
|
+
)
|
|
195
|
+
)
|
|
196
|
+
return {area.area_name: area for area in addressable_areas}
|
|
197
|
+
|
|
198
|
+
def _add_addressable_area(self, addressable_area_name: str) -> None:
|
|
199
|
+
if addressable_area_name not in self._state.loaded_addressable_areas_by_name:
|
|
200
|
+
cutout_id = self._validate_addressable_area_for_simulation(
|
|
201
|
+
addressable_area_name
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
cutout_position = deck_configuration_provider.get_cutout_position(
|
|
205
|
+
cutout_id, self._state.deck_definition
|
|
206
|
+
)
|
|
207
|
+
addressable_area = (
|
|
208
|
+
deck_configuration_provider.get_addressable_area_from_name(
|
|
209
|
+
addressable_area_name=addressable_area_name,
|
|
210
|
+
cutout_position=cutout_position,
|
|
211
|
+
deck_definition=self._state.deck_definition,
|
|
212
|
+
)
|
|
213
|
+
)
|
|
214
|
+
self._state.loaded_addressable_areas_by_name[
|
|
215
|
+
addressable_area.area_name
|
|
216
|
+
] = addressable_area
|
|
217
|
+
|
|
218
|
+
def _validate_addressable_area_for_simulation(
|
|
219
|
+
self, addressable_area_name: str
|
|
220
|
+
) -> str:
|
|
221
|
+
"""Given an addressable area name, validate it can exist on the deck and return cutout id associated with it."""
|
|
222
|
+
(
|
|
223
|
+
cutout_id,
|
|
224
|
+
potential_fixtures,
|
|
225
|
+
) = deck_configuration_provider.get_potential_cutout_fixtures(
|
|
226
|
+
addressable_area_name, self._state.deck_definition
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
if cutout_id in self._state.potential_cutout_fixtures_by_cutout_id:
|
|
230
|
+
# Get the existing potential cutout fixtures for the addressable area already loaded on this cutout
|
|
231
|
+
existing_potential_fixtures = (
|
|
232
|
+
self._state.potential_cutout_fixtures_by_cutout_id[cutout_id]
|
|
233
|
+
)
|
|
234
|
+
# Get common cutout fixture that supplies existing addressable areas and the one being loaded
|
|
235
|
+
remaining_fixtures = existing_potential_fixtures.intersection(
|
|
236
|
+
set(potential_fixtures)
|
|
237
|
+
)
|
|
238
|
+
|
|
239
|
+
self._state.potential_cutout_fixtures_by_cutout_id[
|
|
240
|
+
cutout_id
|
|
241
|
+
] = remaining_fixtures
|
|
242
|
+
else:
|
|
243
|
+
self._state.potential_cutout_fixtures_by_cutout_id[cutout_id] = set(
|
|
244
|
+
potential_fixtures
|
|
245
|
+
)
|
|
246
|
+
|
|
247
|
+
return cutout_id
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
class AddressableAreaView:
|
|
251
|
+
"""Read-only addressable area state view."""
|
|
252
|
+
|
|
253
|
+
_state: AddressableAreaState
|
|
254
|
+
|
|
255
|
+
def __init__(self, state: AddressableAreaState) -> None:
|
|
256
|
+
"""Initialize the computed view of addressable area state.
|
|
257
|
+
|
|
258
|
+
Arguments:
|
|
259
|
+
state: Addressable area state dataclass used for all calculations.
|
|
260
|
+
"""
|
|
261
|
+
self._state = state
|
|
262
|
+
|
|
263
|
+
@cached_property
|
|
264
|
+
def deck_definition(self) -> DeckDefinitionV5:
|
|
265
|
+
"""The full deck definition."""
|
|
266
|
+
return self._state.deck_definition
|
|
267
|
+
|
|
268
|
+
@cached_property
|
|
269
|
+
def deck_extents(self) -> Point:
|
|
270
|
+
"""The maximum space on the deck."""
|
|
271
|
+
extents = self._state.robot_definition["extents"]
|
|
272
|
+
return Point(x=extents[0], y=extents[1], z=extents[2])
|
|
273
|
+
|
|
274
|
+
@cached_property
|
|
275
|
+
def mount_offsets(self) -> Dict[str, Point]:
|
|
276
|
+
"""The left and right mount offsets of the robot."""
|
|
277
|
+
left_offset = self._state.robot_definition["mountOffsets"]["left"]
|
|
278
|
+
right_offset = self._state.robot_definition["mountOffsets"]["right"]
|
|
279
|
+
return {
|
|
280
|
+
"left": Point(x=left_offset[0], y=left_offset[1], z=left_offset[2]),
|
|
281
|
+
"right": Point(x=right_offset[0], y=right_offset[1], z=right_offset[2]),
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
@cached_property
|
|
285
|
+
def padding_offsets(self) -> Dict[str, float]:
|
|
286
|
+
"""The padding offsets to be applied to the deck extents of the robot."""
|
|
287
|
+
rear_offset = self._state.robot_definition["paddingOffsets"]["rear"]
|
|
288
|
+
front_offset = self._state.robot_definition["paddingOffsets"]["front"]
|
|
289
|
+
left_side_offset = self._state.robot_definition["paddingOffsets"]["leftSide"]
|
|
290
|
+
right_side_offset = self._state.robot_definition["paddingOffsets"]["rightSide"]
|
|
291
|
+
return {
|
|
292
|
+
"rear": rear_offset,
|
|
293
|
+
"front": front_offset,
|
|
294
|
+
"left_side": left_side_offset,
|
|
295
|
+
"right_side": right_side_offset,
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
def get_addressable_area(self, addressable_area_name: str) -> AddressableArea:
|
|
299
|
+
"""Get addressable area."""
|
|
300
|
+
if not self._state.use_simulated_deck_config:
|
|
301
|
+
return self._get_loaded_addressable_area(addressable_area_name)
|
|
302
|
+
else:
|
|
303
|
+
return self._get_addressable_area_from_deck_data(
|
|
304
|
+
addressable_area_name=addressable_area_name,
|
|
305
|
+
do_compatibility_check=True,
|
|
306
|
+
)
|
|
307
|
+
|
|
308
|
+
def get_all(self) -> List[str]:
|
|
309
|
+
"""Get a list of all loaded addressable area names."""
|
|
310
|
+
return list(self._state.loaded_addressable_areas_by_name)
|
|
311
|
+
|
|
312
|
+
def get_all_cutout_fixtures(self) -> Optional[List[str]]:
|
|
313
|
+
"""Get the names of all fixtures present in the host robot's deck configuration.
|
|
314
|
+
|
|
315
|
+
If `use_simulated_deck_config` is `True` (see `Config`), we don't have a
|
|
316
|
+
meaningful concrete layout of fixtures, so this will return `None`.
|
|
317
|
+
"""
|
|
318
|
+
if self._state.use_simulated_deck_config:
|
|
319
|
+
return None
|
|
320
|
+
else:
|
|
321
|
+
assert self._state.deck_configuration is not None
|
|
322
|
+
return [
|
|
323
|
+
cutout_fixture_id
|
|
324
|
+
for _, cutout_fixture_id, _serial in self._state.deck_configuration
|
|
325
|
+
]
|
|
326
|
+
|
|
327
|
+
def _get_loaded_addressable_area(
|
|
328
|
+
self, addressable_area_name: str
|
|
329
|
+
) -> AddressableArea:
|
|
330
|
+
"""Get an addressable area that has been loaded into state. Will raise error if it does not exist."""
|
|
331
|
+
try:
|
|
332
|
+
return self._state.loaded_addressable_areas_by_name[addressable_area_name]
|
|
333
|
+
except KeyError:
|
|
334
|
+
raise AreaNotInDeckConfigurationError(
|
|
335
|
+
f"{addressable_area_name} not provided by deck configuration."
|
|
336
|
+
)
|
|
337
|
+
|
|
338
|
+
def _check_if_area_is_compatible_with_potential_fixtures(
|
|
339
|
+
self,
|
|
340
|
+
area_name: str,
|
|
341
|
+
cutout_id: str,
|
|
342
|
+
potential_fixtures: Set[PotentialCutoutFixture],
|
|
343
|
+
) -> None:
|
|
344
|
+
if cutout_id in self._state.potential_cutout_fixtures_by_cutout_id:
|
|
345
|
+
if not self._state.potential_cutout_fixtures_by_cutout_id[
|
|
346
|
+
cutout_id
|
|
347
|
+
].intersection(potential_fixtures):
|
|
348
|
+
loaded_areas_on_cutout = (
|
|
349
|
+
_get_conflicting_addressable_areas_error_string(
|
|
350
|
+
self._state.potential_cutout_fixtures_by_cutout_id[cutout_id],
|
|
351
|
+
self._state.loaded_addressable_areas_by_name,
|
|
352
|
+
self._state.deck_definition,
|
|
353
|
+
)
|
|
354
|
+
)
|
|
355
|
+
area_display_name = (
|
|
356
|
+
deck_configuration_provider.get_addressable_area_display_name(
|
|
357
|
+
area_name, self._state.deck_definition
|
|
358
|
+
)
|
|
359
|
+
)
|
|
360
|
+
raise IncompatibleAddressableAreaError(
|
|
361
|
+
f"Cannot use {area_display_name}, not compatible with one or more of"
|
|
362
|
+
f" the following fixtures: {loaded_areas_on_cutout}"
|
|
363
|
+
)
|
|
364
|
+
|
|
365
|
+
def _get_addressable_area_from_deck_data(
|
|
366
|
+
self,
|
|
367
|
+
addressable_area_name: str,
|
|
368
|
+
do_compatibility_check: bool,
|
|
369
|
+
) -> AddressableArea:
|
|
370
|
+
"""Get an addressable area that may not have been already loaded for a simulated run.
|
|
371
|
+
|
|
372
|
+
Since this may be the first time this addressable area has been called, and it might not exist in the store
|
|
373
|
+
yet (and if not won't until the result completes), we have to check if it is theoretically possible and then
|
|
374
|
+
get the area data from the deck configuration provider.
|
|
375
|
+
"""
|
|
376
|
+
if addressable_area_name in self._state.loaded_addressable_areas_by_name:
|
|
377
|
+
return self._state.loaded_addressable_areas_by_name[addressable_area_name]
|
|
378
|
+
|
|
379
|
+
(
|
|
380
|
+
cutout_id,
|
|
381
|
+
potential_fixtures,
|
|
382
|
+
) = deck_configuration_provider.get_potential_cutout_fixtures(
|
|
383
|
+
addressable_area_name, self._state.deck_definition
|
|
384
|
+
)
|
|
385
|
+
|
|
386
|
+
if do_compatibility_check:
|
|
387
|
+
self._check_if_area_is_compatible_with_potential_fixtures(
|
|
388
|
+
addressable_area_name, cutout_id, potential_fixtures
|
|
389
|
+
)
|
|
390
|
+
|
|
391
|
+
cutout_position = deck_configuration_provider.get_cutout_position(
|
|
392
|
+
cutout_id, self._state.deck_definition
|
|
393
|
+
)
|
|
394
|
+
return deck_configuration_provider.get_addressable_area_from_name(
|
|
395
|
+
addressable_area_name=addressable_area_name,
|
|
396
|
+
cutout_position=cutout_position,
|
|
397
|
+
deck_definition=self._state.deck_definition,
|
|
398
|
+
)
|
|
399
|
+
|
|
400
|
+
def get_addressable_area_base_slot(
|
|
401
|
+
self, addressable_area_name: str
|
|
402
|
+
) -> DeckSlotName:
|
|
403
|
+
"""Get the base slot the addressable area is associated with."""
|
|
404
|
+
addressable_area = self.get_addressable_area(addressable_area_name)
|
|
405
|
+
return addressable_area.base_slot
|
|
406
|
+
|
|
407
|
+
def get_addressable_area_position(
|
|
408
|
+
self,
|
|
409
|
+
addressable_area_name: str,
|
|
410
|
+
do_compatibility_check: bool = True,
|
|
411
|
+
) -> Point:
|
|
412
|
+
"""Get the position of an addressable area.
|
|
413
|
+
|
|
414
|
+
This does not require the addressable area to be in the deck configuration.
|
|
415
|
+
This is primarily used to support legacy fixed trash labware without
|
|
416
|
+
modifying the deck layout to remove the similar, but functionally different,
|
|
417
|
+
trashBinAdapter cutout fixture.
|
|
418
|
+
|
|
419
|
+
Besides that instance, for movement purposes, this should only be called for
|
|
420
|
+
areas that have been pre-validated, otherwise there could be the risk of collision.
|
|
421
|
+
"""
|
|
422
|
+
addressable_area = self._get_addressable_area_from_deck_data(
|
|
423
|
+
addressable_area_name=addressable_area_name,
|
|
424
|
+
do_compatibility_check=False, # This should probably not default to false
|
|
425
|
+
)
|
|
426
|
+
position = addressable_area.position
|
|
427
|
+
return Point(x=position.x, y=position.y, z=position.z)
|
|
428
|
+
|
|
429
|
+
def get_addressable_area_offsets_from_cutout(
|
|
430
|
+
self,
|
|
431
|
+
addressable_area_name: str,
|
|
432
|
+
) -> Point:
|
|
433
|
+
"""Get the offset form cutout fixture of an addressable area."""
|
|
434
|
+
for addressable_area in self._state.deck_definition["locations"][
|
|
435
|
+
"addressableAreas"
|
|
436
|
+
]:
|
|
437
|
+
if addressable_area["id"] == addressable_area_name:
|
|
438
|
+
area_offset = addressable_area["offsetFromCutoutFixture"]
|
|
439
|
+
position = Point(
|
|
440
|
+
x=area_offset[0],
|
|
441
|
+
y=area_offset[1],
|
|
442
|
+
z=area_offset[2],
|
|
443
|
+
)
|
|
444
|
+
return Point(x=position.x, y=position.y, z=position.z)
|
|
445
|
+
raise ValueError(
|
|
446
|
+
f"No matching addressable area named {addressable_area_name} identified."
|
|
447
|
+
)
|
|
448
|
+
|
|
449
|
+
def get_addressable_area_bounding_box(
|
|
450
|
+
self,
|
|
451
|
+
addressable_area_name: str,
|
|
452
|
+
do_compatibility_check: bool = True,
|
|
453
|
+
) -> Dimensions:
|
|
454
|
+
"""Get the bounding box of an addressable area.
|
|
455
|
+
|
|
456
|
+
This does not require the addressable area to be in the deck configuration.
|
|
457
|
+
For movement purposes, this should only be called for
|
|
458
|
+
areas that have been pre-validated, otherwise there could be the risk of collision.
|
|
459
|
+
"""
|
|
460
|
+
addressable_area = self._get_addressable_area_from_deck_data(
|
|
461
|
+
addressable_area_name=addressable_area_name,
|
|
462
|
+
do_compatibility_check=do_compatibility_check,
|
|
463
|
+
)
|
|
464
|
+
return addressable_area.bounding_box
|
|
465
|
+
|
|
466
|
+
def get_addressable_area_move_to_location(
|
|
467
|
+
self, addressable_area_name: str
|
|
468
|
+
) -> Point:
|
|
469
|
+
"""Get the move-to position (top center) for an addressable area."""
|
|
470
|
+
addressable_area = self.get_addressable_area(addressable_area_name)
|
|
471
|
+
position = addressable_area.position
|
|
472
|
+
bounding_box = addressable_area.bounding_box
|
|
473
|
+
return Point(
|
|
474
|
+
x=position.x + bounding_box.x / 2,
|
|
475
|
+
y=position.y + bounding_box.y / 2,
|
|
476
|
+
z=position.z + bounding_box.z,
|
|
477
|
+
)
|
|
478
|
+
|
|
479
|
+
def get_addressable_area_center(self, addressable_area_name: str) -> Point:
|
|
480
|
+
"""Get the (x, y, z) position of the center of the area."""
|
|
481
|
+
addressable_area = self.get_addressable_area(addressable_area_name)
|
|
482
|
+
position = addressable_area.position
|
|
483
|
+
bounding_box = addressable_area.bounding_box
|
|
484
|
+
return Point(
|
|
485
|
+
x=position.x + bounding_box.x / 2,
|
|
486
|
+
y=position.y + bounding_box.y / 2,
|
|
487
|
+
z=position.z,
|
|
488
|
+
)
|
|
489
|
+
|
|
490
|
+
def get_cutout_id_by_deck_slot_name(self, slot_name: DeckSlotName) -> str:
|
|
491
|
+
"""Get the Cutout ID of a given Deck Slot by Deck Slot Name."""
|
|
492
|
+
return deck_configuration_provider.get_cutout_id_by_deck_slot_name(slot_name)
|
|
493
|
+
|
|
494
|
+
def get_fixture_by_deck_slot_name(
|
|
495
|
+
self, slot_name: DeckSlotName
|
|
496
|
+
) -> Optional[CutoutFixture]:
|
|
497
|
+
"""Get the Cutout Fixture currently loaded where a specific Deck Slot would be."""
|
|
498
|
+
deck_config = self._state.deck_configuration
|
|
499
|
+
if deck_config:
|
|
500
|
+
slot_cutout_id = (
|
|
501
|
+
deck_configuration_provider.get_cutout_id_by_deck_slot_name(slot_name)
|
|
502
|
+
)
|
|
503
|
+
slot_cutout_fixture = None
|
|
504
|
+
# This will only ever be one under current assumptions
|
|
505
|
+
for (
|
|
506
|
+
cutout_id,
|
|
507
|
+
cutout_fixture_id,
|
|
508
|
+
opentrons_module_serial_number,
|
|
509
|
+
) in deck_config:
|
|
510
|
+
if cutout_id == slot_cutout_id:
|
|
511
|
+
slot_cutout_fixture = (
|
|
512
|
+
deck_configuration_provider.get_cutout_fixture(
|
|
513
|
+
cutout_fixture_id, self._state.deck_definition
|
|
514
|
+
)
|
|
515
|
+
)
|
|
516
|
+
return slot_cutout_fixture
|
|
517
|
+
if slot_cutout_fixture is None:
|
|
518
|
+
# If this happens, it's a bug. Either DECK_SLOT_TO_CUTOUT_MAP
|
|
519
|
+
# is missing an entry for the slot, or the deck configuration is missing
|
|
520
|
+
# an entry for the cutout.
|
|
521
|
+
raise CutoutDoesNotExistError(
|
|
522
|
+
f"No Cutout was found in the Deck that matched provided slot {slot_name}."
|
|
523
|
+
)
|
|
524
|
+
return None
|
|
525
|
+
|
|
526
|
+
def get_fixture_height(self, cutout_fixture_name: str) -> float:
|
|
527
|
+
"""Get the z height of a cutout fixture."""
|
|
528
|
+
cutout_fixture = deck_configuration_provider.get_cutout_fixture(
|
|
529
|
+
cutout_fixture_name, self._state.deck_definition
|
|
530
|
+
)
|
|
531
|
+
return cutout_fixture["height"]
|
|
532
|
+
|
|
533
|
+
def get_fixture_serial_from_deck_configuration_by_deck_slot(
|
|
534
|
+
self, slot_name: DeckSlotName
|
|
535
|
+
) -> Optional[str]:
|
|
536
|
+
"""Get the serial number provided by the deck configuration for a Fixture at a given location."""
|
|
537
|
+
deck_config = self._state.deck_configuration
|
|
538
|
+
if deck_config:
|
|
539
|
+
slot_cutout_id = (
|
|
540
|
+
deck_configuration_provider.get_cutout_id_by_deck_slot_name(slot_name)
|
|
541
|
+
)
|
|
542
|
+
# This will only ever be one under current assumptions
|
|
543
|
+
for (
|
|
544
|
+
cutout_id,
|
|
545
|
+
cutout_fixture_id,
|
|
546
|
+
opentrons_module_serial_number,
|
|
547
|
+
) in deck_config:
|
|
548
|
+
if cutout_id == slot_cutout_id:
|
|
549
|
+
return opentrons_module_serial_number
|
|
550
|
+
return None
|
|
551
|
+
|
|
552
|
+
def get_serial_number_by_cutout_id(self, slot_cutout_id: str) -> str | None:
|
|
553
|
+
"""Gets serial number from deck at a given cutout ID if one exists."""
|
|
554
|
+
deck_config = self._state.deck_configuration
|
|
555
|
+
if deck_config:
|
|
556
|
+
for (
|
|
557
|
+
cutout_id,
|
|
558
|
+
cutout_fixture_id,
|
|
559
|
+
opentrons_module_serial_number,
|
|
560
|
+
) in deck_config:
|
|
561
|
+
if cutout_id == slot_cutout_id:
|
|
562
|
+
return opentrons_module_serial_number
|
|
563
|
+
return None
|
|
564
|
+
|
|
565
|
+
def get_fixture_serial_from_deck_configuration_by_addressable_area(
|
|
566
|
+
self, addressable_area_name: str
|
|
567
|
+
) -> Optional[str]:
|
|
568
|
+
"""Get the serial number provided by the deck configuration for a Fixture that provides a given addressable area."""
|
|
569
|
+
deck_config = self._state.deck_configuration
|
|
570
|
+
if deck_config:
|
|
571
|
+
potential_fixtures = (
|
|
572
|
+
deck_configuration_provider.get_potential_cutout_fixtures(
|
|
573
|
+
addressable_area_name, self._state.deck_definition
|
|
574
|
+
)
|
|
575
|
+
)
|
|
576
|
+
slot_cutout_id = potential_fixtures[0]
|
|
577
|
+
fixture_ids = [
|
|
578
|
+
fixture.cutout_fixture_id for fixture in potential_fixtures[1]
|
|
579
|
+
]
|
|
580
|
+
# This will only ever be one under current assumptions
|
|
581
|
+
for (
|
|
582
|
+
cutout_id,
|
|
583
|
+
cutout_fixture_id,
|
|
584
|
+
opentrons_module_serial_number,
|
|
585
|
+
) in deck_config:
|
|
586
|
+
if cutout_id == slot_cutout_id and cutout_fixture_id in fixture_ids:
|
|
587
|
+
return opentrons_module_serial_number
|
|
588
|
+
return None
|
|
589
|
+
|
|
590
|
+
def get_slot_definition(self, slot_id: str) -> SlotDefV3:
|
|
591
|
+
"""Get the definition of a slot in the deck.
|
|
592
|
+
|
|
593
|
+
This does not require that the slot exist in deck configuration.
|
|
594
|
+
"""
|
|
595
|
+
try:
|
|
596
|
+
addressable_area = self._get_addressable_area_from_deck_data(
|
|
597
|
+
addressable_area_name=slot_id,
|
|
598
|
+
do_compatibility_check=True, # From the description of get_slot_definition, this might have to be False.
|
|
599
|
+
)
|
|
600
|
+
except AddressableAreaDoesNotExistError:
|
|
601
|
+
raise SlotDoesNotExistError(
|
|
602
|
+
f"Slot ID {slot_id} does not exist in deck {self._state.deck_definition['otId']}"
|
|
603
|
+
)
|
|
604
|
+
position = addressable_area.position
|
|
605
|
+
bounding_box = addressable_area.bounding_box
|
|
606
|
+
return {
|
|
607
|
+
"id": addressable_area.area_name,
|
|
608
|
+
"position": [position.x, position.y, position.z],
|
|
609
|
+
"boundingBox": {
|
|
610
|
+
"xDimension": bounding_box.x,
|
|
611
|
+
"yDimension": bounding_box.y,
|
|
612
|
+
"zDimension": bounding_box.z,
|
|
613
|
+
},
|
|
614
|
+
"displayName": addressable_area.display_name,
|
|
615
|
+
"compatibleModuleTypes": addressable_area.compatible_module_types,
|
|
616
|
+
"features": addressable_area.features,
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
def get_deck_slot_definitions(self) -> Dict[str, SlotDefV3]:
|
|
620
|
+
"""Get all standard slot definitions available in the deck definition."""
|
|
621
|
+
if self._state.robot_type == "OT-2 Standard":
|
|
622
|
+
slots = _OT2_ORDERED_SLOTS
|
|
623
|
+
else:
|
|
624
|
+
slots = _FLEX_ORDERED_SLOTS
|
|
625
|
+
return {slot_name: self.get_slot_definition(slot_name) for slot_name in slots}
|
|
626
|
+
|
|
627
|
+
def get_staging_slot_definitions(self) -> Dict[str, SlotDefV3]:
|
|
628
|
+
"""Get all staging slot definitions available in the deck definition."""
|
|
629
|
+
if self._state.robot_type == "OT-3 Standard":
|
|
630
|
+
return {
|
|
631
|
+
slot_name: self.get_slot_definition(slot_name)
|
|
632
|
+
for slot_name in _FLEX_ORDERED_STAGING_SLOTS
|
|
633
|
+
}
|
|
634
|
+
else:
|
|
635
|
+
return {}
|
|
636
|
+
|
|
637
|
+
def raise_if_area_not_in_deck_configuration(
|
|
638
|
+
self, addressable_area_name: str
|
|
639
|
+
) -> None:
|
|
640
|
+
"""Raise error if an addressable area is not compatible with or in the deck configuration.
|
|
641
|
+
|
|
642
|
+
For simulated runs/analysis, this will raise if the given addressable area is not compatible with other
|
|
643
|
+
previously referenced addressable areas, for example if a movable trash in A1 is in state, referencing the
|
|
644
|
+
deck slot A1 will raise since those two can't exist in any deck configuration combination.
|
|
645
|
+
|
|
646
|
+
For an on robot run, it will check if it is in the robot's deck configuration, if not it will raise an error.
|
|
647
|
+
"""
|
|
648
|
+
if self._state.use_simulated_deck_config:
|
|
649
|
+
(
|
|
650
|
+
cutout_id,
|
|
651
|
+
potential_fixtures,
|
|
652
|
+
) = deck_configuration_provider.get_potential_cutout_fixtures(
|
|
653
|
+
addressable_area_name, self._state.deck_definition
|
|
654
|
+
)
|
|
655
|
+
|
|
656
|
+
self._check_if_area_is_compatible_with_potential_fixtures(
|
|
657
|
+
addressable_area_name, cutout_id, potential_fixtures
|
|
658
|
+
)
|
|
659
|
+
else:
|
|
660
|
+
if (
|
|
661
|
+
addressable_area_name
|
|
662
|
+
not in self._state.loaded_addressable_areas_by_name
|
|
663
|
+
):
|
|
664
|
+
raise AreaNotInDeckConfigurationError(
|
|
665
|
+
f"{addressable_area_name} not provided by deck configuration."
|
|
666
|
+
)
|
|
667
|
+
|
|
668
|
+
def get_current_potential_cutout_fixtures_for_addressable_area(
|
|
669
|
+
self, addressable_area_name: str
|
|
670
|
+
) -> tuple[str, Set[PotentialCutoutFixture]]:
|
|
671
|
+
"""Get the set of cutout fixtures that might provide a given addressable area.
|
|
672
|
+
|
|
673
|
+
This takes into account the constraints already established by load commands or by a loaded deck
|
|
674
|
+
configuration, and may therefore return different results for the same addressable area at
|
|
675
|
+
different points in the protocol after deck configuration constraints have changed.
|
|
676
|
+
|
|
677
|
+
This returns the common cutout id and the potential fixtures.
|
|
678
|
+
"""
|
|
679
|
+
(
|
|
680
|
+
cutout_id,
|
|
681
|
+
base_potential_fixtures,
|
|
682
|
+
) = deck_configuration_provider.get_potential_cutout_fixtures(
|
|
683
|
+
addressable_area_name, self._state.deck_definition
|
|
684
|
+
)
|
|
685
|
+
try:
|
|
686
|
+
loaded_potential_fixtures = (
|
|
687
|
+
self._state.potential_cutout_fixtures_by_cutout_id[cutout_id]
|
|
688
|
+
)
|
|
689
|
+
return cutout_id, loaded_potential_fixtures.intersection(
|
|
690
|
+
base_potential_fixtures
|
|
691
|
+
)
|
|
692
|
+
except KeyError:
|
|
693
|
+
# If there was a key error here, it's because this function was (eventually) called
|
|
694
|
+
# from the body of a command implementation whose state update will load the
|
|
695
|
+
# addressable area it's querying... but that state update has not been submitted
|
|
696
|
+
# and processed, so nothing has created the entry for this cutout id yet. Do what
|
|
697
|
+
# we'll do when we actually get to that state update, which is apply the base
|
|
698
|
+
# potential fixtures from the deck def.
|
|
699
|
+
return cutout_id, base_potential_fixtures
|