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}"`,
+ );
+ }
+ });
+}