Skip to content
Draft
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
10 changes: 2 additions & 8 deletions packages/app/src/vis-packs/core/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import {
type InteractionInfo,
} from '@h5web/lib';
import {
isBigIntArray,
isBigIntTypedArray,
isBoolArray,
isIntegerType,
isNumericType,
} from '@h5web/shared/guards';
Expand Down Expand Up @@ -88,14 +90,6 @@ export function getImageInteractions(keepRatio: boolean): InteractionInfo[] {
return keepRatio ? BASE_INTERACTIONS : INTERACTIONS_WITH_AXIAL_ZOOM;
}

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

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

export function toNumArray<T extends ArrayValue<NumericLikeType> | undefined>(
arr: T,
): T extends ArrayValue<NumericLikeType> ? NumArray : undefined;
Expand Down
21 changes: 20 additions & 1 deletion packages/app/src/vis-packs/nexus/NxValuesFetcher.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
import {
assertDefined,
isBigIntArray,
isBigIntTypedArray,
} from '@h5web/shared/guards';
import {
type ComplexType,
type NumericLikeType,
Expand Down Expand Up @@ -43,7 +48,21 @@ function NxValuesFetcher<T extends NumericLikeType | ComplexType>(
const errors = useDatasetValue(signalDef.errorDataset, selection);
const auxValues = useDatasetsValues(auxDatasets, selection);
const auxErrors = useDatasetsValues(auxErrorDatasets, selection);
const axisValues = useDatasetsValues(axisDatasets);
const rawAxisValues = useDatasetsValues(axisDatasets);

const axisValues = rawAxisValues.map((value, i) => {
if (!value || isBigIntArray(value) || isBigIntTypedArray(value)) {
return value;
}

assertDefined(axisDefs[i]);
const { scalingFactor, offset } = axisDefs[i];
if (scalingFactor === undefined || offset === undefined) {
return value;
}

return value.map((v) => scalingFactor * v + offset);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I'm just realising that the NeXus spec says this should be: 🤔

corrected values = (FIELDNAME + offset) * scaling_factor`

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oopsie-daisy ! Thanks for checking 😹

});

return render({ title, signal, errors, auxValues, auxErrors, axisValues });
}
Expand Down
8 changes: 6 additions & 2 deletions packages/app/src/vis-packs/nexus/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,14 @@ import {
findTitleDataset,
getDatasetInfo,
getDefaultSlice,
getScalingInfo,
getSilxStyle,
} from './utils';

export const useDefaultSlice = createMemo(getDefaultSlice);

export function useNxData(group: GroupWithChildren): NxData {
const { attrValuesStore } = useDataContext();
const { attrValuesStore, valuesStore } = useDataContext();

assertNxDataGroup(group, attrValuesStore);
const signalDataset = findSignalDataset(group, attrValuesStore);
Expand All @@ -46,7 +47,10 @@ export function useNxData(group: GroupWithChildren): NxData {
})),
axisDefs: axisDatasets.map(
(dataset) =>
dataset && { dataset, ...getDatasetInfo(dataset, attrValuesStore) },
dataset && {
dataset,
...getAxisDef(group, dataset, attrValuesStore, valuesStore),
},
Comment on lines +50 to +53
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe time to make a getAxisDef function instead of adding getScalingInfo?

),
defaultSlice: useDefaultSlice(group, signalDataset.shape, attrValuesStore),
silxStyle: getSilxStyle(group, attrValuesStore),
Expand Down
7 changes: 6 additions & 1 deletion packages/app/src/vis-packs/nexus/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ export interface DatasetInfo {
unit: string | undefined;
}

export interface ScalingInfo {
scalingFactor: number | undefined;
offset: number | undefined;
}

export interface DatasetDef<
T extends NumericLikeType | ComplexType = NumericLikeType | ComplexType,
> extends DatasetInfo {
Expand All @@ -38,7 +43,7 @@ type WithError<T extends DatasetDef> = T & {
errorDataset?: Dataset<ArrayShape, NumericType>;
};

export type AxisDef = DatasetDef<NumericType>;
export type AxisDef = DatasetDef<NumericType> & ScalingInfo;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about:

interface AxisDef extends DatasetDef<NumericType> {
  scalingFactor: number | undefined;
  offset: number | undefined;
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, makes sense if we replace getScalingInfo by getAxisDef that will return AxisDef


export type DefaultSlice = (number | '.')[];
export interface SilxStyle {
Expand Down
24 changes: 21 additions & 3 deletions packages/app/src/vis-packs/nexus/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,27 @@ import { describe, expect, it } from 'vitest';
import { applyDefaultSlice, guessKeepRatio } from './utils';

const axisDataset = dataset('foo', intType(), [5]);
const axisDefNoUnit = { label: 'foo', unit: undefined, dataset: axisDataset };
const axisDefUnitX = { label: 'foo', unit: 'mm', dataset: axisDataset };
const axisDefUnitY = { label: 'foo', unit: 'degrees', dataset: axisDataset };
const axisDefNoUnit = {
label: 'foo',
unit: undefined,
dataset: axisDataset,
scalingFactor: undefined,
offset: undefined,
};
const axisDefUnitX = {
label: 'foo',
unit: 'mm',
dataset: axisDataset,
scalingFactor: undefined,
offset: undefined,
};
const axisDefUnitY = {
label: 'foo',
unit: 'degrees',
dataset: axisDataset,
scalingFactor: undefined,
offset: undefined,
};

describe('guessKeepRatio', () => {
it('should return `cover` if units of both axes are provided and equal', () => {
Expand Down
71 changes: 70 additions & 1 deletion packages/app/src/vis-packs/nexus/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
assertArrayShape,
assertDataset,
assertDefined,
assertNum,
assertNumericLikeOrComplexType,
assertNumericType,
assertScalarShape,
Expand All @@ -26,12 +27,13 @@ import {
} from '@h5web/shared/hdf5-models';
import { getChildEntity } from '@h5web/shared/hdf5-utils';

import { type AttrValuesStore } from '../../providers/models';
import { type AttrValuesStore, type ValuesStore } from '../../providers/models';
import { hasAttribute } from '../../utils';
import {
type AxisDef,
type DatasetInfo,
type DefaultSlice,
type ScalingInfo,
type SilxStyle,
} from './models';

Expand Down Expand Up @@ -130,6 +132,38 @@ export function findAuxErrorDataset(
return dataset;
}

export function findScalingFactorDataset(
group: GroupWithChildren,
datasetName: string,
): Dataset<ScalarShape, NumericType> | undefined {
const dataset = getChildEntity(group, `${datasetName}_scaling_factor`);

if (!dataset) {
return undefined;
}

assertDataset(dataset);
assertScalarShape(dataset);
assertNumericType(dataset);
return dataset;
}

export function findOffsetDataset(
group: GroupWithChildren,
datasetName: string,
): Dataset<ScalarShape, NumericType> | undefined {
const dataset = getChildEntity(group, `${datasetName}_offset`);

if (!dataset) {
return undefined;
}

assertDataset(dataset);
assertScalarShape(dataset);
assertNumericType(dataset);
return dataset;
}

export function findAssociatedDatasets(
group: GroupWithChildren,
type: 'axes' | 'auxiliary_signals',
Expand Down Expand Up @@ -312,6 +346,41 @@ export function getSilxStyle(
}
}

function getNumericValue(
dataset: Dataset<ScalarShape, NumericType> | undefined,
valuesStore: ValuesStore,
): number | undefined {
if (dataset === undefined) {
return undefined;
}

const value = valuesStore.get({ dataset });
assertNum(value);
return value;
}

export function getAxisDef(
group: GroupWithChildren,
dataset: Dataset,
attrValuesStore: AttrValuesStore,
valuesStore: ValuesStore,
): ScalingInfo {
const scalingFactor = getNumericValue(
findScalingFactorDataset(group, dataset.name),
valuesStore,
);
const offset = getNumericValue(
findOffsetDataset(group, dataset.name),
valuesStore,
);

return {
scalingFactor,
offset,
...getDatasetInfo(dataset, attrValuesStore),
};
}

export function getDatasetInfo(
dataset: Dataset,
attrValuesStore: AttrValuesStore,
Expand Down
8 changes: 8 additions & 0 deletions packages/shared/src/guards.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,14 @@ export function isComplexArray(val: unknown): val is H5WebComplex[] {
return Array.isArray(val) && isComplex(val[0]);
}

export function isBigIntArray(val: unknown): val is bigint[] {
return Array.isArray(val) && typeof val[0] === 'bigint';
}

export function isBoolArray(val: unknown): val is boolean[] {
return Array.isArray(val) && typeof val[0] === 'boolean';
}

export function isTypedArray(val: unknown): val is TypedArray {
return (
val instanceof Int8Array ||
Expand Down
Loading