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/util/linal.py
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
import logging
|
|
3
|
+
import numpy as np
|
|
4
|
+
from numpy import insert, dot
|
|
5
|
+
from numpy.linalg import inv
|
|
6
|
+
from numpy.typing import NDArray
|
|
7
|
+
from typing import List, Tuple, Union
|
|
8
|
+
|
|
9
|
+
from opentrons.calibration_storage.types import AttitudeMatrix
|
|
10
|
+
|
|
11
|
+
mod_log = logging.getLogger(__name__)
|
|
12
|
+
|
|
13
|
+
# (TODO(lc, 8/11/2020): temporary type until
|
|
14
|
+
# old calibration data is removed.
|
|
15
|
+
AxisPosition = Union[Tuple[float, float, float], Tuple[float, float]]
|
|
16
|
+
|
|
17
|
+
SolvePoints = Tuple[
|
|
18
|
+
Tuple[float, float, float], Tuple[float, float, float], Tuple[float, float, float]
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
DoubleArray = NDArray[np.double]
|
|
22
|
+
DoubleMatrix = NDArray[np.double]
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def identity_deck_transform() -> DoubleArray:
|
|
26
|
+
"""The default deck transform"""
|
|
27
|
+
return np.identity(3)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def solve_attitude(expected: SolvePoints, actual: SolvePoints) -> AttitudeMatrix:
|
|
31
|
+
ex: DoubleMatrix = np.array([list(point) for point in expected]).transpose()
|
|
32
|
+
ac: DoubleMatrix = np.array([list(point) for point in actual]).transpose()
|
|
33
|
+
t = np.dot(ac, inv(ex))
|
|
34
|
+
|
|
35
|
+
mask_transform: NDArray[np.bool_] = np.array(
|
|
36
|
+
[[True, True, False], [True, True, False], [False, False, False]]
|
|
37
|
+
)
|
|
38
|
+
masked_array = np.ma.masked_array(t, ~mask_transform) # type: ignore[var-annotated, no-untyped-call]
|
|
39
|
+
|
|
40
|
+
no_z_component = np.zeros((3, 3))
|
|
41
|
+
np.put(no_z_component, [8, 8], 1)
|
|
42
|
+
|
|
43
|
+
transform = masked_array.filled(0) + no_z_component # type: ignore[no-untyped-call]
|
|
44
|
+
return transform.round(4).tolist() # type: ignore[no-any-return]
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def solve(
|
|
48
|
+
expected: List[Tuple[float, float]],
|
|
49
|
+
actual: List[Tuple[float, float]],
|
|
50
|
+
) -> DoubleArray:
|
|
51
|
+
"""
|
|
52
|
+
Takes two lists of 3 x-y points each, and calculates the matrix
|
|
53
|
+
representing the transformation from one space to the other.
|
|
54
|
+
|
|
55
|
+
The 3x3 matrix returned by this method represents the 2-D transformation
|
|
56
|
+
matrix from the actual point to the expected point.
|
|
57
|
+
|
|
58
|
+
Example:
|
|
59
|
+
If the expected points are:
|
|
60
|
+
[ (1, 1),
|
|
61
|
+
(2, 2),
|
|
62
|
+
(1, 2) ]
|
|
63
|
+
And the actual measured points are:
|
|
64
|
+
[ (1.1, 1.1),
|
|
65
|
+
(2.1, 2.1),
|
|
66
|
+
(1.1, 2.1) ]
|
|
67
|
+
(in other words, a shift of exaxtly +0.1 in both x and y)
|
|
68
|
+
|
|
69
|
+
Then the resulting transformation matrix T should be:
|
|
70
|
+
[ 1 0 -0.1 ]
|
|
71
|
+
[ 0 1 -0.1 ]
|
|
72
|
+
[ 0 0 1 ]
|
|
73
|
+
|
|
74
|
+
Then, if we take a 3x3 matrix B representing one of the measured points
|
|
75
|
+
on the deck:
|
|
76
|
+
[ 1 0 1.1 ]
|
|
77
|
+
[ 0 1 2.1 ]
|
|
78
|
+
[ 0 0 1 ]
|
|
79
|
+
|
|
80
|
+
The B*T will yield the "actual" point:
|
|
81
|
+
[ 1 0 1 ]
|
|
82
|
+
[ 0 1 2 ]
|
|
83
|
+
[ 0 0 1 ]
|
|
84
|
+
|
|
85
|
+
The return value of this function is the transformation matrix T
|
|
86
|
+
"""
|
|
87
|
+
# Note: input list shape validation is handled by the type checker
|
|
88
|
+
|
|
89
|
+
# Turn expected and actual matricies into numpy ndarrays with the last row
|
|
90
|
+
# of [1 1 1] appended, and then take the dot product of the resulting
|
|
91
|
+
# actual matrix with the inverse of the resulting expected matrix.
|
|
92
|
+
|
|
93
|
+
# Shape of `expected` and `actual`:
|
|
94
|
+
# [ (x1, y1),
|
|
95
|
+
# (x2, y2),
|
|
96
|
+
# (x3, y3) ]
|
|
97
|
+
ex: DoubleMatrix = np.array([list(point) + [1] for point in expected]).transpose()
|
|
98
|
+
|
|
99
|
+
ac: DoubleMatrix = np.array([list(point) + [1] for point in actual]).transpose()
|
|
100
|
+
# Shape of `ex` and `ac`:
|
|
101
|
+
# [ x1 x2 x3 ]
|
|
102
|
+
# [ y1 y2 y3 ]
|
|
103
|
+
# [ 1 1 1 ]
|
|
104
|
+
|
|
105
|
+
transform = np.dot(ac, inv(ex))
|
|
106
|
+
# `dot` in numpy is a misnomer. When both arguments are square, N-
|
|
107
|
+
# dimensional arrays, the return type is the result of performing matrix
|
|
108
|
+
# multiplication, rather than the dot-product (so the return here will be
|
|
109
|
+
# a 4x4 matrix)
|
|
110
|
+
return transform # type: ignore[no-any-return]
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def add_z(xy: DoubleArray, z: float) -> DoubleArray:
|
|
114
|
+
"""
|
|
115
|
+
Turn a 2-D transform matrix into a 3-D transform matrix (scale/shift only,
|
|
116
|
+
no rotation).
|
|
117
|
+
|
|
118
|
+
:param xy: A two-dimensional transform matrix (a 3x3 numpy ndarray) in the
|
|
119
|
+
following form:
|
|
120
|
+
[ 1 0 x ]
|
|
121
|
+
[ 0 1 y ]
|
|
122
|
+
[ 0 0 1 ]
|
|
123
|
+
:param z: a float for the z component
|
|
124
|
+
:return: a three-dimensional transformation matrix (a 4x4 numpy ndarray)
|
|
125
|
+
with x, y, and z from the function parameters, in the following form:
|
|
126
|
+
[ 1 0 0 x ]
|
|
127
|
+
[ 0 1 0 y ]
|
|
128
|
+
[ 0 0 1 z ]
|
|
129
|
+
[ 0 0 0 1 ]
|
|
130
|
+
"""
|
|
131
|
+
# First, insert a column of zeros as into the input matrix
|
|
132
|
+
interm = insert(xy, 2, [0, 0, 0], axis=1)
|
|
133
|
+
# Result:
|
|
134
|
+
# [ 1 0 0 x ]
|
|
135
|
+
# [ 0 1 0 y ]
|
|
136
|
+
# [ 0 0 0 1 ]
|
|
137
|
+
|
|
138
|
+
# Then, insert the z row to create a properly formed 3-D transform matrix:
|
|
139
|
+
xyz: DoubleMatrix = insert(interm, 2, [0, 0, 1, z], axis=0)
|
|
140
|
+
# Result:
|
|
141
|
+
# [ 1 0 0 x ]
|
|
142
|
+
# [ 0 1 0 y ]
|
|
143
|
+
# [ 0 0 1 z ]
|
|
144
|
+
# [ 0 0 0 1 ]
|
|
145
|
+
|
|
146
|
+
return xyz.round(11)
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def add_matrices(
|
|
150
|
+
t1: Tuple[float, float, float], t2: Tuple[float, float, float]
|
|
151
|
+
) -> Tuple[float, float, float]:
|
|
152
|
+
"""
|
|
153
|
+
Simple method to convert tuples to numpy arrays and add them.
|
|
154
|
+
"""
|
|
155
|
+
return tuple(np.asarray(t1) + np.asarray(t2))
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def apply_transform(
|
|
159
|
+
t: Union[List[List[float]], DoubleArray],
|
|
160
|
+
pos: AxisPosition,
|
|
161
|
+
) -> Tuple[float, float, float]:
|
|
162
|
+
"""
|
|
163
|
+
Change of base using a transform matrix. Primarily used to render a point
|
|
164
|
+
in space in a way that is more readable for the user.
|
|
165
|
+
|
|
166
|
+
:param t: A transformation matrix from one 3D space [A] to another [B]
|
|
167
|
+
:param pos: XYZ point in space A
|
|
168
|
+
:return: corresponding XYZ point in space B
|
|
169
|
+
"""
|
|
170
|
+
return tuple(dot(t, list(pos))[:3])
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def apply_reverse(
|
|
174
|
+
t: Union[List[List[float]], DoubleArray],
|
|
175
|
+
pos: AxisPosition,
|
|
176
|
+
) -> Tuple[float, float, float]:
|
|
177
|
+
"""Like apply_transform but inverts the transform first"""
|
|
178
|
+
return apply_transform(inv(t), pos)
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from logging.config import dictConfig
|
|
3
|
+
from logging.handlers import QueueListener, RotatingFileHandler
|
|
4
|
+
import sys
|
|
5
|
+
from queue import Queue
|
|
6
|
+
|
|
7
|
+
from opentrons.config import CONFIG, ARCHITECTURE, SystemArchitecture
|
|
8
|
+
|
|
9
|
+
if ARCHITECTURE is SystemArchitecture.YOCTO:
|
|
10
|
+
from opentrons_hardware.sensors import SENSOR_LOG_NAME
|
|
11
|
+
else:
|
|
12
|
+
# we don't use the sensor log on ot2 or host
|
|
13
|
+
SENSOR_LOG_NAME = "unused"
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
# We want this big enough to smooth over any temporary stalls in journald's ability
|
|
17
|
+
# to consume our records--but bounded, so if we consistently outpace journald for
|
|
18
|
+
# some reason, we don't leak memory or get latency from buffer bloat.
|
|
19
|
+
# 50000 is basically an arbitrary guess.
|
|
20
|
+
_LOG_QUEUE_SIZE = 50000
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
log_queue = Queue[logging.LogRecord](maxsize=_LOG_QUEUE_SIZE)
|
|
24
|
+
"""A buffer through which log records will pass.
|
|
25
|
+
|
|
26
|
+
This is intended to work around problems when our logs are going to journald:
|
|
27
|
+
we think journald can block for a while when it flushes records to the filesystem,
|
|
28
|
+
and the backpressure from that will cause calls like `log.debug()` to block and
|
|
29
|
+
interfere with timing-sensitive hardware control.
|
|
30
|
+
https://github.com/Opentrons/opentrons/issues/18034
|
|
31
|
+
|
|
32
|
+
`log_init()` will configure all the logs that this package knows about to pass through
|
|
33
|
+
this queue. This queue is exposed so consumers of this package (i.e. robot-server)
|
|
34
|
+
can do the same thing with their own logs, which is important to preserve ordering.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _config_for_host(level_value: int) -> None:
|
|
39
|
+
serial_log_filename = CONFIG["serial_log_file"]
|
|
40
|
+
api_log_filename = CONFIG["api_log_file"]
|
|
41
|
+
sensor_log_filename = CONFIG["sensor_log_file"]
|
|
42
|
+
config = {
|
|
43
|
+
"version": 1,
|
|
44
|
+
"disable_existing_loggers": False,
|
|
45
|
+
"formatters": {
|
|
46
|
+
"basic": {
|
|
47
|
+
"format": (
|
|
48
|
+
"%(asctime)s %(name)s %(levelname)s [Line %(lineno)s] %(message)s"
|
|
49
|
+
)
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
"handlers": {
|
|
53
|
+
"debug": {
|
|
54
|
+
"class": "logging.StreamHandler",
|
|
55
|
+
"formatter": "basic",
|
|
56
|
+
"level": level_value,
|
|
57
|
+
},
|
|
58
|
+
"serial": {
|
|
59
|
+
"class": "logging.handlers.RotatingFileHandler",
|
|
60
|
+
"formatter": "basic",
|
|
61
|
+
"filename": serial_log_filename,
|
|
62
|
+
"maxBytes": 1000000,
|
|
63
|
+
"level": logging.DEBUG,
|
|
64
|
+
"backupCount": 3,
|
|
65
|
+
},
|
|
66
|
+
"api": {
|
|
67
|
+
"class": "logging.handlers.RotatingFileHandler",
|
|
68
|
+
"formatter": "basic",
|
|
69
|
+
"filename": api_log_filename,
|
|
70
|
+
"maxBytes": 1000000,
|
|
71
|
+
"level": logging.DEBUG,
|
|
72
|
+
"backupCount": 5,
|
|
73
|
+
},
|
|
74
|
+
"sensor": {
|
|
75
|
+
"class": "logging.handlers.RotatingFileHandler",
|
|
76
|
+
"formatter": "basic",
|
|
77
|
+
"filename": sensor_log_filename,
|
|
78
|
+
"maxBytes": 1000000,
|
|
79
|
+
"level": logging.DEBUG,
|
|
80
|
+
"backupCount": 5,
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
"loggers": {
|
|
84
|
+
"opentrons": {
|
|
85
|
+
"handlers": ["debug", "api"],
|
|
86
|
+
"level": level_value,
|
|
87
|
+
},
|
|
88
|
+
"opentrons.deck_calibration": {
|
|
89
|
+
"handlers": ["debug", "api"],
|
|
90
|
+
"level": level_value,
|
|
91
|
+
},
|
|
92
|
+
"opentrons.drivers.asyncio.communication.serial_connection": {
|
|
93
|
+
"handlers": ["serial"],
|
|
94
|
+
"level": logging.DEBUG,
|
|
95
|
+
"propagate": False,
|
|
96
|
+
},
|
|
97
|
+
"opentrons_hardware.drivers.can_bus.can_messenger": {
|
|
98
|
+
"handlers": ["serial"],
|
|
99
|
+
"level": logging.DEBUG,
|
|
100
|
+
"propagate": False,
|
|
101
|
+
},
|
|
102
|
+
"opentrons_hardware.drivers.binary_usb.bin_serial": {
|
|
103
|
+
"handlers": ["serial"],
|
|
104
|
+
"level": logging.DEBUG,
|
|
105
|
+
"propagate": False,
|
|
106
|
+
},
|
|
107
|
+
SENSOR_LOG_NAME: {
|
|
108
|
+
"handlers": ["sensor"],
|
|
109
|
+
"level": logging.DEBUG,
|
|
110
|
+
"propagate": False,
|
|
111
|
+
},
|
|
112
|
+
"__main__": {"handlers": ["api"], "level": level_value},
|
|
113
|
+
},
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
dictConfig(config)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def _config_for_robot(level_value: int) -> None:
|
|
120
|
+
# Import systemd.journald here since it is generally unavailble on non
|
|
121
|
+
# linux systems and we probably don't want to use it on linux desktops
|
|
122
|
+
# either
|
|
123
|
+
from systemd.journal import JournalHandler # type: ignore
|
|
124
|
+
|
|
125
|
+
sensor_log_filename = CONFIG["sensor_log_file"]
|
|
126
|
+
|
|
127
|
+
sensor_log_queue = Queue[logging.LogRecord](maxsize=_LOG_QUEUE_SIZE)
|
|
128
|
+
|
|
129
|
+
config = {
|
|
130
|
+
"version": 1,
|
|
131
|
+
"disable_existing_loggers": False,
|
|
132
|
+
"formatters": {
|
|
133
|
+
"message_only": {"format": "%(message)s"},
|
|
134
|
+
},
|
|
135
|
+
"handlers": {
|
|
136
|
+
"api": {
|
|
137
|
+
"class": "opentrons.util.logging_queue_handler.CustomQueueHandler",
|
|
138
|
+
"level": logging.DEBUG,
|
|
139
|
+
"formatter": "message_only",
|
|
140
|
+
"extra": {"SYSLOG_IDENTIFIER": "opentrons-api"},
|
|
141
|
+
"queue": log_queue,
|
|
142
|
+
},
|
|
143
|
+
"serial": {
|
|
144
|
+
"class": "opentrons.util.logging_queue_handler.CustomQueueHandler",
|
|
145
|
+
"level": logging.DEBUG,
|
|
146
|
+
"formatter": "message_only",
|
|
147
|
+
"extra": {"SYSLOG_IDENTIFIER": "opentrons-api-serial"},
|
|
148
|
+
"queue": log_queue,
|
|
149
|
+
},
|
|
150
|
+
"can_serial": {
|
|
151
|
+
"class": "opentrons.util.logging_queue_handler.CustomQueueHandler",
|
|
152
|
+
"level": logging.DEBUG,
|
|
153
|
+
"formatter": "message_only",
|
|
154
|
+
"extra": {"SYSLOG_IDENTIFIER": "opentrons-api-serial-can"},
|
|
155
|
+
"queue": log_queue,
|
|
156
|
+
},
|
|
157
|
+
"usbbin_serial": {
|
|
158
|
+
"class": "opentrons.util.logging_queue_handler.CustomQueueHandler",
|
|
159
|
+
"level": logging.DEBUG,
|
|
160
|
+
"formatter": "message_only",
|
|
161
|
+
"extra": {"SYSLOG_IDENTIFIER": "opentrons-api-serial-usbbin"},
|
|
162
|
+
"queue": log_queue,
|
|
163
|
+
},
|
|
164
|
+
"sensor": {
|
|
165
|
+
"class": "opentrons.util.logging_queue_handler.CustomQueueHandler",
|
|
166
|
+
"level": logging.DEBUG,
|
|
167
|
+
"formatter": "message_only",
|
|
168
|
+
"queue": sensor_log_queue,
|
|
169
|
+
},
|
|
170
|
+
},
|
|
171
|
+
"loggers": {
|
|
172
|
+
"opentrons.drivers.asyncio.communication.serial_connection": {
|
|
173
|
+
"handlers": ["serial"],
|
|
174
|
+
"level": logging.DEBUG,
|
|
175
|
+
"propagate": False,
|
|
176
|
+
},
|
|
177
|
+
"opentrons": {
|
|
178
|
+
"handlers": ["api"],
|
|
179
|
+
"level": level_value,
|
|
180
|
+
},
|
|
181
|
+
"opentrons_hardware": {
|
|
182
|
+
"handlers": ["api"],
|
|
183
|
+
"level": level_value,
|
|
184
|
+
},
|
|
185
|
+
"opentrons_hardware.drivers.can_bus.can_messenger": {
|
|
186
|
+
"handlers": ["can_serial"],
|
|
187
|
+
"level": logging.DEBUG,
|
|
188
|
+
"propagate": False,
|
|
189
|
+
},
|
|
190
|
+
"opentrons_hardware.drivers.binary_usb.bin_serial": {
|
|
191
|
+
"handlers": ["usbbin_serial"],
|
|
192
|
+
"level": logging.DEBUG,
|
|
193
|
+
"propagate": False,
|
|
194
|
+
},
|
|
195
|
+
SENSOR_LOG_NAME: {
|
|
196
|
+
"handlers": ["sensor"],
|
|
197
|
+
"level": logging.DEBUG,
|
|
198
|
+
"propagate": False,
|
|
199
|
+
},
|
|
200
|
+
"__main__": {"handlers": ["api"], "level": level_value},
|
|
201
|
+
},
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
# Start draining from the queue and sending messages to journald.
|
|
205
|
+
# Then, stash the queue listener in a global variable so it doesn't get garbage-collected.
|
|
206
|
+
# I don't know if we actually need to do this, but let's not find out the hard way.
|
|
207
|
+
global _queue_listener
|
|
208
|
+
if _queue_listener is not None:
|
|
209
|
+
# In case this log init function was called multiple times for some reason.
|
|
210
|
+
_queue_listener.stop()
|
|
211
|
+
_queue_listener = QueueListener(log_queue, JournalHandler())
|
|
212
|
+
_queue_listener.start()
|
|
213
|
+
|
|
214
|
+
# Sensor logs are a special one-off thing that go to their own file instead of journald.
|
|
215
|
+
# We apply the same QueueListener performance workaround for basically the same reasons.
|
|
216
|
+
sensor_rotating_file_handler = RotatingFileHandler(
|
|
217
|
+
filename=sensor_log_filename, maxBytes=1000000, backupCount=3
|
|
218
|
+
)
|
|
219
|
+
sensor_rotating_file_handler.setLevel(logging.DEBUG)
|
|
220
|
+
sensor_rotating_file_handler.setFormatter(logging.Formatter(fmt="%(message)s"))
|
|
221
|
+
global _sensor_queue_listener
|
|
222
|
+
if _sensor_queue_listener is not None:
|
|
223
|
+
_sensor_queue_listener.stop()
|
|
224
|
+
_sensor_queue_listener = QueueListener(
|
|
225
|
+
sensor_log_queue, sensor_rotating_file_handler
|
|
226
|
+
)
|
|
227
|
+
_sensor_queue_listener.start()
|
|
228
|
+
|
|
229
|
+
dictConfig(config)
|
|
230
|
+
|
|
231
|
+
# TODO(2025-04-15): We need some kind of log_deinit() function to call
|
|
232
|
+
# queue_listener.stop() before the process ends. Not doing that means we're
|
|
233
|
+
# dropping some records when the process shuts down.
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
_queue_listener: QueueListener | None = None
|
|
237
|
+
_sensor_queue_listener: QueueListener | None = None
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
def _config(arch: SystemArchitecture, level_value: int) -> None:
|
|
241
|
+
{
|
|
242
|
+
SystemArchitecture.YOCTO: _config_for_robot,
|
|
243
|
+
SystemArchitecture.BUILDROOT: _config_for_robot,
|
|
244
|
+
SystemArchitecture.HOST: _config_for_host,
|
|
245
|
+
}[arch](level_value)
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
def log_init(level_name: str) -> None:
|
|
249
|
+
"""
|
|
250
|
+
Function that sets log levels and format strings. Checks for the
|
|
251
|
+
OT_API_LOG_LEVEL environment variable otherwise defaults to INFO
|
|
252
|
+
"""
|
|
253
|
+
fallback_log_level = "INFO"
|
|
254
|
+
ot_log_level = level_name.upper()
|
|
255
|
+
if ot_log_level not in logging._nameToLevel:
|
|
256
|
+
sys.stderr.write(
|
|
257
|
+
f"OT Log Level {ot_log_level} not found. "
|
|
258
|
+
f"Defaulting to {fallback_log_level}\n"
|
|
259
|
+
)
|
|
260
|
+
ot_log_level = fallback_log_level
|
|
261
|
+
|
|
262
|
+
# todo(mm, 2025-04-14): Use logging.getLevelNamesMapping() when we have Python >=3.11.
|
|
263
|
+
level_value = logging._nameToLevel[ot_log_level]
|
|
264
|
+
|
|
265
|
+
_config(ARCHITECTURE, level_value)
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# noqa: D100
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
import logging.handlers
|
|
5
|
+
import logging
|
|
6
|
+
from queue import Queue
|
|
7
|
+
from typing import cast
|
|
8
|
+
from typing_extensions import override
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class CustomQueueHandler(logging.handlers.QueueHandler):
|
|
12
|
+
"""A logging.QueueHandler with some customizations.
|
|
13
|
+
|
|
14
|
+
- Allow adding `extra` data to handled log records.
|
|
15
|
+
|
|
16
|
+
- Simplify and optimize for single-process use.
|
|
17
|
+
|
|
18
|
+
- If a new message comes in but the queue is full, block until it has room.
|
|
19
|
+
(The default QueueHandler drops records in a way we probably wouldn't notice.)
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
def __init__(
|
|
23
|
+
self, *, queue: Queue[logging.LogRecord], extra: dict[str, object] | None = None
|
|
24
|
+
) -> None:
|
|
25
|
+
"""Construct the handler.
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
queue: When this handler receives a log record, it will insert the message
|
|
29
|
+
into this queue.
|
|
30
|
+
extra: Extra data to attach to each log record, to be interpreted by
|
|
31
|
+
whatever handler is on the consuming side of the queue. e.g. if that's
|
|
32
|
+
`systemd.journal.JournalHandler`, you could add a "SYSLOG_IDENTIFIER"
|
|
33
|
+
key here. This corresponds to the `extra` arg of `Logger.debug()`.
|
|
34
|
+
"""
|
|
35
|
+
super().__init__(queue=queue)
|
|
36
|
+
|
|
37
|
+
# Double underscore because we're subclassing external code so we should try to
|
|
38
|
+
# avoid collisions with its attributes.
|
|
39
|
+
self.__extra = extra
|
|
40
|
+
|
|
41
|
+
@override
|
|
42
|
+
def prepare(self, record: logging.LogRecord) -> logging.LogRecord:
|
|
43
|
+
"""Called internally by the superclass before enqueueing a record."""
|
|
44
|
+
if self.__extra is not None:
|
|
45
|
+
# This looks questionable, but updating __dict__ is the documented behavior
|
|
46
|
+
# of `Logger.debug(msg, extra=...)`.
|
|
47
|
+
record.__dict__.update(self.__extra)
|
|
48
|
+
|
|
49
|
+
# We intentionally do *not* call `super().prepare(record)`. It's documented to
|
|
50
|
+
# muck with the data in the LogRecord, apparently as part of supporting
|
|
51
|
+
# inter-process use. Since we don't need that, we can preserve the original
|
|
52
|
+
# data and also save some compute time.
|
|
53
|
+
return record
|
|
54
|
+
|
|
55
|
+
@override
|
|
56
|
+
def enqueue(self, record: logging.LogRecord) -> None:
|
|
57
|
+
"""Called internally by the superclass to enqueue a record."""
|
|
58
|
+
# This cast is safe because we constrain the type of `self.queue`
|
|
59
|
+
# in our `__init__()` and nobody should mutate it after-the-fact, in practice.
|
|
60
|
+
queue = cast(Queue[logging.LogRecord], self.queue)
|
|
61
|
+
queue.put(record)
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"""Performance helpers for tracking robot activity."""
|
|
2
|
+
|
|
3
|
+
import functools
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from opentrons_shared_data.robot.types import RobotTypeEnum
|
|
7
|
+
import typing
|
|
8
|
+
from opentrons.config import (
|
|
9
|
+
get_performance_metrics_data_dir,
|
|
10
|
+
robot_configs,
|
|
11
|
+
feature_flags as ff,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
if typing.TYPE_CHECKING:
|
|
15
|
+
from performance_metrics import RobotActivityState, SupportsTracking
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
_UnderlyingFunctionParameters = typing.ParamSpec("_UnderlyingFunctionParameters")
|
|
19
|
+
_UnderlyingFunctionReturn = typing.TypeVar("_UnderlyingFunctionReturn")
|
|
20
|
+
_UnderlyingFunction = typing.Callable[
|
|
21
|
+
_UnderlyingFunctionParameters, _UnderlyingFunctionReturn
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
_should_track = ff.enable_performance_metrics(
|
|
26
|
+
RobotTypeEnum.robot_literal_to_enum(robot_configs.load().model)
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class _StubbedTracker:
|
|
31
|
+
"""A stubbed tracker that does nothing."""
|
|
32
|
+
|
|
33
|
+
def __init__(self, storage_location: Path, should_track: bool) -> None:
|
|
34
|
+
"""Initialize the stubbed tracker."""
|
|
35
|
+
pass
|
|
36
|
+
|
|
37
|
+
def track(
|
|
38
|
+
self,
|
|
39
|
+
state: "RobotActivityState",
|
|
40
|
+
) -> typing.Callable[
|
|
41
|
+
[_UnderlyingFunction[_UnderlyingFunctionParameters, _UnderlyingFunctionReturn]],
|
|
42
|
+
_UnderlyingFunction[_UnderlyingFunctionParameters, _UnderlyingFunctionReturn],
|
|
43
|
+
]:
|
|
44
|
+
"""Return the original function."""
|
|
45
|
+
|
|
46
|
+
def inner_decorator(
|
|
47
|
+
func: _UnderlyingFunction[
|
|
48
|
+
_UnderlyingFunctionParameters, _UnderlyingFunctionReturn
|
|
49
|
+
]
|
|
50
|
+
) -> _UnderlyingFunction[
|
|
51
|
+
_UnderlyingFunctionParameters, _UnderlyingFunctionReturn
|
|
52
|
+
]:
|
|
53
|
+
"""Return the original function."""
|
|
54
|
+
return func
|
|
55
|
+
|
|
56
|
+
return inner_decorator
|
|
57
|
+
|
|
58
|
+
def store(self) -> None:
|
|
59
|
+
"""Do nothing."""
|
|
60
|
+
pass
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
# Ensure that _StubbedTracker implements SupportsTracking
|
|
64
|
+
# but do not create a runtime dependency on performance_metrics
|
|
65
|
+
if typing.TYPE_CHECKING:
|
|
66
|
+
_: typing.Type["SupportsTracking"] = _StubbedTracker
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def _handle_package_import() -> typing.Type["SupportsTracking"]:
|
|
70
|
+
"""Handle the import of the performance_metrics package.
|
|
71
|
+
|
|
72
|
+
If the package is not available, return a stubbed tracker.
|
|
73
|
+
"""
|
|
74
|
+
try:
|
|
75
|
+
from performance_metrics import RobotActivityTracker
|
|
76
|
+
|
|
77
|
+
return RobotActivityTracker
|
|
78
|
+
except ImportError:
|
|
79
|
+
return _StubbedTracker
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
_package_to_use = _handle_package_import()
|
|
83
|
+
_robot_activity_tracker: typing.Optional["SupportsTracking"] = None
|
|
84
|
+
|
|
85
|
+
# TODO: derek maggio (06-03-2024): investigate if _should_track should be
|
|
86
|
+
# reevaluated each time _get_robot_activity_tracker is called. I think this
|
|
87
|
+
# might get stuck in a state where after the first call, _should_track is
|
|
88
|
+
# always considered the initial value. It might miss changes to the feature
|
|
89
|
+
# flag. The easiest way to test this is on a robot when that is working.
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def _get_robot_activity_tracker() -> "SupportsTracking":
|
|
93
|
+
"""Singleton for the robot activity tracker."""
|
|
94
|
+
global _robot_activity_tracker
|
|
95
|
+
if _robot_activity_tracker is None:
|
|
96
|
+
_robot_activity_tracker = _package_to_use(
|
|
97
|
+
get_performance_metrics_data_dir(), _should_track
|
|
98
|
+
)
|
|
99
|
+
return _robot_activity_tracker
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def _track_a_function(
|
|
103
|
+
state_name: "RobotActivityState",
|
|
104
|
+
func: _UnderlyingFunction[_UnderlyingFunctionParameters, _UnderlyingFunctionReturn],
|
|
105
|
+
) -> typing.Callable[_UnderlyingFunctionParameters, _UnderlyingFunctionReturn]:
|
|
106
|
+
"""Wrap a passed function with RobotActivityTracker.track.
|
|
107
|
+
|
|
108
|
+
This function is a decorator that will track the given state for the
|
|
109
|
+
decorated function.
|
|
110
|
+
|
|
111
|
+
Args:
|
|
112
|
+
state_name: The state to annotate the tracked function with.
|
|
113
|
+
func: The function to decorate.
|
|
114
|
+
|
|
115
|
+
Returns:
|
|
116
|
+
The decorated function.
|
|
117
|
+
"""
|
|
118
|
+
tracker: SupportsTracking = _get_robot_activity_tracker()
|
|
119
|
+
wrapped = tracker.track(state=state_name)(func)
|
|
120
|
+
|
|
121
|
+
@functools.wraps(func)
|
|
122
|
+
def wrapper(
|
|
123
|
+
*args: _UnderlyingFunctionParameters.args,
|
|
124
|
+
**kwargs: _UnderlyingFunctionParameters.kwargs
|
|
125
|
+
) -> _UnderlyingFunctionReturn:
|
|
126
|
+
try:
|
|
127
|
+
return wrapped(*args, **kwargs)
|
|
128
|
+
finally:
|
|
129
|
+
# TODO: derek maggio (06-18-2024): After investigation, it appears on startup
|
|
130
|
+
# that the first call to tracker.store() will not actually store the data.
|
|
131
|
+
# The second call stores both rows of data.
|
|
132
|
+
|
|
133
|
+
tracker.store()
|
|
134
|
+
|
|
135
|
+
return wrapper
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
class TrackingFunctions:
|
|
139
|
+
"""A class for tracking functions."""
|
|
140
|
+
|
|
141
|
+
@staticmethod
|
|
142
|
+
def track_analysis(
|
|
143
|
+
func: _UnderlyingFunction[
|
|
144
|
+
_UnderlyingFunctionParameters, _UnderlyingFunctionReturn
|
|
145
|
+
]
|
|
146
|
+
) -> typing.Callable[_UnderlyingFunctionParameters, _UnderlyingFunctionReturn]:
|
|
147
|
+
"""Track a function that runs an analysis."""
|
|
148
|
+
return _track_a_function("ANALYZING_PROTOCOL", func)
|
|
149
|
+
|
|
150
|
+
@staticmethod
|
|
151
|
+
def track_getting_cached_protocol_analysis(
|
|
152
|
+
func: _UnderlyingFunction[
|
|
153
|
+
_UnderlyingFunctionParameters, _UnderlyingFunctionReturn
|
|
154
|
+
]
|
|
155
|
+
) -> typing.Callable[_UnderlyingFunctionParameters, _UnderlyingFunctionReturn]:
|
|
156
|
+
"""Track a function that gets cached analysis."""
|
|
157
|
+
return _track_a_function("GETTING_CACHED_ANALYSIS", func)
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: opentrons
|
|
3
|
+
Version: 8.6.0
|
|
4
|
+
Summary: The Opentrons API is a simple framework designed to make writing automated biology lab protocols easy.
|
|
5
|
+
Project-URL: opentrons.com, https://www.opentrons.com
|
|
6
|
+
Project-URL: Source Code On Github, https://github.com/Opentrons/opentrons/tree/edge/api
|
|
7
|
+
Project-URL: Documentation, https://docs.opentrons.com
|
|
8
|
+
Author-email: Opentrons <engineering@opentrons.com>
|
|
9
|
+
License-Expression: Apache-2.0
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: automation,lab,pcr,protocols,robots,synbio
|
|
12
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Science/Research
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Topic :: Scientific/Engineering
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
Requires-Dist: aionotify==0.3.1
|
|
22
|
+
Requires-Dist: anyio<5.0.0,>=4.9.0
|
|
23
|
+
Requires-Dist: click<9,>=8.0.0
|
|
24
|
+
Requires-Dist: importlib-metadata>=1.0; python_version < '3.8'
|
|
25
|
+
Requires-Dist: jsonschema<4.18.0,>=3.0.1
|
|
26
|
+
Requires-Dist: numpy<2,>=1.20.0
|
|
27
|
+
Requires-Dist: opentrons-shared-data==8.6.0
|
|
28
|
+
Requires-Dist: packaging>=21.0
|
|
29
|
+
Requires-Dist: pydantic-settings<3,>=2
|
|
30
|
+
Requires-Dist: pydantic<3,>=2.0.0
|
|
31
|
+
Requires-Dist: pyserial>=3.5
|
|
32
|
+
Requires-Dist: pyusb==1.2.1
|
|
33
|
+
Requires-Dist: typing-extensions<5,>=4.0.0
|
|
34
|
+
Provides-Extra: flex-hardware
|
|
35
|
+
Requires-Dist: opentrons-hardware[flex]==8.6.0; extra == 'flex-hardware'
|
|
36
|
+
Provides-Extra: ot2-hardware
|
|
37
|
+
Requires-Dist: opentrons-hardware==8.6.0; extra == 'ot2-hardware'
|