opentrons 8.7.0a2__py3-none-any.whl → 8.7.0a4__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 (119) hide show
  1. opentrons/_version.py +2 -2
  2. opentrons/drivers/thermocycler/abstract.py +0 -1
  3. opentrons/drivers/thermocycler/driver.py +4 -33
  4. opentrons/drivers/thermocycler/simulator.py +0 -2
  5. opentrons/hardware_control/api.py +5 -24
  6. opentrons/hardware_control/backends/controller.py +2 -8
  7. opentrons/hardware_control/backends/ot3controller.py +0 -3
  8. opentrons/hardware_control/backends/ot3simulator.py +1 -2
  9. opentrons/hardware_control/backends/simulator.py +1 -2
  10. opentrons/hardware_control/backends/subsystem_manager.py +2 -5
  11. opentrons/hardware_control/module_control.py +8 -82
  12. opentrons/hardware_control/modules/__init__.py +0 -3
  13. opentrons/hardware_control/modules/absorbance_reader.py +4 -11
  14. opentrons/hardware_control/modules/flex_stacker.py +9 -38
  15. opentrons/hardware_control/modules/heater_shaker.py +5 -30
  16. opentrons/hardware_control/modules/magdeck.py +4 -8
  17. opentrons/hardware_control/modules/mod_abc.py +5 -13
  18. opentrons/hardware_control/modules/tempdeck.py +5 -25
  19. opentrons/hardware_control/modules/thermocycler.py +10 -56
  20. opentrons/hardware_control/modules/types.py +1 -20
  21. opentrons/hardware_control/modules/utils.py +4 -11
  22. opentrons/hardware_control/nozzle_manager.py +0 -3
  23. opentrons/hardware_control/ot3api.py +5 -26
  24. opentrons/hardware_control/scripts/update_module_fw.py +0 -5
  25. opentrons/hardware_control/types.py +2 -31
  26. opentrons/legacy_commands/protocol_commands.py +0 -20
  27. opentrons/legacy_commands/types.py +0 -42
  28. opentrons/motion_planning/waypoints.py +29 -15
  29. opentrons/protocol_api/__init__.py +0 -5
  30. opentrons/protocol_api/_types.py +1 -6
  31. opentrons/protocol_api/core/common.py +1 -3
  32. opentrons/protocol_api/core/engine/_default_labware_versions.py +11 -32
  33. opentrons/protocol_api/core/engine/labware.py +1 -8
  34. opentrons/protocol_api/core/engine/module_core.py +0 -4
  35. opentrons/protocol_api/core/engine/protocol.py +43 -23
  36. opentrons/protocol_api/core/legacy/legacy_module_core.py +0 -2
  37. opentrons/protocol_api/core/legacy/legacy_protocol_core.py +1 -11
  38. opentrons/protocol_api/core/legacy_simulator/legacy_protocol_core.py +2 -14
  39. opentrons/protocol_api/core/module.py +0 -1
  40. opentrons/protocol_api/core/protocol.py +2 -11
  41. opentrons/protocol_api/module_contexts.py +0 -1
  42. opentrons/protocol_api/protocol_context.py +4 -26
  43. opentrons/protocol_api/robot_context.py +21 -38
  44. opentrons/protocol_api/validation.py +1 -6
  45. opentrons/protocol_engine/actions/__init__.py +2 -4
  46. opentrons/protocol_engine/actions/actions.py +9 -22
  47. opentrons/protocol_engine/clients/sync_client.py +7 -6
  48. opentrons/protocol_engine/commands/__init__.py +0 -42
  49. opentrons/protocol_engine/commands/absorbance_reader/close_lid.py +15 -2
  50. opentrons/protocol_engine/commands/absorbance_reader/open_lid.py +15 -2
  51. opentrons/protocol_engine/commands/aspirate.py +0 -1
  52. opentrons/protocol_engine/commands/command.py +0 -1
  53. opentrons/protocol_engine/commands/command_unions.py +0 -39
  54. opentrons/protocol_engine/commands/dispense.py +0 -1
  55. opentrons/protocol_engine/commands/drop_tip.py +8 -32
  56. opentrons/protocol_engine/commands/movement_common.py +0 -2
  57. opentrons/protocol_engine/commands/pick_up_tip.py +11 -21
  58. opentrons/protocol_engine/commands/thermocycler/run_extended_profile.py +0 -6
  59. opentrons/protocol_engine/commands/thermocycler/run_profile.py +0 -8
  60. opentrons/protocol_engine/commands/thermocycler/set_target_block_temperature.py +1 -17
  61. opentrons/protocol_engine/commands/touch_tip.py +1 -1
  62. opentrons/protocol_engine/commands/unsafe/unsafe_place_labware.py +22 -6
  63. opentrons/protocol_engine/errors/__init__.py +0 -4
  64. opentrons/protocol_engine/errors/exceptions.py +0 -55
  65. opentrons/protocol_engine/execution/__init__.py +0 -2
  66. opentrons/protocol_engine/execution/command_executor.py +0 -8
  67. opentrons/protocol_engine/execution/create_queue_worker.py +1 -5
  68. opentrons/protocol_engine/execution/labware_movement.py +12 -9
  69. opentrons/protocol_engine/execution/movement.py +0 -2
  70. opentrons/protocol_engine/execution/queue_worker.py +0 -4
  71. opentrons/protocol_engine/execution/run_control.py +0 -8
  72. opentrons/protocol_engine/protocol_engine.py +33 -67
  73. opentrons/protocol_engine/resources/__init__.py +0 -2
  74. opentrons/protocol_engine/resources/deck_configuration_provider.py +0 -7
  75. opentrons/protocol_engine/resources/labware_validation.py +6 -10
  76. opentrons/protocol_engine/state/_labware_origin_math.py +636 -0
  77. opentrons/protocol_engine/state/_well_math.py +18 -60
  78. opentrons/protocol_engine/state/addressable_areas.py +0 -2
  79. opentrons/protocol_engine/state/commands.py +7 -7
  80. opentrons/protocol_engine/state/geometry.py +374 -204
  81. opentrons/protocol_engine/state/labware.py +102 -52
  82. opentrons/protocol_engine/state/module_substates/thermocycler_module_substate.py +0 -37
  83. opentrons/protocol_engine/state/modules.py +8 -21
  84. opentrons/protocol_engine/state/motion.py +0 -44
  85. opentrons/protocol_engine/state/state.py +0 -14
  86. opentrons/protocol_engine/state/state_summary.py +0 -2
  87. opentrons/protocol_engine/state/tips.py +258 -177
  88. opentrons/protocol_engine/state/update_types.py +9 -16
  89. opentrons/protocol_engine/types/__init__.py +3 -9
  90. opentrons/protocol_engine/types/deck_configuration.py +1 -5
  91. opentrons/protocol_engine/types/instrument.py +1 -8
  92. opentrons/protocol_engine/types/labware.py +13 -1
  93. opentrons/protocol_engine/types/module.py +0 -10
  94. opentrons/protocol_engine/types/tip.py +0 -9
  95. opentrons/protocol_runner/create_simulating_orchestrator.py +2 -29
  96. opentrons/protocol_runner/run_orchestrator.py +2 -18
  97. opentrons/protocols/api_support/definitions.py +1 -1
  98. opentrons/protocols/api_support/types.py +1 -2
  99. opentrons/simulate.py +15 -48
  100. opentrons/system/camera.py +1 -1
  101. {opentrons-8.7.0a2.dist-info → opentrons-8.7.0a4.dist-info}/METADATA +4 -4
  102. {opentrons-8.7.0a2.dist-info → opentrons-8.7.0a4.dist-info}/RECORD +105 -118
  103. opentrons/protocol_api/core/engine/tasks.py +0 -35
  104. opentrons/protocol_api/core/legacy/tasks.py +0 -19
  105. opentrons/protocol_api/core/legacy_simulator/tasks.py +0 -19
  106. opentrons/protocol_api/core/tasks.py +0 -31
  107. opentrons/protocol_api/tasks.py +0 -48
  108. opentrons/protocol_engine/commands/create_timer.py +0 -83
  109. opentrons/protocol_engine/commands/set_tip_state.py +0 -97
  110. opentrons/protocol_engine/commands/wait_for_tasks.py +0 -98
  111. opentrons/protocol_engine/execution/task_handler.py +0 -157
  112. opentrons/protocol_engine/resources/concurrency_provider.py +0 -27
  113. opentrons/protocol_engine/state/labware_origin_math/errors.py +0 -94
  114. opentrons/protocol_engine/state/labware_origin_math/stackup_origin_to_labware_origin.py +0 -1331
  115. opentrons/protocol_engine/state/tasks.py +0 -139
  116. opentrons/protocol_engine/types/tasks.py +0 -38
  117. {opentrons-8.7.0a2.dist-info → opentrons-8.7.0a4.dist-info}/WHEEL +0 -0
  118. {opentrons-8.7.0a2.dist-info → opentrons-8.7.0a4.dist-info}/entry_points.txt +0 -0
  119. {opentrons-8.7.0a2.dist-info → opentrons-8.7.0a4.dist-info}/licenses/LICENSE +0 -0
