Skip to content

Commit

Permalink
Replace auto-scale toggle with domain widget on line vis
Browse files Browse the repository at this point in the history
  • Loading branch information
axelboc committed Jun 10, 2024
1 parent ead05b2 commit 4eabd44
Show file tree
Hide file tree
Showing 10 changed files with 119 additions and 161 deletions.
55 changes: 0 additions & 55 deletions packages/app/src/__tests__/CorePack.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -98,61 +98,6 @@ test('visualize 2D complex dataset', async () => {
).toBeVisible();
});

test('visualize 1D slice of 3D dataset as Line with and without autoscale', async () => {
const { user } = await renderApp({
initialPath: '/resilience/slow_slicing',
preferredVis: Vis.Line,
withFakeTimers: true,
});

// Wait for slice loader to appear (since autoscale is on by default, only the first slice gets fetched)
await expect(
screen.findByText(/Loading current slice/),
).resolves.toBeVisible();

// Wait for fetch of first slice to succeed
await expect(
screen.findByRole('figure', undefined, { timeout: SLOW_TIMEOUT }),
).resolves.toBeVisible();

// Confirm that autoscale is indeed on
const autoScaleBtn = screen.getByRole('button', { name: 'Auto-scale' });
expect(autoScaleBtn).toHaveAttribute('aria-pressed', 'true');

// Move to next slice
const d0Slider = screen.getByRole('slider', { name: 'D0' });
await user.type(d0Slider, '{ArrowUp}');

// Wait for slice loader to re-appear after debounce
await expect(
screen.findByText(/Loading current slice/),
).resolves.toBeVisible();

// Wait for fetch of second slice to succeed
await expect(
screen.findByRole('figure', undefined, { timeout: SLOW_TIMEOUT }),
).resolves.toBeVisible();

// Activate autoscale
await user.click(autoScaleBtn);

// Now, the entire dataset gets fetched
await expect(
screen.findByText(/Loading entire dataset/),
).resolves.toBeVisible();

// Wait for fetch of entire dataset to succeed
await expect(
screen.findByRole('figure', undefined, { timeout: SLOW_TIMEOUT }),
).resolves.toBeVisible();

// Move to third slice
await user.type(d0Slider, '{ArrowUp}');

// Wait for new slicing to apply to Line visualization to confirm that no more slow fetching is performed
await expect(screen.findByTestId('2,0,x', undefined)).resolves.toBeVisible();
});

