opentrons 8.6.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of opentrons might be problematic. Click here for more details.
- opentrons/__init__.py +150 -0
- opentrons/_version.py +34 -0
- opentrons/calibration_storage/__init__.py +54 -0
- opentrons/calibration_storage/deck_configuration.py +62 -0
- opentrons/calibration_storage/encoder_decoder.py +31 -0
- opentrons/calibration_storage/file_operators.py +142 -0
- opentrons/calibration_storage/helpers.py +103 -0
- opentrons/calibration_storage/ot2/__init__.py +34 -0
- opentrons/calibration_storage/ot2/deck_attitude.py +85 -0
- opentrons/calibration_storage/ot2/mark_bad_calibration.py +27 -0
- opentrons/calibration_storage/ot2/models/__init__.py +0 -0
- opentrons/calibration_storage/ot2/models/v1.py +149 -0
- opentrons/calibration_storage/ot2/pipette_offset.py +129 -0
- opentrons/calibration_storage/ot2/tip_length.py +281 -0
- opentrons/calibration_storage/ot3/__init__.py +31 -0
- opentrons/calibration_storage/ot3/deck_attitude.py +83 -0
- opentrons/calibration_storage/ot3/gripper_offset.py +156 -0
- opentrons/calibration_storage/ot3/models/__init__.py +0 -0
- opentrons/calibration_storage/ot3/models/v1.py +122 -0
- opentrons/calibration_storage/ot3/module_offset.py +138 -0
- opentrons/calibration_storage/ot3/pipette_offset.py +95 -0
- opentrons/calibration_storage/types.py +45 -0
- opentrons/cli/__init__.py +21 -0
- opentrons/cli/__main__.py +5 -0
- opentrons/cli/analyze.py +557 -0
- opentrons/config/__init__.py +631 -0
- opentrons/config/advanced_settings.py +871 -0
- opentrons/config/defaults_ot2.py +214 -0
- opentrons/config/defaults_ot3.py +499 -0
- opentrons/config/feature_flags.py +86 -0
- opentrons/config/gripper_config.py +55 -0
- opentrons/config/reset.py +203 -0
- opentrons/config/robot_configs.py +187 -0
- opentrons/config/types.py +183 -0
- opentrons/drivers/__init__.py +0 -0
- opentrons/drivers/absorbance_reader/__init__.py +11 -0
- opentrons/drivers/absorbance_reader/abstract.py +72 -0
- opentrons/drivers/absorbance_reader/async_byonoy.py +352 -0
- opentrons/drivers/absorbance_reader/driver.py +81 -0
- opentrons/drivers/absorbance_reader/hid_protocol.py +161 -0
- opentrons/drivers/absorbance_reader/simulator.py +84 -0
- opentrons/drivers/asyncio/__init__.py +0 -0
- opentrons/drivers/asyncio/communication/__init__.py +22 -0
- opentrons/drivers/asyncio/communication/async_serial.py +187 -0
- opentrons/drivers/asyncio/communication/errors.py +88 -0
- opentrons/drivers/asyncio/communication/serial_connection.py +557 -0
- opentrons/drivers/command_builder.py +102 -0
- opentrons/drivers/flex_stacker/__init__.py +13 -0
- opentrons/drivers/flex_stacker/abstract.py +214 -0
- opentrons/drivers/flex_stacker/driver.py +768 -0
- opentrons/drivers/flex_stacker/errors.py +68 -0
- opentrons/drivers/flex_stacker/simulator.py +309 -0
- opentrons/drivers/flex_stacker/types.py +367 -0
- opentrons/drivers/flex_stacker/utils.py +19 -0
- opentrons/drivers/heater_shaker/__init__.py +5 -0
- opentrons/drivers/heater_shaker/abstract.py +76 -0
- opentrons/drivers/heater_shaker/driver.py +204 -0
- opentrons/drivers/heater_shaker/simulator.py +94 -0
- opentrons/drivers/mag_deck/__init__.py +6 -0
- opentrons/drivers/mag_deck/abstract.py +44 -0
- opentrons/drivers/mag_deck/driver.py +208 -0
- opentrons/drivers/mag_deck/simulator.py +63 -0
- opentrons/drivers/rpi_drivers/__init__.py +33 -0
- opentrons/drivers/rpi_drivers/dev_types.py +94 -0
- opentrons/drivers/rpi_drivers/gpio.py +282 -0
- opentrons/drivers/rpi_drivers/gpio_simulator.py +127 -0
- opentrons/drivers/rpi_drivers/interfaces.py +15 -0
- opentrons/drivers/rpi_drivers/types.py +364 -0
- opentrons/drivers/rpi_drivers/usb.py +102 -0
- opentrons/drivers/rpi_drivers/usb_simulator.py +22 -0
- opentrons/drivers/serial_communication.py +151 -0
- opentrons/drivers/smoothie_drivers/__init__.py +4 -0
- opentrons/drivers/smoothie_drivers/connection.py +51 -0
- opentrons/drivers/smoothie_drivers/constants.py +121 -0
- opentrons/drivers/smoothie_drivers/driver_3_0.py +1933 -0
- opentrons/drivers/smoothie_drivers/errors.py +49 -0
- opentrons/drivers/smoothie_drivers/parse_utils.py +143 -0
- opentrons/drivers/smoothie_drivers/simulator.py +99 -0
- opentrons/drivers/smoothie_drivers/types.py +16 -0
- opentrons/drivers/temp_deck/__init__.py +10 -0
- opentrons/drivers/temp_deck/abstract.py +54 -0
- opentrons/drivers/temp_deck/driver.py +197 -0
- opentrons/drivers/temp_deck/simulator.py +57 -0
- opentrons/drivers/thermocycler/__init__.py +12 -0
- opentrons/drivers/thermocycler/abstract.py +99 -0
- opentrons/drivers/thermocycler/driver.py +395 -0
- opentrons/drivers/thermocycler/simulator.py +126 -0
- opentrons/drivers/types.py +107 -0
- opentrons/drivers/utils.py +222 -0
- opentrons/execute.py +742 -0
- opentrons/hardware_control/__init__.py +65 -0
- opentrons/hardware_control/__main__.py +77 -0
- opentrons/hardware_control/adapters.py +98 -0
- opentrons/hardware_control/api.py +1347 -0
- opentrons/hardware_control/backends/__init__.py +7 -0
- opentrons/hardware_control/backends/controller.py +400 -0
- opentrons/hardware_control/backends/errors.py +9 -0
- opentrons/hardware_control/backends/estop_state.py +164 -0
- opentrons/hardware_control/backends/flex_protocol.py +497 -0
- opentrons/hardware_control/backends/ot3controller.py +1930 -0
- opentrons/hardware_control/backends/ot3simulator.py +900 -0
- opentrons/hardware_control/backends/ot3utils.py +664 -0
- opentrons/hardware_control/backends/simulator.py +442 -0
- opentrons/hardware_control/backends/status_bar_state.py +240 -0
- opentrons/hardware_control/backends/subsystem_manager.py +431 -0
- opentrons/hardware_control/backends/tip_presence_manager.py +173 -0
- opentrons/hardware_control/backends/types.py +14 -0
- opentrons/hardware_control/constants.py +6 -0
- opentrons/hardware_control/dev_types.py +125 -0
- opentrons/hardware_control/emulation/__init__.py +0 -0
- opentrons/hardware_control/emulation/abstract_emulator.py +21 -0
- opentrons/hardware_control/emulation/app.py +56 -0
- opentrons/hardware_control/emulation/connection_handler.py +38 -0
- opentrons/hardware_control/emulation/heater_shaker.py +150 -0
- opentrons/hardware_control/emulation/magdeck.py +60 -0
- opentrons/hardware_control/emulation/module_server/__init__.py +8 -0
- opentrons/hardware_control/emulation/module_server/client.py +78 -0
- opentrons/hardware_control/emulation/module_server/helpers.py +130 -0
- opentrons/hardware_control/emulation/module_server/models.py +31 -0
- opentrons/hardware_control/emulation/module_server/server.py +110 -0
- opentrons/hardware_control/emulation/parser.py +74 -0
- opentrons/hardware_control/emulation/proxy.py +241 -0
- opentrons/hardware_control/emulation/run_emulator.py +68 -0
- opentrons/hardware_control/emulation/scripts/__init__.py +0 -0
- opentrons/hardware_control/emulation/scripts/run_app.py +54 -0
- opentrons/hardware_control/emulation/scripts/run_module_emulator.py +72 -0
- opentrons/hardware_control/emulation/scripts/run_smoothie.py +37 -0
- opentrons/hardware_control/emulation/settings.py +119 -0
- opentrons/hardware_control/emulation/simulations.py +133 -0
- opentrons/hardware_control/emulation/smoothie.py +192 -0
- opentrons/hardware_control/emulation/tempdeck.py +69 -0
- opentrons/hardware_control/emulation/thermocycler.py +128 -0
- opentrons/hardware_control/emulation/types.py +10 -0
- opentrons/hardware_control/emulation/util.py +38 -0
- opentrons/hardware_control/errors.py +43 -0
- opentrons/hardware_control/execution_manager.py +164 -0
- opentrons/hardware_control/instruments/__init__.py +5 -0
- opentrons/hardware_control/instruments/instrument_abc.py +39 -0
- opentrons/hardware_control/instruments/ot2/__init__.py +0 -0
- opentrons/hardware_control/instruments/ot2/instrument_calibration.py +152 -0
- opentrons/hardware_control/instruments/ot2/pipette.py +777 -0
- opentrons/hardware_control/instruments/ot2/pipette_handler.py +995 -0
- opentrons/hardware_control/instruments/ot3/__init__.py +0 -0
- opentrons/hardware_control/instruments/ot3/gripper.py +420 -0
- opentrons/hardware_control/instruments/ot3/gripper_handler.py +173 -0
- opentrons/hardware_control/instruments/ot3/instrument_calibration.py +214 -0
- opentrons/hardware_control/instruments/ot3/pipette.py +858 -0
- opentrons/hardware_control/instruments/ot3/pipette_handler.py +1030 -0
- opentrons/hardware_control/module_control.py +332 -0
- opentrons/hardware_control/modules/__init__.py +69 -0
- opentrons/hardware_control/modules/absorbance_reader.py +373 -0
- opentrons/hardware_control/modules/errors.py +7 -0
- opentrons/hardware_control/modules/flex_stacker.py +948 -0
- opentrons/hardware_control/modules/heater_shaker.py +426 -0
- opentrons/hardware_control/modules/lid_temp_status.py +35 -0
- opentrons/hardware_control/modules/magdeck.py +233 -0
- opentrons/hardware_control/modules/mod_abc.py +245 -0
- opentrons/hardware_control/modules/module_calibration.py +93 -0
- opentrons/hardware_control/modules/plate_temp_status.py +61 -0
- opentrons/hardware_control/modules/tempdeck.py +299 -0
- opentrons/hardware_control/modules/thermocycler.py +731 -0
- opentrons/hardware_control/modules/types.py +417 -0
- opentrons/hardware_control/modules/update.py +255 -0
- opentrons/hardware_control/modules/utils.py +73 -0
- opentrons/hardware_control/motion_utilities.py +318 -0
- opentrons/hardware_control/nozzle_manager.py +422 -0
- opentrons/hardware_control/ot3_calibration.py +1171 -0
- opentrons/hardware_control/ot3api.py +3227 -0
- opentrons/hardware_control/pause_manager.py +31 -0
- opentrons/hardware_control/poller.py +112 -0
- opentrons/hardware_control/protocols/__init__.py +106 -0
- opentrons/hardware_control/protocols/asyncio_configurable.py +11 -0
- opentrons/hardware_control/protocols/calibratable.py +45 -0
- opentrons/hardware_control/protocols/chassis_accessory_manager.py +90 -0
- opentrons/hardware_control/protocols/configurable.py +48 -0
- opentrons/hardware_control/protocols/event_sourcer.py +18 -0
- opentrons/hardware_control/protocols/execution_controllable.py +33 -0
- opentrons/hardware_control/protocols/flex_calibratable.py +96 -0
- opentrons/hardware_control/protocols/flex_instrument_configurer.py +52 -0
- opentrons/hardware_control/protocols/gripper_controller.py +55 -0
- opentrons/hardware_control/protocols/hardware_manager.py +51 -0
- opentrons/hardware_control/protocols/identifiable.py +16 -0
- opentrons/hardware_control/protocols/instrument_configurer.py +206 -0
- opentrons/hardware_control/protocols/liquid_handler.py +266 -0
- opentrons/hardware_control/protocols/module_provider.py +16 -0
- opentrons/hardware_control/protocols/motion_controller.py +243 -0
- opentrons/hardware_control/protocols/position_estimator.py +45 -0
- opentrons/hardware_control/protocols/simulatable.py +10 -0
- opentrons/hardware_control/protocols/stoppable.py +9 -0
- opentrons/hardware_control/protocols/types.py +27 -0
- opentrons/hardware_control/robot_calibration.py +224 -0
- opentrons/hardware_control/scripts/README.md +28 -0
- opentrons/hardware_control/scripts/__init__.py +1 -0
- opentrons/hardware_control/scripts/gripper_control.py +208 -0
- opentrons/hardware_control/scripts/ot3gripper +7 -0
- opentrons/hardware_control/scripts/ot3repl +7 -0
- opentrons/hardware_control/scripts/repl.py +187 -0
- opentrons/hardware_control/scripts/tc_control.py +97 -0
- opentrons/hardware_control/scripts/update_module_fw.py +274 -0
- opentrons/hardware_control/simulator_setup.py +260 -0
- opentrons/hardware_control/thread_manager.py +431 -0
- opentrons/hardware_control/threaded_async_lock.py +97 -0
- opentrons/hardware_control/types.py +792 -0
- opentrons/hardware_control/util.py +234 -0
- opentrons/legacy_broker.py +53 -0
- opentrons/legacy_commands/__init__.py +1 -0
- opentrons/legacy_commands/commands.py +483 -0
- opentrons/legacy_commands/helpers.py +153 -0
- opentrons/legacy_commands/module_commands.py +276 -0
- opentrons/legacy_commands/protocol_commands.py +54 -0
- opentrons/legacy_commands/publisher.py +155 -0
- opentrons/legacy_commands/robot_commands.py +51 -0
- opentrons/legacy_commands/types.py +1186 -0
- opentrons/motion_planning/__init__.py +32 -0
- opentrons/motion_planning/adjacent_slots_getters.py +168 -0
- opentrons/motion_planning/deck_conflict.py +501 -0
- opentrons/motion_planning/errors.py +35 -0
- opentrons/motion_planning/types.py +42 -0
- opentrons/motion_planning/waypoints.py +218 -0
- opentrons/ordered_set.py +138 -0
- opentrons/protocol_api/__init__.py +105 -0
- opentrons/protocol_api/_liquid.py +157 -0
- opentrons/protocol_api/_liquid_properties.py +814 -0
- opentrons/protocol_api/_nozzle_layout.py +31 -0
- opentrons/protocol_api/_parameter_context.py +300 -0
- opentrons/protocol_api/_parameters.py +31 -0
- opentrons/protocol_api/_transfer_liquid_validation.py +108 -0
- opentrons/protocol_api/_types.py +43 -0
- opentrons/protocol_api/config.py +23 -0
- opentrons/protocol_api/core/__init__.py +23 -0
- opentrons/protocol_api/core/common.py +33 -0
- opentrons/protocol_api/core/core_map.py +74 -0
- opentrons/protocol_api/core/engine/__init__.py +22 -0
- opentrons/protocol_api/core/engine/_default_labware_versions.py +179 -0
- opentrons/protocol_api/core/engine/deck_conflict.py +400 -0
- opentrons/protocol_api/core/engine/exceptions.py +19 -0
- opentrons/protocol_api/core/engine/instrument.py +2391 -0
- opentrons/protocol_api/core/engine/labware.py +238 -0
- opentrons/protocol_api/core/engine/load_labware_params.py +73 -0
- opentrons/protocol_api/core/engine/module_core.py +1027 -0
- opentrons/protocol_api/core/engine/overlap_versions.py +20 -0
- opentrons/protocol_api/core/engine/pipette_movement_conflict.py +358 -0
- opentrons/protocol_api/core/engine/point_calculations.py +64 -0
- opentrons/protocol_api/core/engine/protocol.py +1153 -0
- opentrons/protocol_api/core/engine/robot.py +139 -0
- opentrons/protocol_api/core/engine/stringify.py +74 -0
- opentrons/protocol_api/core/engine/transfer_components_executor.py +1006 -0
- opentrons/protocol_api/core/engine/well.py +241 -0
- opentrons/protocol_api/core/instrument.py +459 -0
- opentrons/protocol_api/core/labware.py +151 -0
- opentrons/protocol_api/core/legacy/__init__.py +11 -0
- opentrons/protocol_api/core/legacy/_labware_geometry.py +37 -0
- opentrons/protocol_api/core/legacy/deck.py +369 -0
- opentrons/protocol_api/core/legacy/labware_offset_provider.py +108 -0
- opentrons/protocol_api/core/legacy/legacy_instrument_core.py +709 -0
- opentrons/protocol_api/core/legacy/legacy_labware_core.py +235 -0
- opentrons/protocol_api/core/legacy/legacy_module_core.py +592 -0
- opentrons/protocol_api/core/legacy/legacy_protocol_core.py +612 -0
- opentrons/protocol_api/core/legacy/legacy_well_core.py +162 -0
- opentrons/protocol_api/core/legacy/load_info.py +67 -0
- opentrons/protocol_api/core/legacy/module_geometry.py +547 -0
- opentrons/protocol_api/core/legacy/well_geometry.py +148 -0
- opentrons/protocol_api/core/legacy_simulator/__init__.py +16 -0
- opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +624 -0
- opentrons/protocol_api/core/legacy_simulator/legacy_protocol_core.py +85 -0
- opentrons/protocol_api/core/module.py +484 -0
- opentrons/protocol_api/core/protocol.py +311 -0
- opentrons/protocol_api/core/robot.py +51 -0
- opentrons/protocol_api/core/well.py +116 -0
- opentrons/protocol_api/core/well_grid.py +45 -0
- opentrons/protocol_api/create_protocol_context.py +177 -0
- opentrons/protocol_api/deck.py +223 -0
- opentrons/protocol_api/disposal_locations.py +244 -0
- opentrons/protocol_api/instrument_context.py +3272 -0
- opentrons/protocol_api/labware.py +1579 -0
- opentrons/protocol_api/module_contexts.py +1447 -0
- opentrons/protocol_api/module_validation_and_errors.py +61 -0
- opentrons/protocol_api/protocol_context.py +1688 -0
- opentrons/protocol_api/robot_context.py +303 -0
- opentrons/protocol_api/validation.py +761 -0
- opentrons/protocol_engine/__init__.py +155 -0
- opentrons/protocol_engine/actions/__init__.py +65 -0
- opentrons/protocol_engine/actions/action_dispatcher.py +30 -0
- opentrons/protocol_engine/actions/action_handler.py +13 -0
- opentrons/protocol_engine/actions/actions.py +302 -0
- opentrons/protocol_engine/actions/get_state_update.py +38 -0
- opentrons/protocol_engine/clients/__init__.py +5 -0
- opentrons/protocol_engine/clients/sync_client.py +174 -0
- opentrons/protocol_engine/clients/transports.py +197 -0
- opentrons/protocol_engine/commands/__init__.py +757 -0
- opentrons/protocol_engine/commands/absorbance_reader/__init__.py +61 -0
- opentrons/protocol_engine/commands/absorbance_reader/close_lid.py +154 -0
- opentrons/protocol_engine/commands/absorbance_reader/common.py +6 -0
- opentrons/protocol_engine/commands/absorbance_reader/initialize.py +151 -0
- opentrons/protocol_engine/commands/absorbance_reader/open_lid.py +154 -0
- opentrons/protocol_engine/commands/absorbance_reader/read.py +226 -0
- opentrons/protocol_engine/commands/air_gap_in_place.py +162 -0
- opentrons/protocol_engine/commands/aspirate.py +244 -0
- opentrons/protocol_engine/commands/aspirate_in_place.py +184 -0
- opentrons/protocol_engine/commands/aspirate_while_tracking.py +211 -0
- opentrons/protocol_engine/commands/blow_out.py +146 -0
- opentrons/protocol_engine/commands/blow_out_in_place.py +119 -0
- opentrons/protocol_engine/commands/calibration/__init__.py +60 -0
- opentrons/protocol_engine/commands/calibration/calibrate_gripper.py +166 -0
- opentrons/protocol_engine/commands/calibration/calibrate_module.py +117 -0
- opentrons/protocol_engine/commands/calibration/calibrate_pipette.py +96 -0
- opentrons/protocol_engine/commands/calibration/move_to_maintenance_position.py +156 -0
- opentrons/protocol_engine/commands/command.py +308 -0
- opentrons/protocol_engine/commands/command_unions.py +974 -0
- opentrons/protocol_engine/commands/comment.py +57 -0
- opentrons/protocol_engine/commands/configure_for_volume.py +108 -0
- opentrons/protocol_engine/commands/configure_nozzle_layout.py +115 -0
- opentrons/protocol_engine/commands/custom.py +67 -0
- opentrons/protocol_engine/commands/dispense.py +194 -0
- opentrons/protocol_engine/commands/dispense_in_place.py +179 -0
- opentrons/protocol_engine/commands/dispense_while_tracking.py +204 -0
- opentrons/protocol_engine/commands/drop_tip.py +232 -0
- opentrons/protocol_engine/commands/drop_tip_in_place.py +205 -0
- opentrons/protocol_engine/commands/flex_stacker/__init__.py +64 -0
- opentrons/protocol_engine/commands/flex_stacker/common.py +900 -0
- opentrons/protocol_engine/commands/flex_stacker/empty.py +293 -0
- opentrons/protocol_engine/commands/flex_stacker/fill.py +281 -0
- opentrons/protocol_engine/commands/flex_stacker/retrieve.py +339 -0
- opentrons/protocol_engine/commands/flex_stacker/set_stored_labware.py +328 -0
- opentrons/protocol_engine/commands/flex_stacker/store.py +339 -0
- opentrons/protocol_engine/commands/generate_command_schema.py +61 -0
- opentrons/protocol_engine/commands/get_next_tip.py +134 -0
- opentrons/protocol_engine/commands/get_tip_presence.py +87 -0
- opentrons/protocol_engine/commands/hash_command_params.py +38 -0
- opentrons/protocol_engine/commands/heater_shaker/__init__.py +102 -0
- opentrons/protocol_engine/commands/heater_shaker/close_labware_latch.py +83 -0
- opentrons/protocol_engine/commands/heater_shaker/deactivate_heater.py +82 -0
- opentrons/protocol_engine/commands/heater_shaker/deactivate_shaker.py +84 -0
- opentrons/protocol_engine/commands/heater_shaker/open_labware_latch.py +110 -0
- opentrons/protocol_engine/commands/heater_shaker/set_and_wait_for_shake_speed.py +125 -0
- opentrons/protocol_engine/commands/heater_shaker/set_target_temperature.py +90 -0
- opentrons/protocol_engine/commands/heater_shaker/wait_for_temperature.py +102 -0
- opentrons/protocol_engine/commands/home.py +100 -0
- opentrons/protocol_engine/commands/identify_module.py +86 -0
- opentrons/protocol_engine/commands/labware_handling_common.py +29 -0
- opentrons/protocol_engine/commands/liquid_probe.py +464 -0
- opentrons/protocol_engine/commands/load_labware.py +210 -0
- opentrons/protocol_engine/commands/load_lid.py +154 -0
- opentrons/protocol_engine/commands/load_lid_stack.py +272 -0
- opentrons/protocol_engine/commands/load_liquid.py +95 -0
- opentrons/protocol_engine/commands/load_liquid_class.py +144 -0
- opentrons/protocol_engine/commands/load_module.py +223 -0
- opentrons/protocol_engine/commands/load_pipette.py +167 -0
- opentrons/protocol_engine/commands/magnetic_module/__init__.py +32 -0
- opentrons/protocol_engine/commands/magnetic_module/disengage.py +97 -0
- opentrons/protocol_engine/commands/magnetic_module/engage.py +119 -0
- opentrons/protocol_engine/commands/move_labware.py +546 -0
- opentrons/protocol_engine/commands/move_relative.py +102 -0
- opentrons/protocol_engine/commands/move_to_addressable_area.py +176 -0
- opentrons/protocol_engine/commands/move_to_addressable_area_for_drop_tip.py +198 -0
- opentrons/protocol_engine/commands/move_to_coordinates.py +107 -0
- opentrons/protocol_engine/commands/move_to_well.py +119 -0
- opentrons/protocol_engine/commands/movement_common.py +338 -0
- opentrons/protocol_engine/commands/pick_up_tip.py +241 -0
- opentrons/protocol_engine/commands/pipetting_common.py +443 -0
- opentrons/protocol_engine/commands/prepare_to_aspirate.py +121 -0
- opentrons/protocol_engine/commands/pressure_dispense.py +155 -0
- opentrons/protocol_engine/commands/reload_labware.py +90 -0
- opentrons/protocol_engine/commands/retract_axis.py +75 -0
- opentrons/protocol_engine/commands/robot/__init__.py +70 -0
- opentrons/protocol_engine/commands/robot/close_gripper_jaw.py +96 -0
- opentrons/protocol_engine/commands/robot/common.py +18 -0
- opentrons/protocol_engine/commands/robot/move_axes_relative.py +101 -0
- opentrons/protocol_engine/commands/robot/move_axes_to.py +100 -0
- opentrons/protocol_engine/commands/robot/move_to.py +94 -0
- opentrons/protocol_engine/commands/robot/open_gripper_jaw.py +86 -0
- opentrons/protocol_engine/commands/save_position.py +109 -0
- opentrons/protocol_engine/commands/seal_pipette_to_tip.py +353 -0
- opentrons/protocol_engine/commands/set_rail_lights.py +67 -0
- opentrons/protocol_engine/commands/set_status_bar.py +89 -0
- opentrons/protocol_engine/commands/temperature_module/__init__.py +46 -0
- opentrons/protocol_engine/commands/temperature_module/deactivate.py +86 -0
- opentrons/protocol_engine/commands/temperature_module/set_target_temperature.py +97 -0
- opentrons/protocol_engine/commands/temperature_module/wait_for_temperature.py +104 -0
- opentrons/protocol_engine/commands/thermocycler/__init__.py +152 -0
- opentrons/protocol_engine/commands/thermocycler/close_lid.py +87 -0
- opentrons/protocol_engine/commands/thermocycler/deactivate_block.py +80 -0
- opentrons/protocol_engine/commands/thermocycler/deactivate_lid.py +80 -0
- opentrons/protocol_engine/commands/thermocycler/open_lid.py +87 -0
- opentrons/protocol_engine/commands/thermocycler/run_extended_profile.py +171 -0
- opentrons/protocol_engine/commands/thermocycler/run_profile.py +124 -0
- opentrons/protocol_engine/commands/thermocycler/set_target_block_temperature.py +140 -0
- opentrons/protocol_engine/commands/thermocycler/set_target_lid_temperature.py +100 -0
- opentrons/protocol_engine/commands/thermocycler/wait_for_block_temperature.py +93 -0
- opentrons/protocol_engine/commands/thermocycler/wait_for_lid_temperature.py +89 -0
- opentrons/protocol_engine/commands/touch_tip.py +189 -0
- opentrons/protocol_engine/commands/unsafe/__init__.py +161 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_blow_out_in_place.py +100 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_drop_tip_in_place.py +121 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_engage_axes.py +82 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_place_labware.py +208 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_stacker_close_latch.py +94 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_stacker_manual_retrieve.py +295 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_stacker_open_latch.py +91 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_stacker_prepare_shuttle.py +136 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_ungrip_labware.py +77 -0
- opentrons/protocol_engine/commands/unsafe/update_position_estimators.py +90 -0
- opentrons/protocol_engine/commands/unseal_pipette_from_tip.py +153 -0
- opentrons/protocol_engine/commands/verify_tip_presence.py +100 -0
- opentrons/protocol_engine/commands/wait_for_duration.py +76 -0
- opentrons/protocol_engine/commands/wait_for_resume.py +75 -0
- opentrons/protocol_engine/create_protocol_engine.py +193 -0
- opentrons/protocol_engine/engine_support.py +28 -0
- opentrons/protocol_engine/error_recovery_policy.py +81 -0
- opentrons/protocol_engine/errors/__init__.py +191 -0
- opentrons/protocol_engine/errors/error_occurrence.py +182 -0
- opentrons/protocol_engine/errors/exceptions.py +1308 -0
- opentrons/protocol_engine/execution/__init__.py +50 -0
- opentrons/protocol_engine/execution/command_executor.py +216 -0
- opentrons/protocol_engine/execution/create_queue_worker.py +102 -0
- opentrons/protocol_engine/execution/door_watcher.py +119 -0
- opentrons/protocol_engine/execution/equipment.py +819 -0
- opentrons/protocol_engine/execution/error_recovery_hardware_state_synchronizer.py +101 -0
- opentrons/protocol_engine/execution/gantry_mover.py +686 -0
- opentrons/protocol_engine/execution/hardware_stopper.py +147 -0
- opentrons/protocol_engine/execution/heater_shaker_movement_flagger.py +207 -0
- opentrons/protocol_engine/execution/labware_movement.py +297 -0
- opentrons/protocol_engine/execution/movement.py +350 -0
- opentrons/protocol_engine/execution/pipetting.py +607 -0
- opentrons/protocol_engine/execution/queue_worker.py +86 -0
- opentrons/protocol_engine/execution/rail_lights.py +25 -0
- opentrons/protocol_engine/execution/run_control.py +33 -0
- opentrons/protocol_engine/execution/status_bar.py +34 -0
- opentrons/protocol_engine/execution/thermocycler_movement_flagger.py +188 -0
- opentrons/protocol_engine/execution/thermocycler_plate_lifter.py +81 -0
- opentrons/protocol_engine/execution/tip_handler.py +550 -0
- opentrons/protocol_engine/labware_offset_standardization.py +194 -0
- opentrons/protocol_engine/notes/__init__.py +17 -0
- opentrons/protocol_engine/notes/notes.py +59 -0
- opentrons/protocol_engine/plugins.py +104 -0
- opentrons/protocol_engine/protocol_engine.py +683 -0
- opentrons/protocol_engine/resources/__init__.py +26 -0
- opentrons/protocol_engine/resources/deck_configuration_provider.py +232 -0
- opentrons/protocol_engine/resources/deck_data_provider.py +94 -0
- opentrons/protocol_engine/resources/file_provider.py +161 -0
- opentrons/protocol_engine/resources/fixture_validation.py +68 -0
- opentrons/protocol_engine/resources/labware_data_provider.py +106 -0
- opentrons/protocol_engine/resources/labware_validation.py +73 -0
- opentrons/protocol_engine/resources/model_utils.py +32 -0
- opentrons/protocol_engine/resources/module_data_provider.py +44 -0
- opentrons/protocol_engine/resources/ot3_validation.py +21 -0
- opentrons/protocol_engine/resources/pipette_data_provider.py +379 -0
- opentrons/protocol_engine/slot_standardization.py +128 -0
- opentrons/protocol_engine/state/__init__.py +1 -0
- opentrons/protocol_engine/state/_abstract_store.py +27 -0
- opentrons/protocol_engine/state/_axis_aligned_bounding_box.py +50 -0
- opentrons/protocol_engine/state/_labware_origin_math.py +636 -0
- opentrons/protocol_engine/state/_move_types.py +83 -0
- opentrons/protocol_engine/state/_well_math.py +193 -0
- opentrons/protocol_engine/state/addressable_areas.py +699 -0
- opentrons/protocol_engine/state/command_history.py +309 -0
- opentrons/protocol_engine/state/commands.py +1164 -0
- opentrons/protocol_engine/state/config.py +39 -0
- opentrons/protocol_engine/state/files.py +57 -0
- opentrons/protocol_engine/state/fluid_stack.py +138 -0
- opentrons/protocol_engine/state/geometry.py +2408 -0
- opentrons/protocol_engine/state/inner_well_math_utils.py +548 -0
- opentrons/protocol_engine/state/labware.py +1432 -0
- opentrons/protocol_engine/state/liquid_classes.py +82 -0
- opentrons/protocol_engine/state/liquids.py +73 -0
- opentrons/protocol_engine/state/module_substates/__init__.py +45 -0
- opentrons/protocol_engine/state/module_substates/absorbance_reader_substate.py +35 -0
- opentrons/protocol_engine/state/module_substates/flex_stacker_substate.py +112 -0
- opentrons/protocol_engine/state/module_substates/heater_shaker_module_substate.py +115 -0
- opentrons/protocol_engine/state/module_substates/magnetic_block_substate.py +17 -0
- opentrons/protocol_engine/state/module_substates/magnetic_module_substate.py +65 -0
- opentrons/protocol_engine/state/module_substates/temperature_module_substate.py +67 -0
- opentrons/protocol_engine/state/module_substates/thermocycler_module_substate.py +163 -0
- opentrons/protocol_engine/state/modules.py +1515 -0
- opentrons/protocol_engine/state/motion.py +373 -0
- opentrons/protocol_engine/state/pipettes.py +905 -0
- opentrons/protocol_engine/state/state.py +421 -0
- opentrons/protocol_engine/state/state_summary.py +36 -0
- opentrons/protocol_engine/state/tips.py +420 -0
- opentrons/protocol_engine/state/update_types.py +904 -0
- opentrons/protocol_engine/state/wells.py +290 -0
- opentrons/protocol_engine/types/__init__.py +310 -0
- opentrons/protocol_engine/types/automatic_tip_selection.py +39 -0
- opentrons/protocol_engine/types/command_annotations.py +53 -0
- opentrons/protocol_engine/types/deck_configuration.py +81 -0
- opentrons/protocol_engine/types/execution.py +96 -0
- opentrons/protocol_engine/types/hardware_passthrough.py +25 -0
- opentrons/protocol_engine/types/instrument.py +47 -0
- opentrons/protocol_engine/types/instrument_sensors.py +47 -0
- opentrons/protocol_engine/types/labware.py +131 -0
- opentrons/protocol_engine/types/labware_movement.py +22 -0
- opentrons/protocol_engine/types/labware_offset_location.py +111 -0
- opentrons/protocol_engine/types/labware_offset_vector.py +16 -0
- opentrons/protocol_engine/types/liquid.py +40 -0
- opentrons/protocol_engine/types/liquid_class.py +59 -0
- opentrons/protocol_engine/types/liquid_handling.py +13 -0
- opentrons/protocol_engine/types/liquid_level_detection.py +191 -0
- opentrons/protocol_engine/types/location.py +194 -0
- opentrons/protocol_engine/types/module.py +310 -0
- opentrons/protocol_engine/types/partial_tip_configuration.py +76 -0
- opentrons/protocol_engine/types/run_time_parameters.py +133 -0
- opentrons/protocol_engine/types/tip.py +18 -0
- opentrons/protocol_engine/types/util.py +21 -0
- opentrons/protocol_engine/types/well_position.py +124 -0
- opentrons/protocol_reader/__init__.py +37 -0
- opentrons/protocol_reader/extract_labware_definitions.py +66 -0
- opentrons/protocol_reader/file_format_validator.py +152 -0
- opentrons/protocol_reader/file_hasher.py +27 -0
- opentrons/protocol_reader/file_identifier.py +284 -0
- opentrons/protocol_reader/file_reader_writer.py +90 -0
- opentrons/protocol_reader/input_file.py +16 -0
- opentrons/protocol_reader/protocol_files_invalid_error.py +6 -0
- opentrons/protocol_reader/protocol_reader.py +188 -0
- opentrons/protocol_reader/protocol_source.py +124 -0
- opentrons/protocol_reader/role_analyzer.py +86 -0
- opentrons/protocol_runner/__init__.py +26 -0
- opentrons/protocol_runner/create_simulating_orchestrator.py +118 -0
- opentrons/protocol_runner/json_file_reader.py +55 -0
- opentrons/protocol_runner/json_translator.py +314 -0
- opentrons/protocol_runner/legacy_command_mapper.py +852 -0
- opentrons/protocol_runner/legacy_context_plugin.py +116 -0
- opentrons/protocol_runner/protocol_runner.py +530 -0
- opentrons/protocol_runner/python_protocol_wrappers.py +179 -0
- opentrons/protocol_runner/run_orchestrator.py +496 -0
- opentrons/protocol_runner/task_queue.py +95 -0
- opentrons/protocols/__init__.py +6 -0
- opentrons/protocols/advanced_control/__init__.py +0 -0
- opentrons/protocols/advanced_control/common.py +38 -0
- opentrons/protocols/advanced_control/mix.py +60 -0
- opentrons/protocols/advanced_control/transfers/__init__.py +0 -0
- opentrons/protocols/advanced_control/transfers/common.py +180 -0
- opentrons/protocols/advanced_control/transfers/transfer.py +972 -0
- opentrons/protocols/advanced_control/transfers/transfer_liquid_utils.py +231 -0
- opentrons/protocols/api_support/__init__.py +0 -0
- opentrons/protocols/api_support/constants.py +8 -0
- opentrons/protocols/api_support/deck_type.py +110 -0
- opentrons/protocols/api_support/definitions.py +18 -0
- opentrons/protocols/api_support/instrument.py +151 -0
- opentrons/protocols/api_support/labware_like.py +233 -0
- opentrons/protocols/api_support/tip_tracker.py +175 -0
- opentrons/protocols/api_support/types.py +32 -0
- opentrons/protocols/api_support/util.py +403 -0
- opentrons/protocols/bundle.py +89 -0
- opentrons/protocols/duration/__init__.py +4 -0
- opentrons/protocols/duration/errors.py +5 -0
- opentrons/protocols/duration/estimator.py +628 -0
- opentrons/protocols/execution/__init__.py +0 -0
- opentrons/protocols/execution/dev_types.py +181 -0
- opentrons/protocols/execution/errors.py +40 -0
- opentrons/protocols/execution/execute.py +84 -0
- opentrons/protocols/execution/execute_json_v3.py +275 -0
- opentrons/protocols/execution/execute_json_v4.py +359 -0
- opentrons/protocols/execution/execute_json_v5.py +28 -0
- opentrons/protocols/execution/execute_python.py +169 -0
- opentrons/protocols/execution/json_dispatchers.py +87 -0
- opentrons/protocols/execution/types.py +7 -0
- opentrons/protocols/geometry/__init__.py +0 -0
- opentrons/protocols/geometry/planning.py +297 -0
- opentrons/protocols/labware.py +312 -0
- opentrons/protocols/models/__init__.py +0 -0
- opentrons/protocols/models/json_protocol.py +679 -0
- opentrons/protocols/parameters/__init__.py +0 -0
- opentrons/protocols/parameters/csv_parameter_definition.py +77 -0
- opentrons/protocols/parameters/csv_parameter_interface.py +96 -0
- opentrons/protocols/parameters/exceptions.py +34 -0
- opentrons/protocols/parameters/parameter_definition.py +272 -0
- opentrons/protocols/parameters/types.py +17 -0
- opentrons/protocols/parameters/validation.py +267 -0
- opentrons/protocols/parse.py +671 -0
- opentrons/protocols/types.py +159 -0
- opentrons/py.typed +0 -0
- opentrons/resources/scripts/lpc21isp +0 -0
- opentrons/resources/smoothie-edge-8414642.hex +23010 -0
- opentrons/simulate.py +1065 -0
- opentrons/system/__init__.py +6 -0
- opentrons/system/camera.py +51 -0
- opentrons/system/log_control.py +59 -0
- opentrons/system/nmcli.py +856 -0
- opentrons/system/resin.py +24 -0
- opentrons/system/smoothie_update.py +15 -0
- opentrons/system/wifi.py +204 -0
- opentrons/tools/__init__.py +0 -0
- opentrons/tools/args_handler.py +22 -0
- opentrons/tools/write_pipette_memory.py +157 -0
- opentrons/types.py +618 -0
- opentrons/util/__init__.py +1 -0
- opentrons/util/async_helpers.py +166 -0
- opentrons/util/broker.py +84 -0
- opentrons/util/change_notifier.py +47 -0
- opentrons/util/entrypoint_util.py +278 -0
- opentrons/util/get_union_elements.py +26 -0
- opentrons/util/helpers.py +6 -0
- opentrons/util/linal.py +178 -0
- opentrons/util/logging_config.py +265 -0
- opentrons/util/logging_queue_handler.py +61 -0
- opentrons/util/performance_helpers.py +157 -0
- opentrons-8.6.0.dist-info/METADATA +37 -0
- opentrons-8.6.0.dist-info/RECORD +601 -0
- opentrons-8.6.0.dist-info/WHEEL +4 -0
- opentrons-8.6.0.dist-info/entry_points.txt +3 -0
- opentrons-8.6.0.dist-info/licenses/LICENSE +202 -0
|
@@ -0,0 +1,900 @@
|
|
|
1
|
+
"""Common flex stacker base models."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from typing import Literal, TYPE_CHECKING, Sequence, Iterator
|
|
6
|
+
from typing_extensions import TypedDict
|
|
7
|
+
from textwrap import dedent
|
|
8
|
+
|
|
9
|
+
from opentrons_shared_data.errors import ErrorCodes
|
|
10
|
+
from opentrons_shared_data.errors.exceptions import CommandPreconditionViolated
|
|
11
|
+
from opentrons_shared_data.labware.labware_definition import LabwareDefinition
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
from ...errors import ErrorOccurrence
|
|
15
|
+
from ...types import (
|
|
16
|
+
StackerStoredLabwareGroup,
|
|
17
|
+
InStackerHopperLocation,
|
|
18
|
+
LoadedLabware,
|
|
19
|
+
OFF_DECK_LOCATION,
|
|
20
|
+
OnLabwareLocation,
|
|
21
|
+
OnLabwareLocationSequenceComponent,
|
|
22
|
+
LabwareLocationSequence,
|
|
23
|
+
LabwareLocation,
|
|
24
|
+
LabwareOffsetLocationSequence,
|
|
25
|
+
OnLabwareOffsetLocationSequenceComponent,
|
|
26
|
+
ModuleLocation,
|
|
27
|
+
)
|
|
28
|
+
from ...state.update_types import StateUpdate
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
if TYPE_CHECKING:
|
|
32
|
+
from opentrons.protocol_engine.execution import EquipmentHandler
|
|
33
|
+
from opentrons.protocol_engine.state.state import StateView
|
|
34
|
+
from opentrons.protocol_engine.resources import ModelUtils
|
|
35
|
+
from opentrons.protocol_engine.execution.equipment import LoadedLabwarePoolData
|
|
36
|
+
from opentrons.protocol_engine.state.module_substates import FlexStackerSubState
|
|
37
|
+
|
|
38
|
+
INITIAL_COUNT_DESCRIPTION = dedent(
|
|
39
|
+
"""\
|
|
40
|
+
The number of labware that should be initially stored in the stacker. This number will be silently clamped to
|
|
41
|
+
the maximum number of labware that will fit; do not rely on the parameter to know how many labware are in the stacker.
|
|
42
|
+
|
|
43
|
+
This field works with the initialStoredLabware field in a complex way.
|
|
44
|
+
|
|
45
|
+
The following must be true for initialCount to be valid:
|
|
46
|
+
- It is not specified, and initialStoredLabware is not specified, in which case the stacker will start empty
|
|
47
|
+
- It is not specified, and initialStoredLabware is specified, in which case the contents of the stacker are entirely
|
|
48
|
+
determined by initialStoredLabware.
|
|
49
|
+
- It is specified, and initialStoredLabware is specified, in which case the length of initialStoredLabware must be
|
|
50
|
+
exactly initialCount, and the contents of the stacker will be determined by initialStoredLabware.
|
|
51
|
+
"""
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
INITIAL_STORED_LABWARE_DESCRIPTION = dedent(
|
|
55
|
+
"""\
|
|
56
|
+
A list of IDs that should be initially stored in the stacker.
|
|
57
|
+
|
|
58
|
+
If specified, the first element of the list is the labware on the physical bottom that will be the first labware retrieved.
|
|
59
|
+
|
|
60
|
+
This is a complex field. The following must be true for the field to be valid:
|
|
61
|
+
- If this field is specified, then either initialCount must not be specified, or this field must have exactly initalCount elements
|
|
62
|
+
- Each element must contain an id for each corresponding labware details field (i.e. if lidLabware is specified, each element must have
|
|
63
|
+
a lidLabwareId) and must not contain an id for a corresponding labware details field that is not specified (i.e., if adapterLabware
|
|
64
|
+
is not specified, each element must not have an adapterLabwareId).
|
|
65
|
+
|
|
66
|
+
The behavior of the command depends on the values of both this field and initialCount.
|
|
67
|
+
- If this field is not specified and initialCount is not specified, the command will create the maximum number of labware objects
|
|
68
|
+
the stacker can hold according to the labware pool specifications.
|
|
69
|
+
- If this field is not specified and initialCount is specified to be 0, the command will create 0 labware objects and the stacker will be empty.
|
|
70
|
+
- If this field is not specified and initialCount is specified to be non-0, the command will create initialCount labware objects of
|
|
71
|
+
each specified labware type (primary, lid, and adapter), with appropriate positions, and arbitrary IDs, loaded into the stacker
|
|
72
|
+
- If this field is specified (and therefore initialCount is not specified or is specified to be the length of this field) then the
|
|
73
|
+
command will create labware objects with the IDs specified in this field and appropriate positions, loaded into the stacker.
|
|
74
|
+
|
|
75
|
+
Behavior is also different depending on whether the labware identified by ID in this field exist or not. Either all labware specified
|
|
76
|
+
in this field must exist, or all must not exist.
|
|
77
|
+
|
|
78
|
+
Further,
|
|
79
|
+
- If the labware exist, they must be of the same type as identified in the primaryLabware field.
|
|
80
|
+
- If the labware exist and the adapterLabware field is specified, each labware must be currently loaded on a labware of the same kind as
|
|
81
|
+
specified in the adapterLabware field, and that labware must be loaded off-deck
|
|
82
|
+
- If the labware exist and the adapterLabware field is not specified, each labware must be currently loaded off deck directly
|
|
83
|
+
- If the labware exist and the lidLabware field is specified, each labware must currently have a loaded lid of the same kind as specified
|
|
84
|
+
in the lidLabware field
|
|
85
|
+
- If the labware exist and the lidLabware field is not specified, each labware must not currently have a lid
|
|
86
|
+
- If the labware exist, they must have nothing loaded underneath them or above them other than what is mentioned above
|
|
87
|
+
|
|
88
|
+
If all the above are true, when this command executes the labware will be immediately moved into InStackerHopper. If any of the above
|
|
89
|
+
are not true, analysis will fail.
|
|
90
|
+
"""
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
class FailedLabware(TypedDict, total=False):
|
|
95
|
+
"""Holds the labware ID that would have been involved in a failed command."""
|
|
96
|
+
|
|
97
|
+
labwareId: str
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
class FlexStackerStallOrCollisionError(ErrorOccurrence):
|
|
101
|
+
"""Returned when the motor driver detects a stall."""
|
|
102
|
+
|
|
103
|
+
isDefined: bool = True
|
|
104
|
+
errorType: Literal["flexStackerStallOrCollision"] = "flexStackerStallOrCollision"
|
|
105
|
+
|
|
106
|
+
errorCode: str = ErrorCodes.STACKER_STALL_OR_COLLISION_DETECTED.value.code
|
|
107
|
+
detail: str = ErrorCodes.STACKER_STALL_OR_COLLISION_DETECTED.value.detail
|
|
108
|
+
|
|
109
|
+
errorInfo: FailedLabware
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
class FlexStackerShuttleError(ErrorOccurrence):
|
|
113
|
+
"""Returned when the Flex Stacker Shuttle is not in the correct location."""
|
|
114
|
+
|
|
115
|
+
isDefined: bool = True
|
|
116
|
+
errorType: Literal["flexStackerShuttleMissing"] = "flexStackerShuttleMissing"
|
|
117
|
+
|
|
118
|
+
errorCode: str = ErrorCodes.STACKER_SHUTTLE_MISSING.value.code
|
|
119
|
+
detail: str = ErrorCodes.STACKER_SHUTTLE_MISSING.value.detail
|
|
120
|
+
|
|
121
|
+
errorInfo: FailedLabware
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
class FlexStackerHopperError(ErrorOccurrence):
|
|
125
|
+
"""Returned when the Flex Stacker hopper labware presence sensor raises an error."""
|
|
126
|
+
|
|
127
|
+
isDefined: bool = True
|
|
128
|
+
errorType: Literal[
|
|
129
|
+
"flexStackerHopperLabwareFailed"
|
|
130
|
+
] = "flexStackerHopperLabwareFailed"
|
|
131
|
+
|
|
132
|
+
errorCode: str = ErrorCodes.STACKER_HOPPER_LABWARE_FAILED.value.code
|
|
133
|
+
detail: str = ErrorCodes.STACKER_HOPPER_LABWARE_FAILED.value.detail
|
|
134
|
+
|
|
135
|
+
errorInfo: FailedLabware
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
class FlexStackerLabwareRetrieveError(ErrorOccurrence):
|
|
139
|
+
"""Returned when the labware was not able to get to the shuttle."""
|
|
140
|
+
|
|
141
|
+
isDefined: bool = True
|
|
142
|
+
errorType: Literal[
|
|
143
|
+
"flexStackerLabwareRetrieveFailed"
|
|
144
|
+
] = "flexStackerLabwareRetrieveFailed"
|
|
145
|
+
|
|
146
|
+
errorCode: str = ErrorCodes.STACKER_SHUTTLE_LABWARE_FAILED.value.code
|
|
147
|
+
detail: str = ErrorCodes.STACKER_SHUTTLE_LABWARE_FAILED.value.detail
|
|
148
|
+
errorInfo: FailedLabware
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
class FlexStackerShuttleOccupiedError(ErrorOccurrence):
|
|
152
|
+
"""Returned when the Flex Stacker Shuttle is occupied when it shouldn't be."""
|
|
153
|
+
|
|
154
|
+
isDefined: bool = True
|
|
155
|
+
errorType: Literal["flexStackerShuttleOccupied"] = "flexStackerShuttleOccupied"
|
|
156
|
+
|
|
157
|
+
errorCode: str = ErrorCodes.STACKER_SHUTTLE_OCCUPIED.value.code
|
|
158
|
+
detail: str = ErrorCodes.STACKER_SHUTTLE_OCCUPIED.value.detail
|
|
159
|
+
errorInfo: FailedLabware
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
@dataclass
|
|
163
|
+
class _LabwareDefPair:
|
|
164
|
+
definition: LabwareDefinition
|
|
165
|
+
id: str
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
@dataclass
|
|
169
|
+
class _GroupWithDefs:
|
|
170
|
+
primary: _LabwareDefPair
|
|
171
|
+
adapter: _LabwareDefPair | None
|
|
172
|
+
lid: _LabwareDefPair | None
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
@dataclass
|
|
176
|
+
class LabwareWithLocationSequence:
|
|
177
|
+
"""Holds a labware id and location."""
|
|
178
|
+
|
|
179
|
+
labwareId: str
|
|
180
|
+
locationSequence: LabwareLocationSequence
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
@dataclass
|
|
184
|
+
class GroupWithLocationSequences:
|
|
185
|
+
"""Holds labware id and location for group components."""
|
|
186
|
+
|
|
187
|
+
primary: LabwareWithLocationSequence
|
|
188
|
+
adapter: LabwareWithLocationSequence | None
|
|
189
|
+
lid: LabwareWithLocationSequence | None
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def _labware_location_seq_for_primary(
|
|
193
|
+
group: StackerStoredLabwareGroup,
|
|
194
|
+
base: LabwareLocationSequence,
|
|
195
|
+
) -> LabwareWithLocationSequence:
|
|
196
|
+
if group.adapterLabwareId is not None:
|
|
197
|
+
return LabwareWithLocationSequence(
|
|
198
|
+
labwareId=group.primaryLabwareId,
|
|
199
|
+
locationSequence=(
|
|
200
|
+
[
|
|
201
|
+
OnLabwareLocationSequenceComponent(
|
|
202
|
+
labwareId=group.adapterLabwareId, lidId=None
|
|
203
|
+
)
|
|
204
|
+
]
|
|
205
|
+
+ base
|
|
206
|
+
),
|
|
207
|
+
)
|
|
208
|
+
else:
|
|
209
|
+
return LabwareWithLocationSequence(
|
|
210
|
+
labwareId=group.primaryLabwareId,
|
|
211
|
+
locationSequence=base,
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def _labware_location_seq_for_lid(
|
|
216
|
+
group: StackerStoredLabwareGroup,
|
|
217
|
+
base: LabwareLocationSequence,
|
|
218
|
+
) -> LabwareWithLocationSequence | None:
|
|
219
|
+
if group.lidLabwareId is None:
|
|
220
|
+
return None
|
|
221
|
+
elif group.adapterLabwareId is None:
|
|
222
|
+
return LabwareWithLocationSequence(
|
|
223
|
+
labwareId=group.lidLabwareId,
|
|
224
|
+
locationSequence=(
|
|
225
|
+
[
|
|
226
|
+
OnLabwareLocationSequenceComponent(
|
|
227
|
+
labwareId=group.primaryLabwareId, lidId=group.lidLabwareId
|
|
228
|
+
)
|
|
229
|
+
]
|
|
230
|
+
+ base
|
|
231
|
+
),
|
|
232
|
+
)
|
|
233
|
+
else:
|
|
234
|
+
return LabwareWithLocationSequence(
|
|
235
|
+
labwareId=group.lidLabwareId,
|
|
236
|
+
locationSequence=(
|
|
237
|
+
[
|
|
238
|
+
OnLabwareLocationSequenceComponent(
|
|
239
|
+
labwareId=group.primaryLabwareId, lidId=group.lidLabwareId
|
|
240
|
+
),
|
|
241
|
+
OnLabwareLocationSequenceComponent(
|
|
242
|
+
labwareId=group.adapterLabwareId, lidId=None
|
|
243
|
+
),
|
|
244
|
+
]
|
|
245
|
+
+ base
|
|
246
|
+
),
|
|
247
|
+
)
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
def _labware_location_seq_for_adapter(
|
|
251
|
+
group: StackerStoredLabwareGroup,
|
|
252
|
+
base: LabwareLocationSequence,
|
|
253
|
+
) -> LabwareWithLocationSequence | None:
|
|
254
|
+
if group.adapterLabwareId is None:
|
|
255
|
+
return None
|
|
256
|
+
return LabwareWithLocationSequence(
|
|
257
|
+
labwareId=group.adapterLabwareId, locationSequence=base
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
def labware_locations_for_group(
|
|
262
|
+
group: StackerStoredLabwareGroup, base: LabwareLocationSequence
|
|
263
|
+
) -> GroupWithLocationSequences:
|
|
264
|
+
"""Get the labware and location sequences bound together."""
|
|
265
|
+
return GroupWithLocationSequences(
|
|
266
|
+
primary=_labware_location_seq_for_primary(group, base),
|
|
267
|
+
adapter=_labware_location_seq_for_adapter(group, base),
|
|
268
|
+
lid=_labware_location_seq_for_lid(group, base),
|
|
269
|
+
)
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
def labware_location_base_sequence(
|
|
273
|
+
sample_group: StackerStoredLabwareGroup,
|
|
274
|
+
state_view: StateView,
|
|
275
|
+
default: LabwareLocationSequence,
|
|
276
|
+
) -> LabwareLocationSequence:
|
|
277
|
+
"""Get the base location sequence for a labware group, including loading the current location if it exists."""
|
|
278
|
+
first = (
|
|
279
|
+
sample_group.adapterLabwareId
|
|
280
|
+
if sample_group.adapterLabwareId is not None
|
|
281
|
+
else sample_group.primaryLabwareId
|
|
282
|
+
)
|
|
283
|
+
if state_view.labware.known(first):
|
|
284
|
+
return state_view.geometry.get_location_sequence(first)
|
|
285
|
+
return default
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
def primary_location_sequences(
|
|
289
|
+
groups: list[GroupWithLocationSequences],
|
|
290
|
+
) -> list[LabwareLocationSequence]:
|
|
291
|
+
"""Collate primary location sequences from lists of labware-plus-location."""
|
|
292
|
+
return [primary_location_sequence(group) for group in groups]
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
def primary_location_sequence(
|
|
296
|
+
group: GroupWithLocationSequences,
|
|
297
|
+
) -> LabwareLocationSequence:
|
|
298
|
+
"""Get the location sequence for the primary labware."""
|
|
299
|
+
return group.primary.locationSequence
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
def adapter_location_sequences(
|
|
303
|
+
groups: list[GroupWithLocationSequences],
|
|
304
|
+
) -> list[LabwareLocationSequence] | None:
|
|
305
|
+
"""Collate adapter location sequences from lists of labware-plus-location."""
|
|
306
|
+
|
|
307
|
+
def _yield_adapters(
|
|
308
|
+
groups: list[GroupWithLocationSequences],
|
|
309
|
+
) -> Iterator[LabwareLocationSequence]:
|
|
310
|
+
for group in groups:
|
|
311
|
+
seq = adapter_location_sequence(group)
|
|
312
|
+
if seq is None:
|
|
313
|
+
continue
|
|
314
|
+
else:
|
|
315
|
+
yield seq
|
|
316
|
+
|
|
317
|
+
adapter_seqs = list(_yield_adapters(groups))
|
|
318
|
+
if len(adapter_seqs) != len(groups):
|
|
319
|
+
return None
|
|
320
|
+
return adapter_seqs
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
def adapter_location_sequences_with_default(
|
|
324
|
+
groups: list[GroupWithLocationSequences], adapter_def: LabwareDefinition | None
|
|
325
|
+
) -> list[LabwareLocationSequence] | None:
|
|
326
|
+
"""Collate adapter location sequences unless there is no adapter."""
|
|
327
|
+
if adapter_def is None:
|
|
328
|
+
return None
|
|
329
|
+
else:
|
|
330
|
+
return adapter_location_sequences(groups)
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
def adapter_location_sequence(
|
|
334
|
+
group: GroupWithLocationSequences,
|
|
335
|
+
) -> LabwareLocationSequence | None:
|
|
336
|
+
"""Get the adapter location sequence from a group."""
|
|
337
|
+
if group.adapter is None:
|
|
338
|
+
return None
|
|
339
|
+
return group.adapter.locationSequence
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
def lid_location_sequences(
|
|
343
|
+
groups: list[GroupWithLocationSequences],
|
|
344
|
+
) -> list[LabwareLocationSequence] | None:
|
|
345
|
+
"""Collate lid location sequences from lists of labware-plus-location."""
|
|
346
|
+
|
|
347
|
+
def _yield_lids(
|
|
348
|
+
groups: list[GroupWithLocationSequences],
|
|
349
|
+
) -> Iterator[LabwareLocationSequence]:
|
|
350
|
+
for group in groups:
|
|
351
|
+
seq = lid_location_sequence(group)
|
|
352
|
+
if seq is None:
|
|
353
|
+
continue
|
|
354
|
+
else:
|
|
355
|
+
yield seq
|
|
356
|
+
|
|
357
|
+
lid_seqs = list(_yield_lids(groups))
|
|
358
|
+
if len(lid_seqs) != len(groups):
|
|
359
|
+
return None
|
|
360
|
+
return lid_seqs
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
def lid_location_sequences_with_default(
|
|
364
|
+
groups: list[GroupWithLocationSequences], lid_def: LabwareDefinition | None
|
|
365
|
+
) -> list[LabwareLocationSequence] | None:
|
|
366
|
+
"""Collate lid location sequences unless there is no lid."""
|
|
367
|
+
if lid_def is None:
|
|
368
|
+
return None
|
|
369
|
+
else:
|
|
370
|
+
return lid_location_sequences(groups)
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
def lid_location_sequence(
|
|
374
|
+
group: GroupWithLocationSequences,
|
|
375
|
+
) -> LabwareLocationSequence | None:
|
|
376
|
+
"""Get the lid location sequence from a group."""
|
|
377
|
+
if group.lid is None:
|
|
378
|
+
return None
|
|
379
|
+
return group.lid.locationSequence
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
def _check_one_preloaded_labware_known(
|
|
383
|
+
group: StackerStoredLabwareGroup, state_view: StateView
|
|
384
|
+
) -> bool:
|
|
385
|
+
"""Slightly tricky way to check if a labware group represents known labware.
|
|
386
|
+
|
|
387
|
+
Return true if all specified labware are known; false if all specified labware are not known; and
|
|
388
|
+
raise CommandPreconditionViolated if some specified labware are known and some are not.
|
|
389
|
+
"""
|
|
390
|
+
if state_view.labware.known(group.primaryLabwareId):
|
|
391
|
+
if group.lidLabwareId is not None and not state_view.labware.known(
|
|
392
|
+
group.lidLabwareId
|
|
393
|
+
):
|
|
394
|
+
raise CommandPreconditionViolated(
|
|
395
|
+
"Either all labware ids must be known or none must be, but primary and lid do not match"
|
|
396
|
+
)
|
|
397
|
+
if group.adapterLabwareId is not None and not state_view.labware.known(
|
|
398
|
+
group.adapterLabwareId
|
|
399
|
+
):
|
|
400
|
+
raise CommandPreconditionViolated(
|
|
401
|
+
"Either all labware ids must be known or none must be, but primary and adapter do not match"
|
|
402
|
+
)
|
|
403
|
+
|
|
404
|
+
return True
|
|
405
|
+
else:
|
|
406
|
+
if group.lidLabwareId is not None and state_view.labware.known(
|
|
407
|
+
group.lidLabwareId
|
|
408
|
+
):
|
|
409
|
+
raise CommandPreconditionViolated(
|
|
410
|
+
"Either all labware ids must be known or none must be, but primary and lid do not match"
|
|
411
|
+
)
|
|
412
|
+
if group.adapterLabwareId is not None and state_view.labware.known(
|
|
413
|
+
group.adapterLabwareId
|
|
414
|
+
):
|
|
415
|
+
raise CommandPreconditionViolated(
|
|
416
|
+
"Either all labware ids must be known or none must be, but primary and lid do not match"
|
|
417
|
+
)
|
|
418
|
+
return False
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
def _check_one_preloaded_labware( # noqa: C901
|
|
422
|
+
pool_primary_definition: LabwareDefinition,
|
|
423
|
+
pool_adapter_definition: LabwareDefinition | None,
|
|
424
|
+
pool_lid_definition: LabwareDefinition | None,
|
|
425
|
+
group: StackerStoredLabwareGroup,
|
|
426
|
+
state_view: StateView,
|
|
427
|
+
) -> None:
|
|
428
|
+
"""Do some preflight checks for labware known to be preloaded.
|
|
429
|
+
|
|
430
|
+
Check that labware known to the engine is located appropriately to be loaded to the stacker.
|
|
431
|
+
hopper directly (i.e. during setStoredLabware or fill, NOT with store). While we're at it, bind the def and the id.
|
|
432
|
+
"""
|
|
433
|
+
pool_primary_uri = state_view.labware.get_uri_from_definition(
|
|
434
|
+
pool_primary_definition
|
|
435
|
+
)
|
|
436
|
+
stored_primary_uri = state_view.labware.get_definition_uri(group.primaryLabwareId)
|
|
437
|
+
|
|
438
|
+
if pool_primary_uri != stored_primary_uri:
|
|
439
|
+
raise CommandPreconditionViolated(
|
|
440
|
+
f"Each labware group must be composed of the same kinds of labware, but previous labware groups specify primary URI {stored_primary_uri} and this one specifies {pool_primary_uri}."
|
|
441
|
+
)
|
|
442
|
+
if pool_adapter_definition:
|
|
443
|
+
if group.adapterLabwareId is None:
|
|
444
|
+
raise CommandPreconditionViolated(
|
|
445
|
+
"Each labware group must be composed of the same kinds of labware, but previous labware groups specify an adapter and this one does not."
|
|
446
|
+
)
|
|
447
|
+
stored_adapter_uri = state_view.labware.get_definition_uri(
|
|
448
|
+
group.adapterLabwareId
|
|
449
|
+
)
|
|
450
|
+
pool_adapter_uri = state_view.labware.get_uri_from_definition(
|
|
451
|
+
pool_adapter_definition
|
|
452
|
+
)
|
|
453
|
+
if stored_adapter_uri != pool_adapter_uri:
|
|
454
|
+
raise CommandPreconditionViolated(
|
|
455
|
+
f"Each labware group must be composed of the same kinds of labware, but previous labware groups specify adapter URI {stored_adapter_uri} and this one specifies {pool_adapter_uri}."
|
|
456
|
+
)
|
|
457
|
+
if state_view.labware.get_location(group.adapterLabwareId) != OFF_DECK_LOCATION:
|
|
458
|
+
raise CommandPreconditionViolated(
|
|
459
|
+
"All existing adapters to be loaded into a stacker must be currently OFF_DECK"
|
|
460
|
+
)
|
|
461
|
+
if state_view.labware.get_location(group.primaryLabwareId) != OnLabwareLocation(
|
|
462
|
+
labwareId=group.adapterLabwareId
|
|
463
|
+
):
|
|
464
|
+
raise CommandPreconditionViolated(
|
|
465
|
+
"Existing labware groups to be loaded into a stacker must already be associated"
|
|
466
|
+
)
|
|
467
|
+
else:
|
|
468
|
+
if group.adapterLabwareId is not None:
|
|
469
|
+
raise CommandPreconditionViolated(
|
|
470
|
+
"Each labware group must be composed of the same kinds of labware, but previous labware groups specify no adapter and this one does."
|
|
471
|
+
)
|
|
472
|
+
if state_view.labware.get_location(group.primaryLabwareId) != OFF_DECK_LOCATION:
|
|
473
|
+
raise CommandPreconditionViolated(
|
|
474
|
+
"All existing labware without adapters to be loaded into a stacker must be currently OFF_DECK"
|
|
475
|
+
)
|
|
476
|
+
if pool_lid_definition:
|
|
477
|
+
if group.lidLabwareId is None:
|
|
478
|
+
raise CommandPreconditionViolated(
|
|
479
|
+
"Each labware group must be composed of the same kinds of labware, but previous labware groups specify a lid and this one does not."
|
|
480
|
+
)
|
|
481
|
+
stored_lid_uri = state_view.labware.get_definition_uri(group.lidLabwareId)
|
|
482
|
+
pool_lid_uri = state_view.labware.get_uri_from_definition(pool_lid_definition)
|
|
483
|
+
if stored_lid_uri != pool_lid_uri:
|
|
484
|
+
raise CommandPreconditionViolated(
|
|
485
|
+
f"Each labware group must be composed of the same kinds of labware, but previous labware groups specify lid URI {stored_lid_uri} and this one specifies {pool_lid_uri}."
|
|
486
|
+
)
|
|
487
|
+
|
|
488
|
+
if (
|
|
489
|
+
state_view.labware.get_location(group.lidLabwareId)
|
|
490
|
+
!= OnLabwareLocation(labwareId=group.primaryLabwareId)
|
|
491
|
+
or state_view.labware.get_lid_id_by_labware_id(group.primaryLabwareId)
|
|
492
|
+
!= group.lidLabwareId
|
|
493
|
+
):
|
|
494
|
+
raise CommandPreconditionViolated(
|
|
495
|
+
"Existing labware groups to be loaded into a stacker must already be associated"
|
|
496
|
+
)
|
|
497
|
+
else:
|
|
498
|
+
if group.lidLabwareId is not None:
|
|
499
|
+
raise CommandPreconditionViolated(
|
|
500
|
+
"Each labware group must be composed of the same kinds of labware, but previous labware groups did not specify a lid and this one does."
|
|
501
|
+
)
|
|
502
|
+
|
|
503
|
+
|
|
504
|
+
def check_preloaded_labware(
|
|
505
|
+
pool_primary_definition: LabwareDefinition,
|
|
506
|
+
pool_adapter_definition: LabwareDefinition | None,
|
|
507
|
+
pool_lid_definition: LabwareDefinition | None,
|
|
508
|
+
ids: list[StackerStoredLabwareGroup],
|
|
509
|
+
state_view: StateView,
|
|
510
|
+
) -> None:
|
|
511
|
+
"""Check whether a list of known-to-be-preloaded labware match the pool constraints."""
|
|
512
|
+
for group in ids:
|
|
513
|
+
_check_one_preloaded_labware(
|
|
514
|
+
pool_primary_definition,
|
|
515
|
+
pool_adapter_definition,
|
|
516
|
+
pool_lid_definition,
|
|
517
|
+
group,
|
|
518
|
+
state_view,
|
|
519
|
+
)
|
|
520
|
+
|
|
521
|
+
|
|
522
|
+
def check_if_labware_preloaded(
|
|
523
|
+
ids: list[StackerStoredLabwareGroup], state_view: StateView
|
|
524
|
+
) -> bool:
|
|
525
|
+
"""Determine whether the list of ids has already been loaded or needs to be loaded."""
|
|
526
|
+
if len(ids) == 0:
|
|
527
|
+
return False
|
|
528
|
+
first = _check_one_preloaded_labware_known(ids[0], state_view)
|
|
529
|
+
for group in ids[1:]:
|
|
530
|
+
if _check_one_preloaded_labware_known(group, state_view) != first:
|
|
531
|
+
raise CommandPreconditionViolated(
|
|
532
|
+
"All labware must be previously loaded or none must be previously loaded."
|
|
533
|
+
)
|
|
534
|
+
return first
|
|
535
|
+
|
|
536
|
+
|
|
537
|
+
def _add_labware_details_to_dicts(
|
|
538
|
+
definitions_by_id: dict[str, LabwareDefinition],
|
|
539
|
+
display_names_by_id: dict[str, str | None],
|
|
540
|
+
new_locations_by_id: dict[str, LabwareLocation],
|
|
541
|
+
offset_ids_by_id: dict[str, str | None],
|
|
542
|
+
definition: LabwareDefinition,
|
|
543
|
+
labware: LoadedLabware,
|
|
544
|
+
) -> None:
|
|
545
|
+
definitions_by_id[labware.id] = definition
|
|
546
|
+
display_names_by_id[labware.id] = None
|
|
547
|
+
new_locations_by_id[labware.id] = labware.location
|
|
548
|
+
offset_ids_by_id[labware.id] = labware.offsetId
|
|
549
|
+
|
|
550
|
+
|
|
551
|
+
def _add_pool_labware_details_to_dicts(
|
|
552
|
+
definitions_by_id: dict[str, LabwareDefinition],
|
|
553
|
+
display_names_by_id: dict[str, str | None],
|
|
554
|
+
new_locations_by_id: dict[str, LabwareLocation],
|
|
555
|
+
offset_ids_by_id: dict[str, str | None],
|
|
556
|
+
lid_parent_ids: list[str],
|
|
557
|
+
lid_ids: list[str],
|
|
558
|
+
pool_primary_definition: LabwareDefinition,
|
|
559
|
+
pool_lid_definition: LabwareDefinition | None,
|
|
560
|
+
pool_adapter_definition: LabwareDefinition | None,
|
|
561
|
+
pool_group: LoadedLabwarePoolData,
|
|
562
|
+
) -> None:
|
|
563
|
+
if pool_group.lid_labware:
|
|
564
|
+
assert pool_lid_definition # safe: only have lids if the pool has lids
|
|
565
|
+
lid_parent_ids.append(pool_group.primary_labware.id)
|
|
566
|
+
lid_ids.append(pool_group.lid_labware.id)
|
|
567
|
+
_add_labware_details_to_dicts(
|
|
568
|
+
definitions_by_id,
|
|
569
|
+
display_names_by_id,
|
|
570
|
+
new_locations_by_id,
|
|
571
|
+
offset_ids_by_id,
|
|
572
|
+
pool_lid_definition,
|
|
573
|
+
pool_group.lid_labware,
|
|
574
|
+
)
|
|
575
|
+
if pool_group.adapter_labware:
|
|
576
|
+
assert pool_adapter_definition
|
|
577
|
+
_add_labware_details_to_dicts(
|
|
578
|
+
definitions_by_id,
|
|
579
|
+
display_names_by_id,
|
|
580
|
+
new_locations_by_id,
|
|
581
|
+
offset_ids_by_id,
|
|
582
|
+
pool_adapter_definition,
|
|
583
|
+
pool_group.adapter_labware,
|
|
584
|
+
)
|
|
585
|
+
|
|
586
|
+
_add_labware_details_to_dicts(
|
|
587
|
+
definitions_by_id,
|
|
588
|
+
display_names_by_id,
|
|
589
|
+
new_locations_by_id,
|
|
590
|
+
offset_ids_by_id,
|
|
591
|
+
pool_primary_definition,
|
|
592
|
+
pool_group.primary_labware,
|
|
593
|
+
)
|
|
594
|
+
|
|
595
|
+
|
|
596
|
+
async def build_n_labware_with_ids(
|
|
597
|
+
pool_primary_definition: LabwareDefinition,
|
|
598
|
+
pool_adapter_definition: LabwareDefinition | None,
|
|
599
|
+
pool_lid_definition: LabwareDefinition | None,
|
|
600
|
+
module_id: str,
|
|
601
|
+
ids: list[StackerStoredLabwareGroup],
|
|
602
|
+
current_contained_labware: list[StackerStoredLabwareGroup],
|
|
603
|
+
equipment: EquipmentHandler,
|
|
604
|
+
) -> tuple[StateUpdate, list[StackerStoredLabwareGroup]]:
|
|
605
|
+
"""Create labware objects to be stored inside the hopper."""
|
|
606
|
+
pool_groups = [
|
|
607
|
+
await equipment.load_labware_pool_from_definitions(
|
|
608
|
+
pool_primary_definition=pool_primary_definition,
|
|
609
|
+
pool_adapter_definition=pool_adapter_definition,
|
|
610
|
+
pool_lid_definition=pool_lid_definition,
|
|
611
|
+
location=InStackerHopperLocation(moduleId=module_id),
|
|
612
|
+
primary_id=id_group.primaryLabwareId,
|
|
613
|
+
adapter_id=id_group.adapterLabwareId,
|
|
614
|
+
lid_id=id_group.lidLabwareId,
|
|
615
|
+
)
|
|
616
|
+
for id_group in ids
|
|
617
|
+
]
|
|
618
|
+
definitions_by_id: dict[str, LabwareDefinition] = {}
|
|
619
|
+
display_names_by_id: dict[str, str | None] = {}
|
|
620
|
+
new_locations_by_id: dict[str, LabwareLocation] = {}
|
|
621
|
+
offset_ids_by_id: dict[str, str | None] = {}
|
|
622
|
+
lid_parent_ids: list[str] = []
|
|
623
|
+
lid_ids: list[str] = []
|
|
624
|
+
for pool_group in pool_groups:
|
|
625
|
+
_add_pool_labware_details_to_dicts(
|
|
626
|
+
definitions_by_id,
|
|
627
|
+
display_names_by_id,
|
|
628
|
+
new_locations_by_id,
|
|
629
|
+
offset_ids_by_id,
|
|
630
|
+
lid_parent_ids,
|
|
631
|
+
lid_ids,
|
|
632
|
+
pool_primary_definition,
|
|
633
|
+
pool_lid_definition,
|
|
634
|
+
pool_adapter_definition,
|
|
635
|
+
pool_group,
|
|
636
|
+
)
|
|
637
|
+
new_contained_labware = current_contained_labware + ids
|
|
638
|
+
return (
|
|
639
|
+
StateUpdate()
|
|
640
|
+
.update_flex_stacker_contained_labware(module_id, new_contained_labware)
|
|
641
|
+
.set_batch_loaded_labware(
|
|
642
|
+
definitions_by_id=definitions_by_id,
|
|
643
|
+
offset_ids_by_id=offset_ids_by_id,
|
|
644
|
+
display_names_by_id=display_names_by_id,
|
|
645
|
+
new_locations_by_id=new_locations_by_id,
|
|
646
|
+
)
|
|
647
|
+
.set_lids(parent_labware_ids=lid_parent_ids, lid_ids=lid_ids)
|
|
648
|
+
), new_contained_labware
|
|
649
|
+
|
|
650
|
+
|
|
651
|
+
async def assign_n_labware(
|
|
652
|
+
pool_primary_definition: LabwareDefinition,
|
|
653
|
+
pool_adapter_definition: LabwareDefinition | None,
|
|
654
|
+
pool_lid_definition: LabwareDefinition | None,
|
|
655
|
+
module_id: str,
|
|
656
|
+
ids: list[StackerStoredLabwareGroup],
|
|
657
|
+
current_contained_labware: list[StackerStoredLabwareGroup],
|
|
658
|
+
state_view: StateView,
|
|
659
|
+
) -> tuple[StateUpdate, list[StackerStoredLabwareGroup]]:
|
|
660
|
+
"""Assign a list of labware to be inside the stacker hopper."""
|
|
661
|
+
check_preloaded_labware(
|
|
662
|
+
pool_primary_definition,
|
|
663
|
+
pool_adapter_definition,
|
|
664
|
+
pool_lid_definition,
|
|
665
|
+
ids,
|
|
666
|
+
state_view,
|
|
667
|
+
)
|
|
668
|
+
|
|
669
|
+
def _bottom_labware(group: StackerStoredLabwareGroup) -> str:
|
|
670
|
+
if group.adapterLabwareId:
|
|
671
|
+
return group.adapterLabwareId
|
|
672
|
+
return group.primaryLabwareId
|
|
673
|
+
|
|
674
|
+
def _add_ids(
|
|
675
|
+
group: StackerStoredLabwareGroup, offset_dict: dict[str, str | None]
|
|
676
|
+
) -> None:
|
|
677
|
+
offset_dict[group.primaryLabwareId] = None
|
|
678
|
+
if group.adapterLabwareId:
|
|
679
|
+
offset_dict[group.adapterLabwareId] = None
|
|
680
|
+
if group.lidLabwareId:
|
|
681
|
+
offset_dict[group.lidLabwareId] = None
|
|
682
|
+
|
|
683
|
+
new_locations_by_id = {
|
|
684
|
+
_bottom_labware(group): InStackerHopperLocation(moduleId=module_id)
|
|
685
|
+
for group in ids
|
|
686
|
+
}
|
|
687
|
+
new_offset_ids_by_id: dict[str, str | None] = {}
|
|
688
|
+
for group in ids:
|
|
689
|
+
_add_ids(group, new_offset_ids_by_id)
|
|
690
|
+
|
|
691
|
+
new_contained_labware = current_contained_labware + ids
|
|
692
|
+
return (
|
|
693
|
+
StateUpdate()
|
|
694
|
+
.update_flex_stacker_contained_labware(module_id, new_contained_labware)
|
|
695
|
+
.set_batch_labware_location(
|
|
696
|
+
new_locations_by_id=new_locations_by_id,
|
|
697
|
+
new_offset_ids_by_id=new_offset_ids_by_id,
|
|
698
|
+
)
|
|
699
|
+
), new_contained_labware
|
|
700
|
+
|
|
701
|
+
|
|
702
|
+
async def build_or_assign_labware_to_hopper(
|
|
703
|
+
pool_primary_definition: LabwareDefinition,
|
|
704
|
+
pool_adapter_definition: LabwareDefinition | None,
|
|
705
|
+
pool_lid_definition: LabwareDefinition | None,
|
|
706
|
+
module_id: str,
|
|
707
|
+
ids: list[StackerStoredLabwareGroup],
|
|
708
|
+
current_contained_labware: list[StackerStoredLabwareGroup],
|
|
709
|
+
equipment: EquipmentHandler,
|
|
710
|
+
state_view: StateView,
|
|
711
|
+
) -> tuple[StateUpdate, list[StackerStoredLabwareGroup]]:
|
|
712
|
+
"""Use the common params to labware-creating stacker commands to load labware appropriately.
|
|
713
|
+
|
|
714
|
+
If the specified labware IDs exist already, labware is moved; if they don't, labware is created.
|
|
715
|
+
"""
|
|
716
|
+
if check_if_labware_preloaded(ids, state_view):
|
|
717
|
+
return await assign_n_labware(
|
|
718
|
+
pool_primary_definition,
|
|
719
|
+
pool_adapter_definition,
|
|
720
|
+
pool_lid_definition,
|
|
721
|
+
module_id,
|
|
722
|
+
ids,
|
|
723
|
+
current_contained_labware,
|
|
724
|
+
state_view,
|
|
725
|
+
)
|
|
726
|
+
else:
|
|
727
|
+
return await build_n_labware_with_ids(
|
|
728
|
+
pool_primary_definition,
|
|
729
|
+
pool_adapter_definition,
|
|
730
|
+
pool_lid_definition,
|
|
731
|
+
module_id,
|
|
732
|
+
ids,
|
|
733
|
+
current_contained_labware,
|
|
734
|
+
equipment,
|
|
735
|
+
)
|
|
736
|
+
|
|
737
|
+
|
|
738
|
+
def _count_from_lw_list_or_initial_count(
|
|
739
|
+
initial_count: int | None,
|
|
740
|
+
initial_lw: list[StackerStoredLabwareGroup] | None,
|
|
741
|
+
max_pool_count: int,
|
|
742
|
+
current_count: int,
|
|
743
|
+
) -> int:
|
|
744
|
+
"""Count the number of labware to be added to the stacker."""
|
|
745
|
+
capacity = max(max_pool_count - current_count, 0)
|
|
746
|
+
|
|
747
|
+
if initial_count is not None:
|
|
748
|
+
if initial_lw and len(initial_lw) != initial_count:
|
|
749
|
+
raise CommandPreconditionViolated(
|
|
750
|
+
"If initialCount and initialStoredLabware are both specified, the number of labware must equal the count"
|
|
751
|
+
)
|
|
752
|
+
to_store_count = initial_count
|
|
753
|
+
elif initial_lw is not None:
|
|
754
|
+
to_store_count = len(initial_lw)
|
|
755
|
+
else:
|
|
756
|
+
# neither initialCount nor initialStoredLabware are specified
|
|
757
|
+
if not capacity:
|
|
758
|
+
raise CommandPreconditionViolated(
|
|
759
|
+
"No labware groups were specified to be stored, but the stacker is already full"
|
|
760
|
+
)
|
|
761
|
+
return capacity
|
|
762
|
+
|
|
763
|
+
if to_store_count > capacity:
|
|
764
|
+
error_text = f" and is already holding {current_count}" if current_count else ""
|
|
765
|
+
raise CommandPreconditionViolated(
|
|
766
|
+
f"{to_store_count} labware groups were requested to be stored, "
|
|
767
|
+
f"but the stacker can hold only {max_pool_count}{error_text}"
|
|
768
|
+
)
|
|
769
|
+
return to_store_count
|
|
770
|
+
|
|
771
|
+
|
|
772
|
+
def _build_one_labware_group(
|
|
773
|
+
has_adapter: bool,
|
|
774
|
+
has_lid: bool,
|
|
775
|
+
group: StackerStoredLabwareGroup | None,
|
|
776
|
+
model_utils: ModelUtils,
|
|
777
|
+
) -> StackerStoredLabwareGroup:
|
|
778
|
+
if group:
|
|
779
|
+
return group
|
|
780
|
+
return StackerStoredLabwareGroup(
|
|
781
|
+
primaryLabwareId=model_utils.generate_id(),
|
|
782
|
+
adapterLabwareId=(model_utils.generate_id() if has_adapter else None),
|
|
783
|
+
lidLabwareId=(model_utils.generate_id() if has_lid else None),
|
|
784
|
+
)
|
|
785
|
+
|
|
786
|
+
|
|
787
|
+
def build_ids_to_fill(
|
|
788
|
+
has_adapter: bool,
|
|
789
|
+
has_lid: bool,
|
|
790
|
+
initialLabware: list[StackerStoredLabwareGroup] | None,
|
|
791
|
+
initialCount: int | None,
|
|
792
|
+
max_count: int,
|
|
793
|
+
current_count: int,
|
|
794
|
+
model_utils: ModelUtils,
|
|
795
|
+
) -> list[StackerStoredLabwareGroup]:
|
|
796
|
+
"""Handle the common params for filling the stacker to make a list of ids.
|
|
797
|
+
|
|
798
|
+
Only builds labware to add to the current stored (defined by current count).
|
|
799
|
+
"""
|
|
800
|
+
count = _count_from_lw_list_or_initial_count(
|
|
801
|
+
initialCount, initialLabware, max_count, current_count
|
|
802
|
+
)
|
|
803
|
+
|
|
804
|
+
def _pad_labware_to_count(
|
|
805
|
+
labware_list: list[StackerStoredLabwareGroup], count: int
|
|
806
|
+
) -> Sequence[StackerStoredLabwareGroup | None]:
|
|
807
|
+
if len(labware_list) < count:
|
|
808
|
+
return labware_list + ([None] * (count - len(labware_list)))
|
|
809
|
+
else:
|
|
810
|
+
return labware_list[:count]
|
|
811
|
+
|
|
812
|
+
return [
|
|
813
|
+
_build_one_labware_group(has_adapter, has_lid, group, model_utils)
|
|
814
|
+
for group in _pad_labware_to_count(initialLabware or [], count)
|
|
815
|
+
]
|
|
816
|
+
|
|
817
|
+
|
|
818
|
+
def build_retrieve_labware_move_updates(
|
|
819
|
+
group: StackerStoredLabwareGroup,
|
|
820
|
+
stacker: FlexStackerSubState,
|
|
821
|
+
state_view: StateView,
|
|
822
|
+
) -> tuple[dict[str, LabwareLocation], dict[str, str | None]]:
|
|
823
|
+
"""Build the arguments required for batch_labware_location."""
|
|
824
|
+
locations_for_ids: dict[str, LabwareLocation] = {}
|
|
825
|
+
offset_ids_by_id: dict[str, str | None] = {}
|
|
826
|
+
base_offset_location = state_view.geometry.get_projected_offset_location(
|
|
827
|
+
ModuleLocation(moduleId=stacker.module_id)
|
|
828
|
+
)
|
|
829
|
+
assert stacker.pool_primary_definition, "Undefined labware pool"
|
|
830
|
+
primary_uri = state_view.labware.get_uri_from_definition(
|
|
831
|
+
stacker.pool_primary_definition
|
|
832
|
+
)
|
|
833
|
+
|
|
834
|
+
def _prepend_loc(
|
|
835
|
+
new: LabwareOffsetLocationSequence,
|
|
836
|
+
current: LabwareOffsetLocationSequence | None,
|
|
837
|
+
) -> LabwareOffsetLocationSequence | None:
|
|
838
|
+
if current is None:
|
|
839
|
+
return None
|
|
840
|
+
return new + current
|
|
841
|
+
|
|
842
|
+
def _find_offset_id(
|
|
843
|
+
uri: str, offset_location: LabwareOffsetLocationSequence | None
|
|
844
|
+
) -> str | None:
|
|
845
|
+
if offset_location is None:
|
|
846
|
+
return None
|
|
847
|
+
offset = state_view.labware.find_applicable_labware_offset(uri, offset_location)
|
|
848
|
+
if offset is None:
|
|
849
|
+
return None
|
|
850
|
+
return offset.id
|
|
851
|
+
|
|
852
|
+
if group.adapterLabwareId:
|
|
853
|
+
locations_for_ids[group.adapterLabwareId] = ModuleLocation(
|
|
854
|
+
moduleId=stacker.module_id
|
|
855
|
+
)
|
|
856
|
+
locations_for_ids[group.primaryLabwareId] = OnLabwareLocation(
|
|
857
|
+
labwareId=group.adapterLabwareId
|
|
858
|
+
)
|
|
859
|
+
assert (
|
|
860
|
+
stacker.pool_adapter_definition
|
|
861
|
+
), "Mismatched pool and labware definitions"
|
|
862
|
+
adapter_uri = state_view.labware.get_uri_from_definition(
|
|
863
|
+
stacker.pool_adapter_definition
|
|
864
|
+
)
|
|
865
|
+
offset_ids_by_id[group.adapterLabwareId] = _find_offset_id(
|
|
866
|
+
adapter_uri, base_offset_location
|
|
867
|
+
)
|
|
868
|
+
primary_offset_location = _prepend_loc(
|
|
869
|
+
[OnLabwareOffsetLocationSequenceComponent(labwareUri=adapter_uri)],
|
|
870
|
+
base_offset_location,
|
|
871
|
+
)
|
|
872
|
+
offset_ids_by_id[group.primaryLabwareId] = _find_offset_id(
|
|
873
|
+
primary_uri, primary_offset_location
|
|
874
|
+
)
|
|
875
|
+
|
|
876
|
+
else:
|
|
877
|
+
locations_for_ids[group.primaryLabwareId] = ModuleLocation(
|
|
878
|
+
moduleId=stacker.module_id
|
|
879
|
+
)
|
|
880
|
+
primary_offset_location = base_offset_location
|
|
881
|
+
offset_ids_by_id[group.primaryLabwareId] = _find_offset_id(
|
|
882
|
+
primary_uri, primary_offset_location
|
|
883
|
+
)
|
|
884
|
+
|
|
885
|
+
if group.lidLabwareId:
|
|
886
|
+
assert (
|
|
887
|
+
stacker.pool_lid_definition is not None
|
|
888
|
+
), "Mismatched pool and stored labware"
|
|
889
|
+
lid_offset_location = _prepend_loc(
|
|
890
|
+
[OnLabwareOffsetLocationSequenceComponent(labwareUri=primary_uri)],
|
|
891
|
+
primary_offset_location,
|
|
892
|
+
)
|
|
893
|
+
locations_for_ids[group.lidLabwareId] = OnLabwareLocation(
|
|
894
|
+
labwareId=group.primaryLabwareId
|
|
895
|
+
)
|
|
896
|
+
offset_ids_by_id[group.lidLabwareId] = _find_offset_id(
|
|
897
|
+
state_view.labware.get_uri_from_definition(stacker.pool_lid_definition),
|
|
898
|
+
lid_offset_location,
|
|
899
|
+
)
|
|
900
|
+
return locations_for_ids, offset_ids_by_id
|