diff --git a/config/default/common/config/wv.json/layerOrder.json b/config/default/common/config/wv.json/layerOrder.json index e08949a6af..385a1368f5 100644 --- a/config/default/common/config/wv.json/layerOrder.json +++ b/config/default/common/config/wv.json/layerOrder.json @@ -1,5 +1,10 @@ { "layerOrder": [ + "GHGC_Net_Primary_Produnction", + "GHGC_Heterotrophic_Respiration", + "GHGC_Net_Ecosystem_Exchange", + "GHGC_Fire_Emissions", + "GHGC_Wood_Fuel_Emissions", "HLS_S30_Nadir_BRDF_Adjusted_Reflectance", "HLS_L30_Nadir_BRDF_Adjusted_Reflectance", "HLS_Customizable_Landsat", diff --git a/config/default/common/config/wv.json/layers/ghgc/GHGC_Fire_Emissions.json b/config/default/common/config/wv.json/layers/ghgc/GHGC_Fire_Emissions.json new file mode 100644 index 0000000000..fccc26cf30 --- /dev/null +++ b/config/default/common/config/wv.json/layers/ghgc/GHGC_Fire_Emissions.json @@ -0,0 +1,28 @@ +{ + "layers": { + "GHGC_Fire_Emissions": { + "id": "GHGC_Fire_Emissions", + "layerName": "fire", + "title": "Fire Emissions", + "subtitle": "U.S. Greenhouse Gas Center", + "description": "ghgc/Fire_Emissions", + "tags": "ghgc fire", + "group": "overlays", + "layergroup": "Reference", + "format": "image/png", + "type": "titiler", + "disableSnapshot": true, + "wrapX": true, + "colormapName": "purd", + "rescale": "0,0.3", + "period": "monthly", + "projections": { + "geographic": { + "source": "GHGC:geographic" + } + }, + "startDate": "2003-01-01T00:00:00Z", + "endDate": "2017-12-31T23:59:59Z" + } + } + } \ No newline at end of file diff --git a/config/default/common/config/wv.json/layers/ghgc/GHGC_Heterotrophic_Respiration.json b/config/default/common/config/wv.json/layers/ghgc/GHGC_Heterotrophic_Respiration.json new file mode 100644 index 0000000000..a347eb92cc --- /dev/null +++ b/config/default/common/config/wv.json/layers/ghgc/GHGC_Heterotrophic_Respiration.json @@ -0,0 +1,28 @@ +{ + "layers": { + "GHGC_Heterotrophic_Respiration": { + "id": "GHGC_Heterotrophic_Respiration", + "layerName": "rh", + "title": "Heterotrophic Respiration", + "subtitle": "U.S. Greenhouse Gas Center", + "description": "ghgc/Heterotrophic_Respiration", + "tags": "ghgc rh", + "group": "overlays", + "layergroup": "Reference", + "format": "image/png", + "type": "titiler", + "disableSnapshot": true, + "wrapX": true, + "colormapName": "purd", + "rescale": "0,0.3", + "period": "monthly", + "projections": { + "geographic": { + "source": "GHGC:geographic" + } + }, + "startDate": "2003-01-01T00:00:00Z", + "endDate": "2017-12-31T23:59:59Z" + } + } + } \ No newline at end of file diff --git a/config/default/common/config/wv.json/layers/ghgc/GHGC_Net_Ecosystem_Exchange.json b/config/default/common/config/wv.json/layers/ghgc/GHGC_Net_Ecosystem_Exchange.json new file mode 100644 index 0000000000..d7ea059474 --- /dev/null +++ b/config/default/common/config/wv.json/layers/ghgc/GHGC_Net_Ecosystem_Exchange.json @@ -0,0 +1,28 @@ +{ + "layers": { + "GHGC_Net_Ecosystem_Exchange": { + "id": "GHGC_Net_Ecosystem_Exchange", + "layerName": "nee", + "title": "Net Ecosystem Exchange", + "subtitle": "U.S. Greenhouse Gas Center", + "description": "ghgc/Net_Ecosystem_Exchange", + "tags": "ghgc nee", + "group": "overlays", + "layergroup": "Reference", + "format": "image/png", + "type": "titiler", + "disableSnapshot": true, + "wrapX": true, + "colormapName": "coolwarm", + "rescale": "-0.1,0.1", + "period": "monthly", + "projections": { + "geographic": { + "source": "GHGC:geographic" + } + }, + "startDate": "2003-01-01T00:00:00Z", + "endDate": "2017-12-31T23:59:59Z" + } + } + } \ No newline at end of file diff --git a/config/default/common/config/wv.json/layers/ghgc/GHGC_Net_Primary_Production.json b/config/default/common/config/wv.json/layers/ghgc/GHGC_Net_Primary_Production.json new file mode 100644 index 0000000000..df3e09c661 --- /dev/null +++ b/config/default/common/config/wv.json/layers/ghgc/GHGC_Net_Primary_Production.json @@ -0,0 +1,28 @@ +{ + "layers": { + "GHGC_Net_Primary_Produnction": { + "id": "GHGC_Net_Primary_Produnction", + "layerName": "npp", + "title": "Net Primary Production", + "subtitle": "U.S. Greenhouse Gas Center", + "description": "ghgc/Net_Primary_Produnction", + "tags": "ghgc npp", + "group": "overlays", + "layergroup": "Reference", + "format": "image/png", + "type": "titiler", + "disableSnapshot": true, + "wrapX": true, + "colormapName": "purd", + "rescale": "0,0.3", + "period": "monthly", + "projections": { + "geographic": { + "source": "GHGC:geographic" + } + }, + "startDate": "2003-01-01T00:00:00Z", + "endDate": "2017-12-31T23:59:59Z" + } + } + } \ No newline at end of file diff --git a/config/default/common/config/wv.json/layers/ghgc/GHGC_Wood_Fuel_Emissions.json b/config/default/common/config/wv.json/layers/ghgc/GHGC_Wood_Fuel_Emissions.json new file mode 100644 index 0000000000..64713bff4f --- /dev/null +++ b/config/default/common/config/wv.json/layers/ghgc/GHGC_Wood_Fuel_Emissions.json @@ -0,0 +1,28 @@ +{ + "layers": { + "GHGC_Wood_Fuel_Emissions": { + "id": "GHGC_Wood_Fuel_Emissions", + "layerName": "fuel", + "title": "Wood Fuel Emissions", + "subtitle": "U.S. Greenhouse Gas Center", + "description": "ghgc/Wood_Fuel_Emissions", + "tags": "ghgc fuel", + "group": "overlays", + "layergroup": "Reference", + "format": "image/png", + "type": "titiler", + "disableSnapshot": true, + "wrapX": true, + "colormapName": "bupu", + "rescale": "0,0.03", + "period": "monthly", + "projections": { + "geographic": { + "source": "GHGC:geographic" + } + }, + "startDate": "2003-01-01T00:00:00Z", + "endDate": "2017-12-31T23:59:59Z" + } + } + } \ No newline at end of file diff --git a/config/default/release/config/wv.json/sources.json b/config/default/release/config/wv.json/sources.json index c9c3337d0f..c6c0295166 100644 --- a/config/default/release/config/wv.json/sources.json +++ b/config/default/release/config/wv.json/sources.json @@ -24,6 +24,9 @@ "FIRMS:xyz": { "url": "https://firms.modaps.eosdis.nasa.gov/layers" }, + "GHGC:geographic": { + "url": "https://ghg.center/api/raster/mosaic" + }, "DDV": { "url": "https://kv9drwgv6l.execute-api.us-west-2.amazonaws.com/", "matrixSets": { diff --git a/web/images/layers/previews/geographic/GHGC_Fire_Emissions.jpg b/web/images/layers/previews/geographic/GHGC_Fire_Emissions.jpg new file mode 100644 index 0000000000..7d9c05ee4f --- /dev/null +++ b/web/images/layers/previews/geographic/GHGC_Fire_Emissions.jpg @@ -0,0 +1,6 @@ + + + +msWMSLoadGetMapParams(): WMS server error. Invalid layer(s) given in the LAYERS parameter. A layer might be disabled for this request. Check wms/ows_enable_request settings. + + diff --git a/web/images/layers/previews/geographic/GHGC_Heterotrophic_Respiration.jpg b/web/images/layers/previews/geographic/GHGC_Heterotrophic_Respiration.jpg new file mode 100644 index 0000000000..7d9c05ee4f --- /dev/null +++ b/web/images/layers/previews/geographic/GHGC_Heterotrophic_Respiration.jpg @@ -0,0 +1,6 @@ + + + +msWMSLoadGetMapParams(): WMS server error. Invalid layer(s) given in the LAYERS parameter. A layer might be disabled for this request. Check wms/ows_enable_request settings. + + diff --git a/web/images/layers/previews/geographic/GHGC_Net_Ecosystem_Exchange.jpg b/web/images/layers/previews/geographic/GHGC_Net_Ecosystem_Exchange.jpg new file mode 100644 index 0000000000..7d9c05ee4f --- /dev/null +++ b/web/images/layers/previews/geographic/GHGC_Net_Ecosystem_Exchange.jpg @@ -0,0 +1,6 @@ + + + +msWMSLoadGetMapParams(): WMS server error. Invalid layer(s) given in the LAYERS parameter. A layer might be disabled for this request. Check wms/ows_enable_request settings. + + diff --git a/web/images/layers/previews/geographic/GHGC_Net_Primary_Produnction.jpg b/web/images/layers/previews/geographic/GHGC_Net_Primary_Produnction.jpg new file mode 100644 index 0000000000..7d9c05ee4f --- /dev/null +++ b/web/images/layers/previews/geographic/GHGC_Net_Primary_Produnction.jpg @@ -0,0 +1,6 @@ + + + +msWMSLoadGetMapParams(): WMS server error. Invalid layer(s) given in the LAYERS parameter. A layer might be disabled for this request. Check wms/ows_enable_request settings. + + diff --git a/web/images/layers/previews/geographic/GHGC_Wood_Fuel_Emissions.jpg b/web/images/layers/previews/geographic/GHGC_Wood_Fuel_Emissions.jpg new file mode 100644 index 0000000000..7d9c05ee4f --- /dev/null +++ b/web/images/layers/previews/geographic/GHGC_Wood_Fuel_Emissions.jpg @@ -0,0 +1,6 @@ + + + +msWMSLoadGetMapParams(): WMS server error. Invalid layer(s) given in the LAYERS parameter. A layer might be disabled for this request. Check wms/ows_enable_request settings. + + diff --git a/web/js/map/layerbuilder.js b/web/js/map/layerbuilder.js index a85b5149a7..eeb3455da8 100644 --- a/web/js/map/layerbuilder.js +++ b/web/js/map/layerbuilder.js @@ -54,15 +54,15 @@ export default function mapLayerBuilder(config, cache, store) { * @param {*} attributes * @param {*} wrapLayer */ - const getLayer = (createLayerFunc, def, options, attributes, wrapLayer) => { + const getLayer = async (createLayerFunc, def, options, attributes, wrapLayer) => { const state = store.getState(); - const layer = createLayerFunc(def, options, null, state, attributes); + const layer = await createLayerFunc(def, options, null, state, attributes); layer.wv = attributes; if (!wrapLayer) { return layer; } - const layerNext = createLayerFunc(def, options, 1, state, attributes); - const layerPrior = createLayerFunc(def, options, -1, state, attributes); + const layerNext = await createLayerFunc(def, options, 1, state, attributes); + const layerPrior = await createLayerFunc(def, options, -1, state, attributes); layerPrior.wv = attributes; layerNext.wv = attributes; @@ -593,7 +593,7 @@ export default function mapLayerBuilder(config, cache, store) { return layer; }; - const registerSearch = async (def, options, state) => { + const registerSearchDDV = async (def, options, state) => { const { date } = state; let requestDate; if (options.group === 'activeB') { @@ -679,16 +679,13 @@ export default function mapLayerBuilder(config, cache, store) { return name; }; - const createTitilerLayer = async (def, options, day, state) => { - const { proj: { selected }, date } = state; - const { maxExtent, crs } = selected; - const { r, g, b } = def.bandCombo; - + const buildDdvTileUrlFunction = async (def, options, state) => { const source = config.sources[def.source]; + const { r, g, b } = def.bandCombo; - const searchID = await registerSearch(def, options, state); + const searchID = await registerSearchDDV(def, options, state); - const tileUrlFunction = (tileCoord) => { + return (tileCoord) => { const z = tileCoord[0] - 1; const x = tileCoord[1]; const y = tileCoord[2]; @@ -703,9 +700,85 @@ export default function mapLayerBuilder(config, cache, store) { const urlParams = `mosaic/tiles/${searchID}/WGS1984Quad/${z}/${x}/${y}@1x?post_process=swir&${params.filter((p) => !p.split('=').includes('undefined')).join('&')}`; - return source.url + urlParams; + return `${source.url}${urlParams}`; + }; + }; + + const registerSearchGHGC = async (def, options, state) => { + const { date } = state; + let requestDate; + if (options.group === 'activeB') { + requestDate = date.selectedB; + } else { + requestDate = date.selected; + } + + const formattedDate = util.toISOStringSeconds(requestDate).slice(0, 10); + const BASE_URL = 'https://ghg.center/api/raster'; + const temporalRange = [`${formattedDate}T00:00:00Z`, `${formattedDate}T23:59:59Z`]; + + const collectionsFilter = { + op: 'eq', + args: [{ property: 'collection' }, 'casagfed-carbonflux-monthgrid-v3'], + }; + + const temporalFilter = { + op: 't_intersects', + args: [{ property: 'datetime' }, { interval: temporalRange }], }; + const searchBody = { + 'filter-lang': 'cql2-json', + filter: { + op: 'and', + args: [ + collectionsFilter, + temporalFilter, + ], + }, + }; + + const registerResponse = await fetch(`${BASE_URL}/mosaic/register`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(searchBody), + }); + const registerResponseJSON = await registerResponse.json(); + + const tilesHref = registerResponseJSON.links?.find((link) => link.rel === 'tilejson').href; + + const tilejsonResponse = await fetch(`${tilesHref}?assets=${def.layerName}&colormap_name=${def.colormapName}&rescale=${encodeURI(def.rescale)}`); + const tilejsonResponseJSON = await tilejsonResponse.json(); + + const { name } = tilejsonResponseJSON; + + return name; + }; + + const buildGhgcTileUrlFunction = async (def, options, state) => { + const source = config.sources[def.source]; + + const searchID = await registerSearchGHGC(def, options, state); + + return (tileCoord) => { + const z = tileCoord[0] - 1; + const x = tileCoord[1]; + const y = tileCoord[2]; + + const urlParams = `${searchID}/tiles/WGS1984Quad/${z}/${x}/${y}?assets=${def.layerName}&colormap_name=${def.colormapName}&rescale=${encodeURI(def.rescale)}`; + + return `${source.url}/${urlParams}`; + }; + }; + + const createTitilerLayer = async (def, options, day, state) => { + const { proj: { selected }, date } = state; + const { maxExtent, crs } = selected; + + const tileUrlFunction = def.source === 'DDV' ? await buildDdvTileUrlFunction(def, options, state) : await buildGhgcTileUrlFunction(def, options, state); + const xyzSourceOptions = { crossOrigin: 'anonymous', projection: get(crs), @@ -720,7 +793,7 @@ export default function mapLayerBuilder(config, cache, store) { const layer = new OlLayerTile({ source: xyzSource, className, - minZoom: def.minZoom, + minZoom: def.minZoom || 0, extent: maxExtent, }); @@ -816,19 +889,19 @@ export default function mapLayerBuilder(config, cache, store) { if (!isGranule) { switch (def.type) { case 'wmts': - layer = getLayer(createLayerWMTS, def, options, attributes, wrapLayer); + layer = await getLayer(createLayerWMTS, def, options, attributes, wrapLayer); break; case 'vector': - layer = getLayer(createLayerVector, def, options, attributes, wrapLayer); + layer = await getLayer(createLayerVector, def, options, attributes, wrapLayer); break; case 'wms': - layer = getLayer(createLayerWMS, def, options, attributes, wrapLayer); + layer = await getLayer(createLayerWMS, def, options, attributes, wrapLayer); break; case 'titiler': layer = await getLayer(createTitilerLayer, def, options, attributes, wrapLayer); break; case 'xyz': - layer = getLayer(createXYZLayer, def, options, attributes, wrapLayer); + layer = await getLayer(createXYZLayer, def, options, attributes, wrapLayer); break; default: throw new Error(`Unknown layer type: ${type}`);