diff --git a/client/component/README.md b/client/component/README.md index 5b63baf7..9badcd71 100644 --- a/client/component/README.md +++ b/client/component/README.md @@ -3,6 +3,7 @@ View the frontend Typescript documentation [here](https://diamondlightsource.github.io/davidia/typedocs/index.html). ## Installation + ### `pnpm add @diamondlightsource/davidia` ## Vite configuration @@ -10,8 +11,8 @@ View the frontend Typescript documentation [here](https://diamondlightsource.git Some davidia dependencies require a global object to be defined when used in Vite applications. Add the following to your vite.config.ts: ```js -import { defineConfig } from "vite"; -import react from "@vitejs/plugin-react"; +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; export default defineConfig({ plugins: [react()], @@ -19,4 +20,4 @@ export default defineConfig({ global: {}, }, }); -``` \ No newline at end of file +``` diff --git a/client/component/package.json b/client/component/package.json index 9d3b44f6..e2c95ac8 100644 --- a/client/component/package.json +++ b/client/component/package.json @@ -40,6 +40,8 @@ "d3-scale": "^4.0.2", "ndarray-concat-rows": "^1.0.1", "ndarray-linspace": "^2.0.3", + "ndarray-tile": "^1.0.3", + "ndarray-unsqueeze": "^1.0.3", "react-colorful": "^5.8.0", "react-draggable": "^4.7.0", "react-icons": "^5.7.0", diff --git a/client/component/src/ImagePlot.tsx b/client/component/src/ImagePlot.tsx index 54eb439d..54f4585b 100644 --- a/client/component/src/ImagePlot.tsx +++ b/client/component/src/ImagePlot.tsx @@ -1,4 +1,6 @@ import { Aspect, type ModifierKey, RgbVis } from '@h5web/lib'; +import unsqueeze from 'ndarray-unsqueeze'; +import tile from 'ndarray-tile'; import SelectionComponent from './SelectionComponent'; import { createInteractionsConfig, InteractionModeType } from './utils'; @@ -38,6 +40,23 @@ function getAxisOffsets( }; } +function makeRGB(values: NDT): NDT | null { + const shape = values.shape; + + if (shape.length == 2) { + return tile(unsqueeze(values), [1, 1, 3]) as NDT; + } else if (shape.length == 3) { + const channels = shape[2]; + if (channels == 1) { + return tile(values, [1, 1, 3]) as NDT; + } else if (channels == 3) { + return values; + } + } + console.log('Shape of array is not compatible with RGB array:', shape); + return null; +} + export function ImageVisCanvas({ xValues, yValues, values }: Props) { const { title, @@ -55,35 +74,39 @@ export function ImageVisCanvas({ xValues, yValues, values }: Props) { } = usePlotCustomizationContext(); const interactionsConfig = createInteractionsConfig(mode); + const rgbValues = makeRGB(values); + return ( - - {canSelect && ( - - )} - + rgbValues && ( + + {canSelect && ( + + )} + + ) ); } diff --git a/client/example/src/App.tsx b/client/example/src/App.tsx index a7cc7986..655f432d 100644 --- a/client/example/src/App.tsx +++ b/client/example/src/App.tsx @@ -62,6 +62,16 @@ function generateImage(width: number, height: number) { return ndarray(rgb, [height, width, 3]) as NDT; } +function generateGreyImage(width: number, height: number, threeD = false) { + const rgb = new Uint8Array(width * height); + + for (let i = 0; i < rgb.length; i++) { + rgb[i] = Math.random() * 255; + } + if (threeD) return ndarray(rgb, [height, width, 1]) as NDT; + return ndarray(rgb, [height, width]) as NDT; +} + class AppMain extends React.Component { uuid: string; constructor(props: AppMainProps) { @@ -136,6 +146,10 @@ class AppMain extends React.Component { const port = import.meta.env.VITE_WS_PORT ?? window.location.port; console.log('host:', host, 'port:', port); + const portraitImage = generateImage(6, 12); + const landscapeImage = generateGreyImage(9, 2); + const squareImage = generateGreyImage(6, 6, true); + return ( @@ -217,7 +231,7 @@ class AppMain extends React.Component { @@ -233,7 +247,7 @@ class AppMain extends React.Component { @@ -245,7 +259,7 @@ class AppMain extends React.Component { yLabel: 'Y Co-ordinate', }} tightAxes={this.state.tightImagePlots} - values={generateImage(6, 6)} + values={squareImage} /> diff --git a/client/types/ndarray-tile/index.d.ts b/client/types/ndarray-tile/index.d.ts new file mode 100644 index 00000000..04572ea9 --- /dev/null +++ b/client/types/ndarray-tile/index.d.ts @@ -0,0 +1,5 @@ +declare module 'ndarray-tile' { + import type { NdArray, TypedArray } from 'ndarray'; + type NDT = NdArray; + export default function tile(array: NDT, repeats: number[]): NDT; +} diff --git a/client/types/ndarray-unsqueeze/index.d.ts b/client/types/ndarray-unsqueeze/index.d.ts new file mode 100644 index 00000000..49dbec90 --- /dev/null +++ b/client/types/ndarray-unsqueeze/index.d.ts @@ -0,0 +1,5 @@ +declare module 'ndarray-unsqueeze' { + import type { NdArray, TypedArray } from 'ndarray'; + type NDT = NdArray; + export default function unsqueeze(array: NDT, axis?: number): NDT; +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2cd5a1c4..e1d37322 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -105,6 +105,12 @@ importers: ndarray-linspace: specifier: ^2.0.3 version: 2.0.3 + ndarray-tile: + specifier: ^1.0.3 + version: 1.0.3 + ndarray-unsqueeze: + specifier: ^1.0.3 + version: 1.0.3 react-colorful: specifier: ^5.8.0 version: 5.8.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -3396,6 +3402,12 @@ packages: ndarray-scratch@1.2.0: resolution: {integrity: sha512-a4pASwB1jQyJcKLYrwrladVfDZDUGc78qLJZbHyb1Q4rhte0URhzc6ALQpBcauwgov0sXLwZz3vYH5jKAhSMIg==} + ndarray-tile@1.0.3: + resolution: {integrity: sha512-8kTPCNwi1RHSWfZClIpTlS+edeHNdBv7YqtKznRqModPHIcqDuJIPum4+GllLBxu67+63RZJgGAcFsc0rGo32A==} + + ndarray-unsqueeze@1.0.3: + resolution: {integrity: sha512-Gvw7eA3rlhKFrOQuNinhQyYFl6dHDix8DG3CRWQAQA4eDPHNfdRdzX80JRAmnLue623ShykszC2ru/JRyl5wig==} + ndarray@1.0.19: resolution: {integrity: sha512-B4JHA4vdyZU30ELBw3g7/p9bZupyew5a7tX1Y/gGeF2hafrPaQZhgrGQfsvgfYbgdFZjYwuEcnaobeM/WMW+HQ==} @@ -8261,6 +8273,15 @@ snapshots: ndarray-ops: 1.2.2 typedarray-pool: 1.2.0 + ndarray-tile@1.0.3: + dependencies: + ndarray-ops: 1.2.2 + ndarray-scratch: 1.2.0 + + ndarray-unsqueeze@1.0.3: + dependencies: + ndarray: 1.0.19 + ndarray@1.0.19: dependencies: iota-array: 1.0.0 diff --git a/tsconfig.json b/tsconfig.json index 2e7c1ed9..4e46cc2e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -13,6 +13,8 @@ "typeRoots": [ "client/types" ], "paths": { "ndarray-concat-rows": ["./client/types/ndarray-concat-rows"], + "ndarray-tile": ["./client/types/ndarray-tile"], + "ndarray-unsqueeze": ["./client/types/ndarray-unsqueeze"], "@diamondlightsource/davidia": [ "./client/component/src/index.ts" ],