Skip to content

Commit c2e6e50

Browse files
committed
included the generate file
1 parent a536dd5 commit c2e6e50

File tree

3 files changed

+130
-1
lines changed

3 files changed

+130
-1
lines changed

algorithm_catalog/vito/biopar/openeo_udp/biopar.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@
100100
}
101101
},
102102
"id": "biopar",
103-
"description": "# Biophysical Parameters \n\nCalculate various biophysical parameters for an area defined by a polygon. The result is a raster file\ncontaining the parameter values. A strict CloudMask is applied to avoid cloud contamination.\n\nThe **Leaf Area Index (LAI)** is half the total area of a canopy's green elements \nper unit of horizontal ground area. The satellite-derived value corresponds to the total green LAI \nof all the canopy layers, including the understory, which may represent a very significant \ncontribution, particularly for forests. The LAI distributed by Terrascope is also known as GAI, \nwhich stands for Green Area Index and is related to the green part of the vegetation only\n (i.e. not only the leaves but excluding the non-green parts).\n\nThe **Fraction of Absorbed Photosynthetic Active Radiation (fAPAR)** quantifies the fraction \nof solar radiation absorbed by leaves for photosynthetic activity. It depends on the \ncanopy structure, vegetation element optical properties, atmospheric conditions, and angular \nconfiguration.\n\nThe **Fraction of Vegetation Coverage (fCOVER)** corresponds to the fraction of ground \ncovered by green vegetation. Practically, it quantifies the vegetation's spatial extent.\n\nThe **Canopy Water Content (CWC)** is the water mass per unit ground area and is a key \nvegetation indicator in agriculture and forestry applications.\n\nThe **Canopy Chlorophyll Content (CCC)** is the total chlorophyll content per \nunit ground area in a contiguous group of plants. It is well suited for quantifying canopy \nlevel nitrogen content and gross primary production estimation.\n\n### Methodology\n\nThe methodology used to derive the biophysical parameters from Sentinel-2 is developed by INRA-\nEMMAH. The methodology was initially developed to generate biophysical products from SPOT-\nVEGETATION, ENVISAT-MERIS, SPOT-HRVIR, and LANDSAT-OLI sensors were later adapted for\nSentinel-2. It mainly simulates a comprehensive database of canopy (TOC) reflectances\nbased on observation of vegetation characteristics and illumination geometry. Neural networks are\nthen trained to estimate a number of these canopy characteristics (BIOPARs) from the simulated TOC\nreflectances, along with set corresponding angles defining the observational configuration.\n\n### Quality\n\n [RD1] reports RMSE\nvalues of 0.89 for LAI, 0.05 for FAPAR, 0.4 for FCOVER, 56 \u00c2\u00b5g/cm2 for CCC and 0.03 g/cm2 for CWC, which demonstrate a good performance of the network. FAPAR and FCOVER show the best\nperformance, with higher RMSE values for mid-range values of the product. LAI is well estimated to be up\nto values of LAI=6, and increasing uncertainties with LAI, and thus CCC and CWC are observed because of their\ndependency on LAI. Furthermore, the networks are unbiased between the BIOPAR\nvariables, as expected.\n\n### Links\n\n- [RD1] Weiss, M., Baret, F. (2016). S2ToolBox Level 2 products: LAI, FAPAR, FCOVER, version\n1.1, 02/05/2016. http://step.esa.int/docs/extra/ATBD_S2ToolBox_L2B_V1.1.pdf",
103+
"description": "# Biophysical Parameters \n\nCalculate various biophysical parameters for an area defined by a polygon. The result is a raster file\ncontaining the parameter values. A strict CloudMask is applied to avoid cloud contamination.\n\nThe **Leaf Area Index (LAI)** is half the total area of a canopy's green elements \nper unit of horizontal ground area. The satellite-derived value corresponds to the total green LAI \nof all the canopy layers, including the understory, which may represent a very significant \ncontribution, particularly for forests. The LAI distributed by Terrascope is also known as GAI, \nwhich stands for Green Area Index and is related to the green part of the vegetation only\n (i.e. not only the leaves but excluding the non-green parts).\n\nThe **Fraction of Absorbed Photosynthetic Active Radiation (fAPAR)** quantifies the fraction \nof solar radiation absorbed by leaves for photosynthetic activity. It depends on the \ncanopy structure, vegetation element optical properties, atmospheric conditions, and angular \nconfiguration.\n\nThe **Fraction of Vegetation Coverage (fCOVER)** corresponds to the fraction of ground \ncovered by green vegetation. Practically, it quantifies the vegetation's spatial extent.\n\nThe **Canopy Water Content (CWC)** is the water mass per unit ground area and is a key \nvegetation indicator in agriculture and forestry applications.\n\nThe **Canopy Chlorophyll Content (CCC)** is the total chlorophyll content per \nunit ground area in a contiguous group of plants. It is well suited for quantifying canopy \nlevel nitrogen content and gross primary production estimation.\n\n### Methodology\n\nThe methodology used to derive the biophysical parameters from Sentinel-2 is developed by INRA-\nEMMAH. The methodology was initially developed to generate biophysical products from SPOT-\nVEGETATION, ENVISAT-MERIS, SPOT-HRVIR, and LANDSAT-OLI sensors were later adapted for\nSentinel-2. It mainly simulates a comprehensive database of canopy (TOC) reflectances\nbased on observation of vegetation characteristics and illumination geometry. Neural networks are\nthen trained to estimate a number of these canopy characteristics (BIOPARs) from the simulated TOC\nreflectances, along with set corresponding angles defining the observational configuration.\n\n### Quality\n\n [RD1] reports RMSE\nvalues of 0.89 for LAI, 0.05 for FAPAR, 0.4 for FCOVER, 56 µg/cm2 for CCC and 0.03 g/cm2 for CWC, which demonstrate a good performance of the network. FAPAR and FCOVER show the best\nperformance, with higher RMSE values for mid-range values of the product. LAI is well estimated to be up\nto values of LAI=6, and increasing uncertainties with LAI, and thus CCC and CWC are observed because of their\ndependency on LAI. Furthermore, the networks are unbiased between the BIOPAR\nvariables, as expected.\n\n### Links\n\n- [RD1] Weiss, M., Baret, F. (2016). S2ToolBox Level 2 products: LAI, FAPAR, FCOVER, version\n1.1, 02/05/2016. http://step.esa.int/docs/extra/ATBD_S2ToolBox_L2B_V1.1.pdf",
104104
"parameters": [
105105
{
106106
"name": "spatial_extent",
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
from functools import lru_cache
2+
import numpy as np
3+
from typing import Dict
4+
from openeo.udf.xarraydatacube import XarrayDataCube
5+
from openeo.udf.debug import inspect
6+
from biopar.bioparnp import BioParNp
7+
8+
@lru_cache(maxsize=6)
9+
def get_bioparrun(biopar) -> BioParNp:
10+
return BioParNp(version='3band', parameter=biopar, singleConfig = True)
11+
12+
def apply_datacube(cube: XarrayDataCube, context: Dict) -> XarrayDataCube:
13+
valid_biopars= ['FAPAR','LAI','FCOVER','CWC','CCC']
14+
biopar = context.get('biopar_type', 'FAPAR')
15+
if biopar not in valid_biopars:
16+
biopar = 'FAPAR'
17+
inspect(biopar, "is not in valid Biopar list, defaulting to FAPAR")
18+
19+
inarr = cube.get_array()
20+
ds_date = inarr
21+
22+
from numpy import cos, radians
23+
scaling_bands = 0.0001
24+
25+
saa = ds_date.sel(bands='sunAzimuthAngles')
26+
sza = ds_date.sel(bands='sunZenithAngles')
27+
vaa = ds_date.sel(bands='viewAzimuthMean')
28+
vza = ds_date.sel(bands='viewZenithMean')
29+
30+
B03 = ds_date.sel(bands='B03') * scaling_bands
31+
B04 = ds_date.sel(bands='B04') * scaling_bands
32+
B8 = ds_date.sel(bands='B08') * scaling_bands
33+
g1 = cos(radians(vza))
34+
g2 = cos(radians(sza))
35+
g3 = cos(radians(saa - vaa))
36+
#### FLATTEN THE ARRAY ####
37+
flat = list(map(lambda arr: arr.flatten(), [B03.values, B04.values,B8.values, g1.values, g2.values, g3.values]))
38+
bands = np.array(flat)
39+
40+
# inspect the parameter passed
41+
inspect(biopar, "biopar parameter passed to the UDF")
42+
43+
#### CALCULATE THE BIOPAR BASED ON THE BANDS #####
44+
image = get_bioparrun(biopar).run(bands, output_scale=1,output_dtype=np.float32,minmax_flagging=False) # netcdf algorithm
45+
as_image = image.reshape((g1.shape))
46+
## set nodata to nan
47+
as_image[np.where(np.isnan(B03))] = np.nan
48+
xr_biopar = vza.copy()
49+
xr_biopar.values = as_image
50+
51+
return XarrayDataCube(xr_biopar) # xarray.DataArray(as_image,vza.dims,vza.coords)'''
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import json
2+
from pathlib import Path
3+
4+
import openeo
5+
from openeo.api.process import Parameter
6+
from openeo.rest.udp import build_process_dict
7+
8+
def generate():
9+
connection = openeo.connect("openeofed.dataspace.copernicus.eu").authenticate_oidc()
10+
11+
spatial_extent = Parameter.spatial_extent(
12+
name="spatial_extent",
13+
description="Limits the data to process to the specified bounding box or polygons.\\n\\nFor raster data, the process loads the pixel into the data cube if the point at the pixel center intersects with the bounding box or any of the polygons (as defined in the Simple Features standard by the OGC).\\nFor vector data, the process loads the geometry into the data cube if the geometry is fully within the bounding box or any of the polygons (as defined in the Simple Features standard by the OGC). Empty geometries may only be in the data cube if no spatial extent has been provided.\\n\\nEmpty geometries are ignored.\\nSet this parameter to null to set no limit for the spatial extent."
14+
)
15+
16+
temporal_extent = Parameter.temporal_interval(
17+
name="temporal_extent",
18+
description="Temporal extent specified as two-element array with start and end date/date-time."
19+
)
20+
biopar_type = Parameter.string(
21+
name="biopar_type",
22+
description="BIOPAR type [FAPAR,LAI,FCOVER,CCC,CWC]",
23+
default="FAPAR",
24+
values=["FAPAR", "LAI", "FCOVER", "CCC", "CWC"],
25+
)
26+
27+
cube = connection.load_collection(
28+
collection_id="SENTINEL2_L2A",
29+
bands=[
30+
"B03",
31+
"B04",
32+
"B08",
33+
"sunAzimuthAngles",
34+
"sunZenithAngles",
35+
"viewAzimuthMean",
36+
"viewZenithMean"
37+
],
38+
temporal_extent=temporal_extent,
39+
spatial_extent=spatial_extent,
40+
)
41+
scl = connection.load_collection(
42+
collection_id="SENTINEL2_L2A",
43+
bands=["SCL"],
44+
temporal_extent=temporal_extent,
45+
spatial_extent=spatial_extent,
46+
)
47+
48+
mask = scl.process("to_scl_dilation_mask", data=scl)
49+
cube = cube.mask(mask)
50+
51+
udf = openeo.UDF.from_file(
52+
Path(__file__).parent / "biopar_udf.py",
53+
runtime="Python",
54+
context={"biopar_type": {"from_parameter": "biopar_type"}},
55+
)
56+
# print(udf)
57+
biopar = cube.reduce_dimension(
58+
dimension="bands",
59+
reducer=udf,
60+
)
61+
biopar = biopar.add_dimension("bands", label=biopar_type, type="bands")
62+
63+
64+
return build_process_dict(
65+
process_graph=biopar,
66+
process_id="biopar",
67+
description=(Path(__file__).parent / "README.md").read_text(),
68+
parameters=[
69+
spatial_extent,
70+
temporal_extent,
71+
biopar_type,
72+
]
73+
)
74+
75+
76+
if __name__ == "__main__":
77+
with open("biopar_apex.json", "w") as f:
78+
json.dump(generate(), f, indent=2)

0 commit comments

Comments
 (0)