Skip to content

Commit

Permalink
Allow flipping RGB visualizations on X and Y
Browse files Browse the repository at this point in the history
  • Loading branch information
axelboc committed Apr 12, 2024
1 parent 524eab5 commit cffd7e9
Show file tree
Hide file tree
Showing 6 changed files with 184 additions and 8 deletions.
126 changes: 126 additions & 0 deletions apps/storybook/src/RgbVis.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import { ImageType, mockValues, RgbVis } from '@h5web/lib';
import type { Meta, StoryObj } from '@storybook/react';

import FillHeight from './decorators/FillHeight';

const dataArray = mockValues.threeD_rgb();

const meta = {
title: 'Visualizations/RgbVis',
component: RgbVis,
decorators: [FillHeight],
parameters: {
layout: 'fullscreen',
controls: { sort: 'requiredFirst' },
},
args: {
dataArray,
aspect: 'equal',
showGrid: true,
},
argTypes: {
dataArray: { control: false },
aspect: {
control: { type: 'inline-radio' },
options: ['auto', 'equal', 0.25],
},
},
} satisfies Meta<typeof RgbVis>;

export default meta;
type Story = StoryObj<typeof meta>;

export const Default = {} satisfies Story;

export const BGR = {
args: {
imageType: ImageType.BGR,
},
} satisfies Story;

export const AxisValues = {
args: {
abscissaParams: {
value: Array.from(
{ length: dataArray.shape[1] }, // works even when right edge of last pixel is not provided
(_, i) => 100 + 10 * i,
),
},
ordinateParams: {
value: Array.from(
{ length: dataArray.shape[0] + 1 },
(_, i) => -100 + 10 * i,
),
},
},
} satisfies Story;

export const DescendingAxisValues = {
args: {
abscissaParams: {
value: Array.from(
{ length: dataArray.shape[1] }, // works even when right edge of last pixel is not provided
(_, i) => -100 - 10 * i,
),
},
ordinateParams: {
value: Array.from(
{ length: dataArray.shape[0] + 1 },
(_, i) => -100 - 10 * i,
),
},
},
} satisfies Story;

export const TypedArray = {
args: {
dataArray: mockValues.int8_rgb(),
},
} satisfies Story;

export const ChangeInteractionKeys = {
args: {
interactions: {
pan: { modifierKey: 'Shift' },
selectToZoom: { modifierKey: 'Control' },
},
},
} satisfies Story;

export const AutoAspectRatio = {
args: {
aspect: 'auto',
},
} satisfies Story;

export const CustomAspectRatio = {
args: {
aspect: 0.25,
},
} satisfies Story;

export const FlipXAxis = {
args: {
dataArray,
flipXAxis: true,
},
} satisfies Story;

export const FlipYAxis = {
args: {
dataArray,
flipYAxis: true,
},
} satisfies Story;

export const NoGrid = {
args: {
showGrid: false,
},
} satisfies Story;

export const WithTitle = {
args: {
title: 'RGB image',
},
} satisfies Story;
4 changes: 3 additions & 1 deletion packages/app/src/vis-packs/core/rgb/MappedRgbVis.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ function MappedRgbVis(props: Props) {
config,
} = props;

const { showGrid, keepRatio, imageType } = config;
const { showGrid, keepRatio, imageType, flipXAxis, flipYAxis } = config;
const { shape: dims } = dataset;

const [slicedDims, slicedMapping] = useSlicedDimsAndMapping(dims, dimMapping);
Expand Down Expand Up @@ -62,6 +62,8 @@ function MappedRgbVis(props: Props) {
label: axisLabels?.[yDimIndex],
value: axisValues?.[yDimIndex],
}}
flipXAxis={flipXAxis}
flipYAxis={flipYAxis}
/>
</>
);
Expand Down
26 changes: 25 additions & 1 deletion packages/app/src/vis-packs/core/rgb/RgbToolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@ import {
ToggleGroup,
Toolbar,
} from '@h5web/lib';
import { MdAspectRatio, MdGridOn } from 'react-icons/md';
import {
MdAspectRatio,
MdGridOn,
MdSwapHoriz,
MdSwapVert,
} from 'react-icons/md';

