opentrons 8.1.0a0__py2.py3-none-any.whl → 8.2.0a0__py2.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.

Files changed (230) hide show
  1. opentrons/cli/analyze.py +71 -7
  2. opentrons/config/__init__.py +9 -0
  3. opentrons/config/advanced_settings.py +22 -0
  4. opentrons/config/defaults_ot3.py +14 -36
  5. opentrons/config/feature_flags.py +4 -0
  6. opentrons/config/types.py +6 -17
  7. opentrons/drivers/absorbance_reader/abstract.py +27 -3
  8. opentrons/drivers/absorbance_reader/async_byonoy.py +207 -154
  9. opentrons/drivers/absorbance_reader/driver.py +24 -15
  10. opentrons/drivers/absorbance_reader/hid_protocol.py +79 -50
  11. opentrons/drivers/absorbance_reader/simulator.py +32 -6
  12. opentrons/drivers/types.py +23 -1
  13. opentrons/execute.py +2 -2
  14. opentrons/hardware_control/api.py +18 -10
  15. opentrons/hardware_control/backends/controller.py +3 -2
  16. opentrons/hardware_control/backends/flex_protocol.py +11 -5
  17. opentrons/hardware_control/backends/ot3controller.py +18 -50
  18. opentrons/hardware_control/backends/ot3simulator.py +7 -6
  19. opentrons/hardware_control/instruments/ot2/pipette_handler.py +22 -82
  20. opentrons/hardware_control/instruments/ot3/pipette_handler.py +10 -2
  21. opentrons/hardware_control/module_control.py +43 -2
  22. opentrons/hardware_control/modules/__init__.py +7 -1
  23. opentrons/hardware_control/modules/absorbance_reader.py +230 -83
  24. opentrons/hardware_control/modules/errors.py +7 -0
  25. opentrons/hardware_control/modules/heater_shaker.py +8 -3
  26. opentrons/hardware_control/modules/magdeck.py +12 -3
  27. opentrons/hardware_control/modules/mod_abc.py +27 -2
  28. opentrons/hardware_control/modules/tempdeck.py +15 -7
  29. opentrons/hardware_control/modules/thermocycler.py +69 -3
  30. opentrons/hardware_control/modules/types.py +11 -5
  31. opentrons/hardware_control/modules/update.py +11 -5
  32. opentrons/hardware_control/modules/utils.py +3 -1
  33. opentrons/hardware_control/ot3_calibration.py +6 -6
  34. opentrons/hardware_control/ot3api.py +126 -89
  35. opentrons/hardware_control/poller.py +15 -11
  36. opentrons/hardware_control/protocols/__init__.py +1 -7
  37. opentrons/hardware_control/protocols/instrument_configurer.py +14 -2
  38. opentrons/hardware_control/protocols/liquid_handler.py +5 -0
  39. opentrons/motion_planning/__init__.py +2 -0
  40. opentrons/motion_planning/waypoints.py +32 -0
  41. opentrons/protocol_api/__init__.py +2 -1
  42. opentrons/protocol_api/_liquid.py +87 -1
  43. opentrons/protocol_api/_parameter_context.py +10 -1
  44. opentrons/protocol_api/core/engine/deck_conflict.py +0 -297
  45. opentrons/protocol_api/core/engine/instrument.py +29 -25
  46. opentrons/protocol_api/core/engine/labware.py +10 -2
  47. opentrons/protocol_api/core/engine/module_core.py +129 -17
  48. opentrons/protocol_api/core/engine/pipette_movement_conflict.py +355 -0
  49. opentrons/protocol_api/core/engine/protocol.py +55 -2
  50. opentrons/protocol_api/core/instrument.py +2 -0
  51. opentrons/protocol_api/core/legacy/legacy_instrument_core.py +2 -0
  52. opentrons/protocol_api/core/legacy/legacy_protocol_core.py +5 -2
  53. opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +2 -0
  54. opentrons/protocol_api/core/module.py +22 -4
  55. opentrons/protocol_api/core/protocol.py +5 -2
  56. opentrons/protocol_api/instrument_context.py +52 -20
  57. opentrons/protocol_api/labware.py +13 -1
  58. opentrons/protocol_api/module_contexts.py +68 -13
  59. opentrons/protocol_api/protocol_context.py +38 -4
  60. opentrons/protocol_api/validation.py +5 -3
  61. opentrons/protocol_engine/__init__.py +10 -9
  62. opentrons/protocol_engine/actions/__init__.py +5 -0
  63. opentrons/protocol_engine/actions/actions.py +42 -25
  64. opentrons/protocol_engine/actions/get_state_update.py +38 -0
  65. opentrons/protocol_engine/clients/sync_client.py +7 -1
  66. opentrons/protocol_engine/clients/transports.py +1 -1
  67. opentrons/protocol_engine/commands/__init__.py +0 -4
  68. opentrons/protocol_engine/commands/absorbance_reader/__init__.py +41 -11
  69. opentrons/protocol_engine/commands/absorbance_reader/close_lid.py +161 -0
  70. opentrons/protocol_engine/commands/absorbance_reader/initialize.py +53 -9
  71. opentrons/protocol_engine/commands/absorbance_reader/open_lid.py +160 -0
  72. opentrons/protocol_engine/commands/absorbance_reader/read.py +196 -0
  73. opentrons/protocol_engine/commands/aspirate.py +29 -16
  74. opentrons/protocol_engine/commands/aspirate_in_place.py +32 -15
  75. opentrons/protocol_engine/commands/blow_out.py +63 -14
  76. opentrons/protocol_engine/commands/blow_out_in_place.py +55 -13
  77. opentrons/protocol_engine/commands/calibration/calibrate_gripper.py +2 -5
  78. opentrons/protocol_engine/commands/calibration/calibrate_module.py +3 -4
  79. opentrons/protocol_engine/commands/calibration/calibrate_pipette.py +2 -5
  80. opentrons/protocol_engine/commands/calibration/move_to_maintenance_position.py +6 -4
  81. opentrons/protocol_engine/commands/command.py +28 -17
  82. opentrons/protocol_engine/commands/command_unions.py +37 -24
  83. opentrons/protocol_engine/commands/comment.py +5 -3
  84. opentrons/protocol_engine/commands/configure_for_volume.py +11 -14
  85. opentrons/protocol_engine/commands/configure_nozzle_layout.py +9 -15
  86. opentrons/protocol_engine/commands/custom.py +5 -3
  87. opentrons/protocol_engine/commands/dispense.py +42 -20
  88. opentrons/protocol_engine/commands/dispense_in_place.py +32 -14
  89. opentrons/protocol_engine/commands/drop_tip.py +68 -15
  90. opentrons/protocol_engine/commands/drop_tip_in_place.py +52 -11
  91. opentrons/protocol_engine/commands/get_tip_presence.py +5 -3
  92. opentrons/protocol_engine/commands/heater_shaker/close_labware_latch.py +6 -6
  93. opentrons/protocol_engine/commands/heater_shaker/deactivate_heater.py +6 -6
  94. opentrons/protocol_engine/commands/heater_shaker/deactivate_shaker.py +6 -6
  95. opentrons/protocol_engine/commands/heater_shaker/open_labware_latch.py +8 -6
  96. opentrons/protocol_engine/commands/heater_shaker/set_and_wait_for_shake_speed.py +8 -4
  97. opentrons/protocol_engine/commands/heater_shaker/set_target_temperature.py +6 -4
  98. opentrons/protocol_engine/commands/heater_shaker/wait_for_temperature.py +6 -6
  99. opentrons/protocol_engine/commands/home.py +11 -5
  100. opentrons/protocol_engine/commands/liquid_probe.py +146 -88
  101. opentrons/protocol_engine/commands/load_labware.py +19 -5
  102. opentrons/protocol_engine/commands/load_liquid.py +18 -7
  103. opentrons/protocol_engine/commands/load_module.py +43 -6
  104. opentrons/protocol_engine/commands/load_pipette.py +18 -17
  105. opentrons/protocol_engine/commands/magnetic_module/disengage.py +6 -6
  106. opentrons/protocol_engine/commands/magnetic_module/engage.py +6 -4
  107. opentrons/protocol_engine/commands/move_labware.py +106 -19
  108. opentrons/protocol_engine/commands/move_relative.py +15 -3
  109. opentrons/protocol_engine/commands/move_to_addressable_area.py +29 -4
  110. opentrons/protocol_engine/commands/move_to_addressable_area_for_drop_tip.py +13 -4
  111. opentrons/protocol_engine/commands/move_to_coordinates.py +11 -5
  112. opentrons/protocol_engine/commands/move_to_well.py +37 -10
  113. opentrons/protocol_engine/commands/pick_up_tip.py +50 -29
  114. opentrons/protocol_engine/commands/pipetting_common.py +39 -15
  115. opentrons/protocol_engine/commands/prepare_to_aspirate.py +62 -15
  116. opentrons/protocol_engine/commands/reload_labware.py +13 -4
  117. opentrons/protocol_engine/commands/retract_axis.py +6 -3
  118. opentrons/protocol_engine/commands/save_position.py +2 -3
  119. opentrons/protocol_engine/commands/set_rail_lights.py +5 -3
  120. opentrons/protocol_engine/commands/set_status_bar.py +5 -3
  121. opentrons/protocol_engine/commands/temperature_module/deactivate.py +6 -4
  122. opentrons/protocol_engine/commands/temperature_module/set_target_temperature.py +3 -4
  123. opentrons/protocol_engine/commands/temperature_module/wait_for_temperature.py +6 -6
  124. opentrons/protocol_engine/commands/thermocycler/__init__.py +19 -0
  125. opentrons/protocol_engine/commands/thermocycler/close_lid.py +8 -8
  126. opentrons/protocol_engine/commands/thermocycler/deactivate_block.py +6 -4
  127. opentrons/protocol_engine/commands/thermocycler/deactivate_lid.py +6 -4
  128. opentrons/protocol_engine/commands/thermocycler/open_lid.py +8 -4
  129. opentrons/protocol_engine/commands/thermocycler/run_extended_profile.py +165 -0
  130. opentrons/protocol_engine/commands/thermocycler/run_profile.py +6 -6
  131. opentrons/protocol_engine/commands/thermocycler/set_target_block_temperature.py +3 -4
  132. opentrons/protocol_engine/commands/thermocycler/set_target_lid_temperature.py +3 -4
  133. opentrons/protocol_engine/commands/thermocycler/wait_for_block_temperature.py +6 -4
  134. opentrons/protocol_engine/commands/thermocycler/wait_for_lid_temperature.py +6 -4
  135. opentrons/protocol_engine/commands/touch_tip.py +19 -7
  136. opentrons/protocol_engine/commands/unsafe/__init__.py +30 -0
  137. opentrons/protocol_engine/commands/unsafe/unsafe_blow_out_in_place.py +6 -4
  138. opentrons/protocol_engine/commands/unsafe/unsafe_drop_tip_in_place.py +12 -4
  139. opentrons/protocol_engine/commands/unsafe/unsafe_engage_axes.py +5 -3
  140. opentrons/protocol_engine/commands/unsafe/unsafe_place_labware.py +194 -0
  141. opentrons/protocol_engine/commands/unsafe/unsafe_ungrip_labware.py +75 -0
  142. opentrons/protocol_engine/commands/unsafe/update_position_estimators.py +5 -3
  143. opentrons/protocol_engine/commands/verify_tip_presence.py +5 -5
  144. opentrons/protocol_engine/commands/wait_for_duration.py +5 -3
  145. opentrons/protocol_engine/commands/wait_for_resume.py +5 -3
  146. opentrons/protocol_engine/create_protocol_engine.py +41 -8
  147. opentrons/protocol_engine/engine_support.py +2 -1
  148. opentrons/protocol_engine/error_recovery_policy.py +14 -3
  149. opentrons/protocol_engine/errors/__init__.py +18 -0
  150. opentrons/protocol_engine/errors/exceptions.py +114 -2
  151. opentrons/protocol_engine/execution/__init__.py +2 -0
  152. opentrons/protocol_engine/execution/command_executor.py +22 -13
  153. opentrons/protocol_engine/execution/create_queue_worker.py +5 -1
  154. opentrons/protocol_engine/execution/door_watcher.py +1 -1
  155. opentrons/protocol_engine/execution/equipment.py +2 -1
  156. opentrons/protocol_engine/execution/error_recovery_hardware_state_synchronizer.py +101 -0
  157. opentrons/protocol_engine/execution/gantry_mover.py +4 -2
  158. opentrons/protocol_engine/execution/hardware_stopper.py +3 -3
  159. opentrons/protocol_engine/execution/heater_shaker_movement_flagger.py +1 -4
  160. opentrons/protocol_engine/execution/labware_movement.py +6 -3
  161. opentrons/protocol_engine/execution/movement.py +8 -3
  162. opentrons/protocol_engine/execution/pipetting.py +7 -4
  163. opentrons/protocol_engine/execution/queue_worker.py +6 -2
  164. opentrons/protocol_engine/execution/run_control.py +1 -1
  165. opentrons/protocol_engine/execution/thermocycler_movement_flagger.py +1 -1
  166. opentrons/protocol_engine/execution/thermocycler_plate_lifter.py +2 -1
  167. opentrons/protocol_engine/execution/tip_handler.py +77 -43
  168. opentrons/protocol_engine/notes/__init__.py +14 -2
  169. opentrons/protocol_engine/notes/notes.py +18 -1
  170. opentrons/protocol_engine/plugins.py +1 -1
  171. opentrons/protocol_engine/protocol_engine.py +54 -31
  172. opentrons/protocol_engine/resources/__init__.py +2 -0
  173. opentrons/protocol_engine/resources/deck_data_provider.py +58 -5
  174. opentrons/protocol_engine/resources/file_provider.py +157 -0
  175. opentrons/protocol_engine/resources/fixture_validation.py +5 -0
  176. opentrons/protocol_engine/resources/labware_validation.py +10 -0
  177. opentrons/protocol_engine/state/__init__.py +0 -70
  178. opentrons/protocol_engine/state/addressable_areas.py +1 -1
  179. opentrons/protocol_engine/state/command_history.py +21 -2
  180. opentrons/protocol_engine/state/commands.py +110 -31
  181. opentrons/protocol_engine/state/files.py +59 -0
  182. opentrons/protocol_engine/state/frustum_helpers.py +440 -0
  183. opentrons/protocol_engine/state/geometry.py +359 -15
  184. opentrons/protocol_engine/state/labware.py +166 -63
  185. opentrons/protocol_engine/state/liquids.py +1 -1
  186. opentrons/protocol_engine/state/module_substates/absorbance_reader_substate.py +19 -3
  187. opentrons/protocol_engine/state/modules.py +167 -85
  188. opentrons/protocol_engine/state/motion.py +16 -9
  189. opentrons/protocol_engine/state/pipettes.py +157 -317
  190. opentrons/protocol_engine/state/state.py +30 -1
  191. opentrons/protocol_engine/state/state_summary.py +3 -0
  192. opentrons/protocol_engine/state/tips.py +69 -114
  193. opentrons/protocol_engine/state/update_types.py +408 -0
  194. opentrons/protocol_engine/state/wells.py +236 -0
  195. opentrons/protocol_engine/types.py +90 -0
  196. opentrons/protocol_reader/file_format_validator.py +83 -15
  197. opentrons/protocol_runner/json_translator.py +21 -5
  198. opentrons/protocol_runner/legacy_command_mapper.py +27 -6
  199. opentrons/protocol_runner/legacy_context_plugin.py +27 -71
  200. opentrons/protocol_runner/protocol_runner.py +6 -3
  201. opentrons/protocol_runner/run_orchestrator.py +26 -6
  202. opentrons/protocols/advanced_control/mix.py +3 -5
  203. opentrons/protocols/advanced_control/transfers.py +125 -56
  204. opentrons/protocols/api_support/constants.py +1 -1
  205. opentrons/protocols/api_support/definitions.py +1 -1
  206. opentrons/protocols/api_support/labware_like.py +4 -4
  207. opentrons/protocols/api_support/tip_tracker.py +2 -2
  208. opentrons/protocols/api_support/types.py +15 -2
  209. opentrons/protocols/api_support/util.py +30 -42
  210. opentrons/protocols/duration/errors.py +1 -1
  211. opentrons/protocols/duration/estimator.py +50 -29
  212. opentrons/protocols/execution/dev_types.py +2 -2
  213. opentrons/protocols/execution/execute_json_v4.py +15 -10
  214. opentrons/protocols/execution/execute_python.py +8 -3
  215. opentrons/protocols/geometry/planning.py +12 -12
  216. opentrons/protocols/labware.py +17 -33
  217. opentrons/simulate.py +3 -3
  218. opentrons/types.py +30 -3
  219. opentrons/util/logging_config.py +34 -0
  220. {opentrons-8.1.0a0.dist-info → opentrons-8.2.0a0.dist-info}/METADATA +5 -4
  221. {opentrons-8.1.0a0.dist-info → opentrons-8.2.0a0.dist-info}/RECORD +227 -215
  222. opentrons/protocol_engine/commands/absorbance_reader/measure.py +0 -94
  223. opentrons/protocol_engine/commands/configuring_common.py +0 -26
  224. opentrons/protocol_runner/thread_async_queue.py +0 -174
  225. /opentrons/protocol_engine/state/{abstract_store.py → _abstract_store.py} +0 -0
  226. /opentrons/protocol_engine/state/{move_types.py → _move_types.py} +0 -0
  227. {opentrons-8.1.0a0.dist-info → opentrons-8.2.0a0.dist-info}/LICENSE +0 -0
  228. {opentrons-8.1.0a0.dist-info → opentrons-8.2.0a0.dist-info}/WHEEL +0 -0
  229. {opentrons-8.1.0a0.dist-info → opentrons-8.2.0a0.dist-info}/entry_points.txt +0 -0
  230. {opentrons-8.1.0a0.dist-info → opentrons-8.2.0a0.dist-info}/top_level.txt +0 -0
