Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Broaden arguments and props to use NumArray for #1356 #1357

Merged
merged 2 commits into from
Jan 25, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 16 additions & 13 deletions packages/lib/src/toolbar/controls/Histogram/Histogram.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { AxisBottom, AxisLeft } from '@visx/axis';
import { scaleLinear } from '@visx/scale';

import { useSafeDomain } from '../../../vis/heatmap/hooks';
import { useToArray, useCombinedDomain, useDomain } from '../../../vis/hooks';
import { useCombinedDomain, useDomain } from '../../../vis/hooks';
import type { HistogramParams } from '../../../vis/models';
import { H5WEB_SCALES } from '../../../vis/scales';
import Tick from '../../../vis/shared/Tick';
Expand Down Expand Up @@ -48,8 +48,6 @@ function Histogram(props: Props) {

const [size, ref] = useMeasure<HTMLDivElement>();

const valuesArray = useToArray(values);

if (!size) {
return <div ref={ref} className={styles.container} />;
}
Expand All @@ -67,19 +65,24 @@ function Histogram(props: Props) {

const markerPositions = safeValue.map(xScale) as Domain;

const rects = [] as JSX.Element[];
PeterC-DLS marked this conversation as resolved.
Show resolved Hide resolved
values.forEach((d, i) =>
rects.push(
<rect
className={styles.bar}
key={i} // eslint-disable-line react/no-array-index-key
x={xScale(bins[i])}
y={height - yScale(d)}
width={xScale(bins[i + 1]) - xScale(bins[i]) + 0.5} // +0.5 removes the small gap between bars
height={yScale(d) - yScale(0)}
/>
)
);

return (
<div ref={ref} className={styles.container}>
<svg width="100%" height="100%" className={styles.histogram}>
{valuesArray.map((d, i) => (
<rect
className={styles.bar}
key={i} // eslint-disable-line react/no-array-index-key
x={xScale(bins[i])}
y={height - yScale(d)}
width={xScale(bins[i + 1]) - xScale(bins[i]) + 0.5} // +0.5 removes the small gap between bars
height={yScale(d) - yScale(0)}
/>
))}
{...rects}
{colorMap && (
<ColorBar
x={markerPositions[0]}
Expand Down
2 changes: 1 addition & 1 deletion packages/lib/src/vis/heatmap/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ export function getLinearGradient(
export function getPixelEdgeValues(
rawValues: NumArray | undefined,
pixelCount: number
): number[] {
): NumArray {
if (rawValues && rawValues.length === pixelCount) {
// Add value at right-hand side of last pixel, assuming raw values are regularly spaced
const deltaCoord = rawValues[1] - rawValues[0];
Expand Down
3 changes: 0 additions & 3 deletions packages/lib/src/vis/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import {
getAxisValues,
getCombinedDomain,
getValueToIndexScale,
toArray,
} from './utils';

const useBounds = createMemo(getBounds);
Expand All @@ -29,8 +28,6 @@ export const useValueToIndexScale = createMemo(getValueToIndexScale);
export const useAxisDomain = createMemo(getAxisDomain);
export const useAxisValues = createMemo(getAxisValues);

export const useToArray = createMemo(toArray);

export function useDomain(
valuesArray: AnyNumArray,
scaleType: ScaleType = ScaleType.Linear,
Expand Down
2 changes: 1 addition & 1 deletion packages/lib/src/vis/line/DataCurve.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ declare global {
}

interface Props {
abscissas: number[];
abscissas: NumArray;
ordinates: NumArray;
errors?: NumArray;
showErrors?: boolean;
Expand Down
2 changes: 1 addition & 1 deletion packages/lib/src/vis/line/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { useVisCanvasContext } from '../shared/VisCanvasProvider';
const CAMERA_FAR = 1000; // R3F's default

export function useCanvasPoints(
abscissas: number[],
abscissas: NumArray,
ordinates: NumArray,
errors?: NumArray
) {
Expand Down
4 changes: 2 additions & 2 deletions packages/lib/src/vis/scatter/ScatterPoints.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import { useDataToColorScale } from './hooks';
import { useBufferAttributes } from './hooks';

interface Props {
abscissas: number[];
ordinates: number[];
abscissas: NumArray;
ordinates: NumArray;
data: NumArray;
domain: Domain;
scaleType: ScaleType;
Expand Down
12 changes: 4 additions & 8 deletions packages/lib/src/vis/scatter/ScatterVis.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import {
} from '@h5web/shared';
import type { ThreeEvent } from '@react-three/fiber';
import { useTooltip } from '@visx/tooltip';
import { toArray } from 'lodash';
import type { NdArray } from 'ndarray';
import type { ReactNode } from 'react';

Expand Down Expand Up @@ -57,21 +56,18 @@ function ScatterVis(props: Props) {
} = props;

const {
value: abscissaValue,
value: abscissas,
label: abscissaLabel,
scaleType: abscissaScaleType,
} = abscissaParams;
const {
value: ordinateValue,
value: ordinates,
label: ordinateLabel,
scaleType: ordinateScaleType,
} = ordinateParams;

assertLength(abscissaValue, dataArray.size, 'abscissa');
assertLength(ordinateValue, dataArray.size, 'ordinates');

const abscissas = toArray(abscissaValue);
const ordinates = toArray(ordinateValue);
assertLength(abscissas, dataArray.size, 'abscissa');
assertLength(ordinates, dataArray.size, 'ordinates');

const abscissaDomain = useAxisDomain(abscissas, abscissaScaleType, 0.01);
assertDefined(abscissaDomain, 'Abscissas have undefined domain');
Expand Down
4 changes: 2 additions & 2 deletions packages/lib/src/vis/scatter/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import { createAxisScale } from '../utils';
const CAMERA_FAR = 1000; // R3F's default

export function useBufferAttributes(
abscissas: number[],
ordinates: number[],
abscissas: NumArray,
ordinates: NumArray,
data: NumArray,
dataToColorScale: (val: number) => [number, number, number]
) {
Expand Down
28 changes: 13 additions & 15 deletions packages/lib/src/vis/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,26 +162,23 @@ function unsafeExtendDomain(
}

export function getValueToIndexScale(
values: number[],
values: NumArray,
switchAtMidpoints?: boolean
): ScaleThreshold<number, number> {
const rawThresholds = switchAtMidpoints
? values.map((_, i) => values[i - 1] + (values[i] - values[i - 1]) / 2) // Shift the thresholds for the switch from i-1 to i to happen between values[i-1] and values[i]
: values; // Else, the switch from i-1 to i will happen at values[i]

// First threshold (going from 0 to 1) should be for the second value. Scaling the first value should return at 0.
const thresholds = rawThresholds.slice(1);
const thresholds = toArray(rawThresholds.slice(1));
const indices = range(values.length);
if (isDescending(thresholds)) {
thresholds.reverse();
indices.reverse();
}

// ScaleThreshold only works with ascending values so the scale is reversed for descending values
return scaleThreshold<number, number>(
isDescending(thresholds)
? {
domain: [...thresholds].reverse(),
range: [...indices].reverse(),
}
: { domain: thresholds, range: indices }
);
return scaleThreshold<number, number>({ domain: thresholds, range: indices });
}

export function getCanvasScale(
Expand Down Expand Up @@ -300,12 +297,12 @@ export function getAxisOffsets(
};
}

function isDescending(array: number[]): boolean {
function isDescending(array: NumArray): boolean {
return array[array.length - 1] - array[0] < 0;
}

export function getAxisDomain(
axisValues: number[],
axisValues: NumArray,
scaleType: ScaleType = ScaleType.Linear,
extensionFactor = 0
): Domain | undefined {
Expand Down Expand Up @@ -348,7 +345,8 @@ export function getUniforms(
}

export function toArray(arr: NumArray): number[] {
return isTypedArray(arr) ? [...arr] : arr;
// eslint-disable-next-line unicorn/prefer-spread
return isTypedArray(arr) ? Array.from(arr) : arr;
PeterC-DLS marked this conversation as resolved.
Show resolved Hide resolved
}

export function getWorldFOV(camera: Camera): {
Expand Down Expand Up @@ -384,7 +382,7 @@ export function getVisibleDomains(
export function getAxisValues(
rawValues: NumArray | undefined,
axisLength: number
): number[] {
): NumArray {
if (!rawValues) {
return range(axisLength);
}
Expand All @@ -393,5 +391,5 @@ export function getAxisValues(
throw new Error(`Expected array to have length ${axisLength} at least`);
}

return toArray(rawValues).slice(0, axisLength);
return rawValues.slice(0, axisLength);
}