import { getImageInteractions } from '../utils';
import type { RgbVisConfig } from './config';
Expand All @@ -20,9 +25,13 @@ function RgbToolbar(props: Props) {
imageType,
keepRatio,
showGrid,
flipXAxis,
flipYAxis,
setImageType,
toggleKeepRatio,
toggleGrid,
toggleXAxisFlip,
toggleYAxisFlip,
} = config;

return (
Expand All @@ -41,6 +50,21 @@ function RgbToolbar(props: Props) {

<Separator />

<ToggleBtn
label="X"
aria-label="Flip X"
icon={MdSwapHoriz}
value={flipXAxis}
onToggle={toggleXAxisFlip}
/>
<ToggleBtn
label="Y"
aria-label="Flip Y"
icon={MdSwapVert}
value={flipYAxis}
onToggle={toggleYAxisFlip}
/>

<ToggleBtn
label="Keep ratio"
icon={MdAspectRatio}
Expand Down
16 changes: 15 additions & 1 deletion packages/app/src/vis-packs/core/rgb/config.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ export interface RgbVisConfig {

imageType: ImageType;
setImageType: (channels: ImageType) => void;

flipXAxis: boolean;
toggleXAxisFlip: () => void;

flipYAxis: boolean;
toggleYAxisFlip: () => void;
}

function createRgbConfigStore() {
Expand All @@ -30,10 +36,18 @@ function createRgbConfigStore() {

imageType: ImageType.RGB,
setImageType: (imageType: ImageType) => set({ imageType }),

flipXAxis: false,
toggleXAxisFlip: () =>
set((state) => ({ flipXAxis: !state.flipXAxis })),

flipYAxis: true,
toggleYAxisFlip: () =>
set((state) => ({ flipYAxis: !state.flipYAxis })),
}),
{
name: 'h5web:rgb',
version: 2,
version: 3,
},
),
);
Expand Down
7 changes: 4 additions & 3 deletions packages/lib/src/vis/rgb/RgbMesh.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import type { NdArray } from 'ndarray';
import { useMemo } from 'react';

import type { VisMeshProps } from '../shared/VisMesh';
import VisMesh from '../shared/VisMesh';
import { getUniforms, VERTEX_SHADER } from '../utils';
import { getData3DTexture } from './utils';

interface Props {
interface Props extends VisMeshProps {
values: NdArray<Uint8Array | Uint8ClampedArray | Float32Array>;
bgr?: boolean;
}

function RgbMesh(props: Props) {
const { values, bgr = false } = props;
const { values, bgr = false, ...visMeshProps } = props;

const dataTexture = useMemo(() => getData3DTexture(values), [values]);

Expand Down Expand Up @@ -39,7 +40,7 @@ function RgbMesh(props: Props) {
};

return (
<VisMesh scale={[1, -1, 1]}>
<VisMesh {...visMeshProps}>
<shaderMaterial args={[shader]} />
</VisMesh>
);
Expand Down
13 changes: 11 additions & 2 deletions packages/lib/src/vis/rgb/RgbVis.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ interface Props extends ClassStyleAttrs {
imageType?: ImageType;
abscissaParams?: AxisParams;
ordinateParams?: AxisParams;
flipXAxis?: boolean;
flipYAxis?: boolean;
children?: ReactNode;
interactions?: DefaultInteractionsConfig;
}
Expand All @@ -38,6 +40,8 @@ function RgbVis(props: Props) {
imageType = ImageType.RGB,
abscissaParams = {},
ordinateParams = {},
flipXAxis,
flipYAxis,
children,
interactions,
className = '',
Expand Down Expand Up @@ -73,19 +77,24 @@ function RgbVis(props: Props) {
showGrid,
isIndexAxis: true,
label: abscissaLabel,
flip: flipXAxis,
}}
ordinateConfig={{
visDomain: ordinateDomain,
showGrid,
isIndexAxis: true,
flip: true,
flip: flipYAxis,
label: ordinateLabel,
}}
>
<DefaultInteractions {...interactions} />
<ResetZoomButton />

<RgbMesh values={safeDataArray} bgr={imageType === ImageType.BGR} />
<RgbMesh
values={safeDataArray}
bgr={imageType === ImageType.BGR}
scale={[flipXAxis ? -1 : 1, flipYAxis ? -1 : 1, 1]}
/>

{children}
</VisCanvas>
Expand Down

0 comments on commit cffd7e9

Please sign in to comment.