Skip to content

Commit 37cdaa6

Browse files
authored
Merge pull request #10 from xcube-dev/konstntokas-xxx-small_things
Enhance small things
2 parents c7f5b6d + c13bb63 commit 37cdaa6

File tree

24 files changed

+1007
-405908
lines changed

24 files changed

+1007
-405908
lines changed

CHANGES.md

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,18 @@
11
## Changes in 0.3.0 (in development)
22

3-
* Switched to the new unified `xcube-resampling` library from
4-
`xcube.core.resampling`.
5-
* Added `spatial_resample_params` support and updated the config visualization to
6-
display the `Spatial Resample Params`.
3+
* **Unified spatial resampling**: Switched to the new
4+
`xcube_resampling.resample_in_space` library, replacing
5+
`xcube.core.resampling.resample_in_space`.
6+
* **Spatial resample parameters**: Added support for `spatial_resample_params`
7+
and updated the configuration visualization to display these parameters.
8+
* **Temporal resampling**: Introduced `xcube_resampling.resample_in_time` with
9+
`temporal_resample_params` added to the configuration to cover temporal resampling.
10+
* **Controlled cube generation**: `xcube_multistore.MultiSourceDataStore` is now only
11+
initialized in the constructor without automatically starting cube generation.
12+
A new `generate()` method is provided to explicitly start cube creation.
13+
* **Geolocation visualization**: Added `display_geolocations()` to visualize
14+
all requested geolocations of the datacubes to be generated.
15+
* Fixed visualization of preload handle
716

817

918
## Changes in 0.2.0
@@ -13,6 +22,7 @@
1322
* Added auxiliary functions to support setting up configurations for cube generation.
1423
Examples of all functionalities are provided in the notebook [setup_config.ipynb](examples/setup_config.ipynb).
1524

25+
1626
## Changes in 0.1.0
1727

1828
* The initial version of the Multi-Source Data Store has been developed in

