Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NATMAP Soil carbon on map view #459

Merged
merged 1 commit into from
Dec 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions app/javascript/projects/layer_palette.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { IMDProperties } from './reify_layer/imd'
import { ProjectPermissions } from './project_editor'
import { KewPointOptions } from './reify_layer/kew'
import { seasonYearOptions } from './modelling/components/kew_samples_component'
import { natmap_outputs } from './modelling/components/natmap_soil_component'

interface AddLayerButtonProps {
prototype: Layer
Expand Down Expand Up @@ -330,6 +331,25 @@ export const LayerPalette = ({ addLayer, hide, dbModels, getTeamDatasets, teamNa
/>)
}
</Section>
{
permissions.NATMAPSoil &&
<Section title="Natmap Soil">
<AddLayerButton
addLayer={addLayer}
prototype={{
type: "WFSLayer",
name: "Natmap Soil Carbon",
layer: "cranfield_soil:NATMAPcarbon",
attribution: "Cranfield University",
propIdx: 0,
visible: true,
opacity: 1,
fill: "jet"
}}
/>

</Section>
}
{
dbModels.overlays.length > 0 &&
<Section title="Overlays">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,134 +15,172 @@ interface NatmapSoilOptions extends SelectControlOptions {
key: string
socket: Socket
unit: string
min: number
max: number
}

const natmap_outputs : NatmapSoilOptions[] = [
export const natmap_outputs : NatmapSoilOptions[] = [
{
id: 0,
name: 'Min Carbon stock 0-10cm (kg/m²)',
key: 'MIN_STK_10',
socket: numericDataSocket,
unit: 'kg/m^2'
unit: 'kg/m^2',
min: 0,
max: 82.32000000000
},
{
id: 1,
name: 'Max Carbon stock 0-10cm (kg/m²)',
key: 'MAX_STK_10',
socket: numericDataSocket,
unit: 'kg/m^2'
unit: 'kg/m^2',
min: 0,
max: 95.13000000000
},
{
id: 2,
name: 'Min Carbon stock 0-15cm (kg/m²)',
key: 'MIN_STK_15',
socket: numericDataSocket,
unit: 'kg/m^2'
unit: 'kg/m^2',
min: 0,
max: 59.64000000000
},
{
id: 3,
name: 'Max Carbon stock 0-15cm (kg/m²)',
key: 'MAX_STK_15',
socket: numericDataSocket,
unit: 'kg/m^2'
unit: 'kg/m^2',
min: 0,
max: 59.64000000000
},
{
id: 4,
name: 'Min Carbon stock 0-30cm (kg/m²)',
key: 'MIN_STK_30',
socket: numericDataSocket,
unit: 'kg/m^2'
unit: 'kg/m^2',
min: 0,
max: 35.45000000000
},
{
id: 5,
name: 'Max Carbon stock 0-30cm (kg/m²)',
key: 'MAX_STK_30',
socket: numericDataSocket,
unit: 'kg/m^2'
unit: 'kg/m^2',
min: 0,
max: 63.23000000000
},
{
id: 6,
name: 'Average Carbon stock 0-30cm (kg/m²)',
key: 'AV_STK_30',
socket: numericDataSocket,
unit: 'kg/m^2'
unit: 'kg/m^2',
min: 0,
max: 51.07000000000
},
{
id: 7,
name: 'Average Carbon stock 30-100cm (kg/m²)',
key: 'AV_STK_100',
socket: numericDataSocket,
unit: 'kg/m^2'
unit: 'kg/m^2',
min: 0,
max: 86.19000000000
},
{
id: 8,
name: 'Average Carbon stock 100-150cm (kg/m²)',
key: 'AV_STK_150',
socket: numericDataSocket,
unit: 'kg/m^2'
unit: 'kg/m^2',
min: 0,
max: 59.64000000000
},
{
id: 9,
name: 'Average Organic Carbon 0-30cm (%)',
key: 'AV_OC_30',
socket: numericDataSocket,
unit: '%'
unit: '%',
min: 0,
max: 100
},
{
id: 10,
name: 'Min Organic Carbon 0-30cm (%)',
key: 'MIN_OC_30',
socket: numericDataSocket,
unit: '%'
unit: '%',
min: 0,
max: 100
},
{
id: 11,
name: 'Max Organic Carbon 0-30cm (%)',
key: 'MAX_OC_30',
socket: numericDataSocket,
unit: '%'
unit: '%',
min: 0,
max: 100
},
{
id: 12,
name: 'Average Organic Carbon 30-100cm (%)',
key: 'AV_OC_100',
socket: numericDataSocket,
unit: '%'
unit: '%',
min: 0,
max: 100
},
{
id: 13,
name: 'Min Organic Carbon 30-100cm (%)',
key: 'MIN_OC_100',
socket: numericDataSocket,
unit: '%'
unit: '%',
min: 0,
max: 100
},
{
id: 14,
name: 'Max Organic Carbon 30-100cm (%)',
key: 'MAX_OC_100',
socket: numericDataSocket,
unit: '%'
unit: '%',
min: 0,
max: 100
},
{
id: 15,
name: 'Average Organic Carbon 100-150cm (%)',
key: 'AV_OC_150',
socket: numericDataSocket,
unit: '%'
unit: '%',
min: 0,
max: 100
},
{
id: 16,
name: 'Min Organic Carbon 100-150cm (%)',
key: 'MIN_OC_150',
socket: numericDataSocket,
unit: '%'
unit: '%',
min: 0,
max: 100
},
{
id: 17,
name: 'Max Organic Carbon 100-150cm (%)',
key: 'MAX_OC_150',
socket: numericDataSocket,
unit: '%'
unit: '%',
min: 0,
max: 100
}

]
Expand Down
2 changes: 2 additions & 0 deletions app/javascript/projects/reify_layer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { reifyGeoserverWMSLayer } from './geoserver'
import { reifyKewLayer, reifyKewPointLayer } from './kew'
import { reifyOrvalLayer } from './orval'
import { reifyIMDLayer } from './imd'
import { reifyWFSLayer } from './wfs'

export const reifyLayer = (layer: Layer, existingLayer: BaseLayer | null, dbModels: DBModels, map: Map, modelOutputCache: ModelOutputCache, DatasetCache: DatasetCache, loadteamDataset: (layer: DatasetLayer) => void): BaseLayer => {
const layerType = layer.type
Expand All @@ -38,6 +39,7 @@ export const reifyLayer = (layer: Layer, existingLayer: BaseLayer | null, dbMode
case "ORValLayer": return reifyOrvalLayer(layer, existingLayer, map)
case "IMDLayer": return reifyIMDLayer(layer, existingLayer, map)
case "KewPointLayer": return reifyKewPointLayer(layer, existingLayer, map)
case "WFSLayer": return reifyWFSLayer(layer, existingLayer, map)
default: {
// Ensure this switch statement is exhaustive
const unreachable: never = layerType
Expand Down
60 changes: 60 additions & 0 deletions app/javascript/projects/reify_layer/wfs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import BaseLayer from "ol/layer/Base"
import { WFSLayer } from "../state"
import GeoJSON from "ol/format/GeoJSON"
import Map from "ol/Map"
import VectorLayer from "ol/layer/Vector"
import { memoize } from "lodash"
import VectorSource from "ol/source/Vector"
import { bbox } from "ol/loadingstrategy"
import { Fill, Stroke, Style } from "ol/style"
import { natmap_outputs } from "../modelling/components/natmap_soil_component"
import { findColor } from "../analysis_panel_tools/subsection"
import { getColorStops } from "./model_output"

const getSource = memoize((id: string, attribution: undefined | string) => {

const store = id.split(":")[0]

const source = new VectorSource({
url: extent => `https://landscapes.wearepal.ai/geoserver/${store}/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=${id}&outputFormat=application/json&bbox=${extent.join(',')},EPSG:3857&crs=EPSG:3857`,
format: new GeoJSON({
extractGeometryName: true
}),
strategy: bbox,
attributions: attribution
})

return source

})

const getStyle = (layer: WFSLayer, colMap: any[]) => (
(feature) => {

const propIdx = layer.propIdx
const prop = natmap_outputs[propIdx]
const val = feature.get(prop.key)
const [min, max] = [prop.min, prop.max]

const normalisedValue = prop.min > prop.max ? 1 - (val - min) / (max - min) : (val - min) / (max - min)
const col = findColor(normalisedValue, colMap)

return new Style({
fill: new Fill({ color: `rgba(${col[0]}, ${col[1]}, ${col[2]}, 1)`})
})

}
)

export function reifyWFSLayer (layer: WFSLayer, existingLayer: BaseLayer | null, map: Map) {

const colMap = getColorStops(layer.fill === "heatmap" ? "jet" : (layer.fill === "greyscale" ? "greys" : layer.fill), 100).reverse()

const vectLayer = new VectorLayer({
source: getSource(layer.layer, layer.attribution),
style: getStyle(layer, colMap),
})

return vectLayer

}
Loading
Loading