geoarrow-pyarrow 0.1.2__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.
- geoarrow/pyarrow/__init__.py +127 -0
- geoarrow/pyarrow/_array.py +184 -0
- geoarrow/pyarrow/_compute.py +633 -0
- geoarrow/pyarrow/_kernel.py +120 -0
- geoarrow/pyarrow/_scalar.py +122 -0
- geoarrow/pyarrow/_type.py +728 -0
- geoarrow/pyarrow/dataset.py +524 -0
- geoarrow/pyarrow/io.py +494 -0
- geoarrow_pyarrow-0.1.2.dist-info/METADATA +19 -0
- geoarrow_pyarrow-0.1.2.dist-info/RECORD +12 -0
- geoarrow_pyarrow-0.1.2.dist-info/WHEEL +5 -0
- geoarrow_pyarrow-0.1.2.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Contains pyarrow integration for the geoarrow Python bindings.
|
|
3
|
+
|
|
4
|
+
Examples
|
|
5
|
+
--------
|
|
6
|
+
|
|
7
|
+
>>> import geoarrow.pyarrow as ga
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from geoarrow.c.lib import GeometryType, Dimensions, CoordType, EdgeType, CrsType
|
|
11
|
+
|
|
12
|
+
from geoarrow.pyarrow._type import (
|
|
13
|
+
GeometryExtensionType,
|
|
14
|
+
WktType,
|
|
15
|
+
WkbType,
|
|
16
|
+
PointType,
|
|
17
|
+
LinestringType,
|
|
18
|
+
PolygonType,
|
|
19
|
+
MultiPointType,
|
|
20
|
+
MultiLinestringType,
|
|
21
|
+
MultiPolygonType,
|
|
22
|
+
wkb,
|
|
23
|
+
large_wkb,
|
|
24
|
+
wkt,
|
|
25
|
+
large_wkt,
|
|
26
|
+
point,
|
|
27
|
+
linestring,
|
|
28
|
+
polygon,
|
|
29
|
+
multipoint,
|
|
30
|
+
multilinestring,
|
|
31
|
+
multipolygon,
|
|
32
|
+
extension_type,
|
|
33
|
+
geometry_type_common,
|
|
34
|
+
register_extension_types,
|
|
35
|
+
unregister_extension_types,
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
from geoarrow.pyarrow._kernel import Kernel
|
|
39
|
+
|
|
40
|
+
from geoarrow.pyarrow._array import array
|
|
41
|
+
|
|
42
|
+
from geoarrow.pyarrow import _scalar
|
|
43
|
+
|
|
44
|
+
from geoarrow.pyarrow._compute import (
|
|
45
|
+
parse_all,
|
|
46
|
+
as_wkt,
|
|
47
|
+
as_wkb,
|
|
48
|
+
infer_type_common,
|
|
49
|
+
as_geoarrow,
|
|
50
|
+
format_wkt,
|
|
51
|
+
make_point,
|
|
52
|
+
unique_geometry_types,
|
|
53
|
+
box,
|
|
54
|
+
box_agg,
|
|
55
|
+
with_coord_type,
|
|
56
|
+
with_crs,
|
|
57
|
+
with_dimensions,
|
|
58
|
+
with_edge_type,
|
|
59
|
+
with_geometry_type,
|
|
60
|
+
rechunk,
|
|
61
|
+
point_coords,
|
|
62
|
+
to_geopandas,
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
__all__ = [
|
|
66
|
+
"GeometryType",
|
|
67
|
+
"Dimensions",
|
|
68
|
+
"CoordType",
|
|
69
|
+
"EdgeType",
|
|
70
|
+
"CrsType",
|
|
71
|
+
"GeometryExtensionType",
|
|
72
|
+
"WktType",
|
|
73
|
+
"WkbType",
|
|
74
|
+
"PointType",
|
|
75
|
+
"LinestringType",
|
|
76
|
+
"PolygonType",
|
|
77
|
+
"MultiPointType",
|
|
78
|
+
"MultiLinestringType",
|
|
79
|
+
"MultiPolygonType",
|
|
80
|
+
"wkb",
|
|
81
|
+
"large_wkb",
|
|
82
|
+
"wkt",
|
|
83
|
+
"large_wkt",
|
|
84
|
+
"point",
|
|
85
|
+
"linestring",
|
|
86
|
+
"polygon",
|
|
87
|
+
"multipoint",
|
|
88
|
+
"multilinestring",
|
|
89
|
+
"multipolygon",
|
|
90
|
+
"extension_type",
|
|
91
|
+
"geometry_type_common",
|
|
92
|
+
"register_extension_types",
|
|
93
|
+
"unregister_extension_types",
|
|
94
|
+
"Kernel",
|
|
95
|
+
"array",
|
|
96
|
+
"parse_all",
|
|
97
|
+
"as_wkt",
|
|
98
|
+
"as_wkb",
|
|
99
|
+
"infer_type_common",
|
|
100
|
+
"as_geoarrow",
|
|
101
|
+
"format_wkt",
|
|
102
|
+
"make_point",
|
|
103
|
+
"unique_geometry_types",
|
|
104
|
+
"box",
|
|
105
|
+
"box_agg",
|
|
106
|
+
"with_coord_type",
|
|
107
|
+
"with_crs",
|
|
108
|
+
"with_dimensions",
|
|
109
|
+
"with_edge_type",
|
|
110
|
+
"with_geometry_type",
|
|
111
|
+
"rechunk",
|
|
112
|
+
"point_coords",
|
|
113
|
+
"to_geopandas",
|
|
114
|
+
"_scalar",
|
|
115
|
+
]
|
|
116
|
+
|
|
117
|
+
try:
|
|
118
|
+
register_extension_types()
|
|
119
|
+
except Exception as e:
|
|
120
|
+
import warnings
|
|
121
|
+
|
|
122
|
+
warnings.warn(
|
|
123
|
+
"Failed to register one or more extension types.\n"
|
|
124
|
+
"If this warning appears from pytest, you may have to re-run with --import-mode=importlib.\n"
|
|
125
|
+
"You may also be able to run `unregister_extension_types()` and `register_extension_types()`.\n"
|
|
126
|
+
f"The original error was {e}"
|
|
127
|
+
)
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import pyarrow as pa
|
|
2
|
+
import pyarrow_hotfix as _ # noqa: F401
|
|
3
|
+
|
|
4
|
+
from geoarrow.c import lib
|
|
5
|
+
|
|
6
|
+
from geoarrow.pyarrow._kernel import Kernel
|
|
7
|
+
from geoarrow.pyarrow._type import (
|
|
8
|
+
GeometryExtensionType,
|
|
9
|
+
wkb,
|
|
10
|
+
wkt,
|
|
11
|
+
large_wkb,
|
|
12
|
+
large_wkt,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class GeometryExtensionArray(pa.ExtensionArray):
|
|
17
|
+
def geobuffers(self):
|
|
18
|
+
import numpy as np
|
|
19
|
+
|
|
20
|
+
cschema = lib.SchemaHolder()
|
|
21
|
+
self.type._export_to_c(cschema._addr())
|
|
22
|
+
carray = lib.ArrayHolder()
|
|
23
|
+
self._export_to_c(carray._addr())
|
|
24
|
+
|
|
25
|
+
array_view = lib.CArrayView(carray, cschema)
|
|
26
|
+
buffers = array_view.buffers()
|
|
27
|
+
return [np.array(b) if b is not None else None for b in buffers]
|
|
28
|
+
|
|
29
|
+
def __repr__(self):
|
|
30
|
+
n_values_to_show = 10
|
|
31
|
+
max_width = 70
|
|
32
|
+
|
|
33
|
+
if len(self) > n_values_to_show:
|
|
34
|
+
n_extra = len(self) - n_values_to_show
|
|
35
|
+
value_s = "values" if n_extra != 1 else "value"
|
|
36
|
+
head = self[: int(n_values_to_show / 2)]
|
|
37
|
+
mid = f"...{n_extra} {value_s}..."
|
|
38
|
+
tail = self[int(-n_values_to_show / 2) :]
|
|
39
|
+
else:
|
|
40
|
+
head = self
|
|
41
|
+
mid = ""
|
|
42
|
+
tail = self[:0]
|
|
43
|
+
|
|
44
|
+
try:
|
|
45
|
+
kernel = Kernel.format_wkt(self.type, max_element_size_bytes=max_width)
|
|
46
|
+
head = kernel.push(head)
|
|
47
|
+
tail = kernel.push(tail)
|
|
48
|
+
except Exception as e:
|
|
49
|
+
err = f"* 1 or more display values failed to parse\n* {str(e)}"
|
|
50
|
+
type_name = type(self).__name__
|
|
51
|
+
super_repr = super().__repr__()
|
|
52
|
+
return f"{type_name}:{repr(self.type)}[{len(self)}]\n{err}\n{super_repr}"
|
|
53
|
+
|
|
54
|
+
head_str = [f"<{item.as_py()}>" for item in head]
|
|
55
|
+
tail_str = [f"<{item.as_py()}>" for item in tail]
|
|
56
|
+
for i in range(len(head)):
|
|
57
|
+
if len(head_str[i]) > max_width:
|
|
58
|
+
head_str[i] = f"{head_str[i][:(max_width - 4)]}...>"
|
|
59
|
+
for i in range(len(tail)):
|
|
60
|
+
if len(tail_str[i]) > max_width:
|
|
61
|
+
tail_str[i] = f"{tail_str[i][:(max_width - 4)]}...>"
|
|
62
|
+
|
|
63
|
+
type_name = type(self).__name__
|
|
64
|
+
head_str = "\n".join(head_str)
|
|
65
|
+
tail_str = "\n".join(tail_str)
|
|
66
|
+
items_str = f"{head_str}\n{mid}\n{tail_str}"
|
|
67
|
+
|
|
68
|
+
return f"{type_name}:{repr(self.type)}[{len(self)}]\n{items_str}".strip()
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
class PointArray(GeometryExtensionArray):
|
|
72
|
+
pass
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class LinestringArray(GeometryExtensionArray):
|
|
76
|
+
pass
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
class PolygonArray(GeometryExtensionArray):
|
|
80
|
+
pass
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class MultiPointArray(GeometryExtensionArray):
|
|
84
|
+
pass
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class MultiLinestringArray(GeometryExtensionArray):
|
|
88
|
+
pass
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
class MultiPolygonArray(GeometryExtensionArray):
|
|
92
|
+
pass
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def array_cls_from_name(name):
|
|
96
|
+
if name == "geoarrow.wkb":
|
|
97
|
+
return GeometryExtensionArray
|
|
98
|
+
elif name == "geoarrow.wkt":
|
|
99
|
+
return GeometryExtensionArray
|
|
100
|
+
elif name == "geoarrow.point":
|
|
101
|
+
return PointArray
|
|
102
|
+
elif name == "geoarrow.linestring":
|
|
103
|
+
return LinestringArray
|
|
104
|
+
elif name == "geoarrow.polygon":
|
|
105
|
+
return PolygonArray
|
|
106
|
+
elif name == "geoarrow.multipoint":
|
|
107
|
+
return MultiPointArray
|
|
108
|
+
elif name == "geoarrow.multilinestring":
|
|
109
|
+
return MultiLinestringArray
|
|
110
|
+
elif name == "geoarrow.multipolygon":
|
|
111
|
+
return MultiPolygonArray
|
|
112
|
+
else:
|
|
113
|
+
raise ValueError(f'Expected valid extension name but got "{name}"')
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
# Inject array_cls_from_name exactly once to avoid circular import
|
|
117
|
+
if GeometryExtensionType._array_cls_from_name is None:
|
|
118
|
+
GeometryExtensionType._array_cls_from_name = array_cls_from_name
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def array(obj, type_=None, *args, **kwargs) -> GeometryExtensionArray:
|
|
122
|
+
"""Attempt to create an Array or ChunkedArray with a geoarrow extension type
|
|
123
|
+
from ``obj``. This constructor attempts to perform the fewest transformations
|
|
124
|
+
possible (i.e., WKB is left as WKB, WKT is left as WKT), whereas
|
|
125
|
+
:func:`geoarrow.pyarrow.as_geoarrow` actively attempts a conversion to
|
|
126
|
+
a geoarrow-encoding based on a common geometry type. GeoPandas objects are
|
|
127
|
+
supported. This implementation relies heavily on ``pyarrow.array()`` and has
|
|
128
|
+
similar behaviour.
|
|
129
|
+
|
|
130
|
+
>>> import geoarrow.pyarrow as ga
|
|
131
|
+
>>> ga.array(["POINT (0 1)"])
|
|
132
|
+
GeometryExtensionArray:WktType(geoarrow.wkt)[1]
|
|
133
|
+
<POINT (0 1)>
|
|
134
|
+
>>> ga.as_geoarrow(["POINT (0 1)"])
|
|
135
|
+
PointArray:PointType(geoarrow.point)[1]
|
|
136
|
+
<POINT (0 1)>
|
|
137
|
+
"""
|
|
138
|
+
# Convert GeoPandas to WKB
|
|
139
|
+
if type(obj).__name__ == "GeoSeries":
|
|
140
|
+
if obj.crs:
|
|
141
|
+
type_ = wkb().with_crs(obj.crs.to_json(), lib.CrsType.PROJJSON)
|
|
142
|
+
else:
|
|
143
|
+
type_ = wkb()
|
|
144
|
+
|
|
145
|
+
# Prefer ISO WKB
|
|
146
|
+
obj = obj.to_wkb(flavor="iso")
|
|
147
|
+
|
|
148
|
+
# Convert obj to array if it isn't already one
|
|
149
|
+
if isinstance(obj, pa.Array) or isinstance(obj, pa.ChunkedArray):
|
|
150
|
+
arr = obj
|
|
151
|
+
else:
|
|
152
|
+
arr = pa.array(obj, *args, **kwargs)
|
|
153
|
+
|
|
154
|
+
# Handle the case where we get to pick the type
|
|
155
|
+
if type_ is None:
|
|
156
|
+
if isinstance(arr.type, GeometryExtensionType):
|
|
157
|
+
return arr
|
|
158
|
+
elif arr.type == pa.utf8():
|
|
159
|
+
return wkt().wrap_array(arr)
|
|
160
|
+
elif arr.type == pa.large_utf8():
|
|
161
|
+
return large_wkt().wrap_array(arr)
|
|
162
|
+
elif arr.type == pa.binary():
|
|
163
|
+
return wkb().wrap_array(arr)
|
|
164
|
+
elif arr.type == pa.large_binary():
|
|
165
|
+
return large_wkb().wrap_array(arr)
|
|
166
|
+
else:
|
|
167
|
+
raise TypeError(
|
|
168
|
+
f"Can't create geoarrow.array from Arrow array of type {type_}"
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
# Handle the case where the type requested is already the correct type
|
|
172
|
+
if type_ == arr.type:
|
|
173
|
+
return arr
|
|
174
|
+
|
|
175
|
+
type_is_geoarrow = isinstance(type_, GeometryExtensionType)
|
|
176
|
+
type_is_wkb_or_wkt = type_.extension_name in ("geoarrow.wkt", "geoarrow.wkb")
|
|
177
|
+
|
|
178
|
+
if type_is_geoarrow and type_is_wkb_or_wkt:
|
|
179
|
+
arr = arr.cast(type_.storage_type)
|
|
180
|
+
return type_.wrap_array(arr)
|
|
181
|
+
|
|
182
|
+
# Eventually we will be able to handle more types (e.g., parse wkt or wkb
|
|
183
|
+
# into a geoarrow type)
|
|
184
|
+
raise TypeError(f"Can't create geoarrow.array for type {type_}")
|