Skip to content

Commit bc42ee8

Browse files
authored
Merge pull request #29 from CMCC-Foundation/version-2025.06
Update Geokube to version 2025.06
2 parents 6d8971b + 077e89e commit bc42ee8

File tree

11 files changed

+65
-56
lines changed

11 files changed

+65
-56
lines changed

.dockerignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
*.nc
1+
*.nc
2+
*.zarr
3+
data

.github/workflows/build-push-docker_release.yml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
name: Build on release a geokube Docker image and push to the geokube container registry
22

33
on:
4-
push:
5-
tags:
6-
- 'v*'
4+
release:
5+
types: [published]
76
workflow_dispatch:
87
jobs:
98
build:

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,4 +120,5 @@ Dockerfile.dev
120120
nuts_shape
121121
*.png
122122
*.zarr
123-
.DS_Store
123+
.DS_Store
124+
data

Dockerfile

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
#FROM rg.fr-par.scw.cloud/geokube/geokube-base:2024.05.03.08.14
2-
#new version with Zarr support
3-
FROM rg.fr-par.scw.cloud/geokube/geokube-base:2025.01.09.14.31
1+
FROM rg.fr-par.scw.cloud/geokube/geokube-base:2025.06.12.14.52
42

53
ADD . /opt/geokube
64
RUN pip install /opt/geokube --break-system-packages

Dockerfile.base

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ RUN make -j4
1919

2020
ENV ESMFMKFILE=/opt/esmf/lib/libO/Linux.gfortran.64.mpiuni.default/esmf.mk
2121

22-
RUN pip install numpy setuptools==75.8.0 --break-system-packages
22+
RUN pip install numpy setuptools==80.9.0 --break-system-packages
2323

2424
WORKDIR /opt/esmf/src/addon/esmpy
2525
RUN pip install . --break-system-packages

geokube/core/datacube.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -517,12 +517,21 @@ def to_xarray(self, encoding=True):
517517
def to_netcdf(self, path, encoding: bool = True):
518518
self.to_xarray(encoding=encoding).to_netcdf(path=path)
519519

520-
def to_zarr(self, path, encoding: bool = True, **kwargs):
520+
@geokube_logging
521+
def _find_best_chunking(self, ds: xr.Dataset):
522+
chunks = {name: 1000 if name.lower() in ['time', 'xtime'] else 100 for name in ds.dims}
523+
self._LOG.info(f"Best chunking: {chunks}")
524+
return chunks
525+
526+
@geokube_logging
527+
def to_zarr(self, path, encoding: bool = True, chunks: dict = None, **kwargs):
521528
kube = self.to_xarray(encoding=encoding)
522529
for var in kube:
523530
if 'chunks' in kube[var].encoding.keys():
524531
del kube[var].encoding['chunks']
525-
kube.unify_chunks().chunk('auto').to_zarr(path,**kwargs)
532+
if chunks is None:
533+
chunks = self._find_best_chunking(kube)
534+
kube.chunk(chunks).to_zarr(path,**kwargs)
526535

527536
@geokube_logging
528537
def to_csv(self, path, encoding: bool = True):