@@ -12,7 +12,7 @@ from opentrons.protocol_engine.errors.exceptions import TipAttachedError
12
12
  from opentrons.protocol_engine.resources.model_utils import ModelUtils
13
13
 
14
14
  from ..state.update_types import StateUpdate
15
- from ..types import DropTipWellLocation, TipRackWellState
15
+ from ..types import DropTipWellLocation
16
16
  from .pipetting_common import (
17
17
  PipetteIdMixin,
18
18
  TipPhysicallyAttachedError,
@@ -140,25 +140,6 @@ class DropTipImplementation(AbstractCommandImpl[DropTipParams, _ExecuteReturn]):
140
140
  partially_configured=is_partially_configured,
141
141
  )
142
142
 
143
- is_tip_rack = self._state_view.labware.get_definition(
144
- labware_id
145
- ).parameters.isTiprack
146
-
147
- # It's possible that we are dropping tips into a labware trash for pre API v2.14 OT-2 protocols
148
- # (or something else unexpected), so if it is not a tip rack mark no wells as used
149
- if is_tip_rack:
150
- tips_to_mark_as_used = (
151
- self._state_view.tips.compute_tips_to_mark_as_used_or_empty(
152
- labware_id=labware_id,
153
- well_name=well_name,
154
- nozzle_map=self._state_view.pipettes.get_nozzle_configuration(
155
- pipette_id
156
- ),
157
- )
158
- )
159
- else:
160
- tips_to_mark_as_used = []
161
-
162
143
  move_result = await move_to_well(
163
144
  movement=self._movement_handler,
164
145
  model_utils=self._model_utils,
@@ -171,7 +152,12 @@ class DropTipImplementation(AbstractCommandImpl[DropTipParams, _ExecuteReturn]):
171
152
  return move_result
172
153
 
173
154
  scrape_type = TipScrapeType.NONE
174
- if params.scrape_tips and is_tip_rack:
155
+ if (
156
+ params.scrape_tips
157
+ and self._state_view.geometry._labware.get_definition(
158
+ labware_id
159
+ ).parameters.isTiprack
160
+ ):
175
161
  if int("".join(filter(str.isdigit, well_name))) <= 6:
176
162
  scrape_type = TipScrapeType.RIGHT_ONE_COL
177
163
  else:
@@ -208,10 +194,6 @@ class DropTipImplementation(AbstractCommandImpl[DropTipParams, _ExecuteReturn]):
208
194
  pipette_id=params.pipetteId,
209
195
  tip_geometry=None,
210
196
  tip_source=None,
211
- ).update_tip_rack_well_state(
212
- tip_state=TipRackWellState.USED,
213
- labware_id=labware_id,
214
- well_names=tips_to_mark_as_used,
215
197
  ),