@@ -9,7 +9,7 @@ from ..command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, Succe
9
9
  from ...errors.error_occurrence import ErrorOccurrence
10
10
 
11
11
  if TYPE_CHECKING:
12
- from opentrons.protocol_engine.state import StateView
12
+ from opentrons.protocol_engine.state.state import StateView
13
13
  from opentrons.protocol_engine.execution import EquipmentHandler
14
14
 
15
15
  SetTargetTemperatureCommandType = Literal["temperatureModule/setTargetTemperature"]
@@ -34,7 +34,7 @@ class SetTargetTemperatureResult(BaseModel):
34
34
 
35
35
  class SetTargetTemperatureImpl(
36
36
  AbstractCommandImpl[
37
- SetTargetTemperatureParams, SuccessData[SetTargetTemperatureResult, None]
37
+ SetTargetTemperatureParams, SuccessData[SetTargetTemperatureResult]
38
38
  ]
39
39
  ):
40
40
  """Execution implementation of a Temperature Module's set temperature command."""
@@ -50,7 +50,7 @@ class SetTargetTemperatureImpl(
50
50
 
51
51
  async def execute(
52
52
  self, params: SetTargetTemperatureParams
53
- ) -> SuccessData[SetTargetTemperatureResult, None]:
53
+ ) -> SuccessData[SetTargetTemperatureResult]:
54
54
  """Set a Temperature Module's target temperature."""
