=============================== Client-side (local) processing =============================== .. warning:: This is a new experimental feature and API, subject to change. Background ---------- The client-side processing functionality allows to test and use openEO with its processes locally, i.e. without any connection to an openEO back-end. It relies on the projects `openeo-pg-parser-networkx `_, which provides an openEO process graph parsing tool, and `openeo-processes-dask `_, which provides an Xarray and Dask implementation of most openEO processes. Installation ------------ .. note:: This feature requires ``Python>=3.9``. Tested with ``openeo-pg-parser-networkx==2023.5.1`` and ``openeo-processes-dask==2023.7.1``. .. code:: bash pip install openeo[localprocessing] Usage ----- Every openEO process graph relies on data which is typically provided by a cloud infrastructure (the openEO back-end). The client-side processing adds the possibility to read and use local netCDFs, geoTIFFs, ZARR files, and remote STAC Collections or Items for your experiments. STAC Collections and Items ~~~~~~~~~~~~~~~~~~~~~~~~~~ .. warning:: The provided examples using STAC rely on third party STAC Catalogs, we can't guarantee that the urls will remain valid. With the ``load_stac`` process it's possible to load and use data provided by remote or local STAC Collections or Items. The following code snippet loads Sentinel-2 L2A data from a public STAC Catalog, using specific spatial and temporal extent, band name and also properties for cloud coverage. .. code-block:: pycon >>> from openeo.local import LocalConnection >>> local_conn = LocalConnection("./") >>> url = "https://earth-search.aws.element84.com/v1/collections/sentinel-2-l2a" >>> spatial_extent = {"west": 11, "east": 12, "south": 46, "north": 47} >>> temporal_extent = ["2019-01-01", "2019-06-15"] >>> bands = ["red"] >>> properties = {"eo:cloud_cover": dict(lt=50)} >>> s2_cube = local_conn.load_stac(url=url, ... spatial_extent=spatial_extent, ... temporal_extent=temporal_extent, ... bands=bands, ... properties=properties, ... ) >>> s2_cube.execute() dask.array Coordinates: (12/53) * time (time) datetime64[ns] 2019-01-02... id (time) `_. If the code can not handle you special netCDF, you can still modify the function that reads the metadata from it `here `_ and the function that reads the data `here `_. Local Processing ~~~~~~~~~~~~~~~~ Let's start with the provided sample netCDF of Sentinel-2 data: .. code-block:: pycon >>> local_collection = "openeo-localprocessing-data/sample_netcdf/S2_L2A_sample.nc" >>> s2_datacube = local_conn.load_collection(local_collection) >>> # Check if the data is loaded correctly >>> s2_datacube.execute() dask.array Coordinates: * t (t) datetime64[ns] 2022-06-02 2022-06-05 ... 2022-06-27 2022-06-30 * x (x) float64 6.75e+05 6.75e+05 6.75e+05 ... 6.843e+05 6.843e+05 * y (y) float64 5.155e+06 5.155e+06 5.155e+06 ... 5.148e+06 5.148e+06 crs |S1 ... * bands (bands) object 'B04' 'B03' 'B02' 'B08' 'SCL' Attributes: Conventions: CF-1.9 institution: openEO platform - Geotrellis backend: 0.9.5a1 description: title: As you can see in the previous example, we are using a call to execute() which will execute locally the generated openEO process graph. In this case, the process graph consist only in a single load_collection, which performs lazy loading of the data. With this first step you can check if the data is being read correctly by openEO. Looking at the metadata of this netCDF sample, we can see that it contains the bands B04, B03, B02, B08 and SCL. Additionally, we also see that it is composed by more than one element in time and that it covers the month of June 2022. We can now do a simple processing for demo purposes, let's compute the median NDVI in time and visualize the result: .. code:: python b04 = s2_datacube.band("B04") b08 = s2_datacube.band("B08") ndvi = (b08 - b04) / (b08 + b04) ndvi_median = ndvi.reduce_dimension(dimension="t", reducer="median") result_ndvi = ndvi_median.execute() result_ndvi.plot.imshow(cmap="Greens") .. image:: ../_static/images/local/local_ndvi.jpg We can perform the same example using data provided by STAC Collection: .. code:: python from openeo.local import LocalConnection local_conn = LocalConnection("./") url = "https://earth-search.aws.element84.com/v1/collections/sentinel-2-l2a" spatial_extent = {"east": 11.40, "north": 46.52, "south": 46.46, "west": 11.25} temporal_extent = ["2022-06-01", "2022-06-30"] bands = ["red", "nir"] properties = {"eo:cloud_cover": dict(lt=80)} s2_datacube = local_conn.load_stac( url=url, spatial_extent=spatial_extent, temporal_extent=temporal_extent, bands=bands, properties=properties, ) b04 = s2_datacube.band("red") b08 = s2_datacube.band("nir") ndvi = (b08 - b04) / (b08 + b04) ndvi_median = ndvi.reduce_dimension(dimension="time", reducer="median") result_ndvi = ndvi_median.execute()