Skip to content

Commit

Permalink
fix(geospatial): ensure that later versions of numpy are compatible w…
Browse files Browse the repository at this point in the history
…ith geospatial code
  • Loading branch information
cpcloud committed Jul 10, 2022
1 parent afa7c61 commit 33f0afb
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 64 deletions.
12 changes: 6 additions & 6 deletions ibis/backends/base/sql/alchemy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,19 +128,19 @@ def _to_geodataframe(df, schema):
Required libraries for geospatial support must be installed and a
geospatial column is present in the dataframe.
"""
import geopandas
import geopandas as gpd
from geoalchemy2 import shape

def to_shapely(row, name):
return shape.to_shape(row[name]) if row[name] is not None else None

geom_col = None
for name, dtype in schema.items():
if isinstance(dtype, dt.GeoSpatial):
geom_col = geom_col or name
df[name] = df.apply(lambda x: to_shapely(x, name), axis=1)
df[name] = df[name].map(
lambda row: None if row is None else shape.to_shape(row)
)
if geom_col:
df = geopandas.GeoDataFrame(df, geometry=geom_col)
df[geom_col] = gpd.array.GeometryArray(df[geom_col].values)
df = gpd.GeoDataFrame(df, geometry=geom_col)
return df

def fetch_from_cursor(self, cursor, schema: sch.Schema) -> pd.DataFrame:
Expand Down
102 changes: 44 additions & 58 deletions ibis/backends/postgres/tests/test_postgis.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import functools

import pandas as pd
import pandas.testing as tm
import pytest
from numpy import testing

pytest.importorskip("psycopg2")
pytest.importorskip("geoalchemy2")
pytest.importorskip("geopandas")
gpd = pytest.importorskip("geopandas")
pytest.importorskip("shapely")

sa = pytest.importorskip("sqlalchemy")
Expand All @@ -13,11 +16,9 @@


def test_load_geodata(con):
import geopandas

t = con.table('geo')
result = t.execute()
assert isinstance(result, geopandas.GeoDataFrame)
assert isinstance(result, gpd.GeoDataFrame)


def test_empty_select(geotable):
Expand Down Expand Up @@ -75,22 +76,20 @@ def test_select_multipolygon_geodata(geotable):


def test_geo_area(geotable, gdf):
import geopandas

expr = geotable.geo_multipolygon.area()
result = expr.execute()
expected = geopandas.GeoSeries(gdf.geo_multipolygon).area
expected = pd.Series([mp.area for mp in gdf.geo_multipolygon])
tm.assert_series_equal(result, expected, check_names=False)


def test_geo_buffer(geotable, gdf):
import geopandas

expr = geotable.geo_linestring.buffer(1.0)
result = expr.execute()
expected = geopandas.GeoSeries(gdf.geo_linestring).buffer(1.0)
expected = pd.Series(
[linestring.buffer(1.0).area for linestring in gdf.geo_linestring]
)
tm.assert_series_equal(
result.area, expected.area, check_names=False, check_less_precise=2
result.area, expected, check_names=False, check_less_precise=2
)


Expand Down Expand Up @@ -137,12 +136,15 @@ def test_geo_end_point(geotable, gdf):


def test_geo_envelope(geotable, gdf):
import geopandas

expr = geotable.geo_linestring.buffer(1.0).envelope()
result = expr.execute()
expected = geopandas.GeoSeries(gdf.geo_linestring).buffer(1.0).envelope
tm.assert_series_equal(result.area, expected.area, check_names=False)
expected = pd.Series(
[
linestring.buffer(1.0).envelope.area
for linestring in gdf.geo_linestring
]
)
tm.assert_series_equal(result.area, expected, check_names=False)


def test_geo_within(geotable):
Expand Down Expand Up @@ -170,7 +172,7 @@ def test_geo_equals(geotable):
def test_geo_geometry_n(geotable, gdf):
expr = geotable.geo_multipolygon.geometry_n(1) # PostGIS is one-indexed.
result = expr.execute()
first_polygon = gdf.apply(lambda x: list(x.geo_multipolygon)[0], axis=1)
first_polygon = [mp.geoms[0] for mp in gdf.geo_multipolygon]
for a, b in zip(result, first_polygon):
assert a.equals(b)

Expand Down Expand Up @@ -198,19 +200,15 @@ def test_geo_line_locate_point(geotable):


def test_geo_line_merge(geotable, gdf):
import geopandas

expr = geotable.geo_linestring.line_merge()
expected = geopandas.GeoSeries(gdf.geo_linestring)
expected = gpd.GeoSeries(gdf.geo_linestring)
tm.assert_series_equal(expr.execute().length, expected.length)


def test_geo_line_substring(geotable, gdf):
import geopandas

expr = geotable.geo_linestring.line_substring(0.25, 0.75)
result = expr.execute()
expected = geopandas.GeoSeries(gdf.geo_linestring)
expected = gpd.GeoSeries(gdf.geo_linestring)
tm.assert_series_equal(expected.length / 2.0, result.length)


Expand All @@ -230,22 +228,21 @@ def test_geo_touches(geotable):


def test_geo_distance(geotable, gdf):
import geopandas

expr = geotable.geo_point.distance(geotable.geo_multipolygon.centroid())
result = expr.execute()
expected = gdf.geo_point.distance(
geopandas.GeoSeries(gdf.geo_multipolygon).centroid
expected = pd.Series(
[
point.distance(mp.centroid)
for point, mp in zip(gdf.geo_point, gdf.geo_multipolygon)
]
)
tm.assert_series_equal(result, expected, check_names=False)


def test_geo_length(geotable, gdf):
import geopandas

expr = geotable.geo_linestring.length()
result = expr.execute()
expected = geopandas.GeoSeries(gdf.geo_linestring).length
expected = gpd.GeoSeries(gdf.geo_linestring).length
tm.assert_series_equal(result, expected, check_names=False)


Expand Down Expand Up @@ -279,78 +276,67 @@ def test_geo_start_point(geotable, gdf):


def test_geo_difference(geotable, gdf):
import geopandas

expr = (
geotable.geo_linestring.buffer(1.0)
.difference(geotable.geo_point.buffer(0.5))
.area()
)
result = expr.execute()
expected = (
geopandas.GeoSeries(gdf.geo_linestring)
.buffer(1.0)
.difference(geopandas.GeoSeries(gdf.geo_point).buffer(0.5))
.area
expected = pd.Series(
[
linestring.buffer(1.0).difference(point.buffer(0.5)).area
for linestring, point in zip(gdf.geo_linestring, gdf.geo_point)
]
)
tm.assert_series_equal(
result, expected, check_names=False, check_less_precise=2
)


def test_geo_intersection(geotable, gdf):
import geopandas

expr = (
geotable.geo_linestring.buffer(1.0)
.intersection(geotable.geo_point.buffer(0.5))
.area()
)
result = expr.execute()
expected = (
geopandas.GeoSeries(gdf.geo_linestring)
.buffer(1.0)
.intersection(geopandas.GeoSeries(gdf.geo_point).buffer(0.5))
.area
expected = pd.Series(
[
linestring.buffer(1.0).intersection(point.buffer(0.5)).area
for linestring, point in zip(gdf.geo_linestring, gdf.geo_point)
]
)
tm.assert_series_equal(
result, expected, check_names=False, check_less_precise=2
)


def test_geo_unary_union(geotable, gdf):
import geopandas

expr = geotable.geo_polygon.unary_union().area()
expected = geopandas.GeoSeries(gdf.geo_polygon).unary_union.area
expected = functools.reduce(lambda x, y: x.union(y), gdf.geo_polygon).area
testing.assert_almost_equal(expr.execute(), expected, decimal=2)


def test_geo_union(geotable, gdf):
import geopandas

expr = geotable.geo_polygon.union(geotable.geo_multipolygon).area()
expected = (
geopandas.GeoSeries(gdf.geo_polygon)
.union(geopandas.GeoSeries(gdf.geo_multipolygon))
.area
expected = pd.Series(
[
p.union(mp).area
for p, mp in zip(gdf.geo_polygon, gdf.geo_multipolygon)
]
)
tm.assert_series_equal(expr.execute(), expected, check_names=False)


def test_geo_x(geotable, gdf):
import geopandas

expr = geotable.geo_point.x()
result = expr.execute()
expected = geopandas.GeoSeries(gdf.geo_point).x
expected = gpd.GeoSeries(gdf.geo_point).x
tm.assert_series_equal(result, expected, check_names=False)


def test_geo_y(geotable, gdf):
import geopandas

expr = geotable.geo_point.y()
result = expr.execute()
expected = geopandas.GeoSeries(gdf.geo_point).y
expected = gpd.GeoSeries(gdf.geo_point).y
tm.assert_series_equal(result, expected, check_names=False)

0 comments on commit 33f0afb

Please sign in to comment.