From 8941a81905922ad23b2e23a74cc79a346227db5b Mon Sep 17 00:00:00 2001 From: sofia Date: Wed, 20 Nov 2024 08:56:11 +0100 Subject: [PATCH 1/4] adding 3 new species to gridded livestock --- .../geeAssets/gridded-livestock-chicken.ts | 31 +++++++++++++++++++ .../src/geeAssets/gridded-livestock-duck.ts | 31 +++++++++++++++++++ .../src/geeAssets/gridded-livestock-pig.ts | 31 +++++++++++++++++++ .../earth_engine_tiler/src/index.ts | 12 +++++-- .../src/tile-request.dto.ts | 5 ++- 5 files changed, 106 insertions(+), 4 deletions(-) create mode 100644 cloud_functions/earth_engine_tiler/src/geeAssets/gridded-livestock-chicken.ts create mode 100644 cloud_functions/earth_engine_tiler/src/geeAssets/gridded-livestock-duck.ts create mode 100644 cloud_functions/earth_engine_tiler/src/geeAssets/gridded-livestock-pig.ts diff --git a/cloud_functions/earth_engine_tiler/src/geeAssets/gridded-livestock-chicken.ts b/cloud_functions/earth_engine_tiler/src/geeAssets/gridded-livestock-chicken.ts new file mode 100644 index 0000000..6049f61 --- /dev/null +++ b/cloud_functions/earth_engine_tiler/src/geeAssets/gridded-livestock-chicken.ts @@ -0,0 +1,31 @@ +import { CategoricalDataset } from './earth-engine-dataset'; +import ee from '@google/earthengine'; +import { EarthEngineUtils } from "../earth-engine-utils"; +import { GriddedLivestockCommonStyles} from "./common-styles-utils"; + +export const GriddedLivestockChicken: CategoricalDataset = { + assetPath: { + default: "projects/gmvad-grass/assets/5_Ch_2015_Da" + + }, + + bandName: 'b1', + + sldStyles: GriddedLivestockCommonStyles, + + + areYearsValid(startYear?: number, endYear?: number): boolean { + // This Asset is static, and year selector is irrelevant + return true; + }, + + getEEAsset() { + return ee.Image(this.assetPath.default); + }, + + async getMapUrl(z, x, y) { + const image = this.getEEAsset().select(this.bandName).sldStyle(this.sldStyles); + const mapId = await EarthEngineUtils.getMapId(image); + return ee.data.getTileUrl(mapId, x, y, z); + }, +}; diff --git a/cloud_functions/earth_engine_tiler/src/geeAssets/gridded-livestock-duck.ts b/cloud_functions/earth_engine_tiler/src/geeAssets/gridded-livestock-duck.ts new file mode 100644 index 0000000..cdabb27 --- /dev/null +++ b/cloud_functions/earth_engine_tiler/src/geeAssets/gridded-livestock-duck.ts @@ -0,0 +1,31 @@ +import { CategoricalDataset } from './earth-engine-dataset'; +import ee from '@google/earthengine'; +import { EarthEngineUtils } from "../earth-engine-utils"; +import { GriddedLivestockCommonStyles} from "./common-styles-utils"; + +export const GriddedLivestockDuck: CategoricalDataset = { + assetPath: { + default: "projects/gmvad-grass/assets/5_Dk_2015_Da" + + }, + + bandName: 'b1', + + sldStyles: GriddedLivestockCommonStyles, + + + areYearsValid(startYear?: number, endYear?: number): boolean { + // This Asset is static, and year selector is irrelevant + return true; + }, + + getEEAsset() { + return ee.Image(this.assetPath.default); + }, + + async getMapUrl(z, x, y) { + const image = this.getEEAsset().select(this.bandName).sldStyle(this.sldStyles); + const mapId = await EarthEngineUtils.getMapId(image); + return ee.data.getTileUrl(mapId, x, y, z); + }, +}; diff --git a/cloud_functions/earth_engine_tiler/src/geeAssets/gridded-livestock-pig.ts b/cloud_functions/earth_engine_tiler/src/geeAssets/gridded-livestock-pig.ts new file mode 100644 index 0000000..2eb9acf --- /dev/null +++ b/cloud_functions/earth_engine_tiler/src/geeAssets/gridded-livestock-pig.ts @@ -0,0 +1,31 @@ +import { CategoricalDataset } from './earth-engine-dataset'; +import ee from '@google/earthengine'; +import { EarthEngineUtils } from "../earth-engine-utils"; +import { GriddedLivestockCommonStyles} from "./common-styles-utils"; + +export const GriddedLivestockPig: CategoricalDataset = { + assetPath: { + default: "projects/gmvad-grass/assets/5_Pg_2015_Da" + + }, + + bandName: 'b1', + + sldStyles: GriddedLivestockCommonStyles, + + + areYearsValid(startYear?: number, endYear?: number): boolean { + // This Asset is static, and year selector is irrelevant + return true; + }, + + getEEAsset() { + return ee.Image(this.assetPath.default); + }, + + async getMapUrl(z, x, y) { + const image = this.getEEAsset().select(this.bandName).sldStyle(this.sldStyles); + const mapId = await EarthEngineUtils.getMapId(image); + return ee.data.getTileUrl(mapId, x, y, z); + }, +}; diff --git a/cloud_functions/earth_engine_tiler/src/index.ts b/cloud_functions/earth_engine_tiler/src/index.ts index 53f4340..0138ce2 100644 --- a/cloud_functions/earth_engine_tiler/src/index.ts +++ b/cloud_functions/earth_engine_tiler/src/index.ts @@ -8,10 +8,13 @@ import {ModisNetPrimaryProductionChange} from './geeAssets/modis-net-primary-pro import {AnthropogenicBiomes} from './geeAssets/anthropogenic-biomes'; import {LivestockProductionSystems} from './geeAssets/livestock-production-systems'; import {ForestLoss} from './geeAssets/forest-loss'; +import {GriddedLivestockBuffalo} from './geeAssets/gridded-livestock-buffalo'; import {GriddedLivestockCattle} from './geeAssets/gridded-livestock-cattle'; +import {GriddedLivestockChicken} from './geeAssets/gridded-livestock-chicken'; +import {GriddedLivestockDuck} from './geeAssets/gridded-livestock-duck'; import {GriddedLivestockGoat} from './geeAssets/gridded-livestock-goat'; -import {GriddedLivestockHorse} from './geeAssets/gridded-livestock-horse'; -import {GriddedLivestockBuffalo} from './geeAssets/gridded-livestock-buffalo'; +import {GriddedLivestockHorse} from './geeAssets/gridded-livestock-horse'; +import {GriddedLivestockPig} from './geeAssets/gridded-livestock-pig'; import {GriddedLivestockSheep} from './geeAssets/gridded-livestock-sheep'; import {EarthEngineDataset} from "./geeAssets/earth-engine-dataset"; import {TileRequestDTO, Tilesets} from "./tile-request.dto"; @@ -26,10 +29,13 @@ const assets: Record = { [Tilesets.anthropogenic_biomes]: AnthropogenicBiomes, [Tilesets.livestock_production_systems]: LivestockProductionSystems, [Tilesets.forest_loss]: ForestLoss, + [Tilesets.gridded_livestock_buffalo]: GriddedLivestockBuffalo, [Tilesets.gridded_livestock_cattle]: GriddedLivestockCattle, + [Tilesets.gridded_livestock_chicken]: GriddedLivestockChicken, + [Tilesets.gridded_livestock_duck]: GriddedLivestockDuck, [Tilesets.gridded_livestock_goat]: GriddedLivestockGoat, [Tilesets.gridded_livestock_horse]: GriddedLivestockHorse, - [Tilesets.gridded_livestock_buffalo]: GriddedLivestockBuffalo, + [Tilesets.gridded_livestock_pig]: GriddedLivestockPig, [Tilesets.gridded_livestock_sheep]: GriddedLivestockSheep, } diff --git a/cloud_functions/earth_engine_tiler/src/tile-request.dto.ts b/cloud_functions/earth_engine_tiler/src/tile-request.dto.ts index fc70818..54057c8 100644 --- a/cloud_functions/earth_engine_tiler/src/tile-request.dto.ts +++ b/cloud_functions/earth_engine_tiler/src/tile-request.dto.ts @@ -7,10 +7,13 @@ export enum Tilesets { anthropogenic_biomes = "anthropogenic_biomes", livestock_production_systems = "livestock_production_systems", forest_loss = "forest_loss", + gridded_livestock_buffalo = "gridded_livestock_buffalo", gridded_livestock_cattle = "gridded_livestock_cattle", + gridded_livestock_chicken = "gridded_livestock_chicken", + gridded_livestock_duck = "gridded_livestock_duck", gridded_livestock_goat = "gridded_livestock_goat", gridded_livestock_horse = "gridded_livestock_horse", - gridded_livestock_buffalo = "gridded_livestock_buffalo", + gridded_livestock_pig = "gridded_livestock_pig", gridded_livestock_sheep = "gridded_livestock_sheep" } From e57ceda7bb226040cf41642948e1f9128fa06bdd Mon Sep 17 00:00:00 2001 From: sofia Date: Wed, 20 Nov 2024 12:29:49 +0100 Subject: [PATCH 2/4] add code for creating the total sum layer for livestock --- .../src/geeAssets/common-styles-utils.ts | 15 ++++++ .../src/geeAssets/gridded-livestock-total.ts | 54 +++++++++++++++++++ .../earth_engine_tiler/src/index.ts | 2 + .../src/tile-request.dto.ts | 1 + 4 files changed, 72 insertions(+) create mode 100644 cloud_functions/earth_engine_tiler/src/geeAssets/gridded-livestock-total.ts diff --git a/cloud_functions/earth_engine_tiler/src/geeAssets/common-styles-utils.ts b/cloud_functions/earth_engine_tiler/src/geeAssets/common-styles-utils.ts index befd537..2ab2d0d 100644 --- a/cloud_functions/earth_engine_tiler/src/geeAssets/common-styles-utils.ts +++ b/cloud_functions/earth_engine_tiler/src/geeAssets/common-styles-utils.ts @@ -11,4 +11,19 @@ export const GriddedLivestockCommonStyles = '' + '' + '' + +'' + +export const GriddedLivestockTotalStyle = + +'' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + '' \ No newline at end of file diff --git a/cloud_functions/earth_engine_tiler/src/geeAssets/gridded-livestock-total.ts b/cloud_functions/earth_engine_tiler/src/geeAssets/gridded-livestock-total.ts new file mode 100644 index 0000000..22c4eb5 --- /dev/null +++ b/cloud_functions/earth_engine_tiler/src/geeAssets/gridded-livestock-total.ts @@ -0,0 +1,54 @@ +import { CategoricalDataset } from './earth-engine-dataset'; +import ee from '@google/earthengine'; +import { EarthEngineUtils } from "../earth-engine-utils"; +import { GriddedLivestockBuffalo } from './gridded-livestock-buffalo'; +import { GriddedLivestockCattle } from './gridded-livestock-cattle'; +import { GriddedLivestockChicken } from './gridded-livestock-chicken'; +import { GriddedLivestockDuck } from './gridded-livestock-duck'; +import { GriddedLivestockGoat } from './gridded-livestock-goat'; +import { GriddedLivestockHorse } from './gridded-livestock-horse'; +import { GriddedLivestockPig } from './gridded-livestock-pig'; +import { GriddedLivestockSheep } from './gridded-livestock-sheep'; +import { GriddedLivestockTotalStyle } from "./common-styles-utils"; + +export const GriddedLivestockTotal: CategoricalDataset = { + assetPath: { + }, + bandName: 'b1', + sldStyles: GriddedLivestockTotalStyle, + + areYearsValid(startYear?: number, endYear?: number): boolean { + // This Asset is static, and year selector is irrelevant + return true; + }, + + // Unmask(0) gives 0 to no data pixels so that they can be included in the sum + getEEAsset() { + const buffaloImage = ee.Image(GriddedLivestockBuffalo.assetPath.default).select(GriddedLivestockBuffalo.bandName).unmask(0); + const cattleImage = ee.Image(GriddedLivestockCattle.assetPath.default).select(GriddedLivestockCattle.bandName).unmask(0); + const chickenImage = ee.Image(GriddedLivestockChicken.assetPath.default).select(GriddedLivestockChicken.bandName).unmask(0); + const duckImage = ee.Image(GriddedLivestockDuck.assetPath.default).select(GriddedLivestockDuck.bandName).unmask(0); + const goatImage = ee.Image(GriddedLivestockGoat.assetPath.default).select(GriddedLivestockGoat.bandName).unmask(0); + const horseImage = ee.Image(GriddedLivestockHorse.assetPath.default).select(GriddedLivestockHorse.bandName).unmask(0); + const pigImage = ee.Image(GriddedLivestockPig.assetPath.default).select(GriddedLivestockPig.bandName).unmask(0); + const sheepImage = ee.Image(GriddedLivestockSheep.assetPath.default).select(GriddedLivestockSheep.bandName).unmask(0); + + // Sum all the images + const totalImage = buffaloImage + .add(cattleImage) + .add(chickenImage) + .add(duckImage) + .add(goatImage) + .add(horseImage) + .add(pigImage) + .add(sheepImage); + + return totalImage; + }, + + async getMapUrl(z, x, y) { + const image = this.getEEAsset().sldStyle(this.sldStyles); + const mapId = await EarthEngineUtils.getMapId(image); + return ee.data.getTileUrl(mapId, x, y, z); + }, +}; \ No newline at end of file diff --git a/cloud_functions/earth_engine_tiler/src/index.ts b/cloud_functions/earth_engine_tiler/src/index.ts index 0138ce2..e830421 100644 --- a/cloud_functions/earth_engine_tiler/src/index.ts +++ b/cloud_functions/earth_engine_tiler/src/index.ts @@ -8,6 +8,7 @@ import {ModisNetPrimaryProductionChange} from './geeAssets/modis-net-primary-pro import {AnthropogenicBiomes} from './geeAssets/anthropogenic-biomes'; import {LivestockProductionSystems} from './geeAssets/livestock-production-systems'; import {ForestLoss} from './geeAssets/forest-loss'; +import {GriddedLivestockTotal} from './geeAssets/gridded-livestock-total'; import {GriddedLivestockBuffalo} from './geeAssets/gridded-livestock-buffalo'; import {GriddedLivestockCattle} from './geeAssets/gridded-livestock-cattle'; import {GriddedLivestockChicken} from './geeAssets/gridded-livestock-chicken'; @@ -29,6 +30,7 @@ const assets: Record = { [Tilesets.anthropogenic_biomes]: AnthropogenicBiomes, [Tilesets.livestock_production_systems]: LivestockProductionSystems, [Tilesets.forest_loss]: ForestLoss, + [Tilesets.gridded_livestock_total]: GriddedLivestockTotal, [Tilesets.gridded_livestock_buffalo]: GriddedLivestockBuffalo, [Tilesets.gridded_livestock_cattle]: GriddedLivestockCattle, [Tilesets.gridded_livestock_chicken]: GriddedLivestockChicken, diff --git a/cloud_functions/earth_engine_tiler/src/tile-request.dto.ts b/cloud_functions/earth_engine_tiler/src/tile-request.dto.ts index 54057c8..f272e3a 100644 --- a/cloud_functions/earth_engine_tiler/src/tile-request.dto.ts +++ b/cloud_functions/earth_engine_tiler/src/tile-request.dto.ts @@ -7,6 +7,7 @@ export enum Tilesets { anthropogenic_biomes = "anthropogenic_biomes", livestock_production_systems = "livestock_production_systems", forest_loss = "forest_loss", + gridded_livestock_total = "gridded_livestock_total", gridded_livestock_buffalo = "gridded_livestock_buffalo", gridded_livestock_cattle = "gridded_livestock_cattle", gridded_livestock_chicken = "gridded_livestock_chicken", From a01713b3f32a7a9c07e670f10dc249d531fa27f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Chaves?= Date: Mon, 2 Dec 2024 21:10:49 +0100 Subject: [PATCH 3/4] Update temporal datasets to accept year values --- .../datasets/components/temporal/absolute.tsx | 22 +++++++++---- .../datasets/components/temporal/changes.tsx | 32 +++++++++++++------ .../containers/map/layer-manager/index.tsx | 1 + 3 files changed, 39 insertions(+), 16 deletions(-) diff --git a/client/src/containers/datasets/components/temporal/absolute.tsx b/client/src/containers/datasets/components/temporal/absolute.tsx index d02e670..8b2acf7 100644 --- a/client/src/containers/datasets/components/temporal/absolute.tsx +++ b/client/src/containers/datasets/components/temporal/absolute.tsx @@ -24,20 +24,30 @@ const isCorrectTimeSelect = (timeSelect: unknown): timeSelect is [number, number timeSelect.every((t) => typeof t === "number") ); }; + +const isCorrectTimeValues = (timeValues: unknown): timeValues is number[] => { + return Array.isArray(timeValues) && timeValues.every((t) => typeof t === "number"); +}; export const TemporalDatasetItem = ({ layer }: TemporalDatasetItemProps) => { const timeSelect = (layer?.attributes?.params_config as Record[])?.find( (p) => p.key === "time-select", )?.default; + const timeValues = (layer?.attributes?.params_config as Record[])?.find( + (p) => p.key === "time-values", + )?.default; const defaultSelected = (layer?.attributes?.params_config as Record[])?.find( - (p) => p.key === "year", + (p) => p.key === "startYear", )?.default; const [layersSettings, setLayersSettings] = useSyncLayersSettings(); const [layers] = useSyncLayers(); - const options = isCorrectTimeSelect(timeSelect) - ? Array.from({ length: timeSelect[1] - timeSelect[0] + 1 }, (_, i) => timeSelect[0] + i) - : undefined; + const options = + timeValues && isCorrectTimeValues(timeValues) + ? timeValues + : isCorrectTimeSelect(timeSelect) + ? Array.from({ length: timeSelect[1] - timeSelect[0] + 1 }, (_, i) => timeSelect[0] + i) + : undefined; const layerSlug = layer?.attributes?.slug; @@ -48,13 +58,13 @@ export const TemporalDatasetItem = ({ layer }: TemporalDatasetItemProps) => { ...prev, [layerSlug]: { ...(prev ? prev[layerSlug] : {}), - year: parseInt(value), + startYear: parseInt(value), }, }; }); }; - const value = layerSlug && (layersSettings?.[layerSlug]?.year as string | undefined); + const value = layerSlug && (layersSettings?.[layerSlug]?.startYear as string | undefined); const defaultValue = typeof defaultSelected === "number" ? `${defaultSelected}` : undefined; const isDisabled = !layerSlug || !layers?.includes(layerSlug); diff --git a/client/src/containers/datasets/components/temporal/changes.tsx b/client/src/containers/datasets/components/temporal/changes.tsx index 37ee5fc..6878acd 100644 --- a/client/src/containers/datasets/components/temporal/changes.tsx +++ b/client/src/containers/datasets/components/temporal/changes.tsx @@ -7,7 +7,7 @@ import { SelectValue, } from "@/components/ui/select"; import { useSyncLayers, useSyncLayersSettings } from "@/store/map"; -import { DefaultLayerComponent, LayerListResponseDataItem } from "@/types/generated/strapi.schemas"; +import { LayerListResponseDataItem } from "@/types/generated/strapi.schemas"; import { CalendarDaysIcon } from "lucide-react"; import { useTranslations } from "next-intl"; import { useEffect, useMemo } from "react"; @@ -20,6 +20,10 @@ const isCorrectTimeSelect = (timeSelect: unknown): timeSelect is [number, number ); }; +const isCorrectTimeValues = (timeValues: unknown): timeValues is number[] => { + return Array.isArray(timeValues) && timeValues.every((t) => typeof t === "number"); +}; + type TemporalDatasetItemSelectProps = { value?: number | undefined; disabled?: boolean; @@ -59,19 +63,27 @@ const TemporalDatasetItemSelect = ({ }; const _getOptions = (params_config: unknown, start?: number, end?: number) => { + const timeValues = (params_config as Record[])?.find( + (p) => p.key === "time-values", + )?.default; const timeSelect = (params_config as Record[])?.find( (p) => p.key === "time-select", )?.default; - return isCorrectTimeSelect(timeSelect) - ? Array.from({ length: timeSelect[1] - timeSelect[0] + 1 }, (_, i) => { - const value = timeSelect[0] + i; - return { - value, - disabled: (!!start && value <= Number(start)) || (!!end && value >= Number(end)), - }; - }) - : []; + return timeValues && isCorrectTimeValues(timeValues) + ? timeValues.map((value) => ({ + value, + disabled: (!!start && value <= Number(start)) || (!!end && value >= Number(end)), + })) + : isCorrectTimeSelect(timeSelect) + ? Array.from({ length: timeSelect[1] - timeSelect[0] + 1 }, (_, i) => { + const value = timeSelect[0] + i; + return { + value, + disabled: (!!start && value <= Number(start)) || (!!end && value >= Number(end)), + }; + }) + : []; }; const selectTypes = ["absolute", "changes"] as const; diff --git a/client/src/containers/map/layer-manager/index.tsx b/client/src/containers/map/layer-manager/index.tsx index c563399..0cf1312 100644 --- a/client/src/containers/map/layer-manager/index.tsx +++ b/client/src/containers/map/layer-manager/index.tsx @@ -84,6 +84,7 @@ const LayerManager = () => { */} {LAYERS.map((l, i) => { const beforeId = i === 0 ? baseLayer : `${LAYERS[i - 1]}-layer`; + console.log(layersSettings?.[l]); return ( Date: Wed, 4 Dec 2024 17:57:10 +0100 Subject: [PATCH 4/4] Fix dataset layers sort --- client/src/components/map/provider.tsx | 1 - client/src/containers/datasets/item.tsx | 6 ++++++ client/src/containers/map/layer-manager/index.tsx | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/client/src/components/map/provider.tsx b/client/src/components/map/provider.tsx index 4ea811e..b7c9516 100644 --- a/client/src/components/map/provider.tsx +++ b/client/src/components/map/provider.tsx @@ -144,7 +144,6 @@ export const useDeckMapboxOverlay = ({ useEffect(() => { if (!layer) return; return () => { - console.log("removeLayer", i); removeLayer(i); }; }, [i, removeLayer]); // eslint-disable-line react-hooks/exhaustive-deps diff --git a/client/src/containers/datasets/item.tsx b/client/src/containers/datasets/item.tsx index f673406..433115a 100644 --- a/client/src/containers/datasets/item.tsx +++ b/client/src/containers/datasets/item.tsx @@ -46,6 +46,12 @@ const DatasetsItem = ({ attributes, className }: DatasetsItemProps) => { { query: { enabled: !!datasetLayers.length, + select: (data) => ({ + ...data, + data: data.data?.sort( + (a, b) => datasetLayers.indexOf(a.id) - datasetLayers.indexOf(b.id), + ), + }), }, }, ); diff --git a/client/src/containers/map/layer-manager/index.tsx b/client/src/containers/map/layer-manager/index.tsx index 0cf1312..5fb256e 100644 --- a/client/src/containers/map/layer-manager/index.tsx +++ b/client/src/containers/map/layer-manager/index.tsx @@ -84,7 +84,7 @@ const LayerManager = () => { */} {LAYERS.map((l, i) => { const beforeId = i === 0 ? baseLayer : `${LAYERS[i - 1]}-layer`; - console.log(layersSettings?.[l]); + return (