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,82 @@
|
|
|
1
|
+
"""A data store of liquid classes."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import dataclasses
|
|
6
|
+
from typing import Dict
|
|
7
|
+
from typing_extensions import Optional
|
|
8
|
+
|
|
9
|
+
from .. import errors
|
|
10
|
+
from ..actions import Action, get_state_updates
|
|
11
|
+
from ..types import LiquidClassRecord
|
|
12
|
+
from . import update_types
|
|
13
|
+
from ._abstract_store import HasState, HandlesActions
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclasses.dataclass
|
|
17
|
+
class LiquidClassState:
|
|
18
|
+
"""Our state is a bidirectional mapping between IDs <-> LiquidClassRecords."""
|
|
19
|
+
|
|
20
|
+
# We use the bidirectional map to see if we've already assigned an ID to a liquid class when the
|
|
21
|
+
# engine is asked to store a new liquid class.
|
|
22
|
+
liquid_class_record_by_id: Dict[str, LiquidClassRecord]
|
|
23
|
+
liquid_class_record_to_id: Dict[LiquidClassRecord, str]
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class LiquidClassStore(HasState[LiquidClassState], HandlesActions):
|
|
27
|
+
"""Container for LiquidClassState."""
|
|
28
|
+
|
|
29
|
+
_state: LiquidClassState
|
|
30
|
+
|
|
31
|
+
def __init__(self) -> None:
|
|
32
|
+
self._state = LiquidClassState(
|
|
33
|
+
liquid_class_record_by_id={},
|
|
34
|
+
liquid_class_record_to_id={},
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
def handle_action(self, action: Action) -> None:
|
|
38
|
+
"""Update the state in response to the action."""
|
|
39
|
+
for state_update in get_state_updates(action):
|
|
40
|
+
if state_update.liquid_class_loaded != update_types.NO_CHANGE:
|
|
41
|
+
self._handle_liquid_class_loaded_update(
|
|
42
|
+
state_update.liquid_class_loaded
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
def _handle_liquid_class_loaded_update(
|
|
46
|
+
self, state_update: update_types.LiquidClassLoadedUpdate
|
|
47
|
+
) -> None:
|
|
48
|
+
# We're just a data store. All the validation and ID generation happens in the command implementation.
|
|
49
|
+
self._state.liquid_class_record_by_id[
|
|
50
|
+
state_update.liquid_class_id
|
|
51
|
+
] = state_update.liquid_class_record
|
|
52
|
+
self._state.liquid_class_record_to_id[
|
|
53
|
+
state_update.liquid_class_record
|
|
54
|
+
] = state_update.liquid_class_id
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class LiquidClassView:
|
|
58
|
+
"""Read-only view of the LiquidClassState."""
|
|
59
|
+
|
|
60
|
+
_state: LiquidClassState
|
|
61
|
+
|
|
62
|
+
def __init__(self, state: LiquidClassState) -> None:
|
|
63
|
+
self._state = state
|
|
64
|
+
|
|
65
|
+
def get(self, liquid_class_id: str) -> LiquidClassRecord:
|
|
66
|
+
"""Get the LiquidClassRecord with the given identifier."""
|
|
67
|
+
try:
|
|
68
|
+
return self._state.liquid_class_record_by_id[liquid_class_id]
|
|
69
|
+
except KeyError as e:
|
|
70
|
+
raise errors.LiquidClassDoesNotExistError(
|
|
71
|
+
f"Liquid class ID {liquid_class_id} not found."
|
|
72
|
+
) from e
|
|
73
|
+
|
|
74
|
+
def get_id_for_liquid_class_record(
|
|
75
|
+
self, liquid_class_record: LiquidClassRecord
|
|
76
|
+
) -> Optional[str]:
|
|
77
|
+
"""See if the given LiquidClassRecord if already in the store, and if so, return its identifier."""
|
|
78
|
+
return self._state.liquid_class_record_to_id.get(liquid_class_record)
|
|
79
|
+
|
|
80
|
+
def get_all(self) -> Dict[str, LiquidClassRecord]:
|
|
81
|
+
"""Get all the LiquidClassRecords in the store."""
|
|
82
|
+
return self._state.liquid_class_record_by_id.copy()
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"""Basic liquid data state and store."""
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
from typing import Dict, List
|
|
4
|
+
from opentrons.protocol_engine.types import Liquid, LiquidId
|
|
5
|
+
|
|
6
|
+
from ._abstract_store import HasState, HandlesActions
|
|
7
|
+
from ..actions import Action, AddLiquidAction
|
|
8
|
+
from ..errors import LiquidDoesNotExistError, InvalidLiquidError
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass
|
|
12
|
+
class LiquidState:
|
|
13
|
+
"""State of all loaded liquids."""
|
|
14
|
+
|
|
15
|
+
liquids_by_id: Dict[str, Liquid]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class LiquidStore(HasState[LiquidState], HandlesActions):
|
|
19
|
+
"""Liquid state container."""
|
|
20
|
+
|
|
21
|
+
_state: LiquidState
|
|
22
|
+
|
|
23
|
+
def __init__(self) -> None:
|
|
24
|
+
"""Initialize a liquid store and its state."""
|
|
25
|
+
self._state = LiquidState(liquids_by_id={})
|
|
26
|
+
|
|
27
|
+
def handle_action(self, action: Action) -> None:
|
|
28
|
+
"""Modify state in reaction to an action."""
|
|
29
|
+
if isinstance(action, AddLiquidAction):
|
|
30
|
+
self._add_liquid(action)
|
|
31
|
+
|
|
32
|
+
def _add_liquid(self, action: AddLiquidAction) -> None:
|
|
33
|
+
"""Add liquid to protocol liquids."""
|
|
34
|
+
self._state.liquids_by_id[action.liquid.id] = action.liquid
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class LiquidView:
|
|
38
|
+
"""Read-only liquid state view."""
|
|
39
|
+
|
|
40
|
+
_state: LiquidState
|
|
41
|
+
|
|
42
|
+
def __init__(self, state: LiquidState) -> None:
|
|
43
|
+
"""Initialize the computed view of liquid state.
|
|
44
|
+
|
|
45
|
+
Arguments:
|
|
46
|
+
state: Liquid state dataclass used for all calculations.
|
|
47
|
+
"""
|
|
48
|
+
self._state = state
|
|
49
|
+
|
|
50
|
+
def get_all(self) -> List[Liquid]:
|
|
51
|
+
"""Get all protocol liquids."""
|
|
52
|
+
return list(self._state.liquids_by_id.values())
|
|
53
|
+
|
|
54
|
+
def validate_liquid_id(self, liquid_id: LiquidId) -> LiquidId:
|
|
55
|
+
"""Check if liquid_id exists in liquids."""
|
|
56
|
+
is_empty = liquid_id == "EMPTY"
|
|
57
|
+
if is_empty:
|
|
58
|
+
return liquid_id
|
|
59
|
+
has_liquid = liquid_id in self._state.liquids_by_id
|
|
60
|
+
if not has_liquid:
|
|
61
|
+
raise LiquidDoesNotExistError(
|
|
62
|
+
f"Supplied liquidId: {liquid_id} does not exist in the loaded liquids."
|
|
63
|
+
)
|
|
64
|
+
return liquid_id
|
|
65
|
+
|
|
66
|
+
def validate_liquid_allowed(self, liquid: Liquid) -> Liquid:
|
|
67
|
+
"""Validate that a liquid is legal to load."""
|
|
68
|
+
is_empty = liquid.id == "EMPTY"
|
|
69
|
+
if is_empty:
|
|
70
|
+
raise InvalidLiquidError(
|
|
71
|
+
message='Protocols may not define a liquid with the special id "EMPTY".'
|
|
72
|
+
)
|
|
73
|
+
return liquid
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"""Hardware Modules' substates."""
|
|
2
|
+
|
|
3
|
+
from typing import Union
|
|
4
|
+
from .magnetic_module_substate import MagneticModuleSubState, MagneticModuleId
|
|
5
|
+
from .heater_shaker_module_substate import (
|
|
6
|
+
HeaterShakerModuleSubState,
|
|
7
|
+
HeaterShakerModuleId,
|
|
8
|
+
)
|
|
9
|
+
from .temperature_module_substate import TemperatureModuleSubState, TemperatureModuleId
|
|
10
|
+
from .thermocycler_module_substate import (
|
|
11
|
+
ThermocyclerModuleSubState,
|
|
12
|
+
ThermocyclerModuleId,
|
|
13
|
+
)
|
|
14
|
+
from .magnetic_block_substate import MagneticBlockSubState, MagneticBlockId
|
|
15
|
+
from .absorbance_reader_substate import AbsorbanceReaderSubState, AbsorbanceReaderId
|
|
16
|
+
from .flex_stacker_substate import FlexStackerSubState, FlexStackerId
|
|
17
|
+
|
|
18
|
+
ModuleSubStateType = Union[
|
|
19
|
+
HeaterShakerModuleSubState,
|
|
20
|
+
MagneticModuleSubState,
|
|
21
|
+
TemperatureModuleSubState,
|
|
22
|
+
ThermocyclerModuleSubState,
|
|
23
|
+
MagneticBlockSubState,
|
|
24
|
+
AbsorbanceReaderSubState,
|
|
25
|
+
FlexStackerSubState,
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
__all__ = [
|
|
29
|
+
"MagneticModuleSubState",
|
|
30
|
+
"MagneticModuleId",
|
|
31
|
+
"HeaterShakerModuleSubState",
|
|
32
|
+
"HeaterShakerModuleId",
|
|
33
|
+
"TemperatureModuleSubState",
|
|
34
|
+
"TemperatureModuleId",
|
|
35
|
+
"ThermocyclerModuleSubState",
|
|
36
|
+
"ThermocyclerModuleId",
|
|
37
|
+
"MagneticBlockSubState",
|
|
38
|
+
"MagneticBlockId",
|
|
39
|
+
"AbsorbanceReaderSubState",
|
|
40
|
+
"AbsorbanceReaderId",
|
|
41
|
+
"FlexStackerSubState",
|
|
42
|
+
"FlexStackerId",
|
|
43
|
+
# Union of all module substates
|
|
44
|
+
"ModuleSubStateType",
|
|
45
|
+
]
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""Heater-Shaker Module sub-state."""
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
from typing import List, NewType, Optional, Dict
|
|
4
|
+
|
|
5
|
+
from opentrons.protocol_engine.errors import CannotPerformModuleAction
|
|
6
|
+
|
|
7
|
+
AbsorbanceReaderId = NewType("AbsorbanceReaderId", str)
|
|
8
|
+
AbsorbanceReaderLidId = NewType("AbsorbanceReaderLidId", str)
|
|
9
|
+
AbsorbanceReaderMeasureMode = NewType("AbsorbanceReaderMeasureMode", str)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
# todo(mm, 2024-11-08): frozen=True is getting pretty painful because ModuleStore has
|
|
13
|
+
# no type-safe way to modify just a single attribute. Consider unfreezing this
|
|
14
|
+
# (taking care to ensure that consumers of ModuleView still only get a read-only view).
|
|
15
|
+
@dataclass(frozen=True)
|
|
16
|
+
class AbsorbanceReaderSubState:
|
|
17
|
+
"""Absorbance-Plate-Reader-specific state."""
|
|
18
|
+
|
|
19
|
+
module_id: AbsorbanceReaderId
|
|
20
|
+
configured: bool
|
|
21
|
+
measured: bool
|
|
22
|
+
is_lid_on: bool
|
|
23
|
+
data: Optional[Dict[int, Dict[str, float]]]
|
|
24
|
+
configured_wavelengths: Optional[List[int]]
|
|
25
|
+
measure_mode: Optional[AbsorbanceReaderMeasureMode]
|
|
26
|
+
reference_wavelength: Optional[int]
|
|
27
|
+
|
|
28
|
+
def raise_if_lid_status_not_expected(self, lid_on_expected: bool) -> None:
|
|
29
|
+
"""Raise if the lid status is not correct."""
|
|
30
|
+
match = self.is_lid_on is lid_on_expected
|
|
31
|
+
if not match:
|
|
32
|
+
raise CannotPerformModuleAction(
|
|
33
|
+
"Cannot perform lid action because the lid is already "
|
|
34
|
+
f"{'closed' if self.is_lid_on else 'open'}"
|
|
35
|
+
)
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
"""Flex Stacker substate."""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import NewType
|
|
5
|
+
from opentrons_shared_data.labware.labware_definition import LabwareDefinition
|
|
6
|
+
from opentrons.protocol_engine.types.module import (
|
|
7
|
+
StackerStoredLabwareGroup,
|
|
8
|
+
StackerPoolDefinition,
|
|
9
|
+
)
|
|
10
|
+
from opentrons.protocol_engine.state.update_types import (
|
|
11
|
+
FlexStackerStateUpdate,
|
|
12
|
+
NO_CHANGE,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
FlexStackerId = NewType("FlexStackerId", str)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@dataclass(frozen=True)
|
|
20
|
+
class FlexStackerSubState:
|
|
21
|
+
"""Flex Stacker-specific state.
|
|
22
|
+
|
|
23
|
+
Provides calculations and read-only state access
|
|
24
|
+
for an individual loaded Flex Stacker Module.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
module_id: FlexStackerId
|
|
28
|
+
pool_primary_definition: LabwareDefinition | None
|
|
29
|
+
pool_adapter_definition: LabwareDefinition | None
|
|
30
|
+
pool_lid_definition: LabwareDefinition | None
|
|
31
|
+
max_pool_count: int
|
|
32
|
+
pool_height: float
|
|
33
|
+
pool_overlap: float
|
|
34
|
+
contained_labware_bottom_first: list[StackerStoredLabwareGroup]
|
|
35
|
+
|
|
36
|
+
def new_from_state_change(
|
|
37
|
+
self, update: FlexStackerStateUpdate
|
|
38
|
+
) -> "FlexStackerSubState":
|
|
39
|
+
"""Return a new state with the given update applied."""
|
|
40
|
+
pool_primary_definition = self.pool_primary_definition
|
|
41
|
+
pool_adapter_definition = self.pool_adapter_definition
|
|
42
|
+
pool_lid_definition = self.pool_lid_definition
|
|
43
|
+
max_pool_count = self.max_pool_count
|
|
44
|
+
pool_overlap = self.pool_overlap
|
|
45
|
+
pool_height = self.pool_height
|
|
46
|
+
if update.pool_constraint != NO_CHANGE:
|
|
47
|
+
max_pool_count = update.pool_constraint.max_pool_count
|
|
48
|
+
pool_primary_definition = update.pool_constraint.primary_definition
|
|
49
|
+
pool_adapter_definition = update.pool_constraint.adapter_definition
|
|
50
|
+
pool_lid_definition = update.pool_constraint.lid_definition
|
|
51
|
+
pool_overlap = update.pool_constraint.pool_overlap
|
|
52
|
+
pool_height = update.pool_constraint.pool_height
|
|
53
|
+
|
|
54
|
+
contained_labware = self.contained_labware_bottom_first
|
|
55
|
+
|
|
56
|
+
if update.contained_labware_bottom_first != NO_CHANGE:
|
|
57
|
+
contained_labware = update.contained_labware_bottom_first
|
|
58
|
+
|
|
59
|
+
return FlexStackerSubState(
|
|
60
|
+
module_id=self.module_id,
|
|
61
|
+
pool_primary_definition=pool_primary_definition,
|
|
62
|
+
pool_adapter_definition=pool_adapter_definition,
|
|
63
|
+
pool_lid_definition=pool_lid_definition,
|
|
64
|
+
contained_labware_bottom_first=contained_labware,
|
|
65
|
+
max_pool_count=max_pool_count,
|
|
66
|
+
pool_overlap=pool_overlap,
|
|
67
|
+
pool_height=pool_height,
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
def get_pool_definition_ordered_list(self) -> list[LabwareDefinition] | None:
|
|
71
|
+
"""Get the pool definitions in a list suitable for getting the height."""
|
|
72
|
+
if not self.pool_primary_definition:
|
|
73
|
+
return None
|
|
74
|
+
|
|
75
|
+
defs: list[LabwareDefinition] = []
|
|
76
|
+
if self.pool_lid_definition is not None:
|
|
77
|
+
defs.append(self.pool_lid_definition)
|
|
78
|
+
defs.append(self.pool_primary_definition)
|
|
79
|
+
if self.pool_adapter_definition is not None:
|
|
80
|
+
defs.append(self.pool_adapter_definition)
|
|
81
|
+
return defs
|
|
82
|
+
|
|
83
|
+
def get_pool_height_minus_overlap(self) -> float:
|
|
84
|
+
"""Get the height used in dispense/store action."""
|
|
85
|
+
return self.pool_height - self.pool_overlap
|
|
86
|
+
|
|
87
|
+
def get_contained_labware(self) -> list[StackerStoredLabwareGroup]:
|
|
88
|
+
"""Get the labware inside the hopper."""
|
|
89
|
+
return self.contained_labware_bottom_first
|
|
90
|
+
|
|
91
|
+
def get_max_pool_count(self) -> int | None:
|
|
92
|
+
"""Get the maximum number of currently-configured labware.
|
|
93
|
+
|
|
94
|
+
If the stacker has not been configured, return None.
|
|
95
|
+
"""
|
|
96
|
+
if not self.pool_primary_definition:
|
|
97
|
+
return None
|
|
98
|
+
return self.max_pool_count
|
|
99
|
+
|
|
100
|
+
def get_pool_overlap(self) -> float:
|
|
101
|
+
"""Get the overlap of the currently-configured labware."""
|
|
102
|
+
return self.pool_overlap
|
|
103
|
+
|
|
104
|
+
def get_pool_definition(self) -> StackerPoolDefinition | None:
|
|
105
|
+
"""Get the labware definitions of the stacker pool."""
|
|
106
|
+
if not self.pool_primary_definition:
|
|
107
|
+
return None
|
|
108
|
+
return StackerPoolDefinition(
|
|
109
|
+
primaryLabwareDefinition=self.pool_primary_definition,
|
|
110
|
+
adapterLabwareDefinition=self.pool_adapter_definition,
|
|
111
|
+
lidLabwareDefinition=self.pool_lid_definition,
|
|
112
|
+
)
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"""Heater-Shaker Module sub-state."""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import NewType, Optional
|
|
5
|
+
|
|
6
|
+
from opentrons.hardware_control.modules import ModuleDataValidator, ModuleData
|
|
7
|
+
from opentrons.protocol_engine.types import (
|
|
8
|
+
TemperatureRange,
|
|
9
|
+
SpeedRange,
|
|
10
|
+
HeaterShakerLatchStatus,
|
|
11
|
+
)
|
|
12
|
+
from opentrons.protocol_engine.errors import (
|
|
13
|
+
InvalidTargetTemperatureError,
|
|
14
|
+
InvalidTargetSpeedError,
|
|
15
|
+
NoTargetTemperatureSetError,
|
|
16
|
+
CannotPerformModuleAction,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
HeaterShakerModuleId = NewType("HeaterShakerModuleId", str)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
HEATER_SHAKER_TEMPERATURE_RANGE = TemperatureRange(min=0, max=95)
|
|
23
|
+
HEATER_SHAKER_SPEED_RANGE = SpeedRange(min=200, max=3000)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@dataclass(frozen=True)
|
|
27
|
+
class HeaterShakerModuleSubState:
|
|
28
|
+
"""Heater-Shaker-specific state.
|
|
29
|
+
|
|
30
|
+
Provides calculations and read-only state access
|
|
31
|
+
for an individual loaded Heater-Shaker Module.
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
module_id: HeaterShakerModuleId
|
|
35
|
+
labware_latch_status: HeaterShakerLatchStatus
|
|
36
|
+
is_plate_shaking: bool
|
|
37
|
+
plate_target_temperature: Optional[float]
|
|
38
|
+
|
|
39
|
+
def get_plate_target_temperature(self) -> float:
|
|
40
|
+
"""Get the module's target plate temperature."""
|
|
41
|
+
target = self.plate_target_temperature
|
|
42
|
+
|
|
43
|
+
if target is None:
|
|
44
|
+
raise NoTargetTemperatureSetError(
|
|
45
|
+
f"Module {self.module_id} does not have a target temperature set."
|
|
46
|
+
)
|
|
47
|
+
return target
|
|
48
|
+
|
|
49
|
+
@staticmethod
|
|
50
|
+
def validate_target_temperature(celsius: float) -> float:
|
|
51
|
+
"""Verify that the target temperature being set is valid for heater-shaker."""
|
|
52
|
+
if (
|
|
53
|
+
HEATER_SHAKER_TEMPERATURE_RANGE.min
|
|
54
|
+
<= celsius
|
|
55
|
+
<= HEATER_SHAKER_TEMPERATURE_RANGE.max
|
|
56
|
+
):
|
|
57
|
+
return celsius
|
|
58
|
+
else:
|
|
59
|
+
raise InvalidTargetTemperatureError(
|
|
60
|
+
f"Cannot set Heater-Shaker to {celsius} °C."
|
|
61
|
+
f" Valid range is {HEATER_SHAKER_TEMPERATURE_RANGE} °C."
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
@staticmethod
|
|
65
|
+
def validate_target_speed(rpm: float) -> int:
|
|
66
|
+
"""Verify that the target speed is valid for heater-shaker & convert to int."""
|
|
67
|
+
rpm_int = int(round(rpm, 0))
|
|
68
|
+
if HEATER_SHAKER_SPEED_RANGE.min <= rpm <= HEATER_SHAKER_SPEED_RANGE.max:
|
|
69
|
+
return rpm_int
|
|
70
|
+
else:
|
|
71
|
+
raise InvalidTargetSpeedError(
|
|
72
|
+
f"Cannot set Heater-Shaker to shake at {rpm} rpm. Valid speed range is "
|
|
73
|
+
f"{HEATER_SHAKER_SPEED_RANGE} rpm."
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
def raise_if_labware_latch_not_closed(self) -> None:
|
|
77
|
+
"""Raise an error if labware is not latched on the heater-shaker."""
|
|
78
|
+
if self.labware_latch_status == HeaterShakerLatchStatus.UNKNOWN:
|
|
79
|
+
raise CannotPerformModuleAction(
|
|
80
|
+
"Heater-Shaker cannot start or deactivate shaking if the labware latch has not been set to closed."
|
|
81
|
+
)
|
|
82
|
+
elif self.labware_latch_status == HeaterShakerLatchStatus.OPEN:
|
|
83
|
+
raise CannotPerformModuleAction(
|
|
84
|
+
"Heater-Shaker cannot start or deactivate shaking while the labware latch is open."
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
def raise_if_shaking(self) -> None:
|
|
88
|
+
"""Raise an error if the heater-shaker is currently shaking."""
|
|
89
|
+
if self.is_plate_shaking:
|
|
90
|
+
raise CannotPerformModuleAction(
|
|
91
|
+
"Heater-Shaker cannot open its labware latch while it is shaking."
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
@classmethod
|
|
95
|
+
def from_live_data(
|
|
96
|
+
cls, module_id: HeaterShakerModuleId, data: ModuleData | None
|
|
97
|
+
) -> "HeaterShakerModuleSubState":
|
|
98
|
+
"""Create a HeaterShakerModuleSubState from live data."""
|
|
99
|
+
if ModuleDataValidator.is_heater_shaker_data(data):
|
|
100
|
+
return cls(
|
|
101
|
+
module_id=module_id,
|
|
102
|
+
labware_latch_status=(
|
|
103
|
+
HeaterShakerLatchStatus.CLOSED
|
|
104
|
+
if data["labwareLatchStatus"] == "idle_closed"
|
|
105
|
+
else HeaterShakerLatchStatus.OPEN
|
|
106
|
+
),
|
|
107
|
+
is_plate_shaking=data["targetSpeed"] is not None,
|
|
108
|
+
plate_target_temperature=data["targetTemp"],
|
|
109
|
+
)
|
|
110
|
+
return cls(
|
|
111
|
+
module_id=module_id,
|
|
112
|
+
labware_latch_status=HeaterShakerLatchStatus.UNKNOWN,
|
|
113
|
+
is_plate_shaking=False,
|
|
114
|
+
plate_target_temperature=None,
|
|
115
|
+
)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""Magnetic block sub-state."""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import NewType
|
|
5
|
+
|
|
6
|
+
MagneticBlockId = NewType("MagneticBlockId", str)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@dataclass(frozen=True)
|
|
10
|
+
class MagneticBlockSubState:
|
|
11
|
+
"""Magnetic Block specific state.
|
|
12
|
+
|
|
13
|
+
Provides a read-only state access
|
|
14
|
+
for an individual loaded Magnetic Block.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
module_id: MagneticBlockId
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"""Magnetic module sub-state."""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import NewType
|
|
5
|
+
|
|
6
|
+
from opentrons.protocol_engine.types import MagneticModuleModel, ModuleModel
|
|
7
|
+
from opentrons.protocol_engine.errors import EngageHeightOutOfRangeError
|
|
8
|
+
from opentrons.hardware_control.modules.magdeck import (
|
|
9
|
+
engage_height_is_in_range,
|
|
10
|
+
OFFSET_TO_LABWARE_BOTTOM as MAGNETIC_MODULE_OFFSET_TO_LABWARE_BOTTOM,
|
|
11
|
+
MAX_ENGAGE_HEIGHT as MAGNETIC_MODULE_MAX_ENGAGE_HEIGHT,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
MagneticModuleId = NewType("MagneticModuleId", str)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass(frozen=True)
|
|
18
|
+
class MagneticModuleSubState:
|
|
19
|
+
"""Magnetic Module specific state.
|
|
20
|
+
|
|
21
|
+
Provides calculations and read-only state access
|
|
22
|
+
for an individual loaded Magnetic Module.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
module_id: MagneticModuleId
|
|
26
|
+
model: MagneticModuleModel
|
|
27
|
+
|
|
28
|
+
def calculate_magnet_hardware_height(self, mm_from_base: float) -> float:
|
|
29
|
+
"""Convert a human-friendly magnet height to be hardware-friendly.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
mm_from_base: The height to convert. Measured in how far the tops
|
|
33
|
+
of the magnets are above the labware base plane.
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
The same height, with its units and origin point converted
|
|
37
|
+
so that it's suitable to pass to `MagDeck.engage()`.
|
|
38
|
+
|
|
39
|
+
Raises:
|
|
40
|
+
EngageHeightOutOfRangeError: If modules of the given model are
|
|
41
|
+
physically incapable of reaching the requested height.
|
|
42
|
+
"""
|
|
43
|
+
hardware_units_from_base = (
|
|
44
|
+
mm_from_base * 2
|
|
45
|
+
if self.model == ModuleModel.MAGNETIC_MODULE_V1
|
|
46
|
+
else mm_from_base
|
|
47
|
+
)
|
|
48
|
+
home_to_base_offset = MAGNETIC_MODULE_OFFSET_TO_LABWARE_BOTTOM[self.model]
|
|
49
|
+
hardware_units_from_home = home_to_base_offset + hardware_units_from_base
|
|
50
|
+
|
|
51
|
+
if not engage_height_is_in_range(
|
|
52
|
+
model=self.model,
|
|
53
|
+
height=hardware_units_from_home,
|
|
54
|
+
):
|
|
55
|
+
# TODO(mm, 2022-03-02): This error message probably will not match how
|
|
56
|
+
# the user specified the height. (Hardware units versus mm,
|
|
57
|
+
# home as origin versus labware base as origin.) This may be confusing
|
|
58
|
+
# depending on how it propagates up.
|
|
59
|
+
raise EngageHeightOutOfRangeError(
|
|
60
|
+
f"Invalid engage height for {self.model}:"
|
|
61
|
+
f" {hardware_units_from_home}. Must be"
|
|
62
|
+
f" 0 - {MAGNETIC_MODULE_MAX_ENGAGE_HEIGHT[self.model]}."
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
return hardware_units_from_home
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"""Temperature module sub-state."""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import NewType, Optional
|
|
5
|
+
|
|
6
|
+
from opentrons.hardware_control.modules import ModuleDataValidator, ModuleData
|
|
7
|
+
from opentrons.protocol_engine.types import TemperatureRange
|
|
8
|
+
from opentrons.protocol_engine.errors import (
|
|
9
|
+
InvalidTargetTemperatureError,
|
|
10
|
+
NoTargetTemperatureSetError,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
TemperatureModuleId = NewType("TemperatureModuleId", str)
|
|
14
|
+
|
|
15
|
+
# TODO (spp, 2022-03-22): Move these values to temperature module definition.
|
|
16
|
+
TEMP_MODULE_TEMPERATURE_RANGE = TemperatureRange(min=-9, max=99)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@dataclass(frozen=True)
|
|
20
|
+
class TemperatureModuleSubState:
|
|
21
|
+
"""Temperature Module specific state.
|
|
22
|
+
|
|
23
|
+
Provides calculations and read-only state access
|
|
24
|
+
for an individual loaded Temperaute Module.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
module_id: TemperatureModuleId
|
|
28
|
+
plate_target_temperature: Optional[float]
|
|
29
|
+
|
|
30
|
+
@staticmethod
|
|
31
|
+
def validate_target_temperature(celsius: float) -> int:
|
|
32
|
+
"""Verify target temperature is within range and of correct type."""
|
|
33
|
+
# Both Gen1 & 2 Temperature modules use 0 decimal precision.
|
|
34
|
+
celsius_int = int(round(celsius, 0))
|
|
35
|
+
if (
|
|
36
|
+
TEMP_MODULE_TEMPERATURE_RANGE.min
|
|
37
|
+
<= celsius_int
|
|
38
|
+
<= TEMP_MODULE_TEMPERATURE_RANGE.max
|
|
39
|
+
):
|
|
40
|
+
return celsius_int
|
|
41
|
+
else:
|
|
42
|
+
raise InvalidTargetTemperatureError(
|
|
43
|
+
f"Temperature module got an invalid temperature {celsius} °C."
|
|
44
|
+
f" Valid range is {TEMP_MODULE_TEMPERATURE_RANGE}."
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
def get_plate_target_temperature(self) -> float:
|
|
48
|
+
"""Get the module's target plate temperature."""
|
|
49
|
+
target = self.plate_target_temperature
|
|
50
|
+
|
|
51
|
+
if target is None:
|
|
52
|
+
raise NoTargetTemperatureSetError(
|
|
53
|
+
f"Module {self.module_id} does not have a target temperature set."
|
|
54
|
+
)
|
|
55
|
+
return target
|
|
56
|
+
|
|
57
|
+
@classmethod
|
|
58
|
+
def from_live_data(
|
|
59
|
+
cls, module_id: TemperatureModuleId, data: ModuleData | None
|
|
60
|
+
) -> "TemperatureModuleSubState":
|
|
61
|
+
"""Create a TemperatureModuleSubState from live data."""
|
|
62
|
+
return cls(
|
|
63
|
+
module_id=module_id,
|
|
64
|
+
plate_target_temperature=data["targetTemp"]
|
|
65
|
+
if ModuleDataValidator.is_temperature_module_data(data)
|
|
66
|
+
else None,
|
|
67
|
+
)
|