Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
1 change: 1 addition & 0 deletions eslint.config.base.js
Original file line number Diff line number Diff line change
Expand Up @@ -822,6 +822,7 @@ export function createConfig(opts = {}) {
'@typescript-eslint/no-unnecessary-parameter-property-assignment':
'warn',
'@typescript-eslint/no-unnecessary-qualifier': 'warn',
'@typescript-eslint/no-unnecessary-type-arguments': 'warn', // downgrade
'@typescript-eslint/no-unsafe-argument': 'warn',
'@typescript-eslint/no-unsafe-assignment': 'off', // too tricky to fix when `any` is declared externally (JSON.parse, Array.isArray, etc.)
'@typescript-eslint/no-unused-vars': [
Expand Down
19 changes: 10 additions & 9 deletions packages/app/src/vis-packs/core/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ import { createMemo } from '@h5web/shared/createMemo';
import { assertDatasetValue, isDefined } from '@h5web/shared/guards';
import {
type ArrayShape,
type ArrayValue,
type Dataset,
type ScalarShape,
type Value,
} from '@h5web/shared/hdf5-models';
import { type NumArray } from '@h5web/shared/vis-models';
import { castArray } from '@h5web/shared/vis-utils';
import { type NdArray, type TypedArray } from 'ndarray';
import { type NdArray } from 'ndarray';
import { useMemo } from 'react';

import { type DimensionMapping } from '../../dimension-mapper/models';
Expand Down Expand Up @@ -100,29 +101,29 @@ export function useDatasetValues<D extends Dataset<ArrayShape | ScalarShape>>(
});
}

export function useBaseArray<T extends unknown[] | TypedArray | undefined>(
export function useBaseArray<T extends ArrayValue | undefined>(
value: T,
rawDims: number[],
): T extends unknown[] | TypedArray ? NdArray<T> : undefined;
): T extends ArrayValue ? NdArray<T> : undefined;

export function useBaseArray(
value: unknown[] | TypedArray | undefined,
value: ArrayValue | undefined,
rawDims: number[],
): NdArray<unknown[] | TypedArray> | undefined {
): NdArray<ArrayValue> | undefined {
return useMemo(() => getBaseArray(value, rawDims), [value, rawDims]);
}

export function useMappedArray<T extends unknown[] | TypedArray | undefined>(
export function useMappedArray<T extends ArrayValue | undefined>(
value: T,
dims: number[],
mapping: DimensionMapping,
): T extends unknown[] | TypedArray ? NdArray<T> : undefined;
): T extends ArrayValue ? NdArray<T> : undefined;

export function useMappedArray(
value: unknown[] | TypedArray | undefined,
value: ArrayValue | undefined,
dims: number[],
mapping: DimensionMapping,
): NdArray<unknown[] | TypedArray> | undefined {
): NdArray<ArrayValue> | undefined {
const baseArray = useBaseArray(value, dims);

return useMemo(() => applyMapping(baseArray, mapping), [baseArray, mapping]);
Expand Down
28 changes: 15 additions & 13 deletions packages/app/src/vis-packs/core/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
type NumArray,
} from '@h5web/shared/vis-models';
import { createArrayFromView } from '@h5web/shared/vis-utils';
import ndarray, { type NdArray, type TypedArray } from 'ndarray';
import ndarray, { type NdArray } from 'ndarray';

import { type DimensionMapping } from '../../dimension-mapper/models';
import { isAxis } from '../../dimension-mapper/utils';
Expand All @@ -32,29 +32,27 @@ export const INTERACTIONS_WITH_AXIAL_ZOOM = [
{ shortcut: 'Ctrl+Shift+Drag', description: 'Select to zoom in Y' },
];

export function getBaseArray<T extends unknown[] | TypedArray | undefined>(
export function getBaseArray<T extends ArrayValue | undefined>(
value: T,
rawDims: number[],
): T extends unknown[] | TypedArray ? NdArray<T> : undefined;
): T extends ArrayValue ? NdArray<T> : undefined;

export function getBaseArray(
value: unknown[] | TypedArray | undefined,
value: ArrayValue | undefined,
rawDims: number[],
): NdArray<unknown[] | TypedArray> | undefined {
): NdArray<ArrayValue> | undefined {
return value && ndarray(value, rawDims);
}

export function applyMapping<
T extends NdArray<unknown[] | TypedArray> | undefined,
>(
export function applyMapping<T extends NdArray<ArrayValue> | undefined>(
baseArray: T,
mapping: (number | Axis | ':')[],
): T extends NdArray<unknown[] | TypedArray> ? T : undefined;
): T extends NdArray<ArrayValue> ? T : undefined;

