del env py

This commit is contained in:
2024-10-11 17:10:34 -07:00
parent 55b630e6c8
commit b010ab0e6d
19334 changed files with 1 additions and 4003544 deletions

View File

@@ -1,484 +0,0 @@
"""Tests for the clip module."""
import numpy as np
import pandas as pd
import shapely
from shapely.geometry import (
GeometryCollection,
LinearRing,
LineString,
MultiPoint,
Point,
Polygon,
box,
)
import geopandas
from geopandas import GeoDataFrame, GeoSeries, clip
from geopandas._compat import HAS_PYPROJ
from geopandas.tools.clip import _mask_is_list_like_rectangle
import pytest
from geopandas.testing import assert_geodataframe_equal, assert_geoseries_equal
from pandas.testing import assert_index_equal
mask_variants_single_rectangle = [
"single_rectangle_gdf",
"single_rectangle_gdf_list_bounds",
"single_rectangle_gdf_tuple_bounds",
"single_rectangle_gdf_array_bounds",
]
mask_variants_large_rectangle = [
"larger_single_rectangle_gdf",
"larger_single_rectangle_gdf_bounds",
]
@pytest.fixture
def point_gdf():
"""Create a point GeoDataFrame."""
pts = np.array([[2, 2], [3, 4], [9, 8], [-12, -15]])
gdf = GeoDataFrame([Point(xy) for xy in pts], columns=["geometry"], crs="EPSG:3857")
return gdf
@pytest.fixture
def point_gdf2():
"""Create a point GeoDataFrame."""
pts = np.array([[5, 5], [2, 2], [4, 4], [0, 0], [3, 3], [1, 1]])
gdf = GeoDataFrame([Point(xy) for xy in pts], columns=["geometry"], crs="EPSG:3857")
return gdf
@pytest.fixture
def pointsoutside_nooverlap_gdf():
"""Create a point GeoDataFrame. Its points are all outside the single
rectangle, and its bounds are outside the single rectangle's."""
pts = np.array([[5, 15], [15, 15], [15, 20]])
gdf = GeoDataFrame([Point(xy) for xy in pts], columns=["geometry"], crs="EPSG:3857")
return gdf
@pytest.fixture
def pointsoutside_overlap_gdf():
"""Create a point GeoDataFrame. Its points are all outside the single
rectangle, and its bounds are overlapping the single rectangle's."""
pts = np.array([[5, 15], [15, 15], [15, 5]])
gdf = GeoDataFrame([Point(xy) for xy in pts], columns=["geometry"], crs="EPSG:3857")
return gdf
@pytest.fixture
def single_rectangle_gdf():
"""Create a single rectangle for clipping."""
poly_inters = Polygon([(0, 0), (0, 10), (10, 10), (10, 0), (0, 0)])
gdf = GeoDataFrame([1], geometry=[poly_inters], crs="EPSG:3857")
gdf["attr2"] = "site-boundary"
return gdf
@pytest.fixture
def single_rectangle_gdf_tuple_bounds(single_rectangle_gdf):
"""Bounds of the created single rectangle"""
return tuple(single_rectangle_gdf.total_bounds)
@pytest.fixture
def single_rectangle_gdf_list_bounds(single_rectangle_gdf):
"""Bounds of the created single rectangle"""
return list(single_rectangle_gdf.total_bounds)
@pytest.fixture
def single_rectangle_gdf_array_bounds(single_rectangle_gdf):
"""Bounds of the created single rectangle"""
return single_rectangle_gdf.total_bounds
@pytest.fixture
def larger_single_rectangle_gdf():
"""Create a slightly larger rectangle for clipping.
The smaller single rectangle is used to test the edge case where slivers
are returned when you clip polygons. This fixture is larger which
eliminates the slivers in the clip return.
"""
poly_inters = Polygon([(-5, -5), (-5, 15), (15, 15), (15, -5), (-5, -5)])
gdf = GeoDataFrame([1], geometry=[poly_inters], crs="EPSG:3857")
gdf["attr2"] = ["study area"]
return gdf
@pytest.fixture
def larger_single_rectangle_gdf_bounds(larger_single_rectangle_gdf):
"""Bounds of the created single rectangle"""
return tuple(larger_single_rectangle_gdf.total_bounds)
@pytest.fixture
def buffered_locations(point_gdf):
"""Buffer points to create a multi-polygon."""
buffered_locs = point_gdf
buffered_locs["geometry"] = buffered_locs.buffer(4)
buffered_locs["type"] = "plot"
return buffered_locs
@pytest.fixture
def donut_geometry(buffered_locations, single_rectangle_gdf):
"""Make a geometry with a hole in the middle (a donut)."""
donut = geopandas.overlay(
buffered_locations, single_rectangle_gdf, how="symmetric_difference"
)
return donut
@pytest.fixture
def two_line_gdf():
"""Create Line Objects For Testing"""
linea = LineString([(1, 1), (2, 2), (3, 2), (5, 3)])
lineb = LineString([(3, 4), (5, 7), (12, 2), (10, 5), (9, 7.5)])
gdf = GeoDataFrame([1, 2], geometry=[linea, lineb], crs="EPSG:3857")
return gdf
@pytest.fixture
def multi_poly_gdf(donut_geometry):
"""Create a multi-polygon GeoDataFrame."""
multi_poly = donut_geometry.union_all()
out_df = GeoDataFrame(geometry=GeoSeries(multi_poly), crs="EPSG:3857")
out_df["attr"] = ["pool"]
return out_df
@pytest.fixture
def multi_line(two_line_gdf):
"""Create a multi-line GeoDataFrame.
This GDF has one multiline and one regular line."""
# Create a single and multi line object
multiline_feat = two_line_gdf.union_all()
linec = LineString([(2, 1), (3, 1), (4, 1), (5, 2)])
out_df = GeoDataFrame(geometry=GeoSeries([multiline_feat, linec]), crs="EPSG:3857")
out_df["attr"] = ["road", "stream"]
return out_df
@pytest.fixture
def multi_point(point_gdf):
"""Create a multi-point GeoDataFrame."""
multi_point = point_gdf.union_all()
out_df = GeoDataFrame(
geometry=GeoSeries(
[multi_point, Point(2, 5), Point(-11, -14), Point(-10, -12)]
),
crs="EPSG:3857",
)
out_df["attr"] = ["tree", "another tree", "shrub", "berries"]
return out_df
@pytest.fixture
def mixed_gdf():
"""Create a Mixed Polygon and LineString For Testing"""
point = Point(2, 3)
line = LineString([(1, 1), (2, 2), (3, 2), (5, 3), (12, 1)])
poly = Polygon([(3, 4), (5, 2), (12, 2), (10, 5), (9, 7.5)])
ring = LinearRing([(1, 1), (2, 2), (3, 2), (5, 3), (12, 1)])
gdf = GeoDataFrame(
[1, 2, 3, 4], geometry=[point, poly, line, ring], crs="EPSG:3857"
)
return gdf
@pytest.fixture
def geomcol_gdf():
"""Create a Mixed Polygon and LineString For Testing"""
point = Point(2, 3)
poly = Polygon([(3, 4), (5, 2), (12, 2), (10, 5), (9, 7.5)])
coll = GeometryCollection([point, poly])
gdf = GeoDataFrame([1], geometry=[coll], crs="EPSG:3857")
return gdf
@pytest.fixture
def sliver_line():
"""Create a line that will create a point when clipped."""
linea = LineString([(10, 5), (13, 5), (15, 5)])
lineb = LineString([(1, 1), (2, 2), (3, 2), (5, 3), (12, 1)])
gdf = GeoDataFrame([1, 2], geometry=[linea, lineb], crs="EPSG:3857")
return gdf
def test_not_gdf(single_rectangle_gdf):
"""Non-GeoDataFrame inputs raise attribute errors."""
with pytest.raises(TypeError):
clip((2, 3), single_rectangle_gdf)
with pytest.raises(TypeError):
clip(single_rectangle_gdf, "foobar")
with pytest.raises(TypeError):
clip(single_rectangle_gdf, (1, 2, 3))
with pytest.raises(TypeError):
clip(single_rectangle_gdf, (1, 2, 3, 4, 5))
def test_non_overlapping_geoms():
"""Test that a bounding box returns empty if the extents don't overlap"""
unit_box = Polygon([(0, 0), (0, 1), (1, 1), (1, 0), (0, 0)])
unit_gdf = GeoDataFrame([1], geometry=[unit_box], crs="EPSG:3857")
non_overlapping_gdf = unit_gdf.copy()
non_overlapping_gdf = non_overlapping_gdf.geometry.apply(
lambda x: shapely.affinity.translate(x, xoff=20)
)
out = clip(unit_gdf, non_overlapping_gdf)
assert_geodataframe_equal(out, unit_gdf.iloc[:0])
out2 = clip(unit_gdf.geometry, non_overlapping_gdf)
assert_geoseries_equal(out2, GeoSeries(crs=unit_gdf.crs))
@pytest.mark.parametrize("mask_fixture_name", mask_variants_single_rectangle)
class TestClipWithSingleRectangleGdf:
@pytest.fixture
def mask(self, mask_fixture_name, request):
return request.getfixturevalue(mask_fixture_name)
def test_returns_gdf(self, point_gdf, mask):
"""Test that function returns a GeoDataFrame (or GDF-like) object."""
out = clip(point_gdf, mask)
assert isinstance(out, GeoDataFrame)
def test_returns_series(self, point_gdf, mask):
"""Test that function returns a GeoSeries if GeoSeries is passed."""
out = clip(point_gdf.geometry, mask)
assert isinstance(out, GeoSeries)
def test_clip_points(self, point_gdf, mask):
"""Test clipping a points GDF with a generic polygon geometry."""
clip_pts = clip(point_gdf, mask)
pts = np.array([[2, 2], [3, 4], [9, 8]])
exp = GeoDataFrame(
[Point(xy) for xy in pts], columns=["geometry"], crs="EPSG:3857"
)
assert_geodataframe_equal(clip_pts, exp)
def test_clip_points_geom_col_rename(self, point_gdf, mask):
"""Test clipping a points GDF with a generic polygon geometry."""
point_gdf_geom_col_rename = point_gdf.rename_geometry("geometry2")
clip_pts = clip(point_gdf_geom_col_rename, mask)
pts = np.array([[2, 2], [3, 4], [9, 8]])
exp = GeoDataFrame(
[Point(xy) for xy in pts],
columns=["geometry2"],
crs="EPSG:3857",
geometry="geometry2",
)
assert_geodataframe_equal(clip_pts, exp)
def test_clip_poly(self, buffered_locations, mask):
"""Test clipping a polygon GDF with a generic polygon geometry."""
clipped_poly = clip(buffered_locations, mask)
assert len(clipped_poly.geometry) == 3
assert all(clipped_poly.geom_type == "Polygon")
def test_clip_poly_geom_col_rename(self, buffered_locations, mask):
"""Test clipping a polygon GDF with a generic polygon geometry."""
poly_gdf_geom_col_rename = buffered_locations.rename_geometry("geometry2")
clipped_poly = clip(poly_gdf_geom_col_rename, mask)
assert len(clipped_poly.geometry) == 3
assert "geometry" not in clipped_poly.keys()
assert "geometry2" in clipped_poly.keys()
def test_clip_poly_series(self, buffered_locations, mask):
"""Test clipping a polygon GDF with a generic polygon geometry."""
clipped_poly = clip(buffered_locations.geometry, mask)
assert len(clipped_poly) == 3
assert all(clipped_poly.geom_type == "Polygon")
def test_clip_multipoly_keep_geom_type(self, multi_poly_gdf, mask):
"""Test a multi poly object where the return includes a sliver.
Also the bounds of the object should == the bounds of the clip object
if they fully overlap (as they do in these fixtures)."""
clipped = clip(multi_poly_gdf, mask, keep_geom_type=True)
expected_bounds = (
mask if _mask_is_list_like_rectangle(mask) else mask.total_bounds
)
assert np.array_equal(clipped.total_bounds, expected_bounds)
# Assert returned data is a not geometry collection
assert (clipped.geom_type.isin(["Polygon", "MultiPolygon"])).all()
def test_clip_multiline(self, multi_line, mask):
"""Test that clipping a multiline feature with a poly returns expected
output."""
clipped = clip(multi_line, mask)
assert clipped.geom_type[0] == "MultiLineString"
def test_clip_multipoint(self, multi_point, mask):
"""Clipping a multipoint feature with a polygon works as expected.
should return a geodataframe with a single multi point feature"""
clipped = clip(multi_point, mask)
assert clipped.geom_type[0] == "MultiPoint"
assert hasattr(clipped, "attr")
# All points should intersect the clip geom
assert len(clipped) == 2
clipped_mutltipoint = MultiPoint(
[
Point(2, 2),
Point(3, 4),
Point(9, 8),
]
)
assert clipped.iloc[0].geometry.wkt == clipped_mutltipoint.wkt
shape_for_points = (
box(*mask) if _mask_is_list_like_rectangle(mask) else mask.union_all()
)
assert all(clipped.intersects(shape_for_points))
def test_clip_lines(self, two_line_gdf, mask):
"""Test what happens when you give the clip_extent a line GDF."""
clip_line = clip(two_line_gdf, mask)
assert len(clip_line.geometry) == 2
def test_mixed_geom(self, mixed_gdf, mask):
"""Test clipping a mixed GeoDataFrame"""
clipped = clip(mixed_gdf, mask)
assert (
clipped.geom_type[0] == "Point"
and clipped.geom_type[1] == "Polygon"
and clipped.geom_type[2] == "LineString"
)
def test_mixed_series(self, mixed_gdf, mask):
"""Test clipping a mixed GeoSeries"""
clipped = clip(mixed_gdf.geometry, mask)
assert (
clipped.geom_type[0] == "Point"
and clipped.geom_type[1] == "Polygon"
and clipped.geom_type[2] == "LineString"
)
def test_clip_with_line_extra_geom(self, sliver_line, mask):
"""When the output of a clipped line returns a geom collection,
and keep_geom_type is True, no geometry collections should be returned."""
clipped = clip(sliver_line, mask, keep_geom_type=True)
assert len(clipped.geometry) == 1
# Assert returned data is a not geometry collection
assert not (clipped.geom_type == "GeometryCollection").any()
def test_clip_no_box_overlap(self, pointsoutside_nooverlap_gdf, mask):
"""Test clip when intersection is empty and boxes do not overlap."""
clipped = clip(pointsoutside_nooverlap_gdf, mask)
assert len(clipped) == 0
def test_clip_box_overlap(self, pointsoutside_overlap_gdf, mask):
"""Test clip when intersection is empty and boxes do overlap."""
clipped = clip(pointsoutside_overlap_gdf, mask)
assert len(clipped) == 0
def test_warning_extra_geoms_mixed(self, mixed_gdf, mask):
"""Test the correct warnings are raised if keep_geom_type is
called on a mixed GDF"""
with pytest.warns(UserWarning):
clip(mixed_gdf, mask, keep_geom_type=True)
def test_warning_geomcoll(self, geomcol_gdf, mask):
"""Test the correct warnings are raised if keep_geom_type is
called on a GDF with GeometryCollection"""
with pytest.warns(UserWarning):
clip(geomcol_gdf, mask, keep_geom_type=True)
def test_clip_line_keep_slivers(sliver_line, single_rectangle_gdf):
"""Test the correct output if a point is returned
from a line only geometry type."""
clipped = clip(sliver_line, single_rectangle_gdf)
# Assert returned data is a geometry collection given sliver geoms
assert "Point" == clipped.geom_type[0]
assert "LineString" == clipped.geom_type[1]
def test_clip_multipoly_keep_slivers(multi_poly_gdf, single_rectangle_gdf):
"""Test a multi poly object where the return includes a sliver.
Also the bounds of the object should == the bounds of the clip object
if they fully overlap (as they do in these fixtures)."""
clipped = clip(multi_poly_gdf, single_rectangle_gdf)
assert np.array_equal(clipped.total_bounds, single_rectangle_gdf.total_bounds)
# Assert returned data is a geometry collection given sliver geoms
assert "GeometryCollection" in clipped.geom_type[0]
@pytest.mark.skipif(not HAS_PYPROJ, reason="pyproj not available")
def test_warning_crs_mismatch(point_gdf, single_rectangle_gdf):
with pytest.warns(UserWarning, match="CRS mismatch between the CRS"):
clip(point_gdf, single_rectangle_gdf.to_crs(4326))
def test_clip_with_polygon(single_rectangle_gdf):
"""Test clip when using a shapely object"""
polygon = Polygon([(0, 0), (5, 12), (10, 0), (0, 0)])
clipped = clip(single_rectangle_gdf, polygon)
exp_poly = polygon.intersection(
Polygon([(0, 0), (0, 10), (10, 10), (10, 0), (0, 0)])
)
exp = GeoDataFrame([1], geometry=[exp_poly], crs="EPSG:3857")
exp["attr2"] = "site-boundary"
assert_geodataframe_equal(clipped, exp)
def test_clip_with_multipolygon(buffered_locations, single_rectangle_gdf):
"""Test clipping a polygon with a multipolygon."""
multi = buffered_locations.dissolve(by="type").reset_index()
clipped = clip(single_rectangle_gdf, multi)
assert clipped.geom_type[0] == "Polygon"
@pytest.mark.parametrize(
"mask_fixture_name",
mask_variants_large_rectangle,
)
def test_clip_single_multipoly_no_extra_geoms(
buffered_locations, mask_fixture_name, request
):
"""When clipping a multi-polygon feature, no additional geom types
should be returned."""
masks = request.getfixturevalue(mask_fixture_name)
multi = buffered_locations.dissolve(by="type").reset_index()
clipped = clip(multi, masks)
assert clipped.geom_type[0] == "Polygon"
@pytest.mark.filterwarnings("ignore:All-NaN slice encountered")
@pytest.mark.parametrize(
"mask",
[
Polygon(),
(np.nan,) * 4,
(np.nan, 0, np.nan, 1),
GeoSeries([Polygon(), Polygon()], crs="EPSG:3857"),
GeoSeries([Polygon(), Polygon()], crs="EPSG:3857").to_frame(),
GeoSeries([], crs="EPSG:3857"),
GeoSeries([], crs="EPSG:3857").to_frame(),
],
)
def test_clip_empty_mask(buffered_locations, mask):
"""Test that clipping with empty mask returns an empty result."""
clipped = clip(buffered_locations, mask)
assert_geodataframe_equal(
clipped,
GeoDataFrame([], columns=["geometry", "type"], crs="EPSG:3857"),
check_index_type=False,
)
clipped = clip(buffered_locations.geometry, mask)
assert_geoseries_equal(clipped, GeoSeries([], crs="EPSG:3857"))
def test_clip_sorting(point_gdf2):
"""Test the sorting kwarg in clip"""
bbox = shapely.geometry.box(0, 0, 2, 2)
unsorted_clipped_gdf = point_gdf2.clip(bbox)
sorted_clipped_gdf = point_gdf2.clip(bbox, sort=True)
expected_sorted_index = pd.Index([1, 3, 5])
assert not (sorted(unsorted_clipped_gdf.index) == unsorted_clipped_gdf.index).all()
assert (sorted(sorted_clipped_gdf.index) == sorted_clipped_gdf.index).all()
assert_index_equal(expected_sorted_index, sorted_clipped_gdf.index)

