openEO Platform DEMO

OpenEO Platform logo

openEO Platform DEMO#

Land Cover change over an alpine region using Client Side Processing

Import the necessary modules fro openEO Client Side Processing

from openeo.local import LocalConnection
local_conn = LocalConnection("./")

Have a look at the collection#

We will use a collection from Microsoft Planetary Computer:

10m Annual Land Use Land Cover (9-class)

https://planetarycomputer.microsoft.com/dataset/io-lulc-9-class

url      = "https://planetarycomputer.microsoft.com/api/stac/v1/collections/io-lulc-9-class"

spatial_extent = {"west": 12.1783447265625,
                  "south": 46.9061837801476,
                  "east": 13.50151062011719,
                  "north": 47.093500502407764}

iulc_9_class_2017 = local_conn.load_stac(url = url,
                             spatial_extent = spatial_extent,
                             temporal_extent = ["2017-01-01", "2017-01-02"]
                            )

# We need to select this temporal internal (2023-01) to get the 2022 data due to how this particular collection is stored in STAC.
# You can experiment changing temporal_extent and check the outout of iulc_9_class_2022.execute()
iulc_9_class_2022 = local_conn.load_stac(url = url,
                             spatial_extent = spatial_extent,
                             temporal_extent = ["2023-01-01", "2023-01-02"]
                            )
