diff --git a/pyproject.toml b/pyproject.toml index fa36bb6..eaab1f2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,7 +26,6 @@ classifiers = [ dynamic = ["version"] dependencies = [ "cftime", - "dask", "h5netcdf", "xarray", "rioxarray", diff --git a/tests/fixtures/3B42_Daily.19980101.7.nc4 b/tests/fixtures/3B42_Daily.19980101.7.nc4 new file mode 100644 index 0000000..6b3e07c Binary files /dev/null and b/tests/fixtures/3B42_Daily.19980101.7.nc4 differ diff --git a/tests/test_app.py b/tests/test_app.py index 9481861..f78685d 100644 --- a/tests/test_app.py +++ b/tests/test_app.py @@ -6,7 +6,7 @@ DATA_DIR = "tests/fixtures" test_zarr_store = os.path.join(DATA_DIR, "test_zarr_store.zarr") test_reference_store = os.path.join(DATA_DIR, "reference.json") -test_netcdf_store = os.path.join(DATA_DIR, "testfile.nc") +test_netcdf_store = os.path.join(DATA_DIR, "3B42_Daily.19980101.7.nc4") test_remote_netcdf_store = "https://nex-gddp-cmip6.s3-us-west-2.amazonaws.com/NEX-GDDP-CMIP6/GISS-E2-1-G/historical/r1i1p1f2/pr/pr_day_GISS-E2-1-G_historical_r1i1p1f2_gn_1950.nc" test_unconsolidated_store = os.path.join(DATA_DIR, "unconsolidated.zarr") test_pyramid_store = os.path.join(DATA_DIR, "pyramid.zarr") @@ -26,8 +26,8 @@ "variables": ["value"], } test_netcdf_store_params = { - "params": {"url": test_netcdf_store, "variable": "data", "decode_times": False}, - "variables": ["data"], + "params": {"url": test_netcdf_store, "variable": "precipitation", "decode_times": False}, + "variables": ["precipitation"], } test_remote_netcdf_store_params = { "params": { @@ -162,7 +162,7 @@ def test_get_tilejson_pyramid(app): def get_tile_test(app, ds_params, zoom: int = 0): response = app.get( - f"/tiles/{zoom}/0/0.png", + f"/tiles/1/0/0.png", params=ds_params["params"], ) assert response.status_code == 200 diff --git a/titiler/xarray/reader.py b/titiler/xarray/reader.py index 7d81091..65fbda5 100644 --- a/titiler/xarray/reader.py +++ b/titiler/xarray/reader.py @@ -131,8 +131,7 @@ def xarray_open_dataset( xr_open_args: Dict[str, Any] = { "decode_coords": "all", "decode_times": decode_times, - "engine": xr_engine, - "chunks": 'auto', + "engine": xr_engine } # Argument if we're opening a datatree @@ -155,7 +154,7 @@ def xarray_open_dataset( return ds -def arrange_coordinates(da: xarray.DataArray) -> xarray.DataArray: +def arrange_coordinates(da: xarray.DataArray, xr_engine: str) -> xarray.DataArray: """ Arrange coordinates to DataArray. An rioxarray.exceptions.InvalidDimensionOrder error is raised if the coordinates are not in the correct order time, y, and x. @@ -170,13 +169,21 @@ def arrange_coordinates(da: xarray.DataArray) -> xarray.DataArray: if "longitude" in da.dims: longitude_var_name = "longitude" da = da.rename({latitude_var_name: "y", longitude_var_name: "x"}) - da = da.transpose("time", "y", "x", missing_dims="ignore") + if da.dims != ["time", "y", "x"]: + da = da.transpose("time", "y", "x", missing_dims="ignore") + # if we're caching the data, we need to load the transposed data into memory rather than lazily loading it later. + # Trying to modify the data with rioxarray during the tile operation will result in an error: + # `cannot pickle io.BufferedReader`. This only happens when operating on a cached file, like NetCDF. + # if api_settings.enable_fsspec_cache and xr_engine == "h5netcdf": + # #da.load() + # pass return da def get_variable( ds: xarray.Dataset, variable: str, + xr_engine: str, time_slice: Optional[str] = None, drop_dim: Optional[str] = None, ) -> xarray.DataArray: @@ -187,7 +194,7 @@ def get_variable( if drop_dim: dim_to_drop, dim_val = drop_dim.split("=") da = da.sel({dim_to_drop: dim_val}).drop(dim_to_drop) - da = arrange_coordinates(da) + da = arrange_coordinates(da, xr_engine=xr_engine) if (da.x > 180).any(): # Adjust the longitude coordinates to the -180 to 180 range @@ -264,6 +271,7 @@ def __attrs_post_init__(self): self.input = get_variable( self.ds, self.variable, + xr_engine=xarray_engine(self.src_path), time_slice=self.time_slice, drop_dim=self.drop_dim, )