yirgacheffe 1.3.3__tar.gz → 1.3.4__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.
- {yirgacheffe-1.3.3/yirgacheffe.egg-info → yirgacheffe-1.3.4}/PKG-INFO +1 -1
- {yirgacheffe-1.3.3 → yirgacheffe-1.3.4}/pyproject.toml +1 -1
- yirgacheffe-1.3.4/tests/test_area.py +21 -0
- yirgacheffe-1.3.4/tests/test_auto_windowing.py +284 -0
- yirgacheffe-1.3.4/tests/test_constants.py +32 -0
- yirgacheffe-1.3.4/tests/test_datatypes.py +67 -0
- {yirgacheffe-1.3.3 → yirgacheffe-1.3.4}/tests/test_group.py +4 -4
- {yirgacheffe-1.3.3 → yirgacheffe-1.3.4}/tests/test_h3layer.py +9 -7
- {yirgacheffe-1.3.3 → yirgacheffe-1.3.4}/tests/test_intersection.py +1 -1
- {yirgacheffe-1.3.3 → yirgacheffe-1.3.4}/tests/test_multiband.py +2 -2
- {yirgacheffe-1.3.3 → yirgacheffe-1.3.4}/tests/test_operators.py +2 -3
- {yirgacheffe-1.3.3 → yirgacheffe-1.3.4}/tests/test_optimisation.py +2 -2
- {yirgacheffe-1.3.3 → yirgacheffe-1.3.4}/tests/test_parallel_operators.py +3 -3
- {yirgacheffe-1.3.3 → yirgacheffe-1.3.4}/tests/test_pickle.py +3 -2
- {yirgacheffe-1.3.3 → yirgacheffe-1.3.4}/tests/test_raster.py +3 -3
- {yirgacheffe-1.3.3 → yirgacheffe-1.3.4}/tests/test_rescaling.py +1 -1
- {yirgacheffe-1.3.3 → yirgacheffe-1.3.4}/tests/test_save_with_window.py +1 -1
- {yirgacheffe-1.3.3 → yirgacheffe-1.3.4}/tests/test_sum_with_window.py +1 -1
- {yirgacheffe-1.3.3 → yirgacheffe-1.3.4}/tests/test_uniform_area_layer.py +1 -1
- {yirgacheffe-1.3.3 → yirgacheffe-1.3.4}/tests/test_union.py +1 -1
- {yirgacheffe-1.3.3 → yirgacheffe-1.3.4}/tests/test_vectors.py +14 -4
- {yirgacheffe-1.3.3 → yirgacheffe-1.3.4}/yirgacheffe/operators.py +22 -3
- {yirgacheffe-1.3.3 → yirgacheffe-1.3.4/yirgacheffe.egg-info}/PKG-INFO +1 -1
- {yirgacheffe-1.3.3 → yirgacheffe-1.3.4}/yirgacheffe.egg-info/SOURCES.txt +1 -0
- yirgacheffe-1.3.3/tests/test_area.py +0 -21
- yirgacheffe-1.3.3/tests/test_auto_windowing.py +0 -284
- yirgacheffe-1.3.3/tests/test_datatypes.py +0 -67
- {yirgacheffe-1.3.3 → yirgacheffe-1.3.4}/LICENSE +0 -0
- {yirgacheffe-1.3.3 → yirgacheffe-1.3.4}/MANIFEST.in +0 -0
- {yirgacheffe-1.3.3 → yirgacheffe-1.3.4}/README.md +0 -0
- {yirgacheffe-1.3.3 → yirgacheffe-1.3.4}/setup.cfg +0 -0
- {yirgacheffe-1.3.3 → yirgacheffe-1.3.4}/tests/test_base.py +0 -0
- {yirgacheffe-1.3.3 → yirgacheffe-1.3.4}/tests/test_rounding.py +0 -0
- {yirgacheffe-1.3.3 → yirgacheffe-1.3.4}/tests/test_window.py +0 -0
- {yirgacheffe-1.3.3 → yirgacheffe-1.3.4}/yirgacheffe/__init__.py +0 -0
- {yirgacheffe-1.3.3 → yirgacheffe-1.3.4}/yirgacheffe/backends/__init__.py +0 -0
- {yirgacheffe-1.3.3 → yirgacheffe-1.3.4}/yirgacheffe/backends/enumeration.py +0 -0
- {yirgacheffe-1.3.3 → yirgacheffe-1.3.4}/yirgacheffe/backends/mlx.py +0 -0
- {yirgacheffe-1.3.3 → yirgacheffe-1.3.4}/yirgacheffe/backends/numpy.py +0 -0
- {yirgacheffe-1.3.3 → yirgacheffe-1.3.4}/yirgacheffe/constants.py +0 -0
- {yirgacheffe-1.3.3 → yirgacheffe-1.3.4}/yirgacheffe/h3layer.py +0 -0
- {yirgacheffe-1.3.3 → yirgacheffe-1.3.4}/yirgacheffe/layers/__init__.py +0 -0
- {yirgacheffe-1.3.3 → yirgacheffe-1.3.4}/yirgacheffe/layers/area.py +0 -0
- {yirgacheffe-1.3.3 → yirgacheffe-1.3.4}/yirgacheffe/layers/base.py +0 -0
- {yirgacheffe-1.3.3 → yirgacheffe-1.3.4}/yirgacheffe/layers/constant.py +0 -0
- {yirgacheffe-1.3.3 → yirgacheffe-1.3.4}/yirgacheffe/layers/group.py +0 -0
- {yirgacheffe-1.3.3 → yirgacheffe-1.3.4}/yirgacheffe/layers/h3layer.py +0 -0
- {yirgacheffe-1.3.3 → yirgacheffe-1.3.4}/yirgacheffe/layers/rasters.py +0 -0
- {yirgacheffe-1.3.3 → yirgacheffe-1.3.4}/yirgacheffe/layers/rescaled.py +0 -0
- {yirgacheffe-1.3.3 → yirgacheffe-1.3.4}/yirgacheffe/layers/vectors.py +0 -0
- {yirgacheffe-1.3.3 → yirgacheffe-1.3.4}/yirgacheffe/rounding.py +0 -0
- {yirgacheffe-1.3.3 → yirgacheffe-1.3.4}/yirgacheffe/window.py +0 -0
- {yirgacheffe-1.3.3 → yirgacheffe-1.3.4}/yirgacheffe.egg-info/dependency_links.txt +0 -0
- {yirgacheffe-1.3.3 → yirgacheffe-1.3.4}/yirgacheffe.egg-info/entry_points.txt +0 -0
- {yirgacheffe-1.3.3 → yirgacheffe-1.3.4}/yirgacheffe.egg-info/requires.txt +0 -0
- {yirgacheffe-1.3.3 → yirgacheffe-1.3.4}/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.3.
|
|
9
|
+
version = "1.3.4"
|
|
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" }]
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
|
|
3
|
+
# I've no idea why pylint dislikes this particular import but accepts
|
|
4
|
+
# other entries in the module.
|
|
5
|
+
from yirgacheffe.window import Area # pylint: disable=E0401, E0611
|
|
6
|
+
|
|
7
|
+
@pytest.mark.parametrize(
|
|
8
|
+
"lhs,rhs,is_equal,overlaps",
|
|
9
|
+
[
|
|
10
|
+
# Obvious equality
|
|
11
|
+
(Area(-10.0, 10.0, 10.0, -10.0), Area(-10.0, 10.0, 10.0, -10.0), True, True),
|
|
12
|
+
(Area(-9.0, 9.0, 9.0, -9.0), Area(-10.0, 10.0, 10.0, -10.0), False, True), # subset
|
|
13
|
+
(Area(-9.0, 9.0, -1.0, 1.0), Area(1.0, -1.0, 9.0, -9.0), False, False),
|
|
14
|
+
(Area(-10.0, 10.0, 1.0, -10.0), Area(-1.0, 10.0, 10.0, -10.0), False, True),
|
|
15
|
+
]
|
|
16
|
+
)
|
|
17
|
+
def test_area_operators(lhs: Area, rhs: Area, is_equal: bool, overlaps: bool) -> None:
|
|
18
|
+
assert (lhs == rhs) == is_equal
|
|
19
|
+
assert (lhs != rhs) == (not is_equal)
|
|
20
|
+
assert (lhs.overlaps(rhs)) == overlaps
|
|
21
|
+
assert (rhs.overlaps(lhs)) == overlaps
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import tempfile
|
|
3
|
+
|
|
4
|
+
import numpy as np
|
|
5
|
+
import pytest
|
|
6
|
+
|
|
7
|
+
import yirgacheffe
|
|
8
|
+
from tests.helpers import gdal_dataset_with_data, make_vectors_with_mutlile_ids
|
|
9
|
+
from yirgacheffe.layers import ConstantLayer, RasterLayer, VectorLayer
|
|
10
|
+
from yirgacheffe.window import Area
|
|
11
|
+
|
|
12
|
+
def test_add_windows() -> None:
|
|
13
|
+
data1 = np.array([[1, 2], [3, 4]])
|
|
14
|
+
data2 = np.array([[10, 20, 30, 40], [50, 60, 70, 80], [90, 100, 110, 120], [130, 140, 150, 160]])
|
|
15
|
+
|
|
16
|
+
layer1 = RasterLayer(gdal_dataset_with_data((0.0, 0.0), 0.02, data1))
|
|
17
|
+
layer2 = RasterLayer(gdal_dataset_with_data((0.0, 0.0), 0.02, data2))
|
|
18
|
+
|
|
19
|
+
assert layer1.area != layer2.area
|
|
20
|
+
assert layer1.window != layer2.window
|
|
21
|
+
|
|
22
|
+
calc = layer1 + layer2
|
|
23
|
+
|
|
24
|
+
assert calc.area == layer2.area
|
|
25
|
+
assert calc.window == layer2.window
|
|
26
|
+
|
|
27
|
+
result = RasterLayer.empty_raster_layer_like(calc)
|
|
28
|
+
calc.save(result)
|
|
29
|
+
|
|
30
|
+
expected = np.array([[11, 22, 30, 40], [53, 64, 70, 80], [90, 100, 110, 120], [130, 140, 150, 160]])
|
|
31
|
+
actual = result.read_array(0, 0, 4, 4)
|
|
32
|
+
assert (expected == actual).all()
|
|
33
|
+
|
|
34
|
+
def test_multiply_windows() -> None:
|
|
35
|
+
data1 = np.array([[1, 2], [3, 4]])
|
|
36
|
+
data2 = np.array([[10, 20, 30, 40], [50, 60, 70, 80], [90, 100, 110, 120], [130, 140, 150, 160]])
|
|
37
|
+
|
|
38
|
+
layer1 = RasterLayer(gdal_dataset_with_data((0.0, 0.0), 0.02, data1))
|
|
39
|
+
layer2 = RasterLayer(gdal_dataset_with_data((0.0, 0.0), 0.02, data2))
|
|
40
|
+
|
|
41
|
+
assert layer1.area != layer2.area
|
|
42
|
+
assert layer1.window != layer2.window
|
|
43
|
+
|
|
44
|
+
calc = layer1 * layer2
|
|
45
|
+
|
|
46
|
+
assert calc.area == layer1.area
|
|
47
|
+
assert calc.window == layer1.window
|
|
48
|
+
|
|
49
|
+
result = RasterLayer.empty_raster_layer_like(calc)
|
|
50
|
+
calc.save(result)
|
|
51
|
+
|
|
52
|
+
expected = np.array([[10, 40], [150, 240]])
|
|
53
|
+
actual = result.read_array(0, 0, 2, 2)
|
|
54
|
+
assert (expected == actual).all()
|
|
55
|
+
|
|
56
|
+
def test_add_windows_offset() -> None:
|
|
57
|
+
data1 = np.array([[1, 2], [3, 4]])
|
|
58
|
+
data2 = np.array([[10, 20, 30, 40], [50, 60, 70, 80], [90, 100, 110, 120], [130, 140, 150, 160]])
|
|
59
|
+
|
|
60
|
+
layer1 = RasterLayer(gdal_dataset_with_data((-0.02, 0.02), 0.02, data1))
|
|
61
|
+
layer2 = RasterLayer(gdal_dataset_with_data((-0.04, 0.04), 0.02, data2))
|
|
62
|
+
|
|
63
|
+
assert layer1.area != layer2.area
|
|
64
|
+
assert layer1.window != layer2.window
|
|
65
|
+
|
|
66
|
+
calc = layer1 + layer2
|
|
67
|
+
|
|
68
|
+
assert calc.area == layer2.area
|
|
69
|
+
|
|
70
|
+
result = RasterLayer.empty_raster_layer_like(calc)
|
|
71
|
+
calc.save(result)
|
|
72
|
+
|
|
73
|
+
expected = np.array([[10, 20, 30, 40], [50, 61, 72, 80], [90, 103, 114, 120], [130, 140, 150, 160]])
|
|
74
|
+
actual = result.read_array(0, 0, 4, 4)
|
|
75
|
+
assert (expected == actual).all()
|
|
76
|
+
|
|
77
|
+
def test_multiply_windows_offset() -> None:
|
|
78
|
+
data1 = np.array([[1, 2], [3, 4]])
|
|
79
|
+
data2 = np.array([[10, 20, 30, 40], [50, 60, 70, 80], [90, 100, 110, 120], [130, 140, 150, 160]])
|
|
80
|
+
|
|
81
|
+
layer1 = RasterLayer(gdal_dataset_with_data((-0.02, 0.02), 0.02, data1))
|
|
82
|
+
layer2 = RasterLayer(gdal_dataset_with_data((-0.04, 0.04), 0.02, data2))
|
|
83
|
+
|
|
84
|
+
assert layer1.area != layer2.area
|
|
85
|
+
assert layer1.window != layer2.window
|
|
86
|
+
|
|
87
|
+
calc = layer1 * layer2
|
|
88
|
+
|
|
89
|
+
assert calc.area == layer1.area
|
|
90
|
+
|
|
91
|
+
result = RasterLayer.empty_raster_layer_like(calc)
|
|
92
|
+
calc.save(result)
|
|
93
|
+
|
|
94
|
+
expected = np.array([[60, 140], [300, 440]])
|
|
95
|
+
actual = result.read_array(0, 0, 2, 2)
|
|
96
|
+
assert (expected == actual).all()
|
|
97
|
+
|
|
98
|
+
def test_add_windows_sum() -> None:
|
|
99
|
+
data1 = np.array([[1, 2], [3, 4]])
|
|
100
|
+
data2 = np.array([[10, 20, 30, 40], [50, 60, 70, 80], [90, 100, 110, 120], [130, 140, 150, 160]])
|
|
101
|
+
|
|
102
|
+
layer1 = RasterLayer(gdal_dataset_with_data((-0.02, 0.02), 0.02, data1))
|
|
103
|
+
layer2 = RasterLayer(gdal_dataset_with_data((-0.04, 0.04), 0.02, data2))
|
|
104
|
+
|
|
105
|
+
calc = layer1 + layer2
|
|
106
|
+
total = calc.sum()
|
|
107
|
+
|
|
108
|
+
expected = np.array([[10, 20, 30, 40], [50, 61, 72, 80], [90, 103, 114, 120], [130, 140, 150, 160]])
|
|
109
|
+
assert total == np.sum(expected)
|
|
110
|
+
|
|
111
|
+
def test_multiply_windows_sum() -> None:
|
|
112
|
+
data1 = np.array([[1, 2], [3, 4]])
|
|
113
|
+
data2 = np.array([[10, 20, 30, 40], [50, 60, 70, 80], [90, 100, 110, 120], [130, 140, 150, 160]])
|
|
114
|
+
|
|
115
|
+
layer1 = RasterLayer(gdal_dataset_with_data((-0.02, 0.02), 0.02, data1))
|
|
116
|
+
layer2 = RasterLayer(gdal_dataset_with_data((-0.04, 0.04), 0.02, data2))
|
|
117
|
+
|
|
118
|
+
calc = layer1 * layer2
|
|
119
|
+
total = calc.sum()
|
|
120
|
+
|
|
121
|
+
expected = np.array([[60, 140], [300, 440]])
|
|
122
|
+
assert total == np.sum(expected)
|
|
123
|
+
|
|
124
|
+
def test_constant_layer_result_rhs_add() -> None:
|
|
125
|
+
data1 = np.array([[1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0]])
|
|
126
|
+
layer1 = RasterLayer(gdal_dataset_with_data((0.0, 0.0), 0.02, data1))
|
|
127
|
+
const_layer = ConstantLayer(1.0)
|
|
128
|
+
|
|
129
|
+
calc = layer1 + const_layer
|
|
130
|
+
|
|
131
|
+
assert calc.area == layer1.area
|
|
132
|
+
|
|
133
|
+
result = RasterLayer.empty_raster_layer_like(calc)
|
|
134
|
+
calc.save(result)
|
|
135
|
+
actual = result.read_array(0, 0, 4, 2)
|
|
136
|
+
|
|
137
|
+
expected = 1.0 + data1
|
|
138
|
+
|
|
139
|
+
assert (expected == actual).all()
|
|
140
|
+
|
|
141
|
+
def test_constant_layer_result_lhs_add() -> None:
|
|
142
|
+
data1 = np.array([[1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0]])
|
|
143
|
+
layer1 = RasterLayer(gdal_dataset_with_data((0.0, 0.0), 0.02, data1))
|
|
144
|
+
const_layer = ConstantLayer(1.0)
|
|
145
|
+
result = RasterLayer.empty_raster_layer_like(layer1)
|
|
146
|
+
|
|
147
|
+
intersection = RasterLayer.find_intersection([layer1, const_layer])
|
|
148
|
+
const_layer.set_window_for_intersection(intersection)
|
|
149
|
+
layer1.set_window_for_intersection(intersection)
|
|
150
|
+
|
|
151
|
+
calc = const_layer + layer1
|
|
152
|
+
|
|
153
|
+
assert calc.area == layer1.area
|
|
154
|
+
|
|
155
|
+
result = RasterLayer.empty_raster_layer_like(calc)
|
|
156
|
+
calc.save(result)
|
|
157
|
+
actual = result.read_array(0, 0, 4, 2)
|
|
158
|
+
|
|
159
|
+
expected = 1.0 + data1
|
|
160
|
+
|
|
161
|
+
assert (expected == actual).all()
|
|
162
|
+
|
|
163
|
+
def test_constant_layer_result_rhs_multiply() -> None:
|
|
164
|
+
data1 = np.array([[1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0]])
|
|
165
|
+
layer1 = RasterLayer(gdal_dataset_with_data((0.0, 0.0), 0.02, data1))
|
|
166
|
+
const_layer = ConstantLayer(2.0)
|
|
167
|
+
|
|
168
|
+
calc = layer1 * const_layer
|
|
169
|
+
|
|
170
|
+
assert calc.area == layer1.area
|
|
171
|
+
|
|
172
|
+
result = RasterLayer.empty_raster_layer_like(calc)
|
|
173
|
+
calc.save(result)
|
|
174
|
+
actual = result.read_array(0, 0, 4, 2)
|
|
175
|
+
|
|
176
|
+
expected = data1 * 2.0
|
|
177
|
+
|
|
178
|
+
assert (expected == actual).all()
|
|
179
|
+
|
|
180
|
+
def test_constant_layer_result_lhs_multiply() -> None:
|
|
181
|
+
data1 = np.array([[1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0]])
|
|
182
|
+
layer1 = RasterLayer(gdal_dataset_with_data((0.0, 0.0), 0.02, data1))
|
|
183
|
+
const_layer = ConstantLayer(2.0)
|
|
184
|
+
result = RasterLayer.empty_raster_layer_like(layer1)
|
|
185
|
+
|
|
186
|
+
intersection = RasterLayer.find_intersection([layer1, const_layer])
|
|
187
|
+
const_layer.set_window_for_intersection(intersection)
|
|
188
|
+
layer1.set_window_for_intersection(intersection)
|
|
189
|
+
|
|
190
|
+
calc = const_layer * layer1
|
|
191
|
+
|
|
192
|
+
assert calc.area == layer1.area
|
|
193
|
+
|
|
194
|
+
result = RasterLayer.empty_raster_layer_like(calc)
|
|
195
|
+
calc.save(result)
|
|
196
|
+
actual = result.read_array(0, 0, 4, 2)
|
|
197
|
+
|
|
198
|
+
expected = 2.0 * data1
|
|
199
|
+
|
|
200
|
+
assert (expected == actual).all()
|
|
201
|
+
|
|
202
|
+
def test_vector_layers_add() -> None:
|
|
203
|
+
data1 = np.array([[1, 2], [3, 4]])
|
|
204
|
+
layer1 = RasterLayer(gdal_dataset_with_data((0.0, 0.0), 1.0, data1))
|
|
205
|
+
|
|
206
|
+
with tempfile.TemporaryDirectory() as tempdir:
|
|
207
|
+
path = os.path.join(tempdir, "test.gpkg")
|
|
208
|
+
areas = {
|
|
209
|
+
(Area(-10.0, 10.0, 0.0, 0.0), 42),
|
|
210
|
+
(Area(0.0, 0.0, 10, -10), 43)
|
|
211
|
+
}
|
|
212
|
+
make_vectors_with_mutlile_ids(areas, path)
|
|
213
|
+
|
|
214
|
+
burn_value = 2
|
|
215
|
+
layer2 = VectorLayer.layer_from_file(path, None, layer1.pixel_scale, layer1.projection, burn_value=burn_value)
|
|
216
|
+
layer2_total = layer2.sum()
|
|
217
|
+
assert layer2_total == ((layer2.window.xsize * layer2.window.ysize) / 2) * burn_value
|
|
218
|
+
|
|
219
|
+
calc = layer1 + layer2
|
|
220
|
+
|
|
221
|
+
assert calc.area == layer2.area
|
|
222
|
+
|
|
223
|
+
total = calc.sum()
|
|
224
|
+
assert total == layer2_total + np.sum(data1)
|
|
225
|
+
|
|
226
|
+
def test_vector_layers_multiply() -> None:
|
|
227
|
+
data1 = np.array([[1, 2], [3, 4]])
|
|
228
|
+
layer1 = RasterLayer(gdal_dataset_with_data((-1.0, 1.0), 1.0, data1))
|
|
229
|
+
|
|
230
|
+
with tempfile.TemporaryDirectory() as tempdir:
|
|
231
|
+
path = os.path.join(tempdir, "test.gpkg")
|
|
232
|
+
areas = {
|
|
233
|
+
(Area(-10.0, 10.0, 0.0, 0.0), 42),
|
|
234
|
+
(Area(0.0, 0.0, 10, -10), 43)
|
|
235
|
+
}
|
|
236
|
+
make_vectors_with_mutlile_ids(areas, path)
|
|
237
|
+
|
|
238
|
+
burn_value = 2
|
|
239
|
+
layer2 = VectorLayer.layer_from_file(path, None, layer1.pixel_scale, layer1.projection, burn_value=burn_value)
|
|
240
|
+
layer2_total = layer2.sum()
|
|
241
|
+
assert layer2_total == ((layer2.window.xsize * layer2.window.ysize) / 2) * burn_value
|
|
242
|
+
|
|
243
|
+
calc = layer1 * layer2
|
|
244
|
+
|
|
245
|
+
assert calc.area == layer1.area
|
|
246
|
+
|
|
247
|
+
result = RasterLayer.empty_raster_layer_like(calc)
|
|
248
|
+
calc.save(result)
|
|
249
|
+
actual = result.read_array(0, 0, 2, 2)
|
|
250
|
+
|
|
251
|
+
expected = np.array([[2, 0], [0, 8]])
|
|
252
|
+
assert (expected == actual).all()
|
|
253
|
+
|
|
254
|
+
@pytest.mark.skipif(yirgacheffe.backends.BACKEND != "NUMPY", reason="Only applies for numpy")
|
|
255
|
+
def test_parallel_save_windows() -> None:
|
|
256
|
+
data1 = np.array([[1, 2], [3, 4]])
|
|
257
|
+
data2 = np.array([[10, 20, 30, 40], [50, 60, 70, 80], [90, 100, 110, 120], [130, 140, 150, 160]])
|
|
258
|
+
|
|
259
|
+
with tempfile.TemporaryDirectory() as tempdir:
|
|
260
|
+
layer1_filename = os.path.join(tempdir, "layer1.tif")
|
|
261
|
+
layer1_dataset = gdal_dataset_with_data((0.0, 0.0), 0.02, data1, filename=layer1_filename)
|
|
262
|
+
layer1_dataset.Close()
|
|
263
|
+
|
|
264
|
+
layer2_filename = os.path.join(tempdir, "layer2.tif")
|
|
265
|
+
layer2_dataset = gdal_dataset_with_data((0.0, 0.0), 0.02, data2, filename=layer2_filename)
|
|
266
|
+
layer2_dataset.Close()
|
|
267
|
+
|
|
268
|
+
layer1 = RasterLayer.layer_from_file(layer1_filename)
|
|
269
|
+
layer2 = RasterLayer.layer_from_file(layer2_filename)
|
|
270
|
+
|
|
271
|
+
assert layer1.area != layer2.area
|
|
272
|
+
assert layer1.window != layer2.window
|
|
273
|
+
|
|
274
|
+
calc = layer1 + layer2
|
|
275
|
+
|
|
276
|
+
assert calc.area == layer2.area
|
|
277
|
+
assert calc.window == layer2.window
|
|
278
|
+
|
|
279
|
+
result = RasterLayer.empty_raster_layer_like(calc)
|
|
280
|
+
calc.parallel_save(result)
|
|
281
|
+
|
|
282
|
+
expected = np.array([[11, 22, 30, 40], [53, 64, 70, 80], [90, 100, 110, 120], [130, 140, 150, 160]])
|
|
283
|
+
actual = result.read_array(0, 0, 4, 4)
|
|
284
|
+
assert (expected == actual).all()
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
|
|
2
|
+
import numpy as np
|
|
3
|
+
import yirgacheffe
|
|
4
|
+
from yirgacheffe.layers import RasterLayer, ConstantLayer
|
|
5
|
+
from yirgacheffe.operators import DataType
|
|
6
|
+
from yirgacheffe.window import Area, PixelScale
|
|
7
|
+
|
|
8
|
+
def test_constant_save() -> None:
|
|
9
|
+
area = Area(left=-1.0, right=1.0, top=1.0, bottom=-1.0)
|
|
10
|
+
scale = PixelScale(0.1, -0.1)
|
|
11
|
+
with RasterLayer.empty_raster_layer(area, scale, DataType.Float32) as result:
|
|
12
|
+
with ConstantLayer(42.0) as c:
|
|
13
|
+
c.save(result)
|
|
14
|
+
|
|
15
|
+
expected = np.full((20, 20), 42.0)
|
|
16
|
+
actual = result.read_array(0, 0, 20, 20)
|
|
17
|
+
|
|
18
|
+
assert (expected == actual).all()
|
|
19
|
+
|
|
20
|
+
def test_constant_parallel_save(monkeypatch) -> None:
|
|
21
|
+
area = Area(left=-1.0, right=1.0, top=1.0, bottom=-1.0)
|
|
22
|
+
scale = PixelScale(0.1, -0.1)
|
|
23
|
+
with RasterLayer.empty_raster_layer(area, scale, DataType.Float32) as result:
|
|
24
|
+
with ConstantLayer(42.0) as c:
|
|
25
|
+
with monkeypatch.context() as m:
|
|
26
|
+
m.setattr(yirgacheffe.constants, "YSTEP", 1)
|
|
27
|
+
c.parallel_save(result)
|
|
28
|
+
|
|
29
|
+
expected = np.full((20, 20), 42.0)
|
|
30
|
+
actual = result.read_array(0, 0, 20, 20)
|
|
31
|
+
|
|
32
|
+
assert (expected == actual).all()
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
|
|
2
|
+
import numpy as np
|
|
3
|
+
import pytest
|
|
4
|
+
from osgeo import gdal
|
|
5
|
+
|
|
6
|
+
from yirgacheffe.operators import DataType
|
|
7
|
+
from yirgacheffe.backends import backend, BACKEND
|
|
8
|
+
from yirgacheffe.layers import RasterLayer
|
|
9
|
+
|
|
10
|
+
from tests.helpers import gdal_dataset_with_data
|
|
11
|
+
|
|
12
|
+
@pytest.mark.parametrize("gtype", [
|
|
13
|
+
gdal.GDT_Int8,
|
|
14
|
+
gdal.GDT_Int16,
|
|
15
|
+
gdal.GDT_Int32,
|
|
16
|
+
gdal.GDT_Int64,
|
|
17
|
+
gdal.GDT_Byte,
|
|
18
|
+
gdal.GDT_UInt16,
|
|
19
|
+
gdal.GDT_UInt32,
|
|
20
|
+
gdal.GDT_UInt64,
|
|
21
|
+
gdal.GDT_Float32,
|
|
22
|
+
])
|
|
23
|
+
def test_round_trip(gtype) -> None:
|
|
24
|
+
ytype = DataType.of_gdal(gtype)
|
|
25
|
+
backend_type = backend.dtype_to_backed(ytype)
|
|
26
|
+
assert backend.backend_to_dtype(backend_type) == ytype
|
|
27
|
+
|
|
28
|
+
@pytest.mark.parametrize("ytype", [
|
|
29
|
+
DataType.Int8,
|
|
30
|
+
DataType.Int16,
|
|
31
|
+
DataType.Int32,
|
|
32
|
+
DataType.Int64,
|
|
33
|
+
DataType.UInt8,
|
|
34
|
+
DataType.UInt16,
|
|
35
|
+
DataType.UInt32,
|
|
36
|
+
DataType.UInt64,
|
|
37
|
+
DataType.Float32,
|
|
38
|
+
DataType.Float64,
|
|
39
|
+
])
|
|
40
|
+
def test_round_trip_from_gdal(ytype) -> None:
|
|
41
|
+
gtype = ytype.to_gdal()
|
|
42
|
+
assert DataType.of_gdal(gtype) == ytype
|
|
43
|
+
|
|
44
|
+
def test_round_trip_float64() -> None:
|
|
45
|
+
backend_type = backend.dtype_to_backed(DataType.Float64)
|
|
46
|
+
ytype = backend.backend_to_dtype(backend_type)
|
|
47
|
+
print(BACKEND, "sad")
|
|
48
|
+
match BACKEND:
|
|
49
|
+
case "NUMPY":
|
|
50
|
+
assert ytype == DataType.Float64
|
|
51
|
+
case "MLX":
|
|
52
|
+
assert ytype == DataType.Float32
|
|
53
|
+
|
|
54
|
+
def test_float_to_int() -> None:
|
|
55
|
+
data1 = np.array([[1.0, 2.0, 3.0, 4.0], [5.5, 6.5, 7.5, 8.5]])
|
|
56
|
+
|
|
57
|
+
layer1 = RasterLayer(gdal_dataset_with_data((0.0, 0.0), 0.02, data1))
|
|
58
|
+
# Note the float 32 here is to rule out that writing the result to the
|
|
59
|
+
# new dataset was what caused the truncation
|
|
60
|
+
result = RasterLayer.empty_raster_layer_like(layer1, datatype=DataType.Float32)
|
|
61
|
+
|
|
62
|
+
comp = layer1.astype(DataType.UInt8)
|
|
63
|
+
comp.save(result)
|
|
64
|
+
|
|
65
|
+
expected = backend.promote(np.array([[1, 2, 3, 4], [5, 6, 7, 8]]))
|
|
66
|
+
actual = backend.demote_array(result.read_array(0, 0, 4, 2))
|
|
67
|
+
assert (expected == actual).all()
|
|
@@ -5,7 +5,7 @@ import tempfile
|
|
|
5
5
|
import numpy as np
|
|
6
6
|
import pytest
|
|
7
7
|
|
|
8
|
-
from helpers import gdal_dataset_of_region, gdal_dataset_with_data, make_vectors_with_id, generate_child_tile
|
|
8
|
+
from tests.helpers import gdal_dataset_of_region, gdal_dataset_with_data, make_vectors_with_id, generate_child_tile
|
|
9
9
|
from yirgacheffe import WGS_84_PROJECTION
|
|
10
10
|
from yirgacheffe.layers import GroupLayer, RasterLayer, TiledGroupLayer, VectorLayer
|
|
11
11
|
from yirgacheffe.window import Area, PixelScale, Window
|
|
@@ -35,7 +35,7 @@ def test_valid_file_list():
|
|
|
35
35
|
assert group.area == area
|
|
36
36
|
assert group.window == Window(0, 0, 100, 100)
|
|
37
37
|
|
|
38
|
-
def
|
|
38
|
+
def test_valid_file_list_from_dir():
|
|
39
39
|
with tempfile.TemporaryDirectory() as tempdir:
|
|
40
40
|
path = os.path.join(tempdir, "test.tif")
|
|
41
41
|
area = Area(-10, 10, 10, -10)
|
|
@@ -221,8 +221,8 @@ def test_with_window_adjust(klass):
|
|
|
221
221
|
|
|
222
222
|
# Test before we apply a window
|
|
223
223
|
row = group.read_array(0, 0, 100, 1)[0]
|
|
224
|
-
for idx in
|
|
225
|
-
assert
|
|
224
|
+
for idx, val in enumerate(row):
|
|
225
|
+
assert val == math.ceil((idx + 1) / 10.0)
|
|
226
226
|
|
|
227
227
|
# Test also for manual offsets that we get expected result
|
|
228
228
|
for idx in range(0, 10):
|
|
@@ -6,9 +6,11 @@ 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.operators import ShaderStyleOperation
|
|
10
9
|
from yirgacheffe.backends import backend
|
|
11
10
|
|
|
11
|
+
# work around of pylint
|
|
12
|
+
demote_array = backend.demote_array
|
|
13
|
+
|
|
12
14
|
|
|
13
15
|
@pytest.mark.parametrize(
|
|
14
16
|
"cell_id,is_valid,expected_zoom",
|
|
@@ -135,10 +137,10 @@ def test_h3_layer_clipped(lat: float, lng: float) -> None:
|
|
|
135
137
|
|
|
136
138
|
# whilst we're here, check that we do have an filled border (i.e., does window for
|
|
137
139
|
# intersection do the right thing)
|
|
138
|
-
assert np.sum(
|
|
139
|
-
assert np.sum(
|
|
140
|
-
assert np.sum(
|
|
141
|
-
assert np.sum(
|
|
140
|
+
assert np.sum(demote_array(h3_layer.read_array(0, 0, h3_layer.window.xsize, 5))) > 0.0
|
|
141
|
+
assert np.sum(demote_array(h3_layer.read_array(0, h3_layer.window.ysize - 5, h3_layer.window.xsize, 5))) > 0.0
|
|
142
|
+
assert np.sum(demote_array(h3_layer.read_array(0, 0, 5, h3_layer.window.ysize))) > 0.0
|
|
143
|
+
assert np.sum(demote_array(h3_layer.read_array(h3_layer.window.xsize - 5, 0, 5, h3_layer.window.ysize))) > 0.0
|
|
142
144
|
|
|
143
145
|
@pytest.mark.parametrize(
|
|
144
146
|
"lat,lng",
|
|
@@ -189,8 +191,8 @@ def test_h3_layer_wrapped_on_projection(lat: float, lng: float) -> None:
|
|
|
189
191
|
assert expanded_area == area
|
|
190
192
|
|
|
191
193
|
# whilst we're here, check that we do have an empty border (i.e., does window for union do the right thing)
|
|
192
|
-
assert np.sum(
|
|
193
|
-
assert np.sum(
|
|
194
|
+
assert np.sum(demote_array(h3_layer.read_array(0, 0, h3_layer.window.xsize, 2))) == 0.0
|
|
195
|
+
assert np.sum(demote_array(h3_layer.read_array(0, h3_layer.window.ysize - 2, h3_layer.window.xsize, 2))) == 0.0
|
|
194
196
|
|
|
195
197
|
def test_h3_layer_overlapped():
|
|
196
198
|
# This is based on a regression, where somehow I made tiles not tesselate properly
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import pytest
|
|
2
2
|
from osgeo import gdal
|
|
3
3
|
|
|
4
|
-
from helpers import gdal_dataset_of_region, gdal_empty_dataset_of_region
|
|
4
|
+
from tests.helpers import gdal_dataset_of_region, gdal_empty_dataset_of_region
|
|
5
5
|
from yirgacheffe.window import Area, PixelScale, Window
|
|
6
6
|
from yirgacheffe.layers import RasterLayer, ConstantLayer
|
|
7
7
|
from yirgacheffe.h3layer import H3CellLayer
|
|
@@ -4,7 +4,7 @@ import tempfile
|
|
|
4
4
|
import numpy as np
|
|
5
5
|
from osgeo import gdal
|
|
6
6
|
|
|
7
|
-
from helpers import gdal_dataset_with_data
|
|
7
|
+
from tests.helpers import gdal_dataset_with_data
|
|
8
8
|
from yirgacheffe.layers import RasterLayer
|
|
9
9
|
from yirgacheffe.window import Area, PixelScale
|
|
10
10
|
|
|
@@ -52,7 +52,7 @@ def test_stack_tifs_with_area_match() -> None:
|
|
|
52
52
|
for layer in source_layers:
|
|
53
53
|
layer.set_window_for_intersection(intersection)
|
|
54
54
|
|
|
55
|
-
|
|
55
|
+
layer = source_layers[-1]
|
|
56
56
|
assert layer.window.xsize == 100 - (bands - 1)
|
|
57
57
|
assert layer.window.ysize == 100 - (bands - 1)
|
|
58
58
|
|
|
@@ -5,13 +5,12 @@ import tempfile
|
|
|
5
5
|
import numpy as np
|
|
6
6
|
import pytest
|
|
7
7
|
import torch
|
|
8
|
-
from osgeo import gdal
|
|
9
8
|
|
|
10
|
-
from helpers import gdal_dataset_with_data
|
|
11
9
|
import yirgacheffe
|
|
12
10
|
from yirgacheffe.layers import RasterLayer, ConstantLayer
|
|
13
11
|
from yirgacheffe.operators import LayerOperation, DataType
|
|
14
12
|
from yirgacheffe.backends import backend
|
|
13
|
+
from tests.helpers import gdal_dataset_with_data
|
|
15
14
|
|
|
16
15
|
def test_add_byte_layers() -> None:
|
|
17
16
|
data1 = np.array([[1, 2, 3, 4], [5, 6, 7, 8]]).astype(np.uint8)
|
|
@@ -71,7 +70,7 @@ def test_add_byte_layers_with_callback(skip, expected_steps) -> None:
|
|
|
71
70
|
|
|
72
71
|
comp = layer1 + layer2
|
|
73
72
|
comp.ystep = skip
|
|
74
|
-
comp.save(result, callback=
|
|
73
|
+
comp.save(result, callback=callback_possitions.append)
|
|
75
74
|
|
|
76
75
|
expected = data1 + data2
|
|
77
76
|
actual = result.read_array(0, 0, 4, 2)
|
|
@@ -5,7 +5,7 @@ import pytest
|
|
|
5
5
|
|
|
6
6
|
from yirgacheffe import WGS_84_PROJECTION
|
|
7
7
|
from yirgacheffe.h3layer import H3CellLayer
|
|
8
|
-
from yirgacheffe.layers import PixelScale,
|
|
8
|
+
from yirgacheffe.layers import PixelScale, RasterLayer
|
|
9
9
|
from yirgacheffe.window import Area
|
|
10
10
|
import yirgacheffe.operators as yo
|
|
11
11
|
|
|
@@ -14,7 +14,7 @@ class NaiveH3CellLayer(H3CellLayer):
|
|
|
14
14
|
so the H3CellLayer has a bunch of tricks to try reduce the work done. This is a naive
|
|
15
15
|
version that checks for every cell."""
|
|
16
16
|
|
|
17
|
-
def read_array(self, xoffset, yoffset, xsize, ysize):
|
|
17
|
+
def read_array(self, xoffset, yoffset, xsize, ysize): # pylint: disable=W0237
|
|
18
18
|
res = np.zeros((ysize, xsize), dtype=float)
|
|
19
19
|
start_x = self._active_area.left + (xoffset * self._pixel_scale.xstep)
|
|
20
20
|
start_y = self._active_area.top + (yoffset * self._pixel_scale.ystep)
|
|
@@ -6,8 +6,8 @@ import pytest
|
|
|
6
6
|
import torch
|
|
7
7
|
|
|
8
8
|
import yirgacheffe
|
|
9
|
-
from helpers import gdal_dataset_with_data
|
|
10
|
-
from yirgacheffe.layers import RasterLayer
|
|
9
|
+
from tests.helpers import gdal_dataset_with_data
|
|
10
|
+
from yirgacheffe.layers import RasterLayer
|
|
11
11
|
from yirgacheffe.operators import LayerOperation
|
|
12
12
|
|
|
13
13
|
# These tests are marked skip for MLX, because there seems to be a problem with
|
|
@@ -153,7 +153,7 @@ def test_parallel_with_different_skip(monkeypatch, skip, expected_steps) -> None
|
|
|
153
153
|
|
|
154
154
|
comp = layer1 + layer2
|
|
155
155
|
comp.ystep = skip
|
|
156
|
-
comp.parallel_save(result, callback=
|
|
156
|
+
comp.parallel_save(result, callback=callback_possitions.append)
|
|
157
157
|
|
|
158
158
|
expected = data1 + data2
|
|
159
159
|
actual = result.read_array(0, 0, 4, 4)
|
|
@@ -7,9 +7,10 @@ import tempfile
|
|
|
7
7
|
import numpy as np
|
|
8
8
|
import pytest
|
|
9
9
|
|
|
10
|
-
from helpers import gdal_dataset_of_region, make_vectors_with_id
|
|
10
|
+
from tests.helpers import gdal_dataset_of_region, make_vectors_with_id
|
|
11
11
|
from yirgacheffe.window import Area, PixelScale, Window
|
|
12
|
-
from yirgacheffe.layers import ConstantLayer, GroupLayer, RasterLayer, RescaledRasterLayer,
|
|
12
|
+
from yirgacheffe.layers import ConstantLayer, GroupLayer, RasterLayer, RescaledRasterLayer, \
|
|
13
|
+
UniformAreaLayer, VectorLayer
|
|
13
14
|
from yirgacheffe import WGS_84_PROJECTION
|
|
14
15
|
from yirgacheffe.backends import backend
|
|
15
16
|
|
|
@@ -5,7 +5,7 @@ import numpy as np
|
|
|
5
5
|
import pytest
|
|
6
6
|
from osgeo import gdal
|
|
7
7
|
|
|
8
|
-
from 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
|
|
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
|
|
@@ -39,7 +39,7 @@ def test_make_basic_layer() -> None:
|
|
|
39
39
|
assert close_called
|
|
40
40
|
|
|
41
41
|
def test_make_basic_layer_old_name() -> None:
|
|
42
|
-
from yirgacheffe.layers import Layer
|
|
42
|
+
from yirgacheffe.layers import Layer # pylint: disable=C0415
|
|
43
43
|
|
|
44
44
|
area = Area(-10, 10, 10, -10)
|
|
45
45
|
with Layer(gdal_dataset_of_region(area, 0.02)) as layer:
|
|
@@ -104,7 +104,7 @@ def test_empty_layer_from_raster():
|
|
|
104
104
|
assert empty.window == source.window
|
|
105
105
|
assert empty.datatype == source.datatype
|
|
106
106
|
assert empty.geo_transform == source.geo_transform
|
|
107
|
-
assert empty._dataset.GetRasterBand(1).GetNoDataValue()
|
|
107
|
+
assert empty._dataset.GetRasterBand(1).GetNoDataValue() is None
|
|
108
108
|
|
|
109
109
|
@pytest.mark.parametrize("nodata", [0, 0.0, 2, 2.0])
|
|
110
110
|
def test_empty_layer_from_raster_with_no_data_value(nodata):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import numpy as np
|
|
2
2
|
|
|
3
|
-
from helpers import gdal_dataset_of_region, gdal_dataset_with_data
|
|
3
|
+
from tests.helpers import gdal_dataset_of_region, gdal_dataset_with_data
|
|
4
4
|
from yirgacheffe.layers import RasterLayer, RescaledRasterLayer
|
|
5
5
|
from yirgacheffe.window import Area, PixelScale, Window
|
|
6
6
|
|
|
@@ -2,9 +2,8 @@ import os
|
|
|
2
2
|
import tempfile
|
|
3
3
|
|
|
4
4
|
import pytest
|
|
5
|
-
from osgeo import gdal
|
|
6
5
|
|
|
7
|
-
from helpers import make_vectors_with_mutlile_ids, make_vectors_with_id, make_vectors_with_empty_feature
|
|
6
|
+
from tests.helpers import make_vectors_with_mutlile_ids, make_vectors_with_id, make_vectors_with_empty_feature
|
|
8
7
|
from yirgacheffe import WGS_84_PROJECTION
|
|
9
8
|
from yirgacheffe.layers import RasterLayer, RasteredVectorLayer, VectorLayer, VectorRangeLayer, DynamicVectorRangeLayer
|
|
10
9
|
from yirgacheffe.window import Area, PixelScale, Window
|
|
@@ -111,7 +110,12 @@ def test_empty_layer_from_vector():
|
|
|
111
110
|
area = Area(left=44.00253688814017, top=-12.440948032828079, right=50.483612168477286, bottom=-25.1535466075739)
|
|
112
111
|
make_vectors_with_id(42, {area}, path)
|
|
113
112
|
|
|
114
|
-
source = VectorLayer.layer_from_file(
|
|
113
|
+
source = VectorLayer.layer_from_file(
|
|
114
|
+
path,
|
|
115
|
+
"id_no = 42",
|
|
116
|
+
PixelScale(xstep=0.00026949458523585647, ystep=-0.00026949458523585647),
|
|
117
|
+
WGS_84_PROJECTION
|
|
118
|
+
)
|
|
115
119
|
|
|
116
120
|
empty = RasterLayer.empty_raster_layer_like(source)
|
|
117
121
|
assert empty.pixel_scale == source.pixel_scale
|
|
@@ -422,7 +426,13 @@ def test_anchor_offsets(anchor, area, expected):
|
|
|
422
426
|
path = os.path.join(tempdir, "test.gpkg")
|
|
423
427
|
make_vectors_with_id(42, {area}, path)
|
|
424
428
|
|
|
425
|
-
source = VectorLayer.layer_from_file(
|
|
429
|
+
source = VectorLayer.layer_from_file(
|
|
430
|
+
path,
|
|
431
|
+
"id_no = 42",
|
|
432
|
+
PixelScale(1.0, -1.0),
|
|
433
|
+
WGS_84_PROJECTION,
|
|
434
|
+
anchor=anchor
|
|
435
|
+
)
|
|
426
436
|
|
|
427
437
|
final_area = source.area
|
|
428
438
|
assert final_area == expected
|
|
@@ -521,9 +521,17 @@ class LayerOperation(LayerMathMixin):
|
|
|
521
521
|
except AttributeError as exc:
|
|
522
522
|
raise ValueError("Layer must be a raster backed layer") from exc
|
|
523
523
|
|
|
524
|
-
computation_window = self.window
|
|
525
524
|
destination_window = destination_layer.window
|
|
526
525
|
|
|
526
|
+
# If we're calculating purely from a constant layer, then we don't have a window or area
|
|
527
|
+
# so we should use the destination raster details.
|
|
528
|
+
try:
|
|
529
|
+
computation_window = self.window
|
|
530
|
+
computation_area = self.area
|
|
531
|
+
except AttributeError:
|
|
532
|
+
computation_window = destination_window
|
|
533
|
+
computation_area = destination_layer.area
|
|
534
|
+
|
|
527
535
|
if (computation_window.xsize != destination_window.xsize) \
|
|
528
536
|
or (computation_window.ysize != destination_window.ysize):
|
|
529
537
|
raise ValueError("Destination raster window size does not match input raster window size.")
|
|
@@ -536,7 +544,7 @@ class LayerOperation(LayerMathMixin):
|
|
|
536
544
|
step=self.ystep
|
|
537
545
|
if yoffset+step > computation_window.ysize:
|
|
538
546
|
step = computation_window.ysize - yoffset
|
|
539
|
-
chunk = self._eval(
|
|
547
|
+
chunk = self._eval(computation_area, yoffset, step, computation_window)
|
|
540
548
|
if isinstance(chunk, (float, int)):
|
|
541
549
|
chunk = backend.full((step, destination_window.xsize), chunk)
|
|
542
550
|
band.WriteArray(
|
|
@@ -599,7 +607,18 @@ class LayerOperation(LayerMathMixin):
|
|
|
599
607
|
|
|
600
608
|
def _parallel_save(self, destination_layer, and_sum=False, callback=None, parallelism=None, band=1):
|
|
601
609
|
assert (destination_layer is not None) or and_sum
|
|
602
|
-
|
|
610
|
+
try:
|
|
611
|
+
computation_window = self.window
|
|
612
|
+
except AttributeError:
|
|
613
|
+
# This is most likely because the calculation is on a constant layer (or combination of only constant
|
|
614
|
+
# layers) and there's no real benefit to parallel saving then, so to keep this code from getting yet
|
|
615
|
+
# more complicated just fall back to the single threaded path
|
|
616
|
+
if destination_layer:
|
|
617
|
+
return self.save(destination_layer, and_sum, callback, band)
|
|
618
|
+
elif and_sum:
|
|
619
|
+
return self.sum()
|
|
620
|
+
else:
|
|
621
|
+
assert False
|
|
603
622
|
|
|
604
623
|
worker_count = parallelism or multiprocessing.cpu_count()
|
|
605
624
|
work_blocks = len(range(0, computation_window.ysize, self.ystep))
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import pytest
|
|
2
|
-
|
|
3
|
-
# I've no idea why pylint dislikes this particular import but accepts
|
|
4
|
-
# other entries in the module.
|
|
5
|
-
from yirgacheffe.window import Area # pylint: disable=E0401, E0611
|
|
6
|
-
|
|
7
|
-
@pytest.mark.parametrize(
|
|
8
|
-
"lhs,rhs,is_equal,overlaps",
|
|
9
|
-
[
|
|
10
|
-
# Obvious equality
|
|
11
|
-
(Area(-10.0, 10.0, 10.0, -10.0), Area(-10.0, 10.0, 10.0, -10.0), True, True),
|
|
12
|
-
(Area(-9.0, 9.0, 9.0, -9.0), Area(-10.0, 10.0, 10.0, -10.0), False, True), # subset
|
|
13
|
-
(Area(-9.0, 9.0, -1.0, 1.0), Area(1.0, -1.0, 9.0, -9.0), False, False),
|
|
14
|
-
(Area(-10.0, 10.0, 1.0, -10.0), Area(-1.0, 10.0, 10.0, -10.0), False, True),
|
|
15
|
-
]
|
|
16
|
-
)
|
|
17
|
-
def test_area_operators(lhs: Area, rhs: Area, is_equal: bool, overlaps: bool) -> None:
|
|
18
|
-
assert (lhs == rhs) == is_equal
|
|
19
|
-
assert (lhs != rhs) == (not is_equal)
|
|
20
|
-
assert (lhs.overlaps(rhs)) == overlaps
|
|
21
|
-
assert (rhs.overlaps(lhs)) == overlaps
|
|
@@ -1,284 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
import tempfile
|
|
3
|
-
|
|
4
|
-
import numpy as np
|
|
5
|
-
import pytest
|
|
6
|
-
|
|
7
|
-
import yirgacheffe
|
|
8
|
-
from helpers import gdal_dataset_with_data, make_vectors_with_mutlile_ids
|
|
9
|
-
from yirgacheffe.layers import ConstantLayer, RasterLayer, VectorLayer, area
|
|
10
|
-
from yirgacheffe.window import Area
|
|
11
|
-
|
|
12
|
-
def test_add_windows() -> None:
|
|
13
|
-
data1 = np.array([[1, 2], [3, 4]])
|
|
14
|
-
data2 = np.array([[10, 20, 30, 40], [50, 60, 70, 80], [90, 100, 110, 120], [130, 140, 150, 160]])
|
|
15
|
-
|
|
16
|
-
layer1 = RasterLayer(gdal_dataset_with_data((0.0, 0.0), 0.02, data1))
|
|
17
|
-
layer2 = RasterLayer(gdal_dataset_with_data((0.0, 0.0), 0.02, data2))
|
|
18
|
-
|
|
19
|
-
assert layer1.area != layer2.area
|
|
20
|
-
assert layer1.window != layer2.window
|
|
21
|
-
|
|
22
|
-
calc = layer1 + layer2
|
|
23
|
-
|
|
24
|
-
assert calc.area == layer2.area
|
|
25
|
-
assert calc.window == layer2.window
|
|
26
|
-
|
|
27
|
-
result = RasterLayer.empty_raster_layer_like(calc)
|
|
28
|
-
calc.save(result)
|
|
29
|
-
|
|
30
|
-
expected = np.array([[11, 22, 30, 40], [53, 64, 70, 80], [90, 100, 110, 120], [130, 140, 150, 160]])
|
|
31
|
-
actual = result.read_array(0, 0, 4, 4)
|
|
32
|
-
assert (expected == actual).all()
|
|
33
|
-
|
|
34
|
-
def test_multiply_windows() -> None:
|
|
35
|
-
data1 = np.array([[1, 2], [3, 4]])
|
|
36
|
-
data2 = np.array([[10, 20, 30, 40], [50, 60, 70, 80], [90, 100, 110, 120], [130, 140, 150, 160]])
|
|
37
|
-
|
|
38
|
-
layer1 = RasterLayer(gdal_dataset_with_data((0.0, 0.0), 0.02, data1))
|
|
39
|
-
layer2 = RasterLayer(gdal_dataset_with_data((0.0, 0.0), 0.02, data2))
|
|
40
|
-
|
|
41
|
-
assert layer1.area != layer2.area
|
|
42
|
-
assert layer1.window != layer2.window
|
|
43
|
-
|
|
44
|
-
calc = layer1 * layer2
|
|
45
|
-
|
|
46
|
-
assert calc.area == layer1.area
|
|
47
|
-
assert calc.window == layer1.window
|
|
48
|
-
|
|
49
|
-
result = RasterLayer.empty_raster_layer_like(calc)
|
|
50
|
-
calc.save(result)
|
|
51
|
-
|
|
52
|
-
expected = np.array([[10, 40], [150, 240]])
|
|
53
|
-
actual = result.read_array(0, 0, 2, 2)
|
|
54
|
-
assert (expected == actual).all()
|
|
55
|
-
|
|
56
|
-
def test_add_windows_offset() -> None:
|
|
57
|
-
data1 = np.array([[1, 2], [3, 4]])
|
|
58
|
-
data2 = np.array([[10, 20, 30, 40], [50, 60, 70, 80], [90, 100, 110, 120], [130, 140, 150, 160]])
|
|
59
|
-
|
|
60
|
-
layer1 = RasterLayer(gdal_dataset_with_data((-0.02, 0.02), 0.02, data1))
|
|
61
|
-
layer2 = RasterLayer(gdal_dataset_with_data((-0.04, 0.04), 0.02, data2))
|
|
62
|
-
|
|
63
|
-
assert layer1.area != layer2.area
|
|
64
|
-
assert layer1.window != layer2.window
|
|
65
|
-
|
|
66
|
-
calc = layer1 + layer2
|
|
67
|
-
|
|
68
|
-
assert calc.area == layer2.area
|
|
69
|
-
|
|
70
|
-
result = RasterLayer.empty_raster_layer_like(calc)
|
|
71
|
-
calc.save(result)
|
|
72
|
-
|
|
73
|
-
expected = np.array([[10, 20, 30, 40], [50, 61, 72, 80], [90, 103, 114, 120], [130, 140, 150, 160]])
|
|
74
|
-
actual = result.read_array(0, 0, 4, 4)
|
|
75
|
-
assert (expected == actual).all()
|
|
76
|
-
|
|
77
|
-
def test_multiply_windows_offset() -> None:
|
|
78
|
-
data1 = np.array([[1, 2], [3, 4]])
|
|
79
|
-
data2 = np.array([[10, 20, 30, 40], [50, 60, 70, 80], [90, 100, 110, 120], [130, 140, 150, 160]])
|
|
80
|
-
|
|
81
|
-
layer1 = RasterLayer(gdal_dataset_with_data((-0.02, 0.02), 0.02, data1))
|
|
82
|
-
layer2 = RasterLayer(gdal_dataset_with_data((-0.04, 0.04), 0.02, data2))
|
|
83
|
-
|
|
84
|
-
assert layer1.area != layer2.area
|
|
85
|
-
assert layer1.window != layer2.window
|
|
86
|
-
|
|
87
|
-
calc = layer1 * layer2
|
|
88
|
-
|
|
89
|
-
assert calc.area == layer1.area
|
|
90
|
-
|
|
91
|
-
result = RasterLayer.empty_raster_layer_like(calc)
|
|
92
|
-
calc.save(result)
|
|
93
|
-
|
|
94
|
-
expected = np.array([[60, 140], [300, 440]])
|
|
95
|
-
actual = result.read_array(0, 0, 2, 2)
|
|
96
|
-
assert (expected == actual).all()
|
|
97
|
-
|
|
98
|
-
def test_add_windows_sum() -> None:
|
|
99
|
-
data1 = np.array([[1, 2], [3, 4]])
|
|
100
|
-
data2 = np.array([[10, 20, 30, 40], [50, 60, 70, 80], [90, 100, 110, 120], [130, 140, 150, 160]])
|
|
101
|
-
|
|
102
|
-
layer1 = RasterLayer(gdal_dataset_with_data((-0.02, 0.02), 0.02, data1))
|
|
103
|
-
layer2 = RasterLayer(gdal_dataset_with_data((-0.04, 0.04), 0.02, data2))
|
|
104
|
-
|
|
105
|
-
calc = layer1 + layer2
|
|
106
|
-
total = calc.sum()
|
|
107
|
-
|
|
108
|
-
expected = np.array([[10, 20, 30, 40], [50, 61, 72, 80], [90, 103, 114, 120], [130, 140, 150, 160]])
|
|
109
|
-
assert total == np.sum(expected)
|
|
110
|
-
|
|
111
|
-
def test_multiply_windows_sum() -> None:
|
|
112
|
-
data1 = np.array([[1, 2], [3, 4]])
|
|
113
|
-
data2 = np.array([[10, 20, 30, 40], [50, 60, 70, 80], [90, 100, 110, 120], [130, 140, 150, 160]])
|
|
114
|
-
|
|
115
|
-
layer1 = RasterLayer(gdal_dataset_with_data((-0.02, 0.02), 0.02, data1))
|
|
116
|
-
layer2 = RasterLayer(gdal_dataset_with_data((-0.04, 0.04), 0.02, data2))
|
|
117
|
-
|
|
118
|
-
calc = layer1 * layer2
|
|
119
|
-
total = calc.sum()
|
|
120
|
-
|
|
121
|
-
expected = np.array([[60, 140], [300, 440]])
|
|
122
|
-
assert total == np.sum(expected)
|
|
123
|
-
|
|
124
|
-
def test_constant_layer_result_rhs_add() -> None:
|
|
125
|
-
data1 = np.array([[1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0]])
|
|
126
|
-
layer1 = RasterLayer(gdal_dataset_with_data((0.0, 0.0), 0.02, data1))
|
|
127
|
-
const_layer = ConstantLayer(1.0)
|
|
128
|
-
|
|
129
|
-
calc = layer1 + const_layer
|
|
130
|
-
|
|
131
|
-
assert calc.area == layer1.area
|
|
132
|
-
|
|
133
|
-
result = RasterLayer.empty_raster_layer_like(calc)
|
|
134
|
-
calc.save(result)
|
|
135
|
-
actual = result.read_array(0, 0, 4, 2)
|
|
136
|
-
|
|
137
|
-
expected = 1.0 + data1
|
|
138
|
-
|
|
139
|
-
assert (expected == actual).all()
|
|
140
|
-
|
|
141
|
-
def test_constant_layer_result_lhs_add() -> None:
|
|
142
|
-
data1 = np.array([[1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0]])
|
|
143
|
-
layer1 = RasterLayer(gdal_dataset_with_data((0.0, 0.0), 0.02, data1))
|
|
144
|
-
const_layer = ConstantLayer(1.0)
|
|
145
|
-
result = RasterLayer.empty_raster_layer_like(layer1)
|
|
146
|
-
|
|
147
|
-
intersection = RasterLayer.find_intersection([layer1, const_layer])
|
|
148
|
-
const_layer.set_window_for_intersection(intersection)
|
|
149
|
-
layer1.set_window_for_intersection(intersection)
|
|
150
|
-
|
|
151
|
-
calc = const_layer + layer1
|
|
152
|
-
|
|
153
|
-
assert calc.area == layer1.area
|
|
154
|
-
|
|
155
|
-
result = RasterLayer.empty_raster_layer_like(calc)
|
|
156
|
-
calc.save(result)
|
|
157
|
-
actual = result.read_array(0, 0, 4, 2)
|
|
158
|
-
|
|
159
|
-
expected = 1.0 + data1
|
|
160
|
-
|
|
161
|
-
assert (expected == actual).all()
|
|
162
|
-
|
|
163
|
-
def test_constant_layer_result_rhs_multiply() -> None:
|
|
164
|
-
data1 = np.array([[1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0]])
|
|
165
|
-
layer1 = RasterLayer(gdal_dataset_with_data((0.0, 0.0), 0.02, data1))
|
|
166
|
-
const_layer = ConstantLayer(2.0)
|
|
167
|
-
|
|
168
|
-
calc = layer1 * const_layer
|
|
169
|
-
|
|
170
|
-
assert calc.area == layer1.area
|
|
171
|
-
|
|
172
|
-
result = RasterLayer.empty_raster_layer_like(calc)
|
|
173
|
-
calc.save(result)
|
|
174
|
-
actual = result.read_array(0, 0, 4, 2)
|
|
175
|
-
|
|
176
|
-
expected = data1 * 2.0
|
|
177
|
-
|
|
178
|
-
assert (expected == actual).all()
|
|
179
|
-
|
|
180
|
-
def test_constant_layer_result_lhs_multiply() -> None:
|
|
181
|
-
data1 = np.array([[1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0]])
|
|
182
|
-
layer1 = RasterLayer(gdal_dataset_with_data((0.0, 0.0), 0.02, data1))
|
|
183
|
-
const_layer = ConstantLayer(2.0)
|
|
184
|
-
result = RasterLayer.empty_raster_layer_like(layer1)
|
|
185
|
-
|
|
186
|
-
intersection = RasterLayer.find_intersection([layer1, const_layer])
|
|
187
|
-
const_layer.set_window_for_intersection(intersection)
|
|
188
|
-
layer1.set_window_for_intersection(intersection)
|
|
189
|
-
|
|
190
|
-
calc = const_layer * layer1
|
|
191
|
-
|
|
192
|
-
assert calc.area == layer1.area
|
|
193
|
-
|
|
194
|
-
result = RasterLayer.empty_raster_layer_like(calc)
|
|
195
|
-
calc.save(result)
|
|
196
|
-
actual = result.read_array(0, 0, 4, 2)
|
|
197
|
-
|
|
198
|
-
expected = 2.0 * data1
|
|
199
|
-
|
|
200
|
-
assert (expected == actual).all()
|
|
201
|
-
|
|
202
|
-
def test_vector_layers_add() -> None:
|
|
203
|
-
data1 = np.array([[1, 2], [3, 4]])
|
|
204
|
-
layer1 = RasterLayer(gdal_dataset_with_data((0.0, 0.0), 1.0, data1))
|
|
205
|
-
|
|
206
|
-
with tempfile.TemporaryDirectory() as tempdir:
|
|
207
|
-
path = os.path.join(tempdir, "test.gpkg")
|
|
208
|
-
areas = {
|
|
209
|
-
(Area(-10.0, 10.0, 0.0, 0.0), 42),
|
|
210
|
-
(Area(0.0, 0.0, 10, -10), 43)
|
|
211
|
-
}
|
|
212
|
-
make_vectors_with_mutlile_ids(areas, path)
|
|
213
|
-
|
|
214
|
-
burn_value = 2
|
|
215
|
-
layer2 = VectorLayer.layer_from_file(path, None, layer1.pixel_scale, layer1.projection, burn_value=burn_value)
|
|
216
|
-
layer2_total = layer2.sum()
|
|
217
|
-
assert layer2_total == ((layer2.window.xsize * layer2.window.ysize) / 2) * burn_value
|
|
218
|
-
|
|
219
|
-
calc = layer1 + layer2
|
|
220
|
-
|
|
221
|
-
assert calc.area == layer2.area
|
|
222
|
-
|
|
223
|
-
total = calc.sum()
|
|
224
|
-
assert total == layer2_total + np.sum(data1)
|
|
225
|
-
|
|
226
|
-
def test_vector_layers_multiply() -> None:
|
|
227
|
-
data1 = np.array([[1, 2], [3, 4]])
|
|
228
|
-
layer1 = RasterLayer(gdal_dataset_with_data((-1.0, 1.0), 1.0, data1))
|
|
229
|
-
|
|
230
|
-
with tempfile.TemporaryDirectory() as tempdir:
|
|
231
|
-
path = os.path.join(tempdir, "test.gpkg")
|
|
232
|
-
areas = {
|
|
233
|
-
(Area(-10.0, 10.0, 0.0, 0.0), 42),
|
|
234
|
-
(Area(0.0, 0.0, 10, -10), 43)
|
|
235
|
-
}
|
|
236
|
-
make_vectors_with_mutlile_ids(areas, path)
|
|
237
|
-
|
|
238
|
-
burn_value = 2
|
|
239
|
-
layer2 = VectorLayer.layer_from_file(path, None, layer1.pixel_scale, layer1.projection, burn_value=burn_value)
|
|
240
|
-
layer2_total = layer2.sum()
|
|
241
|
-
assert layer2_total == ((layer2.window.xsize * layer2.window.ysize) / 2) * burn_value
|
|
242
|
-
|
|
243
|
-
calc = layer1 * layer2
|
|
244
|
-
|
|
245
|
-
assert calc.area == layer1.area
|
|
246
|
-
|
|
247
|
-
result = RasterLayer.empty_raster_layer_like(calc)
|
|
248
|
-
calc.save(result)
|
|
249
|
-
actual = result.read_array(0, 0, 2, 2)
|
|
250
|
-
|
|
251
|
-
expected = np.array([[2, 0], [0, 8]])
|
|
252
|
-
assert (expected == actual).all()
|
|
253
|
-
|
|
254
|
-
@pytest.mark.skipif(yirgacheffe.backends.BACKEND != "NUMPY", reason="Only applies for numpy")
|
|
255
|
-
def test_parallel_save_windows() -> None:
|
|
256
|
-
data1 = np.array([[1, 2], [3, 4]])
|
|
257
|
-
data2 = np.array([[10, 20, 30, 40], [50, 60, 70, 80], [90, 100, 110, 120], [130, 140, 150, 160]])
|
|
258
|
-
|
|
259
|
-
with tempfile.TemporaryDirectory() as tempdir:
|
|
260
|
-
layer1_filename = os.path.join(tempdir, "layer1.tif")
|
|
261
|
-
layer1_dataset = gdal_dataset_with_data((0.0, 0.0), 0.02, data1, filename=layer1_filename)
|
|
262
|
-
layer1_dataset.Close()
|
|
263
|
-
|
|
264
|
-
layer2_filename = os.path.join(tempdir, "layer2.tif")
|
|
265
|
-
layer2_dataset = gdal_dataset_with_data((0.0, 0.0), 0.02, data2, filename=layer2_filename)
|
|
266
|
-
layer2_dataset.Close()
|
|
267
|
-
|
|
268
|
-
layer1 = RasterLayer.layer_from_file(layer1_filename)
|
|
269
|
-
layer2 = RasterLayer.layer_from_file(layer2_filename)
|
|
270
|
-
|
|
271
|
-
assert layer1.area != layer2.area
|
|
272
|
-
assert layer1.window != layer2.window
|
|
273
|
-
|
|
274
|
-
calc = layer1 + layer2
|
|
275
|
-
|
|
276
|
-
assert calc.area == layer2.area
|
|
277
|
-
assert calc.window == layer2.window
|
|
278
|
-
|
|
279
|
-
result = RasterLayer.empty_raster_layer_like(calc)
|
|
280
|
-
calc.parallel_save(result)
|
|
281
|
-
|
|
282
|
-
expected = np.array([[11, 22, 30, 40], [53, 64, 70, 80], [90, 100, 110, 120], [130, 140, 150, 160]])
|
|
283
|
-
actual = result.read_array(0, 0, 4, 4)
|
|
284
|
-
assert (expected == actual).all()
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import numpy as np
|
|
3
|
-
import pytest
|
|
4
|
-
from osgeo import gdal
|
|
5
|
-
|
|
6
|
-
from yirgacheffe.operators import DataType
|
|
7
|
-
from yirgacheffe.backends import backend, BACKEND
|
|
8
|
-
from yirgacheffe.layers import RasterLayer
|
|
9
|
-
|
|
10
|
-
from helpers import gdal_dataset_with_data
|
|
11
|
-
|
|
12
|
-
@pytest.mark.parametrize("gtype", [
|
|
13
|
-
gdal.GDT_Int8,
|
|
14
|
-
gdal.GDT_Int16,
|
|
15
|
-
gdal.GDT_Int32,
|
|
16
|
-
gdal.GDT_Int64,
|
|
17
|
-
gdal.GDT_Byte,
|
|
18
|
-
gdal.GDT_UInt16,
|
|
19
|
-
gdal.GDT_UInt32,
|
|
20
|
-
gdal.GDT_UInt64,
|
|
21
|
-
gdal.GDT_Float32,
|
|
22
|
-
])
|
|
23
|
-
def test_round_trip(gtype) -> None:
|
|
24
|
-
ytype = DataType.of_gdal(gtype)
|
|
25
|
-
backend_type = backend.dtype_to_backed(ytype)
|
|
26
|
-
assert backend.backend_to_dtype(backend_type) == ytype
|
|
27
|
-
|
|
28
|
-
@pytest.mark.parametrize("ytype", [
|
|
29
|
-
DataType.Int8,
|
|
30
|
-
DataType.Int16,
|
|
31
|
-
DataType.Int32,
|
|
32
|
-
DataType.Int64,
|
|
33
|
-
DataType.UInt8,
|
|
34
|
-
DataType.UInt16,
|
|
35
|
-
DataType.UInt32,
|
|
36
|
-
DataType.UInt64,
|
|
37
|
-
DataType.Float32,
|
|
38
|
-
DataType.Float64,
|
|
39
|
-
])
|
|
40
|
-
def test_round_trip_from_gdal(ytype) -> None:
|
|
41
|
-
gtype = ytype.to_gdal()
|
|
42
|
-
assert DataType.of_gdal(gtype) == ytype
|
|
43
|
-
|
|
44
|
-
def test_round_trip_float64() -> None:
|
|
45
|
-
backend_type = backend.dtype_to_backed(DataType.Float64)
|
|
46
|
-
ytype = backend.backend_to_dtype(backend_type)
|
|
47
|
-
print(BACKEND, "sad")
|
|
48
|
-
match BACKEND:
|
|
49
|
-
case "NUMPY":
|
|
50
|
-
assert ytype == DataType.Float64
|
|
51
|
-
case "MLX":
|
|
52
|
-
assert ytype == DataType.Float32
|
|
53
|
-
|
|
54
|
-
def test_float_to_int() -> None:
|
|
55
|
-
data1 = np.array([[1.0, 2.0, 3.0, 4.0], [5.5, 6.5, 7.5, 8.5]])
|
|
56
|
-
|
|
57
|
-
layer1 = RasterLayer(gdal_dataset_with_data((0.0, 0.0), 0.02, data1))
|
|
58
|
-
# Note the float 32 here is to rule out that writing the result to the
|
|
59
|
-
# new dataset was what caused the truncation
|
|
60
|
-
result = RasterLayer.empty_raster_layer_like(layer1, datatype=DataType.Float32)
|
|
61
|
-
|
|
62
|
-
comp = layer1.astype(DataType.UInt8)
|
|
63
|
-
comp.save(result)
|
|
64
|
-
|
|
65
|
-
expected = backend.promote(np.array([[1, 2, 3, 4], [5, 6, 7, 8]]))
|
|
66
|
-
actual = backend.demote_array(result.read_array(0, 0, 4, 2))
|
|
67
|
-
assert (expected == actual).all()
|
|
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
|