Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

revert shapely hard dependecy #454

Merged
merged 5 commits into from
Mar 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions .github/workflows/unittests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,39 +19,39 @@
strategy:
matrix:
os: ['ubuntu-latest']
environment-file: [ci/37.yaml, ci/38.yaml, ci/39.yaml, ci/310.yaml]
environment-file: [ci/37-minimal.yaml, ci/37.yaml, ci/38.yaml, ci/39.yaml, ci/310.yaml]
include:
- environment-file: ci/310.yaml
os: macos-latest
- environment-file: ci/310.yaml
os: windows-latest

steps:
- name: checkout repo
uses: actions/checkout@v3

- name: setup micromamba
uses: mamba-org/provision-with-micromamba@main
with:
environment-file: ${{ matrix.environment-file }}
micromamba-version: 'latest'

- name: run tests - bash
shell: bash -l {0}
run: |
${{ env.FETCH_EXAMPLES }}
${{ env.RUN_TEST }}
if: matrix.os != 'windows-latest'

- name: run tests - powershell
shell: powershell
run: |
${{ env.FETCH_EXAMPLES }}
${{ env.RUN_TEST }}
if: matrix.os == 'windows-latest'

- name: codecov
uses: codecov/codecov-action@v2
uses: codecov/codecov-action@v2
with:
token: ${{ secrets.CODECOV_TOKEN }}
file: ./coverage.xml
Expand Down
17 changes: 17 additions & 0 deletions ci/37-minimal.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
name: test
channels:
- conda-forge
dependencies:
- python=3.7
- appdirs
- beautifulsoup4
- jinja2
- pandas>=1.0
- scipy>=1.0
- xarray
# testing
- codecov
- matplotlib
- pytest
- pytest-cov
- pytest-xdist
9 changes: 9 additions & 0 deletions libpysal/cg/tests/test_voronoi.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@
from ..voronoi import voronoi, voronoi_frames
from ..shapes import Polygon, asShape

import pytest

try:
import shapely
HAS_SHAPELY = True
except ImportError:
HAS_SHAPELY = False


class Voronoi(unittest.TestCase):
def setUp(self):
Expand All @@ -29,6 +37,7 @@ def test_voronoi(self):

np.testing.assert_array_almost_equal(vertices, self.vertices)

@pytest.mark.skipif(not HAS_SHAPELY, reason="shapely needed")
jGaboardi marked this conversation as resolved.
Show resolved Hide resolved
def test_voronoi_frames(self):
r_df, p_df = voronoi_frames(self.points)
region = r_df.iloc[0]["geometry"]
Expand Down
16 changes: 15 additions & 1 deletion libpysal/weights/tests/test_contiguity.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from ... import examples as pysal_examples
import unittest as ut
import numpy as np
import pytest

PANDAS_EXTINCT = pandas is None
try:
Expand All @@ -18,6 +19,12 @@
except ImportError:
GEOPANDAS_EXTINCT = True

try:
import shapely
HAS_SHAPELY = True
except ImportError:
HAS_SHAPELY = False


class Contiguity_Mixin(object):
polygon_path = pysal_examples.get_path("columbus.shp")
Expand Down Expand Up @@ -90,6 +97,7 @@ def test_from_array(self):
# test named, sparse from point array
pass


@ut.skipIf(PANDAS_EXTINCT, "Missing pandas")
def test_from_dataframe(self):
# basic
Expand All @@ -102,7 +110,12 @@ def test_from_dataframe(self):
w = self.cls.from_dataframe(df, geom_col="the_geom")
self.assertEqual(w[self.known_wi], self.known_w)


@ut.skipIf(GEOPANDAS_EXTINCT, "Missing geopandas")
def test_from_geodataframe(self):
df = pdio.read_files(self.polygon_path)
# named active geometry
df.rename(columns={"geometry": "the_geom"}, inplace=True)
df = df.set_geometry("the_geom")
w = self.cls.from_dataframe(df)
self.assertEqual(w[self.known_wi], self.known_w)
Expand Down Expand Up @@ -148,7 +161,7 @@ def setUp(self):
(1, -90.0, 60.0): 1,
(1, -30.0, -180.0): 1,
(1, -30.0, 60.0): 1,
(1, 30.0, -180.0): 1,
(1, 30.0, -180.0): 1,
(1, 30.0, -60.0): 1,
(1, 30.0, 60.0): 1
}
Expand Down Expand Up @@ -192,6 +205,7 @@ def setUp(self):


