Skip to content

Commit a31fc50

Browse files
authored
Merge pull request #1745 from silx-kit/bigint-new
Allow providers to return bigints
2 parents 02f6f73 + 0748093 commit a31fc50

34 files changed

+395
-137
lines changed

.vscode/settings.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"typescript.preferences.importModuleSpecifier": "relative",
1919
"typescript.preferences.preferTypeOnlyAutoImports": true,
2020
"typescript.preferences.autoImportSpecifierExcludeRegexes": [
21-
"^(node:)?(console|util)$",
21+
"^(node:)?(console|util|test)$",
2222
"^three/.*$"
2323
],
2424

-7 Bytes
Loading
-265 Bytes
Loading
Loading
319 Bytes
Loading
341 Bytes
Loading
Loading
326 Bytes
Loading
Loading
201 Bytes
Loading
531 Bytes
Loading

packages/app/src/providers/mock/mock-file.ts

+8
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ export function makeMockFile(): GroupWithChildren {
160160
group('typed_arrays', [
161161
array('uint8', { type: intType(false, 8) }),
162162
array('int16', { type: intType(true, 16) }),
163+
array('int64', { type: intType(true, 64) }),
163164
array('float32', { type: floatType(32) }),
164165
array('float64', { type: floatType(64) }),
165166
withImageAttr(array('uint8_rgb', { type: intType(false, 8) })),
@@ -275,6 +276,13 @@ export function makeMockFile(): GroupWithChildren {
275276
axes: { X: array('X'), Y_scatter: array('Y_scatter') },
276277
axesAttr: ['X', 'Y_scatter'],
277278
}),
279+
nxData('bigint', {
280+
signal: array('twoD_bigint'),
281+
auxiliary: { secondary_bigint: array('secondary_bigint') },
282+
auxAttr: ['secondary_bigint'],
283+
axes: { X_bigint: array('X_bigint') },
284+
axesAttr: ['.', 'X_bigint'],
285+
}),
278286
nxGroup('old-style', 'NXdata', {
279287
children: [
280288
array('twoD', {

packages/app/src/vis-packs/core/complex/MappedComplexLineVis.tsx

+3-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { createPortal } from 'react-dom';
1616

1717
import { type DimensionMapping } from '../../../dimension-mapper/models';
1818
import visualizerStyles from '../../../visualizer/Visualizer.module.css';
19+
import { useToNumArrays } from '../hooks';
1920
import { type LineConfig } from '../line/config';
2021
import { DEFAULT_DOMAIN } from '../utils';
2122
import ComplexLineToolbar from './ComplexLineToolbar';
@@ -58,6 +59,7 @@ function MappedComplexLineVis(props: Props) {
5859
const { customDomain, yScaleType, xScaleType, curveType, showGrid } =
5960
lineConfig;
6061

62+
const numAxisArrays = useToNumArrays(axisValues);
6163
const [dataArray, ...auxArrays] = useMappedComplexArrays(
6264
[value, ...auxValues],
6365
dims,
@@ -99,7 +101,7 @@ function MappedComplexLineVis(props: Props) {
99101
showGrid={showGrid}
100102
abscissaParams={{
101103
label: axisLabels[xDimIndex],
102-
value: axisValues[xDimIndex],
104+
value: numAxisArrays[xDimIndex],
103105
scaleType: xScaleType,
104106
}}
105107
ordinateLabel={ordinateLabel}

packages/app/src/vis-packs/core/complex/MappedComplexVis.tsx

+5-3
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
useBaseArray,
2222
useMappedArray,
2323
useSlicedDimsAndMapping,
24+
useToNumArrays,
2425
} from '../hooks';
2526
import { DEFAULT_DOMAIN } from '../utils';
2627
import ComplexToolbar from './ComplexToolbar';
@@ -62,8 +63,9 @@ function MappedComplexVis(props: Props) {
6263
invertColorMap,
6364
} = heatmapConfig;
6465

65-
const [slicedDims, slicedMapping] = useSlicedDimsAndMapping(dims, dimMapping);
66+
const numAxisArrays = useToNumArrays(axisValues);
6667

68+
const [slicedDims, slicedMapping] = useSlicedDimsAndMapping(dims, dimMapping);
6769
const mappedArray = useMappedArray(value, slicedDims, slicedMapping);
6870

6971
const { phaseValues, phaseBounds, amplitudeValues, amplitudeBounds } =
@@ -112,11 +114,11 @@ function MappedComplexVis(props: Props) {
112114
invertColorMap={invertColorMap}
113115
abscissaParams={{
114116
label: axisLabels[xDimIndex],
115-
value: axisValues[xDimIndex],
117+
value: numAxisArrays[xDimIndex],
116118
}}
117119
ordinateParams={{
118120
label: axisLabels[yDimIndex],
119-
value: axisValues[yDimIndex],
121+
value: numAxisArrays[yDimIndex],
120122
}}
121123
alpha={
122124
visType === ComplexVisType.PhaseAmplitude

packages/app/src/vis-packs/core/heatmap/MappedHeatmapVis.tsx

+4-2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import {
2222
useMappedArray,
2323
useSlicedDimsAndMapping,
2424
useToNumArray,
25+
useToNumArrays,
2526
} from '../hooks';
2627
import { DEFAULT_DOMAIN, formatNumLikeType, getSliceSelection } from '../utils';
2728
import { type HeatmapConfig } from './config';
@@ -64,6 +65,7 @@ function MappedHeatmapVis(props: Props) {
6465
} = config;
6566

6667
const numArray = useToNumArray(value);
68+
const numAxisArrays = useToNumArrays(axisValues);
6769

6870
const { shape: dims } = dataset;
6971
const [slicedDims, slicedMapping] = useSlicedDimsAndMapping(dims, dimMapping);
@@ -109,11 +111,11 @@ function MappedHeatmapVis(props: Props) {
109111
invertColorMap={invertColorMap}
110112
abscissaParams={{
111113
label: axisLabels[xDimIndex],
112-
value: axisValues[xDimIndex],
114+
value: numAxisArrays[xDimIndex],
113115
}}
114116
ordinateParams={{
115117
label: axisLabels[yDimIndex],
116-
value: axisValues[yDimIndex],
118+
value: numAxisArrays[yDimIndex],
117119
}}
118120
flipXAxis={flipXAxis}
119121
flipYAxis={flipYAxis}

packages/app/src/vis-packs/core/hooks.ts

+9-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,15 @@ export const useToNumArray = createMemo(toNumArray);
2828

2929
export function useToNumArrays(
3030
arrays: ArrayValue<NumericLikeType>[],
31-
): NumArray[] {
31+
): NumArray[];
32+
33+
export function useToNumArrays(
34+
arrays: (ArrayValue<NumericLikeType> | undefined)[],
35+
): (NumArray | undefined)[];
36+
37+
export function useToNumArrays(
38+
arrays: (ArrayValue<NumericLikeType> | undefined)[],
39+
): (NumArray | undefined)[] {
3240
return useMemo(() => arrays.map(toNumArray), arrays); // eslint-disable-line react-hooks/exhaustive-deps
3341
}
3442

packages/app/src/vis-packs/core/line/MappedLineVis.tsx

+6-3
Original file line numberDiff line numberDiff line change
@@ -81,11 +81,14 @@ function MappedLineVis(props: Props) {
8181

8282
const numArray = useToNumArray(value);
8383
const numAuxArrays = useToNumArrays(auxValues);
84+
const numErrorsArray = useToNumArray(errors);
85+
const numAuxErrorsArrays = useToNumArrays(auxErrors);
86+
const numAxisArrays = useToNumArrays(axisValues);
8487

8588
const dataArray = useMappedArray(numArray, ...hookArgs);
86-
const errorsArray = useMappedArray(errors, ...hookArgs);
89+
const errorsArray = useMappedArray(numErrorsArray, ...hookArgs);
8790
const auxArrays = useMappedArrays(numAuxArrays, ...hookArgs);
88-
const auxErrorsArrays = useMappedArrays(auxErrors, ...hookArgs);
91+
const auxErrorsArrays = useMappedArrays(numAuxErrorsArrays, ...hookArgs);
8992

9093
const dataDomain = useDomain(
9194
dataArray,
@@ -132,7 +135,7 @@ function MappedLineVis(props: Props) {
132135
showGrid={showGrid}
133136
abscissaParams={{
134137
label: axisLabels[xDimIndex],
135-
value: axisValues[xDimIndex],
138+
value: numAxisArrays[xDimIndex],
136139
scaleType: xScaleType,
137140
}}
138141
ordinateLabel={valueLabel}

packages/app/src/vis-packs/core/matrix/utils.ts

+20-4
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import {
33
isBoolType,
44
isComplexType,
55
isEnumType,
6-
isNumericType,
6+
isFloatType,
7+
isIntegerType,
78
} from '@h5web/shared/guards';
89
import {
910
type ComplexType,
@@ -21,9 +22,20 @@ import {
2122
} from '@h5web/shared/vis-utils';
2223
import { format } from 'd3-format';
2324

24-
export function createNumericFormatter(
25+
export function createIntegerFormatter(
2526
notation: Notation,
2627
): (val: ScalarValue<NumericType>) => string {
28+
if (notation === Notation.Scientific) {
29+
const formatter = format('.3e');
30+
return (val) => formatter(Number(val));
31+
}
32+
33+
return (val) => val.toString();
34+
}
35+
36+
export function createFloatFormatter(
37+
notation: Notation,
38+
): (val: number) => string {
2739
switch (notation) {
2840
case Notation.FixedPoint:
2941
return format('.3f');
@@ -54,8 +66,12 @@ export function getFormatter(
5466
type: PrintableType,
5567
notation: Notation,
5668
): ValueFormatter<PrintableType> {
57-
if (isNumericType(type)) {
58-
return createNumericFormatter(notation);
69+
if (isIntegerType(type)) {
70+
return createIntegerFormatter(notation);
71+
}
72+
73+
if (isFloatType(type)) {
74+
return createFloatFormatter(notation);
5975
}
6076

6177
if (isBoolType(type)) {

packages/app/src/vis-packs/core/rgb/MappedRgbVis.tsx

+13-4
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,12 @@ import { createPortal } from 'react-dom';
1010

1111
import { type DimensionMapping } from '../../../dimension-mapper/models';
1212
import visualizerStyles from '../../../visualizer/Visualizer.module.css';
13-
import { useMappedArray, useSlicedDimsAndMapping } from '../hooks';
13+
import {
14+
useMappedArray,
15+
useSlicedDimsAndMapping,
16+
useToNumArray,
17+
useToNumArrays,
18+
} from '../hooks';
1419
import { type RgbVisConfig } from './config';
1520
import RgbToolbar from './RgbToolbar';
1621

@@ -40,8 +45,12 @@ function MappedRgbVis(props: Props) {
4045
const { showGrid, keepRatio, imageType, flipXAxis, flipYAxis } = config;
4146
const { shape: dims } = dataset;
4247

48+
const numAxisArrays = useToNumArrays(axisValues);
49+
4350
const [slicedDims, slicedMapping] = useSlicedDimsAndMapping(dims, dimMapping);
44-
const dataArray = useMappedArray(value, slicedDims, slicedMapping);
51+
52+
const numArray = useToNumArray(value);
53+
const dataArray = useMappedArray(numArray, slicedDims, slicedMapping);
4554

4655
const xDimIndex = dimMapping.indexOf('x');
4756
const yDimIndex = dimMapping.indexOf('y');
@@ -59,11 +68,11 @@ function MappedRgbVis(props: Props) {
5968
imageType={imageType}
6069
abscissaParams={{
6170
label: axisLabels[xDimIndex],
62-
value: axisValues[xDimIndex],
71+
value: numAxisArrays[xDimIndex],
6372
}}
6473
ordinateParams={{
6574
label: axisLabels[yDimIndex],
66-
value: axisValues[yDimIndex],
75+
value: numAxisArrays[yDimIndex],
6776
}}
6877
flipXAxis={flipXAxis}
6978
flipYAxis={flipYAxis}

packages/app/src/vis-packs/core/scalar/utils.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,5 @@ export function getFormatter<T extends PrintableType>(
3131
return createEnumFormatter(dataset.type.mapping);
3232
}
3333

34-
return (val: number | string) => val.toString();
34+
return (val: number | bigint | string) => val.toString();
3535
}

packages/app/src/vis-packs/core/scatter/MappedScatterVis.tsx

+6-3
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { type AxisMapping } from '@h5web/shared/nexus-models';
55
import { createPortal } from 'react-dom';
66

77
import visualizerStyles from '../../../visualizer/Visualizer.module.css';
8-
import { useBaseArray } from '../hooks';
8+
import { useBaseArray, useToNumArray, useToNumArrays } from '../hooks';
99
import { DEFAULT_DOMAIN } from '../utils';
1010
import { type ScatterConfig } from './config';
1111
import ScatterToolbar from './ScatterToolbar';
@@ -33,13 +33,16 @@ function MappedScatterVis(props: Props) {
3333
yScaleType,
3434
} = config;
3535

36-
const dataArray = useBaseArray(value, [value.length]);
36+
const numArray = useToNumArray(value);
37+
const numAxisArrays = useToNumArrays(axisValues);
38+
39+
const dataArray = useBaseArray(numArray, [value.length]);
3740
const dataDomain = useDomain(dataArray, scaleType) || DEFAULT_DOMAIN;
3841
const visDomain = useVisDomain(customDomain, dataDomain);
3942
const [safeDomain] = useSafeDomain(visDomain, dataDomain, scaleType);
4043

4144
const [xLabel, yLabel] = axisLabels;
42-
const [xValue, yValue] = axisValues;
45+
const [xValue, yValue] = numAxisArrays;
4346
assertDefined(xValue);
4447
assertDefined(yValue);
4548

packages/app/src/vis-packs/core/surface/MappedSurfaceVis.tsx

+8-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@ import { createPortal } from 'react-dom';
99

1010
import { type DimensionMapping } from '../../../dimension-mapper/models';
1111
import visualizerStyles from '../../../visualizer/Visualizer.module.css';
12-
import { useMappedArray, useSlicedDimsAndMapping } from '../hooks';
12+
import {
13+
useMappedArray,
14+
useSlicedDimsAndMapping,
15+
useToNumArray,
16+
} from '../hooks';
1317
import { DEFAULT_DOMAIN } from '../utils';
1418
import { type SurfaceConfig } from './config';
1519
import SurfaceToolbar from './SurfaceToolbar';
@@ -29,7 +33,9 @@ function MappedSurfaceVis(props: Props) {
2933

3034
const { shape: dims } = dataset;
3135
const [slicedDims, slicedMapping] = useSlicedDimsAndMapping(dims, dimMapping);
32-
const dataArray = useMappedArray(value, slicedDims, slicedMapping);
36+
37+
const numArray = useToNumArray(value);
38+
const dataArray = useMappedArray(numArray, slicedDims, slicedMapping);
3339

3440
const dataDomain = useDomain(dataArray, scaleType) || DEFAULT_DOMAIN;
3541
const visDomain = useVisDomain(customDomain, dataDomain);

packages/app/src/vis-packs/core/utils.ts

+28-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
import { type InteractionInfo } from '@h5web/lib';
2-
import { isIntegerType, isNumericType } from '@h5web/shared/guards';
2+
import {
3+
isBigIntTypedArray,
4+
isIntegerType,
5+
isNumericType,
6+
} from '@h5web/shared/guards';
37
import {
48
type ArrayValue,
59
DTypeClass,
@@ -93,11 +97,33 @@ export function getImageInteractions(keepRatio: boolean): InteractionInfo[] {
9397
return keepRatio ? BASE_INTERACTIONS : INTERACTIONS_WITH_AXIAL_ZOOM;
9498
}
9599

100+
function isBigIntArray(val: ArrayValue<NumericLikeType>): val is bigint[] {
101+
return Array.isArray(val) && typeof val[0] === 'bigint';
102+
}
103+
96104
function isBoolArray(val: ArrayValue<NumericLikeType>): val is boolean[] {
97105
return Array.isArray(val) && typeof val[0] === 'boolean';
98106
}
99107

100-
export function toNumArray(arr: ArrayValue<NumericLikeType>): NumArray {
108+
export function toNumArray<T extends ArrayValue<NumericLikeType> | undefined>(
109+
arr: T,
110+
): T extends ArrayValue<NumericLikeType> ? NumArray : undefined;
111+
112+
export function toNumArray(
113+
arr: ArrayValue<NumericLikeType> | undefined,
114+
): NumArray | undefined {
115+
if (!arr) {
116+
return undefined;
117+
}
118+
119+
if (isBigIntTypedArray(arr)) {
120+
return Float64Array.from(arr, Number); // cast to float 64
121+
}
122+
123+
if (isBigIntArray(arr)) {
124+
return arr.map(Number); // cast to float 64
125+
}
126+
101127
if (isBoolArray(arr)) {
102128
return arr.map((val) => (val ? 1 : 0));
103129
}

packages/app/src/vis-packs/core/visualizations.test.ts

+5
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,15 @@ const mockStore = {
3131

3232
const scalarInt = dataset('int', intType(), []);
3333
const scalarUint = dataset('uint', intType(false), []);
34+
const scalarBigInt = dataset('bigint', intType(true, 64), []);
3435
const scalarFloat = dataset('float', floatType(), []);
3536
const scalarStr = dataset('float', strType(), []);
3637
const scalarBool = dataset('bool', boolType(intType(true, 8)), []);
3738
const scalarCplx = dataset('cplx', cplxType(floatType()), []);
3839
const scalarCompound = dataset('comp', compoundType({ int: intType() }), []);
3940
const oneDInt = dataset('int_1d', intType(), [5]);
4041
const oneDUint = dataset('uint_1d', intType(false), [5]);
42+
const oneDBigUint = dataset('biguint_1d', intType(false, 64), [5]);
4143
const oneDBool = dataset('bool_1d', boolType(intType(true, 8)), [3]);
4244
const oneDCplx = dataset('cplx_1d', cplxType(floatType()), [10]);
4345
const oneDCompound = dataset('comp_1d', compoundType({ int: intType() }), [5]);
@@ -82,6 +84,7 @@ describe('Scalar', () => {
8284
it('should support dataset with printable type and scalar shape', () => {
8385
expect(supportsDataset(scalarInt)).toBe(true);
8486
expect(supportsDataset(scalarUint)).toBe(true);
87+
expect(supportsDataset(scalarBigInt)).toBe(true);
8588
expect(supportsDataset(scalarFloat)).toBe(true);
8689
expect(supportsDataset(scalarStr)).toBe(true);
8790
expect(supportsDataset(scalarBool)).toBe(true);
@@ -103,6 +106,7 @@ describe('Matrix', () => {
103106
it('should support array dataset with printable type and at least one dimension', () => {
104107
expect(supportsDataset(oneDInt)).toBe(true);
105108
expect(supportsDataset(oneDUint)).toBe(true);
109+
expect(supportsDataset(oneDBigUint)).toBe(true);
106110
expect(supportsDataset(twoDStr)).toBe(true);
107111
expect(supportsDataset(twoDCplx)).toBe(true);
108112
expect(supportsDataset(threeDFloat)).toBe(true);
@@ -124,6 +128,7 @@ describe('Line', () => {
124128
it('should support array dataset with numeric-like type and at least one dimension', () => {
125129
expect(supportsDataset(oneDInt)).toBe(true);
126130
expect(supportsDataset(oneDUint)).toBe(true);
131+
expect(supportsDataset(oneDBigUint)).toBe(true);
127132
expect(supportsDataset(oneDBool)).toBe(true);
128133
expect(supportsDataset(twoDBool)).toBe(true);
129134
expect(supportsDataset(threeDFloat)).toBe(true);

0 commit comments

Comments
 (0)