opentrons 8.7.0a7__py3-none-any.whl → 8.7.0a9__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 (147) hide show
  1. opentrons/_version.py +2 -2
  2. opentrons/drivers/asyncio/communication/serial_connection.py +55 -129
  3. opentrons/drivers/flex_stacker/driver.py +6 -1
  4. opentrons/drivers/heater_shaker/abstract.py +0 -5
  5. opentrons/drivers/heater_shaker/driver.py +0 -10
  6. opentrons/drivers/heater_shaker/simulator.py +0 -4
  7. opentrons/drivers/thermocycler/abstract.py +0 -6
  8. opentrons/drivers/thermocycler/driver.py +10 -61
  9. opentrons/drivers/thermocycler/simulator.py +0 -6
  10. opentrons/hardware_control/api.py +5 -24
  11. opentrons/hardware_control/backends/controller.py +2 -8
  12. opentrons/hardware_control/backends/flex_protocol.py +1 -0
  13. opentrons/hardware_control/backends/ot3controller.py +3 -3
  14. opentrons/hardware_control/backends/ot3simulator.py +2 -2
  15. opentrons/hardware_control/backends/simulator.py +1 -2
  16. opentrons/hardware_control/backends/subsystem_manager.py +2 -5
  17. opentrons/hardware_control/emulation/abstract_emulator.py +4 -6
  18. opentrons/hardware_control/emulation/connection_handler.py +5 -8
  19. opentrons/hardware_control/emulation/heater_shaker.py +3 -12
  20. opentrons/hardware_control/emulation/settings.py +1 -1
  21. opentrons/hardware_control/emulation/thermocycler.py +15 -67
  22. opentrons/hardware_control/module_control.py +8 -82
  23. opentrons/hardware_control/modules/__init__.py +0 -3
  24. opentrons/hardware_control/modules/absorbance_reader.py +4 -11
  25. opentrons/hardware_control/modules/flex_stacker.py +9 -38
  26. opentrons/hardware_control/modules/heater_shaker.py +5 -42
  27. opentrons/hardware_control/modules/magdeck.py +4 -8
  28. opentrons/hardware_control/modules/mod_abc.py +5 -13
  29. opentrons/hardware_control/modules/tempdeck.py +5 -25
  30. opentrons/hardware_control/modules/thermocycler.py +11 -68
  31. opentrons/hardware_control/modules/types.py +1 -20
  32. opentrons/hardware_control/modules/utils.py +4 -11
  33. opentrons/hardware_control/nozzle_manager.py +0 -3
  34. opentrons/hardware_control/ot3api.py +7 -26
  35. opentrons/hardware_control/poller.py +8 -22
  36. opentrons/hardware_control/protocols/gripper_controller.py +1 -0
  37. opentrons/hardware_control/scripts/update_module_fw.py +0 -5
  38. opentrons/hardware_control/types.py +2 -31
  39. opentrons/legacy_commands/module_commands.py +0 -23
  40. opentrons/legacy_commands/protocol_commands.py +0 -20
  41. opentrons/legacy_commands/types.py +0 -80
  42. opentrons/motion_planning/deck_conflict.py +12 -17
  43. opentrons/motion_planning/waypoints.py +29 -15
  44. opentrons/protocol_api/__init__.py +1 -5
  45. opentrons/protocol_api/_types.py +1 -6
  46. opentrons/protocol_api/core/common.py +1 -3
  47. opentrons/protocol_api/core/engine/_default_labware_versions.py +11 -32
  48. opentrons/protocol_api/core/engine/labware.py +1 -8
  49. opentrons/protocol_api/core/engine/module_core.py +8 -75
  50. opentrons/protocol_api/core/engine/protocol.py +1 -18
  51. opentrons/protocol_api/core/engine/well.py +0 -8
  52. opentrons/protocol_api/core/legacy/legacy_module_core.py +4 -24
  53. opentrons/protocol_api/core/legacy/legacy_protocol_core.py +1 -11
  54. opentrons/protocol_api/core/legacy/legacy_well_core.py +0 -4
  55. opentrons/protocol_api/core/legacy_simulator/legacy_protocol_core.py +2 -14
  56. opentrons/protocol_api/core/module.py +4 -37
  57. opentrons/protocol_api/core/protocol.py +2 -11
  58. opentrons/protocol_api/core/well.py +0 -4
  59. opentrons/protocol_api/labware.py +0 -5
  60. opentrons/protocol_api/module_contexts.py +61 -122
  61. opentrons/protocol_api/protocol_context.py +4 -26
  62. opentrons/protocol_api/robot_context.py +21 -38
  63. opentrons/protocol_api/validation.py +1 -6
  64. opentrons/protocol_engine/actions/__init__.py +2 -4
  65. opentrons/protocol_engine/actions/actions.py +9 -22
  66. opentrons/protocol_engine/clients/sync_client.py +7 -42
  67. opentrons/protocol_engine/commands/__init__.py +0 -42
  68. opentrons/protocol_engine/commands/absorbance_reader/close_lid.py +15 -2
  69. opentrons/protocol_engine/commands/absorbance_reader/open_lid.py +15 -2
  70. opentrons/protocol_engine/commands/aspirate.py +0 -1
  71. opentrons/protocol_engine/commands/command.py +0 -1
  72. opentrons/protocol_engine/commands/command_unions.py +0 -49
  73. opentrons/protocol_engine/commands/dispense.py +0 -1
  74. opentrons/protocol_engine/commands/drop_tip.py +8 -32
  75. opentrons/protocol_engine/commands/heater_shaker/__init__.py +0 -14
  76. opentrons/protocol_engine/commands/heater_shaker/set_and_wait_for_shake_speed.py +4 -5
  77. opentrons/protocol_engine/commands/heater_shaker/set_target_temperature.py +5 -31
  78. opentrons/protocol_engine/commands/movement_common.py +0 -2
  79. opentrons/protocol_engine/commands/pick_up_tip.py +11 -21
  80. opentrons/protocol_engine/commands/temperature_module/set_target_temperature.py +7 -38
  81. opentrons/protocol_engine/commands/thermocycler/__init__.py +0 -16
  82. opentrons/protocol_engine/commands/thermocycler/run_extended_profile.py +0 -6
  83. opentrons/protocol_engine/commands/thermocycler/run_profile.py +0 -8
  84. opentrons/protocol_engine/commands/thermocycler/set_target_block_temperature.py +6 -40
  85. opentrons/protocol_engine/commands/thermocycler/set_target_lid_temperature.py +5 -29
  86. opentrons/protocol_engine/commands/touch_tip.py +1 -1
  87. opentrons/protocol_engine/commands/unsafe/unsafe_place_labware.py +22 -6
  88. opentrons/protocol_engine/errors/__init__.py +0 -4
  89. opentrons/protocol_engine/errors/exceptions.py +0 -55
  90. opentrons/protocol_engine/execution/__init__.py +0 -2
  91. opentrons/protocol_engine/execution/command_executor.py +0 -8
  92. opentrons/protocol_engine/execution/create_queue_worker.py +1 -5
  93. opentrons/protocol_engine/execution/labware_movement.py +21 -10
  94. opentrons/protocol_engine/execution/movement.py +0 -2
  95. opentrons/protocol_engine/execution/queue_worker.py +0 -4
  96. opentrons/protocol_engine/execution/run_control.py +0 -8
  97. opentrons/protocol_engine/protocol_engine.py +34 -75
  98. opentrons/protocol_engine/resources/__init__.py +0 -2
  99. opentrons/protocol_engine/resources/deck_configuration_provider.py +0 -7
  100. opentrons/protocol_engine/resources/labware_validation.py +6 -10
  101. opentrons/protocol_engine/state/_labware_origin_math.py +636 -0
  102. opentrons/protocol_engine/state/_well_math.py +18 -60
  103. opentrons/protocol_engine/state/addressable_areas.py +0 -2
  104. opentrons/protocol_engine/state/commands.py +11 -14
  105. opentrons/protocol_engine/state/geometry.py +374 -213
  106. opentrons/protocol_engine/state/labware.py +102 -52
  107. opentrons/protocol_engine/state/module_substates/thermocycler_module_substate.py +0 -37
  108. opentrons/protocol_engine/state/modules.py +8 -21
  109. opentrons/protocol_engine/state/motion.py +0 -44
  110. opentrons/protocol_engine/state/state.py +0 -14
  111. opentrons/protocol_engine/state/state_summary.py +0 -2
  112. opentrons/protocol_engine/state/tips.py +258 -177
  113. opentrons/protocol_engine/state/update_types.py +9 -16
  114. opentrons/protocol_engine/types/__init__.py +3 -9
  115. opentrons/protocol_engine/types/deck_configuration.py +1 -5
  116. opentrons/protocol_engine/types/instrument.py +1 -8
  117. opentrons/protocol_engine/types/labware.py +13 -1
  118. opentrons/protocol_engine/types/module.py +0 -10
  119. opentrons/protocol_engine/types/tip.py +0 -9
  120. opentrons/protocol_runner/create_simulating_orchestrator.py +2 -29
  121. opentrons/protocol_runner/run_orchestrator.py +2 -18
  122. opentrons/protocols/api_support/definitions.py +1 -1
  123. opentrons/protocols/api_support/types.py +1 -2
  124. opentrons/simulate.py +15 -48
  125. opentrons/system/camera.py +1 -1
  126. {opentrons-8.7.0a7.dist-info → opentrons-8.7.0a9.dist-info}/METADATA +4 -4
  127. {opentrons-8.7.0a7.dist-info → opentrons-8.7.0a9.dist-info}/RECORD +130 -146
  128. opentrons/protocol_api/core/engine/tasks.py +0 -48
  129. opentrons/protocol_api/core/legacy/tasks.py +0 -19
  130. opentrons/protocol_api/core/legacy_simulator/tasks.py +0 -19
  131. opentrons/protocol_api/core/tasks.py +0 -31
  132. opentrons/protocol_api/tasks.py +0 -48
  133. opentrons/protocol_engine/commands/create_timer.py +0 -83
  134. opentrons/protocol_engine/commands/heater_shaker/common.py +0 -20
  135. opentrons/protocol_engine/commands/heater_shaker/set_shake_speed.py +0 -136
  136. opentrons/protocol_engine/commands/set_tip_state.py +0 -97
  137. opentrons/protocol_engine/commands/thermocycler/start_run_extended_profile.py +0 -191
  138. opentrons/protocol_engine/commands/wait_for_tasks.py +0 -98
  139. opentrons/protocol_engine/execution/task_handler.py +0 -157
  140. opentrons/protocol_engine/resources/concurrency_provider.py +0 -27
  141. opentrons/protocol_engine/state/labware_origin_math/errors.py +0 -94
  142. opentrons/protocol_engine/state/labware_origin_math/stackup_origin_to_labware_origin.py +0 -1331
  143. opentrons/protocol_engine/state/tasks.py +0 -139
  144. opentrons/protocol_engine/types/tasks.py +0 -38
  145. {opentrons-8.7.0a7.dist-info → opentrons-8.7.0a9.dist-info}/WHEEL +0 -0
  146. {opentrons-8.7.0a7.dist-info → opentrons-8.7.0a9.dist-info}/entry_points.txt +0 -0
  147. {opentrons-8.7.0a7.dist-info → opentrons-8.7.0a9.dist-info}/licenses/LICENSE +0 -0
