yirgacheffe 1.7.4__py3-none-any.whl → 1.7.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of yirgacheffe might be problematic. Click here for more details.
- yirgacheffe/__init__.py +1 -1
- yirgacheffe/_core.py +49 -0
- yirgacheffe/layers/rasters.py +6 -2
- yirgacheffe/layers/vectors.py +8 -0
- yirgacheffe/operators.py +3 -43
- {yirgacheffe-1.7.4.dist-info → yirgacheffe-1.7.6.dist-info}/METADATA +21 -5
- {yirgacheffe-1.7.4.dist-info → yirgacheffe-1.7.6.dist-info}/RECORD +11 -11
- {yirgacheffe-1.7.4.dist-info → yirgacheffe-1.7.6.dist-info}/WHEEL +0 -0
- {yirgacheffe-1.7.4.dist-info → yirgacheffe-1.7.6.dist-info}/entry_points.txt +0 -0
- {yirgacheffe-1.7.4.dist-info → yirgacheffe-1.7.6.dist-info}/licenses/LICENSE +0 -0
- {yirgacheffe-1.7.4.dist-info → yirgacheffe-1.7.6.dist-info}/top_level.txt +0 -0
yirgacheffe/__init__.py
CHANGED
|
@@ -12,7 +12,7 @@ except ModuleNotFoundError:
|
|
|
12
12
|
pyproject_data = tomllib.load(f)
|
|
13
13
|
__version__ = pyproject_data["project"]["version"]
|
|
14
14
|
|
|
15
|
-
from ._core import read_raster, read_rasters, read_shape, read_shape_like
|
|
15
|
+
from ._core import read_raster, read_rasters, read_shape, read_shape_like, constant, read_narrow_raster
|
|
16
16
|
from .constants import WGS_84_PROJECTION
|
|
17
17
|
|
|
18
18
|
gdal.UseExceptions()
|
yirgacheffe/_core.py
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
2
|
from typing import Optional, Sequence, Tuple, Union
|
|
3
3
|
|
|
4
|
+
from .layers.area import UniformAreaLayer
|
|
4
5
|
from .layers.base import YirgacheffeLayer
|
|
6
|
+
from .layers.constant import ConstantLayer
|
|
5
7
|
from .layers.group import GroupLayer, TiledGroupLayer
|
|
6
8
|
from .layers.rasters import RasterLayer
|
|
7
9
|
from .layers.vectors import VectorLayer
|
|
@@ -31,6 +33,33 @@ def read_raster(
|
|
|
31
33
|
"""
|
|
32
34
|
return RasterLayer.layer_from_file(filename, band, ignore_nodata)
|
|
33
35
|
|
|
36
|
+
def read_narrow_raster(
|
|
37
|
+
filename: Union[Path,str],
|
|
38
|
+
band: int = 1,
|
|
39
|
+
ignore_nodata: bool = False,
|
|
40
|
+
) -> RasterLayer:
|
|
41
|
+
"""Open a 1 pixel wide raster file as a global raster.
|
|
42
|
+
|
|
43
|
+
This exists for the special use case where an area per pixel raster would have the same value per horizontal row
|
|
44
|
+
(e.g., a WGS84 map projection). For that case you can use this to load a raster that is 1 pixel wide and have
|
|
45
|
+
it automatically expanded to act like a global raster in calculations.
|
|
46
|
+
|
|
47
|
+
Parameters
|
|
48
|
+
----------
|
|
49
|
+
filename : Path
|
|
50
|
+
Path of raster file to open.
|
|
51
|
+
band : int, default=1
|
|
52
|
+
For multi-band rasters, which band to use (defaults to first if not specified)
|
|
53
|
+
ignore_nodata : bool, default=False
|
|
54
|
+
If the GeoTIFF has a NODATA value, don't subsitute that value for NaN
|
|
55
|
+
|
|
56
|
+
Returns
|
|
57
|
+
-------
|
|
58
|
+
RasterLayer
|
|
59
|
+
Returns an layer representing the raster data.
|
|
60
|
+
"""
|
|
61
|
+
return UniformAreaLayer.layer_from_file(filename, band, ignore_nodata)
|
|
62
|
+
|
|
34
63
|
def read_rasters(
|
|
35
64
|
filenames : Sequence[Union[Path,str]],
|
|
36
65
|
tiled: bool=False
|
|
@@ -132,3 +161,23 @@ def read_shape_like(
|
|
|
132
161
|
datatype,
|
|
133
162
|
burn_value,
|
|
134
163
|
)
|
|
164
|
+
|
|
165
|
+
def constant(value: Union[int,float]) -> ConstantLayer:
|
|
166
|
+
"""Generate a layer that has the same value in all pixels regardless of scale, projection, and area.
|
|
167
|
+
|
|
168
|
+
Generally this should not be necessary unless you must have the constant as the first term in an
|
|
169
|
+
expression, as Yirgacheffe will automatically convert numbers into constant layers. However if the
|
|
170
|
+
constant is the first term in the expression it must be wrapped by this call otherwise Python will
|
|
171
|
+
not know that it should be part of the Yirgacheffe expression.
|
|
172
|
+
|
|
173
|
+
Parameters
|
|
174
|
+
----------
|
|
175
|
+
value : int or float
|
|
176
|
+
The value to be in each pixel of the expression term.
|
|
177
|
+
|
|
178
|
+
Returns
|
|
179
|
+
-------
|
|
180
|
+
ConstantLayer
|
|
181
|
+
Returns a constant layer of the provided value.
|
|
182
|
+
"""
|
|
183
|
+
return ConstantLayer(value)
|
yirgacheffe/layers/rasters.py
CHANGED
|
@@ -97,8 +97,6 @@ class RasterLayer(YirgacheffeLayer):
|
|
|
97
97
|
threads: Optional[int]=None,
|
|
98
98
|
bands: int=1
|
|
99
99
|
) -> RasterLayer:
|
|
100
|
-
width = layer.window.xsize
|
|
101
|
-
height = layer.window.ysize
|
|
102
100
|
if area is None:
|
|
103
101
|
area = layer.area
|
|
104
102
|
assert area is not None
|
|
@@ -117,6 +115,12 @@ class RasterLayer(YirgacheffeLayer):
|
|
|
117
115
|
area.left, projection.xstep, 0.0, area.top, 0.0, projection.ystep
|
|
118
116
|
)
|
|
119
117
|
|
|
118
|
+
if area is None:
|
|
119
|
+
og_width = layer.window.xsize
|
|
120
|
+
og_height = layer.window.ysize
|
|
121
|
+
assert (og_width == width) and (og_height == height), \
|
|
122
|
+
f"original size ({og_width}, {og_height}) != estimated ({width}, {height})"
|
|
123
|
+
|
|
120
124
|
if datatype is None:
|
|
121
125
|
datatype_arg = layer.datatype
|
|
122
126
|
elif isinstance(datatype, int):
|
yirgacheffe/layers/vectors.py
CHANGED
|
@@ -4,8 +4,10 @@ from pathlib import Path
|
|
|
4
4
|
from typing import Any, Optional, Tuple, Union
|
|
5
5
|
from typing_extensions import NotRequired
|
|
6
6
|
|
|
7
|
+
import deprecation
|
|
7
8
|
from osgeo import gdal, ogr
|
|
8
9
|
|
|
10
|
+
from .. import __version__
|
|
9
11
|
from ..operators import DataType
|
|
10
12
|
from ..window import Area, MapProjection, PixelScale
|
|
11
13
|
from .base import YirgacheffeLayer
|
|
@@ -60,6 +62,12 @@ class RasteredVectorLayer(RasterLayer):
|
|
|
60
62
|
VectorLayer."""
|
|
61
63
|
|
|
62
64
|
@classmethod
|
|
65
|
+
@deprecation.deprecated(
|
|
66
|
+
deprecated_in="1.7",
|
|
67
|
+
removed_in="2.0",
|
|
68
|
+
current_version=__version__,
|
|
69
|
+
details="Use `VectorLayer` instead."
|
|
70
|
+
)
|
|
63
71
|
def layer_from_file( # type: ignore[override] # pylint: disable=W0221
|
|
64
72
|
cls,
|
|
65
73
|
filename: Union[Path,str],
|
yirgacheffe/operators.py
CHANGED
|
@@ -387,50 +387,9 @@ class LayerOperation(LayerMathMixin):
|
|
|
387
387
|
|
|
388
388
|
@property
|
|
389
389
|
def area(self) -> Area:
|
|
390
|
-
|
|
391
|
-
lhs_area = self.lhs.area
|
|
392
|
-
try:
|
|
393
|
-
rhs_area = self.rhs.area
|
|
394
|
-
except AttributeError:
|
|
395
|
-
rhs_area = None
|
|
396
|
-
try:
|
|
397
|
-
other_area = self.other.area
|
|
398
|
-
except AttributeError:
|
|
399
|
-
other_area = None
|
|
400
|
-
|
|
401
|
-
all_areas = [x for x in [lhs_area, rhs_area, other_area] if (x is not None) and (not x.is_world)]
|
|
402
|
-
|
|
403
|
-
match self.window_op:
|
|
404
|
-
case WindowOperation.NONE:
|
|
405
|
-
return all_areas[0]
|
|
406
|
-
case WindowOperation.LEFT:
|
|
407
|
-
return lhs_area
|
|
408
|
-
case WindowOperation.RIGHT:
|
|
409
|
-
assert rhs_area is not None
|
|
410
|
-
return rhs_area
|
|
411
|
-
case WindowOperation.INTERSECTION:
|
|
412
|
-
intersection = Area(
|
|
413
|
-
left=max(x.left for x in all_areas),
|
|
414
|
-
top=min(x.top for x in all_areas),
|
|
415
|
-
right=min(x.right for x in all_areas),
|
|
416
|
-
bottom=max(x.bottom for x in all_areas)
|
|
417
|
-
)
|
|
418
|
-
if (intersection.left >= intersection.right) or (intersection.bottom >= intersection.top):
|
|
419
|
-
raise ValueError('No intersection possible')
|
|
420
|
-
return intersection
|
|
421
|
-
case WindowOperation.UNION:
|
|
422
|
-
return Area(
|
|
423
|
-
left=min(x.left for x in all_areas),
|
|
424
|
-
top=max(x.top for x in all_areas),
|
|
425
|
-
right=max(x.right for x in all_areas),
|
|
426
|
-
bottom=min(x.bottom for x in all_areas)
|
|
427
|
-
)
|
|
428
|
-
case _:
|
|
429
|
-
assert False, "Should not be reached"
|
|
390
|
+
return self._get_operation_area(self.map_projection)
|
|
430
391
|
|
|
431
392
|
def _get_operation_area(self, projection: Optional[MapProjection]) -> Area:
|
|
432
|
-
|
|
433
|
-
# The type().__name__ here is to avoid a circular import dependancy
|
|
434
393
|
lhs_area = self.lhs._get_operation_area(projection)
|
|
435
394
|
try:
|
|
436
395
|
rhs_area = self.rhs._get_operation_area(projection)
|
|
@@ -462,12 +421,13 @@ class LayerOperation(LayerMathMixin):
|
|
|
462
421
|
raise ValueError('No intersection possible')
|
|
463
422
|
return intersection
|
|
464
423
|
case WindowOperation.UNION:
|
|
465
|
-
|
|
424
|
+
union = Area(
|
|
466
425
|
left=min(x.left for x in all_areas),
|
|
467
426
|
top=max(x.top for x in all_areas),
|
|
468
427
|
right=max(x.right for x in all_areas),
|
|
469
428
|
bottom=min(x.bottom for x in all_areas)
|
|
470
429
|
)
|
|
430
|
+
return union
|
|
471
431
|
case _:
|
|
472
432
|
assert False, "Should not be reached"
|
|
473
433
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: yirgacheffe
|
|
3
|
-
Version: 1.7.
|
|
3
|
+
Version: 1.7.6
|
|
4
4
|
Summary: Abstraction of gdal datasets for doing basic math operations
|
|
5
5
|
Author-email: Michael Dales <mwd24@cam.ac.uk>
|
|
6
6
|
License-Expression: ISC
|
|
@@ -262,17 +262,33 @@ Notes:
|
|
|
262
262
|
* You can have missing tiles, and these will be filled in with zeros.
|
|
263
263
|
* You can have tiles that overlap, so long as they still conform to the rule that all tiles are the same size and on a grid.
|
|
264
264
|
|
|
265
|
-
###
|
|
265
|
+
### Constants
|
|
266
266
|
|
|
267
|
-
|
|
267
|
+
At times it is useful to have a fixed constant in an expression. Typically, similar to numpy, if an expression involving layers has a constant in, Yirgacheffe will apply that to all pixels in the equation without need for further elaboration:
|
|
268
|
+
|
|
269
|
+
```python
|
|
270
|
+
with yg.read_raster("some_data.tif") as layer:
|
|
271
|
+
doubled_layer = layer * 2.0
|
|
272
|
+
...
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
This can be useful in tasks where you have an optional layer in your code. For example, here the code optionally loads an area-per-pixel layer, which if not present can just be substituted with a 1.0:
|
|
268
276
|
|
|
269
277
|
```python
|
|
270
278
|
try:
|
|
271
|
-
area_layer =
|
|
279
|
+
area_layer = yg.read_raster('myarea.tiff')
|
|
272
280
|
except FileDoesNotExist:
|
|
273
|
-
area_layer =
|
|
281
|
+
area_layer = 1.0
|
|
274
282
|
```
|
|
275
283
|
|
|
284
|
+
However, as with numpy, Python can not make the correct inference if the constant value is the first term in the equation. In that case you need to explicitly wrap the value with `constant` to help Python understand what is happening:
|
|
285
|
+
|
|
286
|
+
```python
|
|
287
|
+
with yg.read_raster("some_data.tif") as layer:
|
|
288
|
+
result = yg.constant(1.0) / layer
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
|
|
276
292
|
### H3CellLayer
|
|
277
293
|
|
|
278
294
|
If you have H3 installed, you can generate a mask layer based on an H3 cell identifier, where pixels inside the cell will have a value of 1, and those outside will have a value of 0.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
yirgacheffe/__init__.py,sha256=
|
|
2
|
-
yirgacheffe/_core.py,sha256=
|
|
1
|
+
yirgacheffe/__init__.py,sha256=pY9dqmHHARfY44T-7-7y6Ah97qQHj9_0pgYTItI5TR8,567
|
|
2
|
+
yirgacheffe/_core.py,sha256=C3TefRffw8n57AQGTNXgyEtXXZb9exZcRFg0yxNtqlo,6062
|
|
3
3
|
yirgacheffe/constants.py,sha256=uCWJwec3-ND-zVxYbsk1sdHKANl3ToNCTPg7MZb0j2g,434
|
|
4
|
-
yirgacheffe/operators.py,sha256=
|
|
4
|
+
yirgacheffe/operators.py,sha256=PIF3ec2ogGf2-8D7m56usNNer1bOe0HA9kL5JOqpbnQ,34576
|
|
5
5
|
yirgacheffe/rounding.py,sha256=ggBG4lMyLMtHLW3dBxr3gBCcF2qhRrY5etZiFGlIoqA,2258
|
|
6
6
|
yirgacheffe/window.py,sha256=0Wy3BT4SZLyviDwzLcX8LYOo2MeZ2zXCWAiJNpMbQpc,9505
|
|
7
7
|
yirgacheffe/_backends/__init__.py,sha256=jN-2iRrHStnPI6cNL7XhwhsROtI0EaGfIrbF5c-ECV0,334
|
|
@@ -14,12 +14,12 @@ yirgacheffe/layers/base.py,sha256=MPVGEsFRPuRDYtL1OBu7XP26kBDWfpS3RS3twYKBOQc,14
|
|
|
14
14
|
yirgacheffe/layers/constant.py,sha256=XQ1ibeSckAcUOow-dMUlZiW5S2MKeFquOz_m8Y027GI,1437
|
|
15
15
|
yirgacheffe/layers/group.py,sha256=YgA0Bl0lAO2KwTT57126rXfyPq6MCssaaFrTQLe377s,16182
|
|
16
16
|
yirgacheffe/layers/h3layer.py,sha256=Ys6F-e4Jre7lbFBYErF_4oidQx22WkWMKpHpQ7pPDTs,9875
|
|
17
|
-
yirgacheffe/layers/rasters.py,sha256
|
|
17
|
+
yirgacheffe/layers/rasters.py,sha256=w1lmZmvwU7tKUy84y8uqWNnVn-0T268VrsQTUKfQkP0,13565
|
|
18
18
|
yirgacheffe/layers/rescaled.py,sha256=hkvsd7paDCyUViABxrAXdXPOZegdwiphibkdrBuRclk,3366
|
|
19
|
-
yirgacheffe/layers/vectors.py,sha256=
|
|
20
|
-
yirgacheffe-1.7.
|
|
21
|
-
yirgacheffe-1.7.
|
|
22
|
-
yirgacheffe-1.7.
|
|
23
|
-
yirgacheffe-1.7.
|
|
24
|
-
yirgacheffe-1.7.
|
|
25
|
-
yirgacheffe-1.7.
|
|
19
|
+
yirgacheffe/layers/vectors.py,sha256=8tt0rCkhrT-HZi90rEvv8qL6cVSYLG5HZTqqTz6BuTU,20118
|
|
20
|
+
yirgacheffe-1.7.6.dist-info/licenses/LICENSE,sha256=dNSHwUCJr6axStTKDEdnJtfmDdFqlE3h1NPCveqPfnY,757
|
|
21
|
+
yirgacheffe-1.7.6.dist-info/METADATA,sha256=kUhrFtnD5Me9SSD0VBCk48z6YLJ9U7vU94Fto5VSDZY,23134
|
|
22
|
+
yirgacheffe-1.7.6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
23
|
+
yirgacheffe-1.7.6.dist-info/entry_points.txt,sha256=j4KgHXbVGbGyfTySc1ypBdERpfihO4WNjppvCdE9HjE,52
|
|
24
|
+
yirgacheffe-1.7.6.dist-info/top_level.txt,sha256=9DBFlKO2Ld3hG6TuE3qOTd3Tt8ugTiXil4AN4Wr9_y0,12
|
|
25
|
+
yirgacheffe-1.7.6.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|