@fxi/zartigl 0.1.3 → 0.2.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,15 +1,19 @@
1
1
  {
2
2
  "name": "@fxi/zartigl",
3
- "version": "0.1.3",
3
+ "version": "0.2.13",
4
4
  "description": "MapLibre GL JS plugin for animated particle flow from Zarr ocean current data",
5
5
  "type": "module",
6
6
  "main": "./dist/zartigl.js",
7
7
  "module": "./dist/zartigl.js",
8
- "types": "./dist/index.d.ts",
8
+ "types": "./dist/zartigl.d.ts",
9
9
  "exports": {
10
10
  ".": {
11
11
  "import": "./dist/zartigl.js",
12
- "types": "./dist/index.d.ts"
12
+ "types": "./dist/zartigl.d.ts"
13
+ },
14
+ "./catalog": {
15
+ "import": "./dist/catalog.js",
16
+ "types": "./dist/catalog.d.ts"
13
17
  }
14
18
  },
15
19
  "files": [
@@ -17,11 +21,22 @@
17
21
  ],
18
22
  "scripts": {
19
23
  "dev": "vite",
20
- "dev:mapbox": "vite --config vite.config.demo-mapbox.ts",
24
+ "dev:minimal": "vite --config vite.config.minimal.ts",
25
+ "dev:prod": "npm run dev",
26
+ "test": "vitest run",
27
+ "test:unit": "vitest run",
21
28
  "build": "vite build",
22
- "build:mapbox": "vite build --config vite.config.demo-mapbox.ts",
29
+ "build:minimal": "vite build --config vite.config.minimal.ts",
30
+ "build:prod": "npm run build",
23
31
  "build:lib": "vite build --config vite.config.lib.ts",
24
32
  "preview": "vite preview",
33
+ "catalog": "npm run catalog:validate",
34
+ "catalog:validate": "uv run scripts/catalog_builder/skills/validate_catalog.py",
35
+ "geovideo:dry-run": "uv run scripts/geovideo/render.py scripts/geovideo/examples/sst-anomaly.json --dry-run",
36
+ "geovideo:calibrate": "uv run scripts/geovideo/calibrate.py",
37
+ "geovideo:calibrate:browser": "uv run scripts/geovideo/browser_calibrate.py",
38
+ "smoke:sample": "npm run build:lib && node scripts/smoke-sample-point.mjs",
39
+ "release:check": "npm run test && npm run catalog:validate && npm run build && npm run build:lib && npm run smoke:sample",
25
40
  "prepublishOnly": "npm run build:lib"
26
41
  },
27
42
  "publishConfig": {
@@ -40,17 +55,21 @@
40
55
  "peerDependencies": {
41
56
  "maplibre-gl": ">=4.0.0"
42
57
  },
58
+ "dependencies": {
59
+ "numcodecs": "^0.3.2",
60
+ "pako": "^2.1.0"
61
+ },
43
62
  "devDependencies": {
44
63
  "@tweakpane/core": "^2.0.5",
64
+ "@types/d3": "^7.4.3",
45
65
  "@types/pako": "^2.0.4",
46
- "mapbox-gl": "^2.15.0",
66
+ "d3": "^7.9.0",
47
67
  "maplibre-gl": "^5.17.0",
48
- "numcodecs": "^0.3.2",
49
- "pako": "^2.1.0",
50
68
  "tweakpane": "^4.0.5",
51
69
  "typescript": "^5.9.3",
52
70
  "vite": "^7.3.1",
53
71
  "vite-plugin-dts": "^4.5.4",
54
- "vite-plugin-glsl": "^1.5.5"
72
+ "vite-plugin-glsl": "^1.5.5",
73
+ "vitest": "^4.1.7"
55
74
  }
56
75
  }
@@ -1,108 +0,0 @@
1
- {
2
- "generated": "2026-02-11T08:27:15.746557+00:00",
3
- "datasets": [
4
- {
5
- "id": "cmems_mod_glo_phy-cur_anfc_0.083deg_PT6H-i",
6
- "product": "GLOBAL_ANALYSISFORECAST_PHY_001_024",
7
- "label": "Global Ocean Currents (analysis+forecast)",
8
- "zarr_url": "https://s3.waw3-1.cloudferro.com/mdl-arco-time-009/arco/GLOBAL_ANALYSISFORECAST_PHY_001_024/cmems_mod_glo_phy-cur_anfc_0.083deg_PT6H-i_202406/timeChunked.zarr",
9
- "variables": {
10
- "uo": {
11
- "standard_name": "eastward_sea_water_velocity",
12
- "units": "m s-1"
13
- },
14
- "vo": {
15
- "standard_name": "northward_sea_water_velocity",
16
- "units": "m s-1"
17
- }
18
- },
19
- "dimensions": {
20
- "depth": {
21
- "axis": "z",
22
- "values": [
23
- 5727.9169921875,
24
- 5274.7841796875,
25
- 4833.291015625,
26
- 4405.22412109375,
27
- 3992.48388671875,
28
- 3597.031982421875,
29
- 3220.820068359375,
30
- 2865.702880859375,
31
- 2533.3359375,
32
- 2225.077880859375,
33
- 1941.8929443359375,
34
- 1684.2840576171875,
35
- 1452.2509765625,
36
- 1245.291015625,
37
- 1062.43994140625,
38
- 902.3392944335938,
39
- 763.3331298828125,
40
- 643.5667724609375,
41
- 541.0889282226562,
42
- 453.9377136230469,
43
- 380.2130126953125,
44
- 318.1274108886719,
45
- 266.0403137207031,
46
- 222.47520446777344,
47
- 186.12559509277344,
48
- 155.85069274902344,
49
- 130.66600036621094,
50
- 109.72930145263672,
51
- 92.3260726928711,
52
- 77.85385131835938,
53
- 65.80726623535156,
54
- 55.76428985595703,
55
- 47.37369155883789,
56
- 40.344051361083984,
57
- 34.43415069580078,
58
- 29.444730758666992,
59
- 25.211410522460938,
60
- 21.598819732666016,
61
- 18.495559692382812,
62
- 15.810070037841797,
63
- 13.467140197753906,
64
- 11.404999732971191,
65
- 9.572997093200684,
66
- 7.92956018447876,
67
- 6.440614223480225,
68
- 5.078224182128906,
69
- 3.8194949626922607,
70
- 2.6456689834594727,
71
- 1.5413750410079956,
72
- 0.49402499198913574
73
- ],
74
- "size": 50,
75
- "chunk_size": 1,
76
- "units": "m"
77
- },
78
- "latitude": {
79
- "axis": "y",
80
- "size": 2041,
81
- "min": -80.0,
82
- "max": 90.0,
83
- "step": 0.08333333333333333,
84
- "chunk_size": 512,
85
- "units": "degrees_north"
86
- },
87
- "longitude": {
88
- "axis": "x",
89
- "size": 4320,
90
- "min": -180.0,
91
- "max": 179.91668701171875,
92
- "step": 0.08333333804392655,
93
- "chunk_size": 2048,
94
- "units": "degrees_east"
95
- },
96
- "time": {
97
- "axis": "t",
98
- "size": 5445,
99
- "min": 1654041600000.0,
100
- "max": 1771632000000.0,
101
- "step": 21600000.0,
102
- "chunk_size": 1,
103
- "units": "milliseconds since 1970-01-01 00:00:00Z (no leap seconds)"
104
- }
105
- }
106
- }
107
- ]
108
- }
package/dist/index.d.ts DELETED
@@ -1,282 +0,0 @@
1
- import { CustomLayerInterface } from 'maplibre-gl';
2
- import { CustomRenderMethodInput } from 'maplibre-gl';
3
- import { Map as Map_2 } from 'maplibre-gl';
4
-
5
- declare interface CoordArrays {
6
- time: Float64Array | Float32Array;
7
- vertical: Float32Array;
8
- latitude: Float32Array;
9
- longitude: Float32Array;
10
- }
11
-
12
- export declare class ParticleLayer implements CustomLayerInterface {
13
- readonly id: string;
14
- readonly type: "custom";
15
- readonly renderingMode: "2d";
16
- private map;
17
- private gl;
18
- private simulation;
19
- private velocityField;
20
- private zarrSource;
21
- private opts;
22
- private initialized;
23
- private loading;
24
- private velocityTexUnit;
25
- private moveEndHandler;
26
- constructor(options: ParticleLayerOptions);
27
- onAdd(map: Map_2, gl: WebGLRenderingContext): Promise<void>;
28
- private initAsync;
29
- private loadViewportVelocity;
30
- render(gl: WebGLRenderingContext, options: CustomRenderMethodInput | number[]): void;
31
- onRemove(): void;
32
- setTime(time: string | number): void;
33
- setDepth(depth: number): void;
34
- setSpeedFactor(v: number): void;
35
- setFadeOpacity(v: number): void;
36
- setDropRate(v: number): void;
37
- setDropRateBump(v: number): void;
38
- setPointSize(v: number): void;
39
- setParticleCount(count: number): void;
40
- setColorRamp(ramp: Record<number, string>): void;
41
- }
42
-
43
- export declare interface ParticleLayerOptions {
44
- id: string;
45
- source: string;
46
- variableU?: string;
47
- variableV?: string;
48
- particleCount?: number;
49
- speedFactor?: number;
50
- fadeOpacity?: number;
51
- dropRate?: number;
52
- dropRateBump?: number;
53
- pointSize?: number;
54
- colorRamp?: Record<number, string>;
55
- time?: string | number;
56
- depth?: number;
57
- }
58
-
59
- export declare class ParticleSimulation {
60
- private gl;
61
- private params;
62
- private updateProgram;
63
- private drawProgram;
64
- private fadeProgram;
65
- private particleStateTextures;
66
- private particleFramebuffers;
67
- private particleStateRes;
68
- private particleIndexBuffer;
69
- private numParticles;
70
- private screenTextures;
71
- private screenFramebuffers;
72
- private screenWidth;
73
- private screenHeight;
74
- private quadBuffer;
75
- private colorRampTexture;
76
- private updateLocs;
77
- private drawLocs;
78
- private fadeLocs;
79
- constructor(params?: Partial<SimulationParams>);
80
- init(gl: WebGLRenderingContext): void;
81
- private getUniforms;
82
- private initParticleState;
83
- /**
84
- * Ensure screen textures match the current canvas size.
85
- */
86
- resize(width: number, height: number): void;
87
- /**
88
- * Run one simulation step: update positions, fade trails, draw particles.
89
- * Must be called within the MapLibre render callback.
90
- */
91
- render(velocityTexUnit: number, velocityMin: [number, number], velocityMax: [number, number], matrix: Iterable<number>, bounds: {
92
- minX: number;
93
- minY: number;
94
- maxX: number;
95
- maxY: number;
96
- }, worldSize: number, geoBounds?: {
97
- west: number;
98
- south: number;
99
- east: number;
100
- north: number;
101
- }): void;
102
- private drawQuad;
103
- setSpeedFactor(v: number): void;
104
- setFadeOpacity(v: number): void;
105
- setDropRate(v: number): void;
106
- setDropRateBump(v: number): void;
107
- setPointSize(v: number): void;
108
- setParticleCount(count: number): void;
109
- setColorRamp(ramp: Record<number, string>): void;
110
- /**
111
- * Reset all particles to random positions. Call after time/depth change.
112
- */
113
- resetParticles(): void;
114
- destroy(): void;
115
- }
116
-
117
- declare interface SimulationParams {
118
- particleCount: number;
119
- speedFactor: number;
120
- fadeOpacity: number;
121
- dropRate: number;
122
- dropRateBump: number;
123
- pointSize: number;
124
- colorRamp?: Record<number, string>;
125
- }
126
-
127
- /**
128
- * Stitch multiple decoded chunks into a single global velocity grid.
129
- * The result covers [0,360) longitude x [-90,90] latitude.
130
- * Grid resolution matches the source data.
131
- */
132
- export declare function stitchVelocityChunks(uChunks: Array<{
133
- data: Float32Array;
134
- latStart: number;
135
- lonStart: number;
136
- latSize: number;
137
- lonSize: number;
138
- }>, vChunks: Array<{
139
- data: Float32Array;
140
- latStart: number;
141
- lonStart: number;
142
- latSize: number;
143
- lonSize: number;
144
- }>, totalLat: number, totalLon: number, geoBounds?: {
145
- west: number;
146
- south: number;
147
- east: number;
148
- north: number;
149
- }): VelocityData;
150
-
151
- export declare interface VelocityData {
152
- u: Float32Array;
153
- v: Float32Array;
154
- width: number;
155
- height: number;
156
- uMin: number;
157
- uMax: number;
158
- vMin: number;
159
- vMax: number;
160
- bounds: {
161
- west: number;
162
- south: number;
163
- east: number;
164
- north: number;
165
- };
166
- }
167
-
168
- /**
169
- * Manages a WebGL texture that holds stitched U/V velocity data
170
- * in geographic space [0,1]x[0,1], with R=u, G=v normalized to [0,1].
171
- */
172
- export declare class VelocityField {
173
- private gl;
174
- private texture;
175
- private width;
176
- private height;
177
- uMin: number;
178
- uMax: number;
179
- vMin: number;
180
- vMax: number;
181
- geoBounds: {
182
- west: number;
183
- south: number;
184
- east: number;
185
- north: number;
186
- };
187
- init(gl: WebGLRenderingContext): void;
188
- /**
189
- * Upload velocity data as a 2-channel (RG) texture.
190
- * Input: u/v Float32Arrays with real physical values.
191
- * Stored normalized to [0,1] using uMin/uMax/vMin/vMax.
192
- */
193
- update(data: VelocityData): void;
194
- bind(unit: number): void;
195
- hasData(): boolean;
196
- destroy(): void;
197
- }
198
-
199
- export declare interface ZarrArrayMeta {
200
- zarr_format: number;
201
- shape: number[];
202
- chunks: number[];
203
- dtype: string;
204
- compressor: {
205
- id: string;
206
- level?: number;
207
- clevel?: number;
208
- cname?: string;
209
- shuffle?: number;
210
- blocksize?: number;
211
- } | null;
212
- fill_value: number | string | null;
213
- order: string;
214
- filters: unknown[] | null;
215
- dimension_separator?: string;
216
- }
217
-
218
- declare interface ZarrAttrs {
219
- _ARRAY_DIMENSIONS?: string[];
220
- units?: string;
221
- standard_name?: string;
222
- long_name?: string;
223
- calendar?: string;
224
- [key: string]: unknown;
225
- }
226
-
227
- export declare interface ZarrConsolidatedMeta {
228
- zarr_consolidated_format: number;
229
- metadata: Record<string, ZarrArrayMeta | ZarrAttrs | {
230
- zarr_format: number;
231
- }>;
232
- }
233
-
234
- export declare class ZarrSource {
235
- private root;
236
- private meta;
237
- private coords;
238
- private verticalName;
239
- private cache;
240
- private maxCacheSize;
241
- private abortControllers;
242
- private bloscCodecCache;
243
- constructor(root: string, maxCacheSize?: number);
244
- init(): Promise<void>;
245
- private getArrayMeta;
246
- private getAttrs;
247
- getDimensionSeparator(variable: string): string;
248
- getShape(variable: string): number[];
249
- getChunkShape(variable: string): number[];
250
- getCoords(): CoordArrays;
251
- getDimensions(variable: string): string[];
252
- findNearestIndex(array: Float32Array | Float64Array, value: number): number;
253
- findTimeIndex(time: string | number): number;
254
- findDepthIndex(depth: number): number;
255
- /** Return the actual name of the vertical dimension ("depth" or "elevation"). */
256
- getVerticalDimName(): string;
257
- /**
258
- * Get chunk indices that intersect a geographic bounding box.
259
- */
260
- getChunksForBounds(variable: string, timeIdx: number, depthIdx: number, bounds: {
261
- west: number;
262
- south: number;
263
- east: number;
264
- north: number;
265
- }): Array<{
266
- timeIdx: number;
267
- depthIdx: number;
268
- latIdx: number;
269
- lonIdx: number;
270
- latRange: [number, number];
271
- lonRange: [number, number];
272
- latSize: number;
273
- lonSize: number;
274
- }>;
275
- fetchChunk(variable: string, indices: number[]): Promise<Float32Array>;
276
- cancelAll(): void;
277
- private getBloscCodec;
278
- private decompress;
279
- private loadCoordinates;
280
- }
281
-
282
- export { }