yirgacheffe 1.8.0__tar.gz → 1.8.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. {yirgacheffe-1.8.0/yirgacheffe.egg-info → yirgacheffe-1.8.1}/PKG-INFO +1 -1
  2. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/pyproject.toml +1 -1
  3. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/tests/test_area.py +3 -0
  4. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/tests/test_auto_windowing.py +2 -2
  5. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/tests/test_intersection.py +30 -0
  6. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/tests/test_union.py +11 -0
  7. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/yirgacheffe/__init__.py +1 -0
  8. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/yirgacheffe/_backends/enumeration.py +20 -0
  9. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/yirgacheffe/layers/vectors.py +29 -29
  10. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/yirgacheffe/window.py +3 -1
  11. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1/yirgacheffe.egg-info}/PKG-INFO +1 -1
  12. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/LICENSE +0 -0
  13. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/MANIFEST.in +0 -0
  14. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/README.md +0 -0
  15. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/setup.cfg +0 -0
  16. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/tests/test_base.py +0 -0
  17. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/tests/test_constants.py +0 -0
  18. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/tests/test_datatypes.py +0 -0
  19. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/tests/test_group.py +0 -0
  20. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/tests/test_h3layer.py +0 -0
  21. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/tests/test_multiband.py +0 -0
  22. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/tests/test_nodata.py +0 -0
  23. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/tests/test_openers.py +0 -0
  24. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/tests/test_operators.py +0 -0
  25. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/tests/test_optimisation.py +0 -0
  26. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/tests/test_parallel_operators.py +0 -0
  27. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/tests/test_pickle.py +0 -0
  28. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/tests/test_projection.py +0 -0
  29. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/tests/test_raster.py +0 -0
  30. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/tests/test_rescaling.py +0 -0
  31. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/tests/test_rounding.py +0 -0
  32. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/tests/test_save_with_window.py +0 -0
  33. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/tests/test_sum_with_window.py +0 -0
  34. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/tests/test_uniform_area_layer.py +0 -0
  35. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/tests/test_vectors.py +0 -0
  36. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/tests/test_window.py +0 -0
  37. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/yirgacheffe/_backends/__init__.py +0 -0
  38. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/yirgacheffe/_backends/mlx.py +0 -0
  39. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/yirgacheffe/_backends/numpy.py +0 -0
  40. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/yirgacheffe/_core.py +0 -0
  41. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/yirgacheffe/_operators.py +0 -0
  42. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/yirgacheffe/constants.py +0 -0
  43. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/yirgacheffe/layers/__init__.py +0 -0
  44. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/yirgacheffe/layers/area.py +0 -0
  45. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/yirgacheffe/layers/base.py +0 -0
  46. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/yirgacheffe/layers/constant.py +0 -0
  47. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/yirgacheffe/layers/group.py +0 -0
  48. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/yirgacheffe/layers/h3layer.py +0 -0
  49. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/yirgacheffe/layers/rasters.py +0 -0
  50. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/yirgacheffe/layers/rescaled.py +0 -0
  51. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/yirgacheffe/operators.py +0 -0
  52. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/yirgacheffe/py.typed +0 -0
  53. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/yirgacheffe/rounding.py +0 -0
  54. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/yirgacheffe.egg-info/SOURCES.txt +0 -0
  55. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/yirgacheffe.egg-info/dependency_links.txt +0 -0
  56. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/yirgacheffe.egg-info/entry_points.txt +0 -0
  57. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/yirgacheffe.egg-info/requires.txt +0 -0
  58. {yirgacheffe-1.8.0 → yirgacheffe-1.8.1}/yirgacheffe.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: yirgacheffe
3
- Version: 1.8.0
3
+ Version: 1.8.1
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
@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
6
6
 
7
7
  [project]
8
8
  name = "yirgacheffe"
9
- version = "1.8.0"
9
+ version = "1.8.1"
10
10
  description = "Abstraction of gdal datasets for doing basic math operations"
11
11
  readme = "README.md"