docs/config.md

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ This configures a dataset object from a single data source.
5656
* **[format_id](#format_id)**
5757
* **[custom_processing](#custom_processing)**
5858
* **[spatial_resample_params](#spatial_resample_params)**
59+
* **[temporal_resample_params](#temporal_resample_params)**
5960

6061

6162
#### multi dataset object
@@ -83,6 +84,7 @@ This configures a variable object, which is stored as a data variable within a s
8384
* **[open_params](#open_params)**
8485
* **[custom_processing](#custom_processing)**
8586
* **[spatial_resample_params](#spatial_resample_params)**
87+
* **[temporal_resample_params](#temporal_resample_params)**
8688

8789
### store object
8890
This configures a store object representing one xcube data store instance.
@@ -132,7 +134,6 @@ generation process.
132134

133135
* **[visualize](#visualize)**
134136
* **[force_preload](#force_preload)**
135-
* **[dask_scheduler](#dask_scheduler)**
136137
* **[gdal_http_params](#gdal_http_params)**
137138

138139

@@ -162,7 +163,7 @@ datacube is required. For further information view the [xarray.merge documentati
162163
Desired format of the saved datacube.
163164

164165
**Default:** `zarr`
165-
**Allowed values:** `netcdf`, `zarr`
166+
**Allowed values:** `netcdf`, `zarr`, [`levels`](https://xcube.readthedocs.io/en/latest/mldatasets.html#the-xcube-levels-format)
166167

167168
### custom_processing
168169
This section enables users to define a Python function that is executed after opening
@@ -176,9 +177,18 @@ the dataset. For a full list of supported parameters, refer to the
176177
[`xcube_resampling.resample_in_space` Python API documentation](https://xcube-dev.github.io/xcube-resampling/api/#xcube_resampling.resample_in_space).
177178

178179

179-
_NOTE_: The first 3 arguments `(source_ds, target_gm, source_gm)` in the `xcube_resampling.resample_in_space` are not
180-
required and will be inferred automatically from the config file's dataset and
181-
gridmapping section.
180+
_NOTE_: The first 3 arguments `(source_ds, target_gm, source_gm)` in the
181+
`xcube_resampling.resample_in_space` are not required and will be inferred
182+
automatically from the config file's dataset and gridmapping section.
183+
184+
### temporal_resample_params
185+
This section enables user to define the parameters for temporal resampling of
186+
the dataset. For a full list of supported parameters, refer to the
187+
[`xcube_resampling.resample_in_time` Python API documentation](https://xcube-dev.github.io/xcube-resampling/api/#xcube_resampling.resample_in_time).
188+
189+
_NOTE_: The argument `frequency` is required; the remaining keyword arguments are
190+
optional.
191+
182192

183193
**Properties**:
184194

@@ -202,7 +212,7 @@ below.
202212
* [file, https, memory, s3](https://xcube.readthedocs.io/en/latest/dataaccess.html#filesystem-based-data-stores)
203213
* [sentinelhub, sentinelhub-cdse](https://github.com/xcube-dev/xcube-sh)
204214
* [smos](https://github.com/xcube-dev/xcube-smos)
205-
* [stac, stac-cdse, stac-xcube](https://github.com/xcube-dev/xcube-stac)
215+
* [stac, stac-cdse, stac-cdse-ardc, stac-pc, stac-pc-ardc, stac-xcube](https://github.com/xcube-dev/xcube-stac)
206216
* [zenodo](https://github.com/xcube-dev/xcube-zenodo)
207217

208218
---
@@ -243,12 +253,6 @@ only non-preloaded datasets will be preloaded.
243253

244254
**Default:** `True`
245255

246-
### dask_scheduler
247-
Scheduler mode put into `dask.config.set(scheduler=<scheduler_mode>)`
248-
249-
**Default:** `threads`
250-
**Allowed values:** `threads`, `processes`, `single-threaded`, `sync`, `distributed`
251-
252256
### gdal_http_params
253257
GDAL http environment variables which are used when opening a tif file with
254258
`rioxarray.open_rasterio`, which uses GDAL driver under the hood, from a remote source.

docs/examples/example2/scs2_config.yml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,3 @@ grid_mappings:
119119
crs: EPSG:4326
120120
tile_size: 1000
121121

122-
general:
123-
dask_scheduler: "single-threaded"
124-

test/accessors/__init__.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# MIT License
2+
#
3+
# Copyright (c) 2025 Brockmann Consult GmbH
4+
#
5+
# Permission is hereby granted, free of charge, to any person obtaining a copy
6+
# of this software and associated documentation files (the "Software"), to deal
7+
# in the Software without restriction, including without limitation the rights
8+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
# copies of the Software, and to permit persons to whom the Software is
10+
# furnished to do so, subject to the following conditions:
11+
#
12+
# The above copyright notice and this permission notice shall be included in all
13+
# copies or substantial portions of the Software.
14+
#
15+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
# FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE
18+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
# SOFTWARE.

test/accessors/test_cds.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# MIT License
2+
#
3+
# Copyright (c) 2025 Brockmann Consult GmbH
4+
#
5+
# Permission is hereby granted, free of charge, to any person obtaining a copy
6+
# of this software and associated documentation files (the "Software"), to deal
7+
# in the Software without restriction, including without limitation the rights
8+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
# copies of the Software, and to permit persons to whom the Software is
10+
# furnished to do so, subject to the following conditions:
11+
#
12+
# The above copyright notice and this permission notice shall be included in all
13+
# copies or substantial portions of the Software.
14+
#
15+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
# FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE
18+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
# SOFTWARE.
22+
23+
from xcube.core.store import new_data_store
24+
from xcube.util.jsonschema import JsonObjectSchema,JsonNumberSchema
25+
import xarray as xr
26+
from unittest.mock import patch
27+
28+
from xcube_multistore.accessors.cds import CdsAccessor
29+
from ..sample_data import get_sample_data_3d
30+
31+
import unittest
32+
33+
34+
class CdsAccessorTest(unittest.TestCase):
35+
36+
def setUp(self):
37+
ds_3d = get_sample_data_3d()
38+
memory_store = new_data_store("memory", root="datasource")
39+
memory_store.write_data(ds_3d, "era5_dataset3.zarr", replace=True)
40+
self.accesor = CdsAccessor(memory_store)
41+
42+
def test_open_data(self):
43+
ds = self.accesor.open_data("era5_dataset3.zarr")
44+
self.assertIsInstance(ds, xr.Dataset)
45+
self.assertCountEqual(["band_1"], ds.data_vars)
46+
self.assertEqual([10, 3, 3], [ds.sizes["time"], ds.sizes["lat"], ds.sizes["lon"]])
47+
48+
@patch("xcube.core.store.fs.store.BaseFsDataStore.open_data")
49+
@patch("xcube.core.store.fs.store.BaseFsDataStore.get_open_data_params_schema")
50+
def test_open_data_spatial_res(self, mock_open_params_schema, mock_open_data):
51+
mock_open_params_schema.return_value = JsonObjectSchema(
52+
properties=dict(spatial_res=JsonNumberSchema(minimum=0.1 ))
53+
)
54+
mock_open_data.return_value = get_sample_data_3d()
55+
ds = self.accesor.open_data("era5_dataset3.zarr", point=(5.0, 40.0))
56+
self.assertIsInstance(ds, xr.Dataset)
57+
self.assertCountEqual(["band_1"], ds.data_vars)
58+
self.assertCountEqual(("time",), ds.dims)
59+
self.assertEqual([10], [ds.sizes["time"]])

test/accessors/test_clms.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# MIT License
2+
#
3+
# Copyright (c) 2025 Brockmann Consult GmbH
4+
#
5+
# Permission is hereby granted, free of charge, to any person obtaining a copy
6+
# of this software and associated documentation files (the "Software"), to deal
7+
# in the Software without restriction, including without limitation the rights
8+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
# copies of the Software, and to permit persons to whom the Software is
10+
# furnished to do so, subject to the following conditions:
11+
#
12+
# The above copyright notice and this permission notice shall be included in all
13+
# copies or substantial portions of the Software.
14+
#
15+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
# FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE
18+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
# SOFTWARE.
22+
23+
from xcube.core.store import new_data_store, PreloadedDataStore
24+
from xcube.util.jsonschema import JsonObjectSchema,JsonNumberSchema
25+
import xarray as xr
26+
from unittest.mock import patch
27+
28+
from xcube_multistore.accessors.clms import ClmsAccessor
29+
from ..sample_data import get_sample_data_3d
30+
31+
import unittest
32+
33+
34+
class ClmsAccessorTest(unittest.TestCase):
35+
36+
def setUp(self):
37+
self.ds_3d = get_sample_data_3d()
38+
memory_store = new_data_store("memory", root="datasource")
39+
memory_store.cache_store = new_data_store("memory", root="cache_datadource")
40+
memory_store.cache_store.write_data(self.ds_3d, "clms_storage|clms_dataset.zarr", replace=True)
41+
self.accesor = ClmsAccessor(memory_store)
42+
43+
def test_open_data_cache_store(self):
44+
ds = self.accesor.open_data("clms_storage|clms_dataset.zarr")
45+
self.assertIsInstance(ds, xr.Dataset)
46+
self.assertCountEqual(["band_1"], ds.data_vars)
47+
self.assertEqual([10, 3, 3], [ds.sizes["time"], ds.sizes["lat"], ds.sizes["lon"]])

test/accessors/test_zenodo.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# MIT License
2+
#
3+
# Copyright (c) 2025 Brockmann Consult GmbH
4+
#
5+
# Permission is hereby granted, free of charge, to any person obtaining a copy
6+
# of this software and associated documentation files (the "Software"), to deal
7+
# in the Software without restriction, including without limitation the rights
8+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
# copies of the Software, and to permit persons to whom the Software is
10+
# furnished to do so, subject to the following conditions:
11+
#
12+
# The above copyright notice and this permission notice shall be included in all
13+
# copies or substantial portions of the Software.
14+
#
15+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
# FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE
18+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
# SOFTWARE.
22+
23+
from xcube.core.store import new_data_store
24+
import xarray as xr
25+
26+
from xcube_multistore.accessors.zenodo import ZenodoAccessor
27+
from ..sample_data import get_sample_data_3d
28+
29+
import unittest
30+
31+
32+
class ZenodoAccessorTest(unittest.TestCase):
33+
34+
def setUp(self):
35+
self.ds_3d = get_sample_data_3d()
36+
memory_store = new_data_store("memory", root="datasource")
37+
memory_store.write_data(self.ds_3d, "dataset.zarr", replace=True)
38+
memory_store.cache_store = new_data_store("memory", root="cache_datadource")
39+
memory_store.cache_store.write_data(self.ds_3d, "zenodo_cache/dataset.zarr", replace=True)
40+
self.accesor = ZenodoAccessor(memory_store)
41+
42+
def test_open_data(self):
43+
ds = self.accesor.open_data("dataset.zarr")
44+
self.assertIsInstance(ds, xr.Dataset)
45+
self.assertCountEqual(["band_1"], ds.data_vars)
46+
self.assertEqual([10, 3, 3], [ds.sizes["time"], ds.sizes["lat"], ds.sizes["lon"]])
47+
48+
def test_open_data_cache_store(self):
49+
ds = self.accesor.open_data("zenodo_cache/dataset.zarr")
50+
self.assertIsInstance(ds, xr.Dataset)
51+
self.assertCountEqual(["band_1"], ds.data_vars)
52+
self.assertEqual([10, 3, 3], [ds.sizes["time"], ds.sizes["lat"], ds.sizes["lon"]])

0 commit comments

Comments
 (0)