diff --git a/package.json b/package.json index a235f53..28393ca 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "test:mode": "node -r esm ./src/mode/mode.test.js", "test:modes": "node -r esm ./src/modes/modes.test.js", "test:range": "node -r esm ./src/range/range.test.js", + "test:stats": "node -r esm ./src/stats/stats.test.js", "test:sum": "node -r esm ./src/sum/sum.test.js", "test-loading-builds": "node test-loading-builds.js", "setup": "bash setup.sh" diff --git a/src/intersect-polygon/intersect-polygon.module.js b/src/intersect-polygon/intersect-polygon.module.js index 5c810c2..e702130 100644 --- a/src/intersect-polygon/intersect-polygon.module.js +++ b/src/intersect-polygon/intersect-polygon.module.js @@ -52,8 +52,9 @@ const intersectPolygon = (georaster, geometry, perPixelFunction, { debug_level = if (geometry_bbox_size_ratios.some(([xratio, yratio]) => xratio <= 1 || yratio <= 1)) { const geometry_bboxes_multipliers = geometry_bbox_size_ratios.map(([xratio, yratio]) => [2 / xratio, 2 / yratio]); vrm = [ - Math.ceil(fastMax(geometry_bboxes_multipliers.map(([xmul, ymul]) => xmul))), - Math.ceil(fastMax(geometry_bboxes_multipliers.map(([xmul, ymul]) => ymul))) + // don't drop more than 10,000 sample lines per pixel + Math.min(10000, Math.ceil(fastMax(geometry_bboxes_multipliers.map(([xmul, ymul]) => xmul)))), + Math.min(10000, Math.ceil(fastMax(geometry_bboxes_multipliers.map(([xmul, ymul]) => ymul)))) ]; } else { vrm = VRM_NO_RESAMPLING; @@ -79,10 +80,10 @@ const intersectPolygon = (georaster, geometry, perPixelFunction, { debug_level = const intersections = dufour_peyton_intersection.calculate({ debug: false, raster_bbox: georaster_bbox, - raster_height: georaster.height, - raster_width: georaster.width, - pixel_height: georaster.pixelHeight, - pixel_width: georaster.pixelWidth, + raster_height: georaster.height * yvrm, + raster_width: georaster.width * xvrm, + pixel_height: georaster.pixelHeight / yvrm, + pixel_width: georaster.pixelWidth / xvrm, geometry }); diff --git a/src/max/index.js b/src/max/index.js index 995a11d..b127dec 100644 --- a/src/max/index.js +++ b/src/max/index.js @@ -19,5 +19,5 @@ import stat from "../stat"; */ export default function max(georaster, geometry, test) { - return stat(georaster, geometry, "max", test, { vrm: 100 }); + return stat(georaster, geometry, "max", test, { vrm: "minimal" }); } diff --git a/src/max/max.test.js b/src/max/max.test.js index d4c1ac7..c76aaac 100644 --- a/src/max/max.test.js +++ b/src/max/max.test.js @@ -5,7 +5,7 @@ import { serve } from "srvd"; import load from "../load"; import max from "."; -serve({ debug: true, max: 5, port: 3000 }); +serve({ debug: true, max: 7, port: 3000, wait: 240 }); const url = "http://localhost:3000/data/test.tiff"; @@ -65,13 +65,13 @@ test("Max with Web Mercator Bounding Box and GeoRaster URL", async ({ eq }) => { test("virtual resampling, contained", async ({ eq }) => { const url = "http://localhost:3000/data/geotiff-test-data/nz_habitat_anticross_4326_1deg.tif"; const geojson = await fetch("http://localhost:3000/data/virtual-resampling/virtual-resampling-one.geojson").then(res => res.json()); - const result = await max(url, geojson) - eq(result, [38]); -}) + const result = await max(url, geojson); + eq(result, [38]); +}); test("virtual resampling, intersecting 4 pixels", async ({ eq }) => { const url = "http://localhost:3000/data/geotiff-test-data/nz_habitat_anticross_4326_1deg.tif"; const geojson = await fetch("http://localhost:3000/data/virtual-resampling/virtual-resampling-intersect.geojson").then(res => res.json()); - const result = await max(url, geojson) - eq(result, [38]); -}) + const result = await max(url, geojson); + eq(result, [38]); +}); diff --git a/src/mean/index.js b/src/mean/index.js index c484004..f751bd4 100644 --- a/src/mean/index.js +++ b/src/mean/index.js @@ -19,5 +19,5 @@ import stat from "../stat"; */ export default function mean(georaster, geometry, test) { - return stat(georaster, geometry, "mean", test, { vrm: 100 }); + return stat(georaster, geometry, "mean", test, { vrm: "minimal" }); } diff --git a/src/mean/mean.test.js b/src/mean/mean.test.js index ed552aa..ad3659f 100644 --- a/src/mean/mean.test.js +++ b/src/mean/mean.test.js @@ -95,13 +95,28 @@ test("(Modern) Mean from GeoJSON", async ({ eq }) => { test("virtual resampling, contained", async ({ eq }) => { const url = "http://localhost:3000/data/geotiff-test-data/nz_habitat_anticross_4326_1deg.tif"; const geojson = await fetch("http://localhost:3000/data/virtual-resampling/virtual-resampling-one.geojson").then(res => res.json()); - const result = await mean(url, geojson) - eq(result, [38]); -}) + const result = await mean(url, geojson); + eq(result, [38]); +}); test("virtual resampling, intersecting 4 pixels", async ({ eq }) => { const url = "http://localhost:3000/data/geotiff-test-data/nz_habitat_anticross_4326_1deg.tif"; const geojson = await fetch("http://localhost:3000/data/virtual-resampling/virtual-resampling-intersect.geojson").then(res => res.json()); - const result = await mean(url, geojson) - eq(result, [33.61065313887127]); -}) \ No newline at end of file + const result = await mean(url, geojson); + eq(result, [38]); +}); + +test("virtual resampling, intersecting 4 pixels (sync)", async ({ eq }) => { + const url = "http://localhost:3000/data/geotiff-test-data/nz_habitat_anticross_4326_1deg.tif"; + const geojson = await fetch("http://localhost:3000/data/virtual-resampling/virtual-resampling-intersect.geojson").then(res => res.json()); + const georaster = await load(url); + const result = await mean(georaster, geojson); + eq(result, [38]); +}); + +test("virtual resampling with bbox", async ({ eq }) => { + const url = "http://localhost:3000/data/geotiff-test-data/nz_habitat_anticross_4326_1deg.tif"; + const geom = [166.06811846012403, -46.42907237702467, 166.23189176587618, -46.40887433963862]; + const result = await mean(url, geom); + eq(result, [38]); +}); diff --git a/src/median/index.js b/src/median/index.js index 1e29289..5323c1f 100644 --- a/src/median/index.js +++ b/src/median/index.js @@ -19,5 +19,5 @@ import stat from "../stat"; */ export default function median(georaster, geometry, test) { - return stat(georaster, geometry, "median", test, { vrm: 100 }); + return stat(georaster, geometry, "median", test, { vrm: "minimal" }); } diff --git a/src/median/median.test.js b/src/median/median.test.js index 48e3625..0e5b637 100644 --- a/src/median/median.test.js +++ b/src/median/median.test.js @@ -82,13 +82,13 @@ test("Get Median from Whole Raster from url", async ({ eq }) => { test("virtual resampling, contained", async ({ eq }) => { const url = "http://localhost:3000/data/geotiff-test-data/nz_habitat_anticross_4326_1deg.tif"; const geojson = await fetch("http://localhost:3000/data/virtual-resampling/virtual-resampling-one.geojson").then(res => res.json()); - const result = await median(url, geojson) - eq(result, [38]); -}) + const result = await median(url, geojson); + eq(result, [38]); +}); test("virtual resampling, intersecting 4 pixels", async ({ eq }) => { const url = "http://localhost:3000/data/geotiff-test-data/nz_habitat_anticross_4326_1deg.tif"; const geojson = await fetch("http://localhost:3000/data/virtual-resampling/virtual-resampling-intersect.geojson").then(res => res.json()); - const result = await median(url, geojson) - eq(result, [38]); -}) + const result = await median(url, geojson); + eq(result, [38]); +}); diff --git a/src/min/index.js b/src/min/index.js index 9fd4ecc..7fac1d3 100644 --- a/src/min/index.js +++ b/src/min/index.js @@ -19,5 +19,5 @@ import stat from "../stat"; */ export default function min(georaster, geometry, test) { - return stat(georaster, geometry, "min", test, { vrm: 100 }); + return stat(georaster, geometry, "min", test, { vrm: "minimal" }); } diff --git a/src/min/min.test.js b/src/min/min.test.js index f3e2e73..99e0825 100644 --- a/src/min/min.test.js +++ b/src/min/min.test.js @@ -3,7 +3,7 @@ import { serve } from "srvd"; import load from "../load"; import min from "."; -serve({ debug: true, max: 5, port: 3000 }); +serve({ debug: true, max: 5, port: 3000, wait: 120 }); const url = "http://localhost:3000/data/test.tiff"; const bbox = [80.63, 7.42, 84.21, 10.1]; @@ -65,13 +65,13 @@ test("(Modern) Get Min from whole Raster", async ({ eq }) => { test("virtual resampling, contained", async ({ eq }) => { const url = "http://localhost:3000/data/geotiff-test-data/nz_habitat_anticross_4326_1deg.tif"; const geojson = await fetch("http://localhost:3000/data/virtual-resampling/virtual-resampling-one.geojson").then(res => res.json()); - const result = await min(url, geojson) - eq(result, [38]); -}) + const result = await min(url, geojson); + eq(result, [38]); +}); test("virtual resampling, intersecting 4 pixels", async ({ eq }) => { const url = "http://localhost:3000/data/geotiff-test-data/nz_habitat_anticross_4326_1deg.tif"; const geojson = await fetch("http://localhost:3000/data/virtual-resampling/virtual-resampling-intersect.geojson").then(res => res.json()); - const result = await min(url, geojson) - eq(result, [1]); -}) + const result = await min(url, geojson); + eq(result, [38]); +}); diff --git a/src/mode/index.js b/src/mode/index.js index 80b4059..ada8d6b 100644 --- a/src/mode/index.js +++ b/src/mode/index.js @@ -20,5 +20,5 @@ import stat from "../stat"; */ export default function mode(georaster, geometry, test) { - return stat(georaster, geometry, "mode", test, { vrm: 100 }); + return stat(georaster, geometry, "mode", test, { vrm: "minimal" }); } diff --git a/src/mode/mode.test.js b/src/mode/mode.test.js index 9adead1..76dfee6 100644 --- a/src/mode/mode.test.js +++ b/src/mode/mode.test.js @@ -48,13 +48,13 @@ test("(Modern) Mode Polygon", async ({ eq }) => { test("virtual resampling, contained", async ({ eq }) => { const url = "http://localhost:3000/data/geotiff-test-data/nz_habitat_anticross_4326_1deg.tif"; const geojson = await fetch("http://localhost:3000/data/virtual-resampling/virtual-resampling-one.geojson").then(res => res.json()); - const result = await mode(url, geojson) - eq(result, [38]); -}) + const result = await mode(url, geojson); + eq(result, [38]); +}); test("virtual resampling, intersecting 4 pixels", async ({ eq }) => { const url = "http://localhost:3000/data/geotiff-test-data/nz_habitat_anticross_4326_1deg.tif"; const geojson = await fetch("http://localhost:3000/data/virtual-resampling/virtual-resampling-intersect.geojson").then(res => res.json()); - const result = await mode(url, geojson) - eq(result, [38]); -}) + const result = await mode(url, geojson); + eq(result, [38]); +}); diff --git a/src/modes/index.js b/src/modes/index.js index 920efe7..b2e52b3 100644 --- a/src/modes/index.js +++ b/src/modes/index.js @@ -20,5 +20,5 @@ import stat from "../stat"; */ export default function modes(georaster, geometry, test) { - return stat(georaster, geometry, "modes", test, { vrm: 100 }); + return stat(georaster, geometry, "modes", test, { vrm: "minimal" }); } diff --git a/src/modes/modes.test.js b/src/modes/modes.test.js index eed02e1..77c0d9d 100644 --- a/src/modes/modes.test.js +++ b/src/modes/modes.test.js @@ -48,13 +48,13 @@ test("(Modern) Modes Polygon", async ({ eq }) => { test("virtual resampling, contained", async ({ eq }) => { const url = "http://localhost:3000/data/geotiff-test-data/nz_habitat_anticross_4326_1deg.tif"; const geojson = await fetch("http://localhost:3000/data/virtual-resampling/virtual-resampling-one.geojson").then(res => res.json()); - const result = await modes(url, geojson) - eq(result, [38]); -}) + const result = await modes(url, geojson); + eq(result, [[38]]); +}); test("virtual resampling, intersecting 4 pixels", async ({ eq }) => { const url = "http://localhost:3000/data/geotiff-test-data/nz_habitat_anticross_4326_1deg.tif"; const geojson = await fetch("http://localhost:3000/data/virtual-resampling/virtual-resampling-intersect.geojson").then(res => res.json()); - const result = await modes(url, geojson) - eq(result, [38]); -}) \ No newline at end of file + const result = await modes(url, geojson); + eq(result, [[38]]); +}); diff --git a/src/range/index.js b/src/range/index.js index 37b6e66..99c2a28 100644 --- a/src/range/index.js +++ b/src/range/index.js @@ -19,5 +19,5 @@ import stat from "../stat"; */ export default function range(georaster, geometry, test) { - return stat(georaster, geometry, "range", test, { vrm: 100 }); + return stat(georaster, geometry, "range", test, { vrm: "minimal" }); } diff --git a/src/range/range.test.js b/src/range/range.test.js index 96ca0bf..86456ba 100644 --- a/src/range/range.test.js +++ b/src/range/range.test.js @@ -2,7 +2,9 @@ import test from "flug"; import { serve } from "srvd"; import range from "."; -serve({ debug: true, max: 25, port: 3000 }); +const sleep = ms => new Promise(resolve => setTimeout(() => resolve(), ms)); + +serve({ debug: true, max: 22, port: 3000, wait: 160 }); const url = "http://localhost:3000/data/test.tiff"; const bbox = [80.63, 7.42, 84.21, 10.1]; @@ -40,18 +42,22 @@ test("(Modern) Get Range from Polygon", async ({ eq }) => { test("(Modern) Get Range from whole Raster", async ({ eq }) => { const results = await range(url); eq(results, [8131.2]); + + // weird hack to give time for main thread and/or srvd to clear up tasks before next request is sent + await sleep(1000); }); test("virtual resampling, contained", async ({ eq }) => { + const geojson_res = await fetch("http://localhost:3000/data/virtual-resampling/virtual-resampling-one.geojson"); + const geojson = await geojson_res.json(); const url = "http://localhost:3000/data/geotiff-test-data/nz_habitat_anticross_4326_1deg.tif"; - const geojson = await fetch("http://localhost:3000/data/virtual-resampling/virtual-resampling-one.geojson").then(res => res.json()); - const result = await range(url, geojson) - eq(result, [0]); -}) + const result = await range(url, geojson); + eq(result, [0]); +}); test("virtual resampling, intersecting 4 pixels", async ({ eq }) => { const url = "http://localhost:3000/data/geotiff-test-data/nz_habitat_anticross_4326_1deg.tif"; const geojson = await fetch("http://localhost:3000/data/virtual-resampling/virtual-resampling-intersect.geojson").then(res => res.json()); - const result = await range(url, geojson) - eq(result, [37]); -}) + const result = await range(url, geojson); + eq(result, [0]); // range is zero because by default doing minimal (i.e. bare minimum) resampling +}); diff --git a/src/stats/stats.core.js b/src/stats/stats.core.js index f235f3a..6a4233a 100644 --- a/src/stats/stats.core.js +++ b/src/stats/stats.core.js @@ -1,12 +1,16 @@ import calcStats from "calc-stats"; import QuickPromise from "quick-promise"; +import polygon from "bbox-fns/polygon"; +import validate from "bbox-fns/validate"; import get from "../get"; import utils from "../utils"; import wrap from "../wrap-parse"; import { convertBbox, convertMultiPolygon } from "../convert-geometry"; import intersectPolygon from "../intersect-polygon"; -const stats = (georaster, geometry, calcStatsOptions, test, { debug_level = 0, vrm } = {}) => { +const VRM_NO_RESAMPLING = [1, 1]; + +const stats = (georaster, geometry, calcStatsOptions, test, { debug_level = 0, include_meta = false, rescale = false, vrm = VRM_NO_RESAMPLING } = {}) => { try { // shallow clone calcStatsOptions = { ...calcStatsOptions }; @@ -18,20 +22,13 @@ const stats = (georaster, geometry, calcStatsOptions, test, { debug_level = 0, v calcStatsOptions.noData = noDataValue; } - let xvrm; - let yvrm; if (typeof vrm === "number") { - if (vrm !== Math.round(vrm)) { - throw new Error("[geoblaze] divisor must be an integer"); + if (vrm <= 0 || vrm !== Math.round(vrm)) { + throw new Error("[geoblaze] vrm can only be defined as a positive integer"); } - xvrm = vrm; - yvrm = vrm; - } else if (Array.isArray(vrm) && vrm.length === 2 && typeof vrm[0] === "number") { - [xvrm, yvrm] = vrm; + vrm = [vrm, vrm]; } - console.log("vrm:", [xvrm, yvrm]); - if (test) { if (calcStatsOptions && calcStatsOptions.filter) { const original_filter = calcStatsOptions.filter; @@ -44,14 +41,24 @@ const stats = (georaster, geometry, calcStatsOptions, test, { debug_level = 0, v const flat = true; const getStatsByBand = values => values.map(band => calcStats(band, calcStatsOptions)); - if (geometry === null || geometry === undefined) { + const resample = vrm === "minimal" || (Array.isArray(vrm) && (vrm[0] !== 1 || vrm[1] !== 1)); + const geometry_is_nullish = geometry === null || geometry === undefined; + + if (resample === true) { + if (geometry_is_nullish) { + geometry = polygon([georaster.xmin, georaster.ymin, georaster.xmax, georaster.ymax]); + } else if (validate(geometry)) { + geometry = polygon(geometry); + } + } + + if (geometry_is_nullish && resample === false) { if (debug_level >= 2) console.log("[geoblaze] geometry is nullish"); const values = get(georaster, undefined, flat); return QuickPromise.resolve(values).then(getStatsByBand); - } else if (utils.isBbox(geometry)) { + } else if (utils.isBbox(geometry) && resample === false) { if (debug_level >= 2) console.log("[geoblaze] geometry is a rectangle"); geometry = convertBbox(geometry); - // if using multiplier, might need to pad get results or at least not round const values = get(georaster, geometry, flat); return QuickPromise.resolve(values).then(getStatsByBand); } else if (utils.isPolygonal(geometry)) { @@ -77,10 +84,85 @@ const stats = (georaster, geometry, calcStatsOptions, test, { debug_level = 0, v { debug_level, vrm } ); - return QuickPromise.resolve(done).then(() => { + return QuickPromise.resolve(done).then(({ vrm }) => { + // check if the user wants the number of valid pixels returned + const want_valid = calcStatsOptions.stats ? calcStatsOptions.stats.includes("valid") : calcStatsOptions.calcValid === true; + + const use_virtual_resampling = vrm[0] !== 1 && vrm[1] !== 1; + const bands = values.filter(band => band.length !== 0); - if (bands.length > 0) return bands.map(band => calcStats(band, calcStatsOptions)); - else throw "No Values were found in the given geometry"; + + if (bands.length > 0) { + // if we need to know the number of valid pixels for intermediate calculations, + // but the user didn't ask for it, calculate it anyway + // and then remove the valid count from the returned results + if (use_virtual_resampling) { + if (calcStatsOptions.stats) { + if (calcStatsOptions.stats.includes("product") && calcStatsOptions.stats.includes("valid") === false) { + calcStatsOptions.stats = [...calcStatsOptions.stats, "valid"]; + if (debug_level >= 2) console.log('[geoblaze] added "valid" to stats'); + } + } else { + if (calcStatsOptions.calcProduct === true && calcStatsOptions.calcValid === false) { + calcStatsOptions.calcValid = true; + if (debug_level >= 2) console.log('[geoblaze] set "calcValid" to true'); + } + } + } + + const stats = bands.map(band => calcStats(band, calcStatsOptions)); + if (debug_level >= 2) console.log("[geoblaze] stats (before rescaling):", stats); + + // only rescaling results if virtual resampling is on + if (use_virtual_resampling && rescale) { + if (debug_level >= 2) console.log("[geoblaze] rescaling results based on relative size of virtual pixels"); + + // if vrm is [2, 4] then area_multiplier will be 8, + // meaning there are 8 virtual pixels for every actual pixel + const area_multiplier = vrm[0] * vrm[1]; + if (debug_level >= 2) console.log("[geoblaze] area_multiplier:", area_multiplier); + + stats.forEach(band => { + const { valid } = band; + if (typeof band.count === "number") band.count /= area_multiplier; + if (typeof band.invalid === "number") band.invalid /= area_multiplier; + if (typeof band.sum === "number") band.sum /= area_multiplier; + if (typeof band.valid === "number") band.valid /= area_multiplier; + + if (band.histogram) { + for (let key in band.histogram) { + // this will lead to fractions of pixels + // for example, a pixel could appear 3.75 times if vrm is [2, 2] + band.histogram[key].ct /= area_multiplier; + } + } + + if (typeof band.product === "number") { + band.product /= Math.pow(area_multiplier, valid); + } + }); + } + + // if the user asked not to have the valid stat, + // exclude if from the results + if (want_valid === false) { + stats.forEach(band => delete band.valid); + } + + if (include_meta) { + stats.forEach(band => { + band._meta = { + vph: georaster.pixelHeight / vrm[1], + vpw: georaster.pixelWidth / vrm[0], + vrm: [vrm[0], vrm[1]] + }; + }); + } + + return stats; + } else { + throw "No Values were found in the given geometry"; + } }); } else { throw "Geometry Type is Not Supported"; diff --git a/src/stats/stats.test.js b/src/stats/stats.test.js index 3025307..09c2a88 100644 --- a/src/stats/stats.test.js +++ b/src/stats/stats.test.js @@ -10,7 +10,7 @@ import load from "../load"; import parse from "../parse"; import stats from "./stats.module"; -serve({ debug: true, max: 30, port: 3000, wait: 240 }); +serve({ debug: true, max: 35, port: 3000, wait: 240 }); const url = "http://localhost:3000/data/test.tiff"; @@ -244,3 +244,66 @@ test("multipolygon vs 2 polygons", async ({ eq }) => { const results2 = await stats(georaster, poly2, { debug_level: 5, stats: _stats }); eq(results2, [{ count: 576, valid: 4, invalid: 572, min: 0, max: 0, sum: 0 }]); }); + +test("virtual resampling, contained", async ({ eq }) => { + const url = "http://localhost:3000/data/geotiff-test-data/nz_habitat_anticross_4326_1deg.tif"; + const geojson = await fetch("http://localhost:3000/data/virtual-resampling/virtual-resampling-one.geojson").then(res => res.json()); + const result = await stats(url, geojson, undefined, undefined, { debug_level: 10, rescale: true, vrm: "minimal" }); + eq(result, [ + { + count: 0.007936507936507936, + invalid: 0, + median: 38, + min: 38, + max: 38, + product: 0.022738725119677502, + sum: 0.30158730158730157, + range: 0, + mean: 38, + variance: 0, + std: 0, + histogram: { 38: { n: 38, ct: 0.007936507936507936 } }, + modes: [38], + mode: 38, + uniques: [38] + } + ]); +}); + +test("virtual resampling, intersecting 4 pixels", async ({ eq }) => { + const url = "http://localhost:3000/data/geotiff-test-data/nz_habitat_anticross_4326_1deg.tif"; + const geojson = await fetch("http://localhost:3000/data/virtual-resampling/virtual-resampling-intersect.geojson").then(res => res.json()); + const result = await stats(url, geojson, null, null, { include_meta: false, rescale: true, vrm: [10, 10] }); + eq(result, [ + { + count: 0.18, + invalid: 0, + median: 38, + min: 1, + max: 38, + product: 1.5122637183654097e-10, + sum: 6.17, + range: 37, + mean: 34.27777777777778, + variance: 112.20061728395062, + std: 10.592479279373201, + histogram: { + 1: { + n: 1, + ct: 0.01 + }, + 8: { + n: 8, + ct: 0.01 + }, + 38: { + n: 38, + ct: 0.16 + } + }, + modes: [38], + mode: 38, + uniques: [1, 8, 38] + } + ]); +}); diff --git a/src/sum/index.js b/src/sum/index.js index 7eebc35..75659af 100644 --- a/src/sum/index.js +++ b/src/sum/index.js @@ -1,3 +1,4 @@ +import QuickPromise from "quick-promise"; import stat from "../stat"; /** @@ -17,6 +18,6 @@ import stat from "../stat"; * // results is [red, green, blue, nir] * [217461, 21375, 57312, 457125] */ -export default function sum(georaster, geometry, test, { vrm } = {}) { - return stat(georaster, geometry, "sum", test, { vrm }); +export default function sum(georaster, geometry, test) { + return QuickPromise.resolve(stat(georaster, geometry, "sum", test, { rescale: true, vrm: "minimal" })); } diff --git a/src/sum/sum.test.js b/src/sum/sum.test.js index 24db67e..da5639d 100644 --- a/src/sum/sum.test.js +++ b/src/sum/sum.test.js @@ -312,6 +312,6 @@ test("Virtual Resampling", async ({ eq }) => { await fetchJson(`http://localhost:${port}/data/virtual-resampling/virtual-resampling-one.geojson`) ]; const [georaster, geojson] = values; - const results = await sum(georaster, geojson, undefined, { vrm: 10 }); - eq(results, []); + const results = await sum(georaster, geojson, undefined); + eq(results, [0.30158730158730157]); });