View File

@@ -1,76 +0,0 @@
import numpy as np
from shapely.geometry import Point
from shapely.wkt import loads
import geopandas
import pytest
from pandas.testing import assert_series_equal
def test_hilbert_distance():
# test the actual Hilbert Code algorithm against some hardcoded values
geoms = geopandas.GeoSeries.from_wkt(
[
"POINT (0 0)",
"POINT (1 1)",
"POINT (1 0)",
"POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0))",
]
)
result = geoms.hilbert_distance(total_bounds=(0, 0, 1, 1), level=2)
assert result.tolist() == [0, 10, 15, 2]
result = geoms.hilbert_distance(total_bounds=(0, 0, 1, 1), level=3)
assert result.tolist() == [0, 42, 63, 10]
result = geoms.hilbert_distance(total_bounds=(0, 0, 1, 1), level=16)
assert result.tolist() == [0, 2863311530, 4294967295, 715827882]
@pytest.fixture
def geoseries_points():
p1 = Point(1, 2)
p2 = Point(2, 3)
p3 = Point(3, 4)
p4 = Point(4, 1)
return geopandas.GeoSeries([p1, p2, p3, p4])
def test_hilbert_distance_level(geoseries_points):
with pytest.raises(ValueError):
geoseries_points.hilbert_distance(level=20)
def test_specified_total_bounds(geoseries_points):
result = geoseries_points.hilbert_distance(
total_bounds=geoseries_points.total_bounds
)
expected = geoseries_points.hilbert_distance()
assert_series_equal(result, expected)
@pytest.mark.parametrize(
"empty",
[
None,
loads("POLYGON EMPTY"),
],
)
def test_empty(geoseries_points, empty):
s = geoseries_points
s.iloc[-1] = empty
with pytest.raises(
ValueError, match="cannot be computed on a GeoSeries with empty"
):
s.hilbert_distance()
def test_zero_width():
# special case of all points on the same line -> avoid warnings because
# of division by 0 and introducing NaN
s = geopandas.GeoSeries([Point(0, 0), Point(0, 2), Point(0, 1)])
with np.errstate(all="raise"):
result = s.hilbert_distance()
assert np.array(result).argsort().tolist() == [0, 2, 1]

