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
opentrons/types.py
ADDED
|
@@ -0,0 +1,618 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
import enum
|
|
3
|
+
from math import sqrt, isclose
|
|
4
|
+
from typing import (
|
|
5
|
+
TYPE_CHECKING,
|
|
6
|
+
Any,
|
|
7
|
+
NamedTuple,
|
|
8
|
+
Iterator,
|
|
9
|
+
Union,
|
|
10
|
+
List,
|
|
11
|
+
Optional,
|
|
12
|
+
Protocol,
|
|
13
|
+
Dict,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
from opentrons_shared_data.robot.types import RobotType
|
|
17
|
+
|
|
18
|
+
from .protocols.api_support.labware_like import LabwareLike
|
|
19
|
+
|
|
20
|
+
if TYPE_CHECKING:
|
|
21
|
+
from .protocol_api.labware import Labware, Well
|
|
22
|
+
from .protocol_api.core.legacy.module_geometry import ModuleGeometry
|
|
23
|
+
from .protocol_api.module_contexts import ModuleContext
|
|
24
|
+
from .protocol_api._types import OffDeckType
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class PipetteNotAttachedError(KeyError):
|
|
28
|
+
"""An error raised if a pipette is accessed that is not attached"""
|
|
29
|
+
|
|
30
|
+
pass
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class Point(NamedTuple):
|
|
34
|
+
x: float = 0.0
|
|
35
|
+
y: float = 0.0
|
|
36
|
+
z: float = 0.0
|
|
37
|
+
|
|
38
|
+
def __add__(self, other: Any) -> Point:
|
|
39
|
+
if not isinstance(other, Point):
|
|
40
|
+
return NotImplemented
|
|
41
|
+
return Point(self.x + other.x, self.y + other.y, self.z + other.z)
|
|
42
|
+
|
|
43
|
+
def __sub__(self, other: Any) -> Point:
|
|
44
|
+
if not isinstance(other, Point):
|
|
45
|
+
return NotImplemented
|
|
46
|
+
return Point(self.x - other.x, self.y - other.y, self.z - other.z)
|
|
47
|
+
|
|
48
|
+
def __mul__(self, other: Union[int, float]) -> Point: # type: ignore[override]
|
|
49
|
+
if not isinstance(other, (float, int)):
|
|
50
|
+
return NotImplemented
|
|
51
|
+
return Point(self.x * other, self.y * other, self.z * other)
|
|
52
|
+
|
|
53
|
+
def __rmul__(self, other: Union[int, float]) -> Point: # type: ignore[override]
|
|
54
|
+
if not isinstance(other, (float, int)):
|
|
55
|
+
return NotImplemented
|
|
56
|
+
return Point(self.x * other, self.y * other, self.z * other)
|
|
57
|
+
|
|
58
|
+
def __abs__(self) -> Point:
|
|
59
|
+
return Point(abs(self.x), abs(self.y), abs(self.z))
|
|
60
|
+
|
|
61
|
+
def __str__(self) -> str:
|
|
62
|
+
return "({}, {}, {})".format(self.x, self.y, self.z)
|
|
63
|
+
|
|
64
|
+
def magnitude_to(self, other: Point) -> float:
|
|
65
|
+
x_diff = self.x - other.x
|
|
66
|
+
y_diff = self.y - other.y
|
|
67
|
+
z_diff = self.z - other.z
|
|
68
|
+
return sqrt(x_diff**2 + y_diff**2 + z_diff**2)
|
|
69
|
+
|
|
70
|
+
def elementwise_isclose(
|
|
71
|
+
self, other: Point, *, rel_tol: float = 1e-05, abs_tol: float = 1e-08
|
|
72
|
+
) -> bool:
|
|
73
|
+
pairs = ((self.x, other.x), (self.y, other.y), (self.z, other.z))
|
|
74
|
+
return all(isclose(s, o, rel_tol=rel_tol, abs_tol=abs_tol) for s, o in pairs)
|
|
75
|
+
|
|
76
|
+
@classmethod
|
|
77
|
+
def from_xyz_attrs(cls, has_xyz: _HasXYZ) -> Point:
|
|
78
|
+
"""Construct a Point from another object that has .x/.y/.z attributes."""
|
|
79
|
+
return cls(has_xyz.x, has_xyz.y, has_xyz.z)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class _HasXYZ(Protocol):
|
|
83
|
+
@property
|
|
84
|
+
def x(self) -> float:
|
|
85
|
+
...
|
|
86
|
+
|
|
87
|
+
@property
|
|
88
|
+
def y(self) -> float:
|
|
89
|
+
...
|
|
90
|
+
|
|
91
|
+
@property
|
|
92
|
+
def z(self) -> float:
|
|
93
|
+
...
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
LocationLabware = Union[
|
|
97
|
+
"Labware",
|
|
98
|
+
"Well",
|
|
99
|
+
str,
|
|
100
|
+
"ModuleGeometry",
|
|
101
|
+
LabwareLike,
|
|
102
|
+
None,
|
|
103
|
+
"OffDeckType",
|
|
104
|
+
"ModuleContext",
|
|
105
|
+
]
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
class MeniscusTrackingTarget(enum.Enum):
|
|
109
|
+
START = "start"
|
|
110
|
+
END = "end"
|
|
111
|
+
DYNAMIC = "dynamic"
|
|
112
|
+
|
|
113
|
+
def __str__(self) -> str:
|
|
114
|
+
return self.name
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
class Location:
|
|
118
|
+
"""Location(point: Point, labware: Union["Labware", "Well", str, "ModuleGeometry", LabwareLike, None, "ModuleContext"])
|
|
119
|
+
|
|
120
|
+
A location to target as a motion.
|
|
121
|
+
|
|
122
|
+
The location contains a :py:class:`.Point` (in
|
|
123
|
+
:ref:`protocol-api-deck-coords`) and possibly an associated
|
|
124
|
+
:py:class:`.Labware` or :py:class:`.Well` instance.
|
|
125
|
+
|
|
126
|
+
It should rarely be constructed directly by the user; rather, it is the
|
|
127
|
+
return type of most :py:class:`.Well` accessors like :py:meth:`.Well.top`
|
|
128
|
+
and is passed directly into a method like ``InstrumentContext.aspirate()``.
|
|
129
|
+
|
|
130
|
+
.. warning::
|
|
131
|
+
The ``.labware`` attribute of this class is used by the protocol
|
|
132
|
+
API internals to, among other things, determine safe heights to retract
|
|
133
|
+
the instruments to when moving between locations. If constructing an
|
|
134
|
+
instance of this class manually, be sure to either specify ``None`` as the
|
|
135
|
+
labware (so the robot does its worst case retraction) or specify the
|
|
136
|
+
correct labware for the ``.point`` attribute.
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
.. warning::
|
|
140
|
+
The ``==`` operation compares both the position and associated labware.
|
|
141
|
+
If you only need to compare locations, compare the ``.point``
|
|
142
|
+
of each item.
|
|
143
|
+
"""
|
|
144
|
+
|
|
145
|
+
def __init__(
|
|
146
|
+
self,
|
|
147
|
+
point: Point,
|
|
148
|
+
labware: Union[
|
|
149
|
+
"Labware",
|
|
150
|
+
"Well",
|
|
151
|
+
str,
|
|
152
|
+
"ModuleGeometry",
|
|
153
|
+
LabwareLike,
|
|
154
|
+
None,
|
|
155
|
+
"ModuleContext",
|
|
156
|
+
],
|
|
157
|
+
*,
|
|
158
|
+
_meniscus_tracking: Optional[MeniscusTrackingTarget] = None,
|
|
159
|
+
):
|
|
160
|
+
self._point = point
|
|
161
|
+
self._given_labware = labware
|
|
162
|
+
self._labware = LabwareLike(labware)
|
|
163
|
+
self._meniscus_tracking = _meniscus_tracking
|
|
164
|
+
|
|
165
|
+
# todo(mm, 2021-10-01): Figure out how to get .point and .labware to show up
|
|
166
|
+
# in the rendered docs, and then update the class docstring to use cross-references.
|
|
167
|
+
|
|
168
|
+
@property
|
|
169
|
+
def point(self) -> Point:
|
|
170
|
+
return self._point
|
|
171
|
+
|
|
172
|
+
@property
|
|
173
|
+
def labware(self) -> LabwareLike:
|
|
174
|
+
return self._labware
|
|
175
|
+
|
|
176
|
+
@property
|
|
177
|
+
def meniscus_tracking(self) -> Optional[MeniscusTrackingTarget]:
|
|
178
|
+
return self._meniscus_tracking
|
|
179
|
+
|
|
180
|
+
def __iter__(self) -> Iterator[Union[Point, LabwareLike]]:
|
|
181
|
+
"""Iterable interface to support unpacking. Like a tuple.
|
|
182
|
+
|
|
183
|
+
.. note::
|
|
184
|
+
While type annotations cannot properly support this, it will work in practice:
|
|
185
|
+
|
|
186
|
+
point, labware = location
|
|
187
|
+
some_function_taking_both(*location)
|
|
188
|
+
"""
|
|
189
|
+
return iter((self._point, self._labware))
|
|
190
|
+
|
|
191
|
+
def __eq__(self, other: object) -> bool:
|
|
192
|
+
return (
|
|
193
|
+
isinstance(other, Location)
|
|
194
|
+
and other._point == self._point
|
|
195
|
+
and other._labware == self._labware
|
|
196
|
+
and other._meniscus_tracking == self._meniscus_tracking
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
def move(self, point: Point) -> "Location":
|
|
200
|
+
"""
|
|
201
|
+
Alter the point stored in the location while preserving the labware.
|
|
202
|
+
|
|
203
|
+
This returns a new Location and does not alter the current one. It
|
|
204
|
+
should be used like
|
|
205
|
+
|
|
206
|
+
.. code-block:: python
|
|
207
|
+
|
|
208
|
+
>>> loc = Location(Point(1, 1, 1), None)
|
|
209
|
+
>>> new_loc = loc.move(Point(1, 1, 1))
|
|
210
|
+
>>>
|
|
211
|
+
>>> # The new point is the old one plus the given offset.
|
|
212
|
+
>>> assert new_loc.point == Point(2, 2, 2) # True
|
|
213
|
+
>>>
|
|
214
|
+
>>> # The old point hasn't changed.
|
|
215
|
+
>>> assert loc.point == Point(1, 1, 1) # True
|
|
216
|
+
|
|
217
|
+
"""
|
|
218
|
+
|
|
219
|
+
return Location(
|
|
220
|
+
point=self.point + point,
|
|
221
|
+
labware=self._given_labware,
|
|
222
|
+
_meniscus_tracking=self._meniscus_tracking,
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
def __repr__(self) -> str:
|
|
226
|
+
return f"Location(point={repr(self._point)}, labware={self._labware}, meniscus_tracking={self._meniscus_tracking})"
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
# TODO(mc, 2020-10-22): use MountType implementation for Mount
|
|
230
|
+
class Mount(enum.Enum):
|
|
231
|
+
LEFT = enum.auto()
|
|
232
|
+
RIGHT = enum.auto()
|
|
233
|
+
EXTENSION = enum.auto()
|
|
234
|
+
|
|
235
|
+
def __str__(self) -> str:
|
|
236
|
+
return self.name
|
|
237
|
+
|
|
238
|
+
@classmethod
|
|
239
|
+
def ot2_mounts(cls) -> List["Mount"]:
|
|
240
|
+
return [Mount.LEFT, Mount.RIGHT]
|
|
241
|
+
|
|
242
|
+
@classmethod
|
|
243
|
+
def string_to_mount(cls, mount: str) -> "Mount":
|
|
244
|
+
if mount == "right":
|
|
245
|
+
return cls.RIGHT
|
|
246
|
+
elif mount == "left":
|
|
247
|
+
return cls.LEFT
|
|
248
|
+
else:
|
|
249
|
+
return cls.EXTENSION
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
class MountType(str, enum.Enum):
|
|
253
|
+
LEFT = "left"
|
|
254
|
+
RIGHT = "right"
|
|
255
|
+
EXTENSION = "extension"
|
|
256
|
+
|
|
257
|
+
# TODO (spp, 2023-05-04): we should deprecate this and instead create an 'other_pipette_mount' method
|
|
258
|
+
def other_mount(self) -> MountType:
|
|
259
|
+
return MountType.LEFT if self is MountType.RIGHT else MountType.RIGHT
|
|
260
|
+
|
|
261
|
+
def to_hw_mount(self) -> Mount:
|
|
262
|
+
return {
|
|
263
|
+
MountType.LEFT: Mount.LEFT,
|
|
264
|
+
MountType.RIGHT: Mount.RIGHT,
|
|
265
|
+
MountType.EXTENSION: Mount.EXTENSION,
|
|
266
|
+
}[self]
|
|
267
|
+
|
|
268
|
+
@staticmethod
|
|
269
|
+
def from_hw_mount(mount: Mount) -> MountType:
|
|
270
|
+
"""Convert from Mount to MountType."""
|
|
271
|
+
mount_map = {Mount.LEFT: MountType.LEFT, Mount.RIGHT: MountType.RIGHT}
|
|
272
|
+
return mount_map[mount]
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
class PipetteMountType(enum.Enum):
|
|
276
|
+
LEFT = "left"
|
|
277
|
+
RIGHT = "right"
|
|
278
|
+
COMBINED = "combined" # added for 96-channel. Remove if not required
|
|
279
|
+
|
|
280
|
+
def to_mount_type(self) -> MountType:
|
|
281
|
+
return {
|
|
282
|
+
PipetteMountType.LEFT: MountType.LEFT,
|
|
283
|
+
PipetteMountType.RIGHT: MountType.RIGHT,
|
|
284
|
+
}[self]
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
# What is this used for? Can we consolidate this into MountType?
|
|
288
|
+
# If not, can we change the 'GRIPPER' mount name to 'EXTENSION' so that it's
|
|
289
|
+
# consistent with all user-facing mount names?
|
|
290
|
+
class OT3MountType(str, enum.Enum):
|
|
291
|
+
LEFT = "left"
|
|
292
|
+
RIGHT = "right"
|
|
293
|
+
GRIPPER = "gripper"
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
class AxisType(enum.Enum):
|
|
297
|
+
X = "X" # gantry
|
|
298
|
+
Y = "Y"
|
|
299
|
+
Z_L = "Z_L" # left pipette mount Z
|
|
300
|
+
Z_R = "Z_R" # right pipette mount Z
|
|
301
|
+
Z_G = "Z_G" # gripper mount Z
|
|
302
|
+
P_L = "P_L" # left pipette plunger
|
|
303
|
+
P_R = "P_R" # right pipette plunger
|
|
304
|
+
Q = "Q" # hi-throughput pipette tiprack grab
|
|
305
|
+
G = "G" # gripper grab
|
|
306
|
+
|
|
307
|
+
@classmethod
|
|
308
|
+
def axis_for_mount(cls, mount: Mount) -> "AxisType":
|
|
309
|
+
map_axis_to_mount = {
|
|
310
|
+
Mount.LEFT: cls.Z_L,
|
|
311
|
+
Mount.RIGHT: cls.Z_R,
|
|
312
|
+
Mount.EXTENSION: cls.Z_G,
|
|
313
|
+
}
|
|
314
|
+
return map_axis_to_mount[mount]
|
|
315
|
+
|
|
316
|
+
@classmethod
|
|
317
|
+
def mount_for_axis(cls, axis: "AxisType") -> Mount:
|
|
318
|
+
map_mount_to_axis = {
|
|
319
|
+
cls.Z_L: Mount.LEFT,
|
|
320
|
+
cls.Z_R: Mount.RIGHT,
|
|
321
|
+
cls.Z_G: Mount.EXTENSION,
|
|
322
|
+
}
|
|
323
|
+
return map_mount_to_axis[axis]
|
|
324
|
+
|
|
325
|
+
@classmethod
|
|
326
|
+
def plunger_axis_for_mount(cls, mount: Mount) -> "AxisType":
|
|
327
|
+
map_plunger_axis_mount = {Mount.LEFT: cls.P_L, Mount.RIGHT: cls.P_R}
|
|
328
|
+
return map_plunger_axis_mount[mount]
|
|
329
|
+
|
|
330
|
+
@classmethod
|
|
331
|
+
def ot2_axes(cls) -> List["AxisType"]:
|
|
332
|
+
return [
|
|
333
|
+
AxisType.X,
|
|
334
|
+
AxisType.Y,
|
|
335
|
+
AxisType.Z_L,
|
|
336
|
+
AxisType.Z_R,
|
|
337
|
+
AxisType.P_L,
|
|
338
|
+
AxisType.P_R,
|
|
339
|
+
]
|
|
340
|
+
|
|
341
|
+
@classmethod
|
|
342
|
+
def flex_gantry_axes(cls) -> List["AxisType"]:
|
|
343
|
+
return [
|
|
344
|
+
AxisType.X,
|
|
345
|
+
AxisType.Y,
|
|
346
|
+
AxisType.Z_L,
|
|
347
|
+
AxisType.Z_R,
|
|
348
|
+
AxisType.Z_G,
|
|
349
|
+
]
|
|
350
|
+
|
|
351
|
+
@classmethod
|
|
352
|
+
def ot2_gantry_axes(cls) -> List["AxisType"]:
|
|
353
|
+
return [
|
|
354
|
+
AxisType.X,
|
|
355
|
+
AxisType.Y,
|
|
356
|
+
AxisType.Z_L,
|
|
357
|
+
AxisType.Z_R,
|
|
358
|
+
]
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
AxisMapType = Dict[AxisType, float]
|
|
362
|
+
StringAxisMap = Dict[str, float]
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
# TODO(mc, 2020-11-09): this makes sense in shared-data or other common
|
|
366
|
+
# model library
|
|
367
|
+
# https://github.com/Opentrons/opentrons/pull/6943#discussion_r519029833
|
|
368
|
+
class DeckSlotName(enum.Enum):
|
|
369
|
+
"""Deck slot identifiers."""
|
|
370
|
+
|
|
371
|
+
# OT-2:
|
|
372
|
+
SLOT_1 = "1"
|
|
373
|
+
SLOT_2 = "2"
|
|
374
|
+
SLOT_3 = "3"
|
|
375
|
+
SLOT_4 = "4"
|
|
376
|
+
SLOT_5 = "5"
|
|
377
|
+
SLOT_6 = "6"
|
|
378
|
+
SLOT_7 = "7"
|
|
379
|
+
SLOT_8 = "8"
|
|
380
|
+
SLOT_9 = "9"
|
|
381
|
+
SLOT_10 = "10"
|
|
382
|
+
SLOT_11 = "11"
|
|
383
|
+
FIXED_TRASH = "12"
|
|
384
|
+
|
|
385
|
+
# OT-3:
|
|
386
|
+
SLOT_A1 = "A1"
|
|
387
|
+
SLOT_A2 = "A2"
|
|
388
|
+
SLOT_A3 = "A3"
|
|
389
|
+
SLOT_B1 = "B1"
|
|
390
|
+
SLOT_B2 = "B2"
|
|
391
|
+
SLOT_B3 = "B3"
|
|
392
|
+
SLOT_C1 = "C1"
|
|
393
|
+
SLOT_C2 = "C2"
|
|
394
|
+
SLOT_C3 = "C3"
|
|
395
|
+
SLOT_D1 = "D1"
|
|
396
|
+
SLOT_D2 = "D2"
|
|
397
|
+
SLOT_D3 = "D3"
|
|
398
|
+
|
|
399
|
+
@classmethod
|
|
400
|
+
def from_primitive(cls, value: DeckLocation) -> DeckSlotName:
|
|
401
|
+
str_val = str(value).upper()
|
|
402
|
+
return cls(str_val)
|
|
403
|
+
|
|
404
|
+
@classmethod
|
|
405
|
+
def ot3_slots(cls) -> List["DeckSlotName"]:
|
|
406
|
+
return [
|
|
407
|
+
DeckSlotName.SLOT_A1,
|
|
408
|
+
DeckSlotName.SLOT_A2,
|
|
409
|
+
DeckSlotName.SLOT_A3,
|
|
410
|
+
DeckSlotName.SLOT_B1,
|
|
411
|
+
DeckSlotName.SLOT_B2,
|
|
412
|
+
DeckSlotName.SLOT_B3,
|
|
413
|
+
DeckSlotName.SLOT_C1,
|
|
414
|
+
DeckSlotName.SLOT_C2,
|
|
415
|
+
DeckSlotName.SLOT_C3,
|
|
416
|
+
DeckSlotName.SLOT_D1,
|
|
417
|
+
DeckSlotName.SLOT_D2,
|
|
418
|
+
DeckSlotName.SLOT_D3,
|
|
419
|
+
]
|
|
420
|
+
|
|
421
|
+
# TODO(mm, 2023-05-08):
|
|
422
|
+
# Migrate callers off of this method. https://opentrons.atlassian.net/browse/RLAB-345
|
|
423
|
+
def as_int(self) -> int:
|
|
424
|
+
"""Return this deck slot as an OT-2-style integer.
|
|
425
|
+
|
|
426
|
+
For example, `SLOT_5.as_int()` and `SLOT_C2.as_int()` are both `5`.
|
|
427
|
+
|
|
428
|
+
Deprecated:
|
|
429
|
+
This will not make sense when the OT-3 has staging area slots.
|
|
430
|
+
"""
|
|
431
|
+
return int(self.to_ot2_equivalent().value)
|
|
432
|
+
|
|
433
|
+
def to_ot2_equivalent(self) -> DeckSlotName:
|
|
434
|
+
"""Return the OT-2 deck slot that's in the same place as this one.
|
|
435
|
+
|
|
436
|
+
For example, `SLOT_C2.to_ot3_equivalent()` is `SLOT_5`.
|
|
437
|
+
|
|
438
|
+
If this is already an OT-2 deck slot, returns itself.
|
|
439
|
+
"""
|
|
440
|
+
return _ot3_to_ot2.get(self, self)
|
|
441
|
+
|
|
442
|
+
def to_ot3_equivalent(self) -> DeckSlotName:
|
|
443
|
+
"""Return the OT-3 deck slot that's in the same place as this one.
|
|
444
|
+
|
|
445
|
+
For example, `SLOT_5.to_ot3_equivalent()` is `SLOT_C2`.
|
|
446
|
+
|
|
447
|
+
If this is already an OT-3 deck slot, returns itself.
|
|
448
|
+
"""
|
|
449
|
+
return _ot2_to_ot3.get(self, self)
|
|
450
|
+
|
|
451
|
+
def to_equivalent_for_robot_type(self, robot_type: RobotType) -> DeckSlotName:
|
|
452
|
+
"""Return the deck slot, for the given robot type, that's in the same place as this one.
|
|
453
|
+
|
|
454
|
+
See `to_ot2_equivalent()` and `to_ot3_equivalent()`.
|
|
455
|
+
"""
|
|
456
|
+
if robot_type == "OT-2 Standard":
|
|
457
|
+
return self.to_ot2_equivalent()
|
|
458
|
+
elif robot_type == "OT-3 Standard":
|
|
459
|
+
return self.to_ot3_equivalent()
|
|
460
|
+
|
|
461
|
+
@property
|
|
462
|
+
def id(self) -> str:
|
|
463
|
+
"""This slot's unique ID, as it appears in the deck definition.
|
|
464
|
+
|
|
465
|
+
This can be used to look up slot details in the deck definition.
|
|
466
|
+
|
|
467
|
+
This is preferred over `.value` or `.__str__()` for explicitness.
|
|
468
|
+
"""
|
|
469
|
+
return self.value
|
|
470
|
+
|
|
471
|
+
def __str__(self) -> str:
|
|
472
|
+
"""Stringify to the unique ID.
|
|
473
|
+
|
|
474
|
+
For explicitness, prefer using `.id` instead.
|
|
475
|
+
"""
|
|
476
|
+
return self.id
|
|
477
|
+
|
|
478
|
+
|
|
479
|
+
_slot_equivalencies = [
|
|
480
|
+
(DeckSlotName.SLOT_1, DeckSlotName.SLOT_D1),
|
|
481
|
+
(DeckSlotName.SLOT_2, DeckSlotName.SLOT_D2),
|
|
482
|
+
(DeckSlotName.SLOT_3, DeckSlotName.SLOT_D3),
|
|
483
|
+
(DeckSlotName.SLOT_4, DeckSlotName.SLOT_C1),
|
|
484
|
+
(DeckSlotName.SLOT_5, DeckSlotName.SLOT_C2),
|
|
485
|
+
(DeckSlotName.SLOT_6, DeckSlotName.SLOT_C3),
|
|
486
|
+
(DeckSlotName.SLOT_7, DeckSlotName.SLOT_B1),
|
|
487
|
+
(DeckSlotName.SLOT_8, DeckSlotName.SLOT_B2),
|
|
488
|
+
(DeckSlotName.SLOT_9, DeckSlotName.SLOT_B3),
|
|
489
|
+
(DeckSlotName.SLOT_10, DeckSlotName.SLOT_A1),
|
|
490
|
+
(DeckSlotName.SLOT_11, DeckSlotName.SLOT_A2),
|
|
491
|
+
(DeckSlotName.FIXED_TRASH, DeckSlotName.SLOT_A3),
|
|
492
|
+
]
|
|
493
|
+
|
|
494
|
+
_ot2_to_ot3 = {ot2: ot3 for ot2, ot3 in _slot_equivalencies}
|
|
495
|
+
_ot3_to_ot2 = {ot3: ot2 for ot2, ot3 in _slot_equivalencies}
|
|
496
|
+
|
|
497
|
+
|
|
498
|
+
# TODO(jbl 11-17-2023) move this away from being an Enum and make this a NewType or something similar
|
|
499
|
+
class StagingSlotName(enum.Enum):
|
|
500
|
+
"""Staging slot identifiers."""
|
|
501
|
+
|
|
502
|
+
SLOT_A4 = "A4"
|
|
503
|
+
SLOT_B4 = "B4"
|
|
504
|
+
SLOT_C4 = "C4"
|
|
505
|
+
SLOT_D4 = "D4"
|
|
506
|
+
|
|
507
|
+
@classmethod
|
|
508
|
+
def from_primitive(cls, value: str) -> StagingSlotName:
|
|
509
|
+
str_val = value.upper()
|
|
510
|
+
return cls(str_val)
|
|
511
|
+
|
|
512
|
+
@property
|
|
513
|
+
def id(self) -> str:
|
|
514
|
+
"""This slot's unique ID, as it appears in the deck definition.
|
|
515
|
+
|
|
516
|
+
This can be used to look up slot details in the deck definition.
|
|
517
|
+
|
|
518
|
+
This is preferred over `.value` or `.__str__()` for explicitness.
|
|
519
|
+
"""
|
|
520
|
+
return self.value
|
|
521
|
+
|
|
522
|
+
def __str__(self) -> str:
|
|
523
|
+
"""Stringify to the unique ID.
|
|
524
|
+
|
|
525
|
+
For explicitness, prefer using `.id` instead.
|
|
526
|
+
"""
|
|
527
|
+
return self.id
|
|
528
|
+
|
|
529
|
+
|
|
530
|
+
class TransferTipPolicy(enum.Enum):
|
|
531
|
+
ONCE = enum.auto()
|
|
532
|
+
NEVER = enum.auto()
|
|
533
|
+
ALWAYS = enum.auto()
|
|
534
|
+
|
|
535
|
+
|
|
536
|
+
DeckLocation = Union[int, str]
|
|
537
|
+
ALLOWED_PRIMARY_NOZZLES = ["A1", "H1", "A12", "H12"]
|
|
538
|
+
|
|
539
|
+
|
|
540
|
+
class NozzleConfigurationType(enum.Enum):
|
|
541
|
+
"""Short names for types of nozzle configurations.
|
|
542
|
+
|
|
543
|
+
Represents the current nozzle configuration stored in a NozzleMap.
|
|
544
|
+
"""
|
|
545
|
+
|
|
546
|
+
COLUMN = "COLUMN"
|
|
547
|
+
ROW = "ROW"
|
|
548
|
+
SINGLE = "SINGLE"
|
|
549
|
+
FULL = "FULL"
|
|
550
|
+
SUBRECT = "SUBRECT"
|
|
551
|
+
|
|
552
|
+
|
|
553
|
+
class NozzleMapInterface(Protocol):
|
|
554
|
+
"""
|
|
555
|
+
A NozzleMap instance represents a specific configuration of active nozzles on a pipette.
|
|
556
|
+
|
|
557
|
+
It exposes properties of the configuration like the configuration's front-right, front-left,
|
|
558
|
+
back-left and starting nozzles as well as a map of all the nozzles active in the configuration.
|
|
559
|
+
|
|
560
|
+
Because NozzleMaps represent configurations directly, the properties of the NozzleMap may not
|
|
561
|
+
match the properties of the physical pipette. For instance, a NozzleMap for a single channel
|
|
562
|
+
configuration of an 8-channel pipette - say, A1 only - will have its front left, front right,
|
|
563
|
+
and active channels all be A1, while the physical configuration would have the front right
|
|
564
|
+
channel be H1.
|
|
565
|
+
"""
|
|
566
|
+
|
|
567
|
+
@property
|
|
568
|
+
def starting_nozzle(self) -> str:
|
|
569
|
+
"""The nozzle that automated operations that count nozzles should start at."""
|
|
570
|
+
...
|
|
571
|
+
|
|
572
|
+
@property
|
|
573
|
+
def rows(self) -> dict[str, list[str]]:
|
|
574
|
+
"""A map of all the rows active in this configuration."""
|
|
575
|
+
...
|
|
576
|
+
|
|
577
|
+
@property
|
|
578
|
+
def columns(self) -> dict[str, list[str]]:
|
|
579
|
+
"""A map of all the columns active in this configuration."""
|
|
580
|
+
...
|
|
581
|
+
|
|
582
|
+
@property
|
|
583
|
+
def back_left(self) -> str:
|
|
584
|
+
"""The backest, leftest (i.e. back if it's a column, left if it's a row) nozzle of the configuration.
|
|
585
|
+
|
|
586
|
+
Note: This is the value relevant for this particular configuration, and it may not represent the back left nozzle
|
|
587
|
+
of the underlying physical pipette. For instance, the back-left nozzle of a configuration representing nozzles
|
|
588
|
+
D7 to H12 of a 96-channel pipette is D7, which is not the back-left nozzle of the physical pipette (A1).
|
|
589
|
+
"""
|
|
590
|
+
...
|
|
591
|
+
|
|
592
|
+
@property
|
|
593
|
+
def configuration(self) -> NozzleConfigurationType:
|
|
594
|
+
"""The kind of configuration represented by this nozzle map."""
|
|
595
|
+
...
|
|
596
|
+
|
|
597
|
+
@property
|
|
598
|
+
def front_right(self) -> str:
|
|
599
|
+
"""The frontest, rightest (i.e. front if it's a column, right if it's a row) nozzle of the configuration.
|
|
600
|
+
|
|
601
|
+
Note: This is the value relevant for this configuration, not the physical pipette. See the note on back_left.
|
|
602
|
+
"""
|
|
603
|
+
...
|
|
604
|
+
|
|
605
|
+
@property
|
|
606
|
+
def tip_count(self) -> int:
|
|
607
|
+
"""The total number of active nozzles in the configuration, and thus the number of tips that will be picked up."""
|
|
608
|
+
...
|
|
609
|
+
|
|
610
|
+
@property
|
|
611
|
+
def physical_nozzle_count(self) -> int:
|
|
612
|
+
"""The number of actual physical nozzles on the pipette, regardless of configuration."""
|
|
613
|
+
...
|
|
614
|
+
|
|
615
|
+
@property
|
|
616
|
+
def active_nozzles(self) -> list[str]:
|
|
617
|
+
"""An unstructured list of all nozzles active in the configuration."""
|
|
618
|
+
...
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Things that are independent from Opentrons business logic, like data structures."""
|