opentrons 8.2.0a4__py2.py3-none-any.whl → 8.3.0a1__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.
Files changed (229) hide show
  1. opentrons/calibration_storage/deck_configuration.py +3 -3
  2. opentrons/calibration_storage/file_operators.py +3 -3
  3. opentrons/calibration_storage/helpers.py +3 -1
  4. opentrons/calibration_storage/ot2/models/v1.py +16 -29
  5. opentrons/calibration_storage/ot2/tip_length.py +7 -4
  6. opentrons/calibration_storage/ot3/models/v1.py +14 -23
  7. opentrons/cli/analyze.py +18 -6
  8. opentrons/config/defaults_ot3.py +1 -0
  9. opentrons/drivers/asyncio/communication/__init__.py +2 -0
  10. opentrons/drivers/asyncio/communication/errors.py +16 -3
  11. opentrons/drivers/asyncio/communication/serial_connection.py +24 -9
  12. opentrons/drivers/command_builder.py +2 -2
  13. opentrons/drivers/flex_stacker/__init__.py +9 -0
  14. opentrons/drivers/flex_stacker/abstract.py +89 -0
  15. opentrons/drivers/flex_stacker/driver.py +260 -0
  16. opentrons/drivers/flex_stacker/simulator.py +109 -0
  17. opentrons/drivers/flex_stacker/types.py +138 -0
  18. opentrons/drivers/heater_shaker/driver.py +18 -3
  19. opentrons/drivers/temp_deck/driver.py +13 -3
  20. opentrons/drivers/thermocycler/driver.py +17 -3
  21. opentrons/execute.py +3 -1
  22. opentrons/hardware_control/__init__.py +1 -2
  23. opentrons/hardware_control/api.py +28 -20
  24. opentrons/hardware_control/backends/flex_protocol.py +17 -7
  25. opentrons/hardware_control/backends/ot3controller.py +213 -63
  26. opentrons/hardware_control/backends/ot3simulator.py +18 -9
  27. opentrons/hardware_control/backends/ot3utils.py +43 -15
  28. opentrons/hardware_control/dev_types.py +4 -0
  29. opentrons/hardware_control/emulation/heater_shaker.py +4 -0
  30. opentrons/hardware_control/emulation/module_server/client.py +1 -1
  31. opentrons/hardware_control/emulation/module_server/server.py +5 -3
  32. opentrons/hardware_control/emulation/settings.py +3 -4
  33. opentrons/hardware_control/instruments/ot2/instrument_calibration.py +2 -1
  34. opentrons/hardware_control/instruments/ot2/pipette.py +15 -22
  35. opentrons/hardware_control/instruments/ot2/pipette_handler.py +8 -1
  36. opentrons/hardware_control/instruments/ot3/gripper.py +2 -2
  37. opentrons/hardware_control/instruments/ot3/pipette.py +23 -22
  38. opentrons/hardware_control/instruments/ot3/pipette_handler.py +10 -1
  39. opentrons/hardware_control/modules/mod_abc.py +2 -2
  40. opentrons/hardware_control/motion_utilities.py +68 -0
  41. opentrons/hardware_control/nozzle_manager.py +39 -41
  42. opentrons/hardware_control/ot3_calibration.py +1 -1
  43. opentrons/hardware_control/ot3api.py +60 -23
  44. opentrons/hardware_control/protocols/gripper_controller.py +3 -0
  45. opentrons/hardware_control/protocols/hardware_manager.py +5 -1
  46. opentrons/hardware_control/protocols/liquid_handler.py +18 -0
  47. opentrons/hardware_control/protocols/motion_controller.py +6 -0
  48. opentrons/hardware_control/robot_calibration.py +1 -1
  49. opentrons/hardware_control/types.py +61 -0
  50. opentrons/protocol_api/__init__.py +20 -1
  51. opentrons/protocol_api/_liquid.py +24 -49
  52. opentrons/protocol_api/_liquid_properties.py +754 -0
  53. opentrons/protocol_api/_types.py +24 -0
  54. opentrons/protocol_api/core/common.py +2 -0
  55. opentrons/protocol_api/core/engine/instrument.py +82 -10
  56. opentrons/protocol_api/core/engine/labware.py +29 -7
  57. opentrons/protocol_api/core/engine/protocol.py +130 -5
  58. opentrons/protocol_api/core/engine/robot.py +139 -0
  59. opentrons/protocol_api/core/engine/well.py +4 -1
  60. opentrons/protocol_api/core/instrument.py +46 -4
  61. opentrons/protocol_api/core/labware.py +13 -4
  62. opentrons/protocol_api/core/legacy/legacy_instrument_core.py +37 -3
  63. opentrons/protocol_api/core/legacy/legacy_labware_core.py +13 -4
  64. opentrons/protocol_api/core/legacy/legacy_protocol_core.py +32 -1
  65. opentrons/protocol_api/core/legacy/legacy_robot_core.py +0 -0
  66. opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +37 -3
  67. opentrons/protocol_api/core/protocol.py +34 -1
  68. opentrons/protocol_api/core/robot.py +51 -0
  69. opentrons/protocol_api/instrument_context.py +158 -44
  70. opentrons/protocol_api/labware.py +231 -7
  71. opentrons/protocol_api/module_contexts.py +21 -17
  72. opentrons/protocol_api/protocol_context.py +125 -4
  73. opentrons/protocol_api/robot_context.py +204 -32
  74. opentrons/protocol_api/validation.py +262 -3
  75. opentrons/protocol_engine/__init__.py +4 -0
  76. opentrons/protocol_engine/actions/actions.py +2 -3
  77. opentrons/protocol_engine/clients/sync_client.py +18 -0
  78. opentrons/protocol_engine/commands/__init__.py +81 -0
  79. opentrons/protocol_engine/commands/absorbance_reader/close_lid.py +0 -2
  80. opentrons/protocol_engine/commands/absorbance_reader/initialize.py +19 -5
  81. opentrons/protocol_engine/commands/absorbance_reader/open_lid.py +0 -1
  82. opentrons/protocol_engine/commands/absorbance_reader/read.py +32 -9
  83. opentrons/protocol_engine/commands/air_gap_in_place.py +160 -0
  84. opentrons/protocol_engine/commands/aspirate.py +103 -53
  85. opentrons/protocol_engine/commands/aspirate_in_place.py +55 -51
  86. opentrons/protocol_engine/commands/blow_out.py +44 -39
  87. opentrons/protocol_engine/commands/blow_out_in_place.py +21 -32
  88. opentrons/protocol_engine/commands/calibration/calibrate_gripper.py +13 -6
  89. opentrons/protocol_engine/commands/calibration/calibrate_module.py +1 -1
  90. opentrons/protocol_engine/commands/calibration/calibrate_pipette.py +3 -3
  91. opentrons/protocol_engine/commands/calibration/move_to_maintenance_position.py +1 -1
  92. opentrons/protocol_engine/commands/command.py +73 -66
  93. opentrons/protocol_engine/commands/command_unions.py +101 -1
  94. opentrons/protocol_engine/commands/comment.py +1 -1
  95. opentrons/protocol_engine/commands/configure_for_volume.py +10 -3
  96. opentrons/protocol_engine/commands/configure_nozzle_layout.py +6 -4
  97. opentrons/protocol_engine/commands/custom.py +6 -12
  98. opentrons/protocol_engine/commands/dispense.py +82 -48
  99. opentrons/protocol_engine/commands/dispense_in_place.py +71 -51
  100. opentrons/protocol_engine/commands/drop_tip.py +52 -31
  101. opentrons/protocol_engine/commands/drop_tip_in_place.py +13 -3
  102. opentrons/protocol_engine/commands/generate_command_schema.py +4 -11
  103. opentrons/protocol_engine/commands/get_next_tip.py +134 -0
  104. opentrons/protocol_engine/commands/get_tip_presence.py +1 -1
  105. opentrons/protocol_engine/commands/heater_shaker/close_labware_latch.py +1 -1
  106. opentrons/protocol_engine/commands/heater_shaker/deactivate_heater.py +1 -1
  107. opentrons/protocol_engine/commands/heater_shaker/deactivate_shaker.py +1 -1
  108. opentrons/protocol_engine/commands/heater_shaker/open_labware_latch.py +1 -1
  109. opentrons/protocol_engine/commands/heater_shaker/set_and_wait_for_shake_speed.py +1 -1
  110. opentrons/protocol_engine/commands/heater_shaker/set_target_temperature.py +1 -1
  111. opentrons/protocol_engine/commands/heater_shaker/wait_for_temperature.py +10 -4
  112. opentrons/protocol_engine/commands/home.py +13 -4
  113. opentrons/protocol_engine/commands/liquid_probe.py +67 -24
  114. opentrons/protocol_engine/commands/load_labware.py +29 -7
  115. opentrons/protocol_engine/commands/load_lid.py +146 -0
  116. opentrons/protocol_engine/commands/load_lid_stack.py +189 -0
  117. opentrons/protocol_engine/commands/load_liquid.py +12 -4
  118. opentrons/protocol_engine/commands/load_liquid_class.py +144 -0
  119. opentrons/protocol_engine/commands/load_module.py +31 -10
  120. opentrons/protocol_engine/commands/load_pipette.py +19 -8
  121. opentrons/protocol_engine/commands/magnetic_module/disengage.py +1 -1
  122. opentrons/protocol_engine/commands/magnetic_module/engage.py +1 -1
  123. opentrons/protocol_engine/commands/move_labware.py +19 -6
  124. opentrons/protocol_engine/commands/move_relative.py +35 -25
  125. opentrons/protocol_engine/commands/move_to_addressable_area.py +40 -27
  126. opentrons/protocol_engine/commands/move_to_addressable_area_for_drop_tip.py +53 -32
  127. opentrons/protocol_engine/commands/move_to_coordinates.py +36 -22
  128. opentrons/protocol_engine/commands/move_to_well.py +40 -24
  129. opentrons/protocol_engine/commands/movement_common.py +338 -0
  130. opentrons/protocol_engine/commands/pick_up_tip.py +49 -27
  131. opentrons/protocol_engine/commands/pipetting_common.py +169 -87
  132. opentrons/protocol_engine/commands/prepare_to_aspirate.py +24 -33
  133. opentrons/protocol_engine/commands/reload_labware.py +1 -1
  134. opentrons/protocol_engine/commands/retract_axis.py +1 -1
  135. opentrons/protocol_engine/commands/robot/__init__.py +69 -0
  136. opentrons/protocol_engine/commands/robot/close_gripper_jaw.py +86 -0
  137. opentrons/protocol_engine/commands/robot/common.py +18 -0
  138. opentrons/protocol_engine/commands/robot/move_axes_relative.py +101 -0
  139. opentrons/protocol_engine/commands/robot/move_axes_to.py +100 -0
  140. opentrons/protocol_engine/commands/robot/move_to.py +94 -0
  141. opentrons/protocol_engine/commands/robot/open_gripper_jaw.py +77 -0
  142. opentrons/protocol_engine/commands/save_position.py +14 -5
  143. opentrons/protocol_engine/commands/set_rail_lights.py +1 -1
  144. opentrons/protocol_engine/commands/set_status_bar.py +1 -1
  145. opentrons/protocol_engine/commands/temperature_module/deactivate.py +1 -1
  146. opentrons/protocol_engine/commands/temperature_module/set_target_temperature.py +1 -1
  147. opentrons/protocol_engine/commands/temperature_module/wait_for_temperature.py +10 -4
  148. opentrons/protocol_engine/commands/thermocycler/close_lid.py +1 -1
  149. opentrons/protocol_engine/commands/thermocycler/deactivate_block.py +1 -1
  150. opentrons/protocol_engine/commands/thermocycler/deactivate_lid.py +1 -1
  151. opentrons/protocol_engine/commands/thermocycler/open_lid.py +1 -1
  152. opentrons/protocol_engine/commands/thermocycler/run_extended_profile.py +8 -2
  153. opentrons/protocol_engine/commands/thermocycler/run_profile.py +9 -3
  154. opentrons/protocol_engine/commands/thermocycler/set_target_block_temperature.py +11 -4
  155. opentrons/protocol_engine/commands/thermocycler/set_target_lid_temperature.py +1 -1
  156. opentrons/protocol_engine/commands/thermocycler/wait_for_block_temperature.py +1 -1
  157. opentrons/protocol_engine/commands/thermocycler/wait_for_lid_temperature.py +1 -1
  158. opentrons/protocol_engine/commands/touch_tip.py +65 -16
  159. opentrons/protocol_engine/commands/unsafe/unsafe_blow_out_in_place.py +4 -1
  160. opentrons/protocol_engine/commands/unsafe/unsafe_drop_tip_in_place.py +12 -3
  161. opentrons/protocol_engine/commands/unsafe/unsafe_engage_axes.py +1 -4
  162. opentrons/protocol_engine/commands/unsafe/update_position_estimators.py +1 -4
  163. opentrons/protocol_engine/commands/verify_tip_presence.py +11 -4
  164. opentrons/protocol_engine/commands/wait_for_duration.py +10 -3
  165. opentrons/protocol_engine/commands/wait_for_resume.py +10 -3
  166. opentrons/protocol_engine/errors/__init__.py +8 -0
  167. opentrons/protocol_engine/errors/error_occurrence.py +19 -20
  168. opentrons/protocol_engine/errors/exceptions.py +50 -0
  169. opentrons/protocol_engine/execution/command_executor.py +1 -1
  170. opentrons/protocol_engine/execution/equipment.py +73 -5
  171. opentrons/protocol_engine/execution/gantry_mover.py +364 -8
  172. opentrons/protocol_engine/execution/movement.py +27 -0
  173. opentrons/protocol_engine/execution/pipetting.py +5 -1
  174. opentrons/protocol_engine/execution/tip_handler.py +4 -6
  175. opentrons/protocol_engine/notes/notes.py +1 -1
  176. opentrons/protocol_engine/protocol_engine.py +7 -6
  177. opentrons/protocol_engine/resources/labware_data_provider.py +1 -1
  178. opentrons/protocol_engine/resources/labware_validation.py +5 -0
  179. opentrons/protocol_engine/resources/module_data_provider.py +1 -1
  180. opentrons/protocol_engine/resources/pipette_data_provider.py +26 -0
  181. opentrons/protocol_engine/slot_standardization.py +9 -9
  182. opentrons/protocol_engine/state/_move_types.py +9 -5
  183. opentrons/protocol_engine/state/_well_math.py +193 -0
  184. opentrons/protocol_engine/state/addressable_areas.py +25 -61
  185. opentrons/protocol_engine/state/command_history.py +12 -0
  186. opentrons/protocol_engine/state/commands.py +17 -13
  187. opentrons/protocol_engine/state/files.py +10 -12
  188. opentrons/protocol_engine/state/fluid_stack.py +138 -0
  189. opentrons/protocol_engine/state/frustum_helpers.py +57 -32
  190. opentrons/protocol_engine/state/geometry.py +47 -1
  191. opentrons/protocol_engine/state/labware.py +79 -25
  192. opentrons/protocol_engine/state/liquid_classes.py +82 -0
  193. opentrons/protocol_engine/state/liquids.py +16 -4
  194. opentrons/protocol_engine/state/modules.py +52 -70
  195. opentrons/protocol_engine/state/motion.py +6 -1
  196. opentrons/protocol_engine/state/pipettes.py +144 -58
  197. opentrons/protocol_engine/state/state.py +21 -2
  198. opentrons/protocol_engine/state/state_summary.py +4 -2
  199. opentrons/protocol_engine/state/tips.py +11 -44
  200. opentrons/protocol_engine/state/update_types.py +343 -48
  201. opentrons/protocol_engine/state/wells.py +19 -11
  202. opentrons/protocol_engine/types.py +176 -28
  203. opentrons/protocol_reader/extract_labware_definitions.py +5 -2
  204. opentrons/protocol_reader/file_format_validator.py +5 -5
  205. opentrons/protocol_runner/json_file_reader.py +9 -3
  206. opentrons/protocol_runner/json_translator.py +51 -25
  207. opentrons/protocol_runner/legacy_command_mapper.py +66 -64
  208. opentrons/protocol_runner/protocol_runner.py +35 -4
  209. opentrons/protocol_runner/python_protocol_wrappers.py +1 -1
  210. opentrons/protocol_runner/run_orchestrator.py +13 -3
  211. opentrons/protocols/advanced_control/common.py +38 -0
  212. opentrons/protocols/advanced_control/mix.py +1 -1
  213. opentrons/protocols/advanced_control/transfers/__init__.py +0 -0
  214. opentrons/protocols/advanced_control/transfers/common.py +56 -0
  215. opentrons/protocols/advanced_control/{transfers.py → transfers/transfer.py} +10 -85
  216. opentrons/protocols/api_support/definitions.py +1 -1
  217. opentrons/protocols/api_support/instrument.py +1 -1
  218. opentrons/protocols/api_support/util.py +10 -0
  219. opentrons/protocols/labware.py +39 -6
  220. opentrons/protocols/models/json_protocol.py +5 -9
  221. opentrons/simulate.py +3 -1
  222. opentrons/types.py +162 -2
  223. opentrons/util/logging_config.py +1 -1
  224. {opentrons-8.2.0a4.dist-info → opentrons-8.3.0a1.dist-info}/METADATA +16 -15
  225. {opentrons-8.2.0a4.dist-info → opentrons-8.3.0a1.dist-info}/RECORD +229 -202
  226. {opentrons-8.2.0a4.dist-info → opentrons-8.3.0a1.dist-info}/WHEEL +1 -1
  227. {opentrons-8.2.0a4.dist-info → opentrons-8.3.0a1.dist-info}/LICENSE +0 -0
  228. {opentrons-8.2.0a4.dist-info → opentrons-8.3.0a1.dist-info}/entry_points.txt +0 -0
  229. {opentrons-8.2.0a4.dist-info → opentrons-8.3.0a1.dist-info}/top_level.txt +0 -0