C:\Users\mclaus\Miniconda3\envs\stacenv\lib\site-packages\stackstac\prepare.py:408: UserWarning: The argument 'infer_datetime_format' is deprecated and will be removed in a future version. A strict version of it is now the default, see https://pandas.pydata.org/pdeps/0004-consistent-to-datetime-parsing.html. You can safely remove this argument.
  times = pd.to_datetime(
C:\Users\mclaus\Miniconda3\envs\stacenv\lib\site-packages\stackstac\prepare.py:408: UserWarning: The argument 'infer_datetime_format' is deprecated and will be removed in a future version. A strict version of it is now the default, see https://pandas.pydata.org/pdeps/0004-consistent-to-datetime-parsing.html. You can safely remove this argument.
  times = pd.to_datetime(
iulc_2017 = iulc_9_class_2017.drop_dimension("time").drop_dimension("band").add_dimension(type="bands",name="bands",label="iulc_2017")
iulc_2022 = iulc_9_class_2022.drop_dimension("time").drop_dimension("band").add_dimension(type="bands",name="bands",label="iulc_2022")
iulc_2017_2022 = iulc_2017.merge_cubes(iulc_2022)

The IULC class for “Snow and Ice” is reflected by the values which are equal to 9.

snow_and_ice = iulc_2017_2022.apply(lambda x: x.eq(9))

Compute the difference between the different snow and ice maps:

def compute_difference(data):
    snow_and_ice_2017 = data.array_element(0)
    snow_and_ice_2022 = data.array_element(1)
    return snow_and_ice_2022 - snow_and_ice_2017
    
snow_and_ice_difference = snow_and_ice.reduce_dimension(reducer=compute_difference,dimension="bands").add_dimension(type="bands",name="bands",label="diff")

Merge all in one datacube and visualiza the final process graph:

snow_and_ice_2017_2022_diff = snow_and_ice.merge_cubes(snow_and_ice_difference)
snow_and_ice_2017_2022_diff

Get the result as an Dask based xArray object:

snow_and_ice_2017_2022_diff_xr = snow_and_ice_2017_2022_diff.execute()
snow_and_ice_2017_2022_diff_xr
C:\Users\mclaus\Miniconda3\envs\stacenv\lib\site-packages\stackstac\prepare.py:408: UserWarning: The argument 'infer_datetime_format' is deprecated and will be removed in a future version. A strict version of it is now the default, see https://pandas.pydata.org/pdeps/0004-consistent-to-datetime-parsing.html. You can safely remove this argument.
  times = pd.to_datetime(
C:\Users\mclaus\Miniconda3\envs\stacenv\lib\site-packages\stackstac\prepare.py:408: UserWarning: The argument 'infer_datetime_format' is deprecated and will be removed in a future version. A strict version of it is now the default, see https://pandas.pydata.org/pdeps/0004-consistent-to-datetime-parsing.html. You can safely remove this argument.
  times = pd.to_datetime(
<xarray.DataArray (bands: 3, y: 2359, x: 10116)>
dask.array<getitem, shape=(3, 2359, 10116), dtype=float64, chunksize=(1, 1024, 1024), chunktype=numpy.ndarray>
Coordinates: (12/15)
  * x                (x) float64 2.851e+05 2.851e+05 ... 3.863e+05 3.863e+05
  * y                (y) float64 5.219e+06 5.219e+06 ... 5.196e+06 5.196e+06
  * bands            (bands) <U9 'iulc_2017' 'iulc_2022' 'diff'
    id               <U8 '33T-2017'
    io:tile_id       <U3 '33T'
    proj:bbox        object {756097.7729520155, 243907.7729520155, 5320646.33...
    ...               ...
    proj:epsg        int32 32633
    proj:transform   object {0.0, 243907.7729520155, 5320646.335981226, 10.0,...
    start_datetime   <U20 '2017-01-01T00:00:00Z'
    raster:bands     object {'nodata': 0, 'spatial_resolution': 10}
    file:size        int32 165589758
    epsg             int32 32633
Attributes:
    reduced_dimensions_min_values:  {'bands': 'iulc_2017'}

Compute the values from the Dask based xArray objects for visualization:

data_2017 = snow_and_ice_2017_2022_diff_xr.sel(bands="iulc_2017")
data_2022 = snow_and_ice_2017_2022_diff_xr.sel(bands="iulc_2022")
data_diff = snow_and_ice_2017_2022_diff_xr.sel(bands="diff")

iulc_9_class_2017 = data_2017.values
iulc_9_class_2022 = data_2022.values
diff = data_diff.values

Compute some statistics on the data:

import numpy as np

diff = iulc_9_class_2017 - iulc_9_class_2022
print("Glaciers and perpetual snow in 2017: ", np.sum(iulc_9_class_2017))
print("Glaciers and perpetual snow in 2022:  ", np.sum(iulc_9_class_2022))
Glaciers and perpetual snow in 2017:  3474257.0
Glaciers and perpetual snow in 2022:   1760962.0

You could also perform the count operation directly in openEO:

snow_and_ice_2017_2022_diff_sum = snow_and_ice_2017_2022_diff.reduce_spatial(reducer="sum")
print(snow_and_ice_2017_2022_diff_sum.execute().sel(bands="iulc_2017").values)
C:\Users\mclaus\Miniconda3\envs\stacenv\lib\site-packages\stackstac\prepare.py:408: UserWarning: The argument 'infer_datetime_format' is deprecated and will be removed in a future version. A strict version of it is now the default, see https://pandas.pydata.org/pdeps/0004-consistent-to-datetime-parsing.html. You can safely remove this argument.
  times = pd.to_datetime(
C:\Users\mclaus\Miniconda3\envs\stacenv\lib\site-packages\stackstac\prepare.py:408: UserWarning: The argument 'infer_datetime_format' is deprecated and will be removed in a future version. A strict version of it is now the default, see https://pandas.pydata.org/pdeps/0004-consistent-to-datetime-parsing.html. You can safely remove this argument.
  times = pd.to_datetime(
3474257.0

Visualize the Glaciers and perpetual snow map for two different years and the differece:

import matplotlib.pyplot as plt

plt.figure(figsize=(24,10))

plt.subplot(3,1,1)
plt.title("2017-01-01")
plt.imshow(iulc_9_class_2017, cmap = "RdBu")
# plt.colorbar()

plt.subplot(3,1,2)
plt.title("2022-01-01")
plt.imshow(iulc_9_class_2022, cmap = "RdBu")
# plt.colorbar()

plt.subplot(3,1,3)
plt.title("Difference")
plt.imshow(diff, cmap = "coolwarm")
# plt.colorbar()
<matplotlib.image.AxesImage at 0x19b019a7df0>
../_images/eb80e246d69fc312d2248029e0f78d5194da053d70e418361ffa3a6aa8c263ec.png