@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,13 +0,0 @@
1
- import { OT2_ROBOT_TYPE, THERMOCYCLER_MODULE_TYPE } from '..'
2
- import type { ModuleType, RobotType } from '..'
3
-
4
- export function getOccludedSlotCountForModule(
5
- moduleType: ModuleType,
6
- robotType: RobotType
7
- ): number {
8
- if (moduleType === THERMOCYCLER_MODULE_TYPE) {
9
- return robotType === OT2_ROBOT_TYPE ? 4 : 2
10
- } else {
11
- return 1
12
- }
13
- }
@@ -1,12 +0,0 @@
1
- import type { Coordinates } from '../types'
2
-
3
- export function getVectorDifference(
4
- pointA: Coordinates,
5
- pointB: Coordinates
6
- ): Coordinates {
7
- return {
8
- x: pointA.x - pointB.x,
9
- y: pointA.y - pointB.y,
10
- z: pointA.z - pointB.z,
11
- }
12
- }
@@ -1,12 +0,0 @@
1
- import type { Coordinates } from '../types'
2
-
3
- export function getVectorSum(
4
- pointA: Coordinates,
5
- pointB: Coordinates
6
- ): Coordinates {
7
- return {
8
- x: pointA.x + pointB.x,
9
- y: pointA.y + pointB.y,
10
- z: pointA.z + pointB.z,
11
- }
12
- }
@@ -1,86 +0,0 @@
1
- import range from 'lodash/range'
2
- import { get96Channel384WellPlateWells } from './get96Channel384WellPlateWells'
3
- import { getLabwareHasQuirk, orderWells, sortWells } from './index'
4
- import type { LabwareDefinition2 } from '../types'
5
-
6
- // TODO Ian 2018-03-13 pull pipette offsets/positions from some pipette definitions data
7
- const OFFSET_8_CHANNEL = 9 // offset in mm between tips
8
-
9
- const MULTICHANNEL_TIP_SPAN = OFFSET_8_CHANNEL * (8 - 1) // length in mm from first to last tip of multichannel
10
-
11
- export function findWellAt(
12
- labwareDef: LabwareDefinition2,
13
- x: number,
14
- y: number
15
- ): string | null | undefined {
16
- return Object.keys(labwareDef.wells)
17
- .sort(sortWells)
18
- .find((wellName: string) => {
19
- const well = labwareDef.wells[wellName]
20
-
21
- if (well.shape === 'circular') {
22
- return (
23
- Math.sqrt(Math.pow(x - well.x, 2) + Math.pow(y - well.y, 2)) <
24
- well.diameter / 2
25
- )
26
- }
27
-
28
- // Not circular, must be a rectangular well
29
- // For rectangular wells, (x, y) is at the center.
30
- return (
31
- Math.abs(x - well.x) < well.xDimension / 2 &&
32
- Math.abs(y - well.y) < well.yDimension / 2
33
- )
34
- })
35
- }
36
-
37
- // "topWellName" means well at the "top" of the column we're accessing: usually A row, or B row for 384-format
38
- export function getWellNamePerMultiTip(
39
- labwareDef: LabwareDefinition2,
40
- topWellName: string,
41
- channels: 8 | 96
42
- ): string[] | null {
43
- const topWell = labwareDef.wells[topWellName]
44
- if (!topWell) {
45
- console.warn(
46
- `well "${topWellName}" does not exist in labware ${labwareDef?.namespace}/${labwareDef?.parameters?.loadName}, cannot getWellNamePerMultiTip`
47
- )
48
- return null
49
- }
50
-
51
- const { x, y } = topWell
52
- let offsetYTipPositions: number[] = range(0, 8).map(
53
- tipNo => y - tipNo * OFFSET_8_CHANNEL
54
- )
55
- const orderedWells = orderWells(labwareDef.ordering, 't2b', 'l2r')
56
-
57
- if (getLabwareHasQuirk(labwareDef, 'centerMultichannelOnWells')) {
58
- // move multichannel up in Y by half the pipette's tip span to center it in the well
59
- offsetYTipPositions = offsetYTipPositions.map(
60
- tipPosY => tipPosY + MULTICHANNEL_TIP_SPAN / 2
61
- )
62
- }
63
- // Return null for containers with any undefined wells
64
- const wellsAccessed = offsetYTipPositions.reduce(
65
- (acc: string[] | null, tipPosY) => {
66
- const wellForTip = findWellAt(labwareDef, x, tipPosY)
67
- if (acc === null || !wellForTip) {
68
- return null
69
- }
70
- return acc.concat(wellForTip)
71
- },
72
- []
73
- )
74
-
75
- let ninetySixChannelWells = orderedWells
76
- // special casing 384 well plates to be every other well
77
- // both on the x and y ases.
78
- if (orderedWells.length === 384) {
79
- ninetySixChannelWells = get96Channel384WellPlateWells(
80
- orderedWells,
81
- topWellName
82
- )
83
- }
84
-
85
- return channels === 8 ? wellsAccessed : ninetySixChannelWells
86
- }
@@ -1,16 +0,0 @@
1
- import type { LabwareDefinition2 } from '../types'
2
- export const getWellTotalVolume = (
3
- labwareDef: LabwareDefinition2,
4
- wellName: string
5
- ): number | null | undefined => {
6
- const well = labwareDef.wells[wellName]
7
-
8
- if (!well) {
9
- console.warn(
10
- `No well "${wellName}" found for labware ${labwareDef?.namespace}/${labwareDef?.parameters?.loadName}/${labwareDef?.version}"`
11
- )
12
- return null
13
- }
14
-
15
- return well.totalLiquidVolume
16
- }
@@ -1,347 +0,0 @@
1
- import assert from 'assert'
2
- import uniq from 'lodash/uniq'
3
-
4
- import { OPENTRONS_LABWARE_NAMESPACE } from '../constants'
5
- import standardOt2DeckDef from '../../deck/definitions/4/ot2_standard.json'
6
- import standardFlexDeckDef from '../../deck/definitions/4/ot3_standard.json'
7
- import type {
8
- DeckDefinition,
9
- LabwareDefinition2,
10
- ModuleModel,
11
- RobotType,
12
- ThermalAdapterName,
13
- } from '../types'
14
-
15
- export { getWellNamePerMultiTip } from './getWellNamePerMultiTip'
16
- export { getWellTotalVolume } from './getWellTotalVolume'
17
- export { wellIsRect } from './wellIsRect'
18
- export { orderWells } from './orderWells'
19
- export { get96Channel384WellPlateWells } from './get96Channel384WellPlateWells'
20
-
21
- export * from './parseProtocolData'
22
- export * from './volume'
23
- export * from './wellSets'
24
- export * from './getModuleVizDims'
25
- export * from './getVectorDifference'
26
- export * from './getVectorSum'
27
- export * from './getLoadedLabwareDefinitionsByUri'
28
- export * from './getOccludedSlotCountForModule'
29
- export * from './labwareInference'
30
- export * from './getAddressableAreasInProtocol'
31
-
32
- export const getLabwareDefIsStandard = (def: LabwareDefinition2): boolean =>
33
- def?.namespace === OPENTRONS_LABWARE_NAMESPACE
34
-
35
- export const getLabwareDefURI = (def: LabwareDefinition2): string =>
36
- constructLabwareDefURI(
37
- def.namespace,
38
- def.parameters.loadName,
39
- String(def.version)
40
- )
41
-
42
- export const constructLabwareDefURI = (
43
- namespace: string,
44
- loadName: string,
45
- version: string
46
- ): string => `${namespace}/${loadName}/${version}`
47
-
48
- // Load names of "retired" labware
49
- // TODO(mc, 2019-12-3): how should this correspond to LABWAREV2_DO_NOT_LIST?
50
- // see shared-data/js/getLabware.js
51
- const RETIRED_LABWARE = [
52
- 'geb_96_tiprack_10ul',
53
- 'geb_96_tiprack_1000ul',
54
- 'opentrons_1_trash_850ml_fixed',
55
- 'opentrons_10_tuberack_falcon_4x50ml_6x15ml_conical_acrylic',
56
- 'opentrons_24_tuberack_eppendorf_2ml_safelock_snapcap_acrylic',
57
- 'opentrons_24_tuberack_generic_0.75ml_snapcap_acrylic',
58
- 'opentrons_40_aluminumblock_eppendorf_24x2ml_safelock_snapcap_generic_16x0.2ml_pcr_strip',
59
- 'opentrons_96_aluminumblock_biorad_wellplate_200ul',
60
- 'tipone_96_tiprack_200ul',
61
- 'eppendorf_96_tiprack_1000ul_eptips',
62
- 'eppendorf_96_tiprack_10ul_eptips',
63
- // Replaced by opentrons_96_wellplate_200ul_pcr_full_skirt
64
- // https://opentrons.atlassian.net/browse/RLAB-230
65
- 'armadillo_96_wellplate_200ul_pcr_full_skirt',
66
- ]
67
-
68
- export const getLabwareDisplayName = (
69
- labwareDef: LabwareDefinition2
70
- ): string => {
71
- const { displayName } = labwareDef.metadata
72
-
73
- if (
74
- getLabwareDefIsStandard(labwareDef) &&
75
- RETIRED_LABWARE.includes(labwareDef.parameters.loadName)
76
- ) {
77
- return `(Retired) ${displayName}`
78
- }
79
-
80
- return displayName
81
- }
82
-
83
- export const getTiprackVolume = (labwareDef: LabwareDefinition2): number => {
84
- assert(
85
- labwareDef.parameters.isTiprack,
86
- `getTiprackVolume expected a tiprack labware ${getLabwareDefURI(
87
- labwareDef
88
- )}, but 'isTiprack' isn't true`
89
- )
90
- // NOTE: Ian 2019-04-16 assuming all tips are the same volume across the rack
91
- const volume = labwareDef.wells.A1.totalLiquidVolume
92
- assert(
93
- volume >= 0,
94
- `getTiprackVolume expected tip volume to be at least 0, got ${volume}`
95
- )
96
- return volume
97
- }
98
-
99
- export function getLabwareHasQuirk(
100
- labwareDef: LabwareDefinition2,
101
- quirk: string
102
- ): boolean {
103
- const quirks = labwareDef.parameters.quirks
104
- return quirks ? quirks.includes(quirk) : false
105
- }
106
-
107
- export const intToAlphabetLetter = (
108
- i: number,
109
- lowerCase: boolean = false
110
- ): string => String.fromCharCode((lowerCase ? 96 : 65) + i)
111
- // These utils are great candidates for unit tests
112
- export const toWellName = ({
113
- rowNum,
114
- colNum,
115
- }: {
116
- rowNum: number
117
- colNum: number
118
- }): string => String.fromCharCode(rowNum + 65) + (colNum + 1)
119
-
120
- function _parseWell(well: string): [string, number] {
121
- const res = well.match(/([A-Z]+)(\d+)/)
122
- const letters = res && res[1]
123
- const number = res && parseInt(res[2])
124
-
125
- if (!letters || number == null || Number.isNaN(number)) {
126
- console.warn(
127
- `Could not parse well ${well}. Got letters: "${
128
- letters || 'void'
129
- }", number: "${number || 'void'}"`
130
- )
131
- return ['', NaN]
132
- }
133
-
134
- return [letters, number]
135
- }
136
-
137
- /** A compareFunction for sorting an array of well names
138
- * Goes down the columns (A1 to H1 on 96 plate)
139
- * Then L to R across rows (1 to 12 on 96 plate)
140
- */
141
- export function sortWells(a: string, b: string): number {
142
- const [letterA, numberA] = _parseWell(a)
143
-
144
- const [letterB, numberB] = _parseWell(b)
145
-
146
- if (numberA !== numberB) {
147
- return numberA > numberB ? 1 : -1
148
- }
149
-
150
- if (letterA.length !== letterB.length) {
151
- // Eg 'B' vs 'AA'
152
- return letterA.length > letterB.length ? 1 : -1
153
- }
154
-
155
- return letterA > letterB ? 1 : -1
156
- }
157
-
158
- export function splitWellsOnColumn(sortedArray: string[]): string[][] {
159
- return sortedArray.reduce<string[][]>((acc, curr) => {
160
- const lastColumn = acc.slice(-1)
161
-
162
- if (lastColumn === undefined || lastColumn.length === 0) {
163
- return [[curr]]
164
- }
165
-
166
- const lastEle = lastColumn[0].slice(-1)[0].slice(1)
167
-
168
- if (Number(curr.slice(1)) > Number(lastEle)) {
169
- return [...acc, [curr]]
170
- } else {
171
- return [...acc.slice(0, -1), [...lastColumn[0], curr]]
172
- }
173
- }, [])
174
- }
175
-
176
- export const getWellDepth = (
177
- labwareDef: LabwareDefinition2,
178
- well: string
179
- ): number => labwareDef.wells[well].depth
180
-
181
- // NOTE: this is used in PD for converting "offset from top" to "mm from bottom".
182
- // Assumes all wells have same offset because multi-offset not yet supported.
183
- // TODO: Ian 2019-07-13 return {[string: well]: offset} to support multi-offset
184
- export const getWellsDepth = (
185
- labwareDef: LabwareDefinition2,
186
- wells: string[]
187
- ): number => {
188
- const offsets = wells.map(well => getWellDepth(labwareDef, well))
189
-
190
- if (uniq(offsets).length !== 1) {
191
- console.warn(
192
- `expected wells ${JSON.stringify(
193
- wells
194
- )} to all have same offset, but they were different. Labware def is ${getLabwareDefURI(
195
- labwareDef
196
- )}`
197
- )
198
- }
199
-
200
- return offsets[0]
201
- }
202
-
203
- export const getSlotHasMatingSurfaceUnitVector = (
204
- deckDef: DeckDefinition,
205
- addressableAreaName: string
206
- ): boolean => {
207
- const matingSurfaceUnitVector = deckDef.locations.addressableAreas.find(
208
- aa => aa.id === addressableAreaName
209
- )?.matingSurfaceUnitVector
210
-
211
- return Boolean(matingSurfaceUnitVector)
212
- }
213
-
214
- export const getAreSlotsHorizontallyAdjacent = (
215
- slotNameA?: string | null,
216
- slotNameB?: string | null
217
- ): boolean => {
218
- if (slotNameA == null || slotNameB == null) {
219
- return false
220
- }
221
- const slotANumber = parseInt(slotNameA)
222
- const slotBNumber = parseInt(slotNameB)
223
- if (isNaN(slotBNumber) || isNaN(slotANumber)) {
224
- return false
225
- }
226
- const orderedSlots = standardOt2DeckDef.locations.cutouts
227
- // intentionally not substracting by 1 because trash (slot 12) should not count
228
- const numSlots = orderedSlots.length
229
- if (slotBNumber > numSlots || slotANumber > numSlots) {
230
- return false
231
- }
232
- const slotWidth = orderedSlots[1].position[0] - orderedSlots[0].position[0]
233
- const slotAPosition = orderedSlots[slotANumber - 1].position
234
- const slotBPosition = orderedSlots[slotBNumber - 1].position
235
-
236
- const yPositionSlotA = slotAPosition[1]
237
- const yPositionSlotB = slotBPosition[1]
238
-
239
- const xPositionSlotA = slotAPosition[0]
240
- const xPositionSlotB = slotBPosition[0]
241
-
242
- const areSlotsHorizontallyAdjacent =
243
- yPositionSlotA === yPositionSlotB &&
244
- Math.abs(xPositionSlotA - xPositionSlotB) === slotWidth
245
-
246
- return areSlotsHorizontallyAdjacent
247
- }
248
- export const getAreSlotsVerticallyAdjacent = (
249
- slotNameA?: string | null,
250
- slotNameB?: string | null
251
- ): boolean => {
252
- if (slotNameA == null || slotNameB == null) {
253
- return false
254
- }
255
- const slotANumber = parseInt(slotNameA)
256
- const slotBNumber = parseInt(slotNameB)
257
-
258
- if (isNaN(slotBNumber) || isNaN(slotANumber)) {
259
- return false
260
- }
261
- const orderedSlots = standardOt2DeckDef.locations.cutouts
262
- // intentionally not substracting by 1 because trash (slot 12) should not count
263
- const numSlots = orderedSlots.length
264
-
265
- if (slotBNumber > numSlots || slotANumber > numSlots) {
266
- return false
267
- }
268
- // take the y coord of slot 4, and subtact from y coord of slot 1
269
- const slotHeight = orderedSlots[3].position[1] - orderedSlots[0].position[1]
270
- const slotAPosition = orderedSlots[slotANumber - 1].position
271
- const slotBPosition = orderedSlots[slotBNumber - 1].position
272
-
273
- const yPositionSlotA = slotAPosition[1]
274
- const yPositionSlotB = slotBPosition[1]
275
-
276
- const xPositionSlotA = slotAPosition[0]
277
- const xPositionSlotB = slotBPosition[0]
278
-
279
- const areSlotsVerticallyAdjacent =
280
- xPositionSlotA === xPositionSlotB &&
281
- Math.abs(yPositionSlotA - yPositionSlotB) === slotHeight
282
-
283
- return areSlotsVerticallyAdjacent
284
- }
285
- // TODO(jr, 11/12/23): rename this utility to mention that it
286
- // is only used in the OT-2, same with getAreSlotsHorizontallyAdjacent
287
- // and getAreSlotsVerticallyAdjacent
288
- export const getAreSlotsAdjacent = (
289
- slotNameA?: string | null,
290
- slotNameB?: string | null
291
- ): boolean =>
292
- getAreSlotsHorizontallyAdjacent(slotNameA, slotNameB) ||
293
- getAreSlotsVerticallyAdjacent(slotNameA, slotNameB)
294
-
295
- export const getIsLabwareAboveHeight = (
296
- labwareDef: LabwareDefinition2,
297
- height: number
298
- ): boolean => labwareDef.dimensions.zDimension > height
299
-
300
- export const getAdapterName = (labwareLoadname: string): ThermalAdapterName => {
301
- let adapterName: ThermalAdapterName = 'Universal Flat Adapter'
302
-
303
- if (
304
- labwareLoadname ===
305
- 'opentrons_96_pcr_adapter_nest_wellplate_100ul_pcr_full_skirt'
306
- ) {
307
- adapterName = 'PCR Adapter'
308
- } else if (
309
- labwareLoadname === 'opentrons_96_deep_well_adapter_nest_wellplate_2ml_deep'
310
- ) {
311
- adapterName = 'Deep Well Adapter'
312
- } else if (
313
- labwareLoadname ===
314
- 'opentrons_96_flat_bottom_adapter_nest_wellplate_200ul_flat'
315
- ) {
316
- adapterName = '96 Flat Bottom Adapter'
317
- }
318
-
319
- return adapterName
320
- }
321
-
322
- export const getCalibrationAdapterLoadName = (
323
- moduleModel: ModuleModel
324
- ): string | null => {
325
- switch (moduleModel) {
326
- case 'heaterShakerModuleV1':
327
- return 'opentrons_calibration_adapter_heatershaker_module'
328
- case 'temperatureModuleV2':
329
- return 'opentrons_calibration_adapter_temperature_module'
330
- case 'thermocyclerModuleV2':
331
- return 'opentrons_calibration_adapter_thermocycler_module'
332
- default:
333
- console.error(
334
- `${moduleModel} does not have an associated calibration adapter`
335
- )
336
- return null
337
- }
338
- }
339
-
340
- export const getDeckDefFromRobotType = (
341
- robotType: RobotType
342
- ): DeckDefinition => {
343
- // @ts-expect-error imported JSON not playing nice with TS. see https://github.com/microsoft/TypeScript/issues/32063
344
- return robotType === 'OT-3 Standard'
345
- ? standardFlexDeckDef
346
- : standardOt2DeckDef
347
- }
@@ -1,92 +0,0 @@
1
- import isEqual from 'lodash/isEqual'
2
- import uniqWith from 'lodash/uniqWith'
3
- import round from 'lodash/round'
4
- import sortedUniq from 'lodash/sortedUniq'
5
- import uniq from 'lodash/uniq'
6
- import type {
7
- LabwareWell,
8
- LabwareWellShapeProperties,
9
- LabwareDefinition2,
10
- LabwareWellGroupMetadata,
11
- LabwareBrand,
12
- } from '../types'
13
-
14
- export interface LabwareWellGroupProperties {
15
- xOffsetFromLeft: number
16
- yOffsetFromTop: number
17
- xSpacing: number | null
18
- ySpacing: number | null
19
- wellCount: number
20
- shape: LabwareWellShapeProperties | null
21
- depth: number | null
22
- totalLiquidVolume: number | null
23
- metadata: LabwareWellGroupMetadata
24
- brand: LabwareBrand | null
25
- }
26
- const ROUNDING_PRECISION = 2
27
-
28
- export function getUniqueWellProperties(
29
- definition: LabwareDefinition2
30
- ): LabwareWellGroupProperties[] {
31
- const { groups, wells, dimensions } = definition
32
-
33
- return groups.map(group => {
34
- const wellProps = group.wells.map(n => wells[n])
35
-
36
- const wellDepths = wellProps.map<number>(w => w.depth)
37
- const wellVolumes = wellProps.map<number>(w => w.totalLiquidVolume)
38
- const wellShapes = wellProps.map<LabwareWellShapeProperties>(
39
- (well: LabwareWell) =>
40
- well.shape === 'circular'
41
- ? { shape: well.shape, diameter: well.diameter }
42
- : {
43
- shape: well.shape,
44
- xDimension: well.xDimension,
45
- yDimension: well.yDimension,
46
- }
47
- )
48
-
49
- const xStart = wellProps[0]?.x ?? 0
50
- const yStart = wellProps[0]?.y ?? 0
51
-
52
- return {
53
- metadata: group.metadata,
54
- brand: group.brand || null,
55
- xSpacing: getSpacingIfUniform(wellProps, 'x'),
56
- ySpacing: getSpacingIfUniform(wellProps, 'y'),
57
- xOffsetFromLeft: xStart,
58
- yOffsetFromTop: round(dimensions.yDimension - yStart, ROUNDING_PRECISION),
59
- wellCount: wellProps.length,
60
- depth: getIfConsistent(wellDepths),
61
- totalLiquidVolume: getIfConsistent(wellVolumes),
62
- shape: getIfConsistent(wellShapes),
63
- }
64
- })
65
- }
66
-
67
- export function getIfConsistent<T>(items: T[]): T | null {
68
- return uniqWith(items, isEqual).length === 1 ? items[0] : null
69
- }
70
-
71
- // returning null means "spacing is irregular"; returning 0 means "there is only 1 well along the given axis"
72
- export function getSpacingIfUniform(
73
- wells: LabwareWell[],
74
- axis: 'x' | 'y'
75
- ): number | null {
76
- const wellPositions = sortedUniq(uniq(wells.map(well => well[axis])))
77
- if (wellPositions.length < 2) return 0
78
-
79
- const initialSpacing = round(
80
- wellPositions[1] - wellPositions[0],
81
- ROUNDING_PRECISION
82
- )
83
-
84
- for (let i = 2; i < wellPositions.length; i++) {
85
- const pos = wellPositions[i]
86
- const prevWellPos = wellPositions[i - 1]
87
- const spacing = round(pos - prevWellPos, ROUNDING_PRECISION)
88
- if (spacing !== initialSpacing) return null
89
- }
90
-
91
- return Math.abs(initialSpacing)
92
- }
@@ -1,69 +0,0 @@
1
- import zipWith from 'lodash/zipWith'
2
- import uniq from 'lodash/uniq'
3
- import compact from 'lodash/compact'
4
- import flatten from 'lodash/flatten'
5
-
6
- export type WellOrderOption = 'l2r' | 'r2l' | 't2b' | 'b2t'
7
-
8
- // labware definitions in shared-data have an ordering
9
- // attribute which is an Array of Arrays of wells. Each inner
10
- // Array represents a physical column of wells on the labware
11
- // this function takes that 2d Array of columns and returns
12
- // the same wells in a 2d Array where each inner Array represents
13
- // a physical row of wells on the labware.
14
- // e.g.
15
- // [ \ [
16
- // ['A1', 'B1'], === \ ['A1', 'A2']
17
- // ['A2', 'B2'] === / ['B1', 'B2']
18
- // ] / ]
19
- //
20
- const _orderingColsToRows = (ordering: string[][]): string[][] =>
21
- zipWith(...ordering, (...col) => compact(uniq(col)))
22
-
23
- // given a default "ordering" 2d array from labware definitions
24
- // where each inner array represents a physical column of wells
25
- // and well order option selections (e.g. 'l2r', 'r2l', 't2b', 'b2t')
26
- // this function returns a 1d array of wells from the labware
27
- // ordered by the given traversal technique
28
- export const orderWells = (
29
- defaultOrdering: string[][],
30
- first: WellOrderOption,
31
- second: WellOrderOption
32
- ): string[] => {
33
- let orderedWells: string[][] = []
34
-
35
- if (first === 't2b') {
36
- if (second === 'l2r') {
37
- orderedWells = defaultOrdering
38
- } else if (second === 'r2l') {
39
- orderedWells = defaultOrdering.slice().reverse()
40
- }
41
- } else if (first === 'b2t') {
42
- if (second === 'l2r') {
43
- orderedWells = defaultOrdering.map(col => col.slice().reverse())
44
- } else if (second === 'r2l') {
45
- orderedWells = defaultOrdering
46
- .slice()
47
- .reverse()
48
- .map(col => col.slice().reverse())
49
- }
50
- } else if (first === 'l2r') {
51
- if (second === 't2b') {
52
- orderedWells = _orderingColsToRows(defaultOrdering)
53
- } else if (second === 'b2t') {
54
- orderedWells = _orderingColsToRows(defaultOrdering).slice().reverse()
55
- }
56
- } else if (first === 'r2l') {
57
- if (second === 't2b') {
58
- orderedWells = _orderingColsToRows(defaultOrdering).map(col =>
59
- col.slice().reverse()
60
- )
61
- } else if (second === 'b2t') {
62
- orderedWells = _orderingColsToRows(defaultOrdering)
63
- .slice()
64
- .reverse()
65
- .map(col => col.slice().reverse())
66
- }
67
- }
68
- return flatten(orderedWells)
69
- }