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,420 @@
|
|
|
1
|
+
"""Tip state tracking."""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from enum import Enum
|
|
5
|
+
from typing import Dict, Iterable, Optional, List, Union
|
|
6
|
+
|
|
7
|
+
from opentrons.types import NozzleMapInterface
|
|
8
|
+
from opentrons.protocol_engine.state import update_types
|
|
9
|
+
|
|
10
|
+
from ._abstract_store import HasState, HandlesActions
|
|
11
|
+
from ._well_math import wells_covered_dense
|
|
12
|
+
from ..actions import Action, ResetTipsAction, get_state_updates
|
|
13
|
+
|
|
14
|
+
from opentrons.hardware_control.nozzle_manager import NozzleMap
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class _TipRackWellState(Enum):
|
|
18
|
+
"""The state of a single tip in a tip rack's well."""
|
|
19
|
+
|
|
20
|
+
CLEAN = "clean"
|
|
21
|
+
USED = "used"
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
_TipRackStateByWellName = Dict[str, _TipRackWellState]
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@dataclass
|
|
28
|
+
class TipState:
|
|
29
|
+
"""State of all tips."""
|
|
30
|
+
|
|
31
|
+
tips_by_labware_id: Dict[str, _TipRackStateByWellName]
|
|
32
|
+
columns_by_labware_id: Dict[str, List[List[str]]]
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class TipStore(HasState[TipState], HandlesActions):
|
|
36
|
+
"""Tip state container."""
|
|
37
|
+
|
|
38
|
+
_state: TipState
|
|
39
|
+
|
|
40
|
+
def __init__(self) -> None:
|
|
41
|
+
"""Initialize a liquid store and its state."""
|
|
42
|
+
self._state = TipState(
|
|
43
|
+
tips_by_labware_id={},
|
|
44
|
+
columns_by_labware_id={},
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
def handle_action(self, action: Action) -> None:
|
|
48
|
+
"""Modify state in reaction to an action."""
|
|
49
|
+
for state_update in get_state_updates(action):
|
|
50
|
+
self._handle_state_update(state_update)
|
|
51
|
+
|
|
52
|
+
if isinstance(action, ResetTipsAction):
|
|
53
|
+
labware_id = action.labware_id
|
|
54
|
+
|
|
55
|
+
for well_name in self._state.tips_by_labware_id[labware_id].keys():
|
|
56
|
+
self._state.tips_by_labware_id[labware_id][
|
|
57
|
+
well_name
|
|
58
|
+
] = _TipRackWellState.CLEAN
|
|
59
|
+
|
|
60
|
+
def _handle_state_update(self, state_update: update_types.StateUpdate) -> None:
|
|
61
|
+
if state_update.tips_used != update_types.NO_CHANGE:
|
|
62
|
+
self._set_used_tips(
|
|
63
|
+
labware_id=state_update.tips_used.labware_id,
|
|
64
|
+
well_names=state_update.tips_used.well_names,
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
if state_update.loaded_labware != update_types.NO_CHANGE:
|
|
68
|
+
labware_id = state_update.loaded_labware.labware_id
|
|
69
|
+
definition = state_update.loaded_labware.definition
|
|
70
|
+
if definition.parameters.isTiprack:
|
|
71
|
+
self._state.tips_by_labware_id[labware_id] = {
|
|
72
|
+
well_name: _TipRackWellState.CLEAN
|
|
73
|
+
for column in definition.ordering
|
|
74
|
+
for well_name in column
|
|
75
|
+
}
|
|
76
|
+
self._state.columns_by_labware_id[labware_id] = [
|
|
77
|
+
column for column in definition.ordering
|
|
78
|
+
]
|
|
79
|
+
if state_update.batch_loaded_labware != update_types.NO_CHANGE:
|
|
80
|
+
for labware_id in state_update.batch_loaded_labware.new_locations_by_id:
|
|
81
|
+
definition = state_update.batch_loaded_labware.definitions_by_id[
|
|
82
|
+
labware_id
|
|
83
|
+
]
|
|
84
|
+
if definition.parameters.isTiprack:
|
|
85
|
+
self._state.tips_by_labware_id[labware_id] = {
|
|
86
|
+
well_name: _TipRackWellState.CLEAN
|
|
87
|
+
for column in definition.ordering
|
|
88
|
+
for well_name in column
|
|
89
|
+
}
|
|
90
|
+
self._state.columns_by_labware_id[labware_id] = [
|
|
91
|
+
column for column in definition.ordering
|
|
92
|
+
]
|
|
93
|
+
|
|
94
|
+
def _set_used_tips(self, labware_id: str, well_names: Iterable[str]) -> None:
|
|
95
|
+
well_states = self._state.tips_by_labware_id.get(labware_id, {})
|
|
96
|
+
for well_name in well_names:
|
|
97
|
+
well_states[well_name] = _TipRackWellState.USED
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
class TipView:
|
|
101
|
+
"""Read-only tip state view."""
|
|
102
|
+
|
|
103
|
+
_state: TipState
|
|
104
|
+
|
|
105
|
+
def __init__(self, state: TipState) -> None:
|
|
106
|
+
"""Initialize the computed view of liquid state.
|
|
107
|
+
|
|
108
|
+
Arguments:
|
|
109
|
+
state: Liquid state dataclass used for all calculations.
|
|
110
|
+
"""
|
|
111
|
+
self._state = state
|
|
112
|
+
|
|
113
|
+
def get_next_tip( # noqa: C901
|
|
114
|
+
self,
|
|
115
|
+
labware_id: str,
|
|
116
|
+
num_tips: int,
|
|
117
|
+
starting_tip_name: Optional[str],
|
|
118
|
+
nozzle_map: Optional[NozzleMapInterface],
|
|
119
|
+
) -> Optional[str]:
|
|
120
|
+
"""Get the next available clean tip. Does not support use of a starting tip if the pipette used is in a partial configuration."""
|
|
121
|
+
wells = self._state.tips_by_labware_id.get(labware_id, {})
|
|
122
|
+
columns = self._state.columns_by_labware_id.get(labware_id, [])
|
|
123
|
+
|
|
124
|
+
# TODO(sf): I'm pretty sure this can be replaced with wells_covered_96 but I'm not quite sure how
|
|
125
|
+
def _identify_tip_cluster(
|
|
126
|
+
active_columns: int,
|
|
127
|
+
active_rows: int,
|
|
128
|
+
critical_column: int,
|
|
129
|
+
critical_row: int,
|
|
130
|
+
entry_well: str,
|
|
131
|
+
) -> Optional[List[str]]:
|
|
132
|
+
tip_cluster: list[str] = []
|
|
133
|
+
for i in range(active_columns):
|
|
134
|
+
if entry_well == "A1" or entry_well == "H1":
|
|
135
|
+
if critical_column - i >= 0:
|
|
136
|
+
column = columns[critical_column - i]
|
|
137
|
+
else:
|
|
138
|
+
return None
|
|
139
|
+
elif entry_well == "A12" or entry_well == "H12":
|
|
140
|
+
if critical_column + i < len(columns):
|
|
141
|
+
column = columns[critical_column + i]
|
|
142
|
+
else:
|
|
143
|
+
return None
|
|
144
|
+
else:
|
|
145
|
+
raise ValueError(
|
|
146
|
+
f"Invalid entry well {entry_well} for tip cluster identification."
|
|
147
|
+
)
|
|
148
|
+
for j in range(active_rows):
|
|
149
|
+
if entry_well == "A1" or entry_well == "A12":
|
|
150
|
+
if critical_row - j >= 0:
|
|
151
|
+
well = column[critical_row - j]
|
|
152
|
+
else:
|
|
153
|
+
return None
|
|
154
|
+
elif entry_well == "H1" or entry_well == "H12":
|
|
155
|
+
if critical_row + j < len(column):
|
|
156
|
+
well = column[critical_row + j]
|
|
157
|
+
else:
|
|
158
|
+
return None
|
|
159
|
+
tip_cluster.append(well)
|
|
160
|
+
|
|
161
|
+
if any(well not in [*wells] for well in tip_cluster):
|
|
162
|
+
return None
|
|
163
|
+
|
|
164
|
+
return tip_cluster
|
|
165
|
+
|
|
166
|
+
def _validate_tip_cluster(
|
|
167
|
+
active_columns: int, active_rows: int, tip_cluster: List[str]
|
|
168
|
+
) -> Union[str, int, None]:
|
|
169
|
+
if not any(wells[well] == _TipRackWellState.USED for well in tip_cluster):
|
|
170
|
+
return tip_cluster[0]
|
|
171
|
+
elif all(wells[well] == _TipRackWellState.USED for well in tip_cluster):
|
|
172
|
+
return None
|
|
173
|
+
else:
|
|
174
|
+
# In the case of an 8ch pipette where a column has mixed state tips we may simply progress to the next column in our search
|
|
175
|
+
if nozzle_map is not None and nozzle_map.physical_nozzle_count == 8:
|
|
176
|
+
return None
|
|
177
|
+
|
|
178
|
+
# In the case of a 96ch we can attempt to index in by singular rows and columns assuming that indexed direction is safe
|
|
179
|
+
# The tip cluster list is ordered: Each row from a column in order by columns
|
|
180
|
+
tip_cluster_final_column: list[str] = []
|
|
181
|
+
for i in range(active_rows):
|
|
182
|
+
tip_cluster_final_column.append(
|
|
183
|
+
tip_cluster[((active_columns * active_rows) - 1) - i]
|
|
184
|
+
)
|
|
185
|
+
tip_cluster_final_row: list[str] = []
|
|
186
|
+
for i in range(active_columns):
|
|
187
|
+
tip_cluster_final_row.append(
|
|
188
|
+
tip_cluster[(active_rows - 1) + (i * active_rows)]
|
|
189
|
+
)
|
|
190
|
+
if all(
|
|
191
|
+
wells[well] == _TipRackWellState.USED
|
|
192
|
+
for well in tip_cluster_final_column
|
|
193
|
+
):
|
|
194
|
+
return None
|
|
195
|
+
elif all(
|
|
196
|
+
wells[well] == _TipRackWellState.USED
|
|
197
|
+
for well in tip_cluster_final_row
|
|
198
|
+
):
|
|
199
|
+
return None
|
|
200
|
+
else:
|
|
201
|
+
# Tiprack has no valid tip selection, cannot progress
|
|
202
|
+
return -1
|
|
203
|
+
|
|
204
|
+
# Search through the tiprack beginning at A1
|
|
205
|
+
def _cluster_search_A1(active_columns: int, active_rows: int) -> Optional[str]:
|
|
206
|
+
critical_column = active_columns - 1
|
|
207
|
+
critical_row = active_rows - 1
|
|
208
|
+
|
|
209
|
+
while critical_column < len(columns):
|
|
210
|
+
tip_cluster = _identify_tip_cluster(
|
|
211
|
+
active_columns, active_rows, critical_column, critical_row, "A1"
|
|
212
|
+
)
|
|
213
|
+
if tip_cluster is not None:
|
|
214
|
+
result = _validate_tip_cluster(
|
|
215
|
+
active_columns, active_rows, tip_cluster
|
|
216
|
+
)
|
|
217
|
+
if isinstance(result, str):
|
|
218
|
+
return result
|
|
219
|
+
elif isinstance(result, int) and result == -1:
|
|
220
|
+
return None
|
|
221
|
+
if critical_row + 1 < len(columns[0]):
|
|
222
|
+
critical_row = critical_row + 1
|
|
223
|
+
else:
|
|
224
|
+
critical_column += 1
|
|
225
|
+
critical_row = active_rows - 1
|
|
226
|
+
return None
|
|
227
|
+
|
|
228
|
+
# Search through the tiprack beginning at A12
|
|
229
|
+
def _cluster_search_A12(active_columns: int, active_rows: int) -> Optional[str]:
|
|
230
|
+
critical_column = len(columns) - active_columns
|
|
231
|
+
critical_row = active_rows - 1
|
|
232
|
+
|
|
233
|
+
while critical_column >= 0:
|
|
234
|
+
tip_cluster = _identify_tip_cluster(
|
|
235
|
+
active_columns, active_rows, critical_column, critical_row, "A12"
|
|
236
|
+
)
|
|
237
|
+
if tip_cluster is not None:
|
|
238
|
+
result = _validate_tip_cluster(
|
|
239
|
+
active_columns, active_rows, tip_cluster
|
|
240
|
+
)
|
|
241
|
+
if isinstance(result, str):
|
|
242
|
+
return result
|
|
243
|
+
elif isinstance(result, int) and result == -1:
|
|
244
|
+
return None
|
|
245
|
+
if critical_row + 1 < len(columns[0]):
|
|
246
|
+
critical_row = critical_row + 1
|
|
247
|
+
else:
|
|
248
|
+
critical_column -= 1
|
|
249
|
+
critical_row = active_rows - 1
|
|
250
|
+
return None
|
|
251
|
+
|
|
252
|
+
# Search through the tiprack beginning at H1
|
|
253
|
+
def _cluster_search_H1(active_columns: int, active_rows: int) -> Optional[str]:
|
|
254
|
+
critical_column = active_columns - 1
|
|
255
|
+
critical_row = len(columns[critical_column]) - active_rows
|
|
256
|
+
|
|
257
|
+
while critical_column <= len(columns): # change to max size of labware
|
|
258
|
+
tip_cluster = _identify_tip_cluster(
|
|
259
|
+
active_columns, active_rows, critical_column, critical_row, "H1"
|
|
260
|
+
)
|
|
261
|
+
if tip_cluster is not None:
|
|
262
|
+
result = _validate_tip_cluster(
|
|
263
|
+
active_columns, active_rows, tip_cluster
|
|
264
|
+
)
|
|
265
|
+
if isinstance(result, str):
|
|
266
|
+
return result
|
|
267
|
+
elif isinstance(result, int) and result == -1:
|
|
268
|
+
return None
|
|
269
|
+
if critical_row - 1 >= 0:
|
|
270
|
+
critical_row = critical_row - 1
|
|
271
|
+
else:
|
|
272
|
+
critical_column += 1
|
|
273
|
+
if critical_column >= len(columns):
|
|
274
|
+
return None
|
|
275
|
+
critical_row = len(columns[critical_column]) - active_rows
|
|
276
|
+
return None
|
|
277
|
+
|
|
278
|
+
# Search through the tiprack beginning at H12
|
|
279
|
+
def _cluster_search_H12(active_columns: int, active_rows: int) -> Optional[str]:
|
|
280
|
+
critical_column = len(columns) - active_columns
|
|
281
|
+
critical_row = len(columns[critical_column]) - active_rows
|
|
282
|
+
|
|
283
|
+
while critical_column >= 0:
|
|
284
|
+
tip_cluster = _identify_tip_cluster(
|
|
285
|
+
active_columns, active_rows, critical_column, critical_row, "H12"
|
|
286
|
+
)
|
|
287
|
+
if tip_cluster is not None:
|
|
288
|
+
result = _validate_tip_cluster(
|
|
289
|
+
active_columns, active_rows, tip_cluster
|
|
290
|
+
)
|
|
291
|
+
if isinstance(result, str):
|
|
292
|
+
return result
|
|
293
|
+
elif isinstance(result, int) and result == -1:
|
|
294
|
+
return None
|
|
295
|
+
if critical_row - 1 >= 0:
|
|
296
|
+
critical_row = critical_row - 1
|
|
297
|
+
else:
|
|
298
|
+
critical_column -= 1
|
|
299
|
+
if critical_column < 0:
|
|
300
|
+
return None
|
|
301
|
+
critical_row = len(columns[critical_column]) - active_rows
|
|
302
|
+
return None
|
|
303
|
+
|
|
304
|
+
if starting_tip_name is None and nozzle_map is not None and columns:
|
|
305
|
+
num_channels = nozzle_map.physical_nozzle_count
|
|
306
|
+
num_nozzle_cols = len(nozzle_map.columns)
|
|
307
|
+
num_nozzle_rows = len(nozzle_map.rows)
|
|
308
|
+
# Each pipette's cluster search is determined by the point of entry for a given pipette/configuration:
|
|
309
|
+
# - Single channel pipettes always search a tiprack top to bottom, left to right
|
|
310
|
+
# - Eight channel pipettes will begin at the top if the primary nozzle is H1 and at the bottom if
|
|
311
|
+
# it is A1. The eight channel will always progress across the columns left to right.
|
|
312
|
+
# - 96 Channel pipettes will begin in the corner opposite their primary/starting nozzle (if starting nozzle = A1, enter tiprack at H12)
|
|
313
|
+
# The 96 channel will then progress towards the opposite corner, either going up or down, left or right depending on configuration.
|
|
314
|
+
|
|
315
|
+
if num_channels == 1:
|
|
316
|
+
return _cluster_search_A1(num_nozzle_cols, num_nozzle_rows)
|
|
317
|
+
elif num_channels == 8:
|
|
318
|
+
if nozzle_map.starting_nozzle == "A1":
|
|
319
|
+
return _cluster_search_H1(num_nozzle_cols, num_nozzle_rows)
|
|
320
|
+
elif nozzle_map.starting_nozzle == "H1":
|
|
321
|
+
return _cluster_search_A1(num_nozzle_cols, num_nozzle_rows)
|
|
322
|
+
elif num_channels == 96:
|
|
323
|
+
if nozzle_map.starting_nozzle == "A1":
|
|
324
|
+
return _cluster_search_H12(num_nozzle_cols, num_nozzle_rows)
|
|
325
|
+
elif nozzle_map.starting_nozzle == "A12":
|
|
326
|
+
return _cluster_search_H1(num_nozzle_cols, num_nozzle_rows)
|
|
327
|
+
elif nozzle_map.starting_nozzle == "H1":
|
|
328
|
+
return _cluster_search_A12(num_nozzle_cols, num_nozzle_rows)
|
|
329
|
+
elif nozzle_map.starting_nozzle == "H12":
|
|
330
|
+
return _cluster_search_A1(num_nozzle_cols, num_nozzle_rows)
|
|
331
|
+
else:
|
|
332
|
+
raise ValueError(
|
|
333
|
+
f"Nozzle {nozzle_map.starting_nozzle} is an invalid starting tip for automatic tip pickup."
|
|
334
|
+
)
|
|
335
|
+
else:
|
|
336
|
+
raise RuntimeError(
|
|
337
|
+
"Invalid number of channels for automatic tip tracking."
|
|
338
|
+
)
|
|
339
|
+
else:
|
|
340
|
+
if columns and num_tips == len(columns[0]): # Get next tips for 8-channel
|
|
341
|
+
column_head = [column[0] for column in columns]
|
|
342
|
+
starting_column_index = 0
|
|
343
|
+
|
|
344
|
+
if starting_tip_name:
|
|
345
|
+
for idx, column in enumerate(columns):
|
|
346
|
+
if starting_tip_name in column:
|
|
347
|
+
if starting_tip_name not in column_head:
|
|
348
|
+
starting_column_index = idx + 1
|
|
349
|
+
else:
|
|
350
|
+
starting_column_index = idx
|
|
351
|
+
|
|
352
|
+
for column in columns[starting_column_index:]:
|
|
353
|
+
if not any(
|
|
354
|
+
wells[well] == _TipRackWellState.USED for well in column
|
|
355
|
+
):
|
|
356
|
+
return column[0]
|
|
357
|
+
|
|
358
|
+
elif num_tips == len(wells.keys()): # Get next tips for 96 channel
|
|
359
|
+
if starting_tip_name and starting_tip_name != columns[0][0]:
|
|
360
|
+
return None
|
|
361
|
+
|
|
362
|
+
if not any(
|
|
363
|
+
tip_state == _TipRackWellState.USED for tip_state in wells.values()
|
|
364
|
+
):
|
|
365
|
+
return next(iter(wells))
|
|
366
|
+
|
|
367
|
+
else: # Get next tips for single channel
|
|
368
|
+
if starting_tip_name is not None:
|
|
369
|
+
wells = _drop_wells_before_starting_tip(wells, starting_tip_name)
|
|
370
|
+
|
|
371
|
+
for well_name, tip_state in wells.items():
|
|
372
|
+
if tip_state == _TipRackWellState.CLEAN:
|
|
373
|
+
return well_name
|
|
374
|
+
return None
|
|
375
|
+
|
|
376
|
+
def has_clean_tip(self, labware_id: str, well_name: str) -> bool:
|
|
377
|
+
"""Get whether a well in a labware has a clean tip.
|
|
378
|
+
|
|
379
|
+
Args:
|
|
380
|
+
labware_id: The labware ID to check.
|
|
381
|
+
well_name: The well name to check.
|
|
382
|
+
|
|
383
|
+
Returns:
|
|
384
|
+
True if the labware is a tip rack and the well has a clean tip,
|
|
385
|
+
otherwise False.
|
|
386
|
+
"""
|
|
387
|
+
tip_rack = self._state.tips_by_labware_id.get(labware_id)
|
|
388
|
+
well_state = tip_rack.get(well_name) if tip_rack else None
|
|
389
|
+
|
|
390
|
+
return well_state == _TipRackWellState.CLEAN
|
|
391
|
+
|
|
392
|
+
def compute_tips_to_mark_as_used(
|
|
393
|
+
self, labware_id: str, well_name: str, nozzle_map: NozzleMap
|
|
394
|
+
) -> list[str]:
|
|
395
|
+
"""Compute which tips a hypothetical tip pickup should mark as "used".
|
|
396
|
+
|
|
397
|
+
Params:
|
|
398
|
+
labware_id: The labware ID of the tip rack.
|
|
399
|
+
well_name: The single target well of the tip pickup.
|
|
400
|
+
nozzle_map: The nozzle configuration that the pipette will use for the pickup.
|
|
401
|
+
|
|
402
|
+
Returns:
|
|
403
|
+
The well names of all the tips that the operation will use.
|
|
404
|
+
"""
|
|
405
|
+
columns = self._state.columns_by_labware_id.get(labware_id, [])
|
|
406
|
+
return list(wells_covered_dense(nozzle_map, well_name, columns))
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
def _drop_wells_before_starting_tip(
|
|
410
|
+
wells: _TipRackStateByWellName, starting_tip_name: str
|
|
411
|
+
) -> _TipRackStateByWellName:
|
|
412
|
+
"""Drop any wells that come before the starting tip and return the remaining ones after."""
|
|
413
|
+
seen_starting_well = False
|
|
414
|
+
remaining_wells: dict[str, _TipRackWellState] = {}
|
|
415
|
+
for well_name, tip_state in wells.items():
|
|
416
|
+
if well_name == starting_tip_name:
|
|
417
|
+
seen_starting_well = True
|
|
418
|
+
if seen_starting_well:
|
|
419
|
+
remaining_wells[well_name] = tip_state
|
|
420
|
+
return remaining_wells
|