@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.
- package/Makefile +1 -1
- package/lib/opentrons-shared-data.js +1 -1
- package/lib/opentrons-shared-data.js.map +1 -1
- package/package.json +1 -1
- package/js/__tests__/__snapshots__/pipettes.test.ts.snap +0 -5969
- package/js/__tests__/deckSchemas.test.ts +0 -87
- package/js/__tests__/errors.test.js +0 -21
- package/js/__tests__/getAreSlotsAdjacent.test.ts +0 -128
- package/js/__tests__/getWellNamePerMultiTip.test.ts +0 -162
- package/js/__tests__/labwareDefQuirks.test.ts +0 -37
- package/js/__tests__/labwareDefSchemaV1.test.ts +0 -82
- package/js/__tests__/labwareDefSchemaV2.test.ts +0 -298
- package/js/__tests__/moduleAccessors.test.ts +0 -50
- package/js/__tests__/moduleSpecsSchema.test.ts +0 -77
- package/js/__tests__/pipetteSchemaV2.test.ts +0 -107
- package/js/__tests__/pipetteSpecSchemas.test.ts +0 -48
- package/js/__tests__/pipettes.test.ts +0 -58
- package/js/__tests__/protocolSchemaV4.test.ts +0 -137
- package/js/__tests__/protocolSchemaV5.test.ts +0 -137
- package/js/__tests__/protocolSchemaV6.test.ts +0 -132
- package/js/__tests__/protocolSchemaV7.test.ts +0 -64
- package/js/__tests__/protocolValidation.test.ts +0 -83
- package/js/__tests__/sortWells.test.ts +0 -40
- package/js/__tests__/splitWellsOnColumn.test.ts +0 -21
- package/js/__tests__/validateErrors.test.js +0 -34
- package/js/constants.ts +0 -338
- package/js/cypressUtils.ts +0 -35
- package/js/errors.ts +0 -33
- package/js/fixtures.ts +0 -161
- package/js/getLabware.ts +0 -154
- package/js/gripper.ts +0 -29
- package/js/helpers/__tests__/getAdapterName.test.ts +0 -31
- package/js/helpers/__tests__/getDeckDefFromLoadedLabware.test.ts +0 -12
- package/js/helpers/__tests__/getVectorDifference.test.ts +0 -25
- package/js/helpers/__tests__/getVectorSum.test.ts +0 -21
- package/js/helpers/__tests__/labwareInference.test.ts +0 -84
- package/js/helpers/__tests__/orderWells.test.ts +0 -87
- package/js/helpers/__tests__/parseProtocolData.test.ts +0 -165
- package/js/helpers/__tests__/volume.test.ts +0 -108
- package/js/helpers/__tests__/wellSets.test.ts +0 -352
- package/js/helpers/get96Channel384WellPlateWells.ts +0 -44
- package/js/helpers/getAddressableAreasInProtocol.ts +0 -59
- package/js/helpers/getLoadedLabwareDefinitionsByUri.ts +0 -30
- package/js/helpers/getModuleVizDims.ts +0 -118
- package/js/helpers/getOccludedSlotCountForModule.ts +0 -13
- package/js/helpers/getVectorDifference.ts +0 -12
- package/js/helpers/getVectorSum.ts +0 -12
- package/js/helpers/getWellNamePerMultiTip.ts +0 -86
- package/js/helpers/getWellTotalVolume.ts +0 -16
- package/js/helpers/index.ts +0 -347
- package/js/helpers/labwareInference.ts +0 -92
- package/js/helpers/orderWells.ts +0 -69
- package/js/helpers/parseProtocolData.ts +0 -141
- package/js/helpers/volume.ts +0 -35
- package/js/helpers/wellIsRect.ts +0 -6
- package/js/helpers/wellSets.ts +0 -155
- package/js/index.ts +0 -14
- package/js/labwareTools/__tests__/__snapshots__/createIrregularLabware.test.ts.snap +0 -3
- package/js/labwareTools/__tests__/__snapshots__/createLabware.test.ts.snap +0 -3
- package/js/labwareTools/__tests__/createDefaultDisplayName.test.ts +0 -111
- package/js/labwareTools/__tests__/createIrregularLabware.test.ts +0 -226
- package/js/labwareTools/__tests__/createLabware.test.ts +0 -147
- package/js/labwareTools/index.ts +0 -452
- package/js/modules.ts +0 -97
- package/js/pipettes.ts +0 -89
- package/js/protocols.ts +0 -290
- package/js/schema.ts +0 -80
- package/js/scripts/generateDeckLayersFromSVG.js +0 -46
- package/js/titleCase.ts +0 -30
- package/js/types.ts +0 -600
- package/python/.coveragerc +0 -4
- package/python/.flake8 +0 -32
- package/python/Config.in +0 -10
- package/python/Makefile +0 -134
- package/python/Pipfile +0 -28
- package/python/Pipfile.lock +0 -645
- package/python/buildroot.mk +0 -30
- package/python/mypy.ini +0 -41
- package/python/opentrons_shared_data/__init__.py +0 -17
- package/python/opentrons_shared_data/_version.py +0 -20
- package/python/opentrons_shared_data/command/__init__.py +0 -52
- package/python/opentrons_shared_data/deck/__init__.py +0 -96
- package/python/opentrons_shared_data/deck/dev_types.py +0 -180
- package/python/opentrons_shared_data/errors/__init__.py +0 -30
- package/python/opentrons_shared_data/errors/categories.py +0 -60
- package/python/opentrons_shared_data/errors/codes.py +0 -108
- package/python/opentrons_shared_data/errors/exceptions.py +0 -915
- package/python/opentrons_shared_data/gripper/__init__.py +0 -63
- package/python/opentrons_shared_data/gripper/constants.py +0 -6
- package/python/opentrons_shared_data/gripper/gripper_definition.py +0 -101
- package/python/opentrons_shared_data/labware/__init__.py +0 -22
- package/python/opentrons_shared_data/labware/constants.py +0 -7
- package/python/opentrons_shared_data/labware/dev_types.py +0 -140
- package/python/opentrons_shared_data/labware/labware_definition.py +0 -328
- package/python/opentrons_shared_data/load.py +0 -57
- package/python/opentrons_shared_data/module/__init__.py +0 -74
- package/python/opentrons_shared_data/module/dev_types.py +0 -141
- package/python/opentrons_shared_data/pipette/__init__.py +0 -107
- package/python/opentrons_shared_data/pipette/dev_types.py +0 -177
- package/python/opentrons_shared_data/pipette/file_operation_helpers.py +0 -37
- package/python/opentrons_shared_data/pipette/load_data.py +0 -261
- package/python/opentrons_shared_data/pipette/model_constants.py +0 -123
- package/python/opentrons_shared_data/pipette/mutable_configurations.py +0 -431
- package/python/opentrons_shared_data/pipette/pipette_definition.py +0 -503
- package/python/opentrons_shared_data/pipette/pipette_load_name_conversions.py +0 -240
- package/python/opentrons_shared_data/pipette/scripts/__init__.py +0 -0
- package/python/opentrons_shared_data/pipette/scripts/build_json_script.py +0 -469
- package/python/opentrons_shared_data/pipette/scripts/update_configuration_files.py +0 -450
- package/python/opentrons_shared_data/pipette/types.py +0 -193
- package/python/opentrons_shared_data/protocol/__init__.py +0 -13
- package/python/opentrons_shared_data/protocol/constants.py +0 -98
- package/python/opentrons_shared_data/protocol/dev_types.py +0 -436
- package/python/opentrons_shared_data/protocol/models/__init__.py +0 -48
- package/python/opentrons_shared_data/protocol/models/protocol_schema_v6.py +0 -145
- package/python/opentrons_shared_data/protocol/models/protocol_schema_v7.py +0 -95
- package/python/opentrons_shared_data/protocol/models/protocol_schema_v8.py +0 -110
- package/python/opentrons_shared_data/protocol/models/shared_models.py +0 -111
- package/python/opentrons_shared_data/py.typed +0 -0
- package/python/opentrons_shared_data/robot/__init__.py +0 -33
- package/python/opentrons_shared_data/robot/dev_types.py +0 -37
- package/python/pytest.ini +0 -2
- package/python/setup.cfg +0 -5
- package/python/setup.py +0 -179
- package/python/tests/__init__.py +0 -1
- package/python/tests/conftest.py +0 -0
- package/python/tests/deck/__init__.py +0 -0
- package/python/tests/deck/test_list_names.py +0 -12
- package/python/tests/deck/test_position.py +0 -113
- package/python/tests/deck/test_typechecks.py +0 -28
- package/python/tests/errors/__init__.py +0 -1
- package/python/tests/errors/test_error_completeness.py +0 -19
- package/python/tests/errors/test_exceptions.py +0 -74
- package/python/tests/gripper/__init__.py +0 -0
- package/python/tests/gripper/test_definition.py +0 -30
- package/python/tests/gripper/test_load.py +0 -16
- package/python/tests/labware/__init__.py +0 -13
- package/python/tests/labware/test_typechecks.py +0 -21
- package/python/tests/module/__init__.py +0 -20
- package/python/tests/module/test_load.py +0 -49
- package/python/tests/module/test_typechecks.py +0 -34
- package/python/tests/pipette/__init__.py +0 -0
- package/python/tests/pipette/test_load_data.py +0 -103
- package/python/tests/pipette/test_mutable_configurations.py +0 -266
- package/python/tests/pipette/test_pipette_definition.py +0 -183
- package/python/tests/pipette/test_pipette_load_name_conversions.py +0 -222
- package/python/tests/pipette/test_typechecks.py +0 -50
- package/python/tests/pipette/test_validate_schema.py +0 -37
- package/python/tests/protocol/__init__.py +0 -15
- package/python/tests/protocol/test_protocol_schema_v6.py +0 -107
- package/python/tests/protocol/test_protocol_schema_v7.py +0 -34
- package/python/tests/protocol/test_protocol_schema_v8.py +0 -20
- package/python/tests/protocol/test_typechecks.py +0 -36
- package/python/tests/robot/__init__.py +0 -0
- package/python/tests/robot/test_typechecks.py +0 -20
|
@@ -1,469 +0,0 @@
|
|
|
1
|
-
import argparse
|
|
2
|
-
import csv
|
|
3
|
-
import json
|
|
4
|
-
from ast import literal_eval
|
|
5
|
-
from typing import Optional, Dict, Union, Any, List
|
|
6
|
-
from pathlib import Path
|
|
7
|
-
from pydantic import BaseModel
|
|
8
|
-
import math
|
|
9
|
-
|
|
10
|
-
from ... import get_shared_data_root
|
|
11
|
-
from ..pipette_definition import (
|
|
12
|
-
PipetteGeometryDefinition,
|
|
13
|
-
PipetteLiquidPropertiesDefinition,
|
|
14
|
-
PipettePhysicalPropertiesDefinition,
|
|
15
|
-
PlungerPositions,
|
|
16
|
-
SupportedTipsDefinition,
|
|
17
|
-
MotorConfigurations,
|
|
18
|
-
PartialTipDefinition,
|
|
19
|
-
AvailableSensorDefinition,
|
|
20
|
-
PickUpTipConfigurations,
|
|
21
|
-
PressFitPickUpTipConfiguration,
|
|
22
|
-
DropTipConfigurations,
|
|
23
|
-
PlungerEjectDropTipConfiguration,
|
|
24
|
-
)
|
|
25
|
-
|
|
26
|
-
from ..dev_types import PipetteModelSpec
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
PIPETTE_DEFINITION_ROOT = Path("pipette") / "definitions" / "2"
|
|
30
|
-
GEOMETRY_ROOT = get_shared_data_root() / PIPETTE_DEFINITION_ROOT / "geometry"
|
|
31
|
-
GENERAL_ROOT = get_shared_data_root() / PIPETTE_DEFINITION_ROOT / "general"
|
|
32
|
-
LIQUID_ROOT = get_shared_data_root() / PIPETTE_DEFINITION_ROOT / "liquid"
|
|
33
|
-
|
|
34
|
-
GENERAL_SCHEMA = "#/pipette/schemas/2/pipettePropertiesSchema.json"
|
|
35
|
-
LIQUID_SCHEMA = "#/pipette/schemas/2/pipetteLiquidPropertiesSchema.json"
|
|
36
|
-
GEOMETRY_SCHEMA = "#/pipette/schemas/2/pipetteGeometryPropertiesSchema.json"
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
def _build_pickup_tip_data(
|
|
40
|
-
model_configurations: Optional[PipetteModelSpec] = None,
|
|
41
|
-
) -> PickUpTipConfigurations:
|
|
42
|
-
presses = 0
|
|
43
|
-
increment = 0
|
|
44
|
-
distance = 0.0
|
|
45
|
-
if model_configurations:
|
|
46
|
-
current = model_configurations["pickUpCurrent"]["value"]
|
|
47
|
-
speed = model_configurations["pickUpSpeed"]["value"]
|
|
48
|
-
presses = model_configurations["pickUpPresses"]["value"]
|
|
49
|
-
increment = int(model_configurations["pickUpIncrement"]["value"])
|
|
50
|
-
distance = model_configurations["pickUpDistance"]["value"]
|
|
51
|
-
else:
|
|
52
|
-
print("Handling pick up tip configurations\n")
|
|
53
|
-
speed = float(input("please provide the speed\n"))
|
|
54
|
-
presses = int(input("please provide the number of presses for force pick up\n"))
|
|
55
|
-
increment = int(
|
|
56
|
-
input(
|
|
57
|
-
"please provide the increment to move the pipette down for force pickup\n"
|
|
58
|
-
)
|
|
59
|
-
)
|
|
60
|
-
distance = float(
|
|
61
|
-
input("please provide the starting distance for pick up tip\n")
|
|
62
|
-
)
|
|
63
|
-
print(f"TODO: Current {current} is not used yet")
|
|
64
|
-
return PickUpTipConfigurations(
|
|
65
|
-
pressFit=PressFitPickUpTipConfiguration(
|
|
66
|
-
speed=speed,
|
|
67
|
-
presses=presses,
|
|
68
|
-
increment=increment,
|
|
69
|
-
distance=distance,
|
|
70
|
-
currentByTipCount={},
|
|
71
|
-
)
|
|
72
|
-
)
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
def _build_drop_tip_data(
|
|
76
|
-
model_configurations: Optional[PipetteModelSpec] = None,
|
|
77
|
-
) -> DropTipConfigurations:
|
|
78
|
-
if model_configurations:
|
|
79
|
-
current = model_configurations["dropTipCurrent"]["value"]
|
|
80
|
-
speed = model_configurations["dropTipSpeed"]["value"]
|
|
81
|
-
else:
|
|
82
|
-
print("Handling drop tip configurations\n")
|
|
83
|
-
speed = float(input("please provide the speed\n"))
|
|
84
|
-
return DropTipConfigurations(
|
|
85
|
-
plungerEject=PlungerEjectDropTipConfiguration(
|
|
86
|
-
current=current,
|
|
87
|
-
speed=speed,
|
|
88
|
-
)
|
|
89
|
-
)
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
def _build_plunger_positions(
|
|
93
|
-
model_configurations: Optional[PipetteModelSpec] = None,
|
|
94
|
-
) -> PlungerPositions:
|
|
95
|
-
if model_configurations:
|
|
96
|
-
top = model_configurations["top"]["value"]
|
|
97
|
-
bottom = model_configurations["bottom"]["value"]
|
|
98
|
-
blow_out = model_configurations["blowout"]["value"]
|
|
99
|
-
drop_tip = model_configurations["dropTip"]["value"]
|
|
100
|
-
else:
|
|
101
|
-
print("Handling plunger motor positions\n")
|
|
102
|
-
top = float(input("Please provide the top plunger position\n"))
|
|
103
|
-
bottom = float(input("Please provide the bottom plunger position\n"))
|
|
104
|
-
blow_out = float(input("Please provide the blow out plunger position\n"))
|
|
105
|
-
drop_tip = float(input("Please provide the drop tip plunger position\n"))
|
|
106
|
-
return PlungerPositions(top=top, bottom=bottom, blowout=blow_out, drop=drop_tip)
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
def _build_motor_configurations(
|
|
110
|
-
model_configurations: Optional[PipetteModelSpec] = None,
|
|
111
|
-
) -> MotorConfigurations:
|
|
112
|
-
if model_configurations:
|
|
113
|
-
run = model_configurations["plungerCurrent"]["value"]
|
|
114
|
-
idle = model_configurations.get("idleCurrent", run)
|
|
115
|
-
else:
|
|
116
|
-
print("Handling default plunger motor currents\n")
|
|
117
|
-
idle = float(
|
|
118
|
-
input("Please provide the default idle current of the plunger motor\n")
|
|
119
|
-
)
|
|
120
|
-
run = float(
|
|
121
|
-
input("Please provide the default run current of the plunger motor\n")
|
|
122
|
-
)
|
|
123
|
-
return MotorConfigurations(idle=idle, run=run)
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
def _build_partial_tip_configurations(channels: int) -> PartialTipDefinition:
|
|
127
|
-
if channels == 8:
|
|
128
|
-
return PartialTipDefinition(
|
|
129
|
-
partialTipSupported=True, availableConfigurations=[1, 2, 3, 4, 5, 6, 7, 8]
|
|
130
|
-
)
|
|
131
|
-
elif channels == 96:
|
|
132
|
-
return PartialTipDefinition(
|
|
133
|
-
partialTipSupported=True, availableConfigurations=[1, 8, 12, 96]
|
|
134
|
-
)
|
|
135
|
-
else:
|
|
136
|
-
return PartialTipDefinition(partialTipSupported=False)
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
def build_geometry_model_v2(
|
|
140
|
-
input_dictionary: Dict[str, Any]
|
|
141
|
-
) -> PipetteGeometryDefinition:
|
|
142
|
-
return PipetteGeometryDefinition.parse_obj(input_dictionary)
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
def build_liquid_model_v2(
|
|
146
|
-
input_dictionary: Dict[str, Any],
|
|
147
|
-
supported_tip_configurations: Dict[str, SupportedTipsDefinition],
|
|
148
|
-
) -> PipetteLiquidPropertiesDefinition:
|
|
149
|
-
if input_dictionary:
|
|
150
|
-
if input_dictionary.get("partialTipConfigurations"):
|
|
151
|
-
return PipetteLiquidPropertiesDefinition.parse_obj(
|
|
152
|
-
{**input_dictionary, "supportedTips": supported_tip_configurations}
|
|
153
|
-
)
|
|
154
|
-
else:
|
|
155
|
-
return PipetteLiquidPropertiesDefinition.parse_obj(
|
|
156
|
-
{
|
|
157
|
-
**input_dictionary,
|
|
158
|
-
"supportedTips": supported_tip_configurations,
|
|
159
|
-
}
|
|
160
|
-
)
|
|
161
|
-
max_volume = int(input("please provide the max volume of the pipette\n"))
|
|
162
|
-
min_volume = float(input("please provide the min volume of the pipette\n"))
|
|
163
|
-
default_tipracks = input(
|
|
164
|
-
"please input the load names of default tipracks separated by commas\n"
|
|
165
|
-
)
|
|
166
|
-
list_default_tipracks = default_tipracks.split(",")
|
|
167
|
-
return PipetteLiquidPropertiesDefinition.parse_obj(
|
|
168
|
-
{
|
|
169
|
-
"supportedTips": supported_tip_configurations,
|
|
170
|
-
"maxVolume": max_volume,
|
|
171
|
-
"minVolume": min_volume,
|
|
172
|
-
"defaultTipracks": list_default_tipracks,
|
|
173
|
-
}
|
|
174
|
-
)
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
def build_physical_model_v2(
|
|
178
|
-
input_dictionary: Optional[Dict[str, Any]], pipette_type: Optional[str] = None
|
|
179
|
-
) -> PipettePhysicalPropertiesDefinition:
|
|
180
|
-
if input_dictionary:
|
|
181
|
-
available_sensors = AvailableSensorDefinition(
|
|
182
|
-
sensors=input_dictionary.pop("availableSensors", [])
|
|
183
|
-
)
|
|
184
|
-
back_compat_names = input_dictionary.pop("backCompatNames", [])
|
|
185
|
-
return PipettePhysicalPropertiesDefinition.parse_obj(
|
|
186
|
-
{
|
|
187
|
-
**input_dictionary,
|
|
188
|
-
"availableSensors": available_sensors,
|
|
189
|
-
"backCompatNames": back_compat_names,
|
|
190
|
-
}
|
|
191
|
-
)
|
|
192
|
-
print(f"Handling general pipette information for {pipette_type}\n")
|
|
193
|
-
display_name = input("please provide the product name of the pipette\n")
|
|
194
|
-
|
|
195
|
-
display_category = input("please provide the model generation of the pipette\n")
|
|
196
|
-
input_available_sensors = input(
|
|
197
|
-
"Please provide a list of available sensors, separated by comma\n"
|
|
198
|
-
)
|
|
199
|
-
channels = input(f"Please provide the number of channels your {pipette_type} has\n")
|
|
200
|
-
shaft_diam = float(input(f"Please provide the shaft diameter of {pipette_type}\n"))
|
|
201
|
-
shaft_ul_per_mm = float(
|
|
202
|
-
input(f"Please provide the uL to mm conversion for {pipette_type}\n")
|
|
203
|
-
)
|
|
204
|
-
pick_up_tip_configurations = _build_pickup_tip_data()
|
|
205
|
-
drop_tip_configurations = _build_drop_tip_data()
|
|
206
|
-
plunger_positions = _build_plunger_positions()
|
|
207
|
-
plunger_motor_configurations = _build_motor_configurations()
|
|
208
|
-
partial_tip_configurations = _build_partial_tip_configurations(int(channels))
|
|
209
|
-
|
|
210
|
-
back_compat_names_str = input(
|
|
211
|
-
"Please list compatible pipette names separated by commas or hit enter if none"
|
|
212
|
-
)
|
|
213
|
-
if back_compat_names_str:
|
|
214
|
-
back_compat_names = [i.strip() for i in back_compat_names_str.split(",")]
|
|
215
|
-
else:
|
|
216
|
-
back_compat_names = []
|
|
217
|
-
return PipettePhysicalPropertiesDefinition.parse_obj(
|
|
218
|
-
{
|
|
219
|
-
"displayName": display_name,
|
|
220
|
-
"model": pipette_type,
|
|
221
|
-
"displayCategory": display_category,
|
|
222
|
-
"pickUpTipConfigurations": pick_up_tip_configurations,
|
|
223
|
-
"dropTipConfigurations": drop_tip_configurations,
|
|
224
|
-
"plungerMotorConfigurations": plunger_motor_configurations,
|
|
225
|
-
"plungerPositionsConfigurations": plunger_positions,
|
|
226
|
-
"availableSensors": AvailableSensorDefinition(
|
|
227
|
-
sensors=input_available_sensors.split(",")
|
|
228
|
-
),
|
|
229
|
-
"partialTipConfigurations": partial_tip_configurations,
|
|
230
|
-
"channels": channels,
|
|
231
|
-
"shaftDiameter": shaft_diam,
|
|
232
|
-
"shaftULperMM": shaft_ul_per_mm,
|
|
233
|
-
"backCompatNames": back_compat_names,
|
|
234
|
-
}
|
|
235
|
-
)
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
def build_supported_tips(input_dictionary: Dict[str, Any]) -> SupportedTipsDefinition:
|
|
239
|
-
return SupportedTipsDefinition.parse_obj(input_dictionary)
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
def save_to_file(
|
|
243
|
-
directorypath: Path,
|
|
244
|
-
file_name: str,
|
|
245
|
-
data: Union[BaseModel, Dict[str, Any]],
|
|
246
|
-
schema_path: str,
|
|
247
|
-
) -> None:
|
|
248
|
-
"""
|
|
249
|
-
Function used to save data to a file
|
|
250
|
-
"""
|
|
251
|
-
|
|
252
|
-
directorypath.mkdir(parents=True, exist_ok=True)
|
|
253
|
-
filepath = directorypath / f"{file_name}.json"
|
|
254
|
-
if isinstance(data, BaseModel):
|
|
255
|
-
# We have to rely on the json serialization of the
|
|
256
|
-
# pydantic model to properly convert special objects
|
|
257
|
-
# such as (pipetteModelType) to a string. However,
|
|
258
|
-
# we also want to add in a new key on top of the
|
|
259
|
-
# data in the pydantic model so we need to convert it
|
|
260
|
-
# back to a dictionary before saving to file.
|
|
261
|
-
json_basemodel = data.json(by_alias=True)
|
|
262
|
-
dict_basemodel = json.loads(json_basemodel)
|
|
263
|
-
dict_basemodel["$otSharedSchema"] = schema_path
|
|
264
|
-
filepath.write_text(
|
|
265
|
-
json.dumps(dict_basemodel, ensure_ascii=False), encoding="utf-8"
|
|
266
|
-
)
|
|
267
|
-
else:
|
|
268
|
-
data["$otSharedSchema"] = schema_path
|
|
269
|
-
filepath.write_text(json.dumps(data, ensure_ascii=False), encoding="utf-8")
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
def migrate_new_blow_out_configs_v2() -> None:
|
|
273
|
-
pipette_volumes = {
|
|
274
|
-
1: ["p10", "p50", "p300", "p1000"],
|
|
275
|
-
2: ["p20", "p300", "p1000"],
|
|
276
|
-
3: ["p50", "p1000"],
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
for pipette_gen in range(1, 4): # gen 1, gen 2, gen 3
|
|
280
|
-
print(f"\nTaking data for gen{pipette_gen} pipettes:")
|
|
281
|
-
# overwrite and pass in dict with user input for each gen
|
|
282
|
-
shaft_diameters = {
|
|
283
|
-
vol: float(input(f"Enter shaft diameter for gen{pipette_gen} {vol}: "))
|
|
284
|
-
for vol in pipette_volumes[pipette_gen]
|
|
285
|
-
}
|
|
286
|
-
fill_blowout_configs(pipette_gen, shaft_diameters, pipette_volumes[pipette_gen])
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
def fill_blowout_configs(
|
|
290
|
-
pipette_gen: int, shaft_diameters: Dict[str, float], volumes: List[str]
|
|
291
|
-
) -> None:
|
|
292
|
-
|
|
293
|
-
general_config_files = Path(GENERAL_ROOT).glob("*")
|
|
294
|
-
for pipette_type in general_config_files: # single, eight, 96-channel
|
|
295
|
-
for volume in volumes: # pipette max volume- p10, p20, p50, etc.
|
|
296
|
-
shaft_diameter = shaft_diameters[volume]
|
|
297
|
-
# calculate uL per mm, default blowout vol
|
|
298
|
-
ul_per_mm = math.pi * (shaft_diameter / 2) ** 2
|
|
299
|
-
# get path for every file version for the pipette gen at hand
|
|
300
|
-
volume_path = Path(pipette_type / volume)
|
|
301
|
-
for general_file_version in volume_path.glob(f"{str(pipette_gen)}_*.json"):
|
|
302
|
-
with open(general_file_version, "r") as file:
|
|
303
|
-
general_config_dict = json.load(file)
|
|
304
|
-
general_config_dict["shaftDiameter"] = round(shaft_diameter, 3)
|
|
305
|
-
general_config_dict["shaftULperMM"] = round(ul_per_mm, 3)
|
|
306
|
-
|
|
307
|
-
# get file path to pass into save_to_file
|
|
308
|
-
gen_path = GENERAL_ROOT / pipette_type / volume
|
|
309
|
-
version_str = str(general_file_version).split("/")[-1][:-5]
|
|
310
|
-
save_to_file(gen_path, version_str, general_config_dict, GENERAL_SCHEMA)
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
def build_new_pipette_model_v2(
|
|
314
|
-
pipette_functions_dict: Dict[str, Any], pipette_model_csv: str
|
|
315
|
-
) -> None:
|
|
316
|
-
"""
|
|
317
|
-
Build a brand new pipette model from user inputted data.
|
|
318
|
-
"""
|
|
319
|
-
top_level_pipette_model = {}
|
|
320
|
-
with open(pipette_model_csv, "r") as f:
|
|
321
|
-
reader = csv.reader(f)
|
|
322
|
-
current_key = None
|
|
323
|
-
for row in reader:
|
|
324
|
-
if row[0]:
|
|
325
|
-
current_key = row[0]
|
|
326
|
-
top_level_pipette_model[current_key] = {row[1]: literal_eval(row[2])}
|
|
327
|
-
elif current_key:
|
|
328
|
-
top_level_pipette_model[current_key][row[1]] = literal_eval(row[2])
|
|
329
|
-
else:
|
|
330
|
-
continue
|
|
331
|
-
geometry_model = build_geometry_model_v2(top_level_pipette_model["geometry"])
|
|
332
|
-
liquid_model = build_liquid_model_v2(
|
|
333
|
-
top_level_pipette_model["liquid"],
|
|
334
|
-
pipette_functions_dict,
|
|
335
|
-
)
|
|
336
|
-
liquid_model_dict = liquid_model.dict(by_alias=True)
|
|
337
|
-
liquid_model_dict["supportedTips"] = {
|
|
338
|
-
k.name: v for k, v in liquid_model_dict["supportedTips"].items()
|
|
339
|
-
}
|
|
340
|
-
pipette_type = f"p{liquid_model.max_volume}"
|
|
341
|
-
physical_model = build_physical_model_v2(
|
|
342
|
-
{
|
|
343
|
-
**top_level_pipette_model["general"],
|
|
344
|
-
"plungerMotorConfigurations": top_level_pipette_model[
|
|
345
|
-
"plungerMotorConfigurations"
|
|
346
|
-
],
|
|
347
|
-
"plungerPositionsConfigurations": top_level_pipette_model[
|
|
348
|
-
"plungerPositionsConfigurations"
|
|
349
|
-
],
|
|
350
|
-
"pickUpTipConfigurations": top_level_pipette_model[
|
|
351
|
-
"pickUpTipConfigurations"
|
|
352
|
-
],
|
|
353
|
-
"dropTipConfigurations": top_level_pipette_model["dropTipConfigurations"],
|
|
354
|
-
"partialTipConfigurations": _build_partial_tip_configurations(
|
|
355
|
-
top_level_pipette_model["general"]["channels"]
|
|
356
|
-
),
|
|
357
|
-
},
|
|
358
|
-
pipette_type,
|
|
359
|
-
)
|
|
360
|
-
|
|
361
|
-
major_version = input("please provide the major version of this pipette model\n")
|
|
362
|
-
minor_version = input("please provide the minor version of this pipette model\n")
|
|
363
|
-
|
|
364
|
-
file_name = f"{major_version}_{minor_version}"
|
|
365
|
-
current_pipette_path = Path(physical_model.channels.name.lower()) / pipette_type
|
|
366
|
-
|
|
367
|
-
save_to_file(
|
|
368
|
-
GEOMETRY_ROOT / current_pipette_path, file_name, geometry_model, GEOMETRY_SCHEMA
|
|
369
|
-
)
|
|
370
|
-
save_to_file(
|
|
371
|
-
GENERAL_ROOT / current_pipette_path, file_name, physical_model, GENERAL_SCHEMA
|
|
372
|
-
)
|
|
373
|
-
save_to_file(
|
|
374
|
-
LIQUID_ROOT / current_pipette_path, file_name, liquid_model_dict, LIQUID_SCHEMA
|
|
375
|
-
)
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
def main() -> None:
|
|
379
|
-
"""Entry point."""
|
|
380
|
-
parser = argparse.ArgumentParser(
|
|
381
|
-
description="96 channel tip handling testing script."
|
|
382
|
-
)
|
|
383
|
-
parser.add_argument(
|
|
384
|
-
"--path_to_pipette_model",
|
|
385
|
-
type=str,
|
|
386
|
-
help="the csv filled with data to build a pipette model",
|
|
387
|
-
default=None,
|
|
388
|
-
)
|
|
389
|
-
parser.add_argument(
|
|
390
|
-
"--migrate_blowout_configs",
|
|
391
|
-
type=bool,
|
|
392
|
-
help="If true, migrate new blowout configs to existing json files",
|
|
393
|
-
default=False,
|
|
394
|
-
)
|
|
395
|
-
|
|
396
|
-
args = parser.parse_args()
|
|
397
|
-
if args.migrate_blowout_configs:
|
|
398
|
-
migrate_new_blow_out_configs_v2()
|
|
399
|
-
else:
|
|
400
|
-
using_csv = "" if args.path_to_pipette_model else "out"
|
|
401
|
-
print(f"Building new pipette function with{using_csv} using csv")
|
|
402
|
-
|
|
403
|
-
next_tip = True
|
|
404
|
-
pipette_functions_dict: Dict[str, Any] = {}
|
|
405
|
-
while next_tip:
|
|
406
|
-
print("Preparing pipetting function table from csv\n")
|
|
407
|
-
tip_volume = input("Please provide the next tip volume\n")
|
|
408
|
-
tiprack = input(
|
|
409
|
-
"Please provide the tiprack/tip type associated with this data\n"
|
|
410
|
-
)
|
|
411
|
-
path_to_data = input("Please provide the data path to the csv\n")
|
|
412
|
-
csv_dict = pipette_functions_dict.get(f"t{tip_volume}", {})
|
|
413
|
-
with open(path_to_data, "r") as f:
|
|
414
|
-
reader = csv.reader(f)
|
|
415
|
-
pipetting_key = None
|
|
416
|
-
for row in reader:
|
|
417
|
-
current_key_exists = csv_dict.get(row[0])
|
|
418
|
-
if row[0] == "aspirate" or row[0] == "dispense":
|
|
419
|
-
pipetting_key = row[0]
|
|
420
|
-
if current_key_exists:
|
|
421
|
-
csv_dict[pipetting_key][f"{tiprack}"].append(
|
|
422
|
-
[float(row[1]), float(row[2]), float(row[3])]
|
|
423
|
-
)
|
|
424
|
-
else:
|
|
425
|
-
csv_dict[pipetting_key] = {
|
|
426
|
-
f"{tiprack}": [
|
|
427
|
-
[float(row[1]), float(row[2]), float(row[3])]
|
|
428
|
-
]
|
|
429
|
-
}
|
|
430
|
-
elif pipetting_key and not row[0]:
|
|
431
|
-
csv_dict[pipetting_key][f"{tiprack}"].append(
|
|
432
|
-
[float(row[1]), float(row[2]), float(row[3])]
|
|
433
|
-
)
|
|
434
|
-
else:
|
|
435
|
-
pipetting_key = None
|
|
436
|
-
if current_key_exists:
|
|
437
|
-
continue
|
|
438
|
-
csv_dict[row[0]] = row[1]
|
|
439
|
-
pipette_functions_dict[f"t{tip_volume}"] = csv_dict
|
|
440
|
-
cont = input("Additional tips? Please enter y/n")
|
|
441
|
-
|
|
442
|
-
next_tip = cont == "y" or cont == "yes"
|
|
443
|
-
converted_pipette_functions_dict = {
|
|
444
|
-
k: build_supported_tips(d) for k, d in pipette_functions_dict.items()
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
print(
|
|
448
|
-
"Please review the aspirate and dispense functions once the pipette model is built.\n"
|
|
449
|
-
)
|
|
450
|
-
build_new_pipette_model_v2(
|
|
451
|
-
converted_pipette_functions_dict, args.path_to_pipette_model
|
|
452
|
-
)
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
if __name__ == "__main__":
|
|
456
|
-
"""
|
|
457
|
-
A script to automate building a pipette configuration definition.
|
|
458
|
-
|
|
459
|
-
This script can either perform migrations from a v1 -> v2 schema format
|
|
460
|
-
or build a brand new script from scratch.
|
|
461
|
-
|
|
462
|
-
When building a new pipette configuration model, you will either need
|
|
463
|
-
to provide CSVs or use command line inputs.
|
|
464
|
-
|
|
465
|
-
If you choose CSVs you will need one CSV for the general pipette configuration
|
|
466
|
-
data (such as pipette model or number of channels) and one for every tip
|
|
467
|
-
type that this pipette model can support.
|
|
468
|
-
"""
|
|
469
|
-
main()
|