@opentrons/shared-data 0.0.1-alpha.20 → 0.1.0-alpha.0

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 (154) hide show
  1. package/Makefile +1 -1
  2. package/lib/opentrons-shared-data.js +1 -1
  3. package/lib/opentrons-shared-data.js.map +1 -1
  4. package/package.json +1 -1
  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/python/.coveragerc +0 -4
  72. package/python/.flake8 +0 -32
  73. package/python/Config.in +0 -10
  74. package/python/Makefile +0 -134
  75. package/python/Pipfile +0 -28
  76. package/python/Pipfile.lock +0 -645
  77. package/python/buildroot.mk +0 -30
  78. package/python/mypy.ini +0 -41
  79. package/python/opentrons_shared_data/__init__.py +0 -17
  80. package/python/opentrons_shared_data/_version.py +0 -20
  81. package/python/opentrons_shared_data/command/__init__.py +0 -52
  82. package/python/opentrons_shared_data/deck/__init__.py +0 -96
  83. package/python/opentrons_shared_data/deck/dev_types.py +0 -180
  84. package/python/opentrons_shared_data/errors/__init__.py +0 -30
  85. package/python/opentrons_shared_data/errors/categories.py +0 -60
  86. package/python/opentrons_shared_data/errors/codes.py +0 -108
  87. package/python/opentrons_shared_data/errors/exceptions.py +0 -915
  88. package/python/opentrons_shared_data/gripper/__init__.py +0 -63
  89. package/python/opentrons_shared_data/gripper/constants.py +0 -6
  90. package/python/opentrons_shared_data/gripper/gripper_definition.py +0 -101
  91. package/python/opentrons_shared_data/labware/__init__.py +0 -22
  92. package/python/opentrons_shared_data/labware/constants.py +0 -7
  93. package/python/opentrons_shared_data/labware/dev_types.py +0 -140
  94. package/python/opentrons_shared_data/labware/labware_definition.py +0 -328
  95. package/python/opentrons_shared_data/load.py +0 -57
  96. package/python/opentrons_shared_data/module/__init__.py +0 -74
  97. package/python/opentrons_shared_data/module/dev_types.py +0 -141
  98. package/python/opentrons_shared_data/pipette/__init__.py +0 -107
  99. package/python/opentrons_shared_data/pipette/dev_types.py +0 -177
  100. package/python/opentrons_shared_data/pipette/file_operation_helpers.py +0 -37
  101. package/python/opentrons_shared_data/pipette/load_data.py +0 -261
  102. package/python/opentrons_shared_data/pipette/model_constants.py +0 -123
  103. package/python/opentrons_shared_data/pipette/mutable_configurations.py +0 -431
  104. package/python/opentrons_shared_data/pipette/pipette_definition.py +0 -503
  105. package/python/opentrons_shared_data/pipette/pipette_load_name_conversions.py +0 -240
  106. package/python/opentrons_shared_data/pipette/scripts/__init__.py +0 -0
  107. package/python/opentrons_shared_data/pipette/scripts/build_json_script.py +0 -469
  108. package/python/opentrons_shared_data/pipette/scripts/update_configuration_files.py +0 -450
  109. package/python/opentrons_shared_data/pipette/types.py +0 -193
  110. package/python/opentrons_shared_data/protocol/__init__.py +0 -13
  111. package/python/opentrons_shared_data/protocol/constants.py +0 -98
  112. package/python/opentrons_shared_data/protocol/dev_types.py +0 -436
  113. package/python/opentrons_shared_data/protocol/models/__init__.py +0 -48
  114. package/python/opentrons_shared_data/protocol/models/protocol_schema_v6.py +0 -145
  115. package/python/opentrons_shared_data/protocol/models/protocol_schema_v7.py +0 -95
  116. package/python/opentrons_shared_data/protocol/models/protocol_schema_v8.py +0 -110
  117. package/python/opentrons_shared_data/protocol/models/shared_models.py +0 -111
  118. package/python/opentrons_shared_data/py.typed +0 -0
  119. package/python/opentrons_shared_data/robot/__init__.py +0 -33
  120. package/python/opentrons_shared_data/robot/dev_types.py +0 -37
  121. package/python/pytest.ini +0 -2
  122. package/python/setup.cfg +0 -5
  123. package/python/setup.py +0 -179
  124. package/python/tests/__init__.py +0 -1
  125. package/python/tests/conftest.py +0 -0
  126. package/python/tests/deck/__init__.py +0 -0
  127. package/python/tests/deck/test_list_names.py +0 -12
  128. package/python/tests/deck/test_position.py +0 -113
  129. package/python/tests/deck/test_typechecks.py +0 -28
  130. package/python/tests/errors/__init__.py +0 -1
  131. package/python/tests/errors/test_error_completeness.py +0 -19
  132. package/python/tests/errors/test_exceptions.py +0 -74
  133. package/python/tests/gripper/__init__.py +0 -0
  134. package/python/tests/gripper/test_definition.py +0 -30
  135. package/python/tests/gripper/test_load.py +0 -16
  136. package/python/tests/labware/__init__.py +0 -13
  137. package/python/tests/labware/test_typechecks.py +0 -21
  138. package/python/tests/module/__init__.py +0 -20
  139. package/python/tests/module/test_load.py +0 -49
  140. package/python/tests/module/test_typechecks.py +0 -34
  141. package/python/tests/pipette/__init__.py +0 -0
  142. package/python/tests/pipette/test_load_data.py +0 -103
  143. package/python/tests/pipette/test_mutable_configurations.py +0 -266
  144. package/python/tests/pipette/test_pipette_definition.py +0 -183
  145. package/python/tests/pipette/test_pipette_load_name_conversions.py +0 -222
  146. package/python/tests/pipette/test_typechecks.py +0 -50
  147. package/python/tests/pipette/test_validate_schema.py +0 -37
  148. package/python/tests/protocol/__init__.py +0 -15
  149. package/python/tests/protocol/test_protocol_schema_v6.py +0 -107
  150. package/python/tests/protocol/test_protocol_schema_v7.py +0 -34
  151. package/python/tests/protocol/test_protocol_schema_v8.py +0 -20
  152. package/python/tests/protocol/test_typechecks.py +0 -36
  153. package/python/tests/robot/__init__.py +0 -0
  154. package/python/tests/robot/test_typechecks.py +0 -20
@@ -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"))