@@ -1,47 +1,31 @@
1
1
  """Command models to start heating a Heater-Shaker Module."""
2
2
  from __future__ import annotations
3
- from typing import Optional, TYPE_CHECKING, Any
3
+ from typing import Optional, TYPE_CHECKING
4
4
  from typing_extensions import Literal, Type
5
5
 
6
6
  from pydantic import BaseModel, Field
7
- from pydantic.json_schema import SkipJsonSchema
8
7
 
9
8
  from ..command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, SuccessData
10
9
  from ...errors.error_occurrence import ErrorOccurrence
11
10
 
12
11
  if TYPE_CHECKING:
13
12
  from opentrons.protocol_engine.state.state import StateView
14
- from opentrons.protocol_engine.execution import EquipmentHandler, TaskHandler
13
+ from opentrons.protocol_engine.execution import EquipmentHandler
15
14
 
16
15
 
17
16
  SetTargetTemperatureCommandType = Literal["heaterShaker/setTargetTemperature"]
18
17
 
19
18
 
20
- def _remove_default(s: dict[str, Any]) -> None:
21
- s.pop("default", None)
22
-
23
-
24
19
  class SetTargetTemperatureParams(BaseModel):
25
20
  """Input parameters to set a Heater-Shaker's target temperature."""
26
21
 