View File

@@ -1,67 +0,0 @@
import numpy
import geopandas
from geopandas.tools._random import uniform
import pytest
@pytest.fixture
def multipolygons(nybb_filename):
return geopandas.read_file(nybb_filename).geometry
@pytest.fixture
def polygons(multipolygons):
return multipolygons.explode(ignore_index=True).geometry
@pytest.fixture
def multilinestrings(multipolygons):
return multipolygons.boundary
@pytest.fixture
def linestrings(polygons):
return polygons.boundary
@pytest.fixture
def points(multipolygons):
return multipolygons.centroid
@pytest.mark.parametrize("size", [10, 100])
@pytest.mark.parametrize(
"geom_fixture", ["multipolygons", "polygons", "multilinestrings", "linestrings"]
)
def test_uniform(geom_fixture, size, request):
geom = request.getfixturevalue(geom_fixture)[0]
sample = uniform(geom, size=size, rng=1)
sample_series = (
geopandas.GeoSeries(sample).explode(index_parts=True).reset_index(drop=True)
)
assert len(sample_series) == size
sample_in_geom = sample_series.buffer(0.00000001).sindex.query(
geom, predicate="intersects"
)
assert len(sample_in_geom) == size
def test_uniform_unsupported(points):
with pytest.warns(UserWarning, match="Sampling is not supported"):
sample = uniform(points[0], size=10, rng=1)
assert sample.is_empty
def test_uniform_generator(polygons):
sample = uniform(polygons[0], size=10, rng=1)
sample2 = uniform(polygons[0], size=10, rng=1)
assert sample.equals(sample2)
generator = numpy.random.default_rng(seed=1)
gen_sample = uniform(polygons[0], size=10, rng=generator)
gen_sample2 = uniform(polygons[0], size=10, rng=generator)
assert sample.equals(gen_sample)
assert not sample.equals(gen_sample2)

