Skip to content

Commit 956823c

Browse files
committed
Datetime selection #2
1 parent f648164 commit 956823c

File tree

5 files changed

+130
-33
lines changed

5 files changed

+130
-33
lines changed

src/App.tsx

Lines changed: 33 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import Panel from "@/components/Panel";
1212
import Description from "@/components/Description";
1313
import Dropdown from "@/components/ui/Dropdown";
1414
import RangeSlider from "@/components/ui/RangeSlider";
15+
import SingleSlider from "@/components/ui/Slider";
1516
import CheckBox from "@/components/ui/Checkbox";
1617

1718
import "maplibre-gl/dist/maplibre-gl.css";
@@ -46,33 +47,34 @@ function DeckGLOverlay(props) {
4647
return null;
4748
}
4849

49-
async function getTileData({ index, signal }: _TileLoadProps) {
50-
if (signal?.aborted) {
51-
console.error("Signal aborted: ", signal);
52-
return null;
53-
}
54-
const scale = zarrReader.scale;
55-
56-
const { min, max } = scale;
57-
const chunkData = await zarrReader.getTileData(index);
58-
if (chunkData) {
59-
return {
60-
imageData: chunkData,
61-
min,
62-
max,
63-
};
64-
} else {
65-
throw Error("No tile data available");
66-
}
67-
}
68-
6950
function App() {
7051
const [selectedColormap, setSelectedColormap] = useState<string>("viridis");
7152
const [minMax, setMinMax] = useState<{ min: number; max: number }>(
7253
zarrReader.scale
7354
);
55+
const [timestamp, setTimestamp] = useState<number>(0);
7456
const [showTooltip, setShowTooltip] = useState<boolean>(true);
7557

58+
async function getTileData({ index, signal }: _TileLoadProps) {
59+
if (signal?.aborted) {
60+
console.error("Signal aborted: ", signal);
61+
return null;
62+
}
63+
const scale = zarrReader.scale;
64+
65+
const { min, max } = scale;
66+
const chunkData = await zarrReader.getTileData({ ...index, timestamp });
67+
if (chunkData) {
68+
return {
69+
imageData: chunkData,
70+
min,
71+
max,
72+
};
73+
} else {
74+
throw Error("No tile data available");
75+
}
76+
}
77+
7678
const layers = [
7779
new TileLayer({
7880
id: "TileLayer",
@@ -96,6 +98,9 @@ function App() {
9698
// Any better way to do this?
9799
selectedColormap,
98100
minMax,
101+
updateTriggers: {
102+
getTileData: timestamp,
103+
},
99104
renderSubLayers: (props) => {
100105
const { imageData } = props.data;
101106
const { boundingBox } = props.tile;
@@ -156,8 +161,16 @@ function App() {
156161
<Dropdown onChange={setSelectedColormap} />
157162
<RangeSlider
158163
minMax={[zarrReader.scale.min, zarrReader.scale.max]}
164+
label="Scale"
159165
onValueChange={setMinMax}
160166
/>
167+
168+
<SingleSlider
169+
minMax={[0, 2]}
170+
step={1}
171+
label="Timestamp"
172+
onValueChange={setTimestamp}
173+
/>
161174
<CheckBox onCheckedChange={setShowTooltip} />
162175
</Panel>
163176
</>

src/components/ui/RangeSlider.tsx

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
import { Slider } from "@chakra-ui/react";
2+
import type { SliderUIProps } from "./Slider";
23

3-
type RangeSliderUIProps = {
4-
minMax: [number, number];
4+
type RangeSliderUIProps = SliderUIProps & {
55
onValueChange: (param: { min: number; max: number }) => void;
66
};
77

88
export default function RangeSliderUI({
99
minMax,
10+
step = 20,
11+
label,
1012
onValueChange,
1113
}: RangeSliderUIProps) {
12-
const step = (minMax[1] - minMax[0]) / 20;
14+
const oneStep = (minMax[1] - minMax[0]) / step;
1315

1416
const handleChange = (detail: Slider.ValueChangeDetails) => {
1517
onValueChange({
@@ -24,10 +26,10 @@ export default function RangeSliderUI({
2426
defaultValue={minMax}
2527
max={minMax[1]}
2628
min={minMax[0]}
27-
minStepsBetweenThumbs={step}
29+
minStepsBetweenThumbs={oneStep}
2830
onValueChangeEnd={handleChange}
2931
>
30-
<Slider.Label> Scale </Slider.Label>
32+
<Slider.Label> {label} </Slider.Label>
3133
<Slider.Control>
3234
<Slider.Track>
3335
<Slider.Range />

src/components/ui/Slider.tsx

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { Slider } from "@chakra-ui/react";
2+
3+
export type SliderUIProps = {
4+
minMax: [number, number];
5+
step?: number;
6+
label?: string;
7+
onValueChange: (param: number) => void;
8+
};
9+
10+
export default function SingleSlider({
11+
minMax,
12+
step,
13+
label,
14+
onValueChange,
15+
}: SliderUIProps) {
16+
const handleChange = (detail: Slider.ValueChangeDetails) => {
17+
onValueChange(detail.value[0]);
18+
};
19+
return (
20+
<Slider.Root
21+
defaultValue={[minMax[0]]}
22+
min={minMax[0]}
23+
max={minMax[1]}
24+
maxW="100%"
25+
width="100%"
26+
step={step}
27+
onValueChange={handleChange}
28+
>
29+
<Slider.Label> {label} </Slider.Label>
30+
<Slider.Control>
31+
<Slider.Track>
32+
<Slider.Range />
33+
</Slider.Track>
34+
<Slider.Thumb index={0} boxSize={6} shadow="md"></Slider.Thumb>
35+
</Slider.Control>
36+
</Slider.Root>
37+
);
38+
}

src/layers/NumericDataLayer/index.tsx

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,38 @@ import {
55
LayerContext,
66
GetPickingInfoParams,
77
} from "deck.gl";
8+
import type { CompositeLayerProps, UpdateParameters } from "deck.gl";
89
import type { BitmapLayerPickingInfo } from "@deck.gl/layers";
910
import type { Texture } from "@luma.gl/core";
1011

1112
import { NumericDataPaintLayer } from "../NumericDataPaintLayer";
1213
import type { NumericDataLayerProps, NumericDataPickingInfo } from "./types";
1314

15+
const textureDefaultOption = {
16+
format: "r32float" as const,
17+
dimension: "2d" as const,
18+
};
19+
20+
const textureSamplerDefaultOption = {
21+
minFilter: "linear" as const,
22+
magFilter: "linear" as const,
23+
mipmapFilter: "linear" as const,
24+
addressModeU: "clamp-to-edge" as const,
25+
addressModeV: "clamp-to-edge" as const,
26+
};
27+
1428
export default class NumericDataLayer extends CompositeLayer<NumericDataLayerProps> {
1529
static layerName: string = "numeric-data-layer";
1630

1731
initializeState(context: LayerContext): void {
1832
const { tileSize, textureParameters } = this.props;
1933
const dataTexture = context.device.createTexture({
2034
data: this.props.imageData,
21-
format: "r32float",
2235
width: tileSize,
2336
height: tileSize,
37+
...textureDefaultOption,
2438
sampler: {
25-
minFilter: "linear",
26-
magFilter: "linear",
27-
mipmapFilter: "linear",
28-
addressModeU: "clamp-to-edge",
29-
addressModeV: "clamp-to-edge",
39+
...textureSamplerDefaultOption,
3040
...textureParameters,
3141
},
3242
});
@@ -35,6 +45,32 @@ export default class NumericDataLayer extends CompositeLayer<NumericDataLayerPro
3545
});
3646
}
3747

48+
updateState(
49+
params: UpdateParameters<
50+
Layer<NumericDataLayerProps & Required<CompositeLayerProps>>
51+
>
52+
): void {
53+
const { props, oldProps, context } = params;
54+
const { imageData } = props;
55+
const { imageData: oldImageData } = oldProps;
56+
if (imageData !== oldImageData) {
57+
const { tileSize, textureParameters } = props;
58+
const dataTexture = context.device.createTexture({
59+
data: imageData,
60+
width: tileSize,
61+
height: tileSize,
62+
...textureDefaultOption,
63+
sampler: {
64+
...textureSamplerDefaultOption,
65+
...textureParameters,
66+
},
67+
});
68+
this.setState({
69+
dataTexture,
70+
});
71+
}
72+
}
73+
3874
getPickingInfo(parmas: GetPickingInfoParams): NumericDataPickingInfo {
3975
const info = parmas.info as BitmapLayerPickingInfo;
4076
if (info.bitmap) {

src/zarr/index.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,13 +80,21 @@ export default class ZarrReader {
8080
x,
8181
y,
8282
z,
83-
}: TileIndex): Promise<TypedArray<NumberDataType> | undefined> {
83+
timestamp,
84+
}: TileIndex & { timestamp: number }): Promise<
85+
TypedArray<NumberDataType> | undefined
86+
> {
8487
const arr = await zarr.open.v3(this.root.resolve(`${z}/${this._varName}`), {
8588
kind: "array",
8689
});
8790

8891
if (arr.is("number")) {
89-
const { data } = await arr.getChunk([this._t, y, x]);
92+
const { data } = await arr.getChunk([timestamp, y, x]);
93+
// @TODO : remove once the data has actual timestamps
94+
if (timestamp == 1) {
95+
return new Float32Array(this.tileSize * this.tileSize);
96+
}
97+
9098
return data;
9199
} else {
92100
return undefined;

0 commit comments

Comments
 (0)