yirgacheffe 1.3.4__tar.gz → 1.4.0__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.3.4/yirgacheffe.egg-info → yirgacheffe-1.4.0}/PKG-INFO +1 -1
- {yirgacheffe-1.3.4 → yirgacheffe-1.4.0}/pyproject.toml +1 -1
- {yirgacheffe-1.3.4 → yirgacheffe-1.4.0}/tests/test_auto_windowing.py +1 -1
- {yirgacheffe-1.3.4 → yirgacheffe-1.4.0}/tests/test_datatypes.py +1 -1
- {yirgacheffe-1.3.4 → yirgacheffe-1.4.0}/tests/test_h3layer.py +1 -1
- {yirgacheffe-1.3.4 → yirgacheffe-1.4.0}/tests/test_intersection.py +1 -2
- {yirgacheffe-1.3.4 → yirgacheffe-1.4.0}/tests/test_operators.py +5 -5
- {yirgacheffe-1.3.4 → yirgacheffe-1.4.0}/tests/test_optimisation.py +1 -2
- {yirgacheffe-1.3.4 → yirgacheffe-1.4.0}/tests/test_parallel_operators.py +10 -10
- {yirgacheffe-1.3.4 → yirgacheffe-1.4.0}/tests/test_pickle.py +1 -1
- {yirgacheffe-1.3.4 → yirgacheffe-1.4.0}/tests/test_raster.py +0 -10
- {yirgacheffe-1.3.4 → yirgacheffe-1.4.0}/tests/test_vectors.py +2 -26
- {yirgacheffe-1.3.4 → yirgacheffe-1.4.0}/yirgacheffe/__init__.py +0 -3
- {yirgacheffe-1.3.4/yirgacheffe/backends → yirgacheffe-1.4.0/yirgacheffe/_backends}/__init__.py +1 -1
- {yirgacheffe-1.3.4/yirgacheffe/backends → yirgacheffe-1.4.0/yirgacheffe/_backends}/mlx.py +1 -1
- yirgacheffe-1.4.0/yirgacheffe/layers/__init__.py +14 -0
- {yirgacheffe-1.3.4 → yirgacheffe-1.4.0}/yirgacheffe/layers/base.py +20 -7
- {yirgacheffe-1.3.4 → yirgacheffe-1.4.0}/yirgacheffe/layers/constant.py +1 -1
- {yirgacheffe-1.3.4 → yirgacheffe-1.4.0}/yirgacheffe/layers/group.py +14 -11
- {yirgacheffe-1.3.4 → yirgacheffe-1.4.0}/yirgacheffe/layers/h3layer.py +7 -2
- {yirgacheffe-1.3.4 → yirgacheffe-1.4.0}/yirgacheffe/layers/rasters.py +27 -16
- {yirgacheffe-1.3.4 → yirgacheffe-1.4.0}/yirgacheffe/layers/rescaled.py +3 -2
- {yirgacheffe-1.3.4 → yirgacheffe-1.4.0}/yirgacheffe/layers/vectors.py +37 -30
- {yirgacheffe-1.3.4 → yirgacheffe-1.4.0}/yirgacheffe/operators.py +13 -10
- {yirgacheffe-1.3.4 → yirgacheffe-1.4.0}/yirgacheffe/window.py +93 -2
- {yirgacheffe-1.3.4 → yirgacheffe-1.4.0/yirgacheffe.egg-info}/PKG-INFO +1 -1
- {yirgacheffe-1.3.4 → yirgacheffe-1.4.0}/yirgacheffe.egg-info/SOURCES.txt +4 -5
- yirgacheffe-1.3.4/yirgacheffe/h3layer.py +0 -2
- yirgacheffe-1.3.4/yirgacheffe/layers/__init__.py +0 -43
- {yirgacheffe-1.3.4 → yirgacheffe-1.4.0}/LICENSE +0 -0
- {yirgacheffe-1.3.4 → yirgacheffe-1.4.0}/MANIFEST.in +0 -0
- {yirgacheffe-1.3.4 → yirgacheffe-1.4.0}/README.md +0 -0
- {yirgacheffe-1.3.4 → yirgacheffe-1.4.0}/setup.cfg +0 -0
- {yirgacheffe-1.3.4 → yirgacheffe-1.4.0}/tests/test_area.py +0 -0
- {yirgacheffe-1.3.4 → yirgacheffe-1.4.0}/tests/test_base.py +0 -0
- {yirgacheffe-1.3.4 → yirgacheffe-1.4.0}/tests/test_constants.py +0 -0
- {yirgacheffe-1.3.4 → yirgacheffe-1.4.0}/tests/test_group.py +0 -0
- {yirgacheffe-1.3.4 → yirgacheffe-1.4.0}/tests/test_multiband.py +0 -0
- {yirgacheffe-1.3.4 → yirgacheffe-1.4.0}/tests/test_rescaling.py +0 -0
- {yirgacheffe-1.3.4 → yirgacheffe-1.4.0}/tests/test_rounding.py +0 -0
- {yirgacheffe-1.3.4 → yirgacheffe-1.4.0}/tests/test_save_with_window.py +0 -0
- {yirgacheffe-1.3.4 → yirgacheffe-1.4.0}/tests/test_sum_with_window.py +0 -0
- {yirgacheffe-1.3.4 → yirgacheffe-1.4.0}/tests/test_uniform_area_layer.py +0 -0
- {yirgacheffe-1.3.4 → yirgacheffe-1.4.0}/tests/test_union.py +0 -0
- {yirgacheffe-1.3.4 → yirgacheffe-1.4.0}/tests/test_window.py +0 -0
- {yirgacheffe-1.3.4/yirgacheffe/backends → yirgacheffe-1.4.0/yirgacheffe/_backends}/enumeration.py +0 -0
- {yirgacheffe-1.3.4/yirgacheffe/backends → yirgacheffe-1.4.0/yirgacheffe/_backends}/numpy.py +0 -0
- {yirgacheffe-1.3.4 → yirgacheffe-1.4.0}/yirgacheffe/constants.py +0 -0
- {yirgacheffe-1.3.4 → yirgacheffe-1.4.0}/yirgacheffe/layers/area.py +0 -0
- {yirgacheffe-1.3.4 → yirgacheffe-1.4.0}/yirgacheffe/rounding.py +0 -0
- {yirgacheffe-1.3.4 → yirgacheffe-1.4.0}/yirgacheffe.egg-info/dependency_links.txt +0 -0
- {yirgacheffe-1.3.4 → yirgacheffe-1.4.0}/yirgacheffe.egg-info/entry_points.txt +0 -0
- {yirgacheffe-1.3.4 → yirgacheffe-1.4.0}/yirgacheffe.egg-info/requires.txt +0 -0
- {yirgacheffe-1.3.4 → yirgacheffe-1.4.0}/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.
|
|
9
|
+
version = "1.4.0"
|
|
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" }]
|
|
@@ -251,7 +251,7 @@ def test_vector_layers_multiply() -> None:
|
|
|
251
251
|
expected = np.array([[2, 0], [0, 8]])
|
|
252
252
|
assert (expected == actual).all()
|
|
253
253
|
|
|
254
|
-
@pytest.mark.skipif(yirgacheffe.
|
|
254
|
+
@pytest.mark.skipif(yirgacheffe._backends.BACKEND != "NUMPY", reason="Only applies for numpy")
|
|
255
255
|
def test_parallel_save_windows() -> None:
|
|
256
256
|
data1 = np.array([[1, 2], [3, 4]])
|
|
257
257
|
data2 = np.array([[10, 20, 30, 40], [50, 60, 70, 80], [90, 100, 110, 120], [130, 140, 150, 160]])
|
|
@@ -4,7 +4,7 @@ import pytest
|
|
|
4
4
|
from osgeo import gdal
|
|
5
5
|
|
|
6
6
|
from yirgacheffe.operators import DataType
|
|
7
|
-
from yirgacheffe.
|
|
7
|
+
from yirgacheffe._backends import backend, BACKEND
|
|
8
8
|
from yirgacheffe.layers import RasterLayer
|
|
9
9
|
|
|
10
10
|
from tests.helpers import gdal_dataset_with_data
|
|
@@ -6,7 +6,7 @@ from osgeo import gdal
|
|
|
6
6
|
from yirgacheffe import WGS_84_PROJECTION
|
|
7
7
|
from yirgacheffe.layers import RasterLayer, H3CellLayer
|
|
8
8
|
from yirgacheffe.window import Area, PixelScale
|
|
9
|
-
from yirgacheffe.
|
|
9
|
+
from yirgacheffe._backends import backend
|
|
10
10
|
|
|
11
11
|
# work around of pylint
|
|
12
12
|
demote_array = backend.demote_array
|
|
@@ -3,8 +3,7 @@ from osgeo import gdal
|
|
|
3
3
|
|
|
4
4
|
from tests.helpers import gdal_dataset_of_region, gdal_empty_dataset_of_region
|
|
5
5
|
from yirgacheffe.window import Area, PixelScale, Window
|
|
6
|
-
from yirgacheffe.layers import RasterLayer, ConstantLayer
|
|
7
|
-
from yirgacheffe.h3layer import H3CellLayer
|
|
6
|
+
from yirgacheffe.layers import RasterLayer, ConstantLayer, H3CellLayer
|
|
8
7
|
from yirgacheffe import WGS_84_PROJECTION
|
|
9
8
|
|
|
10
9
|
|
|
@@ -9,7 +9,7 @@ import torch
|
|
|
9
9
|
import yirgacheffe
|
|
10
10
|
from yirgacheffe.layers import RasterLayer, ConstantLayer
|
|
11
11
|
from yirgacheffe.operators import LayerOperation, DataType
|
|
12
|
-
from yirgacheffe.
|
|
12
|
+
from yirgacheffe._backends import backend
|
|
13
13
|
from tests.helpers import gdal_dataset_with_data
|
|
14
14
|
|
|
15
15
|
def test_add_byte_layers() -> None:
|
|
@@ -584,7 +584,7 @@ def test_direct_layer_save_and_sum() -> None:
|
|
|
584
584
|
assert (data1 == actual_data).all()
|
|
585
585
|
assert expected_sum == actual_sum
|
|
586
586
|
|
|
587
|
-
@pytest.mark.skipif(yirgacheffe.
|
|
587
|
+
@pytest.mark.skipif(yirgacheffe._backends.BACKEND != "NUMPY", reason="Only applies for numpy")
|
|
588
588
|
def test_add_to_float_layer_by_np_array() -> None:
|
|
589
589
|
data1 = np.array([[1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0]])
|
|
590
590
|
layer1 = RasterLayer(gdal_dataset_with_data((0.0, 0.0), 0.02, data1))
|
|
@@ -619,7 +619,7 @@ def test_write_mulitband_raster() -> None:
|
|
|
619
619
|
|
|
620
620
|
assert (expected == actual).all()
|
|
621
621
|
|
|
622
|
-
@pytest.mark.skipif(yirgacheffe.
|
|
622
|
+
@pytest.mark.skipif(yirgacheffe._backends.BACKEND != "NUMPY", reason="Only applies for numpy")
|
|
623
623
|
def test_save_and_sum_float32(monkeypatch) -> None:
|
|
624
624
|
random.seed(42)
|
|
625
625
|
data = []
|
|
@@ -643,7 +643,7 @@ def test_save_and_sum_float32(monkeypatch) -> None:
|
|
|
643
643
|
actual = layer1.save(store, and_sum=True)
|
|
644
644
|
assert expected == actual
|
|
645
645
|
|
|
646
|
-
@pytest.mark.skipif(yirgacheffe.
|
|
646
|
+
@pytest.mark.skipif(yirgacheffe._backends.BACKEND != "NUMPY", reason="Only applies for numpy")
|
|
647
647
|
def test_parallel_save_and_sum_float32(monkeypatch) -> None:
|
|
648
648
|
random.seed(42)
|
|
649
649
|
data = []
|
|
@@ -671,7 +671,7 @@ def test_parallel_save_and_sum_float32(monkeypatch) -> None:
|
|
|
671
671
|
actual = layer1.parallel_save(store, and_sum=True)
|
|
672
672
|
assert expected == actual
|
|
673
673
|
|
|
674
|
-
@pytest.mark.skipif(yirgacheffe.
|
|
674
|
+
@pytest.mark.skipif(yirgacheffe._backends.BACKEND != "NUMPY", reason="Only applies for numpy")
|
|
675
675
|
def test_sum_float32(monkeypatch) -> None:
|
|
676
676
|
random.seed(42)
|
|
677
677
|
data = []
|
|
@@ -4,8 +4,7 @@ import numpy as np
|
|
|
4
4
|
import pytest
|
|
5
5
|
|
|
6
6
|
from yirgacheffe import WGS_84_PROJECTION
|
|
7
|
-
from yirgacheffe.
|
|
8
|
-
from yirgacheffe.layers import PixelScale, RasterLayer
|
|
7
|
+
from yirgacheffe.layers import PixelScale, RasterLayer, H3CellLayer
|
|
9
8
|
from yirgacheffe.window import Area
|
|
10
9
|
import yirgacheffe.operators as yo
|
|
11
10
|
|
|
@@ -43,7 +43,7 @@ def test_add_byte_layers_with_one_thread_uses_regular_save(monkeypatch) -> None:
|
|
|
43
43
|
comp.parallel_save(result)
|
|
44
44
|
|
|
45
45
|
|
|
46
|
-
@pytest.mark.skipif(yirgacheffe.
|
|
46
|
+
@pytest.mark.skipif(yirgacheffe._backends.BACKEND != "NUMPY", reason="Only applies for numpy")
|
|
47
47
|
def test_add_byte_layers(monkeypatch) -> None:
|
|
48
48
|
with monkeypatch.context() as m:
|
|
49
49
|
m.setattr(yirgacheffe.constants, "YSTEP", 1)
|
|
@@ -71,7 +71,7 @@ def test_add_byte_layers(monkeypatch) -> None:
|
|
|
71
71
|
|
|
72
72
|
assert (expected == actual).all()
|
|
73
73
|
|
|
74
|
-
@pytest.mark.skipif(yirgacheffe.
|
|
74
|
+
@pytest.mark.skipif(yirgacheffe._backends.BACKEND != "NUMPY", reason="Only applies for numpy")
|
|
75
75
|
def test_add_byte_layers_and_sum(monkeypatch) -> None:
|
|
76
76
|
with monkeypatch.context() as m:
|
|
77
77
|
m.setattr(yirgacheffe.constants, "YSTEP", 1)
|
|
@@ -100,7 +100,7 @@ def test_add_byte_layers_and_sum(monkeypatch) -> None:
|
|
|
100
100
|
assert (expected == actual).all()
|
|
101
101
|
assert sum_total == expected.sum()
|
|
102
102
|
|
|
103
|
-
@pytest.mark.skipif(yirgacheffe.
|
|
103
|
+
@pytest.mark.skipif(yirgacheffe._backends.BACKEND != "NUMPY", reason="Only applies for numpy")
|
|
104
104
|
def test_parallel_sum(monkeypatch) -> None:
|
|
105
105
|
with monkeypatch.context() as m:
|
|
106
106
|
m.setattr(yirgacheffe.constants, "YSTEP", 1)
|
|
@@ -125,7 +125,7 @@ def test_parallel_sum(monkeypatch) -> None:
|
|
|
125
125
|
expected = data1 + data2
|
|
126
126
|
assert sum_total == expected.sum()
|
|
127
127
|
|
|
128
|
-
@pytest.mark.skipif(yirgacheffe.
|
|
128
|
+
@pytest.mark.skipif(yirgacheffe._backends.BACKEND != "NUMPY", reason="Only applies for numpy")
|
|
129
129
|
@pytest.mark.parametrize("skip,expected_steps", [
|
|
130
130
|
(1, [0.0, 0.25, 0.5, 0.75, 1.0]),
|
|
131
131
|
(2, [0.0, 0.5, 1.0]),
|
|
@@ -162,7 +162,7 @@ def test_parallel_with_different_skip(monkeypatch, skip, expected_steps) -> None
|
|
|
162
162
|
|
|
163
163
|
assert callback_possitions == expected_steps
|
|
164
164
|
|
|
165
|
-
@pytest.mark.skipif(yirgacheffe.
|
|
165
|
+
@pytest.mark.skipif(yirgacheffe._backends.BACKEND != "NUMPY", reason="Only applies for numpy")
|
|
166
166
|
def test_parallel_equality(monkeypatch) -> None:
|
|
167
167
|
with monkeypatch.context() as m:
|
|
168
168
|
m.setattr(yirgacheffe.constants, "YSTEP", 1)
|
|
@@ -182,7 +182,7 @@ def test_parallel_equality(monkeypatch) -> None:
|
|
|
182
182
|
|
|
183
183
|
assert (expected == actual).all()
|
|
184
184
|
|
|
185
|
-
@pytest.mark.skipif(yirgacheffe.
|
|
185
|
+
@pytest.mark.skipif(yirgacheffe._backends.BACKEND != "NUMPY", reason="Only applies for numpy")
|
|
186
186
|
def test_parallel_equality_to_file(monkeypatch) -> None:
|
|
187
187
|
with monkeypatch.context() as m:
|
|
188
188
|
m.setattr(yirgacheffe.constants, "YSTEP", 1)
|
|
@@ -202,7 +202,7 @@ def test_parallel_equality_to_file(monkeypatch) -> None:
|
|
|
202
202
|
actual = actual_result.read_array(0, 0, 4, 2)
|
|
203
203
|
assert (expected == actual).all()
|
|
204
204
|
|
|
205
|
-
@pytest.mark.skipif(yirgacheffe.
|
|
205
|
+
@pytest.mark.skipif(yirgacheffe._backends.BACKEND != "NUMPY", reason="Only applies for numpy")
|
|
206
206
|
def test_parallel_unary_numpy_apply_with_function(monkeypatch) -> None:
|
|
207
207
|
with monkeypatch.context() as m:
|
|
208
208
|
m.setattr(yirgacheffe.constants, "YSTEP", 1)
|
|
@@ -228,7 +228,7 @@ def test_parallel_unary_numpy_apply_with_function(monkeypatch) -> None:
|
|
|
228
228
|
|
|
229
229
|
assert (expected == actual).all()
|
|
230
230
|
|
|
231
|
-
@pytest.mark.skipif(yirgacheffe.
|
|
231
|
+
@pytest.mark.skipif(yirgacheffe._backends.BACKEND != "NUMPY", reason="Only applies for numpy")
|
|
232
232
|
def test_parallel_unary_numpy_apply_with_lambda(monkeypatch) -> None:
|
|
233
233
|
with monkeypatch.context() as m:
|
|
234
234
|
m.setattr(yirgacheffe.constants, "YSTEP", 1)
|
|
@@ -251,7 +251,7 @@ def test_parallel_unary_numpy_apply_with_lambda(monkeypatch) -> None:
|
|
|
251
251
|
|
|
252
252
|
assert (expected == actual).all()
|
|
253
253
|
|
|
254
|
-
@pytest.mark.skipif(yirgacheffe.
|
|
254
|
+
@pytest.mark.skipif(yirgacheffe._backends.BACKEND != "NUMPY", reason="Only applies for numpy")
|
|
255
255
|
def test_parallel_where_simple(monkeypatch) -> None:
|
|
256
256
|
with monkeypatch.context() as m:
|
|
257
257
|
m.setattr(yirgacheffe.constants, "YSTEP", 1)
|
|
@@ -273,7 +273,7 @@ def test_parallel_where_simple(monkeypatch) -> None:
|
|
|
273
273
|
actual = result.read_array(0, 0, 4, 2)
|
|
274
274
|
assert (expected == actual).all()
|
|
275
275
|
|
|
276
|
-
@pytest.mark.skipif(yirgacheffe.
|
|
276
|
+
@pytest.mark.skipif(yirgacheffe._backends.BACKEND != "NUMPY", reason="Only applies for numpy")
|
|
277
277
|
def test_parallel_conv2d() -> None:
|
|
278
278
|
with tempfile.TemporaryDirectory() as tempdir:
|
|
279
279
|
|
|
@@ -12,7 +12,7 @@ from yirgacheffe.window import Area, 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.
|
|
15
|
+
from yirgacheffe._backends import backend
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
def test_pickle_raster_layer() -> None:
|
|
@@ -38,16 +38,6 @@ def test_make_basic_layer() -> None:
|
|
|
38
38
|
|
|
39
39
|
assert close_called
|
|
40
40
|
|
|
41
|
-
def test_make_basic_layer_old_name() -> None:
|
|
42
|
-
from yirgacheffe.layers import Layer # pylint: disable=C0415
|
|
43
|
-
|
|
44
|
-
area = Area(-10, 10, 10, -10)
|
|
45
|
-
with Layer(gdal_dataset_of_region(area, 0.02)) as layer:
|
|
46
|
-
assert layer.area == area
|
|
47
|
-
assert layer.pixel_scale == (0.02, -0.02)
|
|
48
|
-
assert layer.geo_transform == (-10, 0.02, 0.0, 10, 0.0, -0.02)
|
|
49
|
-
assert layer.window == Window(0, 0, 1000, 1000)
|
|
50
|
-
|
|
51
41
|
def test_layer_from_null() -> None:
|
|
52
42
|
# Seems a petty test, but gdal doesn't throw exceptions
|
|
53
43
|
# so you often get None datasets if you're not careful
|
|
@@ -5,7 +5,7 @@ import pytest
|
|
|
5
5
|
|
|
6
6
|
from tests.helpers import make_vectors_with_mutlile_ids, make_vectors_with_id, make_vectors_with_empty_feature
|
|
7
7
|
from yirgacheffe import WGS_84_PROJECTION
|
|
8
|
-
from yirgacheffe.layers import RasterLayer, RasteredVectorLayer, VectorLayer
|
|
8
|
+
from yirgacheffe.layers import RasterLayer, RasteredVectorLayer, VectorLayer
|
|
9
9
|
from yirgacheffe.window import Area, PixelScale, Window
|
|
10
10
|
from yirgacheffe.operators import DataType
|
|
11
11
|
|
|
@@ -31,18 +31,6 @@ 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
|
-
def test_old_dyanamic_vector_layer() -> None:
|
|
35
|
-
with tempfile.TemporaryDirectory() as tempdir:
|
|
36
|
-
path = os.path.join(tempdir, "test.gpkg")
|
|
37
|
-
area = Area(-10.0, 10.0, 10.0, 0.0)
|
|
38
|
-
make_vectors_with_id(42, {area}, path)
|
|
39
|
-
|
|
40
|
-
with DynamicVectorRangeLayer(path, "id_no = 42", PixelScale(1.0, -1.0), WGS_84_PROJECTION) as layer:
|
|
41
|
-
assert layer.area == area
|
|
42
|
-
assert layer.geo_transform == (area.left, 1.0, 0.0, area.top, 0.0, -1.0)
|
|
43
|
-
assert layer.window == Window(0, 0, 20, 10)
|
|
44
|
-
assert layer.projection == WGS_84_PROJECTION
|
|
45
|
-
|
|
46
34
|
def test_rastered_vector_layer() -> None:
|
|
47
35
|
with tempfile.TemporaryDirectory() as tempdir:
|
|
48
36
|
path = os.path.join(tempdir, "test.gpkg")
|
|
@@ -55,18 +43,6 @@ def test_rastered_vector_layer() -> None:
|
|
|
55
43
|
assert layer.window == Window(0, 0, 20, 10)
|
|
56
44
|
assert layer.projection == WGS_84_PROJECTION
|
|
57
45
|
|
|
58
|
-
def test_old_rastered_vector_layer() -> None:
|
|
59
|
-
with tempfile.TemporaryDirectory() as tempdir:
|
|
60
|
-
path = os.path.join(tempdir, "test.gpkg")
|
|
61
|
-
area = Area(-10.0, 10.0, 10.0, 0.0)
|
|
62
|
-
make_vectors_with_id(42, {area}, path)
|
|
63
|
-
|
|
64
|
-
with VectorRangeLayer(path, "id_no = 42", PixelScale(1.0, -1.0), WGS_84_PROJECTION) as layer:
|
|
65
|
-
assert layer.area == area
|
|
66
|
-
assert layer.geo_transform == (area.left, 1.0, 0.0, area.top, 0.0, -1.0)
|
|
67
|
-
assert layer.window == Window(0, 0, 20, 10)
|
|
68
|
-
assert layer.projection == WGS_84_PROJECTION
|
|
69
|
-
|
|
70
46
|
def test_basic_dynamic_vector_layer_no_filter_match() -> None:
|
|
71
47
|
with tempfile.TemporaryDirectory() as tempdir:
|
|
72
48
|
path = os.path.join(tempdir, "test.gpkg")
|
|
@@ -385,7 +361,7 @@ def test_read_array_size(size, expect_success):
|
|
|
385
361
|
area = Area(-10.0, 10.0, 10.0, 0.0)
|
|
386
362
|
make_vectors_with_id(42, {area}, path)
|
|
387
363
|
|
|
388
|
-
source =
|
|
364
|
+
source = RasteredVectorLayer.layer_from_file(path, "id_no = 42", PixelScale(1.0, -1.0), WGS_84_PROJECTION)
|
|
389
365
|
|
|
390
366
|
if expect_success:
|
|
391
367
|
data = source.read_array(0, 0, size[0], size[1])
|
|
@@ -12,6 +12,3 @@ WGS_84_PROJECTION = 'GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,
|
|
|
12
12
|
'AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0],'\
|
|
13
13
|
'UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AXIS["Latitude",NORTH],'\
|
|
14
14
|
'AXIS["Longitude",EAST],AUTHORITY["EPSG","4326"]]'
|
|
15
|
-
|
|
16
|
-
# For legacy reasons [facepalm]
|
|
17
|
-
WSG_84_PROJECTION = WGS_84_PROJECTION
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from osgeo import ogr
|
|
2
|
+
|
|
3
|
+
from ..window import PixelScale
|
|
4
|
+
from .base import YirgacheffeLayer
|
|
5
|
+
from .rasters import RasterLayer, InvalidRasterBand
|
|
6
|
+
from .rescaled import RescaledRasterLayer
|
|
7
|
+
from .vectors import RasteredVectorLayer, VectorLayer
|
|
8
|
+
from .area import UniformAreaLayer
|
|
9
|
+
from .constant import ConstantLayer
|
|
10
|
+
from .group import GroupLayer, TiledGroupLayer
|
|
11
|
+
try:
|
|
12
|
+
from .h3layer import H3CellLayer
|
|
13
|
+
except ModuleNotFoundError:
|
|
14
|
+
pass
|
|
@@ -25,7 +25,7 @@ class YirgacheffeLayer(LayerMathMixin):
|
|
|
25
25
|
|
|
26
26
|
self.reset_window()
|
|
27
27
|
|
|
28
|
-
def close(self):
|
|
28
|
+
def close(self) -> None:
|
|
29
29
|
pass
|
|
30
30
|
|
|
31
31
|
def __enter__(self):
|
|
@@ -34,6 +34,16 @@ class YirgacheffeLayer(LayerMathMixin):
|
|
|
34
34
|
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
35
35
|
self.close()
|
|
36
36
|
|
|
37
|
+
def _park(self) -> None:
|
|
38
|
+
pass
|
|
39
|
+
|
|
40
|
+
def _unpark(self) -> None:
|
|
41
|
+
pass
|
|
42
|
+
|
|
43
|
+
@property
|
|
44
|
+
def _raster_dimensions(self) -> Tuple[int,int]:
|
|
45
|
+
raise AttributeError("Does not have raster")
|
|
46
|
+
|
|
37
47
|
@property
|
|
38
48
|
def datatype(self) -> DataType:
|
|
39
49
|
raise NotImplementedError("Must be overridden by subclass")
|
|
@@ -131,9 +141,10 @@ class YirgacheffeLayer(LayerMathMixin):
|
|
|
131
141
|
raise ValueError('Window has negative offset')
|
|
132
142
|
# If there is an underlying raster for this layer, do a sanity check
|
|
133
143
|
try:
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
144
|
+
raster_xsize, raster_ysize = self._raster_dimensions
|
|
145
|
+
if ((new_window.xoff + new_window.xsize) > raster_xsize) or \
|
|
146
|
+
((new_window.yoff + new_window.ysize) > raster_ysize):
|
|
147
|
+
raise ValueError(f'Window is bigger than dataset: raster is {raster_xsize}x{raster_ysize}'\
|
|
137
148
|
f', new window is {new_window.xsize - new_window.xoff}x{new_window.ysize - new_window.yoff}')
|
|
138
149
|
except AttributeError:
|
|
139
150
|
pass
|
|
@@ -162,9 +173,10 @@ class YirgacheffeLayer(LayerMathMixin):
|
|
|
162
173
|
raise ValueError('Window has positive offset')
|
|
163
174
|
# If there is an underlying raster for this layer, do a sanity check
|
|
164
175
|
try:
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
176
|
+
raster_xsize, raster_ysize = self._raster_dimensions
|
|
177
|
+
if ((new_window.xsize - new_window.xoff) < raster_xsize) or \
|
|
178
|
+
((new_window.ysize - new_window.yoff) <raster_ysize):
|
|
179
|
+
raise ValueError(f'Window is smaller than dataset: raster is {raster_xsize}x{raster_ysize}'\
|
|
168
180
|
f', new window is {new_window.xsize - new_window.xoff}x{new_window.ysize - new_window.yoff}')
|
|
169
181
|
except AttributeError:
|
|
170
182
|
pass
|
|
@@ -219,6 +231,7 @@ class YirgacheffeLayer(LayerMathMixin):
|
|
|
219
231
|
raise NotImplementedError("Must be overridden by subclass")
|
|
220
232
|
|
|
221
233
|
def read_array_for_area(self, target_area: Area, x: int, y: int, width: int, height: int) -> Any:
|
|
234
|
+
assert self._pixel_scale is not None
|
|
222
235
|
|
|
223
236
|
target_window = Window(
|
|
224
237
|
xoff=round_down_pixels((target_area.left - self._underlying_area.left) / self._pixel_scale.xstep,
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
1
2
|
import copy
|
|
2
3
|
import glob
|
|
3
4
|
import os
|
|
4
|
-
from typing import Any, List, Optional
|
|
5
|
+
from typing import Any, List, Optional
|
|
5
6
|
|
|
6
7
|
import numpy as np
|
|
7
8
|
from yirgacheffe.operators import DataType
|
|
@@ -10,9 +11,8 @@ from ..rounding import are_pixel_scales_equal_enough, round_down_pixels
|
|
|
10
11
|
from ..window import Area, Window
|
|
11
12
|
from .base import YirgacheffeLayer
|
|
12
13
|
from .rasters import RasterLayer
|
|
13
|
-
from ..
|
|
14
|
+
from .._backends import backend
|
|
14
15
|
|
|
15
|
-
GroupLayerT = TypeVar("GroupLayerT", bound="GroupLayer")
|
|
16
16
|
|
|
17
17
|
class GroupLayerEmpty(ValueError):
|
|
18
18
|
def __init__(self, msg):
|
|
@@ -26,7 +26,7 @@ class GroupLayer(YirgacheffeLayer):
|
|
|
26
26
|
directory_path: str,
|
|
27
27
|
name: Optional[str] = None,
|
|
28
28
|
matching: str = "*.tif"
|
|
29
|
-
) ->
|
|
29
|
+
) -> GroupLayer:
|
|
30
30
|
if directory_path is None:
|
|
31
31
|
raise ValueError("Directory path is None")
|
|
32
32
|
files = [os.path.join(directory_path, x) for x in glob.glob(matching, root_dir=directory_path)]
|
|
@@ -35,12 +35,12 @@ class GroupLayer(YirgacheffeLayer):
|
|
|
35
35
|
return cls.layer_from_files(files, name)
|
|
36
36
|
|
|
37
37
|
@classmethod
|
|
38
|
-
def layer_from_files(cls, filenames: List[str], name: Optional[str] = None) ->
|
|
38
|
+
def layer_from_files(cls, filenames: List[str], name: Optional[str] = None) -> GroupLayer:
|
|
39
39
|
if filenames is None:
|
|
40
40
|
raise ValueError("filenames argument is None")
|
|
41
41
|
if len(filenames) < 1:
|
|
42
42
|
raise GroupLayerEmpty("No files found")
|
|
43
|
-
rasters = [RasterLayer.layer_from_file(x) for x in filenames]
|
|
43
|
+
rasters: List[YirgacheffeLayer] = [RasterLayer.layer_from_file(x) for x in filenames]
|
|
44
44
|
return cls(rasters, name)
|
|
45
45
|
|
|
46
46
|
def __init__(self, layers: List[YirgacheffeLayer], name: Optional[str] = None) -> None:
|
|
@@ -65,7 +65,7 @@ class GroupLayer(YirgacheffeLayer):
|
|
|
65
65
|
self._underlying_layers.reverse()
|
|
66
66
|
self.layers = self._underlying_layers
|
|
67
67
|
|
|
68
|
-
def _park(self):
|
|
68
|
+
def _park(self) -> None:
|
|
69
69
|
for layer in self.layers:
|
|
70
70
|
try:
|
|
71
71
|
layer._park()
|
|
@@ -157,7 +157,7 @@ class GroupLayer(YirgacheffeLayer):
|
|
|
157
157
|
class TileData:
|
|
158
158
|
"""This class exists just to let me sort the tiles into the correct order for processing."""
|
|
159
159
|
|
|
160
|
-
def __init__(self, data, x, y):
|
|
160
|
+
def __init__(self, data: Any, x: int, y: int):
|
|
161
161
|
self.data = data
|
|
162
162
|
self.x = x
|
|
163
163
|
self.y = y
|
|
@@ -219,7 +219,7 @@ class TiledGroupLayer(GroupLayer):
|
|
|
219
219
|
ysize
|
|
220
220
|
)
|
|
221
221
|
|
|
222
|
-
partials = []
|
|
222
|
+
partials: List[TileData] = []
|
|
223
223
|
for layer in self.layers:
|
|
224
224
|
# Normally this is hidden with set_window_for_...
|
|
225
225
|
adjusted_layer_window = Window(
|
|
@@ -251,7 +251,7 @@ class TiledGroupLayer(GroupLayer):
|
|
|
251
251
|
# the "obvious" tile. In which case, we should reject the smaller section. If we have
|
|
252
252
|
# two tiles at the same offset and one is not a perfect subset of the other then the
|
|
253
253
|
# tile set we were given is not regularly shaped, and so we should give up.
|
|
254
|
-
combed_partials = []
|
|
254
|
+
combed_partials: List[TileData] = []
|
|
255
255
|
previous_tile = None
|
|
256
256
|
for tile in sorted_partials:
|
|
257
257
|
if previous_tile is None:
|
|
@@ -276,7 +276,7 @@ class TiledGroupLayer(GroupLayer):
|
|
|
276
276
|
expected_next_x = 0
|
|
277
277
|
expected_next_y = 0
|
|
278
278
|
data = None
|
|
279
|
-
row_chunk = None
|
|
279
|
+
row_chunk: Optional[np.ndarray] = None
|
|
280
280
|
|
|
281
281
|
# Allow for reading off top
|
|
282
282
|
if combed_partials:
|
|
@@ -337,6 +337,7 @@ class TiledGroupLayer(GroupLayer):
|
|
|
337
337
|
data = np.vstack((data, row_chunk))
|
|
338
338
|
expected_next_y += last_y_height
|
|
339
339
|
else:
|
|
340
|
+
assert last_y_offset is not None
|
|
340
341
|
diff = expected_next_y - last_y_offset
|
|
341
342
|
assert diff > 0, f"{expected_next_y} - {last_y_offset} <= 0 (aka {diff})"
|
|
342
343
|
subdata = np.delete(row_chunk, np.s_[0:diff], 0)
|
|
@@ -351,8 +352,10 @@ class TiledGroupLayer(GroupLayer):
|
|
|
351
352
|
last_y_height = tile.data.shape[0]
|
|
352
353
|
expected_next_x = tile.data.shape[1] + tile.x
|
|
353
354
|
|
|
355
|
+
assert last_y_offset is not None
|
|
354
356
|
if (last_y_offset + last_y_height) < ysize:
|
|
355
357
|
data = np.vstack((data, np.zeros((ysize - (last_y_offset + last_y_height), xsize))))
|
|
356
358
|
|
|
359
|
+
assert data is not None
|
|
357
360
|
assert data.shape == (ysize, xsize)
|
|
358
361
|
return backend.promote(data)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from math import ceil, floor
|
|
2
|
-
from typing import Any
|
|
2
|
+
from typing import Any, Tuple
|
|
3
3
|
|
|
4
4
|
import h3
|
|
5
5
|
import numpy as np
|
|
@@ -8,7 +8,7 @@ from yirgacheffe.operators import DataType
|
|
|
8
8
|
from ..rounding import round_up_pixels
|
|
9
9
|
from ..window import Area, PixelScale, Window
|
|
10
10
|
from .base import YirgacheffeLayer
|
|
11
|
-
from ..
|
|
11
|
+
from .._backends import backend
|
|
12
12
|
|
|
13
13
|
class H3CellLayer(YirgacheffeLayer):
|
|
14
14
|
|
|
@@ -74,12 +74,17 @@ class H3CellLayer(YirgacheffeLayer):
|
|
|
74
74
|
(sorted_lats[1] / abs_ystep) * abs_ystep,
|
|
75
75
|
)
|
|
76
76
|
|
|
77
|
+
@property
|
|
78
|
+
def _raster_dimensions(self) -> Tuple[int,int]:
|
|
79
|
+
return (self._raster_xsize, self._raster_ysize)
|
|
77
80
|
|
|
78
81
|
@property
|
|
79
82
|
def datatype(self) -> DataType:
|
|
80
83
|
return DataType.Float64
|
|
81
84
|
|
|
82
85
|
def read_array_with_window(self, xoffset: int, yoffset: int, xsize: int, ysize: int, window: Window) -> Any:
|
|
86
|
+
assert self._pixel_scale is not None
|
|
87
|
+
|
|
83
88
|
if (xsize <= 0) or (ysize <= 0):
|
|
84
89
|
raise ValueError("Request dimensions must be positive and non-zero")
|
|
85
90
|
|