Skip to main content

GPURaster analytical overviews

GPU-generated analytical overviews

Use an existing source-provided overview when its source-side sampling or reduction policy is known, its lower resolution avoids unnecessary decoding or upload, and its analytical meaning is appropriate for the task. Use GPURasterOverview when continuous floating-point observations must be reduced on the GPU without treating nodata as zero, discarding valid-sample weights, or averaging intermediate averages. Use GPURasterCategoricalOverview when classification labels need an explicit nearest-sample or most-frequent-label policy without fractional interpolation.

Generated overviews are distinct from source-provided GPURasterTileReader levels. They do not register new source levels, replace a decoder, select a transport, discover a GeoTIFF pyramid, or move source samples between CPU and GPU. Each contributor adds one explicit compute pass to the caller's command graph and writes only caller-owned output views.

QuestionSource-provided overviewGPU-generated analytical overview
Where do its samples originate?A level the application-owned source already exposes.Existing resident observations in a caller-owned graph.
Who chooses the sampling policy?The source or application; the reader does not infer its meaning.The explicit floating mean or categorical nearest/mode contributor.
Does selecting it create GPU reduction work?No; it requests an existing decoded source level.Yes; the application explicitly adds a bounded compute pass.
Can floating means preserve nodata and future weights?Only if the source itself supplies and documents those semantics.Yes; separate sum, valid count, validity, and mean are published.
Does it become a new decoder/source level automatically?It is already declared in source metadata.No; the generated output remains application-owned graph data.

Display-oriented mipmaps and browser image resampling are not substitutes for either contract: they do not, by themselves, expose exact categorical identity, missing-observation coverage, weighted analytical sums, or the resulting raster's geospatial metadata.

Floating means, nodata, and valid coverage

GPURasterOverview consumes a float32 source band and publishes four separate packed output views: the analytical mean, canonical uint32 validity, calibrated float32 sum, and uint32 valid-sample count.

const generatedMetadata = makeRasterOverviewMetadata(sourceMetadata, [2, 3]);

new GPURasterOverview({
id: 'nodata-aware-reflectance-overview',
metadata: sourceMetadata,
scale: [2, 3],
input: reflectanceBand,
output: overviewValues,
outputValidity: overviewValidity,
sum: overviewSums,
validCount: overviewValidCounts
}).addToGraph(graph);

The reducer first intersects the explicit source validity mask, raw nodata sentinel, and finite raw observation. Source calibration is applied exactly once as rawValue * input.scale + input.offset; non-finite calibrated results are excluded. The parent value is the sum of remaining calibrated observations divided by their valid count, not by the nominal footprint area. A 2 × 2 footprint containing [10, invalid, 30, invalid] therefore publishes sum 40, count 2, mean 20, and validity 1. An entirely invalid footprint publishes sum 0, count 0, validity 0, and a canonical quiet NaN mean.

Odd right and bottom edges use only existing source observations; missing coverage is not zero-padded. Retaining the sum and count separately makes population coverage and correctly weighted downstream pyramid levels available without downloading samples.

Weighted multilevel pyramids

Forward both sum and valid count when reducing an already generated mean. Supply an explicit maximum number of raw observations that any input parent can represent:

new GPURasterOverview({
id: 'weighted-coarser-overview',
metadata: generatedMetadata,
scale: 2,
input: firstOverviewBand,
inputSum: overviewSums,
inputValidCount: overviewValidCounts,
maximumInputValidCount: 6,
output: coarserValues,
outputValidity: coarserValidity,
sum: coarserSums,
validCount: coarserValidCounts
}).addToGraph(graph);

For parent inputs with (sum, count) of (10, 1) and (60, 3), the correct next-level mean is (10 + 60) / (1 + 3) = 17.5; averaging their intermediate means (10 + 20) / 2 = 15 would bias the smaller population. Weighted levels consume the already calibrated sums directly and never apply source calibration a second time.

inputSum and inputValidCount must be supplied together, and weighted mode requires maximumInputValidCount. Construction rejects any configuration whose maximum horizontalScale * verticalScale * maximumInputValidCount could exceed the uint32 count range. An observed child count above its declared bound invalidates the parent instead of wrapping or silently publishing incorrect coverage.

Exact categorical nearest and mode

GPURasterCategoricalOverview preserves either uint32 or sint32 source identities and requires an explicit categorical policy:

new GPURasterCategoricalOverview({
id: 'land-cover-majority-overview',
metadata: sourceMetadata,
scale: [2, 2],
input: landCoverLabels,
policy: 'mode',
output: overviewLabels,
outputValidity: overviewLabelValidity,
validCount: overviewLabelCoverage
}).addToGraph(graph);

Choose 'nearest' when a representative existing sample is required. Even-sized footprints select the upper-left of their central candidates. If that selected observation is masked or matches raw nodata, the result is invalid; it does not silently substitute a different valid label. Choose 'mode' when the most frequent valid label better represents a region. Invalid samples are ignored, and equal frequencies deterministically select the numerically smallest exact label. Negative signed categories and unsigned identifiers above 2²⁴ remain native integers rather than passing through float32.

outputValidity is always explicit. An invalid categorical parent publishes value 0 with validity 0; a valid category whose identity is actually zero remains distinguishable through validity 1. Optional validCount reports the number of valid observations in the complete footprint for either policy, including valid alternatives when a nearest-selected center is itself invalid.

Spatial metadata, grid alignment, and cost

GPURasterOverviewScale accepts an integer or [horizontalScale, verticalScale]; each axis must be between 1 and 8. Output dimensions use independent ceiling division, so a 5 × 7 source at [2, 3] produces 3 × 3 parents. makeRasterOverviewMetadata derives the same target metadata as either contributor without allocating GPU resources:

const metadata = makeRasterOverviewMetadata(sourceMetadata, [2, 3], {
level: 2,
sourcePixelOrigin: [4, 6]
});

For an already positioned source affine [a, b, c, d, e, f], the generated affine is [a * sx, b * sy, c, d * sx, e * sy, f]. Existing source translations c and f stay unchanged, including rotated or sheared grids; source coordinate-reference-system identity, pixel interpretation, and level-zero origin are preserved. The target level defaults to the source level plus one, and an explicitly supplied level must be greater than its source level.

The source origin must align with both reduction axes. When a level-zero source omits sourcePixelOrigin, GPURaster infers its levelZeroOrigin or [0, 0] and rejects globally misaligned translated tiles. A higher-level source with a nonzero levelZeroOrigin must supply sourcePixelOrigin explicitly in its current-level pixel coordinates; its level-zero origin alone cannot safely recover that current-level grid position. An explicit origin verifies alignment only: source metadata already contains the correct affine translation and preserved level-zero origin, so the helper never translates either value a second time.

The floating reduction evaluates up to horizontalScale * verticalScale observations per output pixel. Categorical mode additionally compares bounded candidate frequencies and can cost quadratically more within that footprint. Lower-resolution GPU-resident outputs may reduce work in later histograms, filters, and rendering, but reductions also allocate explicit output/sum/count/mask buffers and add a graph pass. Throughput depends on scale, nodata density, categorical policy, source residency, memory bandwidth, adapter limits, and the measured GPU; neither display-oriented image effects nor ordinary texture mipmaps preserve these analytical validity, weighting, categorical, or affine contracts.