@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.
- package/lib/{bundle.673284981fd97184260c.js → opentrons-shared-data.js} +2 -2
- package/lib/opentrons-shared-data.js.map +1 -0
- package/package.json +1 -1
- package/webpack.config.js +1 -0
- 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/lib/bundle.673284981fd97184260c.js.map +0 -1
- 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
- /package/lib/{bundle.673284981fd97184260c.js.LICENSE.txt → opentrons-shared-data.js.LICENSE.txt} +0 -0
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import typing
|
|
2
|
-
import logging
|
|
3
|
-
import os
|
|
4
|
-
from pathlib import Path
|
|
5
|
-
from functools import lru_cache
|
|
6
|
-
|
|
7
|
-
log = logging.getLogger(__name__)
|
|
8
|
-
|
|
9
|
-
ENV_SHARED_DATA_PATH = "OT_SHARED_DATA_PATH"
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class SharedDataMissingError(IOError):
|
|
13
|
-
pass
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
@lru_cache(maxsize=1)
|
|
17
|
-
def get_shared_data_root() -> Path:
|
|
18
|
-
"""
|
|
19
|
-
Get the root directory of the shared data.
|
|
20
|
-
|
|
21
|
-
Steps (first to succeed wins):
|
|
22
|
-
1) Use environment variable in OT_SHARED_DATA_PATH
|
|
23
|
-
2) Look in "shared_data" in the root of the installed package
|
|
24
|
-
3) Look for "shared-data" in parent directories.
|
|
25
|
-
4) Raise exception
|
|
26
|
-
"""
|
|
27
|
-
# Check environment variable
|
|
28
|
-
override = os.environ.get(ENV_SHARED_DATA_PATH)
|
|
29
|
-
if override is not None:
|
|
30
|
-
log.info("Using override for shared data path: %s", override)
|
|
31
|
-
return Path(override)
|
|
32
|
-
|
|
33
|
-
# Check contents of package
|
|
34
|
-
module_path = Path(__file__).parent
|
|
35
|
-
module_data = module_path / "data"
|
|
36
|
-
if module_data.exists():
|
|
37
|
-
log.info(f"Using packaged shared data path: {str(module_data)}")
|
|
38
|
-
return module_data
|
|
39
|
-
|
|
40
|
-
# We are likely to be running locally and will find shared-data in repo
|
|
41
|
-
for parent in module_path.parents:
|
|
42
|
-
p = parent / "shared-data"
|
|
43
|
-
if p.exists():
|
|
44
|
-
log.info("Using shared data in path: %s", p)
|
|
45
|
-
return p
|
|
46
|
-
|
|
47
|
-
raise SharedDataMissingError()
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
def load_shared_data(path: typing.Union[str, Path]) -> bytes:
|
|
51
|
-
"""
|
|
52
|
-
Load file from shared data directory.
|
|
53
|
-
|
|
54
|
-
path is relative to the root of all shared data (ie. no "shared-data")
|
|
55
|
-
"""
|
|
56
|
-
with open(get_shared_data_root() / path, "rb") as f:
|
|
57
|
-
return f.read()
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
""" opentrons_shared_data.module: functions and types for module defs """
|
|
2
|
-
import json
|
|
3
|
-
from pathlib import Path
|
|
4
|
-
from typing import Union, cast, overload
|
|
5
|
-
|
|
6
|
-
from ..load import load_shared_data
|
|
7
|
-
from .dev_types import (
|
|
8
|
-
SchemaVersions,
|
|
9
|
-
ModuleSchema,
|
|
10
|
-
SchemaV1,
|
|
11
|
-
SchemaV3,
|
|
12
|
-
ModuleDefinitionV1,
|
|
13
|
-
ModuleDefinitionV3,
|
|
14
|
-
ModuleModel,
|
|
15
|
-
)
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
# TODO (spp, 2022-05-12): Python has a built-in error called `ModuleNotFoundError` so,
|
|
19
|
-
# maybe rename this one?
|
|
20
|
-
class ModuleNotFoundError(KeyError):
|
|
21
|
-
def __init__(self, version: str, model_or_loadname: str):
|
|
22
|
-
super().__init__(model_or_loadname)
|
|
23
|
-
self.requested_version = version
|
|
24
|
-
self.requested_module = model_or_loadname
|
|
25
|
-
|
|
26
|
-
def __str__(self) -> str:
|
|
27
|
-
return (
|
|
28
|
-
f"No such version {self.requested_version} module "
|
|
29
|
-
f"{self.requested_module}"
|
|
30
|
-
)
|
|
31
|
-
|
|
32
|
-
def __repr__(self) -> str:
|
|
33
|
-
return (
|
|
34
|
-
f"{self.__class__.__name__}: {self.requested_module} "
|
|
35
|
-
f"at version {self.requested_version}"
|
|
36
|
-
)
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
def load_schema(version: SchemaVersions) -> ModuleSchema:
|
|
40
|
-
path = Path("module") / "schemas" / f"{version}.json"
|
|
41
|
-
return cast(ModuleSchema, json.loads(load_shared_data(path)))
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
@overload
|
|
45
|
-
def load_definition(version: SchemaV1, model_or_loadname: str) -> ModuleDefinitionV1:
|
|
46
|
-
...
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
@overload
|
|
50
|
-
def load_definition(
|
|
51
|
-
version: SchemaV3,
|
|
52
|
-
model_or_loadname: Union[str, ModuleModel],
|
|
53
|
-
) -> ModuleDefinitionV3:
|
|
54
|
-
...
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
def load_definition(
|
|
58
|
-
version: SchemaVersions,
|
|
59
|
-
model_or_loadname: Union[str, ModuleModel],
|
|
60
|
-
) -> Union[ModuleDefinitionV1, ModuleDefinitionV3]:
|
|
61
|
-
if version == "1":
|
|
62
|
-
path = Path("module") / "definitions" / "1.json"
|
|
63
|
-
data = json.loads(load_shared_data(path))
|
|
64
|
-
try:
|
|
65
|
-
return cast(ModuleDefinitionV1, data[model_or_loadname])
|
|
66
|
-
except KeyError:
|
|
67
|
-
raise ModuleNotFoundError("1", model_or_loadname)
|
|
68
|
-
else:
|
|
69
|
-
path = Path(f"module/definitions/{version}/{model_or_loadname}.json")
|
|
70
|
-
try:
|
|
71
|
-
data = load_shared_data(path)
|
|
72
|
-
except FileNotFoundError:
|
|
73
|
-
raise ModuleNotFoundError(version, model_or_loadname)
|
|
74
|
-
return cast(ModuleDefinitionV3, json.loads(data))
|
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
opentrons_shared_data.module.dev_types: types requiring typing_extensions
|
|
3
|
-
for modules
|
|
4
|
-
"""
|
|
5
|
-
|
|
6
|
-
from typing import Any, Dict, List, Union
|
|
7
|
-
from typing_extensions import Literal, TypedDict
|
|
8
|
-
|
|
9
|
-
SchemaV1 = Literal["1"]
|
|
10
|
-
SchemaV2 = Literal["2"]
|
|
11
|
-
SchemaV3 = Literal["3"]
|
|
12
|
-
SchemaVersions = Union[SchemaV1, SchemaV2, SchemaV3]
|
|
13
|
-
|
|
14
|
-
ModuleSchema = Dict[str, Any]
|
|
15
|
-
|
|
16
|
-
MagneticModuleType = Literal["magneticModuleType"]
|
|
17
|
-
TemperatureModuleType = Literal["temperatureModuleType"]
|
|
18
|
-
ThermocyclerModuleType = Literal["thermocyclerModuleType"]
|
|
19
|
-
HeaterShakerModuleType = Literal["heaterShakerModuleType"]
|
|
20
|
-
MagneticBlockType = Literal["magneticBlockType"]
|
|
21
|
-
|
|
22
|
-
ModuleType = Union[
|
|
23
|
-
MagneticModuleType,
|
|
24
|
-
TemperatureModuleType,
|
|
25
|
-
ThermocyclerModuleType,
|
|
26
|
-
HeaterShakerModuleType,
|
|
27
|
-
MagneticBlockType,
|
|
28
|
-
]
|
|
29
|
-
|
|
30
|
-
MagneticModuleModel = Literal["magneticModuleV1", "magneticModuleV2"]
|
|
31
|
-
TemperatureModuleModel = Literal["temperatureModuleV1", "temperatureModuleV2"]
|
|
32
|
-
ThermocyclerModuleModel = Literal["thermocyclerModuleV1", "thermocyclerModuleV2"]
|
|
33
|
-
HeaterShakerModuleModel = Literal["heaterShakerModuleV1"]
|
|
34
|
-
MagneticBlockModel = Literal["magneticBlockV1"]
|
|
35
|
-
|
|
36
|
-
ModuleModel = Union[
|
|
37
|
-
MagneticModuleModel,
|
|
38
|
-
TemperatureModuleModel,
|
|
39
|
-
ThermocyclerModuleModel,
|
|
40
|
-
HeaterShakerModuleModel,
|
|
41
|
-
MagneticBlockModel,
|
|
42
|
-
]
|
|
43
|
-
|
|
44
|
-
ModuleSlotTransform = TypedDict(
|
|
45
|
-
"ModuleSlotTransform", {"labwareOffset": List[List[float]]}
|
|
46
|
-
)
|
|
47
|
-
|
|
48
|
-
ModuleLabwareOffset = TypedDict(
|
|
49
|
-
"ModuleLabwareOffset", {"x": float, "y": float, "z": float}
|
|
50
|
-
)
|
|
51
|
-
|
|
52
|
-
ModuleDimensions = TypedDict(
|
|
53
|
-
"ModuleDimensions",
|
|
54
|
-
{
|
|
55
|
-
"bareOverallHeight": float,
|
|
56
|
-
"overLabwareHeight": float,
|
|
57
|
-
"lidHeight": float,
|
|
58
|
-
"xDimension": float,
|
|
59
|
-
"yDimension": float,
|
|
60
|
-
"footprintXDimension": float,
|
|
61
|
-
"footprintYDimension": float,
|
|
62
|
-
"labwareInterfaceXDimension": float,
|
|
63
|
-
"labwareInterfaceYDimension": float,
|
|
64
|
-
},
|
|
65
|
-
total=False,
|
|
66
|
-
)
|
|
67
|
-
|
|
68
|
-
ModuleCalibrationPointOffset = TypedDict(
|
|
69
|
-
"ModuleCalibrationPointOffset", {"x": float, "y": float}
|
|
70
|
-
)
|
|
71
|
-
|
|
72
|
-
ModuleCalibrationPointOffsetWithZ = TypedDict(
|
|
73
|
-
"ModuleCalibrationPointOffsetWithZ", {"x": float, "y": float, "z": float}
|
|
74
|
-
)
|
|
75
|
-
|
|
76
|
-
CornerOffsetFromSlot = TypedDict(
|
|
77
|
-
"CornerOffsetFromSlot", {"x": float, "y": float, "z": float}
|
|
78
|
-
)
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
class NamedOffset(TypedDict):
|
|
82
|
-
x: float
|
|
83
|
-
y: float
|
|
84
|
-
z: float
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
class GripperOffsets(TypedDict):
|
|
88
|
-
pickUpOffset: NamedOffset
|
|
89
|
-
dropOffset: NamedOffset
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
# TODO(mc, 2022-03-18): potentially move from typed-dict to Pydantic
|
|
93
|
-
ModuleDefinitionV3 = TypedDict(
|
|
94
|
-
"ModuleDefinitionV3",
|
|
95
|
-
{
|
|
96
|
-
"$otSharedSchema": Literal["module/schemas/3"],
|
|
97
|
-
"moduleType": ModuleType,
|
|
98
|
-
"model": ModuleModel,
|
|
99
|
-
"labwareOffset": ModuleLabwareOffset,
|
|
100
|
-
"cornerOffsetFromSlot": CornerOffsetFromSlot,
|
|
101
|
-
"dimensions": ModuleDimensions,
|
|
102
|
-
"calibrationPoint": ModuleCalibrationPointOffsetWithZ,
|
|
103
|
-
"config": Dict[str, int],
|
|
104
|
-
"displayName": str,
|
|
105
|
-
"quirks": List[str],
|
|
106
|
-
"slotTransforms": Dict[str, Dict[str, Dict[str, List[List[float]]]]],
|
|
107
|
-
"compatibleWith": List[ModuleModel],
|
|
108
|
-
"twoDimensionalRendering": Dict[str, Any],
|
|
109
|
-
"gripperOffsets": Dict[str, GripperOffsets],
|
|
110
|
-
},
|
|
111
|
-
total=False,
|
|
112
|
-
)
|
|
113
|
-
|
|
114
|
-
# V2 is not used anymore. This type is preserved for historical purposes
|
|
115
|
-
ModuleDefinitionV2 = TypedDict(
|
|
116
|
-
"ModuleDefinitionV2",
|
|
117
|
-
{
|
|
118
|
-
"$otSharedSchema": Literal["module/schemas/2"],
|
|
119
|
-
"moduleType": ModuleType,
|
|
120
|
-
"model": ModuleModel,
|
|
121
|
-
"labwareOffset": ModuleLabwareOffset,
|
|
122
|
-
"dimensions": ModuleDimensions,
|
|
123
|
-
"calibrationPoint": ModuleCalibrationPointOffset,
|
|
124
|
-
"displayName": str,
|
|
125
|
-
"quirks": List[str],
|
|
126
|
-
"slotTransforms": Dict[str, Dict[str, Dict[str, List[List[float]]]]],
|
|
127
|
-
"compatibleWith": List[ModuleModel],
|
|
128
|
-
},
|
|
129
|
-
)
|
|
130
|
-
|
|
131
|
-
ModuleDefinitionV1 = TypedDict(
|
|
132
|
-
"ModuleDefinitionV1",
|
|
133
|
-
{
|
|
134
|
-
"labwareOffset": ModuleLabwareOffset,
|
|
135
|
-
"dimensions": ModuleDimensions,
|
|
136
|
-
"calibrationPoint": ModuleCalibrationPointOffset,
|
|
137
|
-
"displayName": str,
|
|
138
|
-
"loadName": str,
|
|
139
|
-
"quirks": List[str],
|
|
140
|
-
},
|
|
141
|
-
)
|
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
"""
|
|
4
|
-
opentrons_shared_data.pipette: functions and types for pipette config
|
|
5
|
-
"""
|
|
6
|
-
import copy
|
|
7
|
-
from typing import TYPE_CHECKING, Dict
|
|
8
|
-
import json
|
|
9
|
-
from functools import lru_cache
|
|
10
|
-
|
|
11
|
-
from .. import load_shared_data
|
|
12
|
-
|
|
13
|
-
if TYPE_CHECKING:
|
|
14
|
-
from .dev_types import (
|
|
15
|
-
PipetteNameSpecs,
|
|
16
|
-
PipetteModelSpecs,
|
|
17
|
-
PipetteName,
|
|
18
|
-
PipetteModel,
|
|
19
|
-
PipetteFusedSpec,
|
|
20
|
-
ChannelCount,
|
|
21
|
-
)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
# TODO (spp, 2023-06-22: should probably move this to definition)
|
|
25
|
-
"""
|
|
26
|
-
The span of pipettes in X-direction based on number of channels.
|
|
27
|
-
This is needed in order to determine safe tip drop location within a labware.
|
|
28
|
-
"""
|
|
29
|
-
PIPETTE_X_SPAN: Dict[ChannelCount, float] = {
|
|
30
|
-
1: 75, # includes a margin
|
|
31
|
-
8: 75, # includes a margin
|
|
32
|
-
96: 161,
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
def model_config() -> PipetteModelSpecs:
|
|
37
|
-
"""Load the per-pipette-model config file from within the wheel"""
|
|
38
|
-
return copy.deepcopy(_model_config())
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
@lru_cache(maxsize=None)
|
|
42
|
-
def _model_config() -> PipetteModelSpecs:
|
|
43
|
-
return json.loads(
|
|
44
|
-
load_shared_data("pipette/definitions/1/pipetteModelSpecs.json") or "{}"
|
|
45
|
-
)
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
def name_config() -> PipetteNameSpecs:
|
|
49
|
-
"""Load the per-pipette-name config file from within the wheel"""
|
|
50
|
-
return _name_config()
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
@lru_cache(maxsize=None)
|
|
54
|
-
def _name_config() -> PipetteNameSpecs:
|
|
55
|
-
return json.loads(
|
|
56
|
-
load_shared_data("pipette/definitions/1/pipetteNameSpecs.json") or "{}"
|
|
57
|
-
)
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
def name_for_model(pipette_model: PipetteModel) -> PipetteName:
|
|
61
|
-
"""Quickly look up the name for this model"""
|
|
62
|
-
return model_config()["config"][pipette_model]["name"]
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
def fuse_specs(
|
|
66
|
-
pipette_model: PipetteModel, pipette_name: PipetteName = None
|
|
67
|
-
) -> PipetteFusedSpec:
|
|
68
|
-
"""Combine the model and name spec for a given model.
|
|
69
|
-
|
|
70
|
-
if pipette_name is not given, the name field of the pipette config
|
|
71
|
-
is used. If it is, the given name must be in the backCompatNames field.
|
|
72
|
-
"""
|
|
73
|
-
return copy.deepcopy(_fuse_specs_cached(pipette_model, pipette_name))
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
@lru_cache(maxsize=None)
|
|
77
|
-
def _fuse_specs_cached(
|
|
78
|
-
pipette_model: PipetteModel, pipette_name: PipetteName = None
|
|
79
|
-
) -> PipetteFusedSpec:
|
|
80
|
-
"""
|
|
81
|
-
Do the work of fusing the specs inside an lru cache. This can't be the
|
|
82
|
-
function that's directly called because we want to return a new object
|
|
83
|
-
all the time, hence the wrapper.
|
|
84
|
-
"""
|
|
85
|
-
model_data = _model_config()["config"][pipette_model]
|
|
86
|
-
pipette_name = pipette_name or model_data["name"]
|
|
87
|
-
|
|
88
|
-
valid_names = [model_data["name"]] + model_data.get("backCompatNames", [])
|
|
89
|
-
|
|
90
|
-
if pipette_name not in valid_names:
|
|
91
|
-
raise KeyError(
|
|
92
|
-
f"pipette name {pipette_name} is not valid for model " f"{pipette_model}"
|
|
93
|
-
)
|
|
94
|
-
name_data = _name_config()[pipette_name]
|
|
95
|
-
# unfortunately, mypy can't verify this way to build typed dicts - we'll
|
|
96
|
-
# make sure it's correct in the tests, and leave the function annotated
|
|
97
|
-
# properly
|
|
98
|
-
return {**model_data, **name_data} # type: ignore
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
def dummy_model_for_name(pipette_name: PipetteName) -> PipetteModel:
|
|
102
|
-
if "gen2" in pipette_name:
|
|
103
|
-
return "_".join(pipette_name.split("_")[:-1]) + "_v2.0" # type: ignore
|
|
104
|
-
elif "flex" in pipette_name:
|
|
105
|
-
return "_".join(pipette_name.split("_")[:-1]) + "_v3.0" # type: ignore
|
|
106
|
-
else:
|
|
107
|
-
return pipette_name + "_v1" # type: ignore
|
|
@@ -1,177 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
opentrons_shared_data.pipette.dev_types: types for pipette config that
|
|
3
|
-
require typing_extensions.
|
|
4
|
-
|
|
5
|
-
This module should only be imported if typing.TYPE_CHECKING is True.
|
|
6
|
-
"""
|
|
7
|
-
from enum import Enum
|
|
8
|
-
from typing import Dict, List, NewType, Union
|
|
9
|
-
|
|
10
|
-
from typing_extensions import Literal, TypedDict
|
|
11
|
-
|
|
12
|
-
# TODO(mc, 2022-06-16): remove type alias when able
|
|
13
|
-
# and when certain removal will not break any pickling
|
|
14
|
-
from ..labware.dev_types import LabwareUri as LabwareUri
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
PipetteName = Literal[
|
|
18
|
-
"p10_single",
|
|
19
|
-
"p10_multi",
|
|
20
|
-
"p20_single_gen2",
|
|
21
|
-
"p20_multi_gen2",
|
|
22
|
-
"p50_single",
|
|
23
|
-
"p50_multi",
|
|
24
|
-
"p50_single_flex",
|
|
25
|
-
"p50_multi_flex",
|
|
26
|
-
"p300_single",
|
|
27
|
-
"p300_multi",
|
|
28
|
-
"p300_single_gen2",
|
|
29
|
-
"p300_multi_gen2",
|
|
30
|
-
"p1000_single",
|
|
31
|
-
"p1000_single_gen2",
|
|
32
|
-
"p1000_single_flex",
|
|
33
|
-
"p1000_multi_flex",
|
|
34
|
-
"p1000_96",
|
|
35
|
-
]
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
class PipetteNameType(str, Enum):
|
|
39
|
-
"""Pipette load name values."""
|
|
40
|
-
|
|
41
|
-
value: PipetteName
|
|
42
|
-
|
|
43
|
-
P10_SINGLE = "p10_single"
|
|
44
|
-
P10_MULTI = "p10_multi"
|
|
45
|
-
P20_SINGLE_GEN2 = "p20_single_gen2"
|
|
46
|
-
P20_MULTI_GEN2 = "p20_multi_gen2"
|
|
47
|
-
P50_SINGLE = "p50_single"
|
|
48
|
-
P50_MULTI = "p50_multi"
|
|
49
|
-
P50_SINGLE_FLEX = "p50_single_flex"
|
|
50
|
-
P50_MULTI_FLEX = "p50_multi_flex"
|
|
51
|
-
P300_SINGLE = "p300_single"
|
|
52
|
-
P300_MULTI = "p300_multi"
|
|
53
|
-
P300_SINGLE_GEN2 = "p300_single_gen2"
|
|
54
|
-
P300_MULTI_GEN2 = "p300_multi_gen2"
|
|
55
|
-
P1000_SINGLE = "p1000_single"
|
|
56
|
-
P1000_SINGLE_GEN2 = "p1000_single_gen2"
|
|
57
|
-
P1000_SINGLE_FLEX = "p1000_single_flex"
|
|
58
|
-
P1000_MULTI_FLEX = "p1000_multi_flex"
|
|
59
|
-
P1000_96 = "p1000_96"
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
# Generic NewType for models because we get new ones frequently and theres
|
|
63
|
-
# a huge number of them
|
|
64
|
-
PipetteModel = NewType("PipetteModel", str)
|
|
65
|
-
|
|
66
|
-
DisplayCategory = Literal["GEN1", "GEN2", "FLEX"]
|
|
67
|
-
|
|
68
|
-
# todo(mm, 2022-03-18):
|
|
69
|
-
# The JSON schema defines this as any string, not as an enum of string literals.
|
|
70
|
-
# Check if it's safe to simplify this to just str.
|
|
71
|
-
ConfigUnit = Literal[
|
|
72
|
-
"mm",
|
|
73
|
-
"amps",
|
|
74
|
-
"mm/sec",
|
|
75
|
-
"mm/s", # todo(mm, 2022-03-18): Standardize specs to mm/sec or mm/s.
|
|
76
|
-
"presses",
|
|
77
|
-
]
|
|
78
|
-
|
|
79
|
-
Quirk = NewType("Quirk", str)
|
|
80
|
-
|
|
81
|
-
ChannelCount = Literal[1, 8, 96]
|
|
82
|
-
|
|
83
|
-
UlPerMmAction = Literal["aspirate", "dispense", "blowout"]
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
class PipetteConfigElement(TypedDict):
|
|
87
|
-
value: float
|
|
88
|
-
min: float
|
|
89
|
-
max: float
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
class PipetteConfigElementWithPerApiLevelValue(TypedDict):
|
|
93
|
-
value: float
|
|
94
|
-
min: float
|
|
95
|
-
max: float
|
|
96
|
-
valuesByApiLevel: Dict[str, float]
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
# TypedDicts can't be generic sadly
|
|
100
|
-
class PipetteCustomizableConfigElementFloat(TypedDict):
|
|
101
|
-
value: float
|
|
102
|
-
min: float
|
|
103
|
-
max: float
|
|
104
|
-
units: ConfigUnit
|
|
105
|
-
type: Literal["float"]
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
class PipetteCustomizableConfigElementInt(TypedDict):
|
|
109
|
-
value: int
|
|
110
|
-
min: int
|
|
111
|
-
max: int
|
|
112
|
-
units: ConfigUnit
|
|
113
|
-
type: Literal["int"]
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
PipetteCustomizableConfigElement = Union[
|
|
117
|
-
PipetteCustomizableConfigElementFloat, PipetteCustomizableConfigElementInt
|
|
118
|
-
]
|
|
119
|
-
|
|
120
|
-
SmoothieConfigs = TypedDict(
|
|
121
|
-
"SmoothieConfigs",
|
|
122
|
-
{"stepsPerMM": float, "homePosition": float, "travelDistance": float},
|
|
123
|
-
)
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
class PipetteNameSpec(TypedDict):
|
|
127
|
-
displayName: str
|
|
128
|
-
displayCategory: DisplayCategory
|
|
129
|
-
minVolume: Union[float, int]
|
|
130
|
-
maxVolume: Union[float, int]
|
|
131
|
-
channels: ChannelCount
|
|
132
|
-
defaultAspirateFlowRate: PipetteConfigElementWithPerApiLevelValue
|
|
133
|
-
defaultDispenseFlowRate: PipetteConfigElementWithPerApiLevelValue
|
|
134
|
-
defaultBlowOutFlowRate: PipetteConfigElementWithPerApiLevelValue
|
|
135
|
-
smoothieConfigs: SmoothieConfigs
|
|
136
|
-
defaultTipracks: List[LabwareUri]
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
PipetteNameSpecs = Dict[PipetteName, PipetteNameSpec]
|
|
140
|
-
|
|
141
|
-
UlPerMm = Dict[UlPerMmAction, List[List[float]]]
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
class PipetteModelSpec(TypedDict, total=False):
|
|
145
|
-
name: PipetteName
|
|
146
|
-
top: PipetteCustomizableConfigElementFloat
|
|
147
|
-
bottom: PipetteCustomizableConfigElementFloat
|
|
148
|
-
blowout: PipetteCustomizableConfigElementFloat
|
|
149
|
-
dropTip: PipetteCustomizableConfigElementFloat
|
|
150
|
-
pickUpCurrent: PipetteCustomizableConfigElementFloat
|
|
151
|
-
pickUpDistance: PipetteCustomizableConfigElementFloat
|
|
152
|
-
pickUpIncrement: PipetteCustomizableConfigElementFloat
|
|
153
|
-
pickUpPresses: PipetteCustomizableConfigElementInt
|
|
154
|
-
pickUpSpeed: PipetteCustomizableConfigElementFloat
|
|
155
|
-
plungerCurrent: PipetteCustomizableConfigElementFloat
|
|
156
|
-
dropTipCurrent: PipetteCustomizableConfigElementFloat
|
|
157
|
-
dropTipSpeed: PipetteCustomizableConfigElementFloat
|
|
158
|
-
modelOffset: List[float]
|
|
159
|
-
nozzleOffset: List[float]
|
|
160
|
-
ulPerMm: List[UlPerMm]
|
|
161
|
-
tipOverlap: Dict[str, float]
|
|
162
|
-
tipLength: PipetteCustomizableConfigElementFloat
|
|
163
|
-
quirks: List[Quirk]
|
|
164
|
-
# these keys are not present in some pipette definitions
|
|
165
|
-
backCompatNames: List[PipetteName]
|
|
166
|
-
idleCurrent: float
|
|
167
|
-
returnTipHeight: float
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
class PipetteFusedSpec(PipetteNameSpec, PipetteModelSpec, total=False):
|
|
171
|
-
pass
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
class PipetteModelSpecs(TypedDict):
|
|
175
|
-
config: Dict[PipetteModel, PipetteModelSpec]
|
|
176
|
-
mutableConfigs: List[str]
|
|
177
|
-
validQuirks: List[str]
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
from typing import Any, Dict, Union
|
|
3
|
-
from .types import MutableConfig, QuirkConfig
|
|
4
|
-
from .model_constants import VALID_QUIRKS
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
DecoderType = Union[Dict[str, Any], Dict[str, QuirkConfig], MutableConfig]
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class MutableConfigurationEncoder(json.JSONEncoder):
|
|
11
|
-
def default(self, obj: object) -> Any:
|
|
12
|
-
if isinstance(obj, MutableConfig) or isinstance(obj, QuirkConfig):
|
|
13
|
-
return obj.dict_for_encode()
|
|
14
|
-
return json.JSONEncoder.default(self, obj)
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
class MutableConfigurationDecoder(json.JSONDecoder):
|
|
18
|
-
def __init__(self) -> None:
|
|
19
|
-
super().__init__(
|
|
20
|
-
object_hook=self.dict_to_obj,
|
|
21
|
-
)
|
|
22
|
-
|
|
23
|
-
def dict_to_obj(self, d: object) -> DecoderType:
|
|
24
|
-
if isinstance(d, dict):
|
|
25
|
-
converted = dict(d)
|
|
26
|
-
if converted.get("value"):
|
|
27
|
-
return self._decode_mutable_config("", converted)
|
|
28
|
-
elif all(isinstance(v, bool) for v in converted.values()):
|
|
29
|
-
return {
|
|
30
|
-
q: QuirkConfig.validate_and_build(q, b)
|
|
31
|
-
for q, b in converted.items()
|
|
32
|
-
if q in VALID_QUIRKS
|
|
33
|
-
}
|
|
34
|
-
return d # type: ignore
|
|
35
|
-
|
|
36
|
-
def _decode_mutable_config(self, k: str, obj: Dict[str, Any]) -> MutableConfig:
|
|
37
|
-
return MutableConfig.build(**obj, name=k)
|