openeo-gfmap 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. openeo_gfmap/__init__.py +23 -0
  2. openeo_gfmap/backend.py +122 -0
  3. openeo_gfmap/features/__init__.py +17 -0
  4. openeo_gfmap/features/feature_extractor.py +389 -0
  5. openeo_gfmap/fetching/__init__.py +21 -0
  6. openeo_gfmap/fetching/commons.py +213 -0
  7. openeo_gfmap/fetching/fetching.py +98 -0
  8. openeo_gfmap/fetching/generic.py +165 -0
  9. openeo_gfmap/fetching/meteo.py +126 -0
  10. openeo_gfmap/fetching/s1.py +195 -0
  11. openeo_gfmap/fetching/s2.py +236 -0
  12. openeo_gfmap/inference/__init__.py +3 -0
  13. openeo_gfmap/inference/model_inference.py +347 -0
  14. openeo_gfmap/manager/__init__.py +31 -0
  15. openeo_gfmap/manager/job_manager.py +469 -0
  16. openeo_gfmap/manager/job_splitters.py +144 -0
  17. openeo_gfmap/metadata.py +24 -0
  18. openeo_gfmap/preprocessing/__init__.py +22 -0
  19. openeo_gfmap/preprocessing/cloudmasking.py +268 -0
  20. openeo_gfmap/preprocessing/compositing.py +74 -0
  21. openeo_gfmap/preprocessing/interpolation.py +12 -0
  22. openeo_gfmap/preprocessing/sar.py +64 -0
  23. openeo_gfmap/preprocessing/scaling.py +65 -0
  24. openeo_gfmap/preprocessing/udf_cldmask.py +36 -0
  25. openeo_gfmap/preprocessing/udf_rank.py +37 -0
  26. openeo_gfmap/preprocessing/udf_score.py +103 -0
  27. openeo_gfmap/spatial.py +53 -0
  28. openeo_gfmap/stac/__init__.py +2 -0
  29. openeo_gfmap/stac/constants.py +51 -0
  30. openeo_gfmap/temporal.py +22 -0
  31. openeo_gfmap/utils/__init__.py +23 -0
  32. openeo_gfmap/utils/build_df.py +48 -0
  33. openeo_gfmap/utils/catalogue.py +248 -0
  34. openeo_gfmap/utils/intervals.py +64 -0
  35. openeo_gfmap/utils/netcdf.py +25 -0
  36. openeo_gfmap/utils/tile_processing.py +64 -0
  37. openeo_gfmap-0.1.0.dist-info/METADATA +57 -0
  38. openeo_gfmap-0.1.0.dist-info/RECORD +40 -0
  39. openeo_gfmap-0.1.0.dist-info/WHEEL +4 -0
  40. openeo_gfmap-0.1.0.dist-info/licenses/LICENSE +201 -0