class Test_Voronoi(ut.TestCase):
@pytest.mark.skipif(not HAS_SHAPELY, reason="shapely needed")
def test_voronoiW(self):
np.random.seed(12345)
points = np.random.random((5, 2)) * 10 + 10
Expand Down
25 changes: 24 additions & 1 deletion libpysal/weights/tests/test_distance.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@
import unittest as ut

PANDAS_EXTINCT = pandas is None
try:
import geopandas

GEOPANDAS_EXTINCT = False
except ImportError:
GEOPANDAS_EXTINCT = True
# All instances should test these four methods, and define their own functional
# tests based on common codepaths/estimated weights use cases.

Expand Down Expand Up @@ -107,7 +113,11 @@ def test_from_dataframe(self):
self.assertEqual(w.neighbors[self.known_wi0], self.known_w0)
self.assertEqual(w.neighbors[self.known_wi1], self.known_w1)

@ut.skipIf(GEOPANDAS_EXTINCT, "Missing geopandas")
def test_from_geodataframe(self):
df = pdio.read_files(self.polygon_path)
# named active geometry
df.rename(columns={"geometry": "the_geom"}, inplace=True)
df = df.set_geometry("the_geom")
w = d.KNN.from_dataframe(df, k=4)
self.assertEqual(w.neighbors[self.known_wi0], self.known_w0)
Expand Down Expand Up @@ -176,7 +186,6 @@ def test_from_array(self):
@ut.skipIf(PANDAS_EXTINCT, "Missing pandas")
def test_from_dataframe(self):
import pandas as pd
import geopandas as gpd

geom_series = pdio.shp.shp2series(self.grid_path)
random_data = np.random.random(size=len(geom_series))
Expand All @@ -185,6 +194,17 @@ def test_from_dataframe(self):
for k, v in w:
self.assertEqual(v, self.grid_rook_w[k])

@ut.skipIf(GEOPANDAS_EXTINCT, "Missing geopandas")
def test_from_geodataframe(self):
import geopandas as gpd
import pandas as pd

geom_series = pdio.shp.shp2series(self.grid_path)
random_data = np.random.random(size=len(geom_series))
df = pd.DataFrame({"obs": random_data, "geometry": geom_series})
w = d.DistanceBand.from_dataframe(df, 1)
for k, v in w:
self.assertEqual(v, self.grid_rook_w[k])
# named geometry
df = gpd.GeoDataFrame(df)
df.rename(columns={"geometry": "the_geom"}, inplace=True)
Expand Down Expand Up @@ -329,6 +349,9 @@ def test_from_dataframe(self):
for k, v in list(w[self.known_wi5 - 1].items()):
np.testing.assert_allclose(v, self.known_w5[k + 1], rtol=RTOL)

@ut.skipIf(GEOPANDAS_EXTINCT, "Missing geopandas")
def test_from_geodataframe(self):
df = pdio.read_files(self.polygon_path)
# named geometry
df.rename(columns={"geometry": "the_geom"}, inplace=True)
w = d.Kernel.from_dataframe(df, geom_col="the_geom")
Expand Down
5 changes: 4 additions & 1 deletion libpysal/weights/tests/test_gabriel.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
from .. import gabriel
from ... import examples
import geopandas, numpy
import numpy
import pytest

geopandas = pytest.importorskip("geopandas")

path = examples.get_path("columbus.shp")
df = geopandas.read_file(path)
Expand Down
31 changes: 22 additions & 9 deletions libpysal/weights/util.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
from shapely.geometry.base import BaseGeometry
from ..io.fileio import FileIO as psopen
from .weights import W, WSP
from .set_operations import w_subset
Expand All @@ -23,6 +22,12 @@
except ImportError:
warn("geopandas not available. Some functionality will be disabled.")

try:
from shapely.geometry.base import BaseGeometry
HAS_SHAPELY = True
except ImportError:
HAS_SHAPELY = False

__all__ = [
"lat2W",
"block_weights",
Expand Down Expand Up @@ -1071,14 +1076,22 @@ def get_points_array(iterable):
"""
first_choice, backup = tee(iterable)
try:
data = np.vstack(
[
np.array(shape.centroid.coords)[0]
if isinstance(shape, BaseGeometry)
else np.array(shape.centroid)
for shape in first_choice
]
)
if HAS_SHAPELY:
data = np.vstack(
[
np.array(shape.centroid.coords)[0]
if isinstance(shape, BaseGeometry)
else np.array(shape.centroid)
for shape in first_choice
]
)
else:
data = np.vstack(
[
np.array(shape.centroid)
for shape in first_choice
]
)
except AttributeError:
data = np.vstack([shape for shape in backup])
return data
Expand Down