@opentrons/shared-data 0.0.1-alpha.19 → 0.0.1-alpha.21

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 (156) hide show
  1. package/lib/{bundle.673284981fd97184260c.js → opentrons-shared-data.js} +2 -2
  2. package/lib/opentrons-shared-data.js.map +1 -0
  3. package/package.json +1 -1
  4. package/webpack.config.js +1 -0
  5. package/js/__tests__/__snapshots__/pipettes.test.ts.snap +0 -5969
  6. package/js/__tests__/deckSchemas.test.ts +0 -87
  7. package/js/__tests__/errors.test.js +0 -21
  8. package/js/__tests__/getAreSlotsAdjacent.test.ts +0 -128
  9. package/js/__tests__/getWellNamePerMultiTip.test.ts +0 -162
  10. package/js/__tests__/labwareDefQuirks.test.ts +0 -37
  11. package/js/__tests__/labwareDefSchemaV1.test.ts +0 -82
  12. package/js/__tests__/labwareDefSchemaV2.test.ts +0 -298
  13. package/js/__tests__/moduleAccessors.test.ts +0 -50
  14. package/js/__tests__/moduleSpecsSchema.test.ts +0 -77
  15. package/js/__tests__/pipetteSchemaV2.test.ts +0 -107
  16. package/js/__tests__/pipetteSpecSchemas.test.ts +0 -48
  17. package/js/__tests__/pipettes.test.ts +0 -58
  18. package/js/__tests__/protocolSchemaV4.test.ts +0 -137
  19. package/js/__tests__/protocolSchemaV5.test.ts +0 -137
  20. package/js/__tests__/protocolSchemaV6.test.ts +0 -132
  21. package/js/__tests__/protocolSchemaV7.test.ts +0 -64
  22. package/js/__tests__/protocolValidation.test.ts +0 -83
  23. package/js/__tests__/sortWells.test.ts +0 -40
  24. package/js/__tests__/splitWellsOnColumn.test.ts +0 -21
  25. package/js/__tests__/validateErrors.test.js +0 -34
  26. package/js/constants.ts +0 -338
  27. package/js/cypressUtils.ts +0 -35
  28. package/js/errors.ts +0 -33
  29. package/js/fixtures.ts +0 -161
  30. package/js/getLabware.ts +0 -154
  31. package/js/gripper.ts +0 -29
  32. package/js/helpers/__tests__/getAdapterName.test.ts +0 -31
  33. package/js/helpers/__tests__/getDeckDefFromLoadedLabware.test.ts +0 -12
  34. package/js/helpers/__tests__/getVectorDifference.test.ts +0 -25
  35. package/js/helpers/__tests__/getVectorSum.test.ts +0 -21
  36. package/js/helpers/__tests__/labwareInference.test.ts +0 -84
  37. package/js/helpers/__tests__/orderWells.test.ts +0 -87
  38. package/js/helpers/__tests__/parseProtocolData.test.ts +0 -165
  39. package/js/helpers/__tests__/volume.test.ts +0 -108
  40. package/js/helpers/__tests__/wellSets.test.ts +0 -352
  41. package/js/helpers/get96Channel384WellPlateWells.ts +0 -44
  42. package/js/helpers/getAddressableAreasInProtocol.ts +0 -59
  43. package/js/helpers/getLoadedLabwareDefinitionsByUri.ts +0 -30
  44. package/js/helpers/getModuleVizDims.ts +0 -118
  45. package/js/helpers/getOccludedSlotCountForModule.ts +0 -13
  46. package/js/helpers/getVectorDifference.ts +0 -12
  47. package/js/helpers/getVectorSum.ts +0 -12
  48. package/js/helpers/getWellNamePerMultiTip.ts +0 -86
  49. package/js/helpers/getWellTotalVolume.ts +0 -16
  50. package/js/helpers/index.ts +0 -347
  51. package/js/helpers/labwareInference.ts +0 -92
  52. package/js/helpers/orderWells.ts +0 -69
  53. package/js/helpers/parseProtocolData.ts +0 -141
  54. package/js/helpers/volume.ts +0 -35
  55. package/js/helpers/wellIsRect.ts +0 -6
  56. package/js/helpers/wellSets.ts +0 -155
  57. package/js/index.ts +0 -14
  58. package/js/labwareTools/__tests__/__snapshots__/createIrregularLabware.test.ts.snap +0 -3
  59. package/js/labwareTools/__tests__/__snapshots__/createLabware.test.ts.snap +0 -3
  60. package/js/labwareTools/__tests__/createDefaultDisplayName.test.ts +0 -111
  61. package/js/labwareTools/__tests__/createIrregularLabware.test.ts +0 -226
  62. package/js/labwareTools/__tests__/createLabware.test.ts +0 -147
  63. package/js/labwareTools/index.ts +0 -452
  64. package/js/modules.ts +0 -97
  65. package/js/pipettes.ts +0 -89
  66. package/js/protocols.ts +0 -290
  67. package/js/schema.ts +0 -80
  68. package/js/scripts/generateDeckLayersFromSVG.js +0 -46
  69. package/js/titleCase.ts +0 -30
  70. package/js/types.ts +0 -600
  71. package/lib/bundle.673284981fd97184260c.js.map +0 -1
  72. package/python/.coveragerc +0 -4
  73. package/python/.flake8 +0 -32
  74. package/python/Config.in +0 -10
  75. package/python/Makefile +0 -134
  76. package/python/Pipfile +0 -28
  77. package/python/Pipfile.lock +0 -645
  78. package/python/buildroot.mk +0 -30
  79. package/python/mypy.ini +0 -41
  80. package/python/opentrons_shared_data/__init__.py +0 -17
  81. package/python/opentrons_shared_data/_version.py +0 -20
  82. package/python/opentrons_shared_data/command/__init__.py +0 -52
  83. package/python/opentrons_shared_data/deck/__init__.py +0 -96
  84. package/python/opentrons_shared_data/deck/dev_types.py +0 -180
  85. package/python/opentrons_shared_data/errors/__init__.py +0 -30
  86. package/python/opentrons_shared_data/errors/categories.py +0 -60
  87. package/python/opentrons_shared_data/errors/codes.py +0 -108
  88. package/python/opentrons_shared_data/errors/exceptions.py +0 -915
  89. package/python/opentrons_shared_data/gripper/__init__.py +0 -63
  90. package/python/opentrons_shared_data/gripper/constants.py +0 -6
  91. package/python/opentrons_shared_data/gripper/gripper_definition.py +0 -101
  92. package/python/opentrons_shared_data/labware/__init__.py +0 -22
  93. package/python/opentrons_shared_data/labware/constants.py +0 -7
  94. package/python/opentrons_shared_data/labware/dev_types.py +0 -140
  95. package/python/opentrons_shared_data/labware/labware_definition.py +0 -328
  96. package/python/opentrons_shared_data/load.py +0 -57
  97. package/python/opentrons_shared_data/module/__init__.py +0 -74
  98. package/python/opentrons_shared_data/module/dev_types.py +0 -141
  99. package/python/opentrons_shared_data/pipette/__init__.py +0 -107
  100. package/python/opentrons_shared_data/pipette/dev_types.py +0 -177
  101. package/python/opentrons_shared_data/pipette/file_operation_helpers.py +0 -37
  102. package/python/opentrons_shared_data/pipette/load_data.py +0 -261
  103. package/python/opentrons_shared_data/pipette/model_constants.py +0 -123
  104. package/python/opentrons_shared_data/pipette/mutable_configurations.py +0 -431
  105. package/python/opentrons_shared_data/pipette/pipette_definition.py +0 -503
  106. package/python/opentrons_shared_data/pipette/pipette_load_name_conversions.py +0 -240
  107. package/python/opentrons_shared_data/pipette/scripts/__init__.py +0 -0
  108. package/python/opentrons_shared_data/pipette/scripts/build_json_script.py +0 -469
  109. package/python/opentrons_shared_data/pipette/scripts/update_configuration_files.py +0 -450
  110. package/python/opentrons_shared_data/pipette/types.py +0 -193
  111. package/python/opentrons_shared_data/protocol/__init__.py +0 -13
  112. package/python/opentrons_shared_data/protocol/constants.py +0 -98
  113. package/python/opentrons_shared_data/protocol/dev_types.py +0 -436
  114. package/python/opentrons_shared_data/protocol/models/__init__.py +0 -48
  115. package/python/opentrons_shared_data/protocol/models/protocol_schema_v6.py +0 -145
  116. package/python/opentrons_shared_data/protocol/models/protocol_schema_v7.py +0 -95
  117. package/python/opentrons_shared_data/protocol/models/protocol_schema_v8.py +0 -110
  118. package/python/opentrons_shared_data/protocol/models/shared_models.py +0 -111
  119. package/python/opentrons_shared_data/py.typed +0 -0
  120. package/python/opentrons_shared_data/robot/__init__.py +0 -33
  121. package/python/opentrons_shared_data/robot/dev_types.py +0 -37
  122. package/python/pytest.ini +0 -2
  123. package/python/setup.cfg +0 -5
  124. package/python/setup.py +0 -179
  125. package/python/tests/__init__.py +0 -1
  126. package/python/tests/conftest.py +0 -0
  127. package/python/tests/deck/__init__.py +0 -0
  128. package/python/tests/deck/test_list_names.py +0 -12
  129. package/python/tests/deck/test_position.py +0 -113
  130. package/python/tests/deck/test_typechecks.py +0 -28
  131. package/python/tests/errors/__init__.py +0 -1
  132. package/python/tests/errors/test_error_completeness.py +0 -19
  133. package/python/tests/errors/test_exceptions.py +0 -74
  134. package/python/tests/gripper/__init__.py +0 -0
  135. package/python/tests/gripper/test_definition.py +0 -30
  136. package/python/tests/gripper/test_load.py +0 -16
  137. package/python/tests/labware/__init__.py +0 -13
  138. package/python/tests/labware/test_typechecks.py +0 -21
  139. package/python/tests/module/__init__.py +0 -20
  140. package/python/tests/module/test_load.py +0 -49
  141. package/python/tests/module/test_typechecks.py +0 -34
  142. package/python/tests/pipette/__init__.py +0 -0
  143. package/python/tests/pipette/test_load_data.py +0 -103
  144. package/python/tests/pipette/test_mutable_configurations.py +0 -266
  145. package/python/tests/pipette/test_pipette_definition.py +0 -183
  146. package/python/tests/pipette/test_pipette_load_name_conversions.py +0 -222
  147. package/python/tests/pipette/test_typechecks.py +0 -50
  148. package/python/tests/pipette/test_validate_schema.py +0 -37
  149. package/python/tests/protocol/__init__.py +0 -15
  150. package/python/tests/protocol/test_protocol_schema_v6.py +0 -107
  151. package/python/tests/protocol/test_protocol_schema_v7.py +0 -34
  152. package/python/tests/protocol/test_protocol_schema_v8.py +0 -20
  153. package/python/tests/protocol/test_typechecks.py +0 -36
  154. package/python/tests/robot/__init__.py +0 -0
  155. package/python/tests/robot/test_typechecks.py +0 -20
  156. /package/lib/{bundle.673284981fd97184260c.js.LICENSE.txt → opentrons-shared-data.js.LICENSE.txt} +0 -0
