yirgacheffe 1.8.0__py3-none-any.whl → 1.9.0__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 -0
- yirgacheffe/_backends/enumeration.py +20 -0
- yirgacheffe/_operators.py +44 -2
- yirgacheffe/constants.py +4 -4
- yirgacheffe/layers/base.py +39 -12
- yirgacheffe/layers/vectors.py +29 -29
- yirgacheffe/window.py +23 -8
- {yirgacheffe-1.8.0.dist-info → yirgacheffe-1.9.0.dist-info}/METADATA +7 -1
- {yirgacheffe-1.8.0.dist-info → yirgacheffe-1.9.0.dist-info}/RECORD +13 -13
- {yirgacheffe-1.8.0.dist-info → yirgacheffe-1.9.0.dist-info}/WHEEL +0 -0
- {yirgacheffe-1.8.0.dist-info → yirgacheffe-1.9.0.dist-info}/entry_points.txt +0 -0
- {yirgacheffe-1.8.0.dist-info → yirgacheffe-1.9.0.dist-info}/licenses/LICENSE +0 -0
- {yirgacheffe-1.8.0.dist-info → yirgacheffe-1.9.0.dist-info}/top_level.txt +0 -0
yirgacheffe/__init__.py
CHANGED
|
@@ -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
|
yirgacheffe/_operators.py
CHANGED
|
@@ -654,8 +654,8 @@ class LayerOperation(LayerMathMixin):
|
|
|
654
654
|
for yoffset in range(0, computation_window.ysize, self.ystep):
|
|
655
655
|
if callback:
|
|
656
656
|
callback(yoffset / computation_window.ysize)
|
|
657
|
-
step=self.ystep
|
|
658
|
-
if yoffset+step > computation_window.ysize:
|
|
657
|
+
step = self.ystep
|
|
658
|
+
if yoffset + step > computation_window.ysize:
|
|
659
659
|
step = computation_window.ysize - yoffset
|
|
660
660
|
chunk = self._eval(computation_area, projection, yoffset, step, computation_window)
|
|
661
661
|
if isinstance(chunk, (float, int)):
|
|
@@ -935,6 +935,48 @@ class LayerOperation(LayerMathMixin):
|
|
|
935
935
|
|
|
936
936
|
return result
|
|
937
937
|
|
|
938
|
+
def read_array(self, x: int, y: int, width: int, height: int) -> np.ndarray:
|
|
939
|
+
"""Read an area of pixles from the specified area of a calculated raster.
|
|
940
|
+
|
|
941
|
+
Args:
|
|
942
|
+
x: X axis offset for reading
|
|
943
|
+
y: Y axis offset for reading
|
|
944
|
+
width: Width of data to read
|
|
945
|
+
height: Height of data to read
|
|
946
|
+
|
|
947
|
+
Returns:
|
|
948
|
+
A numpy array containing the requested data. If the region of data read goes
|
|
949
|
+
beyond the bounds of the calculation that area will be filled with zeros.
|
|
950
|
+
"""
|
|
951
|
+
projection = self.map_projection
|
|
952
|
+
if projection is None:
|
|
953
|
+
raise ValueError("No map projection specified for layers in expression")
|
|
954
|
+
|
|
955
|
+
computation_window = Window(0, 0, width, height)
|
|
956
|
+
expression_area = self.area
|
|
957
|
+
pixel_scale = projection.scale
|
|
958
|
+
left = expression_area.left + (x * pixel_scale.xstep)
|
|
959
|
+
top = expression_area.top + (y * pixel_scale.ystep)
|
|
960
|
+
computation_area = Area(
|
|
961
|
+
left=left,
|
|
962
|
+
top=top,
|
|
963
|
+
right=left + (width * pixel_scale.xstep),
|
|
964
|
+
bottom=top + (height * pixel_scale.ystep),
|
|
965
|
+
)
|
|
966
|
+
|
|
967
|
+
chunks = []
|
|
968
|
+
for yoffset in range(0, height, self.ystep):
|
|
969
|
+
step = self.ystep
|
|
970
|
+
if yoffset + step > height:
|
|
971
|
+
step = height - yoffset
|
|
972
|
+
chunk = self._eval(computation_area, projection, yoffset, step, computation_window)
|
|
973
|
+
if isinstance(chunk, (float, int)):
|
|
974
|
+
chunk = backend.full((step, computation_window.xsize), chunk)
|
|
975
|
+
chunks.append(chunk)
|
|
976
|
+
res = np.vstack(chunks)
|
|
977
|
+
|
|
978
|
+
return res
|
|
979
|
+
|
|
938
980
|
class ShaderStyleOperation(LayerOperation):
|
|
939
981
|
|
|
940
982
|
def _eval(self, area, projection, index, step, target_window=None):
|
yirgacheffe/constants.py
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import pyproj
|
|
2
|
+
|
|
1
3
|
YSTEP = 512
|
|
2
4
|
MINIMUM_CHUNKS_PER_THREAD = 1
|
|
3
5
|
|
|
4
6
|
# I don't really want this here, but it's just too useful having it exposed
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
'UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AXIS["Latitude",NORTH],'\
|
|
8
|
-
'AXIS["Longitude",EAST],AUTHORITY["EPSG","4326"]]'
|
|
7
|
+
# This used to be a fixed string, but now it is at least programmatically generated
|
|
8
|
+
WGS_84_PROJECTION = pyproj.CRS.from_epsg(4326).to_wkt(version='WKT1_GDAL')
|
yirgacheffe/layers/base.py
CHANGED
|
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
from typing import Any, Sequence
|
|
3
3
|
|
|
4
4
|
import deprecation
|
|
5
|
+
from pyproj import Transformer
|
|
5
6
|
|
|
6
7
|
from .. import __version__
|
|
7
8
|
from .._operators import LayerMathMixin
|
|
@@ -332,21 +333,47 @@ class YirgacheffeLayer(LayerMathMixin):
|
|
|
332
333
|
res = self._read_array(x, y, width, height)
|
|
333
334
|
return backend.demote_array(res)
|
|
334
335
|
|
|
335
|
-
def latlng_for_pixel(self,
|
|
336
|
-
"""Get geo coords for pixel. This is relative to the set view window.
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
336
|
+
def latlng_for_pixel(self, x: int, y: int) -> tuple[float, float]:
|
|
337
|
+
"""Get geo coords for pixel. This is relative to the set view window.
|
|
338
|
+
|
|
339
|
+
Args:
|
|
340
|
+
x: X axis position within raster
|
|
341
|
+
y: Y axis position within raster
|
|
342
|
+
|
|
343
|
+
Returns:
|
|
344
|
+
A tuple containing the (latitude, longitude).
|
|
345
|
+
"""
|
|
346
|
+
projection = self.map_projection
|
|
347
|
+
if projection is None:
|
|
348
|
+
raise ValueError("Map has not projection space")
|
|
349
|
+
pixel_scale = projection.scale
|
|
350
|
+
coord_in_raster_space = (
|
|
351
|
+
(y * pixel_scale.ystep) + self.area.top,
|
|
352
|
+
(x * pixel_scale.xstep) + self.area.left,
|
|
342
353
|
)
|
|
354
|
+
transformer = Transformer.from_crs(projection.name, "EPSG:4326")
|
|
355
|
+
return transformer.transform(*coord_in_raster_space)
|
|
343
356
|
|
|
344
357
|
def pixel_for_latlng(self, lat: float, lng: float) -> tuple[int, int]:
|
|
345
358
|
"""Get pixel for geo coords. This is relative to the set view window.
|
|
346
|
-
Result is rounded down to nearest pixel.
|
|
347
|
-
|
|
348
|
-
|
|
359
|
+
Result is rounded down to nearest pixel.
|
|
360
|
+
|
|
361
|
+
Args:
|
|
362
|
+
lat: Geospatial latitude in WGS84
|
|
363
|
+
lng: Geospatial longitude in WGS84
|
|
364
|
+
|
|
365
|
+
Returns:
|
|
366
|
+
A tuple containing the x, y coordinates in pixel space.
|
|
367
|
+
"""
|
|
368
|
+
projection = self.map_projection
|
|
369
|
+
if projection is None:
|
|
370
|
+
raise ValueError("Map has not projection space")
|
|
371
|
+
|
|
372
|
+
transformer = Transformer.from_crs("EPSG:4326", projection.name)
|
|
373
|
+
x, y = transformer.transform(lng,lat)
|
|
374
|
+
|
|
375
|
+
pixel_scale = projection.scale
|
|
349
376
|
return (
|
|
350
|
-
round_down_pixels((
|
|
351
|
-
round_down_pixels((
|
|
377
|
+
round_down_pixels((x - self.area.left) / pixel_scale.xstep, abs(pixel_scale.xstep)),
|
|
378
|
+
round_down_pixels((y - self.area.top) / pixel_scale.ystep, abs(pixel_scale.ystep)),
|
|
352
379
|
)
|
yirgacheffe/layers/vectors.py
CHANGED
|
@@ -333,36 +333,36 @@ class VectorLayer(YirgacheffeLayer):
|
|
|
333
333
|
self._anchor = anchor
|
|
334
334
|
self._envelopes = envelopes
|
|
335
335
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
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
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
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
|
|
yirgacheffe/window.py
CHANGED
|
@@ -4,37 +4,50 @@ import sys
|
|
|
4
4
|
from collections import namedtuple
|
|
5
5
|
from dataclasses import dataclass
|
|
6
6
|
|
|
7
|
+
import pyproj
|
|
8
|
+
|
|
7
9
|
PixelScale = namedtuple('PixelScale', ['xstep', 'ystep'])
|
|
8
10
|
|
|
9
|
-
@dataclass
|
|
10
11
|
class MapProjection:
|
|
11
12
|
"""Records the map projection and the size of the pixels in a layer.
|
|
12
13
|
|
|
13
14
|
This superceeeds the old PixelScale class, which will be removed in version 2.0.
|
|
14
15
|
|
|
15
16
|
Args:
|
|
16
|
-
name: The map projection used.
|
|
17
|
+
name: The map projection used in WKT format, or as "epsg:xxxx" or "esri:xxxx".
|
|
17
18
|
xstep: The number of units horizontal distance a step of one pixel makes in the map projection.
|
|
18
19
|
ystep: The number of units vertical distance a step of one pixel makes in the map projection.
|
|
19
20
|
|
|
20
21
|
Attributes:
|
|
21
|
-
name: The map projection used.
|
|
22
|
+
name: The map projection used in WKT format.
|
|
22
23
|
xstep: The number of units horizontal distance a step of one pixel makes in the map projection.
|
|
23
24
|
ystep: The number of units vertical distance a step of one pixel makes in the map projection.
|
|
24
25
|
"""
|
|
25
26
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
def __init__(self, projection_string: str, xstep: float, ystep: float) -> None:
|
|
28
|
+
try:
|
|
29
|
+
self.crs = pyproj.CRS.from_string(projection_string)
|
|
30
|
+
except pyproj.exceptions.CRSError as exc:
|
|
31
|
+
raise ValueError(f"Invalid projection: {projection_string}") from exc
|
|
32
|
+
self.xstep = xstep
|
|
33
|
+
self.ystep = ystep
|
|
29
34
|
|
|
30
35
|
def __eq__(self, other) -> bool:
|
|
31
36
|
if other is None:
|
|
32
37
|
return True
|
|
33
38
|
# to avoid circular dependancies
|
|
34
39
|
from .rounding import are_pixel_scales_equal_enough # pylint: disable=C0415
|
|
35
|
-
return (self.
|
|
40
|
+
return (self.crs == other.crs) and \
|
|
36
41
|
are_pixel_scales_equal_enough([self.scale, other.scale])
|
|
37
42
|
|
|
43
|
+
@property
|
|
44
|
+
def name(self) -> str:
|
|
45
|
+
return self.crs.to_wkt()
|
|
46
|
+
|
|
47
|
+
@property
|
|
48
|
+
def epsg(self) -> int | None:
|
|
49
|
+
return self.crs.to_epsg()
|
|
50
|
+
|
|
38
51
|
@property
|
|
39
52
|
def scale(self) -> PixelScale:
|
|
40
53
|
return PixelScale(self.xstep, self.ystep)
|
|
@@ -72,7 +85,9 @@ class Area:
|
|
|
72
85
|
def __hash__(self):
|
|
73
86
|
return (self.left, self.top, self.right, self.bottom).__hash__()
|
|
74
87
|
|
|
75
|
-
def __eq__(self, other) -> bool:
|
|
88
|
+
def __eq__(self, other: object) -> bool:
|
|
89
|
+
if not isinstance(other, Area):
|
|
90
|
+
return False
|
|
76
91
|
return math.isclose(self.left, other.left, abs_tol=1e-09) and \
|
|
77
92
|
math.isclose(self.right, other.right, abs_tol=1e-09) and \
|
|
78
93
|
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.
|
|
3
|
+
Version: 1.9.0
|
|
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
|
|
@@ -27,6 +27,7 @@ Requires-Dist: dill
|
|
|
27
27
|
Requires-Dist: deprecation
|
|
28
28
|
Requires-Dist: tomli
|
|
29
29
|
Requires-Dist: h3
|
|
30
|
+
Requires-Dist: pyproj
|
|
30
31
|
Provides-Extra: mlx
|
|
31
32
|
Requires-Dist: mlx; extra == "mlx"
|
|
32
33
|
Provides-Extra: dev
|
|
@@ -44,6 +45,11 @@ Dynamic: license-file
|
|
|
44
45
|
|
|
45
46
|
# Yirgacheffe: a declarative geospatial library for Python to make data-science with maps easier
|
|
46
47
|
|
|
48
|
+
[](https://github.com/quantifyearth/yirgacheffe/actions)
|
|
49
|
+
[](https://yirgacheffe.org)
|
|
50
|
+
[](https://pypi.org/project/yirgacheffe/)
|
|
51
|
+
|
|
52
|
+
|
|
47
53
|
## Overview
|
|
48
54
|
|
|
49
55
|
Yirgacheffe is an attempt to wrap raster and polygon geospatial datasets such that you can do computational work on them as a whole or at the pixel level, but without having to do a lot of the grunt work of working out where you need to be in rasters, or managing how much you can load into memory safely.
|
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
yirgacheffe/__init__.py,sha256=
|
|
1
|
+
yirgacheffe/__init__.py,sha256=OOzfXtafPoDpAsNRC08BXjmwv0hBp-mNFCjwplGs9lY,668
|
|
2
2
|
yirgacheffe/_core.py,sha256=AU6tlqovBV_l1dNZs6AlHSw59Z0U6pStUaQZvJGiLhM,5721
|
|
3
|
-
yirgacheffe/_operators.py,sha256=
|
|
4
|
-
yirgacheffe/constants.py,sha256=
|
|
3
|
+
yirgacheffe/_operators.py,sha256=cnJgnfnfIRwrPB6sX2TVU_-s4eDyhZCPyemwIBFurxU,37723
|
|
4
|
+
yirgacheffe/constants.py,sha256=bKUjOGNj19zwggV79lJgK7tiv51DH2-rgNOKswl2gvQ,293
|
|
5
5
|
yirgacheffe/operators.py,sha256=nw-BpnAwTjCwFtjosa8wKd2MGUuC0PJR5jACFdLhqCg,412
|
|
6
6
|
yirgacheffe/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
7
|
yirgacheffe/rounding.py,sha256=ZNuAaxsWfzYETC_G9H5weY1ZOci2pihEKTVrUiIqfZw,2257
|
|
8
|
-
yirgacheffe/window.py,sha256
|
|
8
|
+
yirgacheffe/window.py,sha256=QuyBLOwKFI0XkEQ4Bd2hdELPbJSfHL7mt5KSi7CIHcE,9505
|
|
9
9
|
yirgacheffe/_backends/__init__.py,sha256=jN-2iRrHStnPI6cNL7XhwhsROtI0EaGfIrbF5c-ECV0,334
|
|
10
|
-
yirgacheffe/_backends/enumeration.py,sha256=
|
|
10
|
+
yirgacheffe/_backends/enumeration.py,sha256=9bcCXz9Ssrh8Oh1iazodkx6Gm2kQBi9HQ9z9zehS4AE,1806
|
|
11
11
|
yirgacheffe/_backends/mlx.py,sha256=U1gl1lK1mZXLEET6ylF1TNs6WJ0PBEvfSk7ppn28n8w,6203
|
|
12
12
|
yirgacheffe/_backends/numpy.py,sha256=Gxx49JJH79GFEkKIpV6IyjCUcdtN5-qLlzRfylzKhS4,4142
|
|
13
13
|
yirgacheffe/layers/__init__.py,sha256=mYKjw5YTcMNv_hMy7a6K4yRzIuNUbR8WuBTw4WIAmSk,435
|
|
14
14
|
yirgacheffe/layers/area.py,sha256=wJcMHbLJBaXS4BeFbu5rYeKfgu3gvaE9hwQ5j6aw-y4,3976
|
|
15
|
-
yirgacheffe/layers/base.py,sha256=
|
|
15
|
+
yirgacheffe/layers/base.py,sha256=EkfR3DOQ1I_tQZfpOSczs-sWFSP6uUMXdiB7xspfd4E,14954
|
|
16
16
|
yirgacheffe/layers/constant.py,sha256=gtkQ98Z01CYYDgFElswtRZY4ZG3UnS5NIAoIVue5ufk,1481
|
|
17
17
|
yirgacheffe/layers/group.py,sha256=yaqf-ra_Vh59yrWcz7-OvJ1fBnTcBXZd18AfRDN5Ymo,16157
|
|
18
18
|
yirgacheffe/layers/h3layer.py,sha256=Rq1bFo7CApIh5NdBcV7hSj3hm-DszY79nhYsTRAvJ_g,9916
|
|
19
19
|
yirgacheffe/layers/rasters.py,sha256=zBE9uXm6LvAQF2_XdQzcOgJQOQWGmuPflY5JNDrUf3k,13527
|
|
20
20
|
yirgacheffe/layers/rescaled.py,sha256=gEFbXeYxX1nVn7eQYmbGww90_yc5ENmgQrD_WxXxpQE,3352
|
|
21
|
-
yirgacheffe/layers/vectors.py,sha256=
|
|
22
|
-
yirgacheffe-1.
|
|
23
|
-
yirgacheffe-1.
|
|
24
|
-
yirgacheffe-1.
|
|
25
|
-
yirgacheffe-1.
|
|
26
|
-
yirgacheffe-1.
|
|
27
|
-
yirgacheffe-1.
|
|
21
|
+
yirgacheffe/layers/vectors.py,sha256=A27kuTr0C9BZhHG0-cplNEa7aSNcse37Pm9xTjEzv-c,19990
|
|
22
|
+
yirgacheffe-1.9.0.dist-info/licenses/LICENSE,sha256=dNSHwUCJr6axStTKDEdnJtfmDdFqlE3h1NPCveqPfnY,757
|
|
23
|
+
yirgacheffe-1.9.0.dist-info/METADATA,sha256=ciRPPO-k-vbyd0gbg_u-uinc739ZoPuazQna9MpluCM,24186
|
|
24
|
+
yirgacheffe-1.9.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
25
|
+
yirgacheffe-1.9.0.dist-info/entry_points.txt,sha256=j4KgHXbVGbGyfTySc1ypBdERpfihO4WNjppvCdE9HjE,52
|
|
26
|
+
yirgacheffe-1.9.0.dist-info/top_level.txt,sha256=9DBFlKO2Ld3hG6TuE3qOTd3Tt8ugTiXil4AN4Wr9_y0,12
|
|
27
|
+
yirgacheffe-1.9.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|