55
55
  # Allow propagation of ModuleNotLoadedError and WrongModuleTypeError.
56
56
  module_substate = self._state_view.modules.get_temperature_module_substate(
@@ -69,7 +69,6 @@ class SetTargetTemperatureImpl(
69
69
  await temp_hardware_module.start_set_temperature(celsius=validated_temp)
70
70
  return SuccessData(
71
71
  public=SetTargetTemperatureResult(targetTemperature=validated_temp),
72
- private=None,
73
72
  )
74
73
 
75
74
 
@@ -9,7 +9,7 @@ from ..command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, Succe
9
9
  from ...errors.error_occurrence import ErrorOccurrence
10
10
 
11
11
  if TYPE_CHECKING:
12
- from opentrons.protocol_engine.state import StateView
12
+ from opentrons.protocol_engine.state.state import StateView
13
13
  from opentrons.protocol_engine.execution import EquipmentHandler
14
14
 
15
15
  WaitForTemperatureCommandType = Literal["temperatureModule/waitForTemperature"]
@@ -35,9 +35,7 @@ class WaitForTemperatureResult(BaseModel):
35
35
 
36
36
 
37
37
  class WaitForTemperatureImpl(
38
- AbstractCommandImpl[
39
- WaitForTemperatureParams, SuccessData[WaitForTemperatureResult, None]
40
- ]
38
+ AbstractCommandImpl[WaitForTemperatureParams, SuccessData[WaitForTemperatureResult]]
41
39
  ):
42
40
  """Execution implementation of Temperature Module's wait for temperature command."""
43
41
 
@@ -52,7 +50,7 @@ class WaitForTemperatureImpl(
52
50
 
53
51
  async def execute(
54
52
  self, params: WaitForTemperatureParams
55
- ) -> SuccessData[WaitForTemperatureResult, None]:
53
+ ) -> SuccessData[WaitForTemperatureResult]:
56
54
  """Wait for a Temperature Module's target temperature."""
57
55
  # Allow propagation of ModuleNotLoadedError and WrongModuleTypeError.
58
56
  module_substate = self._state_view.modules.get_temperature_module_substate(
@@ -74,7 +72,9 @@ class WaitForTemperatureImpl(
74
72
  await temp_hardware_module.await_temperature(
75
73
  awaiting_temperature=target_temp
76
74
  )
77
- return SuccessData(public=WaitForTemperatureResult(), private=None)
75
+ return SuccessData(
76
+ public=WaitForTemperatureResult(),
77
+ )
78
78
 
79
79
 
80
80
  class WaitForTemperature(
@@ -73,6 +73,16 @@ from .run_profile import (
73
73
  RunProfileCreate,
74
74
  )
75
75
 
76
+ from .run_extended_profile import (
77
+ RunExtendedProfileCommandType,
78
+ RunExtendedProfileParams,
79
+ RunExtendedProfileResult,
80
+ RunExtendedProfile,
81
+ RunExtendedProfileCreate,
82
+ ProfileCycle,
83
+ ProfileStep,
84
+ )
85
+
76
86
 
77
87
  __all__ = [
78
88
  # Set target block temperature command models
@@ -130,4 +140,13 @@ __all__ = [
130
140
  "RunProfileResult",
131
141
  "RunProfile",
132
142
  "RunProfileCreate",
143
+ # Run extended profile command models.
144
+ "RunExtendedProfileCommandType",
145
+ "RunExtendedProfileParams",
146
+ "RunExtendedProfileStepParams",
147
+ "RunExtendedProfileResult",
148
+ "RunExtendedProfile",
149
+ "RunExtendedProfileCreate",
150
+ "ProfileCycle",
151
+ "ProfileStep",
133
152
  ]
@@ -7,10 +7,11 @@ from pydantic import BaseModel, Field
7
7
 
8
8
  from ..command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, SuccessData
9
9
  from ...errors.error_occurrence import ErrorOccurrence
10
+ from ...state import update_types
10
11
  from opentrons.protocol_engine.types import MotorAxis
11
12
 
12
13
  if TYPE_CHECKING:
13
- from opentrons.protocol_engine.state import StateView
14
+ from opentrons.protocol_engine.state.state import StateView
14
15
  from opentrons.protocol_engine.execution import EquipmentHandler, MovementHandler
15
16
 
16
17
 
@@ -27,9 +28,7 @@ class CloseLidResult(BaseModel):
27
28
  """Result data from closing a Thermocycler's lid."""
28
29
 
29
30
 
30
- class CloseLidImpl(
31
- AbstractCommandImpl[CloseLidParams, SuccessData[CloseLidResult, None]]
32
- ):
31
+ class CloseLidImpl(AbstractCommandImpl[CloseLidParams, SuccessData[CloseLidResult]]):
33
32
  """Execution implementation of a Thermocycler's close lid command."""
34
33
 
35
34
  def __init__(
@@ -43,10 +42,10 @@ class CloseLidImpl(
43
42
  self._equipment = equipment
44
43
  self._movement = movement
45
44
 
46
- async def execute(
47
- self, params: CloseLidParams
48
- ) -> SuccessData[CloseLidResult, None]:
45
+ async def execute(self, params: CloseLidParams) -> SuccessData[CloseLidResult]:
49
46
  """Close a Thermocycler's lid."""
47
+ state_update = update_types.StateUpdate()
48
+
50
49
  thermocycler_state = self._state_view.modules.get_thermocycler_module_substate(
51
50
  params.moduleId
52
51
  )
@@ -61,11 +60,12 @@ class CloseLidImpl(
61
60
  MotorAxis.Y,
62
61
  ] + self._state_view.motion.get_robot_mount_axes()
63
62
  await self._movement.home(axes=axes_to_home)
63
+ state_update.clear_all_pipette_locations()
64
64
 
65
65
  if thermocycler_hardware is not None:
66
66
  await thermocycler_hardware.close()
67
67
 
68
- return SuccessData(public=CloseLidResult(), private=None)
68
+ return SuccessData(public=CloseLidResult(), state_update=state_update)
69
69
 
70
70
 
71
71
  class CloseLid(BaseCommand[CloseLidParams, CloseLidResult, ErrorOccurrence]):
@@ -9,7 +9,7 @@ from ..command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, Succe
9
9
  from ...errors.error_occurrence import ErrorOccurrence
10
10
 
11
11
  if TYPE_CHECKING:
12
- from opentrons.protocol_engine.state import StateView
12
+ from opentrons.protocol_engine.state.state import StateView
13
13
  from opentrons.protocol_engine.execution import EquipmentHandler
14
14
 
15
15
 
@@ -27,7 +27,7 @@ class DeactivateBlockResult(BaseModel):
27
27
 
28
28
 
29
29
  class DeactivateBlockImpl(
30
- AbstractCommandImpl[DeactivateBlockParams, SuccessData[DeactivateBlockResult, None]]
30
+ AbstractCommandImpl[DeactivateBlockParams, SuccessData[DeactivateBlockResult]]
31
31
  ):
32
32
  """Execution implementation of a Thermocycler's deactivate block command."""
33
33
 
@@ -42,7 +42,7 @@ class DeactivateBlockImpl(
42
42
 
43
43
  async def execute(
44
44
  self, params: DeactivateBlockParams
45
- ) -> SuccessData[DeactivateBlockResult, None]:
45
+ ) -> SuccessData[DeactivateBlockResult]:
46
46
  """Unset a Thermocycler's target block temperature."""
47
47
  thermocycler_state = self._state_view.modules.get_thermocycler_module_substate(
48
48
  params.moduleId
@@ -54,7 +54,9 @@ class DeactivateBlockImpl(
54
54
  if thermocycler_hardware is not None:
55
55
  await thermocycler_hardware.deactivate_block()
56
56
 
57
- return SuccessData(public=DeactivateBlockResult(), private=None)
57
+ return SuccessData(
58
+ public=DeactivateBlockResult(),
59
+ )
58
60
 
59
61
 
60
62
  class DeactivateBlock(
@@ -9,7 +9,7 @@ from ..command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, Succe
9
9
  from ...errors.error_occurrence import ErrorOccurrence
10
10
 
11
11
  if TYPE_CHECKING:
12
- from opentrons.protocol_engine.state import StateView
12
+ from opentrons.protocol_engine.state.state import StateView
13
13
  from opentrons.protocol_engine.execution import EquipmentHandler
14
14
 
15
15
 
@@ -27,7 +27,7 @@ class DeactivateLidResult(BaseModel):
27
27
 
28
28
 
29
29
  class DeactivateLidImpl(
30
- AbstractCommandImpl[DeactivateLidParams, SuccessData[DeactivateLidResult, None]]
30
+ AbstractCommandImpl[DeactivateLidParams, SuccessData[DeactivateLidResult]]
31
31
  ):
32
32
  """Execution implementation of a Thermocycler's deactivate lid command."""
33
33
 
@@ -42,7 +42,7 @@ class DeactivateLidImpl(
42
42
 
43
43
  async def execute(
44
44
  self, params: DeactivateLidParams
45
- ) -> SuccessData[DeactivateLidResult, None]:
45
+ ) -> SuccessData[DeactivateLidResult]:
46
46
  """Unset a Thermocycler's target lid temperature."""
47
47
  thermocycler_state = self._state_view.modules.get_thermocycler_module_substate(
48
48
  params.moduleId
@@ -54,7 +54,9 @@ class DeactivateLidImpl(
54
54
  if thermocycler_hardware is not None:
55
55
  await thermocycler_hardware.deactivate_lid()
56
56
 
57
- return SuccessData(public=DeactivateLidResult(), private=None)
57
+ return SuccessData(
58
+ public=DeactivateLidResult(),
59
+ )
58
60
 
59
61
 
60
62
  class DeactivateLid(
@@ -6,11 +6,12 @@ from typing_extensions import Literal, Type
6
6
  from pydantic import BaseModel, Field
7
7
 
8
8
  from ..command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, SuccessData
9
+ from ...state import update_types
9
10
  from ...errors.error_occurrence import ErrorOccurrence
10
11
  from opentrons.protocol_engine.types import MotorAxis
11
12
 
12
13
  if TYPE_CHECKING:
13
- from opentrons.protocol_engine.state import StateView
14
+ from opentrons.protocol_engine.state.state import StateView
14
15
  from opentrons.protocol_engine.execution import EquipmentHandler, MovementHandler
15
16
 
16
17
 
@@ -27,7 +28,7 @@ class OpenLidResult(BaseModel):
27
28
  """Result data from opening a Thermocycler's lid."""
28
29
 
29
30
 
30
- class OpenLidImpl(AbstractCommandImpl[OpenLidParams, SuccessData[OpenLidResult, None]]):
31
+ class OpenLidImpl(AbstractCommandImpl[OpenLidParams, SuccessData[OpenLidResult]]):
31
32
  """Execution implementation of a Thermocycler's open lid command."""
32
33
 
33
34
  def __init__(
@@ -41,8 +42,10 @@ class OpenLidImpl(AbstractCommandImpl[OpenLidParams, SuccessData[OpenLidResult,
41
42
  self._equipment = equipment
42
43
  self._movement = movement
43
44
 
44
- async def execute(self, params: OpenLidParams) -> SuccessData[OpenLidResult, None]:
45
+ async def execute(self, params: OpenLidParams) -> SuccessData[OpenLidResult]:
45
46
  """Open a Thermocycler's lid."""
47
+ state_update = update_types.StateUpdate()
48
+
46
49
  thermocycler_state = self._state_view.modules.get_thermocycler_module_substate(
47
50
  params.moduleId
48
51
  )
@@ -57,11 +60,12 @@ class OpenLidImpl(AbstractCommandImpl[OpenLidParams, SuccessData[OpenLidResult,
57
60
  MotorAxis.Y,
58
61
  ] + self._state_view.motion.get_robot_mount_axes()
59
62
  await self._movement.home(axes=axes_to_home)
63
+ state_update.clear_all_pipette_locations()
60
64
 
61
65
  if thermocycler_hardware is not None:
62
66
  await thermocycler_hardware.open()
63
67
 
64
- return SuccessData(public=OpenLidResult(), private=None)
68
+ return SuccessData(public=OpenLidResult(), state_update=state_update)
65
69
 
66
70
 
67
71
  class OpenLid(BaseCommand[OpenLidParams, OpenLidResult, ErrorOccurrence]):
@@ -0,0 +1,165 @@
1
+ """Command models to execute a Thermocycler profile."""
2
+ from __future__ import annotations
3
+ from typing import List, Optional, TYPE_CHECKING, overload, Union
4
+ from typing_extensions import Literal, Type
5
+
6
+ from pydantic import BaseModel, Field
7
+
8
+ from opentrons.hardware_control.modules.types import ThermocyclerStep, ThermocyclerCycle
9
+
10
+ from ..command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, SuccessData
11
+ from ...errors.error_occurrence import ErrorOccurrence
12
+
13
+ if TYPE_CHECKING:
14
+ from opentrons.protocol_engine.state.state import StateView
15
+ from opentrons.protocol_engine.execution import EquipmentHandler
16
+ from opentrons.protocol_engine.state.module_substates.thermocycler_module_substate import (
17
+ ThermocyclerModuleSubState,
18
+ )
19
+
20
+
21
+ RunExtendedProfileCommandType = Literal["thermocycler/runExtendedProfile"]
22
+
23
+
24
+ class ProfileStep(BaseModel):
25
+ """An individual step in a Thermocycler extended profile."""
26
+
27
+ celsius: float = Field(..., description="Target temperature in °C.")
28
+ holdSeconds: float = Field(
29
+ ..., description="Time to hold target temperature in seconds."
30
+ )
31
+
32
+
33
+ class ProfileCycle(BaseModel):
34
+ """An individual cycle in a Thermocycler extended profile."""
35
+
36
+ steps: List[ProfileStep] = Field(..., description="Steps to repeat.")
37
+ repetitions: int = Field(..., description="Number of times to repeat the steps.")
38
+
39
+
40
+ class RunExtendedProfileParams(BaseModel):
41
+ """Input parameters for an individual Thermocycler profile step."""
42
+
43
+ moduleId: str = Field(..., description="Unique ID of the Thermocycler.")
44
+ profileElements: List[Union[ProfileStep, ProfileCycle]] = Field(
45
+ ...,
46
+ description="Elements of the profile. Each can be either a step or a cycle.",
47
+ )
48
+ blockMaxVolumeUl: Optional[float] = Field(
49
+ None,
50
+ description="Amount of liquid in uL of the most-full well"
51
+ " in labware loaded onto the thermocycler.",
52
+ )
53
+
54
+
55
+ class RunExtendedProfileResult(BaseModel):
56
+ """Result data from running a Thermocycler profile."""
57
+
58
+
59
+ def _transform_profile_step(
60
+ step: ProfileStep, thermocycler_state: ThermocyclerModuleSubState
61
+ ) -> ThermocyclerStep:
62
+ return ThermocyclerStep(
63
+ temperature=thermocycler_state.validate_target_block_temperature(step.celsius),
64
+ hold_time_seconds=step.holdSeconds,
65
+ )
66
+
67
+
68
+ @overload
69
+ def _transform_profile_element(
70
+ element: ProfileStep, thermocycler_state: ThermocyclerModuleSubState
71
+ ) -> ThermocyclerStep:
72
+ ...
73
+
74
+
75
+ @overload
76
+ def _transform_profile_element(
77
+ element: ProfileCycle, thermocycler_state: ThermocyclerModuleSubState
78
+ ) -> ThermocyclerCycle:
79
+ ...
80
+
81
+
82
+ def _transform_profile_element(
83
+ element: Union[ProfileStep, ProfileCycle],
84
+ thermocycler_state: ThermocyclerModuleSubState,
85
+ ) -> Union[ThermocyclerStep, ThermocyclerCycle]:
86
+ if isinstance(element, ProfileStep):
87
+ return _transform_profile_step(element, thermocycler_state)
88
+ else:
89
+ return ThermocyclerCycle(
90
+ steps=[
91
+ _transform_profile_step(step, thermocycler_state)
92
+ for step in element.steps
93
+ ],
94
+ repetitions=element.repetitions,
95
+ )
96
+
97
+
98
+ class RunExtendedProfileImpl(
99
+ AbstractCommandImpl[RunExtendedProfileParams, SuccessData[RunExtendedProfileResult]]
100
+ ):
101
+ """Execution implementation of a Thermocycler's run profile command."""
102
+
103
+ def __init__(
104
+ self,
105
+ state_view: StateView,
106
+ equipment: EquipmentHandler,
107
+ **unused_dependencies: object,
108
+ ) -> None:
109
+ self._state_view = state_view
110
+ self._equipment = equipment
111
+
112
+ async def execute(
113
+ self, params: RunExtendedProfileParams
114
+ ) -> SuccessData[RunExtendedProfileResult]:
115
+ """Run a Thermocycler profile."""
116
+ thermocycler_state = self._state_view.modules.get_thermocycler_module_substate(
117
+ params.moduleId
118
+ )
119
+ thermocycler_hardware = self._equipment.get_module_hardware_api(
120
+ thermocycler_state.module_id
121
+ )
122
+
123
+ profile = [
124
+ _transform_profile_element(element, thermocycler_state)
125
+ for element in params.profileElements
126
+ ]
127
+ target_volume: Optional[float]
128
+ if params.blockMaxVolumeUl is not None:
129
+ target_volume = thermocycler_state.validate_max_block_volume(
130
+ params.blockMaxVolumeUl
131
+ )
132
+ else:
133
+ target_volume = None
134
+
135
+ if thermocycler_hardware is not None:
136
+ # TODO(jbl 2022-06-27) hardcoded constant 1 for `repetitions` should be
137
+ # moved from HardwareControlAPI to the Python ProtocolContext
138
+ await thermocycler_hardware.execute_profile(
139
+ profile=profile, volume=target_volume
140
+ )
141
+
142
+ return SuccessData(
143
+ public=RunExtendedProfileResult(),
144
+ )
145
+
146
+
147
+ class RunExtendedProfile(
148
+ BaseCommand[RunExtendedProfileParams, RunExtendedProfileResult, ErrorOccurrence]
149
+ ):
150
+ """A command to execute a Thermocycler profile run."""
151
+
152
+ commandType: RunExtendedProfileCommandType = "thermocycler/runExtendedProfile"
153
+ params: RunExtendedProfileParams
154
+ result: Optional[RunExtendedProfileResult]
155
+
156
+ _ImplementationCls: Type[RunExtendedProfileImpl] = RunExtendedProfileImpl
157
+
158
+
159
+ class RunExtendedProfileCreate(BaseCommandCreate[RunExtendedProfileParams]):
160
+ """A request to execute a Thermocycler profile run."""
161
+
162
+ commandType: RunExtendedProfileCommandType = "thermocycler/runExtendedProfile"
163
+ params: RunExtendedProfileParams
164
+
165
+ _CommandCls: Type[RunExtendedProfile] = RunExtendedProfile
@@ -11,7 +11,7 @@ from ..command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, Succe
11
11
  from ...errors.error_occurrence import ErrorOccurrence
12
12
 
13
13
  if TYPE_CHECKING:
14
- from opentrons.protocol_engine.state import StateView
14
+ from opentrons.protocol_engine.state.state import StateView
15
15
  from opentrons.protocol_engine.execution import EquipmentHandler
16
16
 
17
17
 
@@ -47,7 +47,7 @@ class RunProfileResult(BaseModel):
47
47
 
48
48
 
49
49
  class RunProfileImpl(
50
- AbstractCommandImpl[RunProfileParams, SuccessData[RunProfileResult, None]]
50
+ AbstractCommandImpl[RunProfileParams, SuccessData[RunProfileResult]]
51
51
  ):
52
52
  """Execution implementation of a Thermocycler's run profile command."""
53
53
 
@@ -60,9 +60,7 @@ class RunProfileImpl(
60
60
  self._state_view = state_view
61
61
  self._equipment = equipment
62
62
 
63
- async def execute(
64
- self, params: RunProfileParams
65
- ) -> SuccessData[RunProfileResult, None]:
63
+ async def execute(self, params: RunProfileParams) -> SuccessData[RunProfileResult]:
66
64
  """Run a Thermocycler profile."""
67
65
  thermocycler_state = self._state_view.modules.get_thermocycler_module_substate(
68
66
  params.moduleId
@@ -96,7 +94,9 @@ class RunProfileImpl(
96
94
  steps=steps, repetitions=1, volume=target_volume
97
95
  )
98
96
 
99
- return SuccessData(public=RunProfileResult(), private=None)
97
+ return SuccessData(
98
+ public=RunProfileResult(),
99
+ )
100
100
 
101
101
 
102
102
  class RunProfile(BaseCommand[RunProfileParams, RunProfileResult, ErrorOccurrence]):
@@ -9,7 +9,7 @@ from ..command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, Succe
9
9
  from ...errors.error_occurrence import ErrorOccurrence
10
10
 
11
11
  if TYPE_CHECKING:
12
- from opentrons.protocol_engine.state import StateView
12
+ from opentrons.protocol_engine.state.state import StateView
13
13
  from opentrons.protocol_engine.execution import EquipmentHandler
14
14
 
15
15
 
@@ -46,7 +46,7 @@ class SetTargetBlockTemperatureResult(BaseModel):
46
46
  class SetTargetBlockTemperatureImpl(
47
47
  AbstractCommandImpl[
48
48
  SetTargetBlockTemperatureParams,
49
- SuccessData[SetTargetBlockTemperatureResult, None],
49
+ SuccessData[SetTargetBlockTemperatureResult],
50
50
  ]
51
51
  ):
52
52
  """Execution implementation of a Thermocycler's set block temperature command."""
@@ -63,7 +63,7 @@ class SetTargetBlockTemperatureImpl(
63
63
  async def execute(
64
64
  self,
65
65
  params: SetTargetBlockTemperatureParams,
66
- ) -> SuccessData[SetTargetBlockTemperatureResult, None]:
66
+ ) -> SuccessData[SetTargetBlockTemperatureResult]:
67
67
  """Set a Thermocycler's target block temperature."""
68
68
  thermocycler_state = self._state_view.modules.get_thermocycler_module_substate(
69
69
  params.moduleId
@@ -97,7 +97,6 @@ class SetTargetBlockTemperatureImpl(
97
97
  public=SetTargetBlockTemperatureResult(
98
98
  targetBlockTemperature=target_temperature
99
99
  ),
100
- private=None,
101
100
  )
102
101
 
103
102
 
@@ -9,7 +9,7 @@ from ..command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, Succe
9
9
  from ...errors.error_occurrence import ErrorOccurrence
10
10
 
11
11
  if TYPE_CHECKING:
12
- from opentrons.protocol_engine.state import StateView
12
+ from opentrons.protocol_engine.state.state import StateView
13
13
  from opentrons.protocol_engine.execution import EquipmentHandler
14
14
 
15
15
 
@@ -34,7 +34,7 @@ class SetTargetLidTemperatureResult(BaseModel):
34
34
 
35
35
  class SetTargetLidTemperatureImpl(
36
36
  AbstractCommandImpl[
37
- SetTargetLidTemperatureParams, SuccessData[SetTargetLidTemperatureResult, None]
37
+ SetTargetLidTemperatureParams, SuccessData[SetTargetLidTemperatureResult]
38
38
  ]
39
39
  ):
40
40
  """Execution implementation of a Thermocycler's set lid temperature command."""
@@ -51,7 +51,7 @@ class SetTargetLidTemperatureImpl(
51
51
  async def execute(
52
52
  self,
53
53
  params: SetTargetLidTemperatureParams,
54
- ) -> SuccessData[SetTargetLidTemperatureResult, None]:
54
+ ) -> SuccessData[SetTargetLidTemperatureResult]:
55
55
  """Set a Thermocycler's target lid temperature."""
56
56
  thermocycler_state = self._state_view.modules.get_thermocycler_module_substate(
57
57
  params.moduleId
@@ -70,7 +70,6 @@ class SetTargetLidTemperatureImpl(
70
70
  public=SetTargetLidTemperatureResult(
71
71
  targetLidTemperature=target_temperature
72
72
  ),
73
- private=None,
74
73
  )
75
74
 
76
75
 
@@ -9,7 +9,7 @@ from ..command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, Succe
9
9
  from ...errors.error_occurrence import ErrorOccurrence
10
10
 
11
11
  if TYPE_CHECKING:
12
- from opentrons.protocol_engine.state import StateView
12
+ from opentrons.protocol_engine.state.state import StateView
13
13
  from opentrons.protocol_engine.execution import EquipmentHandler
14
14
 
15
15
 
@@ -28,7 +28,7 @@ class WaitForBlockTemperatureResult(BaseModel):
28
28
 
29
29
  class WaitForBlockTemperatureImpl(
30
30
  AbstractCommandImpl[
31
- WaitForBlockTemperatureParams, SuccessData[WaitForBlockTemperatureResult, None]
31
+ WaitForBlockTemperatureParams, SuccessData[WaitForBlockTemperatureResult]
32
32
  ]
33
33
  ):
34
34
  """Execution implementation of Thermocycler's wait for block temperature command."""
@@ -45,7 +45,7 @@ class WaitForBlockTemperatureImpl(
45
45
  async def execute(
46
46
  self,
47
47
  params: WaitForBlockTemperatureParams,
48
- ) -> SuccessData[WaitForBlockTemperatureResult, None]:
48
+ ) -> SuccessData[WaitForBlockTemperatureResult]:
49
49
  """Wait for a Thermocycler's target block temperature."""
50
50
  thermocycler_state = self._state_view.modules.get_thermocycler_module_substate(
51
51
  params.moduleId
@@ -61,7 +61,9 @@ class WaitForBlockTemperatureImpl(
61
61
  if thermocycler_hardware is not None:
62
62
  await thermocycler_hardware.wait_for_block_target()
63
63
 
64
- return SuccessData(public=WaitForBlockTemperatureResult(), private=None)
64
+ return SuccessData(
65
+ public=WaitForBlockTemperatureResult(),
66
+ )
65
67
 
66
68
 
67
69
  class WaitForBlockTemperature(
@@ -9,7 +9,7 @@ from ..command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, Succe
9
9
  from ...errors.error_occurrence import ErrorOccurrence
10
10
 
11
11
  if TYPE_CHECKING:
12
- from opentrons.protocol_engine.state import StateView
12
+ from opentrons.protocol_engine.state.state import StateView
13
13
  from opentrons.protocol_engine.execution import EquipmentHandler
14
14
 
15
15
 
@@ -28,7 +28,7 @@ class WaitForLidTemperatureResult(BaseModel):
28
28
 
29
29
  class WaitForLidTemperatureImpl(
30
30
  AbstractCommandImpl[
31
- WaitForLidTemperatureParams, SuccessData[WaitForLidTemperatureResult, None]
31
+ WaitForLidTemperatureParams, SuccessData[WaitForLidTemperatureResult]
32
32
  ]
33
33
  ):
34
34
  """Execution implementation of Thermocycler's wait for lid temperature command."""
@@ -45,7 +45,7 @@ class WaitForLidTemperatureImpl(
45
45
  async def execute(
46
46
  self,
47
47
  params: WaitForLidTemperatureParams,
48
- ) -> SuccessData[WaitForLidTemperatureResult, None]:
48
+ ) -> SuccessData[WaitForLidTemperatureResult]:
49
49
  """Wait for a Thermocycler's lid temperature."""
50
50
  thermocycler_state = self._state_view.modules.get_thermocycler_module_substate(
51
51
  params.moduleId
@@ -61,7 +61,9 @@ class WaitForLidTemperatureImpl(
61
61
  if thermocycler_hardware is not None:
62
62
  await thermocycler_hardware.wait_for_lid_target()
63
63
 
64
- return SuccessData(public=WaitForLidTemperatureResult(), private=None)
64
+ return SuccessData(
65
+ public=WaitForLidTemperatureResult(),
66
+ )
65
67
 
66
68
 
67
69
  class WaitForLidTemperature(