@oceanmetrics/engine 0.1.0 → 0.1.1
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/CHANGELOG.md +6 -0
- package/README.md +3 -1
- package/dist/preview.js +5 -2
- package/package.json +1 -1
- package/src/preview.ts +5 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.1 (2026-10-23)
|
|
4
|
+
|
|
5
|
+
- Fix: `sliceSource().slice()` read the lobes' slabs without the `SELECT DISTINCT` that `runPreview` applies, so where two
|
|
6
|
+
places' boxes overlap (Channel Islands and Chumash) every cell of the overlap came back twice. Regression test with two
|
|
7
|
+
overlapping synthetic slabs.
|
|
8
|
+
|
|
3
9
|
## 0.1.0 (2026-10-23)
|
|
4
10
|
|
|
5
11
|
The browser engine, build week 2 step 2b: erddap-places' engine as a platform package, so the indicators Map's `grid`
|
package/README.md
CHANGED
|
@@ -112,7 +112,9 @@ const run = await runPreview({
|
|
|
112
112
|
`@oceanmetrics/map`'s `gridSlot(spec, source)`: `slice(t)` fetches the one step `t` (a day or an ISO instant;
|
|
113
113
|
`null` is the extent's end, or ERDDAP's `last` without an extent) of every lobe and returns `last_step`'s rows as
|
|
114
114
|
`{ lat, lon, value, weight }`, the mask's own centres, a cell without data kept with `value: null`. The mask goes into
|
|
115
|
-
the engine once, at the first slice.
|
|
115
|
+
the engine once, at the first slice. The slabs of the lobes are read as `SELECT DISTINCT *` (as `runPreview` does), so a
|
|
116
|
+
cell inside two overlapping boxes (Channel Islands and Chumash) comes back once, not twice (0.1.1); the mask you pass is
|
|
117
|
+
the places' union and must hold each cell once.
|
|
116
118
|
|
|
117
119
|
## DuckDB-WASM: the peer and the worker setup
|
|
118
120
|
|
package/dist/preview.js
CHANGED
|
@@ -91,6 +91,9 @@ async function loadSlabs(engine, urls, format, signal, retry) {
|
|
|
91
91
|
return files;
|
|
92
92
|
}
|
|
93
93
|
const readList = (files) => `read_parquet([${files.map((f) => `'${f}'`).join(', ')}])`;
|
|
94
|
+
// the lobes' slabs as one relation without a row twice: where two places' boxes overlap (Channel Islands and Chumash)
|
|
95
|
+
// both slabs hold the cells of the overlap, and the join over the mask would return each of them twice
|
|
96
|
+
const distinctSlab = (files) => `(SELECT DISTINCT * FROM ${readList(files)})`;
|
|
94
97
|
/**
|
|
95
98
|
* The statistics of `variable` over the place for [t0, t1], chunk by chunk. Each chunk's slab (one Parquet request per
|
|
96
99
|
* lobe) is registered, aggregated with the template over the mask and dropped; `onChunk` gets its rows as soon as they
|
|
@@ -142,7 +145,7 @@ export async function runPreview(o) {
|
|
|
142
145
|
files.push(f);
|
|
143
146
|
}
|
|
144
147
|
// DISTINCT: a coarse axis (the 8-day grid) can snap a chunk's two endpoints onto one step
|
|
145
|
-
const slab =
|
|
148
|
+
const slab = distinctSlab(files);
|
|
146
149
|
const out = await engine.runTemplate(name, { expr, slab, mask });
|
|
147
150
|
aborted(signal);
|
|
148
151
|
// two chunks snapped onto the same step of a coarse axis give that step twice, identical: keep the first
|
|
@@ -187,7 +190,7 @@ export function sliceSource(o) {
|
|
|
187
190
|
try {
|
|
188
191
|
await inserted;
|
|
189
192
|
aborted(signal);
|
|
190
|
-
const rows = await o.engine.runTemplate('last_step', { expr: valueExpr(o.variable), slab:
|
|
193
|
+
const rows = await o.engine.runTemplate('last_step', { expr: valueExpr(o.variable), slab: distinctSlab(files), mask });
|
|
191
194
|
return rows.map((r) => ({
|
|
192
195
|
lat: Number(r.latitude), lon: Number(r.longitude), weight: Number(r.weight),
|
|
193
196
|
value: r.value === null || r.value === undefined ? null : Number(r.value),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oceanmetrics/engine",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "the browser engine of Ocean Metrics: the place mask, ERDDAP requests, the SQL shared with the Python engine, DuckDB-WASM statistics and the chunked live preview",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ocean",
|
package/src/preview.ts
CHANGED
|
@@ -109,6 +109,9 @@ async function loadSlabs(engine: Engine, urls: string[], format: Format, signal:
|
|
|
109
109
|
return files
|
|
110
110
|
}
|
|
111
111
|
const readList = (files: string[]) => `read_parquet([${files.map((f) => `'${f}'`).join(', ')}])`
|
|
112
|
+
// the lobes' slabs as one relation without a row twice: where two places' boxes overlap (Channel Islands and Chumash)
|
|
113
|
+
// both slabs hold the cells of the overlap, and the join over the mask would return each of them twice
|
|
114
|
+
const distinctSlab = (files: string[]) => `(SELECT DISTINCT * FROM ${readList(files)})`
|
|
112
115
|
|
|
113
116
|
// ---- the preview ----
|
|
114
117
|
|
|
@@ -205,7 +208,7 @@ export async function runPreview(o: PreviewOptions): Promise<PreviewResult> {
|
|
|
205
208
|
try {
|
|
206
209
|
for (const s of slabs) { const f = `${uid('slab')}.parquet`; await engine.registerBuffer(f, s.buffer!); files.push(f) }
|
|
207
210
|
// DISTINCT: a coarse axis (the 8-day grid) can snap a chunk's two endpoints onto one step
|
|
208
|
-
const slab =
|
|
211
|
+
const slab = distinctSlab(files)
|
|
209
212
|
const out = await engine.runTemplate(name, { expr, slab, mask })
|
|
210
213
|
aborted(signal)
|
|
211
214
|
// two chunks snapped onto the same step of a coarse axis give that step twice, identical: keep the first
|
|
@@ -266,7 +269,7 @@ export function sliceSource(o: SliceSourceOptions): SliceSource {
|
|
|
266
269
|
try {
|
|
267
270
|
await inserted
|
|
268
271
|
aborted(signal)
|
|
269
|
-
const rows = await o.engine.runTemplate('last_step', { expr: valueExpr(o.variable), slab:
|
|
272
|
+
const rows = await o.engine.runTemplate('last_step', { expr: valueExpr(o.variable), slab: distinctSlab(files), mask })
|
|
270
273
|
return rows.map((r) => ({
|
|
271
274
|
lat: Number(r.latitude), lon: Number(r.longitude), weight: Number(r.weight),
|
|
272
275
|
value: r.value === null || r.value === undefined ? null : Number(r.value),
|