export function applyMapping(
baseArray: NdArray<unknown[] | TypedArray> | undefined,
baseArray: NdArray<ArrayValue> | undefined,
mapping: (number | Axis | ':')[],
): NdArray<unknown[] | TypedArray> | undefined {
): NdArray<ArrayValue> | undefined {
if (!baseArray) {
return undefined;
}
Expand Down Expand Up @@ -95,12 +93,16 @@ export function getImageInteractions(keepRatio: boolean): InteractionInfo[] {
return keepRatio ? BASE_INTERACTIONS : INTERACTIONS_WITH_AXIAL_ZOOM;
}

function isBoolArray(val: ArrayValue<NumericLikeType>): val is boolean[] {
return Array.isArray(val) && typeof val[0] === 'boolean';
}

export function toNumArray(arr: ArrayValue<NumericLikeType>): NumArray {
if (typeof arr[0] === 'boolean') {
if (isBoolArray(arr)) {
return arr.map((val) => (val ? 1 : 0));
}

return arr as NumArray;
return arr;
}

const TYPE_STRINGS: Record<NumericLikeType['class'], string> = {
Expand Down
14 changes: 4 additions & 10 deletions packages/shared/src/guards.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,14 +142,6 @@ export function isTypedArray(val: unknown): val is TypedArray {
);
}

export function assertArrayOrTypedArray(
val: unknown,
): asserts val is unknown[] | TypedArray {
if (!Array.isArray(val) && !isTypedArray(val)) {
throw new TypeError('Expected array or typed array');
}
}

export function isGroup(entity: Entity): entity is Group {
return entity.kind === EntityKind.Group;
}
Expand Down Expand Up @@ -431,7 +423,7 @@ export function isComplexValue(
function assertPrimitiveValue(
type: DType,
value: unknown,
): asserts value is Primitive<DType> {
): asserts value is Primitive {
if (isNumericType(type)) {
assertNum(value);
} else if (isStringType(type)) {
Expand All @@ -457,7 +449,9 @@ export function assertDatasetValue<D extends Dataset<ScalarShape | ArrayShape>>(
if (hasScalarShape(dataset)) {
assertPrimitiveValue(type, value);
} else {
assertArrayOrTypedArray(value);
if (!Array.isArray(value) && !isTypedArray(value)) {
throw new TypeError('Expected array or typed array');
}

if (value.length > 0) {
assertPrimitiveValue(type, value[0]);
Expand Down
24 changes: 11 additions & 13 deletions packages/shared/src/hdf5-models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,21 +207,19 @@ export interface UnknownType {
/* ----------------- */
/* ----- VALUE ----- */

export type Primitive<T extends DType> = T extends NumericType | EnumType
? number
export type Primitive<T extends DType = DType> = T extends NumericLikeType
? number | (T extends BooleanType ? boolean : never) // let providers choose how to return booleans
: T extends StringType
? string
: T extends BooleanType
? number | boolean // let providers choose
: T extends ComplexType
? H5WebComplex
: T extends CompoundType<infer TFields>
? Primitive<TFields>[]
: unknown;

export type ArrayValue<T extends DType> =
| Primitive<T>[]
| (T extends NumericLikeType ? TypedArray : never);
: T extends ComplexType
? H5WebComplex
: T extends CompoundType<infer TFields>
? Primitive<TFields>[]
: unknown;

export type ArrayValue<T extends DType = DType> = T extends NumericLikeType
? TypedArray | number[] | (T extends BooleanType ? boolean[] : never) // don't use `Primitive` to avoid `(number | boolean)[]`
: Primitive<T>[];

export type Value<D extends Dataset> =
D extends Dataset<infer S, infer T>
Expand Down
4 changes: 2 additions & 2 deletions packages/shared/src/mock-values.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { range } from 'd3-array';
import ndarray, { type NdArray } from 'ndarray';

import { type ArrayValue, type DType, type H5WebComplex } from './hdf5-models';
import { type ArrayValue, type H5WebComplex } from './hdf5-models';
import { cplx } from './hdf5-utils';

const range1 = () => range(-20, 21);
Expand Down Expand Up @@ -276,4 +276,4 @@ export const mockValues = {
ndarray(range1().map((val) => Math.cos((val * 3.14) / 40))),
Y_scatter: () =>
ndarray(range1().map((_, i) => ((i % 10) + (i % 5)) / 123_456)),
} satisfies Record<string, () => NdArray<ArrayValue<DType>>>;
} satisfies Record<string, () => NdArray<ArrayValue>>;
5 changes: 3 additions & 2 deletions packages/shared/src/vis-utils.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { format } from 'd3-format';
import ndarray, { type NdArray, type TypedArray } from 'ndarray';
import ndarray, { type NdArray } from 'ndarray';
import { assign } from 'ndarray-ops';

import { assertLength, isNdArray } from './guards';
import {
type ArrayValue,
type BooleanType,
type ComplexType,
type EnumType,
Expand Down Expand Up @@ -101,7 +102,7 @@ export function toTypedNdArray<T extends TypedArrayConstructor>(
return ndarray(Constructor.from(arr.data) as InstanceType<T>, arr.shape);
}

export function createArrayFromView<T extends TypedArray | unknown[]>(
export function createArrayFromView<T extends ArrayValue>(
view: NdArray<T>,
): NdArray<T> {
const { data, size, shape } = view;
Expand Down
Loading