@@ -20,6 +20,7 @@ from . import temperature_module
20
20
  from . import thermocycler
21
21
  from . import calibration
22
22
  from . import unsafe
23
+ from . import robot
23
24
 
24
25
  from .hash_command_params import hash_protocol_command_params
25
26
  from .generate_command_schema import generate_command_schema
@@ -34,13 +35,23 @@ from .command import (
34
35
 
35
36
  from .command_unions import (
36
37
  Command,
38
+ CommandAdapter,
37
39
  CommandParams,
38
40
  CommandCreate,
41
+ CommandCreateAdapter,
39
42
  CommandResult,
40
43
  CommandType,
41
44
  CommandDefinedErrorData,
42
45
  )
43
46
 
47
+ from .air_gap_in_place import (
48
+ AirGapInPlace,
49
+ AirGapInPlaceParams,
50
+ AirGapInPlaceCreate,
51
+ AirGapInPlaceResult,
52
+ AirGapInPlaceCommandType,
53
+ )
54
+
44
55
  from .aspirate import (
45
56
  Aspirate,
46
57
  AspirateParams,
@@ -138,6 +149,15 @@ from .load_liquid import (
138
149
  LoadLiquidImplementation,
139
150
  )
140
151
 
152
+ from .load_liquid_class import (
153
+ LoadLiquidClass,
154
+ LoadLiquidClassParams,
155
+ LoadLiquidClassCreate,
156
+ LoadLiquidClassResult,
157
+ LoadLiquidClassCommandType,
158
+ LoadLiquidClassImplementation,
159
+ )
160
+
141
161
  from .load_module import (
142
162
  LoadModule,
143
163
  LoadModuleParams,
@@ -154,6 +174,22 @@ from .load_pipette import (
154
174
  LoadPipetteCommandType,
155
175
  )
156
176
 
177
+ from .load_lid_stack import (
178
+ LoadLidStack,
179
+ LoadLidStackParams,
180
+ LoadLidStackCreate,
181
+ LoadLidStackResult,
182
+ LoadLidStackCommandType,
183
+ )
184
+
185
+ from .load_lid import (
186
+ LoadLid,
187
+ LoadLidParams,
188
+ LoadLidCreate,
189
+ LoadLidResult,
190
+ LoadLidCommandType,
191
+ )
192
+
157
193
  from .move_labware import (
158
194
  MoveLabware,
159
195
  MoveLabwareParams,
@@ -323,6 +359,14 @@ from .verify_tip_presence import (
323
359
  VerifyTipPresenceCommandType,
324
360
  )
325
361
 
362
+ from .get_next_tip import (
363
+ GetNextTip,
364
+ GetNextTipCreate,
365
+ GetNextTipParams,
366
+ GetNextTipResult,
367
+ GetNextTipCommandType,
368
+ )
369
+
326
370
  from .liquid_probe import (
327
371
  LiquidProbe,
328
372
  LiquidProbeParams,
@@ -339,8 +383,10 @@ from .liquid_probe import (
339
383
  __all__ = [
340
384
  # command type unions
341
385
  "Command",
386
+ "CommandAdapter",
342
387
  "CommandParams",
343
388
  "CommandCreate",
389
+ "CommandCreateAdapter",
344
390
  "CommandResult",
345
391
  "CommandType",
346
392
  "CommandPrivateResult",
@@ -355,6 +401,12 @@ __all__ = [
355
401
  "hash_protocol_command_params",
356
402
  # command schema generation
357
403
  "generate_command_schema",
404
+ # air gap command models
405
+ "AirGapInPlace",
406
+ "AirGapInPlaceCreate",
407
+ "AirGapInPlaceParams",
408
+ "AirGapInPlaceResult",
409
+ "AirGapInPlaceCommandType",
358
410
  # aspirate command models
359
411
  "Aspirate",
360
412
  "AspirateCreate",
@@ -440,6 +492,20 @@ __all__ = [
440
492
  "LoadPipetteResult",
441
493
  "LoadPipetteCommandType",
442
494
  "LoadPipettePrivateResult",
495
+ # load lid stack command models
496
+ "LoadLidStack",
497
+ "LoadLidStackCreate",
498
+ "LoadLidStackParams",
499
+ "LoadLidStackResult",
500
+ "LoadLidStackCommandType",
501
+ "LoadLidStackPrivateResult",
502
+ # load lid command models
503
+ "LoadLid",
504
+ "LoadLidCreate",
505
+ "LoadLidParams",
506
+ "LoadLidResult",
507
+ "LoadLidCommandType",
508
+ "LoadLidPrivateResult",
443
509
  # move labware command models
444
510
  "MoveLabware",
445
511
  "MoveLabwareCreate",
@@ -538,6 +604,14 @@ __all__ = [
538
604
  "LoadLiquidParams",
539
605
  "LoadLiquidResult",
540
606
  "LoadLiquidCommandType",
607
+ # load liquid class command models
608
+ "LoadLiquidClass",
609
+ "LoadLiquidClassParams",
610
+ "LoadLiquidClassCreate",
611
+ "LoadLiquidClassResult",
612
+ "LoadLiquidClassImplementation",
613
+ "LoadLiquidClassCommandType",
614
+ # hardware control command models
541
615
  # hardware module command bundles
542
616
  "absorbance_reader",
543
617
  "heater_shaker",
@@ -548,6 +622,7 @@ __all__ = [
548
622
  "calibration",
549
623
  # unsafe command bundle
550
624
  "unsafe",
625
+ "robot",
551
626
  # configure pipette volume command bundle
552
627
  "ConfigureForVolume",
553
628
  "ConfigureForVolumeCreate",
@@ -578,6 +653,12 @@ __all__ = [
578
653
  "VerifyTipPresenceParams",
579
654
  "VerifyTipPresenceResult",
580
655
  "VerifyTipPresenceCommandType",
656
+ # get next tip command bundle
657
+ "GetNextTip",
658
+ "GetNextTipCreate",
659
+ "GetNextTipParams",
660
+ "GetNextTipResult",
661
+ "GetNextTipCommandType",
581
662
  # liquid probe command bundle
582
663
  "LiquidProbe",
583
664
  "LiquidProbeParams",
@@ -60,7 +60,6 @@ class CloseLidImpl(AbstractCommandImpl[CloseLidParams, SuccessData[CloseLidResul
60
60
  hardware_lid_status = AbsorbanceReaderLidStatus.OFF
61
61
  if not self._state_view.config.use_virtual_modules:
62
62
  abs_reader = self._equipment.get_module_hardware_api(mod_substate.module_id)
63
-
64
63
  if abs_reader is not None:
65
64
  hardware_lid_status = await abs_reader.get_current_lid_status()
66
65
  else:
@@ -95,7 +94,6 @@ class CloseLidImpl(AbstractCommandImpl[CloseLidParams, SuccessData[CloseLidResul
95
94
  deck_slot=self._state_view.modules.get_location(
96
95
  params.moduleId
97
96
  ).slotName,
98
- deck_type=self._state_view.config.deck_type,
99
97
  model=absorbance_model,
100
98
  )
101
99
  )
@@ -1,9 +1,10 @@
1
1
  """Command models to initialize an Absorbance Reader."""
2
2
  from __future__ import annotations
3
- from typing import List, Optional, Literal, TYPE_CHECKING
3
+ from typing import List, Optional, Literal, TYPE_CHECKING, Any
4
4
  from typing_extensions import Type
5
5
 
6
6
  from pydantic import BaseModel, Field
7
+ from pydantic.json_schema import SkipJsonSchema
7
8
 
8
9
  from opentrons.drivers.types import ABSMeasurementMode
9
10
  from opentrons.protocol_engine.types import ABSMeasureMode
@@ -11,6 +12,7 @@ from opentrons.protocol_engine.types import ABSMeasureMode
11
12
  from ..command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, SuccessData
12
13
  from ...errors.error_occurrence import ErrorOccurrence
13
14
  from ...errors import InvalidWavelengthError
15
+ from ...state import update_types
14
16
 
15
17
  if TYPE_CHECKING:
16
18
  from opentrons.protocol_engine.state.state import StateView
@@ -20,6 +22,10 @@ if TYPE_CHECKING:
20
22
  InitializeCommandType = Literal["absorbanceReader/initialize"]
21
23
 
22
24
 
25
+ def _remove_default(s: dict[str, Any]) -> None:
26
+ s.pop("default", None)
27
+
28
+
23
29
  class InitializeParams(BaseModel):
24
30
  """Input parameters to initialize an absorbance reading."""
25
31
 
@@ -28,8 +34,10 @@ class InitializeParams(BaseModel):
28
34
  ..., description="Initialize single or multi measurement mode."
29
35
  )
30
36
  sampleWavelengths: List[int] = Field(..., description="Sample wavelengths in nm.")
31
- referenceWavelength: Optional[int] = Field(
32
- None, description="Optional reference wavelength in nm."
37
+ referenceWavelength: int | SkipJsonSchema[None] = Field(
38
+ None,
39
+ description="Optional reference wavelength in nm.",
40
+ json_schema_extra=_remove_default,
33
41
  )
34
42
 
35
43
 
@@ -53,6 +61,7 @@ class InitializeImpl(
53
61
 
54
62
  async def execute(self, params: InitializeParams) -> SuccessData[InitializeResult]:
55
63
  """Initiate a single absorbance measurement."""
64
+ state_update = update_types.StateUpdate()
56
65
  abs_reader_substate = self._state_view.modules.get_absorbance_reader_substate(
57
66
  module_id=params.moduleId
58
67
  )
@@ -113,10 +122,15 @@ class InitializeImpl(
113
122
  reference_wavelength=params.referenceWavelength,
114
123
  )
115
124
 
116
- return SuccessData(
117
- public=InitializeResult(),
125
+ state_update.initialize_absorbance_reader(
126
+ abs_reader_substate.module_id,
127
+ params.measureMode,
128
+ params.sampleWavelengths,
129
+ params.referenceWavelength,
118
130
  )
119
131
 
132
+ return SuccessData(public=InitializeResult(), state_update=state_update)
133
+
120
134
 
121
135
  class Initialize(BaseCommand[InitializeParams, InitializeResult, ErrorOccurrence]):
122
136
  """A command to initialize an Absorbance Reader."""
@@ -91,7 +91,6 @@ class OpenLidImpl(AbstractCommandImpl[OpenLidParams, SuccessData[OpenLidResult]]
91
91
  deck_slot=self._state_view.modules.get_location(
92
92
  params.moduleId
93
93
  ).slotName,
94
- deck_type=self._state_view.config.deck_type,
95
94
  model=absorbance_model,
96
95
  )
97
96
  )
@@ -1,10 +1,11 @@
1
1
  """Command models to read absorbance."""
2
2
  from __future__ import annotations
3
3
  from datetime import datetime
4
- from typing import Optional, Dict, TYPE_CHECKING, List
5
- from typing_extensions import Literal, Type
4
+ from typing import Optional, Dict, TYPE_CHECKING, List, Any
6
5
 
6
+ from typing_extensions import Literal, Type
7
7
  from pydantic import BaseModel, Field
8
+ from pydantic.json_schema import SkipJsonSchema
8
9
 
9
10
  from ..command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, SuccessData
10
11
  from ...errors import CannotPerformModuleAction, StorageLimitReachedError
@@ -16,12 +17,17 @@ from ...resources.file_provider import (
16
17
  MAXIMUM_CSV_FILE_LIMIT,
17
18
  )
18
19
  from ...resources import FileProvider
20
+ from ...state import update_types
19
21
 
20
22
  if TYPE_CHECKING:
21
23
  from opentrons.protocol_engine.state.state import StateView
22
24
  from opentrons.protocol_engine.execution import EquipmentHandler
23
25
 
24
26
 
27
+ def _remove_default(s: dict[str, Any]) -> None:
28
+ s.pop("default", None)
29
+
30
+
25
31
  ReadAbsorbanceCommandType = Literal["absorbanceReader/read"]
26
32
 
27
33
 
@@ -29,9 +35,10 @@ class ReadAbsorbanceParams(BaseModel):
29
35
  """Input parameters for an absorbance reading."""
30
36
 
31
37
  moduleId: str = Field(..., description="Unique ID of the Absorbance Reader.")
32
- fileName: Optional[str] = Field(
38
+ fileName: str | SkipJsonSchema[None] = Field(
33
39
  None,
34
40
  description="Optional file name to use when storing the results of a measurement.",
41
+ json_schema_extra=_remove_default,
35
42
  )
36
43
 
37
44
 
@@ -67,6 +74,7 @@ class ReadAbsorbanceImpl(
67
74
  self, params: ReadAbsorbanceParams
68
75
  ) -> SuccessData[ReadAbsorbanceResult]:
69
76
  """Initiate an absorbance measurement."""
77
+ state_update = update_types.StateUpdate()
70
78
  abs_reader_substate = self._state_view.modules.get_absorbance_reader_substate(
71
79
  module_id=params.moduleId
72
80
  )
@@ -117,7 +125,9 @@ class ReadAbsorbanceImpl(
117
125
  )
118
126
  asbsorbance_result[wavelength] = converted_values
119
127
  transform_results.append(
120
- ReadData.construct(wavelength=wavelength, data=converted_values)
128
+ ReadData.model_construct(
129
+ wavelength=wavelength, data=converted_values
130
+ )
121
131
  )
122
132
  # Handle the virtual module case for data creation (all zeroes)
123
133
  elif self._state_view.config.use_virtual_modules:
@@ -131,22 +141,27 @@ class ReadAbsorbanceImpl(
131
141
  )
132
142
  asbsorbance_result[wavelength] = converted_values
133
143
  transform_results.append(
134
- ReadData.construct(wavelength=wavelength, data=converted_values)
144
+ ReadData.model_construct(
145
+ wavelength=wavelength, data=converted_values
146
+ )
135
147
  )
136
148
  else:
137
149
  raise CannotPerformModuleAction(
138
150
  "Plate Reader data cannot be requested with a module that has not been initialized."
139
151
  )
140
152
 
153
+ state_update.set_absorbance_reader_data(
154
+ module_id=abs_reader_substate.module_id, read_result=asbsorbance_result
155
+ )
141
156
  # TODO (cb, 10-17-2024): FILE PROVIDER - Some day we may want to break the file provider behavior into a seperate API function.
142
157
  # When this happens, we probably will to have the change the command results handler we utilize to track file IDs in engine.
143
158
  # Today, the action handler for the FileStore looks for a ReadAbsorbanceResult command action, this will need to be delinked.
144
159
 
145
160
  # Begin interfacing with the file provider if the user provided a filename
146
- file_ids = []
161
+ file_ids: list[str] = []
147
162
  if params.fileName is not None:
148
163
  # Create the Plate Reader Transform
149
- plate_read_result = PlateReaderData.construct(
164
+ plate_read_result = PlateReaderData.model_construct(
150
165
  read_results=transform_results,
151
166
  reference_wavelength=abs_reader_substate.reference_wavelength,
152
167
  start_time=start_time,
@@ -170,12 +185,20 @@ class ReadAbsorbanceImpl(
170
185
  # Return success data to api
171
186
  return SuccessData(
172
187
  public=ReadAbsorbanceResult(
173
- data=asbsorbance_result, fileIds=file_ids
188
+ data=asbsorbance_result,
189
+ fileIds=file_ids,
174
190
  ),
191
+ state_update=state_update,
175
192
  )
176
193
 
194
+ state_update.files_added = update_types.FilesAddedUpdate(file_ids=file_ids)
195
+
177
196
  return SuccessData(
178
- public=ReadAbsorbanceResult(data=asbsorbance_result, fileIds=file_ids),
197
+ public=ReadAbsorbanceResult(
198
+ data=asbsorbance_result,
199
+ fileIds=file_ids,
200
+ ),
201
+ state_update=state_update,
179
202
  )
180
203
 
181
204
 
@@ -0,0 +1,160 @@
1
+ """AirGap in place command request, result, and implementation models."""
2
+
3
+ from __future__ import annotations
4
+ from typing import TYPE_CHECKING, Optional, Type, Union
5
+ from typing_extensions import Literal
6
+
7
+ from opentrons_shared_data.errors.exceptions import PipetteOverpressureError
8
+
9
+ from opentrons.hardware_control import HardwareControlAPI
10
+
11
+ from .pipetting_common import (
12
+ PipetteIdMixin,
13
+ AspirateVolumeMixin,
14
+ FlowRateMixin,
15
+ BaseLiquidHandlingResult,
16
+ OverpressureError,
17
+ )
18
+ from .command import (
19
+ AbstractCommandImpl,
20
+ BaseCommand,
21
+ BaseCommandCreate,
22
+ SuccessData,
23
+ DefinedErrorData,
24
+ )
25
+ from ..errors.error_occurrence import ErrorOccurrence
26
+ from ..errors.exceptions import PipetteNotReadyToAspirateError
27
+ from ..state.update_types import StateUpdate
28
+ from ..types import AspiratedFluid, FluidKind
29
+
30
+ if TYPE_CHECKING:
31
+ from ..execution import PipettingHandler, GantryMover
32
+ from ..resources import ModelUtils
33
+ from ..state.state import StateView
34
+ from ..notes import CommandNoteAdder
35
+
36
+ AirGapInPlaceCommandType = Literal["airGapInPlace"]
37
+
38
+
39
+ class AirGapInPlaceParams(PipetteIdMixin, AspirateVolumeMixin, FlowRateMixin):
40
+ """Payload required to air gap in place."""
41
+
42
+ pass
43
+
44
+
45
+ class AirGapInPlaceResult(BaseLiquidHandlingResult):
46
+ """Result data from the execution of a AirGapInPlace command."""
47
+
48
+ pass
49
+
50
+
51
+ _ExecuteReturn = Union[
52
+ SuccessData[AirGapInPlaceResult],
53
+ DefinedErrorData[OverpressureError],
54
+ ]
55
+
56
+
57
+ class AirGapInPlaceImplementation(
58
+ AbstractCommandImpl[AirGapInPlaceParams, _ExecuteReturn]
59
+ ):
60
+ """AirGapInPlace command implementation."""
61
+
62
+ def __init__(
63
+ self,
64
+ pipetting: PipettingHandler,
65
+ hardware_api: HardwareControlAPI,
66
+ state_view: StateView,
67
+ command_note_adder: CommandNoteAdder,
68
+ model_utils: ModelUtils,
69
+ gantry_mover: GantryMover,
70
+ **kwargs: object,
71
+ ) -> None:
72
+ self._pipetting = pipetting
73
+ self._state_view = state_view
74
+ self._hardware_api = hardware_api
75
+ self._command_note_adder = command_note_adder
76
+ self._model_utils = model_utils
77
+ self._gantry_mover = gantry_mover
78
+
79
+ async def execute(self, params: AirGapInPlaceParams) -> _ExecuteReturn:
80
+ """Air gap without moving the pipette.
81
+
82
+ Raises:
83
+ TipNotAttachedError: if no tip is attached to the pipette.
84
+ PipetteNotReadyToAirGapError: pipette plunger is not ready.
85
+ """
86
+ ready_to_aspirate = self._pipetting.get_is_ready_to_aspirate(
87
+ pipette_id=params.pipetteId,
88
+ )
89
+
90
+ if not ready_to_aspirate:
91
+ raise PipetteNotReadyToAspirateError(
92
+ "Pipette cannot air gap in place because of a previous blow out."
93
+ " The first aspirate following a blow-out must be from a specific well"
94
+ " so the plunger can be reset in a known safe position."
95
+ )
96
+
97
+ state_update = StateUpdate()
98
+
99
+ try:
100
+ current_position = await self._gantry_mover.get_position(params.pipetteId)
101
+ volume = await self._pipetting.aspirate_in_place(
102
+ pipette_id=params.pipetteId,
103
+ volume=params.volume,
104
+ flow_rate=params.flowRate,
105
+ command_note_adder=self._command_note_adder,
106
+ )
107
+ except PipetteOverpressureError as e:
108
+ return DefinedErrorData(
109
+ public=OverpressureError(
110
+ id=self._model_utils.generate_id(),
111
+ createdAt=self._model_utils.get_timestamp(),
112
+ wrappedErrors=[
113
+ ErrorOccurrence.from_failed(
114
+ id=self._model_utils.generate_id(),
115
+ createdAt=self._model_utils.get_timestamp(),
116
+ error=e,
117
+ )
118
+ ],
119
+ errorInfo=(
120
+ {
121
+ "retryLocation": (
122
+ current_position.x,
123
+ current_position.y,
124
+ current_position.z,
125
+ )
126
+ }
127
+ ),
128
+ ),
129
+ state_update=state_update,
130
+ )
131
+ else:
132
+ state_update.set_fluid_aspirated(
133
+ pipette_id=params.pipetteId,
134
+ fluid=AspiratedFluid(kind=FluidKind.AIR, volume=volume),
135
+ )
136
+ return SuccessData(
137
+ public=AirGapInPlaceResult(volume=volume),
138
+ state_update=state_update,
139
+ )
140
+
141
+
142
+ class AirGapInPlace(
143
+ BaseCommand[AirGapInPlaceParams, AirGapInPlaceResult, OverpressureError]
144
+ ):
145
+ """AirGapInPlace command model."""
146
+
147
+ commandType: AirGapInPlaceCommandType = "airGapInPlace"
148
+ params: AirGapInPlaceParams
149
+ result: Optional[AirGapInPlaceResult]
150
+
151
+ _ImplementationCls: Type[AirGapInPlaceImplementation] = AirGapInPlaceImplementation
152
+
153
+
154
+ class AirGapInPlaceCreate(BaseCommandCreate[AirGapInPlaceParams]):
155
+ """AirGapInPlace command request model."""
156
+
157
+ commandType: AirGapInPlaceCommandType = "airGapInPlace"
158
+ params: AirGapInPlaceParams
159
+
160
+ _CommandCls: Type[AirGapInPlace] = AirGapInPlace