@@ -1,450 +0,0 @@
1
- """A script for updating pre-existing V2 Pipette configurations."""
2
- import os
3
- import json
4
- import argparse
5
-
6
- from pathlib import Path
7
- from typing import List, Dict, Tuple, Any, Iterator, Type
8
-
9
- from pydantic import BaseModel
10
- from pydantic.main import ModelMetaclass
11
- from enum import Enum
12
-
13
- from opentrons_shared_data import get_shared_data_root
14
-
15
- from ..pipette_definition import (
16
- PipetteConfigurations,
17
- PipetteGeometryDefinition,
18
- PipettePhysicalPropertiesDefinition,
19
- PipetteLiquidPropertiesDefinition,
20
- PipetteModelVersionType,
21
- SupportedTipsDefinition,
22
- )
23
- from ..types import (
24
- PipetteModelType,
25
- PipetteChannelType,
26
- PipetteVersionType,
27
- PipetteTipType,
28
- PipetteModelMajorVersion,
29
- PipetteModelMinorVersion,
30
- LiquidClasses,
31
- )
32
- from ..load_data import _geometry, _physical, _liquid
33
- from ..pipette_load_name_conversions import convert_pipette_model
34
- from ..dev_types import PipetteModel
35
-
36
- """
37
- Instructions:
38
-
39
- To run this script, you must be in `shared-data/python`. To invoke, use the command:
40
-
41
- `pipenv run python -m opentrons_shared_data.pipette.scripts.update_configuration_files`
42
-
43
- If you want to update all files, you can simply use the argument `--update_all_models`.
44
-
45
- Make sure to run `make format-js` afterwards to ensure formatting of the json files
46
- is good.
47
-
48
- *Note* If you are adding a brand-new key, you MUST update the pydantic models
49
- found in `python/pipette/pipette_definition.py` before running this script.
50
-
51
- *Note* When you are entering in your data, please utilize the exact type. I.e. if it's a
52
- list, you must input the list like: [1, 2, 3] or if it's a dict, like: {"data": 1}..
53
-
54
- For now, we do not support updating pipetting functions in this script.
55
- """
56
-
57
- ROOT = get_shared_data_root() / "pipette" / "definitions" / "2"
58
- NOZZLE_LOCATION_CONFIGS = ["nozzle_offset", "nozzle_map"]
59
-
60
-
61
- def _change_to_camel_case(c: str) -> str:
62
- # Tiny helper function to convert to camelCase.
63
- config_name = c.split("_")
64
- if len(config_name) == 1:
65
- return config_name[0]
66
- return f"{config_name[0]}" + "".join(s.capitalize() for s in config_name[1::])
67
-
68
-
69
- def list_configuration_keys() -> Tuple[List[str], Dict[int, str]]:
70
- """List out the model keys available to modify at the top level."""
71
- lookup = {i: v for (i, v) in enumerate(PipetteConfigurations.__fields__)}
72
- return [
73
- f"{i}: {v}" for (i, v) in enumerate(PipetteConfigurations.__fields__)
74
- ], lookup
75
-
76
-
77
- def list_available_enum(enum_type: Type[Enum]) -> List[str]:
78
- """List available pipette models"""
79
- return [f"{i}: {v}" for (i, v) in enumerate(enum_type)] # type: ignore[var-annotated]
80
-
81
-
82
- def handle_subclass_model(
83
- top_level_configuration: List[str], base_model: BaseModel, is_basemodel: bool
84
- ) -> List[str]:
85
- """Handle sub-classed basemodels and update the top level model as necessary."""
86
- if is_basemodel:
87
- if base_model.__fields__ == SupportedTipsDefinition.__fields__:
88
- # pydantic does something weird with the types in ModelFields so
89
- # we cannot use isinstance checks to confirm if the base model
90
- # is a supported tips definition
91
- print(f"choose {PipetteTipType.__name__}:")
92
- for row in list_available_enum(PipetteTipType):
93
- print(f"\t{row}")
94
- tip_type = list(PipetteTipType)[
95
- int(input("select the tip volume size to modify"))
96
- ]
97
- top_level_configuration.append(tip_type.name)
98
-
99
- lookup = {i: v for (i, v) in enumerate(base_model.__fields__)}
100
- config_list = [f"{i}: {v}" for (i, v) in enumerate(base_model.__fields__)]
101
- print(f"you selected the basemodel {base_model.__name__}:") # type: ignore[attr-defined]
102
- for row in config_list:
103
- print(f"\t{row}")
104
-
105
- configuration_to_update = lookup[
106
- int(input("select a specific configuration from above\n"))
107
- ]
108
- field_type = base_model.__fields__[configuration_to_update].type_
109
- is_basemodel = isinstance(field_type, ModelMetaclass)
110
-
111
- top_level_configuration.append(configuration_to_update)
112
- return handle_subclass_model(top_level_configuration, field_type, is_basemodel)
113
- else:
114
- return top_level_configuration
115
-
116
-
117
- def check_from_version(version: str) -> str:
118
- """Check that the version requested is supported in the system."""
119
- version_int = [int(v) for v in version.split(".")]
120
- if version_int[0] not in PipetteModelMajorVersion:
121
- raise ValueError(f"Major version {version_int[0]} is not supported.")
122
- if version_int[1] not in PipetteModelMinorVersion:
123
- raise ValueError(f"Minor version {version_int[1]} is not supported.")
124
- return version
125
-
126
-
127
- def save_data_to_file(
128
- directorypath: Path,
129
- file_name: str,
130
- data: Dict[str, Any],
131
- ) -> None:
132
- """
133
- Function used to save data to a file
134
- """
135
- directorypath.mkdir(parents=True, exist_ok=True)
136
- filepath = directorypath / f"{file_name}.json"
137
- with open(filepath, "w") as f:
138
- json.dump(data, f, indent=2)
139
-
140
-
141
- def update(
142
- dict_to_update: Dict[str, Any], iter_of_configs: Iterator[str], value_to_update: Any
143
- ) -> Dict[str, Any]:
144
- """
145
- Recursively update the given dictionary to ensure no data is lost when updating.
146
- """
147
- next_key = next(iter_of_configs, None)
148
- if next_key and isinstance(dict_to_update.get(next_key), dict):
149
- dict_to_update[next_key] = update(
150
- dict_to_update.get(next_key, {}), iter_of_configs, value_to_update
151
- )
152
- elif next_key:
153
- dict_to_update[next_key] = value_to_update
154
- return dict_to_update
155
-
156
-
157
- def build_nozzle_map(
158
- nozzle_offset: List[float], channels: PipetteChannelType
159
- ) -> Dict[str, List[float]]:
160
- Y_OFFSET = -9
161
- X_OFFSET = 9
162
- if channels == PipetteChannelType.SINGLE_CHANNEL:
163
- return {"A1": nozzle_offset}
164
- elif channels == PipetteChannelType.EIGHT_CHANNEL:
165
- return {
166
- f"{chr(ord('A') + 1*row)}1": [
167
- nozzle_offset[0],
168
- nozzle_offset[1] + Y_OFFSET * row,
169
- nozzle_offset[2],
170
- ]
171
- for row in range(8)
172
- }
173
- elif channels == PipetteChannelType.NINETY_SIX_CHANNEL:
174
- return {
175
- f"{chr(ord('A') + 1*row)}{1 + 1*col}": [
176
- nozzle_offset[0] + X_OFFSET * col,
177
- nozzle_offset[1] + Y_OFFSET * row,
178
- nozzle_offset[2],
179
- ]
180
- for row in range(8)
181
- for col in range(12)
182
- }
183
- raise ValueError(f"Unsupported channel type {channels}")
184
-
185
-
186
- def load_and_update_file_from_config(
187
- config_to_update: List[str],
188
- value_to_update: Any,
189
- model_to_update: PipetteModelVersionType,
190
- ) -> None:
191
- """Update the requested config and save to disk.
192
-
193
- Load the requested config sub type (physical, geometry or liquid). Then
194
- update the current file and save to disk.
195
-
196
- """
197
- camel_list_to_update = iter([_change_to_camel_case(i) for i in config_to_update])
198
-
199
- if config_to_update[0] in PipetteGeometryDefinition.__fields__:
200
- geometry = _geometry(
201
- model_to_update.pipette_channels,
202
- model_to_update.pipette_type,
203
- model_to_update.pipette_version,
204
- )
205
- if config_to_update[0] == "nozzle_map":
206
- nozzle_to_use = (
207
- value_to_update if value_to_update else geometry["nozzleOffset"]
208
- )
209
- geometry["nozzleMap"] = build_nozzle_map(
210
- nozzle_to_use, model_to_update.pipette_channels
211
- )
212
- elif config_to_update[0] == "nozzle_offset":
213
- geometry["nozzleMap"] = build_nozzle_map(
214
- value_to_update, model_to_update.pipette_channels
215
- )
216
- geometry["nozzleOffset"] = value_to_update
217
- else:
218
- geometry = update(geometry, camel_list_to_update, value_to_update)
219
- PipetteGeometryDefinition.parse_obj(geometry)
220
-
221
- filepath = (
222
- ROOT
223
- / "geometry"
224
- / model_to_update.pipette_channels.name.lower()
225
- / model_to_update.pipette_type.value
226
- )
227
- save_data_to_file(
228
- filepath,
229
- f"{model_to_update.pipette_version.major}_{model_to_update.pipette_version.minor}",
230
- geometry,
231
- )
232
- elif config_to_update[0] in PipettePhysicalPropertiesDefinition.__fields__:
233
- physical = _physical(
234
- model_to_update.pipette_channels,
235
- model_to_update.pipette_type,
236
- model_to_update.pipette_version,
237
- )
238
-
239
- physical = update(physical, camel_list_to_update, value_to_update)
240
-
241
- PipettePhysicalPropertiesDefinition.parse_obj(physical)
242
- filepath = (
243
- ROOT
244
- / "general"
245
- / model_to_update.pipette_channels.name.lower()
246
- / model_to_update.pipette_type.value
247
- )
248
- save_data_to_file(
249
- filepath,
250
- f"{model_to_update.pipette_version.major}_{model_to_update.pipette_version.minor}",
251
- physical,
252
- )
253
- elif config_to_update[0] == "liquid_properties":
254
- next(camel_list_to_update)
255
- liquid = _liquid(
256
- model_to_update.pipette_channels,
257
- model_to_update.pipette_type,
258
- model_to_update.pipette_version,
259
- )
260
-
261
- print(
262
- "Please select what liquid class you wish to update.\n If you want to update all liquid classes then type 'all'.\n"
263
- )
264
-
265
- print(f"choose {LiquidClasses.__name__} or type 'all':")
266
- for row in list_available_enum(LiquidClasses):
267
- print(f"\t{row}")
268
- liquid_classes = input("liquid class: ")
269
- if liquid_classes == "all":
270
- for c in LiquidClasses:
271
- liquid = update(
272
- liquid[c.name.lower()], camel_list_to_update, value_to_update
273
- )
274
-
275
- PipetteLiquidPropertiesDefinition.parse_obj(liquid)
276
- filepath = (
277
- ROOT
278
- / "liquid"
279
- / model_to_update.pipette_channels.name.lower()
280
- / model_to_update.pipette_type.value
281
- / c.name.lower()
282
- )
283
- save_data_to_file(
284
- filepath,
285
- f"{model_to_update.pipette_version.major}_{model_to_update.pipette_version.minor}",
286
- liquid,
287
- )
288
- else:
289
- lc = list(LiquidClasses)[int(liquid_classes)]
290
- liquid = update(
291
- liquid[lc.name.lower()], camel_list_to_update, value_to_update
292
- )
293
- PipetteLiquidPropertiesDefinition.parse_obj(liquid)
294
-
295
- filepath = (
296
- ROOT
297
- / "liquid"
298
- / model_to_update.pipette_channels.name.lower()
299
- / model_to_update.pipette_type.value
300
- / lc.name.lower()
301
- )
302
- save_data_to_file(
303
- filepath,
304
- f"{model_to_update.pipette_version.major}_{model_to_update.pipette_version.minor}",
305
- liquid,
306
- )
307
- else:
308
- raise KeyError(
309
- f"{config_to_update} is not saved to a file. Check `pipette_definition.py` for more information."
310
- )
311
-
312
-
313
- def _update_single_model(configuration_to_update: List[str]) -> None:
314
- """Helper function to update single model."""
315
- print(f"choose {PipetteModelType.__name__}:")
316
- for row in list_available_enum(PipetteModelType):
317
- print(f"\t{row}")
318
- model = list(PipetteModelType)[int(input("Please select from above\n"))]
319
-
320
- print(f"choose {PipetteChannelType.__name__}:")
321
- for row in list_available_enum(PipetteChannelType):
322
- print(f"\t{row}")
323
- channels = list(PipetteChannelType)[int(input("Please select from above\n"))]
324
-
325
- version = PipetteVersionType.convert_from_float(
326
- float(check_from_version(input("Please input the version of the model\n")))
327
- )
328
-
329
- built_model: PipetteModel = PipetteModel(
330
- f"{model.name}_{str(channels)}_v{version.major}.{version.minor}"
331
- )
332
-
333
- if configuration_to_update[0] == NOZZLE_LOCATION_CONFIGS[1]:
334
- print(
335
- "You selected nozzle_map to edit. If you wish to update the nozzle offset, enter it on the next line.\n"
336
- )
337
- print("Otherwise, please type 'null' on the next line.\n")
338
-
339
- value_to_update = json.loads(
340
- input(
341
- f"Please select what you would like to update {configuration_to_update[-1]} to for {built_model}\n"
342
- )
343
- )
344
-
345
- model_version = convert_pipette_model(built_model)
346
-
347
- load_and_update_file_from_config(
348
- configuration_to_update, value_to_update, model_version
349
- )
350
-
351
-
352
- def _update_all_models(configuration_to_update: List[str]) -> None:
353
- paths_to_validate = ROOT / "general"
354
- _channel_model_str = {
355
- "single_channel": "single",
356
- "ninety_six_channel": "96",
357
- "eight_channel": "multi",
358
- }
359
-
360
- for channel_dir in os.listdir(paths_to_validate):
361
- for model_dir in os.listdir(paths_to_validate / channel_dir):
362
- for version_file in os.listdir(paths_to_validate / channel_dir / model_dir):
363
- version_list = version_file.split(".json")[0].split("_")
364
- built_model: PipetteModel = PipetteModel(
365
- f"{model_dir}_{_channel_model_str[channel_dir]}_v{version_list[0]}.{version_list[1]}"
366
- )
367
-
368
- if configuration_to_update[0] == NOZZLE_LOCATION_CONFIGS[1]:
369
- print(
370
- "You selected nozzle_map to edit. If you wish to update the nozzle offset, enter it on the next line.\n"
371
- )
372
- print("Otherwise, please type 'null' on the next line.\n")
373
-
374
- value_to_update = json.loads(
375
- input(
376
- f"Please select what you would like to update {configuration_to_update} to for {built_model}\n"
377
- )
378
- )
379
-
380
- model_version = convert_pipette_model(built_model)
381
- load_and_update_file_from_config(
382
- configuration_to_update, value_to_update, model_version
383
- )
384
-
385
-
386
- def determine_models_to_update(update_all_models: bool) -> None:
387
- try:
388
- while True:
389
- print(f"choose {PipetteConfigurations.__name__}:")
390
- config_list, table_lookup = list_configuration_keys()
391
- for row in config_list:
392
- print(f"\t{row}")
393
-
394
- configuration_to_update = [
395
- table_lookup[int(input("select a configuration from above\n"))]
396
- ]
397
-
398
- if configuration_to_update[0] == NOZZLE_LOCATION_CONFIGS[0]:
399
- print(
400
- f"NOTE: updating the {configuration_to_update[0]} will automatically update the {NOZZLE_LOCATION_CONFIGS[1]}\n"
401
- )
402
-
403
- field_type = PipetteConfigurations.__fields__[
404
- configuration_to_update[0]
405
- ].type_
406
- is_basemodel = isinstance(field_type, ModelMetaclass)
407
-
408
- configuration_to_update = handle_subclass_model(
409
- configuration_to_update, field_type, is_basemodel
410
- )
411
- if update_all_models:
412
- _update_all_models(configuration_to_update)
413
- else:
414
- _update_single_model(configuration_to_update)
415
- except KeyboardInterrupt:
416
- print("Finished updating! Validate that your files updated successfully.")
417
-
418
-
419
- def main() -> None:
420
- """Entry point."""
421
- parser = argparse.ArgumentParser(
422
- description="96 channel tip handling testing script."
423
- )
424
- parser.add_argument(
425
- "--update_all_models",
426
- type=bool,
427
- help="update all",
428
- default=False,
429
- )
430
-
431
- args = parser.parse_args()
432
-
433
- determine_models_to_update(args.update_all_models)
434
-
435
-
436
- if __name__ == "__main__":
437
- """
438
- A script to automate building a pipette configuration definition.
439
-
440
- This script can either perform migrations from a v1 -> v2 schema format
441
- or build a brand new script from scratch.
442
-
443
- When building a new pipette configuration model, you will either need
444
- to provide CSVs or use command line inputs.
445
-
446
- If you choose CSVs you will need one CSV for the general pipette configuration
447
- data (such as pipette model or number of channels) and one for every tip
448
- type that this pipette model can support.
449
- """
450
- main()
@@ -1,193 +0,0 @@
1
- import enum
2
- from dataclasses import dataclass
3
- from typing import Union, Dict, Mapping, Tuple, cast
4
- from typing_extensions import Literal
5
-
6
- """Pipette Definition V2 Types"""
7
-
8
- # Needed for Int Comparison. Keeping it next to
9
- # the Literal type for ease of readability
10
- PipetteModelMajorVersion = [1, 2, 3]
11
- PipetteModelMinorVersion = [0, 1, 2, 3, 4, 5, 6]
12
-
13
- # TODO Literals are only good for writing down
14
- # exact values. Is there a better typing mechanism
15
- # so we don't need to keep track of versions in two
16
- # different places?
17
- PipetteModelMajorVersionType = Literal[1, 2, 3]
18
- PipetteModelMinorVersionType = Literal[0, 1, 2, 3, 4, 5, 6]
19
-
20
-
21
- class LiquidClasses(enum.Enum):
22
- default = enum.auto()
23
- lowVolumeDefault = enum.auto()
24
-
25
-
26
- class PipetteTipType(enum.Enum):
27
- t10 = 10
28
- t20 = 20
29
- t50 = 50
30
- t200 = 200
31
- t300 = 300
32
- t1000 = 1000
33
-
34
- @classmethod
35
- def check_and_return_type(
36
- cls, working_volume: int, maximum_volume: int
37
- ) -> "PipetteTipType":
38
- try:
39
- return cls(working_volume)
40
- except ValueError:
41
- return cls(maximum_volume)
42
-
43
-
44
- class PipetteChannelType(int, enum.Enum):
45
- SINGLE_CHANNEL = 1
46
- EIGHT_CHANNEL = 8
47
- NINETY_SIX_CHANNEL = 96
48
-
49
- def __str__(self) -> str:
50
- if self.value == 96:
51
- return "96"
52
- elif self.value == 8:
53
- return "multi"
54
- else:
55
- return "single"
56
-
57
-
58
- class PipetteModelType(enum.Enum):
59
- p10 = "p10"
60
- p20 = "p20"
61
- p50 = "p50"
62
- p300 = "p300"
63
- p1000 = "p1000"
64
-
65
-
66
- class PipetteGenerationType(enum.Enum):
67
- GEN1 = "GEN1"
68
- GEN2 = "GEN2"
69
- FLEX = "FLEX"
70
-
71
-
72
- @dataclass(frozen=True)
73
- class PipetteVersionType:
74
- major: PipetteModelMajorVersionType
75
- minor: PipetteModelMinorVersionType
76
-
77
- @classmethod
78
- def convert_from_float(cls, version: float) -> "PipetteVersionType":
79
- major = cast(PipetteModelMajorVersionType, int(version // 1))
80
- minor = cast(PipetteModelMinorVersionType, int(round((version % 1), 2) * 10))
81
- return cls(major=major, minor=minor)
82
-
83
- def __str__(self) -> str:
84
- if self.major == 1 and self.minor == 0:
85
- # Maintain the format of V1 pipettes that
86
- # do not contain a minor version at all.
87
- return f"{self.major}"
88
- else:
89
- return f"{self.major}.{self.minor}"
90
-
91
- @property
92
- def as_tuple(
93
- self,
94
- ) -> Tuple[PipetteModelMajorVersionType, PipetteModelMinorVersionType]:
95
- return (self.major, self.minor)
96
-
97
-
98
- """Mutable Configs Types"""
99
-
100
-
101
- class Quirks(enum.Enum):
102
- pickupTipShake = "pickupTipShake"
103
- dropTipShake = "dropTipShake"
104
- doubleDropTip = "doubleDropTip"
105
- needsUnstick = "needsUnstick"
106
-
107
-
108
- class AvailableUnits(enum.Enum):
109
- mm = "mm"
110
- amps = "amps"
111
- speed = "mm/s"
112
- presses = "presses"
113
-
114
-
115
- @dataclass
116
- class RobotMountConfigs:
117
- stepsPerMM: float
118
- homePosition: float
119
- travelDistance: float
120
-
121
-
122
- @dataclass
123
- class MutableConfig:
124
- value: Union[int, float]
125
- default: Union[int, float]
126
- units: AvailableUnits
127
- type: str
128
- min: float
129
- max: float
130
- name: str
131
-
132
- @classmethod
133
- def build(
134
- cls,
135
- value: Union[int, float],
136
- default: Union[int, float],
137
- units: str,
138
- type: str,
139
- min: float,
140
- max: float,
141
- name: str,
142
- ) -> "MutableConfig":
143
- if units == "mm/sec":
144
- units = "mm/s"
145
- return cls(
146
- value=value,
147
- default=default,
148
- units=AvailableUnits(units),
149
- type=type,
150
- min=min,
151
- max=max,
152
- name=name,
153
- )
154
-
155
- def validate_and_add(self, new_value: Union[int, float]) -> None:
156
- if new_value < self.min or new_value > self.max:
157
- raise ValueError(f"{self.name} out of range with {new_value}")
158
- self.value = new_value
159
-
160
- def dict_for_encode(self) -> Dict[str, Union[int, float, str]]:
161
- return {
162
- "value": self.value,
163
- "default": self.default,
164
- "units": self.units.value,
165
- "type": self.type,
166
- "min": self.min,
167
- "max": self.max,
168
- }
169
-
170
-
171
- @dataclass
172
- class QuirkConfig:
173
- value: bool
174
- name: Quirks
175
-
176
- @classmethod
177
- def validate_and_build(cls, name: str, value: bool) -> "QuirkConfig":
178
- quirk_name = Quirks(name)
179
- cls.validate(name, value)
180
- return cls(value=value, name=quirk_name)
181
-
182
- @classmethod
183
- def validate(cls, name: str, value: bool) -> None:
184
- if not isinstance(value, bool):
185
- raise ValueError(f"{value} is invalid for {name}")
186
-
187
- def dict_for_encode(self) -> bool:
188
- return self.value
189
-
190
-
191
- TypeOverrides = Mapping[str, Union[float, bool, None]]
192
-
193
- OverrideType = Dict[str, Union[Dict[str, QuirkConfig], MutableConfig, str]]
@@ -1,13 +0,0 @@
1
- """
2
- opentrons_shared_data.protocol: types and bindings for json protocols
3
- """
4
- import json
5
- from typing import Any, NewType, Dict
6
-
7
- from .. import load_shared_data
8
-
9
- Schema = NewType("Schema", Dict[str, Any])
10
-
11
-
12
- def load_schema(version: int) -> "Schema":
13
- return json.loads(load_shared_data(f"protocol/schemas/{version}.json"))