12
12
  authors = [{ name = "Michael Dales", email = "mwd24@cam.ac.uk" }]
@@ -29,3 +29,6 @@ def test_global_area() -> None:
29
29
  other_area = Area(-10.0, 10.0, 10.0, -10.0)
30
30
  assert area.overlaps(other_area)
31
31
  assert other_area.overlaps(area)
32
+
33
+ def test_wrong_types_on_eq() -> None:
34
+ assert Area(-10, 10, 10, -10) != 42
@@ -4,7 +4,7 @@ import tempfile
4
4
  import numpy as np
5
5
  import pytest
6
6
 
7
- import yirgacheffe
7
+ import yirgacheffe as yg
8
8
  from tests.helpers import gdal_dataset_with_data, make_vectors_with_mutlile_ids
9
9
  from yirgacheffe.layers import ConstantLayer, RasterLayer, VectorLayer
10
10
  from yirgacheffe.window import Area
@@ -315,7 +315,7 @@ def test_vector_layers_multiply() -> None:
315
315
  expected = np.array([[2, 0], [0, 8]])
316
316
  assert (expected == actual).all()
317
317
 
318
- @pytest.mark.skipif(yirgacheffe._backends.BACKEND != "NUMPY", reason="Only applies for numpy")
318
+ @pytest.mark.skipif(yg._backends.BACKEND != "NUMPY", reason="Only applies for numpy")
319
319
  def test_parallel_save_windows() -> None:
320
320
  data1 = np.array([[1, 2], [3, 4]])
321
321
  data2 = np.array([[10, 20, 30, 40], [50, 60, 70, 80], [90, 100, 110, 120], [130, 140, 150, 160]])
@@ -59,6 +59,9 @@ def test_find_intersection_with_constant() -> None:
59
59
  intersection = RasterLayer.find_intersection(layers)
60
60
  assert intersection == layers[0].area
61
61
 
62
+ for layer in layers:
63
+ layer.set_window_for_intersection(intersection)
64
+
62
65
  def test_find_intersection_with_vector_unbound() -> None:
63
66
  with tempfile.TemporaryDirectory() as tempdir:
64
67
  path = Path(tempdir) / "test.gpkg"
@@ -74,6 +77,10 @@ def test_find_intersection_with_vector_unbound() -> None:
74
77
  intersection = RasterLayer.find_intersection(layers)
75
78
  assert intersection == vector.area
76
79
 
80
+ raster.set_window_for_intersection(intersection)
81
+ with pytest.raises(ValueError):
82
+ vector.set_window_for_intersection(intersection)
83
+
77
84
  def test_find_intersection_with_vector_bound() -> None:
78
85
  with tempfile.TemporaryDirectory() as tempdir:
79
86
  path = Path(tempdir) / "test.gpkg"
@@ -89,6 +96,29 @@ def test_find_intersection_with_vector_bound() -> None:
89
96
  intersection = RasterLayer.find_intersection(layers)
90
97
  assert intersection == vector.area
91
98
 
99
+ for layer in layers:
100
+ layer.set_window_for_intersection(intersection)
101
+
102
+ def test_find_intersection_with_vector_awkward_rounding() -> None:
103
+ with tempfile.TemporaryDirectory() as tempdir:
104
+ path = Path(tempdir) / "test.gpkg"
105
+ area = Area(left=-90, top=45, right=90, bottom=-45)
106
+ make_vectors_with_id(42, {area}, path)
107
+ assert path.exists
108
+
109
+ raster = RasterLayer(gdal_dataset_of_region(Area(left=-180, top=90, right=180, bottom=-90), 18.0))
110
+ vector = VectorLayer.layer_from_file(path, None, raster.map_projection.scale, raster.map_projection.name)
111
+
112
+ rounded_area = Area(left=-90, top=54, right=90, bottom=-54)
113
+ assert vector.area == rounded_area
114
+
115
+ layers = [raster, vector]
116
+ intersection = RasterLayer.find_intersection(layers)
117
+ assert intersection == vector.area
118
+
119
+ for layer in layers:
120
+ layer.set_window_for_intersection(intersection)
121
+
92
122
  def test_find_intersection_different_pixel_pitch() -> None:
