diff --git a/src/Plate/EmptyWell.tsx b/src/Plate/EmptyWell.tsx index 100615fe..2a44f6d9 100644 --- a/src/Plate/EmptyWell.tsx +++ b/src/Plate/EmptyWell.tsx @@ -3,17 +3,25 @@ import React from 'react'; import { PALETTE } from '../theme'; -import { PLATE_FLOW } from './constants'; -import { columnForPosition, rowForPosition } from './utils'; +import { CoordinateSystem } from './coordinateSystem'; import { GENERAL_WELL_STYLE } from './wellUtils'; -export function EmptyWell(props: { position: number }) { +export function EmptyWell({ + position, + coordinateSystem, +}: { + position: number; + coordinateSystem: CoordinateSystem; +}) { + const row = coordinateSystem.rowForRowFlowPosition(position); + const column = coordinateSystem.columnForRowFlowPosition(position); + const { setNodeRef, isOver } = useDroppable({ - id: props.position, + id: position, data: { coordinates: { - row: rowForPosition(props.position, PLATE_FLOW), - column: columnForPosition(props.position, PLATE_FLOW), + row, + column, }, }, }); @@ -30,10 +38,7 @@ export function EmptyWell(props: { position: number }) { alignItems: 'center', }} > - - {rowForPosition(props.position, PLATE_FLOW) + - columnForPosition(props.position, PLATE_FLOW)} - + {row + column} ); } diff --git a/src/Plate/FilledWell.tsx b/src/Plate/FilledWell.tsx index 77992310..df21b259 100644 --- a/src/Plate/FilledWell.tsx +++ b/src/Plate/FilledWell.tsx @@ -4,20 +4,20 @@ import React from 'react'; import { PALETTE } from '../theme'; -import { PLATE_FLOW } from './constants'; +import { CoordinateSystem } from './coordinateSystem'; import { PlateWell } from './types'; -import { columnForPosition, rowForPosition } from './utils'; import { GENERAL_WELL_STYLE } from './wellUtils'; export function FilledWell(props: { + coordinateSystem: CoordinateSystem; well: PlateWell; position: number; isDraggable: boolean; }) { const data = { coordinates: { - row: rowForPosition(props.position, PLATE_FLOW), - column: columnForPosition(props.position, PLATE_FLOW), + row: props.coordinateSystem.rowForRowFlowPosition(props.position), + column: props.coordinateSystem.columnForRowFlowPosition(props.position), }, }; diff --git a/src/Plate/RowLabel.tsx b/src/Plate/RowLabel.tsx index d4f11a44..c5431df3 100644 --- a/src/Plate/RowLabel.tsx +++ b/src/Plate/RowLabel.tsx @@ -1,9 +1,11 @@ import React from 'react'; -import { PLATE_FLOW } from './constants'; -import { rowForPosition } from './utils'; +import { CoordinateSystem } from './coordinateSystem'; -export function RowLabel(props: { position: number }) { +export function RowLabel(props: { + position: number; + coordinateSystem: CoordinateSystem; +}) { return ( - {rowForPosition(props.position, PLATE_FLOW)} + + {props.coordinateSystem.rowForRowFlowPosition(props.position)} + ); } diff --git a/src/Plate/Well.tsx b/src/Plate/Well.tsx index c5835182..ff2f5f4a 100644 --- a/src/Plate/Well.tsx +++ b/src/Plate/Well.tsx @@ -1,21 +1,30 @@ +import { Maybe } from '@mll-lab/js-utils'; import React from 'react'; import { EmptyWell } from './EmptyWell'; import { FilledWell } from './FilledWell'; +import { CoordinateSystem } from './coordinateSystem'; import { PlateWell } from './types'; -export function Well(props: { +export function Well({ + coordinateSystem, + position, + well, + isDraggable, +}: { + coordinateSystem: CoordinateSystem; position: number; - well?: PlateWell; + well: Maybe; isDraggable: boolean; }) { - return props.well?.content ? ( + return well?.content ? ( ) : ( - + ); } diff --git a/src/Plate/constants.ts b/src/Plate/constants.ts index 68459a94..2ef11a8b 100644 --- a/src/Plate/constants.ts +++ b/src/Plate/constants.ts @@ -1,6 +1,8 @@ import { range } from 'lodash'; -import { Coordinates, FlowDirection } from './types'; +import { Coordinates } from '../../types'; + +import { FlowDirection } from './types'; const TUBE_COUNT = 96; export const WELLS = range(1, TUBE_COUNT + 1); diff --git a/src/Plate/coordinateSystem.ts b/src/Plate/coordinateSystem.ts new file mode 100644 index 00000000..9c78325e --- /dev/null +++ b/src/Plate/coordinateSystem.ts @@ -0,0 +1,64 @@ +import { range } from 'lodash'; + +import { + CoordinateColumn, + CoordinateColumns, + PlateWell, + CoordinateRow, + CoordinateRows, +} from './types'; + +export abstract class CoordinateSystem { + abstract rows(): CoordinateRows; + + abstract columns(): CoordinateColumns; + + rowForRowFlowPosition(position: number): CoordinateRow { + return this.rows()[Math.floor((position - 1) / this.columnsCount())]; + } + + rowForColumnFlowPosition(position: number): CoordinateRow { + return this.rows()[(position - 1) % this.rowsCount()]; + } + + columnForRowFlowPosition(position: number): CoordinateColumn { + return this.columns()[(position - 1) % this.columnsCount()]; + } + + columnForColumnFlowPosition(position: number): CoordinateColumn { + return this.columns()[Math.floor((position - 1) / this.rowsCount())]; + } + + positionsCount(): number { + return this.columnsCount() * this.rowsCount(); + } + + rowsCount(): number { + return this.rows().length; + } + + columnsCount(): number { + return this.columns().length; + } + + /** Returns every possible position in the coordinate system. */ + allPositions(): Array { + return range(1, this.rowsCount() * this.columnsCount() + 1); + } + + wellAtPosition( + position: number, + data: Array, + ): PlateWell | undefined { + return data.find( + (well) => + well.coordinates.row === this.rowForRowFlowPosition(position) && + well.coordinates.column === this.columnForRowFlowPosition(position), + ); + } + + /** List of columns, 0-padded to all have the same length. */ + paddedColumns(): Array { + return this.columns().map((column) => column.toString().padStart(2, '0')); + } +} diff --git a/src/Plate/coordinateSystem12Well.ts b/src/Plate/coordinateSystem12Well.ts new file mode 100644 index 00000000..cb697959 --- /dev/null +++ b/src/Plate/coordinateSystem12Well.ts @@ -0,0 +1,12 @@ +import { CoordinateSystem } from './coordinateSystem'; +import { CoordinateColumns, CoordinateRows } from './types'; + +export class CoordinateSystem12Well extends CoordinateSystem { + rows(): CoordinateRows { + return ['A', 'B', 'C']; + } + + columns(): CoordinateColumns { + return [1, 2, 3, 4]; + } +} diff --git a/src/Plate/coordinateSystem96Well.ts b/src/Plate/coordinateSystem96Well.ts new file mode 100644 index 00000000..aa04bd04 --- /dev/null +++ b/src/Plate/coordinateSystem96Well.ts @@ -0,0 +1,12 @@ +import { CoordinateSystem } from './coordinateSystem'; +import { CoordinateColumns, CoordinateRows } from './types'; + +export class CoordinateSystem96Well extends CoordinateSystem { + rows(): CoordinateRows { + return ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']; + } + + columns(): CoordinateColumns { + return [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; + } +} diff --git a/src/Plate/coordinates.ts b/src/Plate/coordinates.ts new file mode 100644 index 00000000..62988494 --- /dev/null +++ b/src/Plate/coordinates.ts @@ -0,0 +1,127 @@ +import { CoordinateSystem } from './coordinateSystem'; +import { CoordinatesXXXX, FlowDirection } from './types'; + +export class Coordinates { + public row: CoordinatesXXXX['row']; + + public column: CoordinatesXXXX['column']; + + public coordinateSystem: CoordinateSystem; + + constructor( + row: CoordinatesXXXX['row'], + column: CoordinatesXXXX['column'], + coordinateSystem: CoordinateSystem, + ) { + if (!coordinateSystem.rows().includes(row)) { + throw new Error( + `Expected a row with value of ${coordinateSystem + .rows() + .join(',')}, got ${row}.`, + ); + } + this.row = row; + + if (!coordinateSystem.columns().includes(column)) { + throw new Error( + `Expected a column with value of ${coordinateSystem + .columns() + .join(',')}, got ${column}.`, + ); + } + this.column = column; + + this.coordinateSystem = coordinateSystem; + } + + static fromString( + coordinateString: string, + coordinateSystem: CoordinateSystem, + ): Coordinates { + const rows = coordinateSystem.rows(); + const rowsOptions = rows.join('|'); + + const columns = [ + ...coordinateSystem.columns(), + ...coordinateSystem.paddedColumns(), + ]; + const columnsOptions = columns.join('|'); + + const matches = coordinateString.match( + new RegExp(`^(${rowsOptions})(${columnsOptions})`), + ); + + if (matches === null || matches.length === 0) { + const coordinateSystemClass = coordinateSystem.constructor.name; + throw new Error( + `Expected a coordinate with rows ${JSON.stringify( + rows, + )} and columns ${JSON.stringify( + columns, + )} for ${coordinateSystemClass}, got: ${coordinateString}.`, + ); + } + + return new this( + matches[1] as CoordinatesXXXX['row'], + Number(matches[2]) as CoordinatesXXXX['column'], + coordinateSystem, + ); + } + + toString(): string { + return this.row + this.column; + } + + static fromPosition( + position: number, + direction: FlowDirection, + coordinateSystem: CoordinateSystem, + ): Coordinates { + this.assertPositionInRange(coordinateSystem, position); + + switch (direction) { + case 'column': + return new this( + coordinateSystem.rowForColumnFlowPosition(position), + coordinateSystem.columnForColumnFlowPosition(position), + coordinateSystem, + ); + + case 'row': + return new this( + coordinateSystem.rowForRowFlowPosition(position), + coordinateSystem.columnForRowFlowPosition(position), + coordinateSystem, + ); + } + } + + position(direction: FlowDirection): number { + const rowIndex = this.coordinateSystem.rows().indexOf(this.row); + + const columnIndex = this.coordinateSystem.columns().indexOf(this.column); + + switch (direction) { + case 'row': + return ( + rowIndex * this.coordinateSystem.columns().length + columnIndex + 1 + ); + case 'column': + return columnIndex * this.coordinateSystem.rows().length + rowIndex + 1; + } + } + + static assertPositionInRange( + coordinateSystem: CoordinateSystem, + position: number, + ): void { + if (!coordinateSystem.allPositions().includes(position)) { + throw new Error( + `Expected a position between ${ + coordinateSystem.allPositions()[0] + } - ${coordinateSystem.positionsCount()}, got: ${position}.`, + ); + } + } +} diff --git a/src/Plate/index.stories.tsx b/src/Plate/index.stories.tsx index e1db3ce2..bff4d0ba 100644 --- a/src/Plate/index.stories.tsx +++ b/src/Plate/index.stories.tsx @@ -4,9 +4,10 @@ import React from 'react'; import { PALETTE } from '../theme'; -import { COORDINATES_COLUMNS, COORDINATES_ROWS, WELLS } from './constants'; +import { CoordinateSystem12Well } from './coordinateSystem12Well'; +import { CoordinateSystem96Well } from './coordinateSystem96Well'; +import { Coordinates } from './coordinates'; import { PlateProps, PlateWell } from './types'; -import { coordinatesForPosition } from './utils'; import { Plate } from './index'; @@ -20,20 +21,20 @@ export default { const data: Array = [ { - coordinates: { row: COORDINATES_ROWS[0], column: COORDINATES_COLUMNS[6] }, + coordinates: new Coordinates('A', 6, new CoordinateSystem96Well()), content: It renders any ReactNode, }, { - coordinates: { row: COORDINATES_ROWS[0], column: COORDINATES_COLUMNS[7] }, + coordinates: new Coordinates('A', 7, new CoordinateSystem96Well()), content: 'Test', color: PALETTE.red, }, { - coordinates: { row: COORDINATES_ROWS[1], column: COORDINATES_COLUMNS[2] }, + coordinates: new Coordinates('B', 2, new CoordinateSystem96Well()), content: 'Some text', }, { - coordinates: { row: COORDINATES_ROWS[2], column: COORDINATES_COLUMNS[2] }, + coordinates: new Coordinates('C', 2, new CoordinateSystem96Well()), content: ( <>

Kontrolle

@@ -45,19 +46,47 @@ const data: Array = [ }, ]; -const rowFlowData: Array = WELLS.map((well) => ({ - coordinates: coordinatesForPosition(well, 'row'), - content: well, -})); +const rowFlowData: Array = new CoordinateSystem12Well() + .allPositions() + .map((well) => ({ + coordinates: Coordinates.fromPosition( + well, + 'row', + new CoordinateSystem96Well(), + ), + content: well, + })); -const columnFlowData: Array = WELLS.map((well) => ({ - coordinates: coordinatesForPosition(well, 'column'), - content: well, -})); +const columnFlowData: Array = new CoordinateSystem96Well() + .allPositions() + .map((well) => ({ + coordinates: Coordinates.fromPosition( + well, + 'column', + new CoordinateSystem96Well(), + ), + content: well, + })); const Template: Story> = function Template(args) { return ( + ); +}; + +const Template12Well: Story> = function Template12Well( + args, +) { + return ( + - {COORDINATES_COLUMNS.map((column) => ( + {props.coordinateSystem.columns().map((column) => ( ))} - {WELLS.map((position) => ( + {props.coordinateSystem.allPositions().map((position) => ( - {columnForPosition(position, PLATE_FLOW) === 1 && ( - + {props.coordinateSystem.columnForRowFlowPosition(position) === + 1 && ( + )} diff --git a/src/Plate/types.ts b/src/Plate/types.ts index 938ebee2..adc41c6a 100644 --- a/src/Plate/types.ts +++ b/src/Plate/types.ts @@ -1,21 +1,32 @@ import { Props } from '@dnd-kit/core/dist/components/DndContext/DndContext'; +import { Maybe } from '@mll-lab/js-utils'; import { ReactNode } from 'react'; -export type Coordinates = { - row: 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H'; - column: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12; +import { CoordinateSystem } from './coordinateSystem'; +import { Coordinates } from './coordinates'; + +export type CoordinateRow = 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H'; +export type CoordinateRows = [CoordinateRow, ...Array]; + +export type CoordinateColumn = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12; +export type CoordinateColumns = [CoordinateColumn, ...Array]; + +export type CoordinatesXXXX = { + row: CoordinateRow; + column: CoordinateColumn; }; export type FlowDirection = 'row' | 'column'; export type PlateWell = { coordinates: Coordinates; - content?: ReactNode; - color?: string; + content?: Maybe; + color?: Maybe; }; export type PlateProps = { - data: Array | null; + coordinateSystem: CoordinateSystem; + data: Maybe>; loading?: boolean; /** Activates DragAndDrop of the wells */ isDraggable?: boolean; diff --git a/src/Plate/utils.test.tsx b/src/Plate/utils.test.tsx index 0ad3a0dc..2184382f 100644 --- a/src/Plate/utils.test.tsx +++ b/src/Plate/utils.test.tsx @@ -1,12 +1,13 @@ -import { Coordinates } from './types'; -import { - areEqualCoordinates, - columnForPosition, - convertPositionFromColumnToRowFlow, - convertPositionFromRowToColumnFlow, - ensureCoordinatesInRange, - rowForPosition, -} from './utils'; +import { render } from '@testing-library/react'; +import React from 'react'; + +import { CoordinateSystem12Well } from './coordinateSystem12Well'; +import { CoordinateSystem96Well } from './coordinateSystem96Well'; +import { Coordinates } from './coordinates'; +import { CoordinatesXXXX } from './types'; +import { areEqualCoordinates, ensureCoordinatesInRange } from './utils'; + +import { Plate } from './index'; const data = [ { @@ -71,39 +72,23 @@ const data = [ }, ]; -describe.each(data)('rowForPosition', (dataSet) => { - it('provides the row for a position depending on the flow', () => { - expect(rowForPosition(dataSet.rowFlowPosition, 'row')).toBe(dataSet.row); - expect(rowForPosition(dataSet.columnFlowPosition, 'column')).toBe( - dataSet.row, - ); - }); -}); - -describe.each(data)('columnForPosition', (dataSet) => { - it('provides the column for a position depending on the flow', () => { - expect(columnForPosition(dataSet.rowFlowPosition, 'row')).toBe( - dataSet.column, - ); - expect(columnForPosition(dataSet.columnFlowPosition, 'column')).toBe( - dataSet.column, - ); - }); -}); +describe.each(data)('coordinateForPosition', (dataSet) => { + it('provides the Coordinate for a position depending on the flow', () => { + expect( + Coordinates.fromPosition( + dataSet.rowFlowPosition, + 'row', + new CoordinateSystem96Well(), + ).toString(), + ).toBe(dataSet.row + dataSet.column); -describe.each(data)('convertPositionFromColumnToRowFlow', (dataSet) => { - it(`converts ${dataSet.columnFlowPosition} to ${dataSet.rowFlowPosition}`, () => { - expect(convertPositionFromColumnToRowFlow(dataSet.columnFlowPosition)).toBe( - dataSet.rowFlowPosition, - ); - }); -}); - -describe.each(data)('convertPositionFromRowToColumnFlow', (dataSet) => { - it(`converts ${dataSet.rowFlowPosition} to ${dataSet.columnFlowPosition}`, () => { - expect(convertPositionFromRowToColumnFlow(dataSet.rowFlowPosition)).toBe( - dataSet.columnFlowPosition, - ); + expect( + Coordinates.fromPosition( + dataSet.columnFlowPosition, + 'column', + new CoordinateSystem96Well(), + ).toString(), + ).toBe(dataSet.row + dataSet.column); }); }); @@ -117,22 +102,73 @@ describe('ensureCoordinatesInRange', () => { }); it('works with valid coordinates', () => { - const coordinates: Coordinates = { row: 'A', column: 3 }; + const coordinates: CoordinatesXXXX = { row: 'A', column: 3 }; expect(ensureCoordinatesInRange(coordinates)).toBe(coordinates); }); }); describe('areEqualCoordinates', () => { it('match', () => { - const a: Coordinates = { row: 'A', column: 2 }; + const a: CoordinatesXXXX = { row: 'A', column: 2 }; expect(areEqualCoordinates(a, a)).toBe(true); expect(areEqualCoordinates(a, { ...a, foo: 'bar' })).toBe(true); }); it('no match', () => { - const a: Coordinates = { row: 'A', column: 2 }; - const b: Coordinates = { row: 'B', column: 3 }; + const a: CoordinatesXXXX = { row: 'A', column: 2 }; + const b: CoordinatesXXXX = { row: 'B', column: 3 }; expect(areEqualCoordinates(a, b)).toBe(false); expect(areEqualCoordinates(a, { ...b, foo: 'bar' })).toBe(false); }); }); + +describe('Plate', () => { + it('renders without data', () => { + render( + , + ); + }); +}); + +describe('Coordinate', () => { + it('can be constructed from a string', () => { + const baseExceptionMessage = + 'Expected a coordinate with rows ["A","B","C","D","E","F","G","H"] and columns [1,2,3,4,5,6,7,8,9,10,11,12,"01","02","03","04","05","06","07","08","09","10","11","12"] for CoordinateSystem96Well, got:'; + expect(() => + Coordinates.fromString('', new CoordinateSystem96Well()), + ).toThrow(`${baseExceptionMessage} .`); + expect(() => + Coordinates.fromString('A', new CoordinateSystem96Well()), + ).toThrow(`${baseExceptionMessage} A.`); + expect(() => + Coordinates.fromString('1', new CoordinateSystem96Well()), + ).toThrow(`${baseExceptionMessage} 1.`); + + expect( + Coordinates.fromString('A1', new CoordinateSystem96Well()).toString(), + ).toBe('A1'); + }); +}); + +describe('Coordinate', () => { + it('can can not be used in Plate with different CoordinateSystem', () => { + expect(() => + render( + , + ), + ).toThrow( + 'Property "data" contains records that are not of type "CoordinateSystem12Well": "CoordinateSystem96Well"', + ); + }); +}); diff --git a/src/Plate/utils.ts b/src/Plate/utils.ts index ea137421..71c34c59 100644 --- a/src/Plate/utils.ts +++ b/src/Plate/utils.ts @@ -1,94 +1,11 @@ import { uniq } from 'lodash'; -import { COORDINATES_COLUMNS, COORDINATES_ROWS } from './constants'; -import { Coordinates, FlowDirection, PlateWell } from './types'; - -export function rowForPosition( - position: number, - flowDirection: FlowDirection, -): Coordinates['row'] { - switch (flowDirection) { - case 'row': - return COORDINATES_ROWS[ - Math.floor((position - 1) / COORDINATES_COLUMNS.length) - ]!; - case 'column': - return COORDINATES_ROWS[(position - 1) % COORDINATES_ROWS.length]!; - default: - throw new Error(`Unknown flow direction: ${flowDirection as string}`); - } -} - -export function columnForPosition( - position: number, - flowDirection: FlowDirection, -): Coordinates['column'] { - switch (flowDirection) { - case 'row': - return COORDINATES_COLUMNS[(position - 1) % COORDINATES_COLUMNS.length]!; - case 'column': - return COORDINATES_COLUMNS[ - Math.floor((position - 1) / COORDINATES_ROWS.length) - ]!; - default: - throw new Error(`Unknown flow direction: ${flowDirection as string}`); - } -} - -export function coordinatesForPosition( - position: number, - flowDirection: FlowDirection, -): Coordinates { - return { - row: rowForPosition(position, flowDirection), - column: columnForPosition(position, flowDirection), - }; -} - -export function positionForCoordinates( - coordinates: Coordinates, - flowDirection: FlowDirection, -): number { - const rowIndex = COORDINATES_ROWS.indexOf(coordinates.row); - const columnIndex = COORDINATES_COLUMNS.indexOf(coordinates.column); - - switch (flowDirection) { - case 'row': - return rowIndex * COORDINATES_COLUMNS.length + columnIndex + 1; - case 'column': - return columnIndex * COORDINATES_ROWS.length + rowIndex + 1; - default: - throw new Error(`Unknown flow direction: ${flowDirection as string}`); - } -} - -export function wellAtPosition( - position: number, - data: Array, - flowDirection: FlowDirection, -): PlateWell | undefined { - return data.find( - (well) => - well.coordinates.row === rowForPosition(position, flowDirection) && - well.coordinates.column === columnForPosition(position, flowDirection), - ); -} - -export function convertPositionFromColumnToRowFlow(position: number): number { - const coordinates = coordinatesForPosition(position, 'column'); - - return positionForCoordinates(coordinates, 'row'); -} - -export function convertPositionFromRowToColumnFlow(position: number): number { - const coordinates = coordinatesForPosition(position, 'row'); - - return positionForCoordinates(coordinates, 'column'); -} +import { CoordinateSystem96Well } from './coordinateSystem96Well'; +import { CoordinatesXXXX, PlateProps, PlateWell } from './types'; export function areEqualCoordinates< - A extends Coordinates, - B extends Coordinates, + A extends CoordinatesXXXX, + B extends CoordinatesXXXX, >(a: A, b: B): boolean { return a.row === b.row && a.column === b.column; } @@ -98,22 +15,28 @@ export function ensureCoordinatesInRange< row: string; column: number; }, ->(coordinates: T): T & Coordinates { - if (!COORDINATES_ROWS.includes(coordinates.row as Coordinates['row'])) { +>(coordinates: T): T & CoordinatesXXXX { + if ( + !new CoordinateSystem96Well() + .rows() + .includes(coordinates.row as CoordinatesXXXX['row']) + ) { throw new Error( `The given coordinates row ${coordinates.row} is not in range A-H.`, ); } if ( - !COORDINATES_COLUMNS.includes(coordinates.column as Coordinates['column']) + !new CoordinateSystem96Well() + .columns() + .includes(coordinates.column as CoordinatesXXXX['column']) ) { throw new Error( `The given coordinates column ${coordinates.column} is not in range 1-12.`, ); } - return coordinates as T & Coordinates; + return coordinates as T & CoordinatesXXXX; } export function assertUniquePositions(data: Array): void { @@ -127,3 +50,18 @@ export function assertUniquePositions(data: Array): void { ); } } + +export function assertDataCoordinatesAreInCoordinateSystem( + plateProps: PlateProps, +): void { + plateProps.data?.forEach((well) => { + if ( + well.coordinates.coordinateSystem.constructor.name !== + plateProps.coordinateSystem.constructor.name + ) { + throw new Error( + `Property "data" contains records that are not of type "${plateProps.coordinateSystem.constructor.name}": "${well.coordinates.coordinateSystem.constructor.name}"`, + ); + } + }); +}