rio-tiler 7.9.2__py3-none-any.whl → 8.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,242 @@
1
+ """rio_tiler.mosaic.backend: base Backend class."""
2
+
3
+ import abc
4
+ import logging
5
+ from typing import Any, Type
6
+
7
+ import attr
8
+ from morecantile import TileMatrixSet
9
+ from pydantic import BaseModel, ConfigDict, Field
10
+ from rasterio.crs import CRS
11
+ from rasterio.features import bounds as featureBounds
12
+ from rasterio.features import geometry_mask
13
+
14
+ from rio_tiler.constants import WEB_MERCATOR_TMS, WGS84_CRS
15
+ from rio_tiler.errors import NoAssetFoundError, PointOutsideBounds
16
+ from rio_tiler.io import BaseReader, MultiBandReader, MultiBaseReader, Reader
17
+ from rio_tiler.models import ImageData, PointData
18
+ from rio_tiler.mosaic import mosaic_reader
19
+ from rio_tiler.tasks import multi_values_list
20
+ from rio_tiler.types import BBox
21
+ from rio_tiler.utils import CRS_to_uri, Timer, _validate_shape_input
22
+
23
+ logger = logging.getLogger(__name__)
24
+
25
+
26
+ class MosaicInfo(BaseModel):
27
+ """Mosaic info responses."""
28
+
29
+ bounds: BBox = Field(default=(-180, -90, 180, 90))
30
+ crs: str
31
+
32
+ model_config = ConfigDict(extra="allow")
33
+
34
+
35
+ @attr.s
36
+ class BaseBackend(BaseReader):
37
+ """Base Class for mosaic backend.
38
+
39
+ Attributes:
40
+ input (str): mosaic path.
41
+ tms (morecantile.TileMatrixSet, optional): TileMatrixSet grid definition. Defaults to `WebMercatorQuad`.
42
+ reader (rio_tiler.io.BaseReader): Dataset reader. Defaults to `rio_tiler.io.Reader`.
43
+ reader_options (dict): Options to forward to the reader config.
44
+ bounds (tuple): mosaic bounds (left, bottom, right, top). **READ ONLY attribute**.
45
+ crs (rasterio.crs.CRS): mosaic crs in which its bounds is defined. **READ ONLY attribute**.
46
+ minzoom (int): mosaic minimum zoom level. **READ ONLY attribute**.
47
+ maxzoom (int): mosaic maximum zoom level. **READ ONLY attribute**.
48
+
49
+ """
50
+
51
+ input: str = attr.ib()
52
+ tms: TileMatrixSet = attr.ib(default=WEB_MERCATOR_TMS)
53
+
54
+ reader: Type[BaseReader] | Type[MultiBaseReader] | Type[MultiBandReader] = attr.ib(
55
+ default=Reader
56
+ )
57
+ reader_options: dict = attr.ib(factory=dict)
58
+
59
+ bounds: BBox = attr.ib(init=False)
60
+ crs: CRS = attr.ib(init=False)
61
+
62
+ minzoom: int = attr.ib(init=False)
63
+ maxzoom: int = attr.ib(init=False)
64
+
65
+ @abc.abstractmethod
66
+ def assets_for_tile(self, x: int, y: int, z: int, **kwargs: Any) -> list[Any]:
67
+ """Retrieve assets for tile."""
68
+
69
+ @abc.abstractmethod
70
+ def assets_for_point(
71
+ self,
72
+ lng: float,
73
+ lat: float,
74
+ coord_crs: CRS | None = None,
75
+ **kwargs: Any,
76
+ ) -> list[Any]:
77
+ """Retrieve assets for point."""
78
+
79
+ @abc.abstractmethod
80
+ def assets_for_bbox(
81
+ self,
82
+ xmin: float,
83
+ ymin: float,
84
+ xmax: float,
85
+ ymax: float,
86
+ coord_crs: CRS | None = None,
87
+ **kwargs,
88
+ ) -> list[Any]:
89
+ """Retrieve assets for bbox."""
90
+
91
+ def asset_name(self, asset: Any) -> str:
92
+ """Get asset name."""
93
+ return str(asset)
94
+
95
+ def info(self) -> MosaicInfo: # type: ignore
96
+ """Mosaic info."""
97
+ return MosaicInfo(
98
+ bounds=self.bounds,
99
+ crs=CRS_to_uri(self.crs) or self.crs.to_wkt(),
100
+ )
101
+
102
+ def point( # type: ignore
103
+ self,
104
+ lon: float,
105
+ lat: float,
106
+ coord_crs: CRS = WGS84_CRS,
107
+ search_options: dict | None = None,
108
+ **kwargs: Any,
109
+ ) -> list[tuple[str, PointData]]:
110
+ """Get Point value from multiple assets."""
111
+ search_options = search_options or {}
112
+ mosaic_assets = self.assets_for_point(
113
+ lon, lat, coord_crs=coord_crs, **search_options
114
+ )
115
+ if not mosaic_assets:
116
+ raise NoAssetFoundError(f"No assets found for point ({lon},{lat})")
117
+
118
+ def _reader(
119
+ asset: Any, lon: float, lat: float, coord_crs: CRS, **kwargs
120
+ ) -> PointData:
121
+ with self.reader(asset, **self.reader_options) as src_dst:
122
+ return src_dst.point(lon, lat, coord_crs=coord_crs, **kwargs)
123
+
124
+ if "allowed_exceptions" not in kwargs:
125
+ kwargs.update({"allowed_exceptions": (PointOutsideBounds,)})
126
+
127
+ logger.info(
128
+ f"reading Point for {len(mosaic_assets)} assets with reader: {self.reader}"
129
+ )
130
+ return [
131
+ (self.asset_name(asset), pt)
132
+ for asset, pt in multi_values_list(
133
+ mosaic_assets, _reader, lon, lat, coord_crs, **kwargs
134
+ )
135
+ ]
136
+
137
+ def tile( # type: ignore
138
+ self,
139
+ x: int,
140
+ y: int,
141
+ z: int,
142
+ search_options: dict | None = None,
143
+ **kwargs: Any,
144
+ ) -> tuple[ImageData, list[str]]:
145
+ """Get Tile from multiple assets."""
146
+ timings = []
147
+ with Timer() as t:
148
+ search_options = search_options or {}
149
+ mosaic_assets = self.assets_for_tile(x, y, z, **search_options)
150
+ timings.append(("search", round(t.elapsed * 1000, 2)))
151
+
152
+ if not mosaic_assets:
153
+ raise NoAssetFoundError(f"No assets found for tile {z}-{x}-{y}")
154
+
155
+ def _reader(asset: Any, x: int, y: int, z: int, **kwargs: Any) -> ImageData:
156
+ with self.reader(asset, tms=self.tms, **self.reader_options) as src_dst:
157
+ return src_dst.tile(x, y, z, **kwargs)
158
+
159
+ logger.info(
160
+ f"reading Tile for {len(mosaic_assets)} assets with reader: {self.reader}"
161
+ )
162
+ with Timer() as t:
163
+ img, asset_used = mosaic_reader(mosaic_assets, _reader, x, y, z, **kwargs)
164
+ timings.append(("mosaicking", round(t.elapsed * 1000, 2)))
165
+ img.metadata = {**img.metadata, "timings": timings}
166
+
167
+ asset_used = [self.asset_name(asset) for asset in asset_used]
168
+ return img, asset_used
169
+
170
+ def part( # type: ignore
171
+ self,
172
+ bbox: BBox,
173
+ bounds_crs: CRS = WGS84_CRS,
174
+ search_options: dict | None = None,
175
+ **kwargs: Any,
176
+ ) -> tuple[ImageData, list[str]]:
177
+ """Create an Image from multiple assets for a bbox."""
178
+ xmin, ymin, xmax, ymax = bbox
179
+ timings = []
180
+
181
+ with Timer() as t:
182
+ search_options = search_options or {}
183
+ mosaic_assets = self.assets_for_bbox(
184
+ xmin,
185
+ ymin,
186
+ xmax,
187
+ ymax,
188
+ coord_crs=bounds_crs,
189
+ **search_options,
190
+ )
191
+ timings.append(("search", round(t.elapsed * 1000, 2)))
192
+
193
+ if not mosaic_assets:
194
+ raise NoAssetFoundError("No assets found for bbox input")
195
+
196
+ def _reader(asset: Any, bbox: BBox, bounds_crs: CRS, **kwargs: Any) -> ImageData:
197
+ with self.reader(asset, **self.reader_options) as src_dst:
198
+ return src_dst.part(bbox, bounds_crs=bounds_crs, **kwargs)
199
+
200
+ logger.info(
201
+ f"reading Part for {len(mosaic_assets)} assets with reader: {self.reader}"
202
+ )
203
+ with Timer() as t:
204
+ img, asset_used = mosaic_reader(
205
+ mosaic_assets, _reader, bbox, bounds_crs, **kwargs
206
+ )
207
+ timings.append(("mosaicking", round(t.elapsed * 1000, 2)))
208
+ img.metadata = {**img.metadata, "timings": timings}
209
+
210
+ asset_used = [self.asset_name(asset) for asset in asset_used]
211
+ return img, asset_used
212
+
213
+ def feature( # type: ignore
214
+ self,
215
+ shape: dict,
216
+ shape_crs: CRS = WGS84_CRS,
217
+ search_options: dict | None = None,
218
+ **kwargs: Any,
219
+ ) -> tuple[ImageData, list[str]]:
220
+ """Create an Image from multiple assets for a GeoJSON feature."""
221
+ shape = _validate_shape_input(shape)
222
+ bbox = featureBounds(shape)
223
+
224
+ img, asset_used = self.part(
225
+ bbox,
226
+ bounds_crs=shape_crs,
227
+ search_options=search_options,
228
+ **kwargs,
229
+ )
230
+ img.array.mask = geometry_mask([shape], (img.height, img.width), img.transform)
231
+ return img, asset_used
232
+
233
+ ############################################################################
234
+ # Not Implemented methods
235
+ # BaseReader required those method to be implemented
236
+ def statistics(self):
237
+ """PlaceHolder for statistics."""
238
+ raise NotImplementedError
239
+
240
+ def preview(self):
241
+ """PlaceHolder for preview."""
242
+ raise NotImplementedError
@@ -95,6 +95,7 @@ def mosaic_reader( # noqa: C901
95
95
  crs = img.crs
96
96
  bounds = img.bounds
97
97
  band_names = img.band_names
98
+ band_descriptions = img.band_descriptions
98
99
  pixel_selection.cutline_mask = img.cutline_mask
99
100
  pixel_selection.width = img.width
100
101
  pixel_selection.height = img.height
@@ -135,6 +136,7 @@ def mosaic_reader( # noqa: C901
135
136
  crs=crs,
136
137
  bounds=bounds,
137
138
  band_names=band_names,
139
+ band_descriptions=band_descriptions,
138
140
  metadata={
139
141
  "mosaic_method": pixel_selection.__class__.__name__,
140
142
  "mosaic_assets_count": len(mosaic_assets),
@@ -154,6 +156,7 @@ def mosaic_reader( # noqa: C901
154
156
  crs=crs,
155
157
  bounds=bounds,
156
158
  band_names=band_names,
159
+ band_descriptions=band_descriptions,
157
160
  metadata={
158
161
  "mosaic_method": pixel_selection.__class__.__name__,
159
162
  "mosaic_assets_count": len(mosaic_assets),
@@ -229,6 +232,7 @@ def mosaic_point_reader(
229
232
  crs = pt.crs
230
233
  coordinates = pt.coordinates
231
234
  band_names = pt.band_names
235
+ band_descriptions = pt.band_descriptions
232
236
  pixel_selection.width = 1
233
237
  pixel_selection.height = 1
234
238
  pixel_selection.count = pt.count
@@ -248,6 +252,7 @@ def mosaic_point_reader(
248
252
  crs=crs,
249
253
  coordinates=coordinates,
250
254
  band_names=band_names,
255
+ band_descriptions=band_descriptions,
251
256
  metadata={
252
257
  "mosaic_method": pixel_selection.__class__.__name__,
253
258
  "mosaic_assets_count": len(mosaic_assets),
@@ -267,6 +272,7 @@ def mosaic_point_reader(
267
272
  crs=crs,
268
273
  coordinates=coordinates,
269
274
  band_names=band_names,
275
+ band_descriptions=band_descriptions,
270
276
  metadata={
271
277
  "mosaic_method": pixel_selection.__class__.__name__,
272
278
  "mosaic_assets_count": len(mosaic_assets),
rio_tiler/reader.py CHANGED
@@ -34,7 +34,6 @@ from rio_tiler.utils import (
34
34
  class Options(TypedDict, total=False):
35
35
  """Reader Options."""
36
36
 
37
- force_binary_mask: Optional[bool]
38
37
  nodata: Optional[NoData]
39
38
  vrt_options: Optional[Dict]
40
39
  resampling_method: Optional[RIOResampling]
@@ -76,7 +75,6 @@ def read(
76
75
  max_size: Optional[int] = None,
77
76
  indexes: Optional[Indexes] = None,
78
77
  window: Optional[windows.Window] = None,
79
- force_binary_mask: bool = True,
80
78
  nodata: Optional[NoData] = None,
81
79
  vrt_options: Optional[Dict] = None,
82
80
  out_dtype: Optional[Union[str, numpy.dtype]] = None,
@@ -99,7 +97,6 @@ def read(
99
97
  vrt_options (dict, optional): Options to be passed to the rasterio.warp.WarpedVRT class.
100
98
  resampling_method (RIOResampling, optional): RasterIO resampling algorithm. Defaults to `nearest`.
101
99
  reproject_method (WarpResampling, optional): WarpKernel resampling algorithm. Defaults to `nearest`.
102
- force_binary_mask (bool, optional): Cast returned mask to binary values (0 or 255). Defaults to `True`.
103
100
  unscale (bool, optional): Apply 'scales' and 'offsets' on output data value. Defaults to `False`.
104
101
  post_process (callable, optional): Function to apply on output data and mask values.
105
102
 
@@ -258,37 +255,33 @@ def read(
258
255
  # We only add dataset statistics if we have them for all the indexes
259
256
  dataset_statistics = stats if len(stats) == len(indexes) else None
260
257
 
261
- # TODO: DEPRECATED, masked array are already using bool
262
- if force_binary_mask:
263
- pass
264
-
258
+ scales = numpy.array(dataset.scales)[numpy.array(indexes) - 1]
259
+ offsets = numpy.array(dataset.offsets)[numpy.array(indexes) - 1]
265
260
  if unscale:
266
261
  data = data.astype("float32", casting="unsafe")
267
-
268
- # reshaped to match data
269
- scales = numpy.array(dataset.scales)[numpy.array(indexes) - 1].reshape(
270
- (-1, 1, 1)
271
- )
272
- offsets = numpy.array(dataset.offsets)[numpy.array(indexes) - 1].reshape(
273
- (-1, 1, 1)
274
- )
275
-
276
- numpy.multiply(data, scales, out=data, casting="unsafe")
277
- numpy.add(data, offsets, out=data, casting="unsafe")
262
+ numpy.multiply(data, scales.reshape((-1, 1, 1)), out=data, casting="unsafe")
263
+ numpy.add(data, offsets.reshape((-1, 1, 1)), out=data, casting="unsafe")
278
264
 
279
265
  # apply scale/offsets to stats
280
266
  if dataset_statistics:
281
- scales = numpy.array(dataset.scales)[numpy.array(indexes) - 1].reshape(
282
- (-1, 1)
267
+ stats_array = numpy.array(dataset_statistics)
268
+ numpy.multiply(
269
+ stats_array,
270
+ scales.reshape((-1, 1)),
271
+ out=stats_array,
272
+ casting="unsafe",
283
273
  )
284
- offsets = numpy.array(dataset.offsets)[numpy.array(indexes) - 1].reshape(
285
- (-1, 1)
274
+ numpy.add(
275
+ stats_array,
276
+ offsets.reshape((-1, 1)),
277
+ out=stats_array,
278
+ casting="unsafe",
286
279
  )
287
- stats_array = numpy.array(dataset_statistics)
288
- numpy.multiply(stats_array, scales, out=stats_array, casting="unsafe")
289
- numpy.add(stats_array, offsets, out=stats_array, casting="unsafe")
290
280
  dataset_statistics = [tuple(s) for s in stats_array.tolist()]
291
281
 
282
+ scales = numpy.zeros(len(indexes)) + 1.0
283
+ offsets = numpy.zeros(len(indexes))
284
+
292
285
  if post_process:
293
286
  data = post_process(data)
294
287
 
@@ -301,8 +294,12 @@ def read(
301
294
  bounds=out_bounds,
302
295
  crs=dataset.crs,
303
296
  band_names=[f"b{idx}" for idx in indexes],
297
+ band_descriptions=[dataset.descriptions[ix - 1] or "" for idx in indexes],
304
298
  dataset_statistics=dataset_statistics,
305
299
  metadata=dataset.tags(),
300
+ nodata=nodata,
301
+ scales=scales.tolist(),
302
+ offsets=offsets.tolist(),
306
303
  )
307
304
 
308
305
 
@@ -319,7 +316,6 @@ def part(
319
316
  minimum_overlap: Optional[float] = None,
320
317
  padding: Optional[int] = None,
321
318
  buffer: Optional[float] = None,
322
- force_binary_mask: bool = True,
323
319
  nodata: Optional[NoData] = None,
324
320
  vrt_options: Optional[Dict] = None,
325
321
  out_dtype: Optional[Union[str, numpy.dtype]] = None,
@@ -456,7 +452,6 @@ def part(
456
452
  out_dtype=out_dtype,
457
453
  resampling_method=resampling_method,
458
454
  reproject_method=reproject_method,
459
- force_binary_mask=force_binary_mask,
460
455
  unscale=unscale,
461
456
  post_process=post_process,
462
457
  )
@@ -501,7 +496,6 @@ def part(
501
496
  out_dtype=out_dtype,
502
497
  resampling_method=resampling_method,
503
498
  reproject_method=reproject_method,
504
- force_binary_mask=force_binary_mask,
505
499
  unscale=unscale,
506
500
  post_process=post_process,
507
501
  )
@@ -511,6 +505,10 @@ def part(
511
505
  bounds=bounds,
512
506
  crs=img.crs,
513
507
  band_names=img.band_names,
508
+ band_descriptions=img.band_descriptions,
509
+ nodata=img.nodata,
510
+ scales=img.scales,
511
+ offsets=img.offsets,
514
512
  dataset_statistics=img.dataset_statistics,
515
513
  metadata=img.metadata,
516
514
  )
@@ -525,7 +523,6 @@ def part(
525
523
  out_dtype=out_dtype,
526
524
  resampling_method=resampling_method,
527
525
  reproject_method=reproject_method,
528
- force_binary_mask=force_binary_mask,
529
526
  unscale=unscale,
530
527
  post_process=post_process,
531
528
  )
@@ -536,7 +533,6 @@ def point(
536
533
  coordinates: Tuple[float, float],
537
534
  indexes: Optional[Indexes] = None,
538
535
  coord_crs: CRS = WGS84_CRS,
539
- force_binary_mask: bool = True,
540
536
  nodata: Optional[NoData] = None,
541
537
  vrt_options: Optional[Dict] = None,
542
538
  out_dtype: Optional[Union[str, numpy.dtype]] = None,
@@ -642,7 +638,6 @@ def point(
642
638
  window=window,
643
639
  out_dtype=out_dtype,
644
640
  resampling_method=resampling_method,
645
- force_binary_mask=force_binary_mask,
646
641
  unscale=unscale,
647
642
  post_process=post_process,
648
643
  )
@@ -650,8 +645,12 @@ def point(
650
645
  return PointData(
651
646
  img.array[:, 0, 0],
652
647
  band_names=img.band_names,
648
+ band_descriptions=img.band_descriptions,
653
649
  coordinates=coordinates,
654
650
  crs=coord_crs,
655
- metadata=dataset.tags(),
656
651
  pixel_location=(col, row),
652
+ nodata=img.nodata,
653
+ scales=img.scales,
654
+ offsets=img.offsets,
655
+ metadata=img.metadata,
657
656
  )
rio_tiler/tasks.py CHANGED
@@ -99,3 +99,19 @@ def multi_values(
99
99
  asset: val
100
100
  for val, asset in filter_tasks(tasks, allowed_exceptions=allowed_exceptions)
101
101
  }
102
+
103
+
104
+ def multi_values_list(
105
+ asset_list: Sequence,
106
+ reader: Callable,
107
+ *args: Any,
108
+ threads: int = MAX_THREADS,
109
+ allowed_exceptions: Optional[Tuple] = None,
110
+ **kwargs: Any,
111
+ ) -> list[tuple[Any, Any]]:
112
+ """Merge values returned from tasks."""
113
+ tasks = create_tasks(reader, asset_list, threads, *args, **kwargs)
114
+ return [
115
+ (asset, val)
116
+ for val, asset in filter_tasks(tasks, allowed_exceptions=allowed_exceptions)
117
+ ]
rio_tiler/utils.py CHANGED
@@ -1,6 +1,7 @@
1
1
  """rio_tiler.utils: utility functions."""
2
2
 
3
3
  import math
4
+ import time
4
5
  import warnings
5
6
  from io import BytesIO
6
7
  from typing import (
@@ -517,7 +518,7 @@ def linear_rescale(
517
518
  """
518
519
  imin, imax = in_range
519
520
  omin, omax = out_range
520
- im = numpy.clip(image, imin, imax) - imin
521
+ im = numpy.clip(image, imin, imax, dtype=numpy.float64) - imin
521
522
  im = im / numpy.float64(imax - imin)
522
523
  return im * (omax - omin) + omin
523
524
 
@@ -893,3 +894,30 @@ def CRS_to_urn(crs: CRS) -> Optional[str]:
893
894
  return f"urn:ogc:def:crs:{authority}:{version}:{code}"
894
895
 
895
896
  return None
897
+
898
+
899
+ # This code is copied from marblecutter
900
+ # https://github.com/mojodna/marblecutter/blob/master/marblecutter/stats.py
901
+ # License:
902
+ # Original work Copyright 2016 Stamen Design
903
+ # Modified work Copyright 2016-2017 Seth Fitzsimmons
904
+ # Modified work Copyright 2016 American Red Cross
905
+ # Modified work Copyright 2016-2017 Humanitarian OpenStreetMap Team
906
+ # Modified work Copyright 2017 Mapzen
907
+ class Timer(object):
908
+ """Time a code block."""
909
+
910
+ def __enter__(self):
911
+ """Starts timer."""
912
+ self.start = time.time()
913
+ return self
914
+
915
+ def __exit__(self, ty, val, tb):
916
+ """Stops timer."""
917
+ self.end = time.time()
918
+ self.elapsed = self.end - self.start
919
+
920
+ @property
921
+ def from_start(self):
922
+ """Return time elapsed from start."""
923
+ return time.time() - self.start
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rio-tiler
3
- Version: 7.9.2
3
+ Version: 8.0.0
4
4
  Summary: User friendly Rasterio plugin to read raster datasets.
5
5
  Project-URL: Homepage, https://cogeotiff.github.io/rio-tiler/
6
6
  Project-URL: Documentation, https://cogeotiff.github.io/rio-tiler/
@@ -43,54 +43,30 @@ Keywords: COGEO,Cloud Optimized Geotiff,STAC,rasterio,slippy-map
43
43
  Classifier: Intended Audience :: Information Technology
44
44
  Classifier: Intended Audience :: Science/Research
45
45
  Classifier: License :: OSI Approved :: BSD License
46
- Classifier: Programming Language :: Python :: 3.9
47
- Classifier: Programming Language :: Python :: 3.10
48
46
  Classifier: Programming Language :: Python :: 3.11
49
47
  Classifier: Programming Language :: Python :: 3.12
50
48
  Classifier: Programming Language :: Python :: 3.13
51
49
  Classifier: Topic :: Scientific/Engineering :: GIS
52
- Requires-Python: >=3.9
50
+ Requires-Python: >=3.11
53
51
  Requires-Dist: attrs
54
52
  Requires-Dist: cachetools
55
53
  Requires-Dist: color-operations
56
54
  Requires-Dist: httpx
57
- Requires-Dist: morecantile<7.0,>=5.0
55
+ Requires-Dist: morecantile<8.0,>=5.0
58
56
  Requires-Dist: numexpr
59
57
  Requires-Dist: numpy
60
58
  Requires-Dist: pydantic~=2.0
61
59
  Requires-Dist: pystac<2.0,>=1.9
62
60
  Requires-Dist: rasterio>=1.4.0
63
61
  Requires-Dist: typing-extensions
64
- Provides-Extra: benchmark
65
- Requires-Dist: pytest; extra == 'benchmark'
66
- Requires-Dist: pytest-benchmark; extra == 'benchmark'
67
- Provides-Extra: dev
68
- Requires-Dist: bump-my-version; extra == 'dev'
69
- Requires-Dist: pre-commit; extra == 'dev'
70
- Provides-Extra: docs
71
- Requires-Dist: griffe-inherited-docstrings>=1.0.0; extra == 'docs'
72
- Requires-Dist: mkdocs-jupyter>=0.24.5; extra == 'docs'
73
- Requires-Dist: mkdocs-material[imaging]>=9.5; extra == 'docs'
74
- Requires-Dist: mkdocs>=1.4.3; extra == 'docs'
75
- Requires-Dist: mkdocstrings[python]>=0.25.1; extra == 'docs'
76
- Requires-Dist: pygments; extra == 'docs'
77
62
  Provides-Extra: s3
78
63
  Requires-Dist: boto3; extra == 's3'
79
- Provides-Extra: test
80
- Requires-Dist: boto3; extra == 'test'
81
- Requires-Dist: h5netcdf; extra == 'test'
82
- Requires-Dist: morecantile<7.0,>=6.0; extra == 'test'
83
- Requires-Dist: pytest; extra == 'test'
84
- Requires-Dist: pytest-cov; extra == 'test'
85
- Requires-Dist: rioxarray; extra == 'test'
86
- Requires-Dist: vsifile>=0.2; extra == 'test'
87
- Requires-Dist: xarray; extra == 'test'
88
- Provides-Extra: tilebench
89
- Requires-Dist: pytest; extra == 'tilebench'
90
- Requires-Dist: tilebench; extra == 'tilebench'
91
64
  Provides-Extra: xarray
92
65
  Requires-Dist: rioxarray; extra == 'xarray'
93
66
  Requires-Dist: xarray; extra == 'xarray'
67
+ Provides-Extra: zarr
68
+ Requires-Dist: obstore; extra == 'zarr'
69
+ Requires-Dist: zarr~=3.0; extra == 'zarr'
94
70
  Description-Content-Type: text/markdown
95
71
 
96
72
  # rio-tiler
@@ -264,17 +240,17 @@ At the low level, `rio-tiler` is *just* a wrapper around the [rasterio](https://
264
240
  You can install `rio-tiler` using pip
265
241
 
266
242
  ```bash
267
- $ python -m pip install -U pip
268
- $ python -m pip install -U rio-tiler
243
+ python -m pip install -U pip
244
+ python -m pip install -U rio-tiler
269
245
  ```
270
246
 
271
247
  or install from source:
272
248
 
273
249
  ```bash
274
- $ git clone https://github.com/cogeotiff/rio-tiler.git
275
- $ cd rio-tiler
276
- $ python -m pip install -U pip
277
- $ python -m pip install -e .
250
+ git clone https://github.com/cogeotiff/rio-tiler.git
251
+ cd rio-tiler
252
+ python -m pip install -U pip
253
+ python -m pip install -e .
278
254
  ```
279
255
 
280
256
  ## Plugins
@@ -1,16 +1,16 @@
1
- rio_tiler/__init__.py,sha256=cZthX4uSnrRjzSzlllIPZcsJZZDBznuvk3N6NP7saaU,192
2
- rio_tiler/colormap.py,sha256=E2FYp6AysmnSAhj2901XUrgB2q-8OvO8zoe_hmM_UZU,11186
1
+ rio_tiler/__init__.py,sha256=lKZDEOYy6ewX4dX9hskgOUWtXPSxhBHJ4fzw3Yvf6Zc,192
2
+ rio_tiler/colormap.py,sha256=4sG9VIfDAHI-ckQgmci0-U-wL9ZU9exZJszgsrt8wBA,11310
3
3
  rio_tiler/constants.py,sha256=55i-7JZDupTXZdLgxL03KsgM4lAzuGuIVP1zZKktzp0,426
4
- rio_tiler/errors.py,sha256=dnaAHPc5VL7SNKXm00gzlrU_4XIuw5rwzD-9Q2kFJsc,2018
5
- rio_tiler/expression.py,sha256=EVHWgjMqIn4TTPfqT_HV1RWCQlxqOj3OtEr1iUDiFHE,2282
4
+ rio_tiler/errors.py,sha256=GFAuE1AaSvx6dd0z5um9n3y1wVzUyQ5S8qY7_tXdrR8,2178
5
+ rio_tiler/expression.py,sha256=8StB3kqW0EqsW48mu8tlnFNgq48Cyuaj0I-ahmg27Uc,2305
6
6
  rio_tiler/logger.py,sha256=RR8lnW3uVXkFkPa3nNJS_tTndmdiNNDVXpCDGDxGf0A,81
7
- rio_tiler/models.py,sha256=_4JaeOrGInIKJqLSWhM_EZPoB8X8RRPSrR1FIel7Lmk,29293
7
+ rio_tiler/models.py,sha256=ABXuGNTtVI1bBZ90AdyXigwug2P7kg9lrDbLss0h61w,34921
8
8
  rio_tiler/profiles.py,sha256=EAx2JdcaOcMw5PZjxbCqQBXXWMac9mjtpHoVFPJEDNQ,1562
9
9
  rio_tiler/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
- rio_tiler/reader.py,sha256=ELTCGRwl53yKAk1k-KvBD25GXnb1xEsSHh1ajSoVSH0,25170
11
- rio_tiler/tasks.py,sha256=tiQo24rZHBVxids40QkNInuMzDFEei08zYW3I_pkSVE,3157
10
+ rio_tiler/reader.py,sha256=5JVlhJS8Ra8jPPVkjkRw2UuXOnG7mPtKxYlDC9vF6qI,25047
11
+ rio_tiler/tasks.py,sha256=7MwIicDMSCScsbds6crWRa7lRwvvt2cbGQAxybkrRvk,3613
12
12
  rio_tiler/types.py,sha256=R9XOL-EEb_cwbD4SFNVmViXC84D2p4BEVNCXg0nlh7I,1684
13
- rio_tiler/utils.py,sha256=Xcx7Ycdy52A3t0OrMIw5lMC2t-rWqZke3iySqsuCXjk,31314
13
+ rio_tiler/utils.py,sha256=BwTHM_qmwRl0QEHwf7qQa22zdQPWeuhUHzCDqlUDkU8,32156
14
14
  rio_tiler/cmap_data/__init__.py,sha256=8FtVmfpTjXlvhxQ5QesN0UC1m_B3MuF3LbGbhMC5Rw4,1039
15
15
  rio_tiler/cmap_data/accent.npy,sha256=Qde1ldOoXghe4L05v1QbVvnMA1ldwNjKWPf5xCBbmI4,1152
16
16
  rio_tiler/cmap_data/accent_r.npy,sha256=ba-GWSMSPRAcm9CGzlXJeNG4ABbBHDCV602hAWV2idc,1152
@@ -225,18 +225,20 @@ rio_tiler/cmap_data/ylorrd.npy,sha256=9ImXljw40oe60w8uV4EMDPY4aFFVkGbyCBi6SlTX83
225
225
  rio_tiler/cmap_data/ylorrd_r.npy,sha256=K5uiHNHbLxV5SizyT09cSVAxldE-BW5GpOXxUp7UsTE,1152
226
226
  rio_tiler/experimental/__init__.py,sha256=dgW817h5U9OQt4V68L912g3DivPfhoWKvS-mI83sqio,328
227
227
  rio_tiler/experimental/vsifile.py,sha256=t1tJviPmFkjWIbr86BEnsK7pU4iiqLh1pKYZyNNb1AY,960
228
+ rio_tiler/experimental/zarr.py,sha256=S9PJcv1JwoMI3sBRg0z2uEj5rk8KvwlR0-k7kA27rJ4,11775
228
229
  rio_tiler/io/__init__.py,sha256=_L4iILm6vSiJ14GEDDOvkuUHRtbWC9oqx6Bu8PxHhvA,270
229
- rio_tiler/io/base.py,sha256=nyaAtfodM-5fXd1WsGG5Qh544PNv9Hy4FLQ_nPj8hw8,52154
230
- rio_tiler/io/rasterio.py,sha256=4j4ffxsBHD7wg2R1p6x6JE_7UZjMZQGx29qtO6JEs8U,29636
230
+ rio_tiler/io/base.py,sha256=3aKWc_1eGe_6Gzn5v8XOmZqUodfYsgytVLvNISqi5-g,53199
231
+ rio_tiler/io/rasterio.py,sha256=JcjHJYmntBx4yyLOnTOJsZ3631TNsXFHbVGwK2MPnS8,29190
231
232
  rio_tiler/io/stac.py,sha256=kIEW4F71PouXF-Ubpz-VVXujnp8LqftptPKDo_J3BTw,12831
232
- rio_tiler/io/xarray.py,sha256=geOGIyhwlKdG4jguuW5AQl657sPmNGRrSJFSk5UEs-Q,26401
233
+ rio_tiler/io/xarray.py,sha256=jISNXCV2lBjs5qOYSLvSfrD7v6fO69sdsb7KC3fatUQ,26915
233
234
  rio_tiler/mosaic/__init__.py,sha256=Yj6CKpnFl8PJhLSp-a55wo33hKZ8-6OOBJtWA1HZVy8,118
234
- rio_tiler/mosaic/reader.py,sha256=KSk6DaUJRN4Ye8lJ-V12sl5i2FN6y9o4wS1GzVSmtgU,10694
235
+ rio_tiler/mosaic/backend.py,sha256=OI4hOM2No30gQVSIyAAwgx6ntEvw0Rk9neTeOmwstrw,8200
236
+ rio_tiler/mosaic/reader.py,sha256=4sgl8IlV7zOtcfCt6XWw5UZLMCP0EgNbR2vRXObEGDA,11029
235
237
  rio_tiler/mosaic/methods/__init__.py,sha256=tgkXM9skaTLXIm5QFoheOEznQXM97KGflcAWHfkrt1g,612
236
238
  rio_tiler/mosaic/methods/base.py,sha256=9YZJWVRwH5Fk9KO9q5CW52Q8Mf60tAJ21oM4ixEDXBo,1424
237
239
  rio_tiler/mosaic/methods/defaults.py,sha256=P-zSVVgvQ2oRiMchC3bMqIYLTX7H3743jsD_VmqStxM,7642
238
- rio_tiler-7.9.2.dist-info/METADATA,sha256=h03DPeFZMtPvtd3etzxHFLhm2XeRShbk8eTCK9MWD9k,12233
239
- rio_tiler-7.9.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
240
- rio_tiler-7.9.2.dist-info/licenses/AUTHORS.txt,sha256=FCVd4Tjg-8syl0ZugCunpXER8X2-XonW2ZfllyTnRvE,158
241
- rio_tiler-7.9.2.dist-info/licenses/LICENSE,sha256=vq8Tt4KoYQT9JxAjQ4yXMmmhFYRTsBRgrOj-ao-bC5o,1517
242
- rio_tiler-7.9.2.dist-info/RECORD,,
240
+ rio_tiler-8.0.0.dist-info/METADATA,sha256=wIZwjY9mXGOW3o3KvcLq-UreK9LX433GBkdvbhFv6yM,11159
241
+ rio_tiler-8.0.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
242
+ rio_tiler-8.0.0.dist-info/licenses/AUTHORS.txt,sha256=FCVd4Tjg-8syl0ZugCunpXER8X2-XonW2ZfllyTnRvE,158
243
+ rio_tiler-8.0.0.dist-info/licenses/LICENSE,sha256=vq8Tt4KoYQT9JxAjQ4yXMmmhFYRTsBRgrOj-ao-bC5o,1517
244
+ rio_tiler-8.0.0.dist-info/RECORD,,