From 2a4a22a13129b6b1927a35087c69af5e81838aa2 Mon Sep 17 00:00:00 2001 From: hrodmn Date: Thu, 21 Nov 2024 09:57:44 -0600 Subject: [PATCH] updates for rio-tiler>=7.2 and titiler>=19 --- pyproject.toml | 7 +- .../test_app/test_rasterio_feature.yaml | 442 ++++++++++++++++++ tests/test_app.py | 53 +-- titiler/cmr/factory.py | 44 +- titiler/cmr/reader.py | 155 +----- uv.lock | 56 ++- 6 files changed, 556 insertions(+), 201 deletions(-) create mode 100644 tests/cassettes/test_app/test_rasterio_feature.yaml diff --git a/pyproject.toml b/pyproject.toml index 85a72fd..546842d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,8 +22,9 @@ classifiers = [ "Topic :: Scientific/Engineering :: GIS", ] dependencies = [ - "titiler.core>=0.18.0,<0.19", - "titiler.mosaic>=0.18.0,<0.19", + "titiler.core>=0.19.0,<0.20", + "titiler.mosaic>=0.19.0,<0.20", + "titiler.xarray>=0.19.0,<0.20", "cftime~=1.6.4", "earthaccess~=0.11.0", "fsspec~=2024.9.0", @@ -31,7 +32,7 @@ dependencies = [ "orjson~=3.10.7", "pydantic-settings~=2.0", "pydantic>=2.4,<3.0", - "rio_tiler[s3]>=6.4.0,<7.0", + "rio_tiler[s3]>=7.2.0,<8.0", "rioxarray~=0.13.4", "s3fs~=2024.9.0", "xarray~=2024.9.0", diff --git a/tests/cassettes/test_app/test_rasterio_feature.yaml b/tests/cassettes/test_app/test_rasterio_feature.yaml new file mode 100644 index 0000000..0b1f848 --- /dev/null +++ b/tests/cassettes/test_app/test_rasterio_feature.yaml @@ -0,0 +1,442 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - earthaccess v0.11.0 + authorization: + - DUMMY + method: POST + uri: https://urs.earthdata.nasa.gov/api/users/find_or_create_token + response: + body: + string: '{"access_token":"eyJ0eXAiOiJKV1QiLCJvcmlnaW4iOiJFYXJ0aGRhdGEgTG9naW4iLCJzaWciOiJlZGxqd3RwdWJrZXlfb3BzIiwiYWxnIjoiUlMyNTYifQ.eyJ0eXBlIjoiVXNlciIsInVpZCI6Imhyb2RtYW4xIiwiZXhwIjoxNzMzNzU2MzAxLCJpYXQiOjE3Mjg1NzIzMDEsImlzcyI6Imh0dHBzOi8vdXJzLmVhcnRoZGF0YS5uYXNhLmdvdiJ9.NZFYum9ebUdihJJflCnCGFeOMZjbX8UTIceRO0cTyTZ4U51cIUaTNur5786kzs1-wTrE0Vz1Ku03fqljYt7jcdos14bNPF2MYjX930BCd_aqax5AN0nCF45lnisVtpxQoFM0-on1REU4CagVTxn7BjvnzmeqQC3F-J_d0-bm-9dzFjFFMScS9HomJOryHWAOfit3cUYVC_B8OHYQlw8R76CBUQvRgpco4SOOE_Tr2RXG-a5r8M9wD_sxrwGxfy-wAtXY2UgqRCrdmUWSv2ekcpe_QRwXt_vS9k-TPC7yIPZicWgsM22_JmAoCwmPH9YzF-jjBEjgsrSVKFy7dZL-ew","token_type":"Bearer","expiration_date":"12/09/2024"}' + headers: + Cache-Control: + - no-store + Connection: + - keep-alive + Content-Type: + - application/json; charset=utf-8 + Date: + - Thu, 21 Nov 2024 12:51:57 GMT + ETag: + - W/"7f2a4669736f22867c05c70d164aebe4" + Expires: + - Fri, 01 Jan 1990 00:00:00 GMT + Pragma: + - no-cache + Referrer-Policy: + - strict-origin-when-cross-origin + Server: + - nginx/1.22.1 + Strict-Transport-Security: + - max-age=31536000 + Transfer-Encoding: + - chunked + Vary: + - Accept + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Request-Id: + - 3b465361-ca17-4ce0-89a1-1a0c59be7e02 + X-Runtime: + - '0.093128' + X-XSS-Protection: + - 1; mode=block + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - earthaccess v0.11.0 + authorization: + - DUMMY + method: GET + uri: https://urs.earthdata.nasa.gov/profile + response: + body: + string: '' + headers: + Cache-Control: + - no-cache + Connection: + - keep-alive + Content-Type: + - text/html; charset=utf-8 + Date: + - Thu, 21 Nov 2024 12:51:58 GMT + Location: + - https://urs.earthdata.nasa.gov/home + Referrer-Policy: + - strict-origin-when-cross-origin + Server: + - nginx/1.22.1 + Set-Cookie: + - _urs-gui_session=8837bf3780fe10ce7630df3ef30ffce2; path=/; expires=Fri, 22 + Nov 2024 12:51:58 GMT; HttpOnly + Strict-Transport-Security: + - max-age=31536000 + Transfer-Encoding: + - chunked + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Request-Id: + - 85bb944e-f092-418c-be4f-5d6f013e036c + X-Runtime: + - '0.007435' + X-XSS-Protection: + - 1; mode=block + status: + code: 302 + message: Found +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Cookie: + - _urs-gui_session=8837bf3780fe10ce7630df3ef30ffce2 + User-Agent: + - earthaccess v0.11.0 + authorization: + - DUMMY + method: GET + uri: https://urs.earthdata.nasa.gov/home + response: + body: + string: !!binary | + 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 + Evq/7vwbkpnUAssjAAA= + headers: + Cache-Control: + - no-store + Connection: + - keep-alive + Content-Encoding: + - gzip + Content-Type: + - text/html; charset=utf-8 + Date: + - Thu, 21 Nov 2024 12:51:58 GMT + ETag: + - W/"1d3312a613414086ef2df8b128aef3df" + Expires: + - Fri, 01 Jan 1990 00:00:00 GMT + Pragma: + - no-cache + Referrer-Policy: + - strict-origin-when-cross-origin + Server: + - nginx/1.22.1 + Set-Cookie: + - _urs-gui_session=8837bf3780fe10ce7630df3ef30ffce2; path=/; expires=Fri, 22 + Nov 2024 12:51:58 GMT; HttpOnly + Strict-Transport-Security: + - max-age=31536000 + Transfer-Encoding: + - chunked + Vary: + - Accept + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Request-Id: + - 9dc56a0d-fd99-4d31-aaf6-e54ca29d5395 + X-Runtime: + - '0.014591' + X-XSS-Protection: + - 1; mode=block + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - earthaccess v0.11.0 + authorization: + - DUMMY + method: GET + uri: https://cmr.earthdata.nasa.gov/search/granules.umm_json?bounding_box=-91.705,48.179,-91.459,48.3&concept_id%5B%5D=C2021957657-LPCLOUD&temporal%5B%5D=2024-10-09T00:00:01Z,2024-10-09T23:59:59Z&page_size=0 + response: + body: + string: !!binary | + H4sIAAAAAAAAAKtWysgsKVayMtJRKsnPz1ayMjGw1FHKLEnNBQpGx9YCAM1+SUAgAAAA + headers: + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - CMR-Hits, CMR-Request-Id, X-Request-Id, CMR-Scroll-Id, CMR-Search-After, CMR-Timed-Out, + CMR-Shapefile-Original-Point-Count, CMR-Shapefile-Simplified-Point-Count + CMR-Hits: + - '2' + CMR-Request-Id: + - 0564fe69-09db-4747-8150-2ce86c26fec1 + CMR-Took: + - '410' + Connection: + - keep-alive + Content-Encoding: + - gzip + Content-MD5: + - 5077bd3a76a9d558029d9d3bfa1247f4 + Content-SHA1: + - 0fc9ceda164b9cdc838fa22418c3bec2035d4385 + Content-Type: + - application/vnd.nasa.cmr.umm_results+json;version=1.6.6; charset=utf-8 + Date: + - Thu, 21 Nov 2024 12:52:00 GMT + Server: + - ServerTokens ProductOnly + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding, User-Agent + Via: + - 1.1 e7d0317d0bc6b15fd0158376ae9d8bfc.cloudfront.net (CloudFront) + X-Amz-Cf-Id: + - nBEkcGFblUwUxaLPiZ7UJIEGLJi8ixqf2dgX82u8kWHEVkQE9yTNig== + X-Amz-Cf-Pop: + - MSP50-C1 + X-Cache: + - Miss from cloudfront + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Request-Id: + - nBEkcGFblUwUxaLPiZ7UJIEGLJi8ixqf2dgX82u8kWHEVkQE9yTNig== + X-XSS-Protection: + - 1; mode=block + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - earthaccess v0.11.0 + authorization: + - DUMMY + method: GET + uri: https://cmr.earthdata.nasa.gov/search/granules.umm_json?bounding_box=-91.705,48.179,-91.459,48.3&concept_id%5B%5D=C2021957657-LPCLOUD&temporal%5B%5D=2024-10-09T00:00:01Z,2024-10-09T23:59:59Z&page_size=100 + response: + body: + string: !!binary | + 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 + headers: + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - CMR-Hits, CMR-Request-Id, X-Request-Id, CMR-Scroll-Id, CMR-Search-After, CMR-Timed-Out, + CMR-Shapefile-Original-Point-Count, CMR-Shapefile-Simplified-Point-Count + CMR-Hits: + - '2' + CMR-Request-Id: + - 3e87cee1-d489-4f3d-948d-d9ea5d260c89 + CMR-Search-After: + - '["lpcloud",1728492695011,3263857658]' + CMR-Took: + - '559' + Connection: + - keep-alive + Content-Encoding: + - gzip + Content-MD5: + - b112368d24167ec3c3ee8a2f68a8397d + Content-SHA1: + - 6bc5986c305dd8a888d82302f85b045dafa7026e + Content-Type: + - application/vnd.nasa.cmr.umm_results+json;version=1.6.6; charset=utf-8 + Date: + - Thu, 21 Nov 2024 12:52:00 GMT + Server: + - ServerTokens ProductOnly + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding, User-Agent + Via: + - 1.1 e7d0317d0bc6b15fd0158376ae9d8bfc.cloudfront.net (CloudFront) + X-Amz-Cf-Id: + - 48wRj8jujzHbscs_z9juZDANl0igaeUJCtNCW-cBd9Et-p0pghXWzg== + X-Amz-Cf-Pop: + - MSP50-C1 + X-Cache: + - Miss from cloudfront + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Request-Id: + - 48wRj8jujzHbscs_z9juZDANl0igaeUJCtNCW-cBd9Et-p0pghXWzg== + X-XSS-Protection: + - 1; mode=block + status: + code: 200 + message: OK +version: 1 diff --git a/tests/test_app.py b/tests/test_app.py index 6786a45..2aab8d0 100644 --- a/tests/test_app.py +++ b/tests/test_app.py @@ -9,7 +9,6 @@ from fastapi.testclient import TestClient from httpx import Response from PIL import Image -from rasterio.errors import NotGeoreferencedWarning from titiler.cmr.timeseries import TimeseriesMediaType from titiler.core.models.mapbox import TileJSON @@ -139,20 +138,16 @@ def test_rasterio_feature( app, mock_cmr_get_assets, rasterio_query_params, mn_geojson ) -> None: """Test /feature endpoint for rasterio backend""" - with pytest.warns( - (PendingDeprecationWarning, NotGeoreferencedWarning), - match=r"is_tiled|no geotransform", - ): - response = app.post( - "/feature", - params={ - **rasterio_query_params, - "format": "tif", - "width": 100, - "height": 100, - }, - json=mn_geojson, - ) + response = app.post( + "/feature", + params={ + **rasterio_query_params, + "format": "tif", + "width": 100, + "height": 100, + }, + json=mn_geojson, + ) assert response.status_code == 200 assert response.headers["content-type"] == "image/tiff; application=geotiff" @@ -166,17 +161,13 @@ def test_rasterio_part( ) -> None: """Test /part endpoint for rasterio backend""" - with pytest.warns( - (PendingDeprecationWarning, NotGeoreferencedWarning), - match=r"is_tiled|no geotransform", - ): - response = app.get( - f"/bbox/{','.join(str(coord) for coord in mn_bounds)}/100x100.tif", - params={ - **rasterio_query_params, - "format": "tif", - }, - ) + response = app.get( + f"/bbox/{','.join(str(coord) for coord in mn_bounds)}/100x100.tif", + params={ + **rasterio_query_params, + "format": "tif", + }, + ) assert response.status_code == 200 assert response.headers["content-type"] == "image/tiff; application=geotiff" @@ -199,9 +190,9 @@ def test_xarray_statistics( # numbers corroborated by QGIS zonal stats for this file and polygon variable = xarray_query_params["variable"] - assert stats[variable]["median"] == 0.79 - assert stats[variable]["sum"] == 2376.73 - assert round(stats[variable]["mean"], 3) == 0.523 + assert round(stats[variable]["median"], 1) == 0.8 + assert round(stats[variable]["sum"]) == 2420 + assert round(stats[variable]["mean"], 2) == 0.53 @pytest.mark.vcr @@ -250,10 +241,10 @@ def test_xarray_part( assert response.headers["content-type"] == "image/png" image_data = io.BytesIO(response.content) - Image.open(image_data) + image = Image.open(image_data) # Check dimensions - # assert image.size == size, f"Expected image size {size}, but got {image.size}" + assert image.size == size, f"Expected image size {size}, but got {image.size}" def test_timeseries_statistics( diff --git a/titiler/cmr/factory.py b/titiler/cmr/factory.py index 707be27..7f6b819 100644 --- a/titiler/cmr/factory.py +++ b/titiler/cmr/factory.py @@ -3,13 +3,13 @@ import json import os import re -from dataclasses import dataclass, field -from typing import Any, Dict, Literal, Optional, Tuple, Type, Union +from typing import Any, Dict, List, Literal, Optional, Tuple, Type, Union from urllib.parse import urlencode import jinja2 import numpy import orjson +from attrs import define, field from fastapi import Body, Depends, Path, Query from fastapi.responses import ORJSONResponse from geojson_pydantic import Feature, FeatureCollection @@ -34,7 +34,7 @@ cmr_query, ) from titiler.cmr.enums import MediaType -from titiler.cmr.reader import MultiFilesBandsReader, ZarrReader +from titiler.cmr.reader import MultiFilesBandsReader, xarray_open_dataset from titiler.core.algorithm import algorithms as available_algorithms from titiler.core.dependencies import ( CoordCRSParams, @@ -44,12 +44,13 @@ PartFeatureParams, StatisticsParams, ) -from titiler.core.factory import BaseTilerFactory, img_endpoint_params +from titiler.core.factory import TilerFactory, img_endpoint_params from titiler.core.models.mapbox import TileJSON from titiler.core.models.responses import MultiBaseStatisticsGeoJSON from titiler.core.resources.enums import ImageType, OptionalHeader from titiler.core.resources.responses import GeoJSONResponse from titiler.core.utils import render_image +from titiler.xarray.io import Reader as XarrayReader jinja2_env = jinja2.Environment( loader=jinja2.ChoiceLoader([jinja2.PackageLoader(__package__, "templates")]) @@ -109,6 +110,7 @@ def parse_reader_options( rasterio_params: RasterioParams, zarr_params: ZarrParams, reader_params: ReaderParams, + image_params: Optional[PartFeatureParams] = None, ) -> Tuple[Type[BaseReader], Dict[str, Any], Dict[str, Any]]: """Convert rasterio and zarr parameters into a reader and a set of reader_options and read_options""" @@ -120,10 +122,11 @@ def parse_reader_options( resampling_method = rasterio_params.resampling_method or "nearest" if reader_params.backend == "xarray": - reader = ZarrReader + reader = XarrayReader read_options = {} options = { + "opener": xarray_open_dataset, "variable": zarr_params.variable, "decode_times": zarr_params.decode_times, "drop_dim": zarr_params.drop_dim, @@ -162,11 +165,14 @@ def parse_reader_options( read_options = {k: v for k, v in options.items() if v is not None} reader_options = {} + if image_params: + read_options.update(image_params.as_dict()) + return reader, read_options, reader_options -@dataclass -class Endpoints(BaseTilerFactory): +@define(kw_only=True) +class Endpoints(TilerFactory): """Endpoints Factory.""" reader: Optional[Type[BaseReader]] = field(default=None) # type: ignore @@ -179,6 +185,7 @@ class Endpoints(BaseTilerFactory): histogram_dependency: Type[DefaultDependency] = HistogramParams img_part_dependency: Type[DefaultDependency] = PartFeatureParams + optional_headers: List[OptionalHeader] = field(factory=list) templates: Jinja2Templates = DEFAULT_TEMPLATES title: str = "TiTiler-CMR" @@ -545,7 +552,7 @@ def tiles_endpoint( image, output_format=format, colormap=colormap, - **render_params, + **render_params.as_dict(), ) return Response(content, media_type=media_type) @@ -757,6 +764,7 @@ def bbox_image( rasterio_params=rasterio_params, zarr_params=zarr_params, reader_params=reader_params, + image_params=image_params, ) with CMRBackend( @@ -772,8 +780,6 @@ def bbox_image( } ) - read_options.update(image_params) - image, assets = src_dst.part( bbox=[minx, miny, maxx, maxy], cmr_query=query, @@ -797,7 +803,7 @@ def bbox_image( image, output_format=format, colormap=colormap or dst_colormap, - **render_params, + **render_params.as_dict(), ) headers: Dict[str, str] = {} @@ -850,6 +856,7 @@ def feature_image( rasterio_params=rasterio_params, zarr_params=zarr_params, reader_params=reader_params, + image_params=image_params, ) with CMRBackend( @@ -865,7 +872,7 @@ def feature_image( } ) - read_options.update(image_params) + read_options.update(image_params.as_dict()) image, assets = src_dst.feature( geojson.model_dump(exclude_none=True), @@ -888,7 +895,7 @@ def feature_image( image, output_format=format, colormap=colormap, - **render_params, + **render_params.as_dict(), ) headers: Dict[str, str] = {} @@ -940,6 +947,7 @@ def geojson_statistics( rasterio_params=rasterio_params, zarr_params=zarr_params, reader_params=reader_params, + image_params=image_params, ) with CMRBackend( @@ -958,7 +966,7 @@ def geojson_statistics( } ) - read_options.update(image_params) + read_options.update(image_params.as_dict(exclude_none=True)) image, _ = src_dst.feature( shape, @@ -977,12 +985,14 @@ def geojson_statistics( image = post_process(image) # set band name for statistics method - if not image.band_names and reader_params.backend == "xarray": + if reader_params.backend == "xarray" and ( + image.band_names == ["value"] or not image.band_names + ): image.band_names = [zarr_params.variable] stats = image.statistics( - **stats_params, - hist_options={**histogram_params}, + **stats_params.as_dict(), + hist_options=histogram_params.as_dict(), coverage=coverage_array, ) diff --git a/titiler/cmr/reader.py b/titiler/cmr/reader.py index 979629b..417ebad 100644 --- a/titiler/cmr/reader.py +++ b/titiler/cmr/reader.py @@ -3,10 +3,9 @@ Originaly from titiler-xarray """ -import contextlib import pickle -import re -from typing import Any, Dict, List, Optional, Type +from typing import Any, Dict, Optional, Type +from urllib.parse import urlparse import attr import earthaccess @@ -16,12 +15,9 @@ import xarray from cachetools import TTLCache from morecantile import TileMatrixSet -from rasterio.crs import CRS from rio_tiler.constants import WEB_MERCATOR_TMS, WGS84_CRS from rio_tiler.errors import InvalidBandName from rio_tiler.io import BaseReader, MultiBandReader, Reader -from rio_tiler.io.xarray import XarrayReader -from rio_tiler.types import BBox from titiler.cmr.settings import CacheSettings @@ -30,35 +26,6 @@ cache_client: Any = TTLCache(maxsize=cache_config.maxsize, ttl=cache_config.ttl) -def parse_protocol(src_path: str, reference: Optional[bool] = False): - """ - Parse protocol from path. - """ - match = re.match(r"^(s3|https|http)", src_path) - protocol = "file" - if match: - protocol = match.group(0) - - # override protocol if reference - if reference: - protocol = "reference" - - return protocol - - -def xarray_engine(src_path: str): - """ - Parse xarray engine from path. - """ - # ".hdf", ".hdf5", ".h5" will be supported once we have tests + expand the type permitted for the group parameter - H5NETCDF_EXTENSIONS = [".nc", ".nc4"] - lower_filename = src_path.lower() - if any(lower_filename.endswith(ext) for ext in H5NETCDF_EXTENSIONS): - return "h5netcdf" - else: - return "zarr" - - def get_filesystem( src_path: str, protocol: str, @@ -100,20 +67,26 @@ def get_filesystem( def xarray_open_dataset( src_path: str, group: Optional[Any] = None, - reference: Optional[bool] = False, decode_times: Optional[bool] = True, - consolidated: Optional[bool] = True, s3_credentials: Optional[Dict] = None, ) -> xarray.Dataset: - """Open dataset.""" + """Modified version of titiler.xarray.io.xarray_open_dataset with + custom handler for earthaccess authentication over https + """ # Generate cache key and attempt to fetch the dataset from cache cache_key = f"{src_path}_{group}" if group is not None else src_path data_bytes = cache_client.get(cache_key, None) if data_bytes: return pickle.loads(data_bytes) - protocol = parse_protocol(src_path, reference=reference) - xr_engine = xarray_engine(src_path) + parsed = urlparse(src_path) + protocol = parsed.scheme or "file" + + if any(src_path.lower().endswith(ext) for ext in [".nc", ".nc4"]): + xr_engine = "h5netcdf" + else: + xr_engine = "zarr" + file_handler = get_filesystem( src_path, protocol, xr_engine, s3_credentials=s3_credentials ) @@ -126,25 +99,23 @@ def xarray_open_dataset( } # Argument if we're opening a datatree - if isinstance(group, int): + if group is not None: xr_open_args["group"] = group # NetCDF arguments if xr_engine == "h5netcdf": - xr_open_args["engine"] = "h5netcdf" - xr_open_args["lock"] = False - - else: - # Zarr arguments - xr_open_args["engine"] = "zarr" - xr_open_args["consolidated"] = consolidated + xr_open_args.update( + { + "engine": "h5netcdf", + "lock": False, + } + ) - # Additional arguments when dealing with a reference file. - if reference: - xr_open_args["consolidated"] = False - xr_open_args["backend_kwargs"] = {"consolidated": False} + ds = xarray.open_dataset(file_handler, **xr_open_args) - ds = xarray.open_dataset(file_handler, **xr_open_args) + # Fallback to Zarr + else: + ds = xarray.open_zarr(file_handler, **xr_open_args) # Serialize the dataset to bytes using pickle cache_client[cache_key] = pickle.dumps(ds) @@ -214,84 +185,6 @@ def get_variable( return da -@attr.s -class ZarrReader(XarrayReader): - """ZarrReader: Open Zarr file and access DataArray.""" - - src_path: str = attr.ib() - variable: str = attr.ib() - - # xarray.Dataset options - reference: bool = attr.ib(default=False) - decode_times: bool = attr.ib(default=False) - group: Optional[Any] = attr.ib(default=None) - consolidated: Optional[bool] = attr.ib(default=True) - s3_credentials: Optional[Dict] = attr.ib(default=None) - - # xarray.DataArray options - time_slice: Optional[str] = attr.ib(default=None) - drop_dim: Optional[str] = attr.ib(default=None) - - tms: TileMatrixSet = attr.ib(default=WEB_MERCATOR_TMS) - geographic_crs: CRS = attr.ib(default=WGS84_CRS) - - ds: xarray.Dataset = attr.ib(init=False) - input: xarray.DataArray = attr.ib(init=False) - - bounds: BBox = attr.ib(init=False) - crs: CRS = attr.ib(init=False) - - _minzoom: int = attr.ib(init=False, default=None) - _maxzoom: int = attr.ib(init=False, default=None) - - _dims: List = attr.ib(init=False, factory=list) - _ctx_stack = attr.ib(init=False, factory=contextlib.ExitStack) - - def __attrs_post_init__(self): - """Set bounds and CRS.""" - self.ds = self._ctx_stack.enter_context( - xarray_open_dataset( - self.src_path, - group=self.group, - reference=self.reference, - consolidated=self.consolidated, - s3_credentials=self.s3_credentials, - ), - ) - self.input = get_variable( - self.ds, - self.variable, - time_slice=self.time_slice, - drop_dim=self.drop_dim, - ) - - self.bounds = tuple(self.input.rio.bounds()) - self.crs = self.input.rio.crs - - self._dims = [ - d - for d in self.input.dims - if d not in [self.input.rio.x_dim, self.input.rio.y_dim] - ] - - @classmethod - def list_variables( - cls, - src_path: str, - group: Optional[Any] = None, - reference: Optional[bool] = False, - consolidated: Optional[bool] = True, - ) -> List[str]: - """List available variable in a dataset.""" - with xarray_open_dataset( - src_path, - group=group, - reference=reference, - consolidated=consolidated, - ) as ds: - return list(ds.data_vars) # type: ignore - - @attr.s class MultiFilesBandsReader(MultiBandReader): """Multiple Files as Bands.""" diff --git a/uv.lock b/uv.lock index 164680d..7135ae9 100644 --- a/uv.lock +++ b/uv.lock @@ -566,7 +566,7 @@ wheels = [ [[package]] name = "cogeo-mosaic" -version = "7.2.0" +version = "8.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "attrs" }, @@ -584,9 +584,9 @@ dependencies = [ { name = "shapely" }, { name = "supermorecado" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b5/2a/4efe88ac2b4e20a6827a9aa89322d81366fc5532c96d2644b5814f41350b/cogeo_mosaic-7.2.0.tar.gz", hash = "sha256:1fa0168f83adcd1065ab49e7c67bc82a507bba895717ac596f8e26b08bc249cb", size = 33458 } +sdist = { url = "https://files.pythonhosted.org/packages/25/28/302c4eb67bbdb09df40896055dac108347a4f8209f8b54598ca076e8e297/cogeo_mosaic-8.0.0.tar.gz", hash = "sha256:04ed86b84da3be606e87248d565b6cbc423fd153400e9a763edfae0af4a099ae", size = 33714 } wheels = [ - { url = "https://files.pythonhosted.org/packages/95/c7/dad3d92c8306200c20b4c02cbde636e23950081bb0731f6e4b3e059e03e4/cogeo_mosaic-7.2.0-py3-none-any.whl", hash = "sha256:ed63cb8f8cbc02fafd27bc30ca41956319ece55012629483b274832b72d2802a", size = 40123 }, + { url = "https://files.pythonhosted.org/packages/25/73/b958c5009640ead469cb30b82378a81e3a5d1a8db6b566c1d53ef1c65b96/cogeo_mosaic-8.0.0-py3-none-any.whl", hash = "sha256:551e0ad8629ce3005f96c0a4931b7243e6d22bc2be067435be4f913df34b33c5", size = 40193 }, ] [[package]] @@ -1038,14 +1038,14 @@ wheels = [ [[package]] name = "geojson-pydantic" -version = "1.1.1" +version = "1.1.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pydantic" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/58/39/6adc983a24a90862d7c14b7e2abde0897d3b195138c8b8cc41117b7df218/geojson_pydantic-1.1.1.tar.gz", hash = "sha256:9c4b3e0a384a41fc919f50766979a559efae2f04ac5936f3e7cb3e1cc28927a7", size = 9185 } +sdist = { url = "https://files.pythonhosted.org/packages/1d/92/f9fa6432ca49e5e702ed9e95155e919440087f3e3f99bb6ad5d06d153813/geojson_pydantic-1.1.2.tar.gz", hash = "sha256:be3b686e059dad95caff1ea411f020333b2c6182d87fcc4f69d1cbde2cca2c09", size = 9231 } wheels = [ - { url = "https://files.pythonhosted.org/packages/a5/5e/3260eda6f1a90721ad2c881d70ec9756785cdab6225785e0a19edf677dc5/geojson_pydantic-1.1.1-py3-none-any.whl", hash = "sha256:3d8adeee9ee0e1bb658c262fcb2e0da44090e44c0123ea95f989e484bdf123d9", size = 8658 }, + { url = "https://files.pythonhosted.org/packages/26/ee/b0f25682efc6a799156d2ede4540d102f0e455119cc8436135911e387a1f/geojson_pydantic-1.1.2-py3-none-any.whl", hash = "sha256:2488736307c1717469419110b31413277fc1095eb2137592d5417e6100268d0f", size = 8721 }, ] [[package]] @@ -2858,7 +2858,7 @@ wheels = [ [[package]] name = "rio-tiler" -version = "6.7.0" +version = "7.2.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "attrs" }, @@ -2871,10 +2871,11 @@ dependencies = [ { name = "pydantic" }, { name = "pystac" }, { name = "rasterio" }, + { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/6e/22/b17aadfec04c38f41a3c361d3107eae62a29841ae7ab84f4196dc3182804/rio_tiler-6.7.0.tar.gz", hash = "sha256:c4cbb8c95d9342d09ad52b16233bfddd5b1ff57586306d3f66deb1136ddd0b97", size = 170283 } +sdist = { url = "https://files.pythonhosted.org/packages/18/c3/47c66b958090fcb07d19bc871db7547fe5773975b0a7344a2361427eb1bb/rio_tiler-7.2.2.tar.gz", hash = "sha256:14306102271f71f943efaf54f4d1db4ac5d4775fa4d71011c4fae958c83a580a", size = 172296 } wheels = [ - { url = "https://files.pythonhosted.org/packages/aa/a8/3f2b134660d2a806170b566af31247ac4c2a9720e2b0a4da4379f890f645/rio_tiler-6.7.0-py3-none-any.whl", hash = "sha256:0ced8f80c2e6ba8c7ccdb8b2ef59de1a3a0f524606f990f6aca7a6daa05165bd", size = 263982 }, + { url = "https://files.pythonhosted.org/packages/84/01/430205c9099b98f14a3fa406a2197dc4f920061bbb1bb77af06b9b66af8c/rio_tiler-7.2.2-py3-none-any.whl", hash = "sha256:dbce793a3b85e1b817eb2902a85d3218ccb07411804b0c8d978659bf95920ec1", size = 265906 }, ] [package.optional-dependencies] @@ -3213,7 +3214,7 @@ wheels = [ [[package]] name = "titiler-cmr" -version = "0.1.dev86+g2f8b744.d20241106" +version = "0.1.3.dev1+g697021c.d20241121" source = { editable = "." } dependencies = [ { name = "cftime" }, @@ -3233,6 +3234,7 @@ dependencies = [ { name = "s3fs" }, { name = "titiler-core" }, { name = "titiler-mosaic" }, + { name = "titiler-xarray" }, { name = "xarray" }, ] @@ -3279,18 +3281,19 @@ requires-dist = [ { name = "pytest-mock", marker = "extra == 'test'", specifier = ">=3.14.0" }, { name = "pytest-recording", marker = "extra == 'test'", specifier = ">=0.13.2" }, { name = "python-dateutil", specifier = ">=2.9.0.post0" }, - { name = "rio-tiler", extras = ["s3"], specifier = ">=6.4.0,<7.0" }, + { name = "rio-tiler", extras = ["s3"], specifier = ">=7.2.0,<8.0" }, { name = "rioxarray", specifier = "~=0.13.4" }, { name = "s3fs", specifier = "~=2024.9.0" }, - { name = "titiler-core", specifier = ">=0.18.0,<0.19" }, - { name = "titiler-mosaic", specifier = ">=0.18.0,<0.19" }, + { name = "titiler-core", specifier = ">=0.19.0,<0.20" }, + { name = "titiler-mosaic", specifier = ">=0.19.0,<0.20" }, + { name = "titiler-xarray", specifier = ">=0.19.0,<0.20" }, { name = "uvicorn", marker = "extra == 'uvicorn'" }, { name = "xarray", specifier = "~=2024.9.0" }, ] [[package]] name = "titiler-core" -version = "0.18.9" +version = "0.19.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "fastapi" }, @@ -3304,22 +3307,37 @@ dependencies = [ { name = "simplejson" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/64/b8/6774195c3a9b584d71e42d9cb5858f4daef8358a1be0c0ea404cae026c84/titiler.core-0.18.9.tar.gz", hash = "sha256:52598a2fe78468d5c84641e609728f85dafd6bf181fa2d0e54d5161f1075b677", size = 30123 } +sdist = { url = "https://files.pythonhosted.org/packages/0a/71/6bc0a8ca679eb712a8d594464ddef384226d0530e55089a89ef37e73f3da/titiler.core-0.19.1.tar.gz", hash = "sha256:337cc56c387b19a9ae92fe2f06fe9c0038eb4f73a1a81827207db67d240175d0", size = 34075 } wheels = [ - { url = "https://files.pythonhosted.org/packages/40/0e/178a74ec4cba7159b944878e4a10313b0c63a3d1bcaa3d04c4d9fe432968/titiler.core-0.18.9-py3-none-any.whl", hash = "sha256:5ee3cc58be108a388a0f6a69552f21ac5d64823c6d4814d1c4bd1cc0d86a152b", size = 35142 }, + { url = "https://files.pythonhosted.org/packages/05/c5/4bc3fdc8159fe527040f44caf62f3149006b0236268b8468837a5c2fdd82/titiler.core-0.19.1-py3-none-any.whl", hash = "sha256:a58d5a8730ad03543c49e12a0a47d4ba032ec71cb498eb424ae9b9ad82bc83e8", size = 39176 }, ] [[package]] name = "titiler-mosaic" -version = "0.18.9" +version = "0.19.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cogeo-mosaic" }, { name = "titiler-core" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ca/b4/869b6b4bbda81dd0e54c50f0b8464112dc588c1791f108bb8c5d6e182c30/titiler.mosaic-0.18.9.tar.gz", hash = "sha256:241e80525bde6a583760de8e0fa4a4d6cf1994d306850ec8884bf14fd78a4d3d", size = 7704 } +sdist = { url = "https://files.pythonhosted.org/packages/9a/e5/d45edfab814ba744f9af2ca86c4f58628e8ef02fff1559d5f9912a4719b2/titiler.mosaic-0.19.1.tar.gz", hash = "sha256:e76d1349171f7454aa834c3ede42ab9a0e8596a9ea6669f927bf4c1b6ff64a00", size = 9671 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/51/32/1ed64942bbeca884ac8859a8554f30f47675b679dfeb8b1e1927a218a88a/titiler.mosaic-0.19.1-py3-none-any.whl", hash = "sha256:172d1fdd23ced57ab98210343dbdc1c049b0725ad4e06a5eaafda9c13c0323ae", size = 10054 }, +] + +[[package]] +name = "titiler-xarray" +version = "0.19.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "rio-tiler" }, + { name = "rioxarray" }, + { name = "titiler-core" }, + { name = "xarray" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/62/98/7c6b7b9aed9142abf3c2f09bb724ea752de14b21f707a7b715f5952800a3/titiler.xarray-0.19.1.tar.gz", hash = "sha256:29ea39a1d3e4cd505a066b96992ac8de24f06f66e1dd8f93e7ac0564469ac9b6", size = 9403 } wheels = [ - { url = "https://files.pythonhosted.org/packages/5c/91/00f4dd82eeb1160743710372771a7950e688c79571a6d9961a799668844d/titiler.mosaic-0.18.9-py3-none-any.whl", hash = "sha256:2316ab94d625b02bdcd5f7787f0e84de978e73e41574d5f5a3f665639a64f52c", size = 8141 }, + { url = "https://files.pythonhosted.org/packages/20/d7/bb31babb4a2b29b85407daf786c1ac2c2bdf668fc66db9488a6e282a5c6f/titiler.xarray-0.19.1-py3-none-any.whl", hash = "sha256:c9a079c0e7404b6d5cc491aed4c16d73deda7d4a2ff7c18a2b140508c543e2a6", size = 9930 }, ] [[package]]