UNPKG

@seasketch/geoprocessing

Version:

Geoprocessing and reporting framework for SeaSketch 2.0

92 lines (83 loc) 2.81 kB
import { Sketch, SketchCollection, Polygon, MultiPolygon, GeoprocessingHandler, getFirstFromParam, DefaultExtraParams, rasterMetrics, isRasterDatasource, loadCog, } from "@seasketch/geoprocessing"; import project from "../../project/projectClient.js"; import { Metric, ReportResult, rekeyMetrics, sortMetrics, } from "@seasketch/geoprocessing/client-core"; import { clipToGeography } from "../util/clipToGeography.js"; /** * rasterFunction: A geoprocessing function that calculates overlap metrics for raster datasources * @param sketch - A sketch or collection of sketches * @param extraParams * @returns Calculated metrics and a null sketch */ export async function rasterFunction( sketch: | Sketch<Polygon | MultiPolygon> | SketchCollection<Polygon | MultiPolygon>, extraParams: DefaultExtraParams = {}, ): Promise<ReportResult> { // Check for client-provided geography, fallback to first geography assigned as default-boundary in metrics.json const geographyId = getFirstFromParam("geographyIds", extraParams); const curGeography = project.getGeographyById(geographyId, { fallbackGroup: "default-boundary", }); // Clip portion of sketch outside geography features const clippedSketch = await clipToGeography(sketch, curGeography); // Calculate overlap metrics for each class in metric group const metricGroup = project.getMetricGroup("rasterFunction"); const metrics: Metric[] = ( await Promise.all( metricGroup.classes.map(async (curClass) => { const ds = project.getMetricGroupDatasource(metricGroup, { classId: curClass.classId, }); if (!isRasterDatasource(ds)) throw new Error(`Expected raster datasource for ${ds.datasourceId}`); const url = project.getDatasourceUrl(ds); // Load raster metadata const raster = await loadCog(url); // Run raster analysis const overlapResult = await rasterMetrics(raster, { metricId: metricGroup.metricId, feature: clippedSketch, ...(ds.measurementType === "quantitative" && { stats: ["sum"] }), ...(ds.measurementType === "categorical" && { categorical: true, categoryMetricValues: [curClass.classId], }), }); return overlapResult.map( (metrics): Metric => ({ ...metrics, classId: curClass.classId, geographyId: curGeography.geographyId, }), ); }), ) ).flat(); return { metrics: sortMetrics(rekeyMetrics(metrics)), }; } export default new GeoprocessingHandler(rasterFunction, { title: "rasterFunction", description: "Function description", timeout: 500, // seconds memory: 1024, // megabytes executionMode: "async", });