yirgacheffe 1.7.0__tar.gz → 1.7.1__tar.gz
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.
Potentially problematic release.
This version of yirgacheffe might be problematic. Click here for more details.
- {yirgacheffe-1.7.0/yirgacheffe.egg-info → yirgacheffe-1.7.1}/PKG-INFO +1 -1
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/pyproject.toml +1 -1
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/tests/test_openers.py +22 -0
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/tests/test_pickle.py +2 -3
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/tests/test_raster.py +10 -1
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/tests/test_vectors.py +5 -1
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/yirgacheffe/_core.py +2 -2
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/yirgacheffe/layers/base.py +6 -1
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/yirgacheffe/layers/group.py +8 -8
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/yirgacheffe/layers/vectors.py +5 -1
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1/yirgacheffe.egg-info}/PKG-INFO +1 -1
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/LICENSE +0 -0
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/MANIFEST.in +0 -0
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/README.md +0 -0
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/setup.cfg +0 -0
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/tests/test_area.py +0 -0
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/tests/test_auto_windowing.py +0 -0
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/tests/test_base.py +0 -0
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/tests/test_constants.py +0 -0
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/tests/test_datatypes.py +0 -0
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/tests/test_group.py +0 -0
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/tests/test_h3layer.py +0 -0
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/tests/test_intersection.py +0 -0
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/tests/test_multiband.py +0 -0
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/tests/test_nodata.py +0 -0
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/tests/test_operators.py +0 -0
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/tests/test_optimisation.py +0 -0
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/tests/test_parallel_operators.py +0 -0
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/tests/test_projection.py +0 -0
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/tests/test_rescaling.py +0 -0
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/tests/test_rounding.py +0 -0
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/tests/test_save_with_window.py +0 -0
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/tests/test_sum_with_window.py +0 -0
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/tests/test_uniform_area_layer.py +0 -0
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/tests/test_union.py +0 -0
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/tests/test_window.py +0 -0
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/yirgacheffe/__init__.py +0 -0
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/yirgacheffe/_backends/__init__.py +0 -0
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/yirgacheffe/_backends/enumeration.py +0 -0
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/yirgacheffe/_backends/mlx.py +0 -0
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/yirgacheffe/_backends/numpy.py +0 -0
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/yirgacheffe/constants.py +0 -0
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/yirgacheffe/layers/__init__.py +0 -0
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/yirgacheffe/layers/area.py +0 -0
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/yirgacheffe/layers/constant.py +0 -0
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/yirgacheffe/layers/h3layer.py +0 -0
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/yirgacheffe/layers/rasters.py +0 -0
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/yirgacheffe/layers/rescaled.py +0 -0
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/yirgacheffe/operators.py +0 -0
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/yirgacheffe/rounding.py +0 -0
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/yirgacheffe/window.py +0 -0
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/yirgacheffe.egg-info/SOURCES.txt +0 -0
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/yirgacheffe.egg-info/dependency_links.txt +0 -0
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/yirgacheffe.egg-info/entry_points.txt +0 -0
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/yirgacheffe.egg-info/requires.txt +0 -0
- {yirgacheffe-1.7.0 → yirgacheffe-1.7.1}/yirgacheffe.egg-info/top_level.txt +0 -0
|
@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
|
|
|
6
6
|
|
|
7
7
|
[project]
|
|
8
8
|
name = "yirgacheffe"
|
|
9
|
-
version = "1.7.
|
|
9
|
+
version = "1.7.1"
|
|
10
10
|
description = "Abstraction of gdal datasets for doing basic math operations"
|
|
11
11
|
readme = "README.md"
|
|
12
12
|
authors = [{ name = "Michael Dales", email = "mwd24@cam.ac.uk" }]
|
|
@@ -191,3 +191,25 @@ def test_open_two_raster_areas_side_by_side(tiled):
|
|
|
191
191
|
with yg.read_raster(path1) as raster1:
|
|
192
192
|
with yg.read_raster(path2) as raster2:
|
|
193
193
|
assert group.sum() == raster1.sum() + raster2.sum()
|
|
194
|
+
|
|
195
|
+
@pytest.mark.parametrize("tiled", [False, True])
|
|
196
|
+
def test_open_two_raster_by_glob(tiled):
|
|
197
|
+
with tempfile.TemporaryDirectory() as tempdir:
|
|
198
|
+
temppath = Path(tempdir)
|
|
199
|
+
path1 = temppath / "test1.tif"
|
|
200
|
+
area1 = Area(-10, 10, 10, -10)
|
|
201
|
+
dataset1 = gdal_dataset_of_region(area1, 0.2, filename=path1)
|
|
202
|
+
dataset1.Close()
|
|
203
|
+
|
|
204
|
+
path2 = temppath / "test2.tif"
|
|
205
|
+
area2 = Area(10, 10, 30, -10)
|
|
206
|
+
dataset2 = gdal_dataset_of_region(area2, 0.2, filename=path2)
|
|
207
|
+
dataset2.Close()
|
|
208
|
+
|
|
209
|
+
with yg.read_rasters(temppath.glob("*.tif"), tiled=tiled) as group:
|
|
210
|
+
assert group.area == Area(-10, 10, 30, -10)
|
|
211
|
+
assert group.window == Window(0, 0, 200, 100)
|
|
212
|
+
|
|
213
|
+
with yg.read_raster(path1) as raster1:
|
|
214
|
+
with yg.read_raster(path2) as raster2:
|
|
215
|
+
assert group.sum() == raster1.sum() + raster2.sum()
|
|
@@ -12,7 +12,6 @@ from yirgacheffe.window import Area, MapProjection, PixelScale, Window
|
|
|
12
12
|
from yirgacheffe.layers import ConstantLayer, GroupLayer, RasterLayer, RescaledRasterLayer, \
|
|
13
13
|
UniformAreaLayer, VectorLayer
|
|
14
14
|
from yirgacheffe import WGS_84_PROJECTION
|
|
15
|
-
from yirgacheffe._backends import backend
|
|
16
15
|
|
|
17
16
|
|
|
18
17
|
def test_pickle_raster_layer() -> None:
|
|
@@ -97,7 +96,7 @@ def test_pickle_group_layer() -> None:
|
|
|
97
96
|
|
|
98
97
|
group = GroupLayer.layer_from_directory(tempdir)
|
|
99
98
|
expected = group.read_array(0, 0, 100, 100)
|
|
100
|
-
assert
|
|
99
|
+
assert expected.sum() != 0 # just check there is meaningful data
|
|
101
100
|
|
|
102
101
|
p = pickle.dumps(group)
|
|
103
102
|
restore = pickle.loads(p)
|
|
@@ -192,4 +191,4 @@ def test_pickle_rescaled_raster_layer() -> None:
|
|
|
192
191
|
assert restore.window == Window(0, 0, 2000, 2000)
|
|
193
192
|
|
|
194
193
|
expected = restore.read_array(0, 0, 100, 100)
|
|
195
|
-
assert
|
|
194
|
+
assert expected.sum() != 0 # just check there is meaningful data
|
|
@@ -5,7 +5,7 @@ import numpy as np
|
|
|
5
5
|
import pytest
|
|
6
6
|
from osgeo import gdal
|
|
7
7
|
|
|
8
|
-
from tests.helpers import gdal_dataset_of_region, gdal_multiband_dataset_with_data
|
|
8
|
+
from tests.helpers import gdal_dataset_of_region, gdal_multiband_dataset_with_data, gdal_dataset_with_data
|
|
9
9
|
from yirgacheffe.window import Area, PixelScale, Window
|
|
10
10
|
from yirgacheffe.layers import RasterLayer, InvalidRasterBand
|
|
11
11
|
from yirgacheffe.rounding import round_up_pixels
|
|
@@ -260,3 +260,12 @@ def test_multiband_raster() -> None:
|
|
|
260
260
|
layer = layers[i]
|
|
261
261
|
actual = layer.read_array(0, 0, 4, 2)
|
|
262
262
|
assert (data == actual).all()
|
|
263
|
+
|
|
264
|
+
def test_read_array_is_numpy():
|
|
265
|
+
# This test will fail if we use say the MLX backend without casting it back to numpy
|
|
266
|
+
data = np.array([[1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0]])
|
|
267
|
+
dataset = gdal_dataset_with_data((0.0, 0.0), 0.02, data)
|
|
268
|
+
with RasterLayer(dataset) as layer1:
|
|
269
|
+
actual = layer1.read_array(0, 0, 4, 2).astype(int)
|
|
270
|
+
expected = data.astype(int)
|
|
271
|
+
assert (actual == expected).all
|
|
@@ -19,7 +19,7 @@ def test_basic_vector_layer_no_filter_match() -> None:
|
|
|
19
19
|
with RasteredVectorLayer.layer_from_file(path, "id_no = 123", PixelScale(1.0, -1.0), "WGS 84") as _layer:
|
|
20
20
|
pass
|
|
21
21
|
|
|
22
|
-
def
|
|
22
|
+
def test_basic_dynamic_vector_layer() -> None:
|
|
23
23
|
with tempfile.TemporaryDirectory() as tempdir:
|
|
24
24
|
path = os.path.join(tempdir, "test.gpkg")
|
|
25
25
|
area = Area(-10.0, 10.0, 10.0, 0.0)
|
|
@@ -31,6 +31,10 @@ def test_basic_dyanamic_vector_layer() -> None:
|
|
|
31
31
|
assert layer.window == Window(0, 0, 20, 10)
|
|
32
32
|
assert layer.projection == WGS_84_PROJECTION
|
|
33
33
|
|
|
34
|
+
# The astype here is to catch escaping MLX types...
|
|
35
|
+
res = layer.read_array(0, 0, 20, 20).astype(int)
|
|
36
|
+
assert res.sum() > 0
|
|
37
|
+
|
|
34
38
|
def test_rastered_vector_layer() -> None:
|
|
35
39
|
with tempfile.TemporaryDirectory() as tempdir:
|
|
36
40
|
path = os.path.join(tempdir, "test.gpkg")
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
|
-
from typing import
|
|
2
|
+
from typing import Optional, Sequence, Tuple, Union
|
|
3
3
|
|
|
4
4
|
from .layers.base import YirgacheffeLayer
|
|
5
5
|
from .layers.group import GroupLayer, TiledGroupLayer
|
|
@@ -32,7 +32,7 @@ def read_raster(
|
|
|
32
32
|
return RasterLayer.layer_from_file(filename, band, ignore_nodata)
|
|
33
33
|
|
|
34
34
|
def read_rasters(
|
|
35
|
-
filenames : Union[
|
|
35
|
+
filenames : Sequence[Union[Path,str]],
|
|
36
36
|
tiled: bool=False
|
|
37
37
|
) -> GroupLayer:
|
|
38
38
|
"""Open a set of raster files (e.g., GeoTIFFs) as a single layer.
|
|
@@ -7,6 +7,7 @@ from .. import __version__
|
|
|
7
7
|
from ..operators import DataType, LayerMathMixin
|
|
8
8
|
from ..rounding import almost_equal, round_up_pixels, round_down_pixels
|
|
9
9
|
from ..window import Area, MapProjection, PixelScale, Window
|
|
10
|
+
from .._backends import backend
|
|
10
11
|
|
|
11
12
|
class YirgacheffeLayer(LayerMathMixin):
|
|
12
13
|
"""The common base class for the different layer types. Most still inherit from RasterLayer as deep down
|
|
@@ -310,6 +311,9 @@ class YirgacheffeLayer(LayerMathMixin):
|
|
|
310
311
|
)
|
|
311
312
|
return self._read_array_with_window(x, y, width, height, target_window)
|
|
312
313
|
|
|
314
|
+
def _read_array(self, x: int, y: int, width: int, height: int) -> Any:
|
|
315
|
+
return self._read_array_with_window(x, y, width, height, self.window)
|
|
316
|
+
|
|
313
317
|
def read_array(self, x: int, y: int, width: int, height: int) -> Any:
|
|
314
318
|
"""Reads data from the layer based on the current reference window.
|
|
315
319
|
|
|
@@ -329,7 +333,8 @@ class YirgacheffeLayer(LayerMathMixin):
|
|
|
329
333
|
Any
|
|
330
334
|
An array of values from the layer.
|
|
331
335
|
"""
|
|
332
|
-
|
|
336
|
+
res = self._read_array(x, y, width, height)
|
|
337
|
+
return backend.demote_array(res)
|
|
333
338
|
|
|
334
339
|
def latlng_for_pixel(self, x_coord: int, y_coord: int) -> Tuple[float,float]:
|
|
335
340
|
"""Get geo coords for pixel. This is relative to the set view window."""
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
import copy
|
|
3
3
|
from pathlib import Path
|
|
4
|
-
from typing import Any, List, Optional, Union
|
|
4
|
+
from typing import Any, List, Optional, Sequence, Union
|
|
5
5
|
|
|
6
6
|
import numpy as np
|
|
7
7
|
from numpy import ma
|
|
@@ -39,14 +39,14 @@ class GroupLayer(YirgacheffeLayer):
|
|
|
39
39
|
@classmethod
|
|
40
40
|
def layer_from_files(
|
|
41
41
|
cls,
|
|
42
|
-
filenames: Union[
|
|
42
|
+
filenames: Sequence[Union[Path,str]],
|
|
43
43
|
name: Optional[str] = None
|
|
44
44
|
) -> GroupLayer:
|
|
45
45
|
if filenames is None:
|
|
46
46
|
raise ValueError("filenames argument is None")
|
|
47
|
-
if len(filenames) < 1:
|
|
48
|
-
raise GroupLayerEmpty("No files found")
|
|
49
47
|
rasters: List[YirgacheffeLayer] = [RasterLayer.layer_from_file(x) for x in filenames]
|
|
48
|
+
if len(rasters) < 1:
|
|
49
|
+
raise GroupLayerEmpty("No files found")
|
|
50
50
|
return cls(rasters, name)
|
|
51
51
|
|
|
52
52
|
def __init__(
|
|
@@ -144,7 +144,7 @@ class GroupLayer(YirgacheffeLayer):
|
|
|
144
144
|
if len(contributing_layers) == 1:
|
|
145
145
|
layer, adjusted_layer_window, intersection = contributing_layers[0]
|
|
146
146
|
if target_window == intersection:
|
|
147
|
-
data = layer.
|
|
147
|
+
data = layer._read_array(
|
|
148
148
|
intersection.xoff - adjusted_layer_window.xoff,
|
|
149
149
|
intersection.yoff - adjusted_layer_window.yoff,
|
|
150
150
|
intersection.xsize,
|
|
@@ -156,11 +156,11 @@ class GroupLayer(YirgacheffeLayer):
|
|
|
156
156
|
|
|
157
157
|
result = np.zeros((ysize, xsize), dtype=float)
|
|
158
158
|
for layer, adjusted_layer_window, intersection in contributing_layers:
|
|
159
|
-
data = layer.
|
|
159
|
+
data = layer._read_array(
|
|
160
160
|
intersection.xoff - adjusted_layer_window.xoff,
|
|
161
161
|
intersection.yoff - adjusted_layer_window.yoff,
|
|
162
162
|
intersection.xsize,
|
|
163
|
-
intersection.ysize
|
|
163
|
+
intersection.ysize
|
|
164
164
|
)
|
|
165
165
|
result_x_offset = (intersection.xoff - xoffset) - window.xoff
|
|
166
166
|
result_y_offset = (intersection.yoff - yoffset) - window.yoff
|
|
@@ -269,7 +269,7 @@ class TiledGroupLayer(GroupLayer):
|
|
|
269
269
|
intersection = Window.find_intersection_no_throw([target_window, adjusted_layer_window])
|
|
270
270
|
if intersection is None:
|
|
271
271
|
continue
|
|
272
|
-
data = layer.
|
|
272
|
+
data = layer._read_array(
|
|
273
273
|
intersection.xoff - adjusted_layer_window.xoff,
|
|
274
274
|
intersection.yoff - adjusted_layer_window.yoff,
|
|
275
275
|
intersection.xsize,
|
|
@@ -490,5 +490,9 @@ class VectorLayer(YirgacheffeLayer):
|
|
|
490
490
|
def _read_array_with_window(self, _x, _y, _width, _height, _window) -> Any:
|
|
491
491
|
assert NotRequired
|
|
492
492
|
|
|
493
|
-
def
|
|
493
|
+
def _read_array(self, x: int, y: int, width: int, height: int) -> Any:
|
|
494
494
|
return self._read_array_for_area(self.area, None, x, y, width, height)
|
|
495
|
+
|
|
496
|
+
def read_array(self, x: int, y: int, width: int, height: int) -> Any:
|
|
497
|
+
res = self._read_array(x, y, width, height)
|
|
498
|
+
return backend.demote_array(res)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|