test('show interactions help for heatmap according to "keep ratio"', async () => {
const { user } = await renderApp();

Expand Down
28 changes: 15 additions & 13 deletions packages/app/src/vis-packs/core/complex/ComplexLineToolbar.tsx
Original file line number Diff line number Diff line change
@@ -1,44 +1,54 @@
import {
ComplexVisTypeSelector,
CurveType,
DomainWidget,
ScaleSelector,
Separator,
ToggleBtn,
ToggleGroup,
Toolbar,
} from '@h5web/lib';
import type { Domain } from '@h5web/shared/vis-models';
import { ComplexVisType } from '@h5web/shared/vis-models';
import { AXIS_SCALE_TYPES } from '@h5web/shared/vis-utils';
import { MdDomain, MdGridOn } from 'react-icons/md';
import { MdGridOn } from 'react-icons/md';

import type { LineConfig } from '../line/config';
import { INTERACTIONS_WITH_AXIAL_ZOOM } from '../utils';
import type { ComplexLineConfig } from './lineConfig';

interface Props {
disableAutoScale: boolean;
dataDomain: Domain;
config: ComplexLineConfig;
lineConfig: LineConfig;
}

function ComplexLineToolbar(props: Props) {
const { disableAutoScale, config, lineConfig } = props;
const { dataDomain, config, lineConfig } = props;
const { visType, setVisType } = config;
const {
customDomain,
curveType,
showGrid,
xScaleType,
yScaleType,
autoScale,
setCustomDomain,
setCurveType,
toggleGrid,
setXScaleType,
setYScaleType,
toggleAutoScale,
} = lineConfig;

return (
<Toolbar interactions={INTERACTIONS_WITH_AXIAL_ZOOM}>
<DomainWidget
dataDomain={dataDomain}
customDomain={customDomain}
scaleType={yScaleType}
onCustomDomainChange={setCustomDomain}
/>
<Separator />

<ScaleSelector
label="X"
value={xScaleType}
Expand All @@ -62,14 +72,6 @@ function ComplexLineToolbar(props: Props) {

<Separator />

<ToggleBtn
label="Auto-scale"
icon={MdDomain}
value={!disableAutoScale && autoScale}
onToggle={toggleAutoScale}
disabled={disableAutoScale}
/>

<ToggleBtn
label="Grid"
icon={MdGridOn}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ function ComplexLineVisContainer(props: VisContainerProps) {

const config = useComplexLineConfig();
const lineConfig = useLineConfig();
const { autoScale } = lineConfig;

return (
<>
Expand All @@ -34,15 +33,10 @@ function ComplexLineVisContainer(props: VisContainerProps) {
mapperState={dimMapping}
onChange={setDimMapping}
/>
<VisBoundary
resetKey={dimMapping}
loadingMessage={`Loading ${
autoScale ? 'current slice' : 'entire dataset'
}`}
>
<VisBoundary resetKey={dimMapping} loadingMessage="Loading current slice">
<ValueFetcher
dataset={entity}
selection={autoScale ? getSliceSelection(dimMapping) : undefined}
selection={getSliceSelection(dimMapping)}
render={(value) => (
<MappedComplexLineVis
value={value}
Expand Down
58 changes: 43 additions & 15 deletions packages/app/src/vis-packs/core/complex/MappedComplexLineVis.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { LineVis, useDomain, useSafeDomain, useVisDomain } from '@h5web/lib';
import type { H5WebComplex } from '@h5web/shared/hdf5-models';
import type { AxisMapping } from '@h5web/shared/nexus-models';
import type { NumArray } from '@h5web/shared/vis-models';
Expand All @@ -6,8 +7,10 @@ import { useMemo } from 'react';
import { createPortal } from 'react-dom';

import type { DimensionMapping } from '../../../dimension-mapper/models';
import visualizerStyles from '../../../visualizer/Visualizer.module.css';
import { useMappedArray, useSlicedDimsAndMapping } from '../hooks';
import type { LineConfig } from '../line/config';
import MappedLineVis from '../line/MappedLineVis';
import { DEFAULT_DOMAIN } from '../utils';
import ComplexLineToolbar from './ComplexLineToolbar';
import type { ComplexLineConfig } from './lineConfig';
import { COMPLEX_VIS_TYPE_LABELS, getPhaseAmplitudeValues } from './utils';
Expand All @@ -29,43 +32,68 @@ function MappedComplexLineVis(props: Props) {
const {
value,
valueLabel,
dims,
dimMapping,
axisLabels,
axisValues,
title,
toolbarContainer,
config,
lineConfig,
...lineProps
} = props;

const { dims } = lineProps;
const { visType } = config;
const { customDomain, yScaleType, xScaleType, curveType, showGrid } =
lineConfig;

const [slicedDims, slicedMapping] = useSlicedDimsAndMapping(dims, dimMapping);
const { phaseValues, amplitudeValues } = useMemo(
() => getPhaseAmplitudeValues(value),
[value],
);

const [dataArray, dataForDomain] = useMappedArray(
visType === ComplexVisType.Amplitude ? amplitudeValues : phaseValues,
slicedDims,
slicedMapping,
);

const dataDomain = useDomain(dataForDomain, yScaleType) || DEFAULT_DOMAIN;
const visDomain = useVisDomain(customDomain, dataDomain);
const [safeDomain] = useSafeDomain(visDomain, dataDomain, yScaleType);

const xDimIndex = dimMapping.indexOf('x');
const ordinateLabel = valueLabel
? `${valueLabel} (${COMPLEX_VIS_TYPE_LABELS[visType].toLowerCase()})`
: COMPLEX_VIS_TYPE_LABELS[visType];

return (
<>
{toolbarContainer &&
createPortal(
<ComplexLineToolbar
disableAutoScale={dims.length <= 1} // with 1D datasets, `baseArray` and `dataArray` are the same so auto-scaling is implied
dataDomain={dataDomain}
config={config}
lineConfig={lineConfig}
/>,
toolbarContainer,
)}

<MappedLineVis
value={
visType === ComplexVisType.Amplitude ? amplitudeValues : phaseValues
}
valueLabel={
valueLabel
? `${valueLabel} (${COMPLEX_VIS_TYPE_LABELS[visType].toLowerCase()})`
: COMPLEX_VIS_TYPE_LABELS[visType]
}
config={lineConfig}
{...lineProps}
<LineVis
className={visualizerStyles.vis}
dataArray={dataArray}
domain={safeDomain}
scaleType={yScaleType}
curveType={curveType}
showGrid={showGrid}
abscissaParams={{
label: axisLabels?.[xDimIndex],
value: axisValues?.[xDimIndex],
scaleType: xScaleType,
}}
ordinateLabel={ordinateLabel}
title={title}
testid={dimMapping.toString()}
/>
</>
);
Expand Down
37 changes: 19 additions & 18 deletions packages/app/src/vis-packs/core/line/LineToolbar.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import type { Domain } from '@h5web/lib';
import {
CurveType,
DomainWidget,
ExportMenu,
ScaleSelector,
Separator,
Expand All @@ -9,7 +11,7 @@ import {
} from '@h5web/lib';
import { AXIS_SCALE_TYPES } from '@h5web/shared/vis-utils';
import { FiItalic } from 'react-icons/fi';
import { MdDomain, MdGridOn } from 'react-icons/md';
import { MdGridOn } from 'react-icons/md';

import type { ExportFormat, ExportURL } from '../../../providers/models';
import { INTERACTIONS_WITH_AXIAL_ZOOM } from '../utils';
Expand All @@ -18,34 +20,41 @@ import type { LineConfig } from './config';
const EXPORT_FORMATS: ExportFormat[] = ['npy', 'csv'];

interface Props {
dataDomain: Domain;
isSlice: boolean;
disableAutoScale: boolean;
disableErrors: boolean;
config: LineConfig;
getExportURL: ((format: ExportFormat) => ExportURL) | undefined;
}

function LineToolbar(props: Props) {
const { isSlice, disableAutoScale, disableErrors, config, getExportURL } =
props;
const { isSlice, dataDomain, disableErrors, config, getExportURL } = props;

const {
customDomain,
curveType,
setCurveType,
showGrid,
toggleGrid,
xScaleType,
setXScaleType,
yScaleType,
setYScaleType,
autoScale,
toggleAutoScale,
showErrors,
setCustomDomain,
setCurveType,
toggleGrid,
setXScaleType,
setYScaleType,
toggleErrors,
} = config;

return (
<Toolbar interactions={INTERACTIONS_WITH_AXIAL_ZOOM}>
<DomainWidget
dataDomain={dataDomain}
customDomain={customDomain}
scaleType={yScaleType}
onCustomDomainChange={setCustomDomain}
/>
<Separator />

<ScaleSelector
label="X"
value={xScaleType}
Expand All @@ -61,14 +70,6 @@ function LineToolbar(props: Props) {

<Separator />

<ToggleBtn
label="Auto-scale"
icon={MdDomain}
value={!disableAutoScale && autoScale}
onToggle={toggleAutoScale}
disabled={disableAutoScale}
/>

<ToggleBtn
label="Errors"
icon={(iconProps) => (
Expand Down
14 changes: 2 additions & 12 deletions packages/app/src/vis-packs/core/line/LineVisContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,6 @@ function LineVisContainer(props: VisContainerProps) {
const [dimMapping, setDimMapping] = useDimMappingState(dims, 1);

const config = useLineConfig();

const { autoScale } = config;
const selection = autoScale ? getSliceSelection(dimMapping) : undefined;

const ignoreValue = useIgnoreFillValue(entity);

return (
Expand All @@ -37,19 +33,13 @@ function LineVisContainer(props: VisContainerProps) {
mapperState={dimMapping}
onChange={setDimMapping}
/>
<VisBoundary
resetKey={dimMapping}
loadingMessage={`Loading ${
autoScale ? 'current slice' : 'entire dataset'
}`}
>
<VisBoundary resetKey={dimMapping} loadingMessage="Loading current slice">
<ValueFetcher
dataset={entity}
selection={selection}
selection={getSliceSelection(dimMapping)}
render={(value) => (
<MappedLineVis
dataset={entity}
selection={selection}
value={value}
dims={dims}
dimMapping={dimMapping}
Expand Down
Loading

0 comments on commit 4eabd44

Please sign in to comment.