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/__init__.py
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
import logging
|
|
5
|
+
import re
|
|
6
|
+
from typing import Any, List, Tuple
|
|
7
|
+
|
|
8
|
+
from opentrons.drivers.serial_communication import get_ports_by_name
|
|
9
|
+
from opentrons.hardware_control import (
|
|
10
|
+
API as HardwareAPI,
|
|
11
|
+
ThreadManager,
|
|
12
|
+
ThreadManagedHardware,
|
|
13
|
+
types as hw_types,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
from opentrons.config import (
|
|
17
|
+
feature_flags as ff,
|
|
18
|
+
name,
|
|
19
|
+
robot_configs,
|
|
20
|
+
IS_ROBOT,
|
|
21
|
+
ROBOT_FIRMWARE_DIR,
|
|
22
|
+
)
|
|
23
|
+
from opentrons.util import logging_config
|
|
24
|
+
from opentrons.protocols.types import ApiDeprecationError
|
|
25
|
+
from opentrons.protocols.api_support.types import APIVersion
|
|
26
|
+
|
|
27
|
+
from ._version import version
|
|
28
|
+
|
|
29
|
+
HERE = os.path.abspath(os.path.dirname(__file__))
|
|
30
|
+
__version__ = version
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
LEGACY_MODULES = ["robot", "reset", "instruments", "containers", "labware", "modules"]
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
__all__ = ["version", "__version__", "HERE", "config"]
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def __getattr__(attrname: str) -> None:
|
|
40
|
+
"""
|
|
41
|
+
Prevent import of legacy modules from global to officially
|
|
42
|
+
deprecate Python API Version 1.0.
|
|
43
|
+
"""
|
|
44
|
+
if attrname in LEGACY_MODULES:
|
|
45
|
+
raise ApiDeprecationError(APIVersion(1, 0))
|
|
46
|
+
raise AttributeError(attrname)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def __dir__() -> List[str]:
|
|
50
|
+
return sorted(__all__ + LEGACY_MODULES)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
log = logging.getLogger(__name__)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
SMOOTHIE_HEX_RE = re.compile("smoothie-(.*).hex")
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def _find_smoothie_file() -> Tuple[Path, str]:
|
|
60
|
+
resources: List[Path] = []
|
|
61
|
+
|
|
62
|
+
# Search for smoothie files in /usr/lib/firmware first then fall back to
|
|
63
|
+
# value packed in wheel
|
|
64
|
+
if IS_ROBOT:
|
|
65
|
+
resources.extend(ROBOT_FIRMWARE_DIR.iterdir()) # type: ignore
|
|
66
|
+
|
|
67
|
+
resources_path = Path(HERE) / "resources"
|
|
68
|
+
resources.extend(resources_path.iterdir())
|
|
69
|
+
|
|
70
|
+
for path in resources:
|
|
71
|
+
matches = SMOOTHIE_HEX_RE.search(path.name)
|
|
72
|
+
if matches:
|
|
73
|
+
branch_plus_ref = matches.group(1)
|
|
74
|
+
return path, branch_plus_ref
|
|
75
|
+
raise OSError(f"Could not find smoothie firmware file in {resources_path}")
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def _get_motor_control_serial_port() -> Any:
|
|
79
|
+
port = os.environ.get("OT_SMOOTHIE_EMULATOR_URI")
|
|
80
|
+
|
|
81
|
+
if port is None:
|
|
82
|
+
smoothie_id = os.environ.get("OT_SMOOTHIE_ID", "AMA")
|
|
83
|
+
# TODO(mc, 2021-08-01): raise a more informative exception than
|
|
84
|
+
# IndexError if a valid serial port is not found
|
|
85
|
+
port = get_ports_by_name(device_name=smoothie_id)[0]
|
|
86
|
+
|
|
87
|
+
log.info(f"Connecting to motor controller at port {port}")
|
|
88
|
+
return port
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def should_use_ot3() -> bool:
|
|
92
|
+
"""Return true if ot3 hardware controller should be used."""
|
|
93
|
+
if ff.enable_ot3_hardware_controller():
|
|
94
|
+
try:
|
|
95
|
+
from opentrons_hardware.drivers.can_bus import CanDriver # noqa: F401
|
|
96
|
+
|
|
97
|
+
return True
|
|
98
|
+
except ModuleNotFoundError:
|
|
99
|
+
log.exception("Cannot use OT3 Hardware controller.")
|
|
100
|
+
return False
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
async def _create_thread_manager() -> ThreadManagedHardware:
|
|
104
|
+
"""Build the hardware controller wrapped in a ThreadManager.
|
|
105
|
+
|
|
106
|
+
.. deprecated:: 4.6
|
|
107
|
+
ThreadManager is on its way out.
|
|
108
|
+
"""
|
|
109
|
+
if os.environ.get("ENABLE_VIRTUAL_SMOOTHIE"):
|
|
110
|
+
log.info("Initialized robot using virtual Smoothie")
|
|
111
|
+
thread_manager: ThreadManagedHardware = ThreadManager(
|
|
112
|
+
HardwareAPI.build_hardware_simulator
|
|
113
|
+
)
|
|
114
|
+
elif should_use_ot3():
|
|
115
|
+
from opentrons.hardware_control.ot3api import OT3API
|
|
116
|
+
|
|
117
|
+
thread_manager = ThreadManager(
|
|
118
|
+
ThreadManager.nonblocking_builder(OT3API.build_hardware_controller),
|
|
119
|
+
use_usb_bus=ff.rear_panel_integration(),
|
|
120
|
+
status_bar_enabled=ff.status_bar_enabled(),
|
|
121
|
+
feature_flags=hw_types.HardwareFeatureFlags.build_from_ff(),
|
|
122
|
+
)
|
|
123
|
+
else:
|
|
124
|
+
thread_manager = ThreadManager(
|
|
125
|
+
ThreadManager.nonblocking_builder(HardwareAPI.build_hardware_controller),
|
|
126
|
+
port=_get_motor_control_serial_port(),
|
|
127
|
+
firmware=_find_smoothie_file(),
|
|
128
|
+
feature_flags=hw_types.HardwareFeatureFlags.build_from_ff(),
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
try:
|
|
132
|
+
await thread_manager.managed_thread_ready_async()
|
|
133
|
+
except RuntimeError:
|
|
134
|
+
log.exception("Could not build hardware controller, forcing virtual")
|
|
135
|
+
thread_manager = ThreadManager(HardwareAPI.build_hardware_simulator)
|
|
136
|
+
|
|
137
|
+
return thread_manager
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
async def initialize() -> ThreadManagedHardware:
|
|
141
|
+
"""
|
|
142
|
+
Initialize the Opentrons hardware returning a hardware instance.
|
|
143
|
+
"""
|
|
144
|
+
robot_conf = robot_configs.load()
|
|
145
|
+
logging_config.log_init(robot_conf.log_level)
|
|
146
|
+
|
|
147
|
+
log.info(f"API server version: {version}")
|
|
148
|
+
log.info(f"Robot Name: {name()}")
|
|
149
|
+
|
|
150
|
+
return await _create_thread_manager()
|
opentrons/_version.py
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# file generated by setuptools-scm
|
|
2
|
+
# don't change, don't track in version control
|
|
3
|
+
|
|
4
|
+
__all__ = [
|
|
5
|
+
"__version__",
|
|
6
|
+
"__version_tuple__",
|
|
7
|
+
"version",
|
|
8
|
+
"version_tuple",
|
|
9
|
+
"__commit_id__",
|
|
10
|
+
"commit_id",
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
TYPE_CHECKING = False
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from typing import Tuple
|
|
16
|
+
from typing import Union
|
|
17
|
+
|
|
18
|
+
VERSION_TUPLE = Tuple[Union[int, str], ...]
|
|
19
|
+
COMMIT_ID = Union[str, None]
|
|
20
|
+
else:
|
|
21
|
+
VERSION_TUPLE = object
|
|
22
|
+
COMMIT_ID = object
|
|
23
|
+
|
|
24
|
+
version: str
|
|
25
|
+
__version__: str
|
|
26
|
+
__version_tuple__: VERSION_TUPLE
|
|
27
|
+
version_tuple: VERSION_TUPLE
|
|
28
|
+
commit_id: COMMIT_ID
|
|
29
|
+
__commit_id__: COMMIT_ID
|
|
30
|
+
|
|
31
|
+
__version__ = version = '8.6.0'
|
|
32
|
+
__version_tuple__ = version_tuple = (8, 6, 0)
|
|
33
|
+
|
|
34
|
+
__commit_id__ = commit_id = None
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
from .ot3 import gripper_offset
|
|
2
|
+
from .ot2 import mark_bad_calibration
|
|
3
|
+
|
|
4
|
+
from .deck_configuration import (
|
|
5
|
+
serialize_deck_configuration,
|
|
6
|
+
deserialize_deck_configuration,
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
# TODO these functions are only used in robot server. We should think about moving them and/or
|
|
10
|
+
# abstracting it away from a robot specific function. We should also check if the tip rack
|
|
11
|
+
# definition information is still needed.
|
|
12
|
+
from .ot2.tip_length import (
|
|
13
|
+
get_custom_tiprack_definition_for_tlc,
|
|
14
|
+
get_all_tip_length_calibrations,
|
|
15
|
+
_save_custom_tiprack_definition,
|
|
16
|
+
)
|
|
17
|
+
from .ot2.pipette_offset import get_all_pipette_offset_calibrations
|
|
18
|
+
from .ot3.deck_attitude import (
|
|
19
|
+
save_robot_belt_attitude,
|
|
20
|
+
get_robot_belt_attitude,
|
|
21
|
+
delete_robot_belt_attitude,
|
|
22
|
+
)
|
|
23
|
+
from .ot2.deck_attitude import (
|
|
24
|
+
save_robot_deck_attitude,
|
|
25
|
+
get_robot_deck_attitude,
|
|
26
|
+
delete_robot_deck_attitude,
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
from . import ot2, ot3, helpers
|
|
30
|
+
|
|
31
|
+
__all__ = [
|
|
32
|
+
"helpers",
|
|
33
|
+
# deck calibration functions
|
|
34
|
+
"save_robot_deck_attitude",
|
|
35
|
+
"get_robot_deck_attitude",
|
|
36
|
+
"delete_robot_deck_attitude",
|
|
37
|
+
"save_robot_belt_attitude",
|
|
38
|
+
"get_robot_belt_attitude",
|
|
39
|
+
"delete_robot_belt_attitude",
|
|
40
|
+
# deck configuration functions
|
|
41
|
+
"serialize_deck_configuration",
|
|
42
|
+
"deserialize_deck_configuration",
|
|
43
|
+
# functions only used in robot server
|
|
44
|
+
"_save_custom_tiprack_definition",
|
|
45
|
+
"get_custom_tiprack_definition_for_tlc",
|
|
46
|
+
"get_all_pipette_offset_calibrations",
|
|
47
|
+
"get_all_tip_length_calibrations",
|
|
48
|
+
# file exports
|
|
49
|
+
"gripper_offset",
|
|
50
|
+
"mark_bad_calibration",
|
|
51
|
+
# Platform specific submodules
|
|
52
|
+
"ot2",
|
|
53
|
+
"ot3",
|
|
54
|
+
]
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
from typing import List, Optional, Tuple
|
|
3
|
+
|
|
4
|
+
import pydantic
|
|
5
|
+
|
|
6
|
+
from .types import CutoutFixturePlacement
|
|
7
|
+
from . import file_operators as io
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class _CutoutFixturePlacementModel(pydantic.BaseModel):
|
|
11
|
+
cutoutId: str
|
|
12
|
+
cutoutFixtureId: str
|
|
13
|
+
opentronsModuleSerialNumber: Optional[str] = None
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class _DeckConfigurationModel(pydantic.BaseModel):
|
|
17
|
+
"""The on-filesystem representation of a deck configuration."""
|
|
18
|
+
|
|
19
|
+
cutoutFixtures: List[_CutoutFixturePlacementModel]
|
|
20
|
+
lastModified: datetime
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def serialize_deck_configuration(
|
|
24
|
+
cutout_fixture_placements: List[CutoutFixturePlacement], last_modified: datetime
|
|
25
|
+
) -> bytes:
|
|
26
|
+
"""Serialize a deck configuration for storing on the filesystem."""
|
|
27
|
+
data = _DeckConfigurationModel.model_construct(
|
|
28
|
+
cutoutFixtures=[
|
|
29
|
+
_CutoutFixturePlacementModel.model_construct(
|
|
30
|
+
cutoutId=e.cutout_id,
|
|
31
|
+
cutoutFixtureId=e.cutout_fixture_id,
|
|
32
|
+
opentronsModuleSerialNumber=e.opentrons_module_serial_number,
|
|
33
|
+
)
|
|
34
|
+
for e in cutout_fixture_placements
|
|
35
|
+
],
|
|
36
|
+
lastModified=last_modified,
|
|
37
|
+
)
|
|
38
|
+
return io.serialize_pydantic_model(data)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
# TODO(mm, 2023-11-21): If the data is corrupt, we should propagate the underlying error.
|
|
42
|
+
# And there should be an enumerated "corrupt storage" error in shared-data.
|
|
43
|
+
def deserialize_deck_configuration(
|
|
44
|
+
serialized: bytes,
|
|
45
|
+
) -> Optional[Tuple[List[CutoutFixturePlacement], datetime]]:
|
|
46
|
+
"""Deserialize bytes previously serialized by `serialize_deck_configuration()`.
|
|
47
|
+
|
|
48
|
+
Returns a tuple `(deck_configuration, last_modified_time)`, or `None` if the data is corrupt.
|
|
49
|
+
"""
|
|
50
|
+
parsed = io.deserialize_pydantic_model(serialized, _DeckConfigurationModel)
|
|
51
|
+
if parsed is None:
|
|
52
|
+
return None
|
|
53
|
+
else:
|
|
54
|
+
cutout_fixture_placements = [
|
|
55
|
+
CutoutFixturePlacement(
|
|
56
|
+
cutout_id=e.cutoutId,
|
|
57
|
+
cutout_fixture_id=e.cutoutFixtureId,
|
|
58
|
+
opentrons_module_serial_number=e.opentronsModuleSerialNumber,
|
|
59
|
+
)
|
|
60
|
+
for e in parsed.cutoutFixtures
|
|
61
|
+
]
|
|
62
|
+
return cutout_fixture_placements, parsed.lastModified
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
""" opentrons.calibration_storage.encoder_decoder: classes that
|
|
2
|
+
allow you to customize serialization to/from json.
|
|
3
|
+
"""
|
|
4
|
+
import json
|
|
5
|
+
import datetime
|
|
6
|
+
from typing import Any, cast
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class DateTimeEncoder(json.JSONEncoder):
|
|
10
|
+
def default(self, obj: object) -> Any:
|
|
11
|
+
if isinstance(obj, datetime.datetime):
|
|
12
|
+
return obj.isoformat()
|
|
13
|
+
return json.JSONEncoder.default(self, obj)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class DateTimeDecoder(json.JSONDecoder):
|
|
17
|
+
def __init__(self) -> None:
|
|
18
|
+
super().__init__(object_hook=self.dict_to_obj)
|
|
19
|
+
|
|
20
|
+
def dict_to_obj(self, d: object) -> Any:
|
|
21
|
+
if isinstance(d, dict):
|
|
22
|
+
d = {k: self._decode_datetime(v) for k, v in d.items()}
|
|
23
|
+
return d
|
|
24
|
+
|
|
25
|
+
def _decode_datetime(self, obj: object) -> Any:
|
|
26
|
+
try:
|
|
27
|
+
return datetime.datetime.fromisoformat(cast(str, obj))
|
|
28
|
+
except ValueError:
|
|
29
|
+
return obj
|
|
30
|
+
except TypeError:
|
|
31
|
+
return self.dict_to_obj(obj)
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
""" opentrons.calibration_storage.file_operators: functions that
|
|
2
|
+
manipulate the file system.
|
|
3
|
+
|
|
4
|
+
These methods should only be imported inside the calibration_storage
|
|
5
|
+
module, except in the special case of v2 labware support in
|
|
6
|
+
the v1 API.
|
|
7
|
+
"""
|
|
8
|
+
import datetime
|
|
9
|
+
import json
|
|
10
|
+
import logging
|
|
11
|
+
import typing
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
|
|
14
|
+
import pydantic
|
|
15
|
+
|
|
16
|
+
from .encoder_decoder import DateTimeEncoder, DateTimeDecoder
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
_log = logging.getLogger(__name__)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
DecoderType = typing.Type[json.JSONDecoder]
|
|
23
|
+
EncoderType = typing.Type[json.JSONEncoder]
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
# TODO(mc, 2022-06-07): replace with Path.unlink(missing_ok=True)
|
|
27
|
+
# when we are on Python >= 3.8
|
|
28
|
+
def delete_file(path: Path) -> None:
|
|
29
|
+
try:
|
|
30
|
+
path.unlink()
|
|
31
|
+
except FileNotFoundError:
|
|
32
|
+
pass
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
# TODO: This is private but used by other files.
|
|
36
|
+
def _remove_json_files_in_directories(p: Path) -> None:
|
|
37
|
+
"""Delete .json files in the given directory and its subdirectories."""
|
|
38
|
+
for item in p.iterdir():
|
|
39
|
+
if item.is_dir():
|
|
40
|
+
_remove_json_files_in_directories(item)
|
|
41
|
+
elif item.suffix == ".json":
|
|
42
|
+
delete_file(item)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _assert_last_modified_value(calibration_dict: typing.Dict[str, typing.Any]) -> None:
|
|
46
|
+
last_modified = calibration_dict.get("lastModified")
|
|
47
|
+
if last_modified:
|
|
48
|
+
assert isinstance(calibration_dict["lastModified"], datetime.datetime), (
|
|
49
|
+
"invalid decoded value type for lastModified: got "
|
|
50
|
+
f"{type(calibration_dict['lastModified']).__name__},"
|
|
51
|
+
"expected datetime"
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def read_cal_file(
|
|
56
|
+
file_path: Path, decoder: DecoderType = DateTimeDecoder
|
|
57
|
+
) -> typing.Dict[str, typing.Any]:
|
|
58
|
+
"""
|
|
59
|
+
Function used to read data from a file
|
|
60
|
+
|
|
61
|
+
:param file_path: path to look for data at
|
|
62
|
+
:param decoder: if there is any specialized decoder needed.
|
|
63
|
+
The default decoder is the date time decoder.
|
|
64
|
+
:return: Data from the file
|
|
65
|
+
"""
|
|
66
|
+
# TODO(6/16): We should use tagged unions for
|
|
67
|
+
# both the calibration and tip length dicts to better
|
|
68
|
+
# categorize the Typed Dicts used here.
|
|
69
|
+
# This can be done when the labware endpoints
|
|
70
|
+
# are refactored to grab tip length calibration
|
|
71
|
+
# from the correct locations.
|
|
72
|
+
with open(file_path, "r", encoding="utf-8") as f:
|
|
73
|
+
calibration_data = typing.cast(
|
|
74
|
+
typing.Dict[str, typing.Any],
|
|
75
|
+
json.load(f, cls=decoder),
|
|
76
|
+
)
|
|
77
|
+
if isinstance(calibration_data.values(), dict):
|
|
78
|
+
_assert_last_modified_value(dict(calibration_data.values()))
|
|
79
|
+
else:
|
|
80
|
+
_assert_last_modified_value(calibration_data)
|
|
81
|
+
return calibration_data
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def save_to_file(
|
|
85
|
+
directory_path: Path,
|
|
86
|
+
# todo(mm, 2023-11-15): This file_name argument does not include the file
|
|
87
|
+
# extension, which is inconsistent with read_cal_file(). The two should match.
|
|
88
|
+
file_name: str,
|
|
89
|
+
data: typing.Union[pydantic.BaseModel, typing.Dict[str, typing.Any], typing.Any],
|
|
90
|
+
encoder: EncoderType = DateTimeEncoder,
|
|
91
|
+
) -> None:
|
|
92
|
+
"""
|
|
93
|
+
Function used to save data to a file
|
|
94
|
+
|
|
95
|
+
:param directory_path: path to the directory in which to save the data
|
|
96
|
+
:param file_name: name of the file within the directory, *without the extension*.
|
|
97
|
+
:param data: The data to save. Either a Pydantic model, or a JSON-like dict to pass to
|
|
98
|
+
`json.dumps()`. If you're storing a Pydantic model, prefer `save_pydantic_model_to_file()`
|
|
99
|
+
and `read_pydantic_model_from_file()` for new code.
|
|
100
|
+
:param encoder: if there is any specialized encoder needed.
|
|
101
|
+
The default encoder is the date time encoder.
|
|
102
|
+
"""
|
|
103
|
+
directory_path.mkdir(parents=True, exist_ok=True)
|
|
104
|
+
file_path = directory_path / f"{file_name}.json"
|
|
105
|
+
json_data = (
|
|
106
|
+
data.model_dump_json()
|
|
107
|
+
if isinstance(data, pydantic.BaseModel)
|
|
108
|
+
else json.dumps(data, cls=encoder)
|
|
109
|
+
)
|
|
110
|
+
file_path.write_text(json_data, encoding="utf-8")
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def serialize_pydantic_model(data: pydantic.BaseModel) -> bytes:
|
|
114
|
+
"""Safely serialize data from a Pydantic model into a form suitable for storing on disk."""
|
|
115
|
+
return data.model_dump_json(by_alias=True).encode("utf-8")
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
_ModelT = typing.TypeVar("_ModelT", bound=pydantic.BaseModel)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
# TODO(mm, 2023-11-20): We probably want to distinguish "missing file" from "corrupt file."
|
|
122
|
+
# The caller needs to deal with those cases separately because the appropriate action depends on
|
|
123
|
+
# context. For example, when running protocols through robot-server, if the file is corrupt, it's
|
|
124
|
+
# safe-ish to fall back to a default because the Opentrons App will let the user confirm everything
|
|
125
|
+
# before starting the run. But when running protocols through the non-interactive
|
|
126
|
+
# `opentrons_execute`, we don't want it to silently use default data if the file is corrupt.
|
|
127
|
+
def deserialize_pydantic_model(
|
|
128
|
+
serialized: bytes,
|
|
129
|
+
model: typing.Type[_ModelT],
|
|
130
|
+
) -> typing.Optional[_ModelT]:
|
|
131
|
+
"""Safely read bytes from `serialize_pydantic_model()` back into a Pydantic model.
|
|
132
|
+
|
|
133
|
+
Returns `None` if the file is missing or corrupt.
|
|
134
|
+
"""
|
|
135
|
+
try:
|
|
136
|
+
return model.model_validate_json(serialized)
|
|
137
|
+
except json.JSONDecodeError:
|
|
138
|
+
_log.warning("Data is not valid JSON.", exc_info=True)
|
|
139
|
+
return None
|
|
140
|
+
except pydantic.ValidationError:
|
|
141
|
+
_log.warning(f"Data is malformed as a {model}.", exc_info=True)
|
|
142
|
+
return None
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
""" opentrons.calibration_storage.helpers: various miscellaneous
|
|
2
|
+
functions
|
|
3
|
+
|
|
4
|
+
This module has functions that you can import to save robot or
|
|
5
|
+
labware calibration to its designated file location.
|
|
6
|
+
"""
|
|
7
|
+
import json
|
|
8
|
+
from typing import Any, Union, List, Dict, TYPE_CHECKING, cast, Tuple
|
|
9
|
+
from dataclasses import is_dataclass, asdict
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
from hashlib import sha256
|
|
13
|
+
|
|
14
|
+
from . import types as local_types
|
|
15
|
+
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
|
+
from opentrons_shared_data.labware.types import LabwareDefinition
|
|
18
|
+
from opentrons_shared_data.pipette.types import LabwareUri
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def dict_filter_none(data: List[Tuple[str, Any]]) -> Dict[str, Any]:
|
|
22
|
+
"""
|
|
23
|
+
Helper function to filter out None keys from a dataclass
|
|
24
|
+
before saving to file.
|
|
25
|
+
"""
|
|
26
|
+
return dict(item for item in data if item[1] is not None)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def convert_to_dict(obj: Any) -> Dict[str, Any]:
|
|
30
|
+
# The correct way to type this is described here:
|
|
31
|
+
# https://github.com/python/mypy/issues/6568
|
|
32
|
+
# Unfortunately, since it's not currently supported I have an
|
|
33
|
+
# assert check instead.
|
|
34
|
+
assert is_dataclass(obj) and not isinstance(
|
|
35
|
+
obj, type
|
|
36
|
+
), "This function is intended for dataclasses only"
|
|
37
|
+
return asdict(obj, dict_factory=dict_filter_none)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
# TODO(mc, 2021-11-09): this hashing function may produce different hashes
|
|
41
|
+
# for semantically identical labware defs. For example, a value of `10` will
|
|
42
|
+
# produce a different hash than a value of `10.0`. Hashing should be produce
|
|
43
|
+
# identical hashes for `==` values. This could be done by running defs through
|
|
44
|
+
# Pydantic or similar rather via json.dumps
|
|
45
|
+
def hash_labware_def(labware_def: "LabwareDefinition") -> str:
|
|
46
|
+
"""
|
|
47
|
+
Helper function to take in a labware definition and return
|
|
48
|
+
a hashed string of key elements from the labware definition
|
|
49
|
+
to make it a unique identifier.
|
|
50
|
+
|
|
51
|
+
:param labware_def: Full labware definition
|
|
52
|
+
:returns: sha256 string
|
|
53
|
+
"""
|
|
54
|
+
# remove keys that do not affect run
|
|
55
|
+
blocklist = ["metadata", "brand", "groups"]
|
|
56
|
+
def_no_metadata = {k: v for k, v in labware_def.items() if k not in blocklist}
|
|
57
|
+
sorted_def_str = json.dumps(def_no_metadata, sort_keys=True, separators=(",", ":"))
|
|
58
|
+
|
|
59
|
+
return sha256(sorted_def_str.encode("utf-8")).hexdigest()
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def details_from_uri(uri: str, delimiter: str = "/") -> local_types.UriDetails:
|
|
63
|
+
"""
|
|
64
|
+
Unpack a labware URI to get the namespace, loadname and version
|
|
65
|
+
"""
|
|
66
|
+
try:
|
|
67
|
+
info = uri.split(delimiter)
|
|
68
|
+
return local_types.UriDetails(
|
|
69
|
+
namespace=info[0], load_name=info[1], version=int(info[2])
|
|
70
|
+
)
|
|
71
|
+
except IndexError:
|
|
72
|
+
# Here we are assuming that the 'uri' passed in is actually
|
|
73
|
+
# the loadname, though sometimes it may be an empty string.
|
|
74
|
+
return local_types.UriDetails(namespace="", load_name=uri, version=1)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def uri_from_details(
|
|
78
|
+
namespace: str, load_name: str, version: Union[str, int], delimiter: str = "/"
|
|
79
|
+
) -> "LabwareUri":
|
|
80
|
+
"""Build a labware URI from its details.
|
|
81
|
+
|
|
82
|
+
A labware URI is a string that uniquely specifies a labware definition.
|
|
83
|
+
|
|
84
|
+
:returns str: The URI.
|
|
85
|
+
"""
|
|
86
|
+
return cast("LabwareUri", f"{namespace}{delimiter}{load_name}{delimiter}{version}")
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def uri_from_definition(
|
|
90
|
+
definition: "LabwareDefinition", delimiter: str = "/"
|
|
91
|
+
) -> "LabwareUri":
|
|
92
|
+
"""Build a labware URI from its definition.
|
|
93
|
+
|
|
94
|
+
A labware URI is a string that uniquely specifies a labware definition.
|
|
95
|
+
|
|
96
|
+
:returns str: The URI.
|
|
97
|
+
"""
|
|
98
|
+
return uri_from_details(
|
|
99
|
+
namespace=definition["namespace"],
|
|
100
|
+
load_name=definition["parameters"]["loadName"],
|
|
101
|
+
version=definition["version"],
|
|
102
|
+
delimiter=delimiter,
|
|
103
|
+
)
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
from . import (
|
|
2
|
+
models,
|
|
3
|
+
mark_bad_calibration,
|
|
4
|
+
)
|
|
5
|
+
from .pipette_offset import (
|
|
6
|
+
save_pipette_calibration,
|
|
7
|
+
clear_pipette_offset_calibrations,
|
|
8
|
+
get_pipette_offset,
|
|
9
|
+
delete_pipette_offset_file,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
from .tip_length import (
|
|
13
|
+
clear_tip_length_calibration,
|
|
14
|
+
create_tip_length_data,
|
|
15
|
+
save_tip_length_calibration,
|
|
16
|
+
tip_lengths_for_pipette,
|
|
17
|
+
load_tip_length_calibration,
|
|
18
|
+
delete_tip_length_calibration,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
__all__ = [
|
|
22
|
+
"models",
|
|
23
|
+
"mark_bad_calibration",
|
|
24
|
+
"save_pipette_calibration",
|
|
25
|
+
"clear_pipette_offset_calibrations",
|
|
26
|
+
"get_pipette_offset",
|
|
27
|
+
"delete_pipette_offset_file",
|
|
28
|
+
"clear_tip_length_calibration",
|
|
29
|
+
"create_tip_length_data",
|
|
30
|
+
"save_tip_length_calibration",
|
|
31
|
+
"tip_lengths_for_pipette",
|
|
32
|
+
"load_tip_length_calibration",
|
|
33
|
+
"delete_tip_length_calibration",
|
|
34
|
+
]
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import logging
|
|
3
|
+
from pydantic import ValidationError
|
|
4
|
+
from typing import Optional, Union
|
|
5
|
+
from dataclasses import asdict
|
|
6
|
+
|
|
7
|
+
from opentrons import config
|
|
8
|
+
from opentrons.util.helpers import utc_now
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
from .. import file_operators as io, types as local_types
|
|
12
|
+
|
|
13
|
+
from .models import v1
|
|
14
|
+
|
|
15
|
+
log = logging.getLogger(__name__)
|
|
16
|
+
|
|
17
|
+
# Delete Deck Calibration
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def delete_robot_deck_attitude() -> None:
|
|
21
|
+
"""
|
|
22
|
+
Delete the robot deck attitude calibration.
|
|
23
|
+
"""
|
|
24
|
+
legacy_deck_calibration_file = config.get_opentrons_path("deck_calibration_file")
|
|
25
|
+
|
|
26
|
+
robot_dir = config.get_opentrons_path("robot_calibration_dir")
|
|
27
|
+
gantry_path = robot_dir / "deck_calibration.json"
|
|
28
|
+
|
|
29
|
+
# TODO(mc, 2022-06-08): this leaves legacy deck calibration backup files in place
|
|
30
|
+
# we should eventually clean them up, too, because they can really crowd /data/
|
|
31
|
+
io.delete_file(legacy_deck_calibration_file)
|
|
32
|
+
io.delete_file(gantry_path)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
# Save Deck Calibration
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def save_robot_deck_attitude(
|
|
39
|
+
transform: local_types.AttitudeMatrix,
|
|
40
|
+
pip_id: Optional[str],
|
|
41
|
+
lw_hash: Optional[str],
|
|
42
|
+
source: Optional[local_types.SourceType] = None,
|
|
43
|
+
cal_status: Optional[
|
|
44
|
+
Union[local_types.CalibrationStatus, v1.CalibrationStatus]
|
|
45
|
+
] = None,
|
|
46
|
+
) -> None:
|
|
47
|
+
robot_dir = config.get_opentrons_path("robot_calibration_dir")
|
|
48
|
+
|
|
49
|
+
if isinstance(cal_status, local_types.CalibrationStatus):
|
|
50
|
+
cal_status_model = v1.CalibrationStatus(**asdict(cal_status))
|
|
51
|
+
elif isinstance(cal_status, v1.CalibrationStatus):
|
|
52
|
+
cal_status_model = cal_status
|
|
53
|
+
else:
|
|
54
|
+
cal_status_model = v1.CalibrationStatus()
|
|
55
|
+
|
|
56
|
+
gantry_calibration = v1.DeckCalibrationModel(
|
|
57
|
+
attitude=transform,
|
|
58
|
+
pipette_calibrated_with=pip_id,
|
|
59
|
+
last_modified=utc_now(),
|
|
60
|
+
tiprack=lw_hash,
|
|
61
|
+
source=source or local_types.SourceType.user,
|
|
62
|
+
status=cal_status_model,
|
|
63
|
+
)
|
|
64
|
+
# convert to schema + validate json conversion
|
|
65
|
+
io.save_to_file(robot_dir, "deck_calibration", gantry_calibration)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
# Get Deck Calibration
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def get_robot_deck_attitude() -> Optional[v1.DeckCalibrationModel]:
|
|
72
|
+
deck_calibration_path = (
|
|
73
|
+
config.get_opentrons_path("robot_calibration_dir") / "deck_calibration.json"
|
|
74
|
+
)
|
|
75
|
+
try:
|
|
76
|
+
return v1.DeckCalibrationModel(**io.read_cal_file(deck_calibration_path))
|
|
77
|
+
except FileNotFoundError:
|
|
78
|
+
log.warning("Deck calibration not found.")
|
|
79
|
+
pass
|
|
80
|
+
except (json.JSONDecodeError, ValidationError):
|
|
81
|
+
log.warning(
|
|
82
|
+
"Deck calibration is malformed. Please factory reset your calibrations.",
|
|
83
|
+
exc_info=True,
|
|
84
|
+
)
|
|
85
|
+
return None
|