27
22
  moduleId: str = Field(..., description="Unique ID of the Heater-Shaker Module.")
28
23
  celsius: float = Field(..., description="Target temperature in °C.")
29
- taskId: str | SkipJsonSchema[None] = Field(
30
- None,
31
- description="Id for the background task that manages the temperature",
32
- json_schema_extra=_remove_default,
33
- )
34
24
 
35
25
 
36
26
  class SetTargetTemperatureResult(BaseModel):
37
27
  """Result data from setting a Heater-Shaker's target temperature."""
38
28
 
39
- taskId: str | SkipJsonSchema[None] = Field(
40
- None,
41
- description="The task id for the setTargetTemperature task",
42
- json_schema_extra=_remove_default,
43
- )
44
-
45
29
 
46
30
  class SetTargetTemperatureImpl(
47
31
  AbstractCommandImpl[
@@ -54,12 +38,10 @@ class SetTargetTemperatureImpl(
54
38
  self,
55
39
  state_view: StateView,
56
40
  equipment: EquipmentHandler,
57
- task_handler: TaskHandler,
58
41
  **unused_dependencies: object,
59
42
  ) -> None:
60
43
  self._state_view = state_view
61
44
  self._equipment = equipment
62
- self._task_handler = task_handler
63
45
 
64
46
  async def execute(
65
47
  self,
@@ -79,19 +61,11 @@ class SetTargetTemperatureImpl(
79
61
  hs_module_substate.module_id
80
62
  )
81
63
 
82
- async def start_set_temperature(task_handler: TaskHandler) -> None:
83
- if hs_hardware_module is not None:
84
- async with task_handler.synchronize_cancel_previous(
85
- hs_module_substate.module_id
86
- ):
87
- await hs_hardware_module.start_set_temperature(validated_temp)
88
- await hs_hardware_module.await_temperature(validated_temp)
64
+ if hs_hardware_module is not None:
65
+ await hs_hardware_module.start_set_temperature(validated_temp)
89
66
 
90
- task = await self._task_handler.create_task(
91
- task_function=start_set_temperature, id=params.taskId
92
- )
93
67
  return SuccessData(
94
- public=SetTargetTemperatureResult(taskId=task.id),
68
+ public=SetTargetTemperatureResult(),
95
69
  )
96
70
 
97
71
 
@@ -152,7 +152,6 @@ async def move_to_well(
152
152
  minimum_z_height: Optional[float] = None,
153
153
  speed: Optional[float] = None,
154
154
  operation_volume: Optional[float] = None,
155
- offset_pipette_for_reservoir_subwells: bool = False,
156
155
  ) -> MoveToWellOperationReturn:
157
156
  """Execute a move to well microoperation."""
158
157
  try:
@@ -166,7 +165,6 @@ async def move_to_well(
166
165
  minimum_z_height=minimum_z_height,
167
166
  speed=speed,
168
167
  operation_volume=operation_volume,
169
- offset_pipette_for_reservoir_subwells=offset_pipette_for_reservoir_subwells,
170
168
  )
171
169
  except StallOrCollisionDetectedError as e:
172
170
  return DefinedErrorData(
@@ -10,7 +10,7 @@ from typing_extensions import Literal
10
10
  from ..errors import ErrorOccurrence, PickUpTipTipNotAttachedError
11
11
  from ..resources import ModelUtils
12
12
  from ..state import update_types
13
- from ..types import PickUpTipWellLocation, LabwareWellId, TipRackWellState
13
+ from ..types import PickUpTipWellLocation, LabwareWellId
14
14
  from .pipetting_common import (
15
15
  PipetteIdMixin,
16
16
  )
@@ -121,14 +121,10 @@ class PickUpTipImplementation(AbstractCommandImpl[PickUpTipParams, _ExecuteRetur
121
121
  labware_id = params.labwareId
122
122
  well_name = params.wellName
123
123
 
124
- tips_to_mark_as_empty = (
125
- self._state_view.tips.compute_tips_to_mark_as_used_or_empty(
126
- labware_id=labware_id,
127
- well_name=well_name,
128
- nozzle_map=self._state_view.pipettes.get_nozzle_configuration(
129
- pipette_id
130
- ),
131
- )
124
+ tips_to_mark_as_used = self._state_view.tips.compute_tips_to_mark_as_used(
125
+ labware_id=labware_id,
126
+ well_name=well_name,
127
+ nozzle_map=self._state_view.pipettes.get_nozzle_configuration(pipette_id),
132
128
  )
133
129
 
134
130
  well_location = self._state_view.geometry.convert_pick_up_tip_well_location(
@@ -164,20 +160,16 @@ class PickUpTipImplementation(AbstractCommandImpl[PickUpTipParams, _ExecuteRetur
164
160
  ),
165
161
  )
166
162
  .set_fluid_empty(pipette_id=pipette_id, clean_tip=True)
167
- .update_tip_rack_well_state(
168
- tip_state=TipRackWellState.EMPTY,
169
- labware_id=labware_id,
170
- well_names=tips_to_mark_as_empty,
163
+ .mark_tips_as_used(
164
+ labware_id=labware_id, well_names=tips_to_mark_as_used
171
165
  )
172
166
  )
173
167
  state_update = (
174
168
  update_types.StateUpdate.reduce(
175
169
  update_types.StateUpdate(), move_result.state_update
176
170
  )
177
- .update_tip_rack_well_state(
178
- tip_state=TipRackWellState.EMPTY,
179
- labware_id=labware_id,
180
- well_names=tips_to_mark_as_empty,
171
+ .mark_tips_as_used(
172
+ labware_id=labware_id, well_names=tips_to_mark_as_used
181
173
  )
182
174
  .set_fluid_unknown(pipette_id=pipette_id)
183
175
  )
@@ -205,10 +197,8 @@ class PickUpTipImplementation(AbstractCommandImpl[PickUpTipParams, _ExecuteRetur
205
197
  labware_id=labware_id, well_name=well_name
206
198
  ),
207
199
  )
208
- .update_tip_rack_well_state(
209
- tip_state=TipRackWellState.EMPTY,
210
- labware_id=labware_id,
211
- well_names=tips_to_mark_as_empty,
200
+ .mark_tips_as_used(
201
+ labware_id=labware_id, well_names=tips_to_mark_as_used
212
202
  )
213
203
  .set_fluid_empty(pipette_id=pipette_id, clean_tip=True)
214
204
  .set_pipette_ready_to_aspirate(
@@ -1,35 +1,25 @@
1
1
  """Command models to start heating a Temperature Module."""
2
2
  from __future__ import annotations
3
- from typing import Optional, TYPE_CHECKING, Any
3
+ from typing import Optional, TYPE_CHECKING
4
4
  from typing_extensions import Literal, Type
5
5
 
6
6
  from pydantic import BaseModel, Field
7
- from pydantic.json_schema import SkipJsonSchema
8
7
 
9
8
  from ..command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, SuccessData
10
9
  from ...errors.error_occurrence import ErrorOccurrence
11
10
 
12
11
  if TYPE_CHECKING:
13
12
  from opentrons.protocol_engine.state.state import StateView
14
- from opentrons.protocol_engine.execution import EquipmentHandler, TaskHandler
13
+ from opentrons.protocol_engine.execution import EquipmentHandler
15
14
 
16
15
  SetTargetTemperatureCommandType = Literal["temperatureModule/setTargetTemperature"]
17
16
 
18
17
 
19
- def _remove_default(s: dict[str, Any]) -> None:
20
- s.pop("default", None)
21
-
22
-
23
18
  class SetTargetTemperatureParams(BaseModel):
24
19
  """Input parameters to set a Temperature Module's target temperature."""
25
20
 
26
21
  moduleId: str = Field(..., description="Unique ID of the Temperature Module.")
27
22
  celsius: float = Field(..., description="Target temperature in °C.")
28
- taskId: str | SkipJsonSchema[None] = Field(
29
- None,
30
- description="Id for the background task that manages the temperature",
31
- json_schema_extra=_remove_default,
32
- )
33
23
 
34
24
 
35
25
  class SetTargetTemperatureResult(BaseModel):
@@ -40,11 +30,6 @@ class SetTargetTemperatureResult(BaseModel):
40
30
  description="The target temperature that was set after validation "
41
31
  "and type conversion (if any).",
42
32
  )
43
- taskId: str | SkipJsonSchema[None] = Field(
44
- None,
45
- description="The task id for the setTargetTemperature task",
46
- json_schema_extra=_remove_default,
47
- )
48
33
 
49
34
 
50
35
  class SetTargetTemperatureImpl(
@@ -58,12 +43,10 @@ class SetTargetTemperatureImpl(
58
43
  self,
59
44
  state_view: StateView,
60
45
  equipment: EquipmentHandler,
61
- task_handler: TaskHandler,
62
46
  **unused_dependencies: object,
63
47
  ) -> None:
64
48
  self._state_view = state_view
65
49
  self._equipment = equipment
66
- self._task_handler = task_handler
67
50
 
68
51
  async def execute(
69
52
  self, params: SetTargetTemperatureParams
@@ -73,33 +56,19 @@ class SetTargetTemperatureImpl(
73
56
  module_substate = self._state_view.modules.get_temperature_module_substate(
74
57
  module_id=params.moduleId
75
58
  )
59
+
76
60
  # Verify temperature from temperature module view
77
61
  validated_temp = module_substate.validate_target_temperature(params.celsius)
62
+
78
63
  # Allow propagation of ModuleNotAttachedError.
79
64
  temp_hardware_module = self._equipment.get_module_hardware_api(
80
65
  module_substate.module_id
81
66
  )
82
67
 
83
- async def start_set_temperature(task_handler: TaskHandler) -> None:
84
- if temp_hardware_module is not None:
85
- async with task_handler.synchronize_cancel_previous(
86
- module_substate.module_id
87
- ):
88
- await temp_hardware_module.start_set_temperature(
89
- celsius=validated_temp
90
- )
91
- await temp_hardware_module.await_temperature(
92
- awaiting_temperature=validated_temp
93
- )
94
-
95
- task = await self._task_handler.create_task(
96
- task_function=start_set_temperature, id=params.taskId
97
- )
98
-
68
+ if temp_hardware_module is not None:
69
+ await temp_hardware_module.start_set_temperature(celsius=validated_temp)
99
70
  return SuccessData(
100
- public=SetTargetTemperatureResult(
101
- targetTemperature=validated_temp, taskId=task.id
102
- ),
71
+ public=SetTargetTemperatureResult(targetTemperature=validated_temp),
103
72
  )
104
73
 
105
74
 
@@ -73,15 +73,6 @@ from .run_profile import (
73
73
  RunProfileCreate,
74
74
  )
75
75
 
76
- from .start_run_extended_profile import (
77
- StartRunExtendedProfileCommandType,
78
- StartRunExtendedProfileParams,
79
- StartRunExtendedProfileStepParams,
80
- StartRunExtendedProfileResult,
81
- StartRunExtendedProfile,
82
- StartRunExtendedProfileCreate,
83
- )
84
-
85
76
  from .run_extended_profile import (
86
77
  RunExtendedProfileCommandType,
87
78
  RunExtendedProfileParams,
@@ -149,13 +140,6 @@ __all__ = [
149
140
  "RunProfileResult",
150
141
  "RunProfile",
151
142
  "RunProfileCreate",
152
- # Start run profile command models,
153
- "StartRunExtendedProfileCommandType",
154
- "StartRunExtendedProfileParams",
155
- "StartRunExtendedProfileStepParams",
156
- "StartRunExtendedProfileResult",
157
- "StartRunExtendedProfile",
158
- "StartRunExtendedProfileCreate",
159
143
  # Run extended profile command models.
160
144
  "RunExtendedProfileCommandType",
161
145
  "RunExtendedProfileParams",
@@ -33,11 +33,6 @@ class ProfileStep(BaseModel):
33
33
  holdSeconds: float = Field(
34
34
  ..., description="Time to hold target temperature in seconds."
35
35
  )
36
- rampRate: float | SkipJsonSchema[None] = Field(
37
- None,
38
- description="How quickly to change temperature in °C/second.",
39
- json_schema_extra=_remove_default,
40
- )
41
36
 
42
37
 
43
38
  class ProfileCycle(BaseModel):
@@ -73,7 +68,6 @@ def _transform_profile_step(
73
68
  return ThermocyclerStep(
74
69
  temperature=thermocycler_state.validate_target_block_temperature(step.celsius),
75
70
  hold_time_seconds=step.holdSeconds,
76
- ramp_rate=thermocycler_state.validate_ramp_rate(step.rampRate, step.celsius),
77
71
  )
78
72
 
79
73
 
@@ -30,11 +30,6 @@ class RunProfileStepParams(BaseModel):
30
30
  holdSeconds: float = Field(
31
31
  ..., description="Time to hold target temperature at in seconds."
32
32
  )
33
- rampRate: float | SkipJsonSchema[None] = Field(
34
- None,
35
- description="How quickly to change temperature in °C/second.",
36
- json_schema_extra=_remove_default,
37
- )
38
33
 
39
34
 
40
35
  class RunProfileParams(BaseModel):
@@ -86,9 +81,6 @@ class RunProfileImpl(
86
81
  profile_step.celsius
87
82
  ),
88
83
  hold_time_seconds=profile_step.holdSeconds,
89
- ramp_rate=thermocycler_state.validate_ramp_rate(
90
- profile_step.rampRate, profile_step.celsius
91
- ),
92
84
  )
93
85
  for profile_step in params.profile
94
86
  ]
@@ -11,7 +11,7 @@ from ...errors.error_occurrence import ErrorOccurrence
11
11
 
12
12
  if TYPE_CHECKING:
13
13
  from opentrons.protocol_engine.state.state import StateView
14
- from opentrons.protocol_engine.execution import EquipmentHandler, TaskHandler
14
+ from opentrons.protocol_engine.execution import EquipmentHandler
15
15
 
16
16
 
17
17
  SetTargetBlockTemperatureCommandType = Literal["thermocycler/setTargetBlockTemperature"]
@@ -39,17 +39,6 @@ class SetTargetBlockTemperatureParams(BaseModel):
39
39
  " the given hold time has elapsed.",
40
40
  json_schema_extra=_remove_default,
41
41
  )
42
- ramp_rate: float | SkipJsonSchema[None] = Field(
43
- None,
44
- description="The rate in C°/second to change temperature from the current target."
45
- " If unspecified, the Thermocycler will change temperature at the fastest possible rate.",
46
- json_schema_extra=_remove_default,
47
- )
48
- taskId: str | SkipJsonSchema[None] = Field(
49
- None,
50
- description="Id for the background task that manages the temperature.",
51
- json_schema_extra=_remove_default,
52
- )
53
42
 
54
43
 
55
44
  class SetTargetBlockTemperatureResult(BaseModel):
@@ -59,11 +48,6 @@ class SetTargetBlockTemperatureResult(BaseModel):
59
48
  ...,
60
49
  description="The target block temperature that was set after validation.",
61
50
  )
62
- taskId: str | SkipJsonSchema[None] = Field(
63
- None,
64
- description="The task id for the setTargetBlockTemperature",
65
- json_schema_extra=_remove_default,
66
- )
67
51
 
68
52
 
69
53
  class SetTargetBlockTemperatureImpl(
@@ -78,12 +62,10 @@ class SetTargetBlockTemperatureImpl(
78
62
  self,
79
63
  state_view: StateView,
80
64
  equipment: EquipmentHandler,
81
- task_handler: TaskHandler,
82
65
  **unused_dependencies: object,
83
66
  ) -> None:
84
67
  self._state_view = state_view
85
68
  self._equipment = equipment
86
- self._task_handler = task_handler
87
69
 
88
70
  async def execute(
89
71
  self,
@@ -108,35 +90,19 @@ class SetTargetBlockTemperatureImpl(
108
90
  hold_time = thermocycler_state.validate_hold_time(params.holdTimeSeconds)
109
91
  else:
110
92
  hold_time = None
111
- target_ramp_rate: Optional[float]
112
- if params.ramp_rate is not None:
113
- target_ramp_rate = thermocycler_state.validate_ramp_rate(
114
- params.ramp_rate, target_temperature
115
- )
116
- else:
117
- target_ramp_rate = None
118
93
 
119
94
  thermocycler_hardware = self._equipment.get_module_hardware_api(
120
95
  thermocycler_state.module_id
121
96
  )
122
97
 
123
- async def set_target_block_temperature(task_handler: TaskHandler) -> None:
124
- if thermocycler_hardware is not None:
125
- await thermocycler_hardware.set_target_block_temperature(
126
- target_temperature,
127
- volume=target_volume,
128
- hold_time_seconds=hold_time,
129
- ramp_rate=target_ramp_rate,
130
- )
131
- await thermocycler_hardware.wait_for_block_target()
132
-
133
- task = await self._task_handler.create_task(
134
- task_function=set_target_block_temperature, id=params.taskId
135
- )
98
+ if thermocycler_hardware is not None:
99
+ await thermocycler_hardware.set_target_block_temperature(
100
+ target_temperature, volume=target_volume, hold_time_seconds=hold_time
101
+ )
136
102
 
137
103
  return SuccessData(
138
104
  public=SetTargetBlockTemperatureResult(
139
- targetBlockTemperature=target_temperature, taskId=task.id
105
+ targetBlockTemperature=target_temperature
140
106
  ),
141
107
  )
142
108
 
@@ -1,36 +1,26 @@
1
1
  """Command models to start heating a Thermocycler's lid."""
2
2
  from __future__ import annotations
3
- from typing import Optional, TYPE_CHECKING, Any
3
+ from typing import Optional, TYPE_CHECKING
4
4
  from typing_extensions import Literal, Type
5
5
 
6
6
  from pydantic import BaseModel, Field
7
- from pydantic.json_schema import SkipJsonSchema
8
7
 
9
8
  from ..command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, SuccessData
10
9
  from ...errors.error_occurrence import ErrorOccurrence
11
10
 
12
11
  if TYPE_CHECKING:
13
12
  from opentrons.protocol_engine.state.state import StateView
14
- from opentrons.protocol_engine.execution import EquipmentHandler, TaskHandler
13
+ from opentrons.protocol_engine.execution import EquipmentHandler
15
14
 
16
15
 
17
16
  SetTargetLidTemperatureCommandType = Literal["thermocycler/setTargetLidTemperature"]
18
17
 
19
18
 
20
- def _remove_default(s: dict[str, Any]) -> None:
21
- s.pop("default", None)
22
-
23
-
24
19
  class SetTargetLidTemperatureParams(BaseModel):
25
20
  """Input parameters to set a Thermocycler's target lid temperature."""
26
21
 
27
22
  moduleId: str = Field(..., description="Unique ID of the Thermocycler Module.")
28
23
  celsius: float = Field(..., description="Target temperature in °C.")
29
- taskId: str | SkipJsonSchema[None] = Field(
30
- None,
31
- description="Id for the background task that manages the temperature.",
32
- json_schema_extra=_remove_default,
33
- )
34
24
 
35
25
 
36
26
  class SetTargetLidTemperatureResult(BaseModel):
@@ -40,11 +30,6 @@ class SetTargetLidTemperatureResult(BaseModel):
40
30
  ...,
41
31
  description="The target lid temperature that was set after validation.",
42
32
  )
43
- taskId: str | SkipJsonSchema[None] = Field(
44
- None,
45
- description="The task id for the setTargetBlockTemperature",
46
- json_schema_extra=_remove_default,
47
- )
48
33
 
49
34
 
50
35
  class SetTargetLidTemperatureImpl(
@@ -58,12 +43,10 @@ class SetTargetLidTemperatureImpl(
58
43
  self,
59
44
  state_view: StateView,
60
45
  equipment: EquipmentHandler,
61
- task_handler: TaskHandler,
62
46
  **unused_dependencies: object,
63
47
  ) -> None:
64
48
  self._state_view = state_view
65
49
  self._equipment = equipment
66
- self._task_handler = task_handler
67
50
 
68
51
  async def execute(
69
52
  self,
@@ -80,19 +63,12 @@ class SetTargetLidTemperatureImpl(
80
63
  thermocycler_state.module_id
81
64
  )
82
65
 
83
- async def set_target_lid_temperature(task_handler: TaskHandler) -> None:
84
- if thermocycler_hardware is not None:
85
- await thermocycler_hardware.set_target_lid_temperature(
86
- target_temperature
87
- )
88
- await thermocycler_hardware.wait_for_lid_target()
66
+ if thermocycler_hardware is not None:
67
+ await thermocycler_hardware.set_target_lid_temperature(target_temperature)
89
68
 
90
- task = await self._task_handler.create_task(
91
- task_function=set_target_lid_temperature, id=params.taskId
92
- )
93
69
  return SuccessData(
94
70
  public=SetTargetLidTemperatureResult(
95
- targetLidTemperature=target_temperature, taskId=task.id
71
+ targetLidTemperature=target_temperature
96
72
  ),
97
73
  )
98
74
 
@@ -114,7 +114,7 @@ class TouchTipImplementation(
114
114
 
115
115
  if self._state_view.labware.get_has_quirk(labware_id, "touchTipDisabled"):
116
116
  raise TouchTipDisabledError(
117
- f"Touch tip not allowed on labware {self._state_view.labware.get_display_name(labware_id)}"
117
+ f"Touch tip not allowed on labware {labware_id}"
118
118
  )
119
119
 
120
120
  if self._state_view.labware.is_tiprack(labware_id):
@@ -14,11 +14,12 @@ from opentrons.protocol_engine.errors.exceptions import (
14
14
  CannotPerformGripperAction,
15
15
  GripperNotAttachedError,
16
16
  )
17
+ from opentrons.types import Point
18
+
17
19
  from ...types import (
18
20
  DeckSlotLocation,
19
21
  ModuleModel,
20
22
  OnDeckLabwareLocation,
21
- GripperMoveType,
22
23
  )
23
24
  from ..command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, SuccessData
24
25
  from ...errors.error_occurrence import ErrorOccurrence
@@ -99,6 +100,22 @@ class UnsafePlaceLabwareImplementation(
99
100
  LabwareUri(params.labwareURI)
100
101
  )
101
102
 
103
+ # todo(mm, 2024-11-06): This is only correct in the special case of an
104
+ # absorbance reader lid. Its definition currently puts the offsets for *itself*
105
+ # in the property that's normally meant for offsets for its *children.*
106
+ final_offsets = self._state_view.labware.get_child_gripper_offsets(
107
+ labware_definition=definition, slot_name=None
108
+ )
109
+ drop_offset = (
110
+ Point(
111
+ final_offsets.dropOffset.x,
112
+ final_offsets.dropOffset.y,
113
+ final_offsets.dropOffset.z,
114
+ )
115
+ if final_offsets
116
+ else None
117
+ )
118
+
102
119
  if isinstance(params.location, DeckSlotLocation):
103
120
  self._state_view.addressable_areas.raise_if_area_not_in_deck_configuration(
104
121
  params.location.slotName.id
@@ -122,7 +139,7 @@ class UnsafePlaceLabwareImplementation(
122
139
  await ot3api.update_axis_position_estimations([Axis.X, Axis.Y])
123
140
 
124
141
  # Place the labware down
125
- await self._start_movement(ot3api, definition, location)
142
+ await self._start_movement(ot3api, definition, location, drop_offset)
126
143
 
127
144
  return SuccessData(public=UnsafePlaceLabwareResult())
128
145
 
@@ -131,6 +148,7 @@ class UnsafePlaceLabwareImplementation(
131
148
  ot3api: OT3HardwareControlAPI,
132
149
  labware_definition: LabwareDefinition,
133
150
  location: OnDeckLabwareLocation,
151
+ drop_offset: Optional[Point],
134
152
  ) -> None:
135
153
  gripper_homed_position = await ot3api.gantry_position(
136
154
  mount=OT3Mount.GRIPPER,
@@ -138,15 +156,13 @@ class UnsafePlaceLabwareImplementation(
138
156
  )
139
157
 
140
158
  to_labware_center = self._state_view.geometry.get_labware_grip_point(
141
- labware_definition=labware_definition,
142
- location=location,
143
- move_type=GripperMoveType.DROP_LABWARE,
144
- user_additional_offset=None,
159
+ labware_definition=labware_definition, location=location
145
160
  )
146
161
 
147
162
  movement_waypoints = get_gripper_labware_placement_waypoints(
148
163
  to_labware_center=to_labware_center,
149
164
  gripper_home_z=gripper_homed_position.z,
165
+ drop_offset=drop_offset,
150
166
  )
151
167
 
152
168
  # start movement
@@ -57,7 +57,6 @@ from .exceptions import (
57
57
  InvalidTargetSpeedError,
58
58
  InvalidTargetTemperatureError,
59
59
  InvalidBlockVolumeError,
60
- InvalidRampRateError,
61
60
  InvalidHoldTimeError,
62
61
  InvalidWavelengthError,
63
62
  CannotPerformModuleAction,
@@ -91,7 +90,6 @@ from .exceptions import (
91
90
  FlexStackerLabwarePoolNotYetDefinedError,
92
91
  FlexStackerNotLogicallyEmptyError,
93
92
  InvalidLabwarePositionError,
94
- InvalidModuleOrientation,
95
93
  )
96
94
 
97
95
  from .error_occurrence import ErrorOccurrence, ProtocolCommandFailedError
@@ -153,7 +151,6 @@ __all__ = [
153
151
  "NoTargetTemperatureSetError",
154
152
  "InvalidTargetTemperatureError",
155
153
  "InvalidTargetSpeedError",
156
- "InvalidRampRateError",
157
154
  "InvalidBlockVolumeError",
158
155
  "InvalidHoldTimeError",
159
156
  "InvalidLiquidError",
@@ -177,7 +174,6 @@ __all__ = [
177
174
  "FlexStackerLabwarePoolNotYetDefinedError",
178
175
  "FlexStackerNotLogicallyEmptyError",
179
176
  "InvalidLabwarePositionError",
180
- "InvalidModuleOrientation",
181
177
  # error occurrence models
182
178
  "ErrorOccurrence",
183
179
  "CommandNotAllowedError",