bruce-models 7.1.88 → 7.1.89

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.
@@ -0,0 +1,520 @@
1
+ import { Geometry } from "../common/geometry";
2
+ import { BruceApi } from "../api/bruce-api";
3
+ import { ClientFile } from "./client-file";
4
+ import type { ClientFileValueMap } from "./client-file-value-map";
5
+ import { ValueMapGrid } from "./value-map-grid";
6
+ /**
7
+ * Reads a generated value map: its frames, the values in them, and the shapes those values make.
8
+ */
9
+ export declare namespace ValueMapReader {
10
+ interface IRaster {
11
+ Width: number;
12
+ Height: number;
13
+ Data: Uint8Array | Uint8ClampedArray;
14
+ }
15
+ /**
16
+ * Turns one PNG's bytes into its pixels.
17
+ */
18
+ type TDecoder = (bytes: Uint8Array) => Promise<IRaster>;
19
+ /**
20
+ * Hands back a slice of the archive blob.
21
+ */
22
+ type TByteSource = (offset: number, length: number) => Promise<Uint8Array>;
23
+ interface IField {
24
+ Width: number;
25
+ Height: number;
26
+ Values: Float64Array | null;
27
+ Covered: Uint8Array;
28
+ }
29
+ interface IMask {
30
+ Width: number;
31
+ Height: number;
32
+ Bits: Uint8Array;
33
+ }
34
+ interface IReading {
35
+ Longitude: number;
36
+ Latitude: number;
37
+ Frame: number;
38
+ Time: string | null;
39
+ Units: string | null;
40
+ Texel: ValueMapGrid.ITexel | null;
41
+ Covered: boolean;
42
+ Value: number | null;
43
+ SourceValue: number | null;
44
+ }
45
+ interface IDetails extends IReading {
46
+ Attribute: string | null;
47
+ Label: string | null;
48
+ Dataset: string | null;
49
+ Frames: number;
50
+ Transform: string | null;
51
+ VerticalDatum: string | null;
52
+ Tile: {
53
+ Level: number;
54
+ TexelMetres: number;
55
+ ResolutionX: number;
56
+ ResolutionY: number;
57
+ West: number;
58
+ East: number;
59
+ South: number;
60
+ North: number;
61
+ };
62
+ TileTexel: ValueMapGrid.ITexel | null;
63
+ ValueMin: number | null;
64
+ ValueMax: number | null;
65
+ Shift: number | null;
66
+ Baseline: boolean;
67
+ }
68
+ interface ISummary {
69
+ Frame: number;
70
+ Time: string | null;
71
+ Units: string | null;
72
+ Texels: number;
73
+ Covered: number;
74
+ Peak: number | null;
75
+ Mean: number | null;
76
+ SourcePeak: number | null;
77
+ SourceMean: number | null;
78
+ }
79
+ interface IAdded {
80
+ Frame: number;
81
+ Time: string | null;
82
+ NewTexels: number;
83
+ Shapes: Geometry.IGeometry[];
84
+ New: IMask;
85
+ Cumulative: IMask;
86
+ }
87
+ const MIN_TEXELS = 8;
88
+ const SIMPLIFY_TOLERANCE = 0.25;
89
+ const ONSET_FRACTION = 0.5;
90
+ const LEVELS = 256;
91
+ const MAX_COMPOSITE_TEXELS = 2048;
92
+ const FRAME_CACHE = 16;
93
+ const TILE_CACHE = 32;
94
+ const MAX_READ_GAP = 131072;
95
+ /**
96
+ * One generated value map, read from its Client File.
97
+ *
98
+ * const map = await ClientFileValueMap.Open({ api, fileId });
99
+ * const frame = await map.Frame(0);
100
+ * for (const shape of await map.ShapesAbove({ threshold: 1.25 })) { ... }
101
+ *
102
+ * Every reading is in the archive's delivered units. Where a transform was applied, ask for the
103
+ * source values instead to get the customer's own numbers.
104
+ */
105
+ interface IReaderParams {
106
+ file: ClientFile.IFile;
107
+ bytes: TByteSource;
108
+ decoder?: TDecoder;
109
+ maxCompositeTexels?: number;
110
+ extent?: ClientFileValueMap.IExtent;
111
+ }
112
+ class Reader {
113
+ readonly File: ClientFile.IFile;
114
+ readonly Metadata: ClientFileValueMap.IMetadata;
115
+ readonly Tiles: ClientFileValueMap.IBinaryTile[];
116
+ readonly Grid: ValueMapGrid.Grid;
117
+ readonly Extent: ClientFileValueMap.IExtent;
118
+ private readonly decoder;
119
+ private readonly bytes;
120
+ private readonly frames;
121
+ private readonly tileLayers;
122
+ private readonly statistics;
123
+ private readonly thresholds;
124
+ private baseline;
125
+ private unchanging;
126
+ constructor(params: IReaderParams);
127
+ /**
128
+ * The attribute this value map was generated from.
129
+ */
130
+ get Attribute(): string | null;
131
+ /**
132
+ * What the attribute is called for a reader, where the source names it.
133
+ */
134
+ get Label(): string | null;
135
+ /**
136
+ * The dataset the values came from, since one account holds several over the same mesh.
137
+ */
138
+ get Dataset(): string | null;
139
+ /**
140
+ * The Entity Type Source this was generated from.
141
+ */
142
+ get EntityTypeSourceID(): number | null;
143
+ /**
144
+ * When the archive was written, which is what tells two generations of it apart.
145
+ */
146
+ get Generated(): string | null;
147
+ get Revision(): number | null;
148
+ /**
149
+ * The units a reading is in, where the source states them.
150
+ */
151
+ get Units(): string | null;
152
+ /**
153
+ * How a frame's number is packed: one channel or two.
154
+ */
155
+ get Format(): string;
156
+ /**
157
+ * The values a reading out of this value map falls between, in its own units.
158
+ */
159
+ get ValueRange(): {
160
+ Min: number;
161
+ Max: number;
162
+ };
163
+ /**
164
+ * The values the source's own numbers fall between, or null where nothing was transformed.
165
+ */
166
+ get SourceRange(): {
167
+ Min: number;
168
+ Max: number;
169
+ } | null;
170
+ /**
171
+ * What the source's own heights are measured from, when the archive says.
172
+ * A thickness declares none, and an untransformed elevation declares one with no transform.
173
+ */
174
+ get VerticalDatum(): string | null;
175
+ /**
176
+ * What was applied to the source's numbers to get the delivered ones, empty for nothing.
177
+ */
178
+ get Transform(): string;
179
+ /**
180
+ * Whether a reading differs from what the source's own data said.
181
+ */
182
+ get IsTransformed(): boolean;
183
+ /**
184
+ * What the source suggests a picture be ramped over, which is not a bound on the data.
185
+ */
186
+ get ColorBarRange(): {
187
+ Min: number;
188
+ Max: number;
189
+ } | null;
190
+ /**
191
+ * The largest movement any one texel made over the series.
192
+ */
193
+ get MovingRangeMax(): number | null;
194
+ /**
195
+ * How many timesteps the generator set out to write.
196
+ */
197
+ get RequestedFrames(): number;
198
+ /**
199
+ * How many it actually wrote.
200
+ */
201
+ get WrittenFrames(): number;
202
+ /**
203
+ * Whether the archive holds every timestep that was asked for.
204
+ */
205
+ get IsComplete(): boolean;
206
+ /**
207
+ * When each frame was sampled. Authoritative, unlike the series increment.
208
+ */
209
+ get Times(): string[];
210
+ /**
211
+ * How many frames the archive holds.
212
+ */
213
+ get Length(): number;
214
+ /**
215
+ * Says so when the archive's heights are not on the ellipsoid, or null when they are.
216
+ */
217
+ Warning(): string | null;
218
+ /**
219
+ * One layer's declaration, or undefined when the archive does not carry it.
220
+ */
221
+ Layer(name: string): ClientFileValueMap.ILayer | undefined;
222
+ /**
223
+ * One frame's values and a mask of which texels were sampled.
224
+ */
225
+ Frame(index?: number, source?: boolean): Promise<IField>;
226
+ /**
227
+ * Each texel's lowest value over the series and where that is known, or null.
228
+ */
229
+ ValueMin(): Promise<IField | null>;
230
+ /**
231
+ * Each texel's highest value over the series and where that is known, or null.
232
+ */
233
+ ValueMax(): Promise<IField | null>;
234
+ /**
235
+ * The per-texel correction applied to the source's own numbers, or null where none was.
236
+ *
237
+ * sourceValue = value - shift, which is what makes the transform reversible per texel rather
238
+ * than only describable in prose.
239
+ */
240
+ ValueShift(): Promise<IField | null>;
241
+ /**
242
+ * The texels flagged as permanently at their own minimum, or null when none were published.
243
+ *
244
+ * A caller measuring change subtracts these rather than reporting ground that never moved.
245
+ */
246
+ Baseline(): Promise<IMask | null>;
247
+ /**
248
+ * The texels holding one value for the whole series, or null for a single frame archive.
249
+ */
250
+ Unchanging(): Promise<IMask | null>;
251
+ /**
252
+ * Every texel a change in the series cannot be read from, or null when there are none.
253
+ *
254
+ * The published baseline and the texels measured as unchanging, since neither describes
255
+ * anything the series does and a caller asking what moved wants both gone.
256
+ */
257
+ Ignored(): Promise<IMask | null>;
258
+ /**
259
+ * The level the series itself separates on, for a caller who cannot name one.
260
+ */
261
+ NaturalThreshold(source?: boolean): Promise<number>;
262
+ /**
263
+ * The level to measure against, read off the series when the caller names none.
264
+ */
265
+ Resolve(threshold: number | null | undefined, source?: boolean): Promise<number>;
266
+ /**
267
+ * The texels in one frame whose value is over a threshold.
268
+ *
269
+ * Ask for source to compare against the customer's own numbers, so a level stated against
270
+ * their data means what they think it means.
271
+ */
272
+ MaskAbove(params?: {
273
+ threshold?: number;
274
+ frame?: number;
275
+ excludeBaseline?: boolean;
276
+ source?: boolean;
277
+ }): Promise<IMask>;
278
+ /**
279
+ * The texels over a threshold in every frame, or null for an archive with no frames.
280
+ *
281
+ * Measured rather than read off the first frame, so a tide that is out at the start does
282
+ * not get counted as ground the event flooded.
283
+ */
284
+ AlwaysAbove(params?: {
285
+ threshold?: number;
286
+ excludeBaseline?: boolean;
287
+ source?: boolean;
288
+ }): Promise<IMask | null>;
289
+ /**
290
+ * One frame's mask with anything below the noise floor already removed.
291
+ *
292
+ * Built from the components so the floor is applied once, which is what lets two frames be
293
+ * compared as sets that already agree on what counts.
294
+ */
295
+ CoveredMask(params?: {
296
+ threshold?: number;
297
+ frame?: number;
298
+ minTexels?: number;
299
+ excludeBaseline?: boolean;
300
+ source?: boolean;
301
+ }): Promise<IMask>;
302
+ /**
303
+ * How many texels are over the threshold in each frame.
304
+ *
305
+ * Decoding is local, so the whole series is read without a request and the frames worth
306
+ * querying can be found rather than guessed at.
307
+ */
308
+ Profile(params?: {
309
+ threshold?: number;
310
+ minTexels?: number;
311
+ excludeBaseline?: boolean;
312
+ source?: boolean;
313
+ }): Promise<number[]>;
314
+ /**
315
+ * The frames that characterise an event: it arriving, its worst, and it passing.
316
+ *
317
+ * Read off the series rather than named by the caller, since a frame number that suits one
318
+ * archive is quietly wrong for the next and finding the worst is usually the question.
319
+ */
320
+ FramesOfInterest(params?: {
321
+ threshold?: number;
322
+ fraction?: number;
323
+ excludeBaseline?: boolean;
324
+ source?: boolean;
325
+ }): Promise<number[]>;
326
+ /**
327
+ * Each area of one frame over a threshold, as a Bruce geometry ready to query with.
328
+ * Holes are dropped unless asked for.
329
+ */
330
+ ShapesAbove(params?: {
331
+ threshold?: number;
332
+ frame?: number;
333
+ minTexels?: number;
334
+ keepHoles?: boolean;
335
+ excludeBaseline?: boolean;
336
+ tolerance?: number;
337
+ source?: boolean;
338
+ }): Promise<Geometry.IGeometry[]>;
339
+ /**
340
+ * Each area of any mask as a Bruce geometry, for a caller who built the mask itself.
341
+ */
342
+ ShapesOf(mask: IMask, params?: {
343
+ minTexels?: number;
344
+ keepHoles?: boolean;
345
+ tolerance?: number;
346
+ }): Geometry.IGeometry[];
347
+ /**
348
+ * One area's outer ring and its holes, as positions.
349
+ *
350
+ * The longest ring is the outer one, since a hole is enclosed by what surrounds it. Pass a
351
+ * tolerance of 0 to keep every traced vertex.
352
+ */
353
+ RingsOf(members: ValueMapGrid.ITexel[], tolerance?: number): {
354
+ Outer: ValueMapGrid.IPoint[];
355
+ Holes: ValueMapGrid.IPoint[][];
356
+ };
357
+ /**
358
+ * Walks the series in order, reporting only the ground each frame adds.
359
+ * Most frames add nothing, so onProgress is called for every frame while only the ones that grew come back.
360
+ */
361
+ NewAreas(params?: {
362
+ threshold?: number;
363
+ minTexels?: number;
364
+ excludeBaseline?: boolean;
365
+ tolerance?: number;
366
+ source?: boolean;
367
+ onProgress?: (at: {
368
+ Frame: number;
369
+ Frames: number;
370
+ Time: string | null;
371
+ NewTexels: number;
372
+ Added: boolean;
373
+ }) => void;
374
+ }): Promise<IAdded[]>;
375
+ /**
376
+ * The texels an Entity covers, from where its record says it is.
377
+ *
378
+ * The raster does not move, so this holds for the whole series and a caller reading every
379
+ * frame works it out once.
380
+ *
381
+ * Ask for geometry to use the Entity's own outline rather than the box around it.
382
+ */
383
+ TexelsOf(entity: any, useGeometry?: boolean): ValueMapGrid.ITexel[];
384
+ /**
385
+ * Every value a frame holds over a set of texels, skipping the texels it never sampled.
386
+ *
387
+ * An unsampled texel decodes to the bottom of the archive's range, which reads as a real
388
+ * measurement rather than as an absence, so the coverage mask decides what is reported.
389
+ */
390
+ ReadingsAt(texels: ValueMapGrid.ITexel[], frame: IField): number[];
391
+ /**
392
+ * The highest value a frame holds over a set of texels, or null where it holds nothing.
393
+ *
394
+ * The highest rather than the middle one, because something spanning more than one texel is
395
+ * described by its worst part.
396
+ */
397
+ PeakAt(texels: ValueMapGrid.ITexel[], frame?: number, source?: boolean): Promise<number | null>;
398
+ /**
399
+ * The average value a frame holds over a set of texels, or null where it holds nothing.
400
+ * What something spanning several texels experienced overall, as against the worst part.
401
+ */
402
+ MeanAt(texels: ValueMapGrid.ITexel[], frame?: number, source?: boolean): Promise<number | null>;
403
+ /**
404
+ * How the values over a mask are spread, for a caller reporting on an area.
405
+ */
406
+ ValuesAt(mask: IMask, frame: IField): {
407
+ Texels: number;
408
+ Peak?: number;
409
+ Mean?: number;
410
+ Median?: number;
411
+ };
412
+ /**
413
+ * The finest tile covering a position, or null when it falls outside every one of them.
414
+ *
415
+ * Tiles overlap, and the finer one is the better answer, so the last match wins over a list
416
+ * that is already sorted coarse first.
417
+ */
418
+ TileAt(longitude: number, latitude: number): ClientFileValueMap.IBinaryTile | null;
419
+ /**
420
+ * One reading at one place, in both the delivered numbers and the source's own.
421
+ *
422
+ * Reads the single tile the position falls in rather than compositing the whole grid, which
423
+ * is what makes charting one point over a long series cheap.
424
+ */
425
+ SampleAt(longitude: number, latitude: number, frame?: number): Promise<IReading | null>;
426
+ /**
427
+ * Everything the archive knows about one place, for a caller inspecting a single point.
428
+ */
429
+ DetailsAt(longitude: number, latitude: number, frame?: number): Promise<IDetails | null>;
430
+ /**
431
+ * Every reading at one place over the whole series, in the order the times run.
432
+ */
433
+ SeriesAt(longitude: number, latitude: number): Promise<IReading[]>;
434
+ /**
435
+ * What one frame holds over an Entity, in both the delivered numbers and the source's own.
436
+ */
437
+ SampleOf(entity: any, frame?: number, useGeometry?: boolean): Promise<ISummary>;
438
+ /**
439
+ * What every frame holds over one Entity, for a caller charting a record through an event.
440
+ */
441
+ SeriesOf(entity: any, useGeometry?: boolean): Promise<ISummary[]>;
442
+ private identity;
443
+ private position;
444
+ private statistic;
445
+ private composite;
446
+ private paste;
447
+ private tileLayer;
448
+ private tileReading;
449
+ private tileFlag;
450
+ private tileSeries;
451
+ private decodeAll;
452
+ private packing;
453
+ private range;
454
+ private toSource;
455
+ private missingShift;
456
+ }
457
+ /**
458
+ * A value map read from a Client File.
459
+ */
460
+ interface IOpenParams {
461
+ api?: BruceApi.Api;
462
+ fileId?: string;
463
+ file?: ClientFile.IFile;
464
+ blob?: ArrayBuffer | Uint8Array;
465
+ bytes?: TByteSource;
466
+ decoder?: TDecoder;
467
+ maxCompositeTexels?: number;
468
+ extent?: ClientFileValueMap.IExtent;
469
+ }
470
+ function Open(params: IOpenParams): Promise<Reader>;
471
+ /**
472
+ * Where an archive's bytes come from: a blob already held, or ranged reads of the file's URL.
473
+ */
474
+ function SourceFor(file: ClientFile.IFile, blob?: ArrayBuffer | Uint8Array, api?: BruceApi.Api): TByteSource;
475
+ /**
476
+ * Decodes a PNG where the runtime has an image decoder of its own.
477
+ *
478
+ * A browser has one. Node does not, and rather than pull an image library into a client library
479
+ * that mostly does not decode anything, a caller there passes their own.
480
+ */
481
+ const DefaultDecoder: TDecoder;
482
+ const MIN_RING_POINTS = 4;
483
+ /**
484
+ * The disconnected areas in a mask, as 4-connected groups of texels.
485
+ */
486
+ function Components(mask: IMask, minTexels?: number): ValueMapGrid.ITexel[][];
487
+ /**
488
+ * The closed rings bounding a group of texels, in texel corner coordinates.
489
+ */
490
+ function Trace(members: ValueMapGrid.ITexel[]): {
491
+ X: number;
492
+ Y: number;
493
+ }[][];
494
+ /**
495
+ * A ring with its texel staircase reduced, by Ramer-Douglas-Peucker.
496
+ */
497
+ function Simplify(ring: {
498
+ X: number;
499
+ Y: number;
500
+ }[], tolerance: number): {
501
+ X: number;
502
+ Y: number;
503
+ }[];
504
+ /**
505
+ * How many texels a mask holds.
506
+ */
507
+ function Count(mask: IMask): number;
508
+ /**
509
+ * Two masks merged texel by texel.
510
+ */
511
+ function Combine(left: IMask, right: IMask, rule: (a: boolean, b: boolean) => boolean): IMask;
512
+ /**
513
+ * A polygon geometry from an outer ring and its holes, ready to query Bruce with.
514
+ */
515
+ function Polygon(outer: ValueMapGrid.IPoint[], holes: ValueMapGrid.IPoint[][]): Geometry.IGeometry;
516
+ /**
517
+ * An Entity's polygon rings, or nothing when its record carries no outline.
518
+ */
519
+ function RingsOfEntity(entity: any): ValueMapGrid.IPoint[][];
520
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bruce-models",
3
- "version": "7.1.88",
3
+ "version": "7.1.89",
4
4
  "description": "",
5
5
  "keywords": [],
6
6
  "main": "dist/bruce-models.umd.js",