Skip to content

Commit e6df73a

Browse files
committed
issue resolved
1 parent 28b16be commit e6df73a

File tree

9 files changed

+82
-235
lines changed

9 files changed

+82
-235
lines changed

CHANGES.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
## Changes in 0.2.0
2+
3+
* Switched to [xcube-resampling](https://xcube-dev.github.io/xcube-resampling/)
4+
for dataset resampling and reprojection.
5+
* Renamed the keyword argument `spline_orders` to `interp_methods` to align with
6+
the naming convention used in xcube-resampling.
7+
* Fixed issue #39: resolved `AttributeError: 'dict' object has no attribute 'coords'`.
8+
9+
110
## Changes in 0.1.1
211

312
* Fixed a bug in Sentinel-2 cube generation where, during mosaicking of adjacent tiles

docs/guide.md

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ These tiles are stored in their native UTM CRS, which varies by geographic locat
174174
| Condition | Requested bounding box lies within a single UTM zone, native CRS is requested, and the spatial resolution matches the native resolution. | Data spans multiple UTM zones, a different CRS is requested (e.g., EPSG:4326), or a custom spatial resolution is requested. |
175175
| Processing steps | Only upsampling or downsampling is applied to align the differing resolutions of the spectral bands. Data cube is directly cropped using the requested bounding box, preserving original pixel values. Spatial extent may deviate slightly due to alignment with native pixel grid. | A target grid mapping is computed from bounding box, spatial resolution, and CRS. Data from each UTM zone is reprojected/resampled to this grid. Overlaps resolved by first non-NaN pixel. |
176176

177-
Upsampling and downsampling are controlled using the `agg_methods` and `spline_order`
177+
Upsampling and downsampling are controlled using the `agg_methods` and `interp_methods`
178178
parameters ([see below](#remarks-to-opening-parameters)).
179179

180180
#### Data Identifiers
@@ -209,20 +209,21 @@ subsequently performs the reprojection.
209209

210210
**Upsampling / Reprojecting:**
211211

212-
- Controlled via 2D interpolation using the `spline_orders` parameter.
213-
- Accepts a single order for all variables, or a dictionary mapping orders to variable
214-
names or data types.
215-
- Supported spline orders:
216-
- `0`: nearest neighbor (default for `scl`)
217-
- `1`: linear
218-
- `2`: bi-linear
219-
- `3`: cubic (default)
212+
- Controlled via 2D interpolation using the `interp_methods` parameter.
213+
- Accepts a single interpolation method for all variables, or a dictionary mapping from
214+
variable names or data types to specific interpolation methods.
215+
- Supported interpolation methods:
216+
- `0` (nearest neighbor)
217+
- `1` (linear / bilinear)
218+
- `"nearest"`
219+
- `"triangular"`
220+
- `"bilinear"`
220221

221222
**Downsampling:**
222223

223224
- Controlled via the `agg_methods` parameter.
224-
- Can be specified as a single method for all variables, or as a dictionary mapping
225-
methods to variable names or data types.
225+
- Can be specified as a single method for all variables, or a dictionary mapping from
226+
variable names or data types to specific interpolation methods.
226227
- Supported aggregation methods:
227228
- `"center"` (default for `scl`)
228229
- `"count"`

environment.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ dependencies:
1212
- xarray
1313
- xarray-eopf >=0.1.1
1414
- xcube >=1.11.0
15+
- xcube-resampling
1516
# Development Dependencies - Tools
1617
- black
1718
- isort

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ dependencies = [
4848
"pystac-client",
4949
"xarray",
5050
"xarray-eopf>=0.1.1",
51-
"xcube-core>=1.11.0"
51+
"xcube-core>=1.11.0",
52+
"xcube-resampling",
5253
]
5354

5455
[project.optional-dependencies]

tests/test_store.py

Lines changed: 18 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ def test_open_data_10m(self, mock_xarray):
117117
spatial_res=10,
118118
crs="EPSG:32632",
119119
variables=["b02", "b03", "b04", "scl"],
120-
spline_orders={0: [np.float32], 3: ["scl"]},
120+
interp_methods={np.float32: 0, "scl": 3},
121121
)
122122
self.assertIsInstance(ds, xr.Dataset)
123123
self.assertCountEqual(["b02", "b03", "b04", "scl"], list(ds.data_vars))
@@ -135,26 +135,17 @@ def test_open_data_10m(self, mock_xarray):
135135

136136
@pytest.mark.vcr()
137137
@patch("xarray.open_dataset")
138-
def test_open_data_5m_spline_order(self, mock_xarray):
138+
def test_open_data_5m_interp_method(self, mock_xarray):
139139
mock_xarray.return_value = l2a_10m()
140-
141-
with self.assertLogs("xcube.eopf", level="WARNING") as cm:
142-
ds = self.store.open_data(
143-
data_id="sentinel-2-l2a",
144-
bbox=(610000, 5880000, 630000, 5900000),
145-
time_range=["2025-05-01", "2025-05-15"],
146-
spatial_res=5,
147-
crs="EPSG:32632",
148-
variables=["b02", "b03", "b04", "scl"],
149-
spline_orders={0: [np.float32], 3: ["scl"]},
150-
)
151-
self.assertEqual(1, len(cm.output))
152-
msg = (
153-
f"WARNING:xcube.eopf:Spline order 3 selected for 'scl' "
154-
f"(categorical data). This may produce corrupted results."
140+
ds = self.store.open_data(
141+
data_id="sentinel-2-l2a",
142+
bbox=(610000, 5880000, 630000, 5900000),
143+
time_range=["2025-05-01", "2025-05-15"],
144+
spatial_res=5,
145+
crs="EPSG:32632",
146+
variables=["b02", "b03", "b04", "scl"],
147+
interp_methods={np.dtype("float64"): "bilinear", "scl": "nearest"},
155148
)
156-
self.assertEqual(msg, str(cm.output[-1]))
157-
158149
self.assertIsInstance(ds, xr.Dataset)
159150
self.assertCountEqual(["b02", "b03", "b04", "scl"], list(ds.data_vars))
160151
self.assertCountEqual(
@@ -173,24 +164,15 @@ def test_open_data_5m_spline_order(self, mock_xarray):
173164
@patch("xarray.open_dataset")
174165
def test_open_data_100m_agg_methods(self, mock_xarray):
175166
mock_xarray.return_value = l2a_60m()
176-
177-
with self.assertLogs("xcube.eopf", level="WARNING") as cm:
178-
ds = self.store.open_data(
179-
data_id="sentinel-2-l2a",
180-
bbox=(610000, 5880000, 630000, 5900000),
181-
time_range=["2025-05-01", "2025-05-15"],
182-
spatial_res=100,
183-
crs="EPSG:32632",
184-
variables=["b02", "b03", "b04", "scl"],
185-
agg_methods={"max": [np.float32], "mean": ["scl"]},
186-
)
187-
self.assertEqual(1, len(cm.output))
188-
msg = (
189-
"WARNING:xcube.eopf:Aggregation method 'mean' selected for 'scl' "
190-
"(categorical data). This may produce corrupted results."
167+
ds = self.store.open_data(
168+
data_id="sentinel-2-l2a",
169+
bbox=(610000, 5880000, 630000, 5900000),
170+
time_range=["2025-05-01", "2025-05-15"],
171+
spatial_res=100,
172+
crs="EPSG:32632",
173+
variables=["b02", "b03", "b04", "scl"],
174+
agg_methods={np.dtype("float64"): "max", "scl": "mode"},
191175
)
192-
self.assertEqual(msg, str(cm.output[-1]))
193-
194176
self.assertIsInstance(ds, xr.Dataset)
195177
self.assertCountEqual(["b02", "b03", "b04", "scl"], list(ds.data_vars))
196178
self.assertCountEqual(
@@ -239,48 +221,6 @@ def test_open_data_geographic(self, mock_xarray):
239221
self.assertIn("open_params", ds.attrs)
240222
self.assertIn("xcube_eopf_version", ds.attrs)
241223

242-
@pytest.mark.vcr()
243-
@patch("xarray.open_dataset")
244-
def test_open_data_spline_order_raise_logs(self, mock_xarray):
245-
mock_xarray.return_value = l2a_60m()
246-
247-
bbox = [610000, 5880000, 630000, 5900000]
248-
bbox_wgs84 = reproject_bbox(bbox, "EPSG:32632", "EPSG:4326")
249-
with self.assertLogs("xcube.eopf", level="WARNING") as cm:
250-
ds = self.store.open_data(
251-
data_id="sentinel-2-l2a",
252-
bbox=bbox_wgs84,
253-
time_range=["2025-05-01", "2025-05-15"],
254-
spatial_res=50 / CONVERSION_FACTOR_DEG_METER,
255-
crs="EPSG:4326",
256-
variables=["b02", "b03", "b04", "scl"],
257-
spline_orders=2,
258-
)
259-
self.assertEqual(1, len(cm.output))
260-
msg = (
261-
"WARNING:xcube.eopf:User-defined spline-orders is not supported yet, "
262-
"when reprojecting to a different CRS. Default interpolation will be "
263-
"used: bilinear for continuous data, and nearest-neighbor for 'scl'."
264-
)
265-
self.assertEqual(msg, str(cm.output[-1]))
266-
self.assertIsInstance(ds, xr.Dataset)
267-
self.assertCountEqual(["b02", "b03", "b04", "scl"], list(ds.data_vars))
268-
self.assertCountEqual(
269-
[4, 412, 684], [ds.sizes["time"], ds.sizes["lat"], ds.sizes["lon"]]
270-
)
271-
self.assertEqual(
272-
[1, 412, 684],
273-
[
274-
ds.chunksizes["time"][0],
275-
ds.chunksizes["lat"][0],
276-
ds.chunksizes["lon"][0],
277-
],
278-
)
279-
self.assertIn("stac_url", ds.attrs)
280-
self.assertIn("stac_items", ds.attrs)
281-
self.assertIn("open_params", ds.attrs)
282-
self.assertIn("xcube_eopf_version", ds.attrs)
283-
284224
@pytest.mark.vcr()
285225
def test_open_data_no_items_found(self):
286226
with self.assertRaises(DataStoreError) as cm:

tests/test_utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import pyproj
1010
import pystac
1111
import xarray as xr
12-
from xcube.core.gridmapping import GridMapping
12+
from xcube_resampling.gridmapping import GridMapping
1313
from xcube.core.store import DataStoreError
1414

1515
from xcube_eopf.utils import (

0 commit comments

Comments
 (0)