rio-tiler 7.0.1__py3-none-any.whl → 7.1.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.
- rio_tiler/__init__.py +1 -1
- rio_tiler/io/xarray.py +211 -55
- rio_tiler/utils.py +19 -5
- {rio_tiler-7.0.1.dist-info → rio_tiler-7.1.0.dist-info}/METADATA +1 -1
- {rio_tiler-7.0.1.dist-info → rio_tiler-7.1.0.dist-info}/RECORD +8 -8
- {rio_tiler-7.0.1.dist-info → rio_tiler-7.1.0.dist-info}/WHEEL +0 -0
- {rio_tiler-7.0.1.dist-info → rio_tiler-7.1.0.dist-info}/licenses/AUTHORS.txt +0 -0
- {rio_tiler-7.0.1.dist-info → rio_tiler-7.1.0.dist-info}/licenses/LICENSE +0 -0
rio_tiler/__init__.py
CHANGED
rio_tiler/io/xarray.py
CHANGED
|
@@ -2,15 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
import warnings
|
|
6
|
+
from typing import Dict, List, Optional
|
|
6
7
|
|
|
7
8
|
import attr
|
|
9
|
+
import numpy
|
|
8
10
|
from morecantile import Tile, TileMatrixSet
|
|
9
11
|
from rasterio.crs import CRS
|
|
10
12
|
from rasterio.enums import Resampling
|
|
13
|
+
from rasterio.errors import NotGeoreferencedWarning
|
|
14
|
+
from rasterio.features import bounds as featureBounds
|
|
15
|
+
from rasterio.features import rasterize
|
|
11
16
|
from rasterio.transform import from_bounds, rowcol
|
|
12
17
|
from rasterio.warp import calculate_default_transform
|
|
13
18
|
from rasterio.warp import transform as transform_coords
|
|
19
|
+
from rasterio.warp import transform_geom
|
|
14
20
|
|
|
15
21
|
from rio_tiler.constants import WEB_MERCATOR_TMS, WGS84_CRS
|
|
16
22
|
from rio_tiler.errors import (
|
|
@@ -21,8 +27,9 @@ from rio_tiler.errors import (
|
|
|
21
27
|
)
|
|
22
28
|
from rio_tiler.io.base import BaseReader
|
|
23
29
|
from rio_tiler.models import BandStatistics, ImageData, Info, PointData
|
|
24
|
-
from rio_tiler.
|
|
25
|
-
from rio_tiler.
|
|
30
|
+
from rio_tiler.reader import _get_width_height
|
|
31
|
+
from rio_tiler.types import BBox, NoData, RIOResampling, WarpResampling
|
|
32
|
+
from rio_tiler.utils import CRS_to_uri, _validate_shape_input, get_array_statistics
|
|
26
33
|
|
|
27
34
|
try:
|
|
28
35
|
import xarray
|
|
@@ -76,11 +83,14 @@ class XarrayReader(BaseReader):
|
|
|
76
83
|
"Dataset doesn't have CRS information, please add it before using rio-tiler (e.g. `ds.rio.write_crs('epsg:4326', inplace=True)`)"
|
|
77
84
|
)
|
|
78
85
|
|
|
86
|
+
# adds half x/y resolution on each values
|
|
87
|
+
# https://github.com/corteva/rioxarray/issues/645#issuecomment-1461070634
|
|
88
|
+
xres, yres = map(abs, self.input.rio.resolution())
|
|
79
89
|
if self.crs == WGS84_CRS and (
|
|
80
|
-
|
|
81
|
-
or
|
|
82
|
-
or
|
|
83
|
-
or
|
|
90
|
+
self.bounds[0] + xres / 2 < -180
|
|
91
|
+
or self.bounds[1] + yres / 2 < -90
|
|
92
|
+
or self.bounds[2] - xres / 2 > 180
|
|
93
|
+
or self.bounds[3] - yres / 2 > 90
|
|
84
94
|
):
|
|
85
95
|
raise InvalidGeographicBounds(
|
|
86
96
|
f"Invalid geographic bounds: {self.bounds}. Must be within (-180, -90, 180, 90)."
|
|
@@ -109,16 +119,20 @@ class XarrayReader(BaseReader):
|
|
|
109
119
|
@property
|
|
110
120
|
def band_names(self) -> List[str]:
|
|
111
121
|
"""Return list of `band names` in DataArray."""
|
|
112
|
-
return [str(band) for d in self._dims for band in self.input[d].values]
|
|
122
|
+
return [str(band) for d in self._dims for band in self.input[d].values] or [
|
|
123
|
+
"value"
|
|
124
|
+
]
|
|
113
125
|
|
|
114
126
|
def info(self) -> Info:
|
|
115
127
|
"""Return xarray.DataArray info."""
|
|
116
|
-
bands = [str(band) for d in self._dims for band in self.input[d].values]
|
|
117
|
-
|
|
128
|
+
bands = [str(band) for d in self._dims for band in self.input[d].values] or [
|
|
129
|
+
"value"
|
|
130
|
+
]
|
|
131
|
+
metadata = [band.attrs for d in self._dims for band in self.input[d]] or [{}]
|
|
118
132
|
|
|
119
133
|
meta = {
|
|
120
134
|
"bounds": self.bounds,
|
|
121
|
-
"crs": CRS_to_uri(self.crs),
|
|
135
|
+
"crs": CRS_to_uri(self.crs) or self.crs.to_wkt(),
|
|
122
136
|
"band_metadata": [(f"b{ix}", v) for ix, v in enumerate(metadata, 1)],
|
|
123
137
|
"band_descriptions": [(f"b{ix}", v) for ix, v in enumerate(bands, 1)],
|
|
124
138
|
"dtype": str(self.input.dtype),
|
|
@@ -127,8 +141,12 @@ class XarrayReader(BaseReader):
|
|
|
127
141
|
"count": self.input.rio.count,
|
|
128
142
|
"width": self.input.rio.width,
|
|
129
143
|
"height": self.input.rio.height,
|
|
130
|
-
"attrs":
|
|
144
|
+
"attrs": {
|
|
145
|
+
k: (v.tolist() if isinstance(v, (numpy.ndarray, numpy.generic)) else v)
|
|
146
|
+
for k, v in self.input.attrs.items()
|
|
147
|
+
},
|
|
131
148
|
}
|
|
149
|
+
|
|
132
150
|
return Info(**meta)
|
|
133
151
|
|
|
134
152
|
def statistics(
|
|
@@ -137,11 +155,29 @@ class XarrayReader(BaseReader):
|
|
|
137
155
|
categories: Optional[List[float]] = None,
|
|
138
156
|
percentiles: Optional[List[int]] = None,
|
|
139
157
|
hist_options: Optional[Dict] = None,
|
|
140
|
-
|
|
141
|
-
**kwargs: Any,
|
|
158
|
+
nodata: Optional[NoData] = None,
|
|
142
159
|
) -> Dict[str, BandStatistics]:
|
|
143
|
-
"""Return
|
|
144
|
-
|
|
160
|
+
"""Return statistics from a dataset."""
|
|
161
|
+
hist_options = hist_options or {}
|
|
162
|
+
|
|
163
|
+
ds = self.input
|
|
164
|
+
if nodata is not None:
|
|
165
|
+
ds = ds.rio.write_nodata(nodata)
|
|
166
|
+
|
|
167
|
+
data = ds.to_masked_array()
|
|
168
|
+
data.mask |= data.data == ds.rio.nodata
|
|
169
|
+
|
|
170
|
+
stats = get_array_statistics(
|
|
171
|
+
data,
|
|
172
|
+
categorical=categorical,
|
|
173
|
+
categories=categories,
|
|
174
|
+
percentiles=percentiles,
|
|
175
|
+
**hist_options,
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
return {
|
|
179
|
+
self.band_names[ix]: BandStatistics(**val) for ix, val in enumerate(stats)
|
|
180
|
+
}
|
|
145
181
|
|
|
146
182
|
def tile(
|
|
147
183
|
self,
|
|
@@ -203,6 +239,11 @@ class XarrayReader(BaseReader):
|
|
|
203
239
|
arr = ds.to_masked_array()
|
|
204
240
|
arr.mask |= arr.data == ds.rio.nodata
|
|
205
241
|
|
|
242
|
+
output_bounds = ds.rio._unordered_bounds()
|
|
243
|
+
if output_bounds[1] > output_bounds[3] and ds.rio.transform().e > 0:
|
|
244
|
+
yaxis = self.input.dims.index(self.input.rio.y_dim)
|
|
245
|
+
arr = numpy.flip(arr, axis=yaxis)
|
|
246
|
+
|
|
206
247
|
return ImageData(
|
|
207
248
|
arr,
|
|
208
249
|
bounds=tile_bounds,
|
|
@@ -219,6 +260,10 @@ class XarrayReader(BaseReader):
|
|
|
219
260
|
reproject_method: WarpResampling = "nearest",
|
|
220
261
|
auto_expand: bool = True,
|
|
221
262
|
nodata: Optional[NoData] = None,
|
|
263
|
+
max_size: Optional[int] = None,
|
|
264
|
+
height: Optional[int] = None,
|
|
265
|
+
width: Optional[int] = None,
|
|
266
|
+
resampling_method: RIOResampling = "nearest",
|
|
222
267
|
) -> ImageData:
|
|
223
268
|
"""Read part of a dataset.
|
|
224
269
|
|
|
@@ -229,11 +274,21 @@ class XarrayReader(BaseReader):
|
|
|
229
274
|
reproject_method (WarpResampling, optional): WarpKernel resampling algorithm. Defaults to `nearest`.
|
|
230
275
|
auto_expand (boolean, optional): When True, rioxarray's clip_box will expand clip search if only 1D raster found with clip. When False, will throw `OneDimensionalRaster` error if only 1 x or y data point is found. Defaults to True.
|
|
231
276
|
nodata (int or float, optional): Overwrite dataset internal nodata value.
|
|
277
|
+
max_size (int, optional): Limit the size of the longest dimension of the dataset read, respecting bounds X/Y aspect ratio.
|
|
278
|
+
height (int, optional): Output height of the array.
|
|
279
|
+
width (int, optional): Output width of the array.
|
|
280
|
+
resampling_method (RIOResampling, optional): RasterIO resampling algorithm. Defaults to `nearest`.
|
|
232
281
|
|
|
233
282
|
Returns:
|
|
234
283
|
rio_tiler.models.ImageData: ImageData instance with data, mask and input spatial info.
|
|
235
284
|
|
|
236
285
|
"""
|
|
286
|
+
if max_size and width and height:
|
|
287
|
+
warnings.warn(
|
|
288
|
+
"'max_size' will be ignored with with 'height' and 'width' set.",
|
|
289
|
+
UserWarning,
|
|
290
|
+
)
|
|
291
|
+
|
|
237
292
|
dst_crs = dst_crs or bounds_crs
|
|
238
293
|
|
|
239
294
|
ds = self.input
|
|
@@ -271,7 +326,12 @@ class XarrayReader(BaseReader):
|
|
|
271
326
|
arr = ds.to_masked_array()
|
|
272
327
|
arr.mask |= arr.data == ds.rio.nodata
|
|
273
328
|
|
|
274
|
-
|
|
329
|
+
output_bounds = ds.rio._unordered_bounds()
|
|
330
|
+
if output_bounds[1] > output_bounds[3] and ds.rio.transform().e > 0:
|
|
331
|
+
yaxis = self.input.dims.index(self.input.rio.y_dim)
|
|
332
|
+
arr = numpy.flip(arr, axis=yaxis)
|
|
333
|
+
|
|
334
|
+
img = ImageData(
|
|
275
335
|
arr,
|
|
276
336
|
bounds=ds.rio.bounds(),
|
|
277
337
|
crs=ds.rio.crs,
|
|
@@ -279,11 +339,29 @@ class XarrayReader(BaseReader):
|
|
|
279
339
|
band_names=self.band_names,
|
|
280
340
|
)
|
|
281
341
|
|
|
342
|
+
output_height = height or img.height
|
|
343
|
+
output_width = width or img.width
|
|
344
|
+
if max_size and not (width and height):
|
|
345
|
+
output_height, output_width = _get_width_height(
|
|
346
|
+
max_size, img.height, img.width
|
|
347
|
+
)
|
|
348
|
+
|
|
349
|
+
if output_height != img.height or output_width != img.width:
|
|
350
|
+
img = img.resize(
|
|
351
|
+
output_height, output_width, resampling_method=resampling_method
|
|
352
|
+
)
|
|
353
|
+
|
|
354
|
+
return img
|
|
355
|
+
|
|
282
356
|
def preview(
|
|
283
357
|
self,
|
|
284
358
|
max_size: int = 1024,
|
|
285
359
|
height: Optional[int] = None,
|
|
286
360
|
width: Optional[int] = None,
|
|
361
|
+
nodata: Optional[NoData] = None,
|
|
362
|
+
dst_crs: Optional[CRS] = None,
|
|
363
|
+
reproject_method: WarpResampling = "nearest",
|
|
364
|
+
resampling_method: RIOResampling = "nearest",
|
|
287
365
|
) -> ImageData:
|
|
288
366
|
"""Return a preview of a dataset.
|
|
289
367
|
|
|
@@ -291,12 +369,76 @@ class XarrayReader(BaseReader):
|
|
|
291
369
|
max_size (int, optional): Limit the size of the longest dimension of the dataset read, respecting bounds X/Y aspect ratio. Defaults to 1024.
|
|
292
370
|
height (int, optional): Output height of the array.
|
|
293
371
|
width (int, optional): Output width of the array.
|
|
372
|
+
nodata (int or float, optional): Overwrite dataset internal nodata value.
|
|
373
|
+
dst_crs (rasterio.crs.CRS, optional): target coordinate reference system.
|
|
374
|
+
reproject_method (WarpResampling, optional): WarpKernel resampling algorithm. Defaults to `nearest`.
|
|
375
|
+
resampling_method (RIOResampling, optional): RasterIO resampling algorithm. Defaults to `nearest`.
|
|
294
376
|
|
|
295
377
|
Returns:
|
|
296
378
|
rio_tiler.models.ImageData: ImageData instance with data, mask and input spatial info.
|
|
297
379
|
|
|
298
380
|
"""
|
|
299
|
-
|
|
381
|
+
if max_size and width and height:
|
|
382
|
+
warnings.warn(
|
|
383
|
+
"'max_size' will be ignored with with 'height' and 'width' set.",
|
|
384
|
+
UserWarning,
|
|
385
|
+
)
|
|
386
|
+
|
|
387
|
+
ds = self.input
|
|
388
|
+
if nodata is not None:
|
|
389
|
+
ds = ds.rio.write_nodata(nodata)
|
|
390
|
+
|
|
391
|
+
if dst_crs and dst_crs != self.crs:
|
|
392
|
+
dst_transform, w, h = calculate_default_transform(
|
|
393
|
+
self.crs,
|
|
394
|
+
dst_crs,
|
|
395
|
+
ds.rio.width,
|
|
396
|
+
ds.rio.height,
|
|
397
|
+
*ds.rio.bounds(),
|
|
398
|
+
)
|
|
399
|
+
ds = ds.rio.reproject(
|
|
400
|
+
dst_crs,
|
|
401
|
+
shape=(h, w),
|
|
402
|
+
transform=dst_transform,
|
|
403
|
+
resampling=Resampling[reproject_method],
|
|
404
|
+
nodata=nodata,
|
|
405
|
+
)
|
|
406
|
+
|
|
407
|
+
# Forward valid_min/valid_max to the ImageData object
|
|
408
|
+
minv, maxv = ds.attrs.get("valid_min"), ds.attrs.get("valid_max")
|
|
409
|
+
stats = None
|
|
410
|
+
if minv is not None and maxv is not None:
|
|
411
|
+
stats = ((minv, maxv),) * ds.rio.count
|
|
412
|
+
|
|
413
|
+
arr = ds.to_masked_array()
|
|
414
|
+
arr.mask |= arr.data == ds.rio.nodata
|
|
415
|
+
|
|
416
|
+
output_bounds = ds.rio._unordered_bounds()
|
|
417
|
+
if output_bounds[1] > output_bounds[3] and ds.rio.transform().e > 0:
|
|
418
|
+
yaxis = self.input.dims.index(self.input.rio.y_dim)
|
|
419
|
+
arr = numpy.flip(arr, axis=yaxis)
|
|
420
|
+
|
|
421
|
+
img = ImageData(
|
|
422
|
+
arr,
|
|
423
|
+
bounds=ds.rio.bounds(),
|
|
424
|
+
crs=ds.rio.crs,
|
|
425
|
+
dataset_statistics=stats,
|
|
426
|
+
band_names=self.band_names,
|
|
427
|
+
)
|
|
428
|
+
|
|
429
|
+
output_height = height or img.height
|
|
430
|
+
output_width = width or img.width
|
|
431
|
+
if max_size and not (width and height):
|
|
432
|
+
output_height, output_width = _get_width_height(
|
|
433
|
+
max_size, img.height, img.width
|
|
434
|
+
)
|
|
435
|
+
|
|
436
|
+
if output_height != img.height or output_width != img.width:
|
|
437
|
+
img = img.resize(
|
|
438
|
+
output_height, output_width, resampling_method=resampling_method
|
|
439
|
+
)
|
|
440
|
+
|
|
441
|
+
return img
|
|
300
442
|
|
|
301
443
|
def point(
|
|
302
444
|
self,
|
|
@@ -331,7 +473,11 @@ class XarrayReader(BaseReader):
|
|
|
331
473
|
|
|
332
474
|
y, x = rowcol(ds.rio.transform(), ds_lon, ds_lat)
|
|
333
475
|
|
|
334
|
-
|
|
476
|
+
if ds.ndim == 2:
|
|
477
|
+
arr = numpy.expand_dims(ds[int(y[0]), int(x[0])].to_masked_array(), axis=0)
|
|
478
|
+
else:
|
|
479
|
+
arr = ds[:, int(y[0]), int(x[0])].to_masked_array()
|
|
480
|
+
|
|
335
481
|
arr.mask |= arr.data == ds.rio.nodata
|
|
336
482
|
|
|
337
483
|
return PointData(
|
|
@@ -347,7 +493,12 @@ class XarrayReader(BaseReader):
|
|
|
347
493
|
dst_crs: Optional[CRS] = None,
|
|
348
494
|
shape_crs: CRS = WGS84_CRS,
|
|
349
495
|
reproject_method: WarpResampling = "nearest",
|
|
496
|
+
auto_expand: bool = True,
|
|
350
497
|
nodata: Optional[NoData] = None,
|
|
498
|
+
max_size: Optional[int] = None,
|
|
499
|
+
height: Optional[int] = None,
|
|
500
|
+
width: Optional[int] = None,
|
|
501
|
+
resampling_method: RIOResampling = "nearest",
|
|
351
502
|
) -> ImageData:
|
|
352
503
|
"""Read part of a dataset defined by a geojson feature.
|
|
353
504
|
|
|
@@ -356,52 +507,57 @@ class XarrayReader(BaseReader):
|
|
|
356
507
|
dst_crs (rasterio.crs.CRS, optional): Overwrite target coordinate reference system.
|
|
357
508
|
shape_crs (rasterio.crs.CRS, optional): Input geojson coordinate reference system. Defaults to `epsg:4326`.
|
|
358
509
|
reproject_method (WarpResampling, optional): WarpKernel resampling algorithm. Defaults to `nearest`.
|
|
510
|
+
auto_expand (boolean, optional): When True, rioxarray's clip_box will expand clip search if only 1D raster found with clip. When False, will throw `OneDimensionalRaster` error if only 1 x or y data point is found. Defaults to True.
|
|
359
511
|
nodata (int or float, optional): Overwrite dataset internal nodata value.
|
|
512
|
+
max_size (int, optional): Limit the size of the longest dimension of the dataset read, respecting bounds X/Y aspect ratio.
|
|
513
|
+
height (int, optional): Output height of the array.
|
|
514
|
+
width (int, optional): Output width of the array.
|
|
515
|
+
resampling_method (RIOResampling, optional): RasterIO resampling algorithm. Defaults to `nearest`.
|
|
360
516
|
|
|
361
517
|
Returns:
|
|
362
518
|
rio_tiler.models.ImageData: ImageData instance with data, mask and input spatial info.
|
|
363
519
|
|
|
364
520
|
"""
|
|
521
|
+
shape = _validate_shape_input(shape)
|
|
522
|
+
|
|
365
523
|
if not dst_crs:
|
|
366
524
|
dst_crs = shape_crs
|
|
367
525
|
|
|
368
|
-
|
|
526
|
+
# Get BBOX of the polygon
|
|
527
|
+
bbox = featureBounds(shape)
|
|
369
528
|
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
529
|
+
img = self.part(
|
|
530
|
+
bbox,
|
|
531
|
+
dst_crs=dst_crs,
|
|
532
|
+
bounds_crs=shape_crs,
|
|
533
|
+
nodata=nodata,
|
|
534
|
+
max_size=max_size,
|
|
535
|
+
width=width,
|
|
536
|
+
height=height,
|
|
537
|
+
reproject_method=reproject_method,
|
|
538
|
+
resampling_method=resampling_method,
|
|
539
|
+
)
|
|
373
540
|
|
|
374
|
-
|
|
541
|
+
if dst_crs != shape_crs:
|
|
542
|
+
shape = transform_geom(shape_crs, dst_crs, shape)
|
|
375
543
|
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
ds.rio.height,
|
|
382
|
-
*ds.rio.bounds(),
|
|
544
|
+
with warnings.catch_warnings():
|
|
545
|
+
warnings.filterwarnings(
|
|
546
|
+
"ignore",
|
|
547
|
+
category=NotGeoreferencedWarning,
|
|
548
|
+
module="rasterio",
|
|
383
549
|
)
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
transform=
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
arr = ds.to_masked_array()
|
|
399
|
-
arr.mask |= arr.data == ds.rio.nodata
|
|
400
|
-
|
|
401
|
-
return ImageData(
|
|
402
|
-
arr,
|
|
403
|
-
bounds=ds.rio.bounds(),
|
|
404
|
-
crs=ds.rio.crs,
|
|
405
|
-
dataset_statistics=stats,
|
|
406
|
-
band_names=self.band_names,
|
|
407
|
-
)
|
|
550
|
+
cutline_mask = rasterize(
|
|
551
|
+
[shape],
|
|
552
|
+
out_shape=(img.height, img.width),
|
|
553
|
+
transform=img.transform,
|
|
554
|
+
all_touched=True, # Mandatory for matching masks at different resolutions
|
|
555
|
+
default_value=0,
|
|
556
|
+
fill=1,
|
|
557
|
+
dtype="uint8",
|
|
558
|
+
).astype("bool")
|
|
559
|
+
|
|
560
|
+
img.cutline_mask = cutline_mask
|
|
561
|
+
img.array.mask = numpy.where(~cutline_mask, img.array.mask, True)
|
|
562
|
+
|
|
563
|
+
return img
|
rio_tiler/utils.py
CHANGED
|
@@ -3,7 +3,17 @@
|
|
|
3
3
|
import math
|
|
4
4
|
import warnings
|
|
5
5
|
from io import BytesIO
|
|
6
|
-
from typing import
|
|
6
|
+
from typing import (
|
|
7
|
+
Any,
|
|
8
|
+
Callable,
|
|
9
|
+
Dict,
|
|
10
|
+
Generator,
|
|
11
|
+
List,
|
|
12
|
+
Optional,
|
|
13
|
+
Sequence,
|
|
14
|
+
Tuple,
|
|
15
|
+
Union,
|
|
16
|
+
)
|
|
7
17
|
|
|
8
18
|
import numpy
|
|
9
19
|
import rasterio
|
|
@@ -642,12 +652,15 @@ def pansharpening_brovey(
|
|
|
642
652
|
def _convert_to_raster_space(
|
|
643
653
|
src_dst: Union[DatasetReader, DatasetWriter, WarpedVRT],
|
|
644
654
|
poly_coordinates: List,
|
|
655
|
+
op: Optional[Callable[[float], Any]] = None,
|
|
645
656
|
) -> List[str]:
|
|
657
|
+
# NOTE: we could remove this once we have rasterio >= 1.4.2
|
|
658
|
+
op = op or numpy.floor
|
|
646
659
|
polygons = []
|
|
647
660
|
for point in poly_coordinates:
|
|
648
661
|
xs, ys = zip(*coords(point))
|
|
649
|
-
src_y, src_x = rowcol(src_dst.transform, xs, ys)
|
|
650
|
-
polygon = ", ".join([f"{x} {y}" for x, y in list(zip(src_x, src_y))])
|
|
662
|
+
src_y, src_x = rowcol(src_dst.transform, xs, ys, op=op)
|
|
663
|
+
polygon = ", ".join([f"{int(x)} {int(y)}" for x, y in list(zip(src_x, src_y))])
|
|
651
664
|
polygons.append(f"({polygon})")
|
|
652
665
|
|
|
653
666
|
return polygons
|
|
@@ -657,6 +670,7 @@ def create_cutline(
|
|
|
657
670
|
src_dst: Union[DatasetReader, DatasetWriter, WarpedVRT],
|
|
658
671
|
geometry: Dict,
|
|
659
672
|
geometry_crs: CRS = None,
|
|
673
|
+
op: Optional[Callable[[float], Any]] = None,
|
|
660
674
|
) -> str:
|
|
661
675
|
"""
|
|
662
676
|
Create WKT Polygon Cutline for GDALWarpOptions.
|
|
@@ -678,13 +692,13 @@ def create_cutline(
|
|
|
678
692
|
geometry = transform_geom(geometry_crs, src_dst.crs, geometry)
|
|
679
693
|
|
|
680
694
|
if geom_type == "Polygon":
|
|
681
|
-
polys = ",".join(_convert_to_raster_space(src_dst, geometry["coordinates"]))
|
|
695
|
+
polys = ",".join(_convert_to_raster_space(src_dst, geometry["coordinates"], op))
|
|
682
696
|
wkt = f"POLYGON ({polys})"
|
|
683
697
|
|
|
684
698
|
elif geom_type == "MultiPolygon":
|
|
685
699
|
multi_polys = []
|
|
686
700
|
for poly in geometry["coordinates"]:
|
|
687
|
-
polys = ",".join(_convert_to_raster_space(src_dst, poly))
|
|
701
|
+
polys = ",".join(_convert_to_raster_space(src_dst, poly, op))
|
|
688
702
|
multi_polys.append(f"({polys})")
|
|
689
703
|
str_multipoly = ",".join(multi_polys)
|
|
690
704
|
wkt = f"MULTIPOLYGON ({str_multipoly})"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: rio-tiler
|
|
3
|
-
Version: 7.0
|
|
3
|
+
Version: 7.1.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/
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
rio_tiler/__init__.py,sha256=
|
|
1
|
+
rio_tiler/__init__.py,sha256=pyAeRkEV5FIxq4iakbatfDdcdwVEAVTlW0urd9m1S5A,192
|
|
2
2
|
rio_tiler/colormap.py,sha256=xx43D4A5w3VgYB2CvuKvYFmAsYSuZLWbIfextsVYDB4,11085
|
|
3
3
|
rio_tiler/constants.py,sha256=55i-7JZDupTXZdLgxL03KsgM4lAzuGuIVP1zZKktzp0,426
|
|
4
4
|
rio_tiler/errors.py,sha256=4I3i0e1FtkLX5sIX6dfhUMUj3SWWoKqkjCkSG7k5i2M,1901
|
|
@@ -10,7 +10,7 @@ rio_tiler/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
10
10
|
rio_tiler/reader.py,sha256=FiDQQU_v8mDk2JTxBpLmsTqaCQFOsjOw0LocasLeXjk,22721
|
|
11
11
|
rio_tiler/tasks.py,sha256=tiQo24rZHBVxids40QkNInuMzDFEei08zYW3I_pkSVE,3157
|
|
12
12
|
rio_tiler/types.py,sha256=HbgECLqI4KoYVdMZv2pHSME4aiVvWea1ircqP9jQQCA,1468
|
|
13
|
-
rio_tiler/utils.py,sha256=
|
|
13
|
+
rio_tiler/utils.py,sha256=_msIyfmDtvNnk3MGIENfGurTs2_Fb-hJ-YughEi82Rc,29507
|
|
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
|
|
@@ -227,14 +227,14 @@ rio_tiler/io/__init__.py,sha256=_L4iILm6vSiJ14GEDDOvkuUHRtbWC9oqx6Bu8PxHhvA,270
|
|
|
227
227
|
rio_tiler/io/base.py,sha256=nyaAtfodM-5fXd1WsGG5Qh544PNv9Hy4FLQ_nPj8hw8,52154
|
|
228
228
|
rio_tiler/io/rasterio.py,sha256=9GtbUPialsFMnxVUKrJ8ZItC3sWS8zddrO8aiPG07AU,29011
|
|
229
229
|
rio_tiler/io/stac.py,sha256=b7RASmoJHGnHvn3LBNaBlMzigZr_qNn1efczxD-Zplc,12629
|
|
230
|
-
rio_tiler/io/xarray.py,sha256=
|
|
230
|
+
rio_tiler/io/xarray.py,sha256=dKRo7Lc2bChPXycmykIwX9in7HGNrNaa990CrtMWgg8,20481
|
|
231
231
|
rio_tiler/mosaic/__init__.py,sha256=Yj6CKpnFl8PJhLSp-a55wo33hKZ8-6OOBJtWA1HZVy8,118
|
|
232
232
|
rio_tiler/mosaic/reader.py,sha256=_YBwTJwHvXOzKwpNpOmmh0F4yicyxgWo9vHyof3w_Do,9686
|
|
233
233
|
rio_tiler/mosaic/methods/__init__.py,sha256=tgkXM9skaTLXIm5QFoheOEznQXM97KGflcAWHfkrt1g,612
|
|
234
234
|
rio_tiler/mosaic/methods/base.py,sha256=9YZJWVRwH5Fk9KO9q5CW52Q8Mf60tAJ21oM4ixEDXBo,1424
|
|
235
235
|
rio_tiler/mosaic/methods/defaults.py,sha256=z34lna2wGXnAPwculjk_6hDrloqS8wzer68FFoIo7pg,6744
|
|
236
|
-
rio_tiler-7.0.
|
|
237
|
-
rio_tiler-7.0.
|
|
238
|
-
rio_tiler-7.0.
|
|
239
|
-
rio_tiler-7.0.
|
|
240
|
-
rio_tiler-7.0.
|
|
236
|
+
rio_tiler-7.1.0.dist-info/METADATA,sha256=MK3yD7CxzNepvJe4UAxaEx4ML5tInrJ6bf2_axh6ANg,12209
|
|
237
|
+
rio_tiler-7.1.0.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
|
|
238
|
+
rio_tiler-7.1.0.dist-info/licenses/AUTHORS.txt,sha256=FCVd4Tjg-8syl0ZugCunpXER8X2-XonW2ZfllyTnRvE,158
|
|
239
|
+
rio_tiler-7.1.0.dist-info/licenses/LICENSE,sha256=vq8Tt4KoYQT9JxAjQ4yXMmmhFYRTsBRgrOj-ao-bC5o,1517
|
|
240
|
+
rio_tiler-7.1.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|