geokube/core/domain.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ def compute_bounds(
279279
val = coord.values
280280
val_b = np.empty(shape=val.size + 1, dtype=np.float64)
281281
val_b[1:-1] = 0.5 * (val[:-1] + val[1:])
282-
half_step = 0.5 * (val.ptp() / (val.size - 1))
282+
half_step = 0.5 * (np.ptp(val) / (val.size - 1))
283283
# The case `val[0] > val[-1]` represents reversed order of values:
284284
i, j = (0, -1) if val[0] <= val[-1] else (-1, 0)
285285
val_b[i] = val[i] - half_step

geokube/core/field.py

Lines changed: 30 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -827,8 +827,9 @@ def _check_and_roll_longitude(self, ds, indexers) -> xr.Dataset:
827827
def to_regular(self):
828828
# Infering latitude and longitude steps from the x and y coordinates.
829829
if isinstance(self.domain.crs, RotatedGeogCS):
830-
lat_step = np.ptp(self.y.values) / (self.y.values.size - 1)
831-
lon_step = np.ptp(self.x.values) / (self.x.values.size - 1)
830+
lat_step = round(np.ptp(self.y.values) / (self.y.values.size - 1), 2)
831+
lat_step = round(np.ptp(self.y.values) / (self.y.values.size - 1), 2)
832+
lon_step = round(np.ptp(self.x.values) / (self.x.values.size - 1), 2)
832833
else:
833834
raise NotImplementedError(
834835
f"'{type(self.domain.crs).__name__}' is not supported as a "
@@ -982,10 +983,16 @@ def regrid(
982983
coords_out = {"lat_b": lat_b, "lon_b": lon_b}
983984

984985
# Regridding
985-
in_ = self.to_xarray(encoding=False).rename(names_in)
986+
try:
987+
in_ = self.to_xarray(encoding=False).rename(names_in)
988+
except:
989+
in_ = self.to_xarray(encoding=False)
986990
if coords_in:
987991
in_ = in_.assign_coords(coords=coords_in)
988-
out = target.to_xarray(encoding=False).to_dataset().rename(names_out)
992+
try:
993+
out = target.to_xarray(encoding=False).to_dataset().rename(names_out)
994+
except:
995+
out = target.to_xarray(encoding=False).to_dataset()
989996
if coords_out:
990997
out = out.assign_coords(coords=coords_out)
991998
regrid_kwa = {
@@ -1000,7 +1007,10 @@ def regrid(
10001007
except PermissionError:
10011008
regridder = xe.Regridder(**regrid_kwa)
10021009
result = regridder(in_, keep_attrs=True, skipna=False)
1003-
result = result.rename({v: k for k, v in names_in.items()})
1010+
try:
1011+
result = result.rename({v: k for k, v in names_in.items()})
1012+
except:
1013+
pass
10041014
result[self.name].encoding = in_[self.name].encoding
10051015
if not isinstance(target.crs, GeogCS):
10061016
missing_coords = {
@@ -1062,37 +1072,22 @@ def resample(
10621072
"""
10631073
ds = self.to_xarray(encoding=False)
10641074
encodings = ds.encoding
1065-
if frequency == '1D':
1066-
match operator:
1067-
case "max":
1068-
ds = ds.coarsen(time=24).max()
1069-
case "min":
1070-
ds = ds.coarsen(time=24).min()
1071-
case "sum":
1072-
ds = ds.coarsen(time=24).sum()
1073-
case "mean":
1074-
ds = ds.coarsen(time=24).mean()
1075-
case "median":
1076-
ds = ds.coarsen(time=24).median()
1077-
case _:
1078-
raise NotImplementedError(f"Operator {operator} not implemented.")
1079-
else:
1080-
ds = ds.resample(time=frequency)
1081-
match operator:
1082-
case "max":
1083-
ds = ds.max(dim="time")
1084-
case "min":
1085-
ds = ds.min(dim="time")
1086-
case "sum":
1087-
ds = ds.sum(dim="time")
1088-
case "mean":
1089-
ds = ds.mean(dim="time")
1090-
case "median":
1091-
ds = ds.median(dim="time")
1092-
case _:
1093-
raise NotImplementedError(f"Operator {operator} not implemented.")
1075+
ds = ds.resample(time=frequency)
1076+
match operator:
1077+
case "max":
1078+
ds = ds.max(dim="time")
1079+
case "min":
1080+
ds = ds.min(dim="time")
1081+
case "sum":
1082+
ds = ds.sum(dim="time")
1083+
case "mean":
1084+
ds = ds.mean(dim="time")
1085+
case "median":
1086+
ds = ds.median(dim="time")
1087+
case _:
1088+
raise NotImplementedError(f"Operator {operator} not implemented.")
10941089
ds.encoding = encodings
1095-
field = Field.from_xarray(ds, ncvar=self.name)
1090+
field = Field.from_xarray(ds, ncvar=self.name, id_pattern=self._id_pattern, mapping=self._mapping, copy=False)
10961091
field.domain.crs = self.domain.crs
10971092
field.domain._type = self.domain._type
10981093
field.domain._calculate_missing_lat_and_lon()

geokube/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "0.2.7.10"
1+
__version__ = "2025.06"

requirements.txt

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@ cf_units==3.3.0
22
cartopy
33
numpy==2.0.2
44
pandas==2.2.3
5-
netCDF4
5+
netCDF4==1.7.2
6+
h5py==3.14.0
67
scipy
7-
xarray==2025.1.2
8-
dask==2024.12.1
8+
xarray==2025.6.1
9+
dask==2025.5.1
910
geopandas
1011
#esmpy==8.2.0
1112
#xesmf==0.7.1
@@ -16,4 +17,8 @@ dask[distributed]
1617
zarr==2.18.4
1718
rioxarray
1819
plotly
19-
pyarrow
20+
pyarrow
21+
numcodecs==0.15.1
22+
flox
23+
cf-xarray==0.10.5
24+
h5netcdf==1.6.1

0 commit comments

Comments
 (0)