@@ -0,0 +1,195 @@
1
+ """ Collection fetching of S1 features, supporting different backends.
2
+ """
3
+
4
+ from functools import partial
5
+ from typing import Callable
6
+
7
+ import openeo
8
+ from geojson import GeoJSON
9
+
10
+ from openeo_gfmap.backend import Backend, BackendContext
11
+ from openeo_gfmap.spatial import SpatialContext
12
+ from openeo_gfmap.temporal import TemporalContext
13
+
14
+ from .commons import (
15
+ _load_collection,
16
+ convert_band_names,
17
+ rename_bands,
18
+ resample_reproject,
19
+ )
20
+ from .fetching import CollectionFetcher, FetchType
21
+
22
+ BASE_SENTINEL1_GRD_MAPPING = {
23
+ "VH": "S1-SIGMA0-VH",
24
+ "HH": "S1-SIGMA0-HH",
25
+ "HV": "S1-SIGMA0-HV",
26
+ "VV": "S1-SIGMA0-VV",
27
+ }
28
+
29
+
30
+ def _get_s1_grd_default_fetcher(
31
+ collection_name: str, fetch_type: FetchType
32
+ ) -> Callable:
33
+ """Return a default fetcher for Sentinel-1 GRD data.
34
+
35
+ Parameters
36
+ ----------
37
+ collection_name : str
38
+ The name of the sentinel1 collection to fetch as named in the backend.
39
+ fetch_type : FetchType
40
+ The type of fetching: TILE, POINT and POLYGON.
41
+ """
42
+
43
+ def s1_grd_fetch_default(
44
+ connection: openeo.Connection,
45
+ spatial_extent: SpatialContext,
46
+ temporal_extent: TemporalContext,
47
+ bands: list,
48
+ **params,
49
+ ) -> openeo.DataCube:
50
+ """Default collection fetcher for Sentinel-1 GRD collections. The
51
+ collection values are expected to be expressed in power values.
52
+ Parameters
53
+ ----------
54
+ connection: openeo.Connection
55
+ Connection to a general backend.
56
+ spatial_extent: SpatialContext
57
+ Either a GeoJSON collection or a bounding box of locations.
58
+ Performs spatial filtering if the spatial context is a GeoJSON
59
+ collection, as it implies sparse data.
60
+ temporal_extent: TemporalContexct
61
+ A time range, defined by a start and end date.
62
+ bands: list
63
+ The name of the bands to load from that collection
64
+ Returns
65
+ ------
66
+ openeo.DataCube: a datacube containing the collection raw products.
67
+ """
68
+ bands = convert_band_names(bands, BASE_SENTINEL1_GRD_MAPPING)
69
+
70
+ load_collection_parameters = params.get("load_collection", {})
71
+
72
+ cube = _load_collection(
73
+ connection,
74
+ bands,
75
+ collection_name,
76
+ spatial_extent,
77
+ temporal_extent,
78
+ fetch_type,
79
+ **load_collection_parameters,
80
+ )
81
+
82
+ if fetch_type is not FetchType.POINT and isinstance(spatial_extent, GeoJSON):
83
+ cube = cube.filter_spatial(spatial_extent)
84
+
85
+ return cube
86
+
87
+ return s1_grd_fetch_default
88
+
89
+
90
+ def _get_s1_grd_default_processor(
91
+ collection_name: str, fetch_type: FetchType, backend: Backend
92
+ ) -> Callable:
93
+ """Builds the preprocessing function from the collection name as it is stored
94
+ in the target backend.
95
+ """
96
+
97
+ def s1_grd_default_processor(cube: openeo.DataCube, **params):
98
+ """Default collection preprocessing method.
99
+ This method performs:
100
+
101
+ * Compute the backscatter of all the S1 products. By default, the
102
+ "sigma0-ellipsoid" method is used with "COPERNICUS_30" DEM, but those
103
+ can be changed by specifying "coefficient" and "elevation_model" in
104
+ params.
105
+ * Resampling to 10m resolution.
106
+ * Reprojection if a "target_crs" key is specified in `params`.
107
+ * Performs value rescaling to uint16.
108
+ """
109
+ elevation_model = params.get("elevation_model", "COPERNICUS_30")
110
+ coefficient = params.get("coefficient", "sigma0-ellipsoid")
111
+
112
+ cube = cube.sar_backscatter(
113
+ elevation_model=elevation_model,
114
+ coefficient=coefficient,
115
+ local_incidence_angle=False,
116
+ )
117
+
118
+ # Reproject collection data to target CRS and resolution, if specified so.
119
+ # Can be disabled by setting target_resolution=None in the parameters
120
+ if params.get("target_resolution", True) is not None:
121
+ cube = resample_reproject(
122
+ cube,
123
+ params.get("target_resolution", 10.0),
124
+ params.get("target_crs", None),
125
+ method=params.get("resampling_method", "near"),
126
+ )
127
+ elif params.get("target_crs") is not None:
128
+ raise ValueError(
129
+ "In fetching parameters: `target_crs` specified but not `target_resolution`, which is required to perform reprojection."
130
+ )
131
+
132
+ # Harmonizing the collection band names to the default GFMAP band names
133
+ cube = rename_bands(cube, BASE_SENTINEL1_GRD_MAPPING)
134
+
135
+ return cube
136
+
137
+ return s1_grd_default_processor
138
+
139
+
140
+ SENTINEL1_GRD_BACKEND_MAP = {
141
+ Backend.TERRASCOPE: {
142
+ "default": partial(
143
+ _get_s1_grd_default_fetcher, collection_name="SENTINEL1_GRD"
144
+ ),
145
+ "preprocessor": partial(
146
+ _get_s1_grd_default_processor,
147
+ collection_name="SENTINEL1_GRD",
148
+ backend=Backend.TERRASCOPE,
149
+ ),
150
+ },
151
+ Backend.CDSE: {
152
+ "default": partial(
153
+ _get_s1_grd_default_fetcher, collection_name="SENTINEL1_GRD"
154
+ ),
155
+ "preprocessor": partial(
156
+ _get_s1_grd_default_processor,
157
+ collection_name="SENTINEL1_GRD",
158
+ backend=Backend.CDSE,
159
+ ),
160
+ },
161
+ Backend.CDSE_STAGING: {
162
+ "default": partial(
163
+ _get_s1_grd_default_fetcher, collection_name="SENTINEL1_GRD"
164
+ ),
165
+ "preprocessor": partial(
166
+ _get_s1_grd_default_processor,
167
+ collection_name="SENTINEL1_GRD",
168
+ backend=Backend.CDSE_STAGING,
169
+ ),
170
+ },
171
+ Backend.FED: {
172
+ "default": partial(
173
+ _get_s1_grd_default_fetcher, collection_name="SENTINEL1_GRD"
174
+ ),
175
+ "preprocessor": partial(
176
+ _get_s1_grd_default_processor,
177
+ collection_name="SENTINEL1_GRD",
178
+ backend=Backend.FED,
179
+ ),
180
+ },
181
+ }
182
+
183
+
184
+ def build_sentinel1_grd_extractor(
185
+ backend_context: BackendContext, bands: list, fetch_type: FetchType, **params
186
+ ) -> CollectionFetcher:
187
+ """Creates a S1 GRD collection extractor for the given backend."""
188
+ backend_functions = SENTINEL1_GRD_BACKEND_MAP.get(backend_context.backend)
189
+
190
+ fetcher, preprocessor = (
191
+ backend_functions["default"](fetch_type=fetch_type),
192
+ backend_functions["preprocessor"](fetch_type=fetch_type),
193
+ )
194
+
195
+ return CollectionFetcher(backend_context, bands, fetcher, preprocessor, **params)
@@ -0,0 +1,236 @@
1
+ """ Extraction of S2 features, supporting different backends.
2
+ """
3
+
4
+ from functools import partial
5
+ from typing import Callable
6
+
7
+ import openeo
8
+ from geojson import GeoJSON
9
+
10
+ from openeo_gfmap.backend import Backend, BackendContext
11
+ from openeo_gfmap.metadata import FakeMetadata
12
+ from openeo_gfmap.spatial import BoundingBoxExtent, SpatialContext
13
+ from openeo_gfmap.temporal import TemporalContext
14
+
15
+ from .commons import (
16
+ _load_collection,
17
+ convert_band_names,
18
+ rename_bands,
19
+ resample_reproject,
20
+ )
21
+ from .fetching import CollectionFetcher, FetchType
22
+
23
+ BASE_SENTINEL2_L2A_MAPPING = {
24
+ "B01": "S2-L2A-B01",
25
+ "B02": "S2-L2A-B02",
26
+ "B03": "S2-L2A-B03",
27
+ "B04": "S2-L2A-B04",
28
+ "B05": "S2-L2A-B05",
29
+ "B06": "S2-L2A-B06",
30
+ "B07": "S2-L2A-B07",
31
+ "B08": "S2-L2A-B08",
32
+ "B8A": "S2-L2A-B8A",
33
+ "B09": "S2-L2A-B09",
34
+ "B11": "S2-L2A-B11",
35
+ "B12": "S2-L2A-B12",
36
+ "AOT": "S2-L2A-AOT",
37
+ "SCL": "S2-L2A-SCL",
38
+ "SNW": "S2-L2A-SNW",
39
+ }
40
+
41
+ ELEMENT84_SENTINEL2_L2A_MAPPING = {
42
+ "coastal": "S2-L2A-B01",
43
+ "blue": "S2-L2A-B02",
44
+ "green": "S2-L2A-B03",
45
+ "red": "S2-L2A-B04",
46
+ "rededge1": "S2-L2A-B05",
47
+ "rededge2": "S2-L2A-B06",
48
+ "rededge3": "S2-L2A-B07",
49
+ "nir": "S2-L2A-B08",
50
+ "nir08": "S2-L2A-B8A",
51
+ "nir09": "S2-L2A-B09",
52
+ "cirrus": "S2-L2A-B10",
53
+ "swir16": "S2-L2A-B11",
54
+ "swir22": "S2-L2A-B12",
55
+ "scl": "S2-L2A-SCL",
56
+ "aot": "S2-L2A-AOT",
57
+ }
58
+
59
+
60
+ def _get_s2_l2a_default_fetcher(
61
+ collection_name: str, fetch_type: FetchType
62
+ ) -> Callable:
63
+ """Builds the fetch function from the collection name as it stored in the
64
+ target backend.
65
+
66
+ Parameters
67
+ ----------
68
+ collection_name: str
69
+ The name of the sentinel2 collection as named in the backend
70
+ point_based: bool
71
+ The type of fetching: TILE, POINT and POLYGON.
72
+ """
73
+
74
+ def s2_l2a_fetch_default(
75
+ connection: openeo.Connection,
76
+ spatial_extent: SpatialContext,
77
+ temporal_extent: TemporalContext,
78
+ bands: list,
79
+ **params,
80
+ ) -> openeo.DataCube:
81
+ """Default collection fetcher for Sentinel_L2A collections.
82
+ Parameters
83
+ ----------
84
+ connection: openeo.Connection
85
+ Connection to a general backend.
86
+ spatial_extent: SpatialContext
87
+ Either a GeoJSON collection or a bounding box of locations.
88
+ Performs spatial filtering if the spatial context is a GeoJSON
89
+ collection, as it implies sparse data.
90
+ temporal_extent: TemporalContexct
91
+ A time range, defined by a start and end date.
92
+ bands: list
93
+ The name of the bands to load from that collection
94
+ Returns
95
+ -------
96
+ openeo.DataCube: a datacube containing the collection raw products.
97
+ """
98
+ # Rename the bands to the backend collection names
99
+ bands = convert_band_names(bands, BASE_SENTINEL2_L2A_MAPPING)
100
+
101
+ cube = _load_collection(
102
+ connection,
103
+ bands,
104
+ collection_name,
105
+ spatial_extent,
106
+ temporal_extent,
107
+ fetch_type,
108
+ **params,
109
+ )
110
+
111
+ return cube
112
+
113
+ return s2_l2a_fetch_default
114
+
115
+
116
+ def _get_s2_l2a_element84_fetcher(
117
+ collection_name: str, fetch_type: FetchType
118
+ ) -> Callable:
119
+ """Fetches the collections from the Sentinel-2 Cloud-Optimized GeoTIFFs
120
+ bucket provided by Amazon and managed by Element84.
121
+ """
122
+
123
+ def s2_l2a_element84_fetcher(
124
+ connection: openeo.Connection,
125
+ spatial_extent: SpatialContext,
126
+ temporal_extent: TemporalContext,
127
+ bands: list,
128
+ **params,
129
+ ) -> openeo.DataCube:
130
+ """Collection fetcher on the element84 collection."""
131
+ bands = convert_band_names(bands, ELEMENT84_SENTINEL2_L2A_MAPPING)
132
+
133
+ if isinstance(spatial_extent, BoundingBoxExtent):
134
+ spatial_extent = dict(spatial_extent)
135
+ elif isinstance(spatial_extent, GeoJSON):
136
+ assert (
137
+ spatial_extent.get("crs", None) is not None
138
+ ), "CRS not defined within GeoJSON collection."
139
+ spatial_extent = dict(spatial_extent)
140
+
141
+ cube = connection.load_stac(
142
+ "https://earth-search.aws.element84.com/v1/collections/sentinel-2-l2a",
143
+ spatial_extent,
144
+ temporal_extent,
145
+ bands,
146
+ )
147
+
148
+ cube.metadata = FakeMetadata(band_names=bands)
149
+
150
+ # Apply if the collection is a GeoJSON Feature collection
151
+ if isinstance(spatial_extent, GeoJSON):
152
+ cube = cube.filter_spatial(spatial_extent)
153
+
154
+ return cube
155
+
156
+ return s2_l2a_element84_fetcher
157
+
158
+
159
+ def _get_s2_l2a_default_processor(
160
+ collection_name: str, fetch_type: FetchType
161
+ ) -> Callable:
162
+ """Builds the preprocessing function from the collection name as it stored
163
+ in the target backend.
164
+ """
165
+
166
+ def s2_l2a_default_processor(cube: openeo.DataCube, **params):
167
+ """Default collection preprocessing method.
168
+ This method performs reprojection if specified, upsampling of bands
169
+ at 10m resolution as well as band reprojection. Finally, it converts
170
+ the type of the cube values to uint16
171
+ """
172
+ # Reproject collection data to target CRS and resolution, if specified so.
173
+ # Can be disabled by setting target_resolution=None in the parameters
174
+ if params.get("target_resolution", True) is not None:
175
+ cube = resample_reproject(
176
+ cube,
177
+ params.get("target_resolution", 10.0),
178
+ params.get("target_crs", None),
179
+ method=params.get("resampling_method", "near"),
180
+ )
181
+ elif params.get("target_crs") is not None:
182
+ raise ValueError(
183
+ "In fetching parameters: `target_crs` specified but not `target_resolution`, which is required to perform reprojection."
184
+ )
185
+
186
+ # Harmonizing the collection band names to the default GFMAP band names
187
+ cube = rename_bands(cube, BASE_SENTINEL2_L2A_MAPPING)
188
+
189
+ # Change the data type to uint16 for optimization purposes
190
+ cube = cube.linear_scale_range(0, 65534, 0, 65534)
191
+
192
+ return cube
193
+
194
+ return s2_l2a_default_processor
195
+
196
+
197
+ SENTINEL2_L2A_BACKEND_MAP = {
198
+ Backend.TERRASCOPE: {
199
+ "fetch": partial(_get_s2_l2a_default_fetcher, collection_name="SENTINEL2_L2A"),
200
+ "preprocessor": partial(
201
+ _get_s2_l2a_default_processor, collection_name="SENTINEL2_L2A"
202
+ ),
203
+ },
204
+ Backend.CDSE: {
205
+ "fetch": partial(_get_s2_l2a_default_fetcher, collection_name="SENTINEL2_L2A"),
206
+ "preprocessor": partial(
207
+ _get_s2_l2a_default_processor, collection_name="SENTINEL2_L2A"
208
+ ),
209
+ },
210
+ Backend.CDSE_STAGING: {
211
+ "fetch": partial(_get_s2_l2a_default_fetcher, collection_name="SENTINEL2_L2A"),
212
+ "preprocessor": partial(
213
+ _get_s2_l2a_default_processor, collection_name="SENTINEL2_L2A"
214
+ ),
215
+ },
216
+ Backend.FED: {
217
+ "fetch": partial(_get_s2_l2a_default_fetcher, collection_name="SENTINEL2_L2A"),
218
+ "preprocessor": partial(
219
+ _get_s2_l2a_default_processor, collection_name="SENTINEL2_L2A"
220
+ ),
221
+ },
222
+ }
223
+
224
+
225
+ def build_sentinel2_l2a_extractor(
226
+ backend_context: BackendContext, bands: list, fetch_type: FetchType, **params
227
+ ) -> CollectionFetcher:
228
+ """Creates a S2 L2A extractor adapted to the given backend."""
229
+ backend_functions = SENTINEL2_L2A_BACKEND_MAP.get(backend_context.backend)
230
+
231
+ fetcher, preprocessor = (
232
+ backend_functions["fetch"](fetch_type=fetch_type),
233
+ backend_functions["preprocessor"](fetch_type=fetch_type),
234
+ )
235
+
236
+ return CollectionFetcher(backend_context, bands, fetcher, preprocessor, **params)
@@ -0,0 +1,3 @@
1
+ """This module contains the base classes for inference models. The base classes
2
+ provide some common methods and attributes to be used by other inference models.
3
+ """