@mailwoman/soil 9.4.0 → 10.1.0
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/README.md +118 -116
- package/lib/index.ts +66 -98
- package/lib/paths.ts +24 -0
- package/lib/schema.ts +188 -120
- package/lib/vocabulary.ts +40 -107
- package/out/index.d.ts +52 -70
- package/out/index.d.ts.map +1 -1
- package/out/index.js +24 -72
- package/out/index.js.map +1 -1
- package/out/paths.d.ts +19 -0
- package/out/paths.d.ts.map +1 -0
- package/out/paths.js +21 -0
- package/out/paths.js.map +1 -0
- package/out/schema.d.ts +187 -119
- package/out/schema.d.ts.map +1 -1
- package/out/schema.js +31 -31
- package/out/schema.js.map +1 -1
- package/out/sdk/acquire.d.ts +15 -24
- package/out/sdk/acquire.d.ts.map +1 -1
- package/out/sdk/acquire.js +5 -20
- package/out/sdk/acquire.js.map +1 -1
- package/out/sdk/build-soil.d.ts +67 -70
- package/out/sdk/build-soil.d.ts.map +1 -1
- package/out/sdk/build-soil.js +65 -95
- package/out/sdk/build-soil.js.map +1 -1
- package/out/sdk/cell-tiers.d.ts +7 -19
- package/out/sdk/cell-tiers.d.ts.map +1 -1
- package/out/sdk/cell-tiers.js +19 -38
- package/out/sdk/cell-tiers.js.map +1 -1
- package/out/sdk/cells.d.ts +15 -41
- package/out/sdk/cells.d.ts.map +1 -1
- package/out/sdk/cells.js +11 -38
- package/out/sdk/cells.js.map +1 -1
- package/out/sdk/client.d.ts +23 -48
- package/out/sdk/client.d.ts.map +1 -1
- package/out/sdk/client.js +19 -63
- package/out/sdk/client.js.map +1 -1
- package/out/sdk/download.d.ts +24 -47
- package/out/sdk/download.d.ts.map +1 -1
- package/out/sdk/download.js +14 -54
- package/out/sdk/download.js.map +1 -1
- package/out/sdk/ingest/chunk.d.ts +77 -0
- package/out/sdk/ingest/chunk.d.ts.map +1 -0
- package/out/sdk/{ingest-chunk.js → ingest/chunk.js} +19 -17
- package/out/sdk/ingest/chunk.js.map +1 -0
- package/out/sdk/ingest/worker.d.ts +9 -0
- package/out/sdk/ingest/worker.d.ts.map +1 -0
- package/out/{scripts/ingest-chunk.js → sdk/ingest/worker.js} +11 -10
- package/out/sdk/ingest/worker.js.map +1 -0
- package/out/sdk/ingest.d.ts +40 -52
- package/out/sdk/ingest.d.ts.map +1 -1
- package/out/sdk/ingest.js +18 -61
- package/out/sdk/ingest.js.map +1 -1
- package/out/sdk/measure-resolutions.d.ts +5 -16
- package/out/sdk/measure-resolutions.d.ts.map +1 -1
- package/out/sdk/measure-resolutions.js +3 -15
- package/out/sdk/measure-resolutions.js.map +1 -1
- package/out/sdk/reduce.d.ts +33 -59
- package/out/sdk/reduce.d.ts.map +1 -1
- package/out/sdk/reduce.js +47 -78
- package/out/sdk/reduce.js.map +1 -1
- package/out/sdk/survey-area.d.ts +16 -48
- package/out/sdk/survey-area.d.ts.map +1 -1
- package/out/sdk/survey-area.js +33 -77
- package/out/sdk/survey-area.js.map +1 -1
- package/out/sdk/tabular.d.ts +32 -31
- package/out/sdk/tabular.d.ts.map +1 -1
- package/out/sdk/tabular.js +58 -56
- package/out/sdk/tabular.js.map +1 -1
- package/out/sdk/test-kit.d.ts +57 -0
- package/out/sdk/test-kit.d.ts.map +1 -0
- package/out/{test-kit.js → sdk/test-kit.js} +18 -39
- package/out/sdk/test-kit.js.map +1 -0
- package/out/sdk/verify.d.ts +15 -51
- package/out/sdk/verify.d.ts.map +1 -1
- package/out/sdk/verify.js +19 -77
- package/out/sdk/verify.js.map +1 -1
- package/out/vocabulary.d.ts +37 -103
- package/out/vocabulary.d.ts.map +1 -1
- package/out/vocabulary.js +34 -107
- package/out/vocabulary.js.map +1 -1
- package/package.json +36 -190
- package/{lib/sdk → sdk}/acquire.ts +17 -27
- package/{lib/sdk → sdk}/build-soil.ts +114 -128
- package/{lib/sdk → sdk}/cell-tiers.ts +20 -39
- package/{lib/sdk → sdk}/cells.ts +17 -43
- package/sdk/client.ts +147 -0
- package/sdk/download.ts +131 -0
- package/{lib/sdk/ingest-chunk.ts → sdk/ingest/chunk.ts} +34 -26
- package/{lib/scripts/ingest-chunk.ts → sdk/ingest/worker.ts} +10 -9
- package/sdk/ingest.ts +253 -0
- package/{lib/sdk → sdk}/measure-resolutions.ts +5 -16
- package/sdk/reduce.ts +344 -0
- package/{lib/sdk → sdk}/survey-area.ts +39 -83
- package/{lib/sdk → sdk}/tabular.ts +62 -59
- package/{lib → sdk}/test-kit.ts +18 -40
- package/{lib/sdk → sdk}/verify.ts +29 -85
- package/lib/sdk/client.ts +0 -184
- package/lib/sdk/download.ts +0 -161
- package/lib/sdk/index.ts +0 -20
- package/lib/sdk/ingest.ts +0 -278
- package/lib/sdk/reduce.ts +0 -375
- package/out/scripts/ingest-chunk.d.ts +0 -11
- package/out/scripts/ingest-chunk.d.ts.map +0 -1
- package/out/scripts/ingest-chunk.js.map +0 -1
- package/out/sdk/index.d.ts +0 -20
- package/out/sdk/index.d.ts.map +0 -1
- package/out/sdk/index.js +0 -20
- package/out/sdk/index.js.map +0 -1
- package/out/sdk/ingest-chunk.d.ts +0 -73
- package/out/sdk/ingest-chunk.d.ts.map +0 -1
- package/out/sdk/ingest-chunk.js.map +0 -1
- package/out/test-kit.d.ts +0 -79
- package/out/test-kit.d.ts.map +0 -1
- package/out/test-kit.js.map +0 -1
package/out/sdk/ingest.js
CHANGED
|
@@ -2,68 +2,34 @@
|
|
|
2
2
|
* @copyright Sister Software
|
|
3
3
|
* @license AGPL-3.0
|
|
4
4
|
* @author Teffen Ellis, et al.
|
|
5
|
-
*
|
|
6
|
-
* Read a survey area's published shapefiles as a stream of WGS84 delineations, through ogr2ogr.
|
|
7
|
-
*
|
|
8
|
-
* OGR IS BUILD TOOLING, NEVER A SERVE DEPENDENCY (SCOPE invariant 6). It converts the authority's geometry
|
|
9
|
-
* into the structure the runtime probes, and nothing downstream of this module knows GDAL exists.
|
|
10
|
-
*
|
|
11
|
-
* THE SOURCE IS ALREADY IN WGS84, AND CHECKING IT IS STILL THE CHECK. Each `.prj` is an ESRI WKT reading
|
|
12
|
-
* `GEOGCS["GCS_WGS_1984",…]`, which GDAL resolves to EPSG:4326 — so no reprojection is needed before H3.
|
|
13
|
-
* The authority code is asserted anyway before a single feature is read, and the reprojected stream is
|
|
14
|
-
* asserted against the layer's own declared extent, which is the check that catches a coordinate-order
|
|
15
|
-
* mistake the projection check cannot see.
|
|
16
|
-
*
|
|
17
|
-
* THE DATUM GUARD RUNS EVEN THOUGH THE ANSWER IS THE IDENTITY, AND THAT IS THE POINT. PROJ substitutes a
|
|
18
|
-
* ballpark datum shift SILENTLY when the accurate grid is missing — measured on the flood layer at 3.4 m
|
|
19
|
-
* over an entire country, visible only as eight disagreements out of 59 against the authority's own
|
|
20
|
-
* service. For an EPSG:4326 source `projinfo` answers `Null geographic offset from WGS 84 to WGS 84, 0 m,
|
|
21
|
-
* World.` and the guard passes in one process. Skipping it on the reasoning that this source needs no
|
|
22
|
-
* shift is how the guard comes to be missing on the day a source arrives that does.
|
|
23
|
-
*
|
|
24
|
-
* THE ID IS THE SHAPEFILE'S OWN FID, AND IT HAS TO BE, because SSURGO publishes no per-delineation key:
|
|
25
|
-
* `MUKEY` names the MAP UNIT and one map unit has many delineations — `IA153` holds 17,966 delineations
|
|
26
|
-
* across 152 map units. So `area_id` is `<areasymbol>:<fid>`, which is stable across runs and is what makes
|
|
27
|
-
* a bounded chunk name the same features every time.
|
|
28
5
|
*/
|
|
29
6
|
import { declaredFeatureCount } from "@mailwoman/core/layers";
|
|
30
7
|
import { assertRingsInsideExtent, requireArealPolygons } from "@mailwoman/spatial";
|
|
31
8
|
import { readOGRLayerIdentity } from "@mailwoman/spatial/tools/ogr";
|
|
32
|
-
import { ogr2ogrGeoJSONSeq } from "@mailwoman/spatial/tools/ogr
|
|
33
|
-
import { basename,
|
|
9
|
+
import { ogr2ogrGeoJSONSeq } from "@mailwoman/spatial/tools/ogr/stream";
|
|
10
|
+
import { basename, PathBuilder } from "path-ts";
|
|
34
11
|
import { SSURGO_SOURCE_EPSG } from "#vocabulary";
|
|
35
|
-
/**
|
|
36
|
-
* Coordinate decimals ogr2ogr writes into the stream. Nine is well past the source's own precision — the metadata
|
|
37
|
-
* states compilation to base maps meeting National Map Accuracy Standards at 1 inch = 1,000 feet — and is chosen so the
|
|
38
|
-
* round trip contributes nothing measurable to the area cross-check.
|
|
39
|
-
*/
|
|
40
12
|
const COORDINATE_PRECISION = 9;
|
|
41
|
-
/**
|
|
42
|
-
* How far outside the layer's declared extent a vertex may fall before the ingest refuses.
|
|
43
|
-
*
|
|
44
|
-
* A tenth of a degree is about 11 km — small enough that an unprojected or axis-swapped read, which lands whole
|
|
45
|
-
* hemispheres away, still fails, and loose enough that a rounded declared extent is not brittle.
|
|
46
|
-
*/
|
|
47
13
|
const BBOX_MARGIN_DEGREES = 0.1;
|
|
48
14
|
/**
|
|
49
|
-
*
|
|
15
|
+
* Returns the path of the shapefile that holds a survey area's map-unit polygons.
|
|
50
16
|
*/
|
|
51
17
|
export function mapUnitShapefile(spatialDirectory, areaSymbol) {
|
|
52
|
-
return
|
|
18
|
+
return PathBuilder.from(spatialDirectory)(`soilmu_a_${areaSymbol.toLowerCase()}.shp`).toString();
|
|
53
19
|
}
|
|
54
20
|
/**
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
21
|
+
* Returns the path of the shapefile holding a survey area's outline.
|
|
22
|
+
*
|
|
23
|
+
* The build takes the footprint from this outline because unrated map units such as `notcom` lie inside it.
|
|
24
|
+
* A union of rated polygons would leave them out.
|
|
58
25
|
*/
|
|
59
26
|
export function surveyAreaShapefile(spatialDirectory, areaSymbol) {
|
|
60
|
-
return
|
|
27
|
+
return PathBuilder.from(spatialDirectory)(`soilsa_a_${areaSymbol.toLowerCase()}.shp`);
|
|
61
28
|
}
|
|
62
29
|
/**
|
|
63
|
-
*
|
|
30
|
+
* Reads the projection, feature count, layer name and extent that a shapefile declares.
|
|
64
31
|
*
|
|
65
|
-
*
|
|
66
|
-
* reports no feature count.
|
|
32
|
+
* It throws when the shapefile declares a projection other than `expectEPSG`.
|
|
67
33
|
*/
|
|
68
34
|
export async function readSoilSourceIdentity(options) {
|
|
69
35
|
const identity = await readOGRLayerIdentity({
|
|
@@ -79,9 +45,6 @@ export async function readSoilSourceIdentity(options) {
|
|
|
79
45
|
});
|
|
80
46
|
return { epsg: identity.epsg, featureCount: identity.featureCount, layer: identity.layer, bbox: identity.extent };
|
|
81
47
|
}
|
|
82
|
-
/**
|
|
83
|
-
* The ingest's `SELECT`, with the FID range applied when one is asked for.
|
|
84
|
-
*/
|
|
85
48
|
function delineationSelectSQL(layer, options) {
|
|
86
49
|
const select = `SELECT FID AS fid, MUKEY AS mukey, AREASYMBOL AS areasymbol FROM "${layer}"`;
|
|
87
50
|
const bounds = [];
|
|
@@ -94,13 +57,12 @@ function delineationSelectSQL(layer, options) {
|
|
|
94
57
|
return bounds.length ? `${select} WHERE ${bounds.join(" AND ")}` : select;
|
|
95
58
|
}
|
|
96
59
|
/**
|
|
97
|
-
*
|
|
60
|
+
* Streams a shapefile's map-unit delineations reprojected to WGS84.
|
|
98
61
|
*
|
|
99
|
-
*
|
|
100
|
-
*
|
|
62
|
+
* It throws when a feature lacks geometry or `mukey`.
|
|
63
|
+
* It also throws when a vertex falls outside the declared extent.
|
|
101
64
|
*
|
|
102
|
-
*
|
|
103
|
-
* the declared extent.
|
|
65
|
+
* The extent check catches swapped coordinate axes that the projection check misses.
|
|
104
66
|
*/
|
|
105
67
|
export async function* readSoilDelineations(options) {
|
|
106
68
|
const layer = options.layer ?? basename(options.shapefilePath, ".shp");
|
|
@@ -109,8 +71,6 @@ export async function* readSoilDelineations(options) {
|
|
|
109
71
|
"-f",
|
|
110
72
|
"GeoJSONSeq",
|
|
111
73
|
"/vsistdout/",
|
|
112
|
-
// The OUTPUT projection. `expectEPSG` is the assertion `readSoilSourceIdentity` makes about the SOURCE and is not
|
|
113
|
-
// the same thing: the consumer reads WGS84, whatever the shapefile declares.
|
|
114
74
|
"-t_srs",
|
|
115
75
|
"EPSG:4326",
|
|
116
76
|
"-lco",
|
|
@@ -124,9 +84,6 @@ export async function* readSoilDelineations(options) {
|
|
|
124
84
|
yield toDelineation(raw, { minLon, minLat, maxLon, maxLat });
|
|
125
85
|
}
|
|
126
86
|
}
|
|
127
|
-
/**
|
|
128
|
-
* Validate one raw GeoJSON feature and narrow it. Split out so the generator body stays a loop.
|
|
129
|
-
*/
|
|
130
87
|
function toDelineation(raw, extent) {
|
|
131
88
|
const { properties, geometry } = raw;
|
|
132
89
|
if (!geometry) {
|
|
@@ -148,14 +105,14 @@ function toDelineation(raw, extent) {
|
|
|
148
105
|
};
|
|
149
106
|
}
|
|
150
107
|
/**
|
|
151
|
-
*
|
|
108
|
+
* Creates a {@link SoilFeatureSource} for one survey area's shapefile.
|
|
109
|
+
*
|
|
110
|
+
* It reads the shapefile's identity immediately and streams features when asked.
|
|
152
111
|
*/
|
|
153
112
|
export async function createShapefileFeatureSource(options) {
|
|
154
113
|
const identity = await readSoilSourceIdentity(options);
|
|
155
114
|
return {
|
|
156
115
|
areaSymbol: options.areaSymbol,
|
|
157
|
-
// A RANGE's own count is supplied by the caller, because `ogrinfo` reports the layer's total and nothing narrower.
|
|
158
|
-
// The whole-file total is still checked: the builder sums what its chunks streamed and compares that.
|
|
159
116
|
declaredFeatureCount: declaredFeatureCount({
|
|
160
117
|
declared: options.declaredFeatureCount,
|
|
161
118
|
limit: options.limit,
|
package/out/sdk/ingest.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ingest.js","sourceRoot":"","sources":["../../
|
|
1
|
+
{"version":3,"file":"ingest.js","sourceRoot":"","sources":["../../sdk/ingest.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,19 +2,6 @@
|
|
|
2
2
|
* @copyright Sister Software
|
|
3
3
|
* @license AGPL-3.0
|
|
4
4
|
* @author Teffen Ellis, et al.
|
|
5
|
-
*
|
|
6
|
-
* The index resolution is a MEASUREMENT this layer takes, not a number argued to.
|
|
7
|
-
*
|
|
8
|
-
* ONE STREAM, EVERY RESOLUTION. Re-reading a survey area's shapefile per candidate buys nothing — the
|
|
9
|
-
* classification is per delineation, so every candidate index folds the same delineation in turn. The cost
|
|
10
|
-
* is memory: each resolution holds its own cell sets, and the finest candidate dominates.
|
|
11
|
-
*
|
|
12
|
-
* THIS INSTRUMENT REPORTS THE FIRST OF THE TWO NUMBERS §4.7 NAMES — the `partial` cell share, plus the mean
|
|
13
|
-
* delineations per cell that drives it. The SECOND number, the share of cells whose top class holds less
|
|
14
|
-
* than half the cell, is not measurable here: it needs the attribute join and the area weighting, which
|
|
15
|
-
* are the build. So it comes off the SHIPPING ARTIFACT instead — {@linkcode buildSoilDatabase} counts it
|
|
16
|
-
* while it writes the rows, and the build receipt reports it. That is the flood layer's lesson applied:
|
|
17
|
-
* the number that describes the artifact is the one taken from the artifact.
|
|
18
5
|
*/
|
|
19
6
|
import type { ResolutionMeasurementOptions } from "@mailwoman/core/layers";
|
|
20
7
|
import { type SoilCellIndexMeasurement } from "#sdk/cells";
|
|
@@ -24,7 +11,8 @@ export interface MeasureSoilResolutionsOptions extends SoilIngestOptions, Resolu
|
|
|
24
11
|
export interface SoilResolutionReport {
|
|
25
12
|
delineations: number;
|
|
26
13
|
/**
|
|
27
|
-
* The count the shapefile declares for itself.
|
|
14
|
+
* The count the shapefile declares for itself.
|
|
15
|
+
* A streamed total that differs read a truncated file.
|
|
28
16
|
*/
|
|
29
17
|
declaredFeatureCount: number;
|
|
30
18
|
measurements: SoilCellIndexMeasurement[];
|
|
@@ -32,8 +20,9 @@ export interface SoilResolutionReport {
|
|
|
32
20
|
/**
|
|
33
21
|
* Measure every candidate resolution over one survey area's real delineations.
|
|
34
22
|
*
|
|
35
|
-
* @throws {Error} When the streamed count does not match the count the shapefile declares.
|
|
36
|
-
*
|
|
23
|
+
* @throws {Error} When the streamed count does not match the count the shapefile declares.
|
|
24
|
+
* A short read produces a well-formed table describing a smaller county.
|
|
25
|
+
* which is the partial result that must throw.
|
|
37
26
|
*/
|
|
38
27
|
export declare function measureSoilCellResolutions(options: MeasureSoilResolutionsOptions): Promise<SoilResolutionReport>;
|
|
39
28
|
//# sourceMappingURL=measure-resolutions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"measure-resolutions.d.ts","sourceRoot":"","sources":["../../
|
|
1
|
+
{"version":3,"file":"measure-resolutions.d.ts","sourceRoot":"","sources":["../../sdk/measure-resolutions.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,wBAAwB,CAAA;AAE1E,OAAO,EAA2C,KAAK,wBAAwB,EAAE,MAAM,YAAY,CAAA;AACnG,OAAO,EAAgD,KAAK,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAElG,MAAM,WAAW,6BAA8B,SAAQ,iBAAiB,EAAE,4BAA4B;CAAG;AAEzG,MAAM,WAAW,oBAAoB;IACpC,YAAY,EAAE,MAAM,CAAA;IACpB;;;OAGG;IACH,oBAAoB,EAAE,MAAM,CAAA;IAC5B,YAAY,EAAE,wBAAwB,EAAE,CAAA;CACxC;AAID;;;;;;GAMG;AACH,wBAAsB,0BAA0B,CAC/C,OAAO,EAAE,6BAA6B,GACpC,OAAO,CAAC,oBAAoB,CAAC,CAmC/B"}
|
|
@@ -2,19 +2,6 @@
|
|
|
2
2
|
* @copyright Sister Software
|
|
3
3
|
* @license AGPL-3.0
|
|
4
4
|
* @author Teffen Ellis, et al.
|
|
5
|
-
*
|
|
6
|
-
* The index resolution is a MEASUREMENT this layer takes, not a number argued to.
|
|
7
|
-
*
|
|
8
|
-
* ONE STREAM, EVERY RESOLUTION. Re-reading a survey area's shapefile per candidate buys nothing — the
|
|
9
|
-
* classification is per delineation, so every candidate index folds the same delineation in turn. The cost
|
|
10
|
-
* is memory: each resolution holds its own cell sets, and the finest candidate dominates.
|
|
11
|
-
*
|
|
12
|
-
* THIS INSTRUMENT REPORTS THE FIRST OF THE TWO NUMBERS §4.7 NAMES — the `partial` cell share, plus the mean
|
|
13
|
-
* delineations per cell that drives it. The SECOND number, the share of cells whose top class holds less
|
|
14
|
-
* than half the cell, is not measurable here: it needs the attribute join and the area weighting, which
|
|
15
|
-
* are the build. So it comes off the SHIPPING ARTIFACT instead — {@linkcode buildSoilDatabase} counts it
|
|
16
|
-
* while it writes the rows, and the build receipt reports it. That is the flood layer's lesson applied:
|
|
17
|
-
* the number that describes the artifact is the one taken from the artifact.
|
|
18
5
|
*/
|
|
19
6
|
import { classifyDelineationCells, SoilCellIndex } from "#sdk/cells";
|
|
20
7
|
import { readSoilDelineations, readSoilSourceIdentity } from "#sdk/ingest";
|
|
@@ -22,8 +9,9 @@ const DEFAULT_PROGRESS_EVERY = 5000;
|
|
|
22
9
|
/**
|
|
23
10
|
* Measure every candidate resolution over one survey area's real delineations.
|
|
24
11
|
*
|
|
25
|
-
* @throws {Error} When the streamed count does not match the count the shapefile declares.
|
|
26
|
-
*
|
|
12
|
+
* @throws {Error} When the streamed count does not match the count the shapefile declares.
|
|
13
|
+
* A short read produces a well-formed table describing a smaller county.
|
|
14
|
+
* which is the partial result that must throw.
|
|
27
15
|
*/
|
|
28
16
|
export async function measureSoilCellResolutions(options) {
|
|
29
17
|
const identity = await readSoilSourceIdentity(options);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"measure-resolutions.js","sourceRoot":"","sources":["../../
|
|
1
|
+
{"version":3,"file":"measure-resolutions.js","sourceRoot":"","sources":["../../sdk/measure-resolutions.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,EAAE,wBAAwB,EAAE,aAAa,EAAiC,MAAM,YAAY,CAAA;AACnG,OAAO,EAAE,oBAAoB,EAAE,sBAAsB,EAA0B,MAAM,aAAa,CAAA;AAclG,MAAM,sBAAsB,GAAG,IAAI,CAAA;AAEnC;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAC/C,OAAsC;IAEtC,MAAM,QAAQ,GAAG,MAAM,sBAAsB,CAAC,OAAO,CAAC,CAAA;IACtD,MAAM,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,IAAI,aAAa,CAAC,UAAU,CAAC,CAAC,CAAA;IACtF,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,sBAAsB,CAAA;IAErE,IAAI,YAAY,GAAG,CAAC,CAAA;IAEpB,IAAI,KAAK,EAAE,MAAM,WAAW,IAAI,oBAAoB,CAAC,EAAE,GAAG,OAAO,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;QAC3F,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC7B,KAAK,CAAC,GAAG,CACR,WAAW,CAAC,MAAM,EAClB,wBAAwB,CAAC,WAAW,CAAC,QAAQ,EAAE,KAAK,CAAC,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,CACpF,CAAA;QACF,CAAC;QAED,YAAY,EAAE,CAAA;QAEd,IAAI,YAAY,GAAG,aAAa,KAAK,CAAC,EAAE,CAAC;YACxC,OAAO,CAAC,UAAU,EAAE,CAAC,GAAG,YAAY,CAAC,cAAc,EAAE,0BAA0B,CAAC,CAAA;QACjF,CAAC;IACF,CAAC;IAED,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,IAAI,QAAQ,CAAC,YAAY,CAAA;IAEvD,IAAI,YAAY,KAAK,QAAQ,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CACd,0BAA0B,YAAY,yCAAyC,QAAQ,mEAAmE,CAC1J,CAAA;IACF,CAAC;IAED,OAAO;QACN,YAAY;QACZ,oBAAoB,EAAE,QAAQ,CAAC,YAAY;QAC3C,YAAY,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;KACpD,CAAA;AACF,CAAC"}
|
package/out/sdk/reduce.d.ts
CHANGED
|
@@ -3,59 +3,35 @@
|
|
|
3
3
|
* @license AGPL-3.0
|
|
4
4
|
* @author Teffen Ellis, et al.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
6
|
+
* Reduces the delineations that reach a cell into that cell's capability-class distribution.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* complexes, associations or undifferentiated groups, which is NRCS stating that the soils are
|
|
13
|
-
* intermingled and cannot be separated at the mapping scale. A winner class would satisfy the result-level
|
|
14
|
-
* consumer and starve the signal consumer, which needs a magnitude to vary over.
|
|
15
|
-
*
|
|
16
|
-
* THE WEIGHT IS A UNIFORM-AREA LATTICE OVER THE CELL, AND THE GRAIN IS CHOSEN AGAINST THE AUTHORITY'S OWN.
|
|
17
|
-
* A cell's children at {@link WEIGHT_LATTICE_DEPTH} levels finer have equal area by construction, so
|
|
18
|
-
* counting which delineation covers each child centre estimates covered area without a polygon clip. At
|
|
19
|
-
* depth 2 that is 49 children — 2.04% per child, which is the finest share NRCS's own
|
|
20
|
-
* `muaggatt.niccdcdpct` ever reports (observed minimum: 2%). Resolving finer than the authority publishes
|
|
21
|
-
* would be precision this layer cannot source.
|
|
22
|
-
*
|
|
23
|
-
* A WHOLE CELL SKIPS THE LATTICE ENTIRELY, and that is exact rather than an optimization: a cell lying
|
|
24
|
-
* wholly inside one delineation is covered by that delineation and by nothing else, so its distribution is
|
|
25
|
-
* that map unit's component split and its `mapped_share` is 1.
|
|
26
|
-
*
|
|
27
|
-
* `mapped_share` EXISTS BECAUSE A SURVEY-AREA EDGE CELL IS PARTLY OUTSIDE EVERY DELINEATION. Without it,
|
|
28
|
-
* the unmapped remainder would silently deflate every class share — an absence represented as a small
|
|
29
|
-
* number, which is the one thing this schema exists to prevent. The five shares are normalized over the
|
|
30
|
-
* mapped part, so they sum to 1 exactly, and `mapped_share` says how much of the cell that was.
|
|
31
|
-
*
|
|
32
|
-
* CLASS 8 IS A CLASS SHARE, NOT AN ABSENCE. It is a determination — the survey looked and rated the land
|
|
33
|
-
* as precluding commercial plant production, and 67,547 national components carry it. Folding it in with
|
|
34
|
-
* `NOTCOM`, a water body and an unrated series would produce a well-formed wrong answer, and separating
|
|
35
|
-
* the four absences from the one positive negative is the whole reason this table has five columns rather
|
|
36
|
-
* than one.
|
|
8
|
+
* The result is a distribution because most map units mix several soil components.
|
|
9
|
+
* The survey cannot separate those components at its mapping scale. Shares are normalized over the mapped part of the cell.
|
|
10
|
+
* `mapped_share` records how large that part is. Capability class 8 is a rated class, so it is stored as a
|
|
11
|
+
* class share. The unrated share, the no-data share and the not-rateable share each have their own column.
|
|
37
12
|
*/
|
|
38
13
|
import { type H3Cell } from "@mailwoman/spatial";
|
|
39
14
|
import type { SoilCapabilityCellTable, SoilComponentTable, SoilMapUnitTable } from "#schema";
|
|
40
15
|
/**
|
|
41
|
-
*
|
|
16
|
+
* The number of H3 levels below the index resolution at which the weighting lattice samples.
|
|
17
|
+
*
|
|
18
|
+
* Children at a finer resolution have equal area, so counting which delineation
|
|
19
|
+
* covers each child center estimates the covered area.
|
|
20
|
+
* A depth of 2 gives 49 children, or about 2% per child.
|
|
42
21
|
*
|
|
43
|
-
*
|
|
44
|
-
* authority itself publishes — `muaggatt.niccdcdpct`'s observed minimum is 2% — because a lattice finer than the
|
|
45
|
-
* source's own reporting grain buys precision this layer cannot source, at 7× the cost per level.
|
|
22
|
+
* NRCS publishes component shares no finer than 2%, and each extra level costs seven times as much.
|
|
46
23
|
*/
|
|
47
24
|
export declare const WEIGHT_LATTICE_DEPTH = 2;
|
|
48
25
|
/**
|
|
49
|
-
*
|
|
26
|
+
* The class share below which a class is added to `other_share` instead of stored.
|
|
50
27
|
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
* why the remainder is stored explicitly and the shares still sum to 1.
|
|
28
|
+
* The floor is below the lattice's 2% step, so it only removes the small shares
|
|
29
|
+
* that minor components contribute.
|
|
30
|
+
* The reducer adds them to `other_share` so all shares sum to 1.
|
|
55
31
|
*/
|
|
56
32
|
export declare const CLASS_SHARE_FLOOR = 0.01;
|
|
57
33
|
/**
|
|
58
|
-
* One delineation
|
|
34
|
+
* One delineation that reaches a cell.
|
|
59
35
|
*/
|
|
60
36
|
export interface CellCandidate {
|
|
61
37
|
areaID: string;
|
|
@@ -68,11 +44,12 @@ export interface CellCandidate {
|
|
|
68
44
|
rings: Uint8Array;
|
|
69
45
|
}
|
|
70
46
|
/**
|
|
71
|
-
*
|
|
47
|
+
* The shares that a map unit contributes per unit of area.
|
|
72
48
|
*/
|
|
73
49
|
export interface MapUnitProfile {
|
|
74
50
|
/**
|
|
75
|
-
*
|
|
51
|
+
* Each class code's share of the map unit.
|
|
52
|
+
* These shares and the three absence shares sum to 1.
|
|
76
53
|
*/
|
|
77
54
|
classShares: ReadonlyMap<string, number>;
|
|
78
55
|
unrated: number;
|
|
@@ -80,43 +57,40 @@ export interface MapUnitProfile {
|
|
|
80
57
|
noData: number;
|
|
81
58
|
}
|
|
82
59
|
/**
|
|
83
|
-
*
|
|
60
|
+
* Builds the profile of one map unit from its components.
|
|
84
61
|
*
|
|
85
|
-
* A `no_mapping` map unit contributes
|
|
86
|
-
* no soil mapping behind it, and reading it as a low class would be the reassuring wrong number §3.2 of the survey is
|
|
87
|
-
* about.
|
|
62
|
+
* A `no_mapping` map unit contributes only to `noData`, because it has no soil mapping.
|
|
88
63
|
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
* 100, and a national build must not depend on that holding everywhere.
|
|
64
|
+
* Components are weighted by `comppct_r`, the component's representative percentage of its map unit.
|
|
65
|
+
* The weights are divided by their actual total, because the percentages may not sum to 100.
|
|
92
66
|
*/
|
|
93
67
|
export declare function mapUnitProfile(mapUnit: Pick<SoilMapUnitTable, "no_mapping">, components: ReadonlyArray<Pick<SoilComponentTable, "comppct_r" | "compkind" | "nirrcapcl">>): MapUnitProfile;
|
|
94
68
|
/**
|
|
95
|
-
*
|
|
69
|
+
* The stored row for one cell, plus diagnostics for the build report.
|
|
96
70
|
*/
|
|
97
71
|
export interface ReducedCell {
|
|
98
72
|
row: SoilCapabilityCellTable;
|
|
99
73
|
/**
|
|
100
|
-
*
|
|
101
|
-
* rather than out of a separate harness.
|
|
74
|
+
* Whether the top class covers less than half the cell.
|
|
102
75
|
*/
|
|
103
76
|
topClassUnderHalf: boolean;
|
|
104
77
|
/**
|
|
105
|
-
*
|
|
78
|
+
* Whether the lattice was used instead of the whole-cell fast path.
|
|
106
79
|
*/
|
|
107
80
|
sampled: boolean;
|
|
108
81
|
}
|
|
109
82
|
/**
|
|
110
|
-
*
|
|
83
|
+
* Reduces one cell.
|
|
111
84
|
*
|
|
112
|
-
* @throws {Error} When a candidate
|
|
113
|
-
*
|
|
114
|
-
*
|
|
85
|
+
* @throws {Error} When a candidate's map unit has no profile.
|
|
86
|
+
* A missing profile means the attribute join is incomplete.
|
|
87
|
+
* The remaining candidates would describe only part of the cell.
|
|
115
88
|
*/
|
|
116
89
|
export declare function reduceCell(cell: H3Cell, resolution: number, candidates: ReadonlyArray<CellCandidate>, profiles: ReadonlyMap<string, MapUnitProfile>, h3Cell: number): ReducedCell;
|
|
117
90
|
/**
|
|
118
|
-
*
|
|
119
|
-
*
|
|
91
|
+
* Returns the sum of a stored row's class shares and four other shares.
|
|
92
|
+
*
|
|
93
|
+
* Tests use it to check that the shares sum to 1.
|
|
120
94
|
*/
|
|
121
95
|
export declare function shareTotal(row: SoilCapabilityCellTable): number;
|
|
122
96
|
//# sourceMappingURL=reduce.d.ts.map
|
package/out/sdk/reduce.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reduce.d.ts","sourceRoot":"","sources":["../../
|
|
1
|
+
{"version":3,"file":"reduce.d.ts","sourceRoot":"","sources":["../../sdk/reduce.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAuB,KAAK,MAAM,EAAE,MAAM,oBAAoB,CAAA;AAGrE,OAAO,KAAK,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAG5F;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,IAAI,CAAA;AAErC;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,OAAO,CAAA;AAErC;;GAEG;AACH,MAAM,WAAW,aAAa;IAC7B,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,UAAU,CAAA;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC9B;;;OAGG;IACH,WAAW,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACxC,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;CACd;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC7B,OAAO,EAAE,IAAI,CAAC,gBAAgB,EAAE,YAAY,CAAC,EAC7C,UAAU,EAAE,aAAa,CAAC,IAAI,CAAC,kBAAkB,EAAE,WAAW,GAAG,UAAU,GAAG,WAAW,CAAC,CAAC,GACzF,cAAc,CA2ChB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC3B,GAAG,EAAE,uBAAuB,CAAA;IAC5B;;OAEG;IACH,iBAAiB,EAAE,OAAO,CAAA;IAC1B;;OAEG;IACH,OAAO,EAAE,OAAO,CAAA;CAChB;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CACzB,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,aAAa,CAAC,aAAa,CAAC,EACxC,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,cAAc,CAAC,EAC7C,MAAM,EAAE,MAAM,GACZ,WAAW,CA8Cb;AAkID;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,uBAAuB,GAAG,MAAM,CAU/D"}
|