216
198
  )
217
199
  else:
@@ -219,16 +201,10 @@ class DropTipImplementation(AbstractCommandImpl[DropTipParams, _ExecuteReturn]):
219
201
  public=DropTipResult(position=move_result.public.position),
220
202
  state_update=move_result.state_update.set_fluid_unknown(
221
203
  pipette_id=pipette_id
222
- )
223
- .update_pipette_tip_state(
204
+ ).update_pipette_tip_state(
224
205
  pipette_id=params.pipetteId,
225
206
  tip_geometry=None,
226
207
  tip_source=None,
227
- )
228
- .update_tip_rack_well_state(
229
- tip_state=TipRackWellState.USED,
230
- labware_id=labware_id,
231
- well_names=tips_to_mark_as_used,
232
208
  ),
233
209
  )
234
210
 
@@ -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(
@@ -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
  ]
@@ -39,12 +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
42
 
49
43
 
50
44
  class SetTargetBlockTemperatureResult(BaseModel):
@@ -96,13 +90,6 @@ class SetTargetBlockTemperatureImpl(
96
90
  hold_time = thermocycler_state.validate_hold_time(params.holdTimeSeconds)
97
91
  else:
98
92
  hold_time = None
99
- target_ramp_rate: Optional[float]
100
- if params.ramp_rate is not None:
101
- target_ramp_rate = thermocycler_state.validate_ramp_rate(
102
- params.ramp_rate, target_temperature
103
- )
104
- else:
105
- target_ramp_rate = None
106
93
 
107
94
  thermocycler_hardware = self._equipment.get_module_hardware_api(
108
95
  thermocycler_state.module_id
@@ -110,10 +97,7 @@ class SetTargetBlockTemperatureImpl(
110
97
 
111
98
  if thermocycler_hardware is not None:
112
99
  await thermocycler_hardware.set_target_block_temperature(
113
- target_temperature,
114
- volume=target_volume,
115
- hold_time_seconds=hold_time,
116
- ramp_rate=target_ramp_rate,
100
+ target_temperature, volume=target_volume, hold_time_seconds=hold_time
117
101
  )
118
102
 
119
103
  return SuccessData(
@@ -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",
@@ -413,36 +413,6 @@ class WellDoesNotExistError(ProtocolEngineError):
413
413
  super().__init__(ErrorCodes.GENERAL_ERROR, message, details, wrapping)
414
414
 
415
415
 
416
- class NoTaskFoundError(ProtocolEngineError):
417
- """Raised when referencing a task that does not exist.
418
-
419
- This error could be raised if a protocol references a task before it
420
- has been created.
421
- """
422
-
423
- def __init__(
424
- self,
425
- message: Optional[str] = None,
426
- details: Optional[Dict[str, Any]] = None,
427
- wrapping: Optional[Sequence[EnumeratedError]] = None,
428
- ) -> None:
429
- """Build a NoTaskFoundError."""
430
- super().__init__(ErrorCodes.GENERAL_ERROR, message, details, wrapping)
431
-
432
-
433
- class TaskFailedError(ProtocolEngineError):
434
- """Raised when waiting on a task that failed."""
435
-
436
- def __init__(
437
- self,
438
- message: Optional[str] = None,
439
- details: Optional[Dict[str, Any]] = None,
440
- wrapping: Optional[Sequence[EnumeratedError]] = None,
441
- ) -> None:
442
- """Build a TaskFailedError."""
443
- super().__init__(ErrorCodes.GENERAL_ERROR, message, details, wrapping)
444
-
445
-
446
416
  class PipetteNotLoadedError(ProtocolEngineError):
447
417
  """Raised when referencing a pipette that has not been loaded."""
448
418
 
@@ -855,19 +825,6 @@ class InvalidTargetTemperatureError(ProtocolEngineError):
855
825
  super().__init__(ErrorCodes.GENERAL_ERROR, message, details, wrapping)
856
826
 
857
827
 
858
- class InvalidRampRateError(ProtocolEngineError):
859
- """Raised when attempting to set an invalid ramp rate."""
860
-
861
- def __init__(
862
- self,
863
- message: Optional[str] = None,
864
- details: Optional[Dict[str, Any]] = None,
865
- wrapping: Optional[Sequence[EnumeratedError]] = None,
866
- ) -> None:
867
- """Build a InvalidRampRateError."""
868
- super().__init__(ErrorCodes.GENERAL_ERROR, message, details, wrapping)
869
-
870
-
871
828
  class InvalidBlockVolumeError(ProtocolEngineError):
872
829
  """Raised when attempting to set an invalid block max volume."""
873
830
 
@@ -1349,15 +1306,3 @@ class InvalidLabwarePositionError(ProtocolEngineError):
1349
1306
  wrapping: Optional[Sequence[EnumeratedError]] = None,
1350
1307
  ) -> None:
1351
1308
  super().__init__(ErrorCodes.GENERAL_ERROR, message, details, wrapping)
1352
-
1353
-
1354
- class InvalidModuleOrientation(ProtocolEngineError):
1355
- """Raised when a module orientation is invalid for a slot id."""
1356
-
1357
- def __init__(
1358
- self,
1359
- message: Optional[str] = None,
1360
- details: Optional[dict[str, Any]] = None,
1361
- wrapping: Optional[Sequence[EnumeratedError]] = None,
1362
- ) -> None:
1363
- super().__init__(ErrorCodes.GENERAL_ERROR, message, details, wrapping)
@@ -21,7 +21,6 @@ from .run_control import RunControlHandler
21
21
  from .hardware_stopper import HardwareStopper
22
22
  from .door_watcher import DoorWatcher
23
23
  from .status_bar import StatusBarHandler
24
- from .task_handler import TaskHandler
25
24
  from ..resources.file_provider import FileProvider
26
25
 
27
26
  # .thermocycler_movement_flagger omitted from package's public interface.
@@ -47,6 +46,5 @@ __all__ = [
47
46
  "DoorWatcher",
48
47
  "RailLightsHandler",
49
48
  "StatusBarHandler",
50
- "TaskHandler",
51
49
  "FileProvider",
52
50
  ]
@@ -35,7 +35,6 @@ from .tip_handler import TipHandler
35
35
  from .run_control import RunControlHandler
36
36
  from .rail_lights import RailLightsHandler
37
37
  from .status_bar import StatusBarHandler
38
- from .task_handler import TaskHandler
39
38
 
40
39
 
41
40
  log = getLogger(__name__)
@@ -86,7 +85,6 @@ class CommandExecutor:
86
85
  run_control: RunControlHandler,
87
86
  rail_lights: RailLightsHandler,
88
87
  status_bar: StatusBarHandler,
89
- task_handler: TaskHandler,
90
88
  model_utils: Optional[ModelUtils] = None,
91
89
  command_note_tracker_provider: Optional[CommandNoteTrackerProvider] = None,
92
90
  ) -> None:
@@ -108,7 +106,6 @@ class CommandExecutor:
108
106
  self._command_note_tracker_provider = (
109
107
  command_note_tracker_provider or _NoteTracker
110
108
  )
111
- self._task_handler = task_handler
112
109
 
113
110
  async def execute(self, command_id: str) -> None:
114
111
  """Run a given command's execution procedure.
@@ -134,7 +131,6 @@ class CommandExecutor:
134
131
  model_utils=self._model_utils,
135
132
  status_bar=self._status_bar,
136
133
  command_note_adder=note_tracker,
137
- task_handler=self._task_handler,
138
134
  )
139
135
 
140
136
  started_at = self._model_utils.get_timestamp()
@@ -218,7 +214,3 @@ class CommandExecutor:
218
214
  type=error_recovery_type,
219
215
  )
220
216
  )
221
-
222
- def cancel_tasks(self, message: str | None = None) -> None:
223
- """Cancel all concurrent tasks."""
224
- self._task_handler.cancel_all(message=message)
@@ -17,7 +17,6 @@ from .run_control import RunControlHandler
17
17
  from .command_executor import CommandExecutor
18
18
  from .queue_worker import QueueWorker
19
19
  from .status_bar import StatusBarHandler
20
- from .task_handler import TaskHandler
21
20
 
22
21
 
23
22
  def create_queue_worker(
@@ -77,9 +76,7 @@ def create_queue_worker(
77
76
  rail_lights_handler = RailLightsHandler(
78
77
  hardware_api=hardware_api,
79
78
  )
80
- task_handler = TaskHandler(
81
- state_store=state_store, action_dispatcher=action_dispatcher
82
- )
79
+
83
80
  status_bar_handler = StatusBarHandler(hardware_api=hardware_api)
84
81
 
85
82
  command_executor = CommandExecutor(
@@ -96,7 +93,6 @@ def create_queue_worker(
96
93
  run_control=run_control_handler,
97
94
  rail_lights=rail_lights_handler,
98
95
  status_bar=status_bar_handler,
99
- task_handler=task_handler,
100
96
  )
101
97
 
102
98
  return QueueWorker(
@@ -31,7 +31,6 @@ from ..types import (
31
31
  OnLabwareLocation,
32
32
  LabwareLocation,
33
33
  OnDeckLabwareLocation,
34
- GripperMoveType,
35
34
  )
36
35
 
37
36
  if TYPE_CHECKING:
@@ -142,16 +141,10 @@ class LabwareMovementHandler:
142
141
  labware_definition = self._state_store.labware.get_definition(labware_id)
143
142
 
144
143
  from_labware_center = self._state_store.geometry.get_labware_grip_point(
145
- labware_definition=labware_definition,
146
- location=current_location,
147
- move_type=GripperMoveType.PICK_UP_LABWARE,
148
- user_additional_offset=user_pick_up_offset,
144
+ labware_definition=labware_definition, location=current_location
149
145
  )
150
146
  to_labware_center = self._state_store.geometry.get_labware_grip_point(
151
- labware_definition=labware_definition,
152
- location=new_location,
153
- move_type=GripperMoveType.DROP_LABWARE,
154
- user_additional_offset=user_drop_offset,
147
+ labware_definition=labware_definition, location=new_location
155
148
  )
156
149
 
157
150
  if use_virtual_gripper:
@@ -200,10 +193,20 @@ class LabwareMovementHandler:
200
193
  async with self._thermocycler_plate_lifter.lift_plate_for_labware_movement(
201
194
  labware_location=current_location
202
195
  ):
196
+ final_offsets = (
197
+ self._state_store.geometry.get_final_labware_movement_offset_vectors(
198
+ from_location=current_location,
199
+ to_location=new_location,
200
+ additional_pick_up_offset=user_pick_up_offset,
201
+ additional_drop_offset=user_drop_offset,
202
+ current_labware=labware_definition,
203
+ )
204
+ )
203
205
  movement_waypoints = get_gripper_labware_movement_waypoints(
204
206
  from_labware_center=from_labware_center,
205
207
  to_labware_center=to_labware_center,
206
208
  gripper_home_z=gripper_homed_position.z,
209
+ offset_data=final_offsets,
207
210
  post_drop_slide_offset=post_drop_slide_offset,
208
211
  gripper_home_z_offset=gripper_z_offset,
209
212
  )
@@ -83,7 +83,6 @@ class MovementHandler:
83
83
  minimum_z_height: Optional[float] = None,
84
84
  speed: Optional[float] = None,
85
85
  operation_volume: Optional[float] = None,
86
- offset_pipette_for_reservoir_subwells: bool = False,
87
86
  ) -> Point:
88
87
  """Move to a specific well."""
89
88
  self._state_store.geometry.raise_if_labware_inaccessible_by_pipette(
@@ -144,7 +143,6 @@ class MovementHandler:
144
143
  force_direct=force_direct,
145
144
  minimum_z_height=minimum_z_height,
146
145
  operation_volume=operation_volume,
147
- offset_pipette_for_reservoir_subwells=offset_pipette_for_reservoir_subwells,
148
146
  )
149
147
 
150
148
  speed = self._state_store.pipettes.get_movement_speed(
@@ -51,7 +51,6 @@ class QueueWorker:
51
51
  """
52
52
  if self._worker_task:
53
53
  self._worker_task.cancel()
54
- self._command_executor.cancel_tasks("Engine cancelled")
55
54
 
56
55
  async def join(self) -> None:
57
56
  """Wait for the worker to finish, propagating any errors."""
@@ -66,10 +65,7 @@ class QueueWorker:
66
65
  pass
67
66
  except Exception as e:
68
67
  log.error("Unhandled exception in QueueWorker job", exc_info=e)
69
- self._command_executor.cancel_tasks("Engine failed")
70
68
  raise e
71
- else:
72
- self._command_executor.cancel_tasks("Engine commands complete")
73
69
 
74
70
  async def _run_commands(self) -> None:
75
71
  async for command_id in self._command_generator():
@@ -31,11 +31,3 @@ class RunControlHandler:
31
31
  """Delay protocol execution for a duration."""
32
32
  if not self._state_store.config.ignore_pause:
33
33
  await asyncio.sleep(seconds)
34
-
35
- async def wait_for_tasks(self, tasks: list[str]) -> None:
36
- """Wait for concurrent tasks to complete."""
37
- await self._state_store.wait_for(
38
- condition=lambda: self._state_store.tasks.all_tasks_finished_or_any_task_failed(
39
- task_ids=tasks
40
- )
41
- )