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
4 changes: 3 additions & 1 deletion client/component/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"d3-array": "^3.2.4",
"d3-format": "^3.1.0",
"d3-scale": "^4.0.2",
"histogram.gl": "^1.0.2",
"messagepack": "^1.1.12",
"ndarray-concat-rows": "^1.0.1",
"ndarray-linspace": "^2.0.3",
Expand All @@ -39,7 +40,8 @@
"react-icons": "^5.3.0",
"react-select": "^5.8.0",
"react-use-websocket": "^4.8.1",
"websocket": "^1.0.35"
"websocket": "^1.0.35",
"zeros": "^1.0.0"
},
"peerDependencies": {
"@h5web/lib": "^13.0.0",
Expand Down
8 changes: 4 additions & 4 deletions client/component/src/AxisConfigModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ interface AxisConfigModalProps<S extends ScaleType> {
domain?: Domain;
/** The custom domain for the axis (optional) */
customDomain?: CustomDomain;
/** Histogram params */
histogram?: HistogramParams;
/** Histogram params getter */
histogramGetter?: () => Promise<HistogramParams>;
/** The function to call when the custom domain is updated (optional) */
setCustomDomain?: (value: CustomDomain) => void;
/** Point size for scatter plot (optional) */
Expand Down Expand Up @@ -106,15 +106,15 @@ function AxisConfigModal<S extends ScaleType>(
);

const domainSelector = props.domain &&
props.histogram &&
props.histogramGetter &&
props.customDomain &&
props.setCustomDomain && (
<DomainConfig
dataDomain={props.domain}
customDomain={props.customDomain}
scaleType={props.scaleType as ColorScaleType | undefined}
onCustomDomainChange={props.setCustomDomain}
histogram={props.histogram}
histogramGetter={props.histogramGetter}
/>
);

Expand Down
19 changes: 17 additions & 2 deletions client/component/src/DomainConfig.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ interface DomainConfigProps {
/** Handles custom domain change */
onCustomDomainChange: (domain: CustomDomain) => void;
/** Histogram params */
histogram?: HistogramParams;
histogramGetter?: () => Promise<HistogramParams>;
}

/**
Expand All @@ -83,11 +83,26 @@ interface DomainConfigProps {
*/
function DomainConfig(props: DomainConfigProps) {
const { dataDomain, customDomain, scaleType } = props;
const { onCustomDomainChange, histogram } = props;
const { onCustomDomainChange, histogramGetter } = props;
const [lockDomain, setLockDomain] = useState<boolean>(false);

const visDomain = useVisDomain(customDomain, dataDomain);

const [histogram, setHistogram] = useState<HistogramParams>();

useEffect(() => {
if (histogramGetter) {
console.time("Histogram calc");
const hp = histogramGetter();
hp.then((h) => {
console.timeEnd("Histogram calc");
setHistogram(h);
}).catch((e) => {
console.log('Could not calculate histogram:', e);
});
}
}, [histogramGetter, setHistogram]);

const memoizedCustomDomain = useMemo(() => {
if (lockDomain) {
return customDomain;
Expand Down
23 changes: 7 additions & 16 deletions client/component/src/HeatmapPlot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
} from '@h5web/lib';

import {
calculateHistogramCounts,
createHistogramParams,
createInteractionsConfig,
InteractionModeType,
} from './utils';
Expand All @@ -20,7 +20,7 @@ import {
usePlotCustomizationContext,
} from './PlotCustomizationContext';
import { AnyToolbar } from './PlotToolbar';
import { useEffect, useMemo } from 'react';
import { useEffect } from 'react';

interface Props {
xValues?: NDT;
Expand All @@ -46,24 +46,15 @@ export function HeatmapVisCanvas({ xValues, yValues, values }: Props) {
colourMap,
invertColourMap,
dScaleType,
setHistogram,
updateHistogramGetter,
} = usePlotCustomizationContext();
const interactionsConfig = createInteractionsConfig(mode);

const histogram = useMemo(
() => calculateHistogramCounts(values.data, dDomain),
[dDomain, values]
);

useEffect(() => {
if (histogram) {
setHistogram({
...histogram,
colorMap: colourMap,
invertColorMap: invertColourMap,
});
}
}, [colourMap, invertColourMap, histogram, setHistogram]);
const hg = () =>
createHistogramParams(values, dDomain, colourMap, invertColourMap);
updateHistogramGetter(hg);
}, [values.data, dDomain, colourMap, invertColourMap, updateHistogramGetter]);

return (
<HeatmapVis
Expand Down
24 changes: 16 additions & 8 deletions client/component/src/PlotCustomizationContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -130,10 +130,11 @@ export interface PlotCustomizationContextValue {
showPoints: boolean;
/** A function that toggles the points */
toggleShowPoints: () => void;
/** Histogram params */
histogram?: HistogramParams;
/** Set heatmap histogram */
setHistogram: (histogram: HistogramParams) => void;
/** Get heatmap histogram */
histogramGetter?: () => Promise<HistogramParams>;
/** Update heatmap histogram getter */
updateHistogramGetter: (getter: () => Promise<HistogramParams>) => void;

/** Can select */
canSelect: boolean;
/** Type of plot */
Expand Down Expand Up @@ -200,9 +201,15 @@ export function PlotCustomizationContextProvider(
new Map()
);
const [currentLineKey, setCurrentLineKey] = useState<string | null>(null);
const [histogram, setHistogram] = useState<HistogramParams>();
const [histogramGetter, setHistogramGetter] =
useState<() => Promise<HistogramParams>>();
const [scatterPointSize, setScatterPointSize] = useState<number>(10);

const updateHistogramGetter = useCallback(
(g: () => Promise<HistogramParams>) => setHistogramGetter(() => g),
[setHistogramGetter]
);

useEffect(() => {
if (props.plotConfig.title) setTitle(props.plotConfig.title);
}, [props.plotConfig.title, setTitle]);
Expand Down Expand Up @@ -335,7 +342,8 @@ export function PlotCustomizationContextProvider(
setDCustomDomain,
selectionType,
setSelectionType,
setHistogram,
histogramGetter,
updateHistogramGetter,
selections,
setSelections,
updateSelection: newUpdateSelection,
Expand All @@ -352,7 +360,6 @@ export function PlotCustomizationContextProvider(
setColourMap,
invertColourMap,
toggleInvertColourMap,
histogram,
scatterPointSize,
setScatterPointSize,
showPoints,
Expand All @@ -370,7 +377,8 @@ export function PlotCustomizationContextProvider(
dCustomDomain,
dDomain,
dScaleType,
histogram,
histogramGetter,
updateHistogramGetter,
invertColourMap,
mode,
newUpdateSelection,
Expand Down
2 changes: 1 addition & 1 deletion client/component/src/PlotToolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ function PlotToolbar(props: PropsWithChildren): JSX.Element {
domain: value.dDomain,
customDomain: value.dCustomDomain,
setCustomDomain: value.setDCustomDomain,
histogram: value.histogram,
histogramGetter: value.histogramGetter,
scatterPointSize: isScatter ? value.scatterPointSize : undefined,
setScatterPointSize: value.setScatterPointSize,
hasBaton,
Expand Down
23 changes: 7 additions & 16 deletions client/component/src/ScatterPlot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {

import SelectionComponent from './SelectionComponent';
import {
calculateHistogramCounts,
createHistogramParams,
createInteractionsConfig,
InteractionModeType,
} from './utils';
Expand All @@ -18,7 +18,7 @@ import {
usePlotCustomizationContext,
} from './PlotCustomizationContext';
import { AnyToolbar } from './PlotToolbar';
import { useEffect, useMemo } from 'react';
import { useEffect } from 'react';

interface Props {
x: NDT;
Expand Down Expand Up @@ -46,24 +46,15 @@ export function ScatterVisCanvas({ x, y, values }: Props) {
invertColourMap,
dScaleType,
scatterPointSize,
setHistogram,
updateHistogramGetter,
} = usePlotCustomizationContext();
const interactionsConfig = createInteractionsConfig(mode);

const histogram = useMemo(
() => calculateHistogramCounts(values.data, dDomain),
[dDomain, values]
);

useEffect(() => {
if (histogram) {
setHistogram({
...histogram,
colorMap: colourMap,
invertColorMap: invertColourMap,
});
}
}, [colourMap, invertColourMap, histogram, setHistogram]);
const hg = () =>
createHistogramParams(values, dDomain, colourMap, invertColourMap);
updateHistogramGetter(hg);
}, [values.data, dDomain, colourMap, invertColourMap, updateHistogramGetter]);

return (
<ScatterVis
Expand Down
20 changes: 6 additions & 14 deletions client/component/src/SurfacePlot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
} from './PlotCustomizationContext';
import { AnyToolbar } from './PlotToolbar';
import { PropsWithChildren, useEffect, useMemo } from 'react';
import { calculateHistogramCounts } from './utils';
import { createHistogramParams } from './utils';

interface Props {
values: NDT;
Expand All @@ -30,7 +30,7 @@ export function SurfaceVisCanvas(props: PropsWithChildren<Props>) {
invertColourMap,
dScaleType,
showPoints,
setHistogram,
updateHistogramGetter,
} = usePlotCustomizationContext();

const visDomain = useMemo(
Expand All @@ -39,18 +39,10 @@ export function SurfaceVisCanvas(props: PropsWithChildren<Props>) {
);

useEffect(() => {
const histogram = calculateHistogramCounts(values.data, dDomain);

if (histogram) {
console.log('Set histogram:', histogram, colourMap, invertColourMap);

setHistogram({
...histogram,
colorMap: colourMap,
invertColorMap: invertColourMap,
});
}
}, [dDomain, values, colourMap, invertColourMap, setHistogram]);
const hg = () =>
createHistogramParams(values, dDomain, colourMap, invertColourMap);
updateHistogramGetter(hg);
}, [values.data, dDomain, colourMap, invertColourMap, updateHistogramGetter]);

return (
<SurfaceVis
Expand Down
61 changes: 60 additions & 1 deletion client/component/src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import ndarray from 'ndarray';
import type { TypedArray } from 'ndarray';
import concatRows from 'ndarray-concat-rows';
import linspace from 'ndarray-linspace';
import cwise from 'cwise';
import zeros from 'zeros';

import { bin } from 'd3-array';
import { scaleLinear } from 'd3-scale';
import type {
Expand All @@ -12,12 +15,14 @@ import type {
ColorScaleType,
DefaultInteractionsConfig,
Domain,
HistogramParams,
PanProps,
SelectToZoomProps,
XAxisZoomProps,
YAxisZoomProps,
ZoomProps,
} from '@h5web/lib';
import { createSingleChannelHistogram } from 'histogram.gl';

import type { PlotConfig, NDT } from './models';
import type { HeatmapData } from './HeatmapPlot';
Expand Down Expand Up @@ -512,7 +517,7 @@ interface HistogramCounts {
*/
function calculateHistogramCounts(
data: TypedArray | undefined,
domain: Domain | undefined
domain?: Domain
): HistogramCounts | undefined {
if (data && data.length != 0) {
const localBin = bin();
Expand Down Expand Up @@ -545,6 +550,59 @@ function calculateHistogramCounts(
return undefined;
}

/**
* Create histogram from given data
* @param data data
* @param _domain optional limits
* @returns histogram
*/
function calculateHistogramCounts2(data: NDT, _domain?: Domain) {
const shape = data.shape;
const hp = createSingleChannelHistogram(
data.data,
shape[1],
shape[0]
) as Promise<TypedArray>;
const mm = nanMinMax(data);
const edges = (linspace(zeros([256 + 1], 'float32'), mm[0], mm[1]) as NDT)
.data;

return hp
.then((h) => {
return {
values: h,
bins: edges,
} as HistogramCounts;
})
.catch((e) => {
console.log('Could not calculate histogram:', e);
return undefined;
}) as Promise<HistogramCounts>;
}

/**
* Create histogram parameters
* @param data
* @param domain
* @param colorMap
* @param invertColorMap
* @returns histogram parameters
*/
function createHistogramParams(
data: NDT,
domain: Domain,
colorMap: ColorMap,
invertColorMap: boolean
) {
const hcp = calculateHistogramCounts2(data, domain);
return hcp.then((hc) => {
return { ...hc, colorMap, invertColorMap };
}) as Promise<HistogramParams>;
}

/**
* Measure time of interaction
*/
function measureInteraction() {
const startTimestamp = performance.now();
return {
Expand Down Expand Up @@ -573,6 +631,7 @@ export {
createSurfaceData,
createTableData,
calculateHistogramCounts,
createHistogramParams,
createInteractionsConfig,
getAspectType,
InteractionModeType,
Expand Down
Loading
Loading