Skip to content

Commit

Permalink
feat(shared-data): labware schema v3 (#16027)
Browse files Browse the repository at this point in the history
  • Loading branch information
caila-marashaj authored Aug 26, 2024
1 parent 6dc8fa4 commit a1a00d9
Show file tree
Hide file tree
Showing 7 changed files with 1,061 additions and 5 deletions.
70 changes: 70 additions & 0 deletions shared-data/js/__tests__/labwareDefSchemaV3.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import path from 'path'
import glob from 'glob'
import { describe, expect, it, beforeAll, test } from 'vitest'

import type { LabwareDefinition3 } from '../types'
import Ajv from 'ajv'
import schema from '../../labware/schemas/3.json'

const fixturesDir = path.join(__dirname, '../../labware/fixtures/3')
const globPattern = '**/*.json'

const ajv = new Ajv({ allErrors: true, jsonPointers: true })
const validate = ajv.compile(schema)

const checkGeometryDefinitions = (
labwareDef: LabwareDefinition3,
filename: string
): void => {
test(`all geometryDefinitionIds specified in {filename} should have an accompanying valid entry in innerLabwareGeometry`, () => {
for (const wellName in labwareDef.wells) {
const wellGeometryId = labwareDef.wells[wellName].geometryDefinitionId

if (wellGeometryId === undefined) {
return
}
if (
labwareDef.innerLabwareGeometry === null ||
labwareDef.innerLabwareGeometry === undefined
) {
return
}

expect(wellGeometryId in labwareDef.innerLabwareGeometry).toBe(true)

const wellDepth = labwareDef.wells[wellName].depth
const wellShape = labwareDef.wells[wellName].shape
const topFrustumHeight =
labwareDef.innerLabwareGeometry[wellGeometryId].frusta[0].topHeight
const topFrustumShape =
labwareDef.innerLabwareGeometry[wellGeometryId].frusta[0].geometry.shape

expect(wellDepth).toEqual(topFrustumHeight)
expect(wellShape).toEqual(topFrustumShape)
}
})
}

describe(`test additions to labware schema in v3`, () => {
const labwarePaths = glob.sync(globPattern, { cwd: fixturesDir })

beforeAll(() => {
// Make sure definitions path didn't break, which would give you false positives
expect(labwarePaths.length).toBeGreaterThan(0)
})

labwarePaths.forEach(labwarePath => {
const filename = path.parse(labwarePath).base
const fullLabwarePath = path.join(fixturesDir, labwarePath)
const labwareDef = require(fullLabwarePath) as LabwareDefinition3

checkGeometryDefinitions(labwareDef, labwarePath)

it(`${filename} validates against schema`, () => {
const valid = validate(labwareDef)
const validationErrors = validate.errors
expect(validationErrors).toBe(null)
expect(valid).toBe(true)
})
})
})
62 changes: 58 additions & 4 deletions shared-data/js/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export interface WellDefinition {
y: number
z: number
'total-liquid-volume': number
geometryDefinitionId?: string | null
}

// typedef for labware definitions under v1 labware schema
Expand Down Expand Up @@ -131,19 +132,19 @@ export interface LabwareBrand {
links?: string[]
}

export interface CircularWellShapeProperties {
export interface CircularWellShape {
shape: 'circular'
diameter: number
}
export interface RectangularWellShapeProperties {
export interface RectangularWellShape {
shape: 'rectangular'
xDimension: number
yDimension: number
}

export type LabwareWellShapeProperties =
| CircularWellShapeProperties
| RectangularWellShapeProperties
| CircularWellShape
| RectangularWellShape

// well without x,y,z
export type LabwareWellProperties = LabwareWellShapeProperties & {
Expand All @@ -155,6 +156,41 @@ export type LabwareWell = LabwareWellProperties & {
x: number
y: number
z: number
geometryDefinitionId?: string
}

export interface CircularCrossSection {
shape: 'circular'
diameter: number
}

export interface RectangularCrossSection {
shape: 'rectangular'
xDimension: number
yDimension: number
}

export interface SphericalSegment {
shape: 'spherical'
radiusOfCurvature: number
depth: number
}

export type TopCrossSection = CircularCrossSection | RectangularCrossSection

export type BottomShape =
| CircularCrossSection
| RectangularCrossSection
| SphericalSegment

export interface BoundedSection {
geometry: TopCrossSection
topHeight: number
}

export interface InnerWellGeometry {
frusta: BoundedSection[]
bottomShape: BottomShape
}

// TODO(mc, 2019-03-21): exact object is tough to use with the initial value in
Expand Down Expand Up @@ -193,6 +229,24 @@ export interface LabwareDefinition2 {
stackingOffsetWithModule?: Record<string, LabwareOffset>
}

export interface LabwareDefinition3 {
version: number
schemaVersion: 3
namespace: string
metadata: LabwareMetadata
dimensions: LabwareDimensions
cornerOffsetFromSlot: LabwareOffset
parameters: LabwareParameters
brand: LabwareBrand
ordering: string[][]
wells: LabwareWellMap
groups: LabwareWellGroup[]
allowedRoles?: LabwareRoles[]
stackingOffsetWithLabware?: Record<string, LabwareOffset>
stackingOffsetWithModule?: Record<string, LabwareOffset>
innerLabwareGeometry?: Record<string, InnerWellGeometry> | null
}

export interface LabwareDefByDefURI {
[defUri: string]: LabwareDefinition2
}
Expand Down
113 changes: 113 additions & 0 deletions shared-data/labware/fixtures/3/fixture_2_plate.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
{
"ordering": [["A1"], ["A2"]],
"schemaVersion": 3,
"version": 3,
"namespace": "fixture",
"metadata": {
"displayName": "12 Channel Trough",
"displayVolumeUnits": "mL",
"displayCategory": "reservoir"
},
"dimensions": {
"xDimension": 127.76,
"yDimension": 85.8,
"zDimension": 44.45
},
"parameters": {
"format": "trough",
"isTiprack": false,
"isMagneticModuleCompatible": false,
"loadName": "fixture_12_trough",
"quirks": ["centerMultichannelOnWells", "touchTipDisabled"]
},
"wells": {
"A1": {
"shape": "circular",
"depth": 42.16,
"diameter": 35.0,
"totalLiquidVolume": 22000,
"x": 13.94,
"y": 42.9,
"z": 2.29,
"geometryDefinitionId": "iuweofiuwhfn"
},
"A2": {
"shape": "rectangular",
"depth": 42.16,
"xDimension": 8.33,
"yDimension": 71.88,
"totalLiquidVolume": 22000,
"x": 23.03,
"y": 42.9,
"z": 2.29,
"geometryDefinitionId": "daiwudhadfhiew"
}
},
"brand": {
"brand": "USA Scientific",
"brandId": ["1061-8150"]
},
"groups": [
{
"wells": ["A1", "A2"],
"metadata": {
"wellBottomShape": "v"
}
}
],
"cornerOffsetFromSlot": {
"x": 0,
"y": 0,
"z": 0
},
"innerLabwareGeometry": {
"daiwudhadfhiew": {
"frusta": [
{
"geometry": {
"shape": "rectangular",
"xDimension": 127.76,
"yDimension": 85.8
},
"topHeight": 42.16
},
{
"geometry": {
"shape": "rectangular",
"xDimension": 70.0,
"yDimension": 50.0
},
"topHeight": 20.0
}
],
"bottomShape": {
"shape": "rectangular",
"xDimension": 2.0,
"yDimension": 3.0
}
},
"iuweofiuwhfn": {
"frusta": [
{
"geometry": {
"shape": "circular",
"diameter": 35.0
},
"topHeight": 42.16
},
{
"geometry": {
"shape": "circular",
"diameter": 22.0
},
"topHeight": 20.0
}
],
"bottomShape": {
"shape": "spherical",
"radiusOfCurvature": 20.0,
"depth": 6.0
}
}
}
}
Loading

0 comments on commit a1a00d9

Please sign in to comment.