View File

@@ -1,51 +0,0 @@
from shapely.geometry import LineString, MultiPoint, Point
from geopandas import GeoSeries
from geopandas.tools import collect
import pytest
class TestTools:
def setup_method(self):
self.p1 = Point(0, 0)
self.p2 = Point(1, 1)
self.p3 = Point(2, 2)
self.mpc = MultiPoint([self.p1, self.p2, self.p3])
self.mp1 = MultiPoint([self.p1, self.p2])
self.line1 = LineString([(3, 3), (4, 4)])
def test_collect_single(self):
result = collect(self.p1)
assert self.p1.equals(result)
def test_collect_single_force_multi(self):
result = collect(self.p1, multi=True)
expected = MultiPoint([self.p1])
assert expected.equals(result)
def test_collect_multi(self):
result = collect(self.mp1)
assert self.mp1.equals(result)
def test_collect_multi_force_multi(self):
result = collect(self.mp1)
assert self.mp1.equals(result)
def test_collect_list(self):
result = collect([self.p1, self.p2, self.p3])
assert self.mpc.equals(result)
def test_collect_GeoSeries(self):
s = GeoSeries([self.p1, self.p2, self.p3])
result = collect(s)
assert self.mpc.equals(result)
def test_collect_mixed_types(self):
with pytest.raises(ValueError):
collect([self.p1, self.line1])
def test_collect_mixed_multi(self):
with pytest.raises(ValueError):
collect([self.mpc, self.mp1])