93
123
  layers = [
94
124
  RasterLayer(gdal_dataset_of_region(Area(-10, 10, 10, -10), 0.02)),
@@ -49,6 +49,9 @@ def test_find_union_distinct() -> None:
49
49
  union = RasterLayer.find_union(layers)
50
50
  assert union == Area(-110, 10, 110, -10)
51
51
 
52
+ for layer in layers:
53
+ layer.set_window_for_union(union)
54
+
52
55
  def test_find_union_with_null() -> None:
53
56
  layers = [
54
57
  RasterLayer(gdal_dataset_of_region(Area(-10, 10, 10, -10), 0.02)),
@@ -80,6 +83,11 @@ def test_find_union_with_vector_unbound() -> None:
80
83
  union = RasterLayer.find_union(layers)
81
84
  assert union == vector.area
82
85
 
86
+ raster.set_window_for_union(union)
87
+ with pytest.raises(ValueError):
88
+ vector.set_window_for_union(union)
89
+
90
+
83
91
  def test_find_union_with_vector_bound() -> None:
84
92
  with tempfile.TemporaryDirectory() as tempdir:
85
93
  path = Path(tempdir) / "test.gpkg"
@@ -95,6 +103,9 @@ def test_find_union_with_vector_bound() -> None:
95
103
  union = RasterLayer.find_union(layers)
96
104
  assert union == vector.area
97
105
 
106
+ for layer in layers:
107
+ layer.set_window_for_union(union)
108
+
98
109
  @pytest.mark.parametrize("scale", [0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09])
99
110
  def test_set_union_self(scale) -> None:
100
111
  layer = RasterLayer(gdal_dataset_of_region(Area(-10, 10, 10, -10), scale))
@@ -15,5 +15,6 @@ except ModuleNotFoundError:
15
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
  from .window import Area, MapProjection, Window
18
+ from ._backends.enumeration import dtype as DataType
18
19
 
19
20
  gdal.UseExceptions()
@@ -41,6 +41,26 @@ class operators(Enum):
41
41
  ISNAN = 36
42
42
 
43
43
  class dtype(Enum):
44
+ """Represents the type of data returned by a layer.
45
+
46
+ This enumeration defines the valid data types supported by Yirgacheffe, and is
47
+ what is returned by calling `datatype` on a layer or expression, and can be
48
+ passed to `astype` to convert values between types.
49
+
50
+ Attributes:
51
+ Float32: 32 bit floating point value
52
+ Float64: 64 bit floating point value
53
+ Byte: Unsigned 8 bit integer value
54
+ Int8: Signed 8 bit integer value
55
+ Int16: Signed 16 bit integer value
56
+ Int32: Signed 32 bit integer value
57
+ Int64: Signed 64 bit integer value
58
+ UInt8: Unsigned 8 bit integer value
59
+ UInt16: Unsigned 16 bit integer value
60
+ UInt32: Unsigned 32 bit integer value
61
+ UInt64: Unsigned 64 bit integer value
62
+ """
63
+
44
64
  Float32 = gdal.GDT_Float32
45
65
  Float64 = gdal.GDT_Float64
46
66
  Byte = gdal.GDT_Byte
@@ -333,36 +333,36 @@ class VectorLayer(YirgacheffeLayer):
333
333
  self._anchor = anchor
334
334
  self._envelopes = envelopes
335
335
 
336
- # if projection is not None:
337
- # # Get the area, but scale it to the pixel resolution that we're using. Note that
338
- # # the pixel scale GDAL uses can have -ve values, but those will mess up the
339
- # # ceil/floor math, so we use absolute versions when trying to round.
340
- # abs_xstep, abs_ystep = abs(projection.xstep), abs(projection.ystep)
341
- #
342
- # # Lacking any other reference, we will make the raster align with
343
- # # (0.0, 0.0), if sometimes we want to align with an existing raster, so if
344
- # # an anchor is specified, ensure we use that as our pixel space alignment
345
- # x_anchor = anchor[0]
346
- # y_anchor = anchor[1]
347
- # left_shift = x_anchor - abs_xstep
348
- # right_shift = x_anchor
349
- # top_shift = y_anchor
350
- # bottom_shift = y_anchor - abs_ystep
351
- #
352
- # area = Area(
353
- # left=(floor((min(x[0] for x in envelopes) - left_shift) / abs_xstep) * abs_xstep) + left_shift,
354
- # top=(ceil((max(x[3] for x in envelopes) - top_shift) / abs_ystep) * abs_ystep) + top_shift,
355
- # right=(ceil((max(x[1] for x in envelopes) - right_shift) / abs_xstep) * abs_xstep) + right_shift,
356
- # bottom=(floor((min(x[2] for x in envelopes) - bottom_shift) / abs_ystep) * abs_ystep) + bottom_shift,
357
- # )
358
- # else:
336
+ if projection is not None:
337
+ # Get the area, but scale it to the pixel resolution that we're using. Note that
338
+ # the pixel scale GDAL uses can have -ve values, but those will mess up the
339
+ # ceil/floor math, so we use absolute versions when trying to round.
340
+ abs_xstep, abs_ystep = abs(projection.xstep), abs(projection.ystep)
341
+
342
+ # Lacking any other reference, we will make the raster align with
343
+ # (0.0, 0.0), if sometimes we want to align with an existing raster, so if
344
+ # an anchor is specified, ensure we use that as our pixel space alignment
345
+ x_anchor = anchor[0]
346
+ y_anchor = anchor[1]
347
+ left_shift = x_anchor - abs_xstep
348
+ right_shift = x_anchor
349
+ top_shift = y_anchor
350
+ bottom_shift = y_anchor - abs_ystep
351
+
352
+ area = Area(
353
+ left=(floor((min(x[0] for x in envelopes) - left_shift) / abs_xstep) * abs_xstep) + left_shift,
354
+ top=(ceil((max(x[3] for x in envelopes) - top_shift) / abs_ystep) * abs_ystep) + top_shift,
355
+ right=(ceil((max(x[1] for x in envelopes) - right_shift) / abs_xstep) * abs_xstep) + right_shift,
356
+ bottom=(floor((min(x[2] for x in envelopes) - bottom_shift) / abs_ystep) * abs_ystep) + bottom_shift,
357
+ )
358
+ else:
359
359
  # If we don't have a projection just go with the idealised area
360
- area = Area(
361
- left=floor(min(x[0] for x in envelopes)),
362
- top=ceil(max(x[3] for x in envelopes)),
363
- right=ceil(max(x[1] for x in envelopes)),
364
- bottom=floor(min(x[2] for x in envelopes)),
365
- )
360
+ area = Area(
361
+ left=floor(min(x[0] for x in envelopes)),
362
+ top=ceil(max(x[3] for x in envelopes)),
363
+ right=ceil(max(x[1] for x in envelopes)),
364
+ bottom=floor(min(x[2] for x in envelopes)),
365
+ )
366
366
 
367
367
  super().__init__(area, projection)
368
368
 
@@ -72,7 +72,9 @@ class Area:
72
72
  def __hash__(self):
73
73
  return (self.left, self.top, self.right, self.bottom).__hash__()
74
74
 
75
- def __eq__(self, other) -> bool:
75
+ def __eq__(self, other: object) -> bool:
76
+ if not isinstance(other, Area):
77
+ return False
76
78
  return math.isclose(self.left, other.left, abs_tol=1e-09) and \
77
79
  math.isclose(self.right, other.right, abs_tol=1e-09) and \
78
80
  math.isclose(self.top, other.top, abs_tol=1e-09) and \
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: yirgacheffe
3
- Version: 1.8.0
3
+ Version: 1.8.1
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
File without changes
File without changes
File without changes
File without changes