def test_astype_multipolygon(): # https://github.com/geopandas/geopandas/issues/1145 multi_poly = shapely.geometry.MultiPolygon( [shapely.geometry.box(0, 0, 1, 1), shapely.geometry.box(3, 3, 4, 4)]) arr = from_shapely([multi_poly]) result = arr.astype(str) assert isinstance(result[0], str) assert result[0] == multi_poly.wkt # astype(object) does not convert to string result = arr.astype(object) assert isinstance(result[0], shapely.geometry.base.BaseGeometry) # astype(np_dtype) honors the dtype result = arr.astype(np.dtype("U10")) assert result.dtype == np.dtype("U10") assert result[0] == multi_poly.wkt[:10]
def test_binary_geo_vector(attr): na_value = None quads = [shapely.geometry.Polygon(), None] while len(quads) < 12: geom = shapely.geometry.Polygon([(random.random(), random.random()) for i in range(4)]) if geom.is_valid: quads.append(geom) Q = from_shapely(quads) result = getattr(T, attr)(Q) expected = [ getattr(t, attr)(q) if t is not None and q is not None else na_value for t, q in zip(triangles, quads) ] assert equal_geometries(result, expected)
def data_for_grouping(): """Data for factorization, grouping, and unique tests. Expected to be like [B, B, NA, NA, A, A, B, C] Where A < B < C and NA is missing """ return from_shapely( [ shapely.geometry.Point(1, 1), shapely.geometry.Point(1, 1), None, None, shapely.geometry.Point(0, 0), shapely.geometry.Point(0, 0), shapely.geometry.Point(1, 1), shapely.geometry.Point(2, 2), ] )
def test_to_crs(self): s = GeoSeries(self.geoms, crs=27700) s = s.to_crs(4326) assert s.crs == self.wgs assert s.values.crs == self.wgs df = GeoDataFrame(geometry=s) assert df.crs == self.wgs df = df.to_crs(27700) assert df.crs == self.osgb assert df.geometry.crs == self.osgb assert df.geometry.values.crs == self.osgb # make sure that only active geometry is transformed arr = from_shapely(self.geoms, crs=4326) df["col1"] = arr df = df.to_crs(3857) assert df.col1.crs == self.wgs assert df.col1.values.crs == self.wgs
def test_unary_geo(attr): na_value = None if attr == "boundary": # boundary raises for empty geometry with pytest.raises(Exception): T.boundary values = triangle_no_missing + [None] A = from_shapely(values) else: values = triangles A = T result = getattr(A, attr) expected = [ getattr(t, attr) if t is not None else na_value for t in values ] assert equal_geometries(result, expected)
def test_getitem(): points = [shapely.geometry.Point(i, i) for i in range(10)] P = from_shapely(points) P2 = P[P.area > 0.3] assert isinstance(P2, GeometryArray) P3 = P[[1, 3, 5]] assert len(P3) == 3 assert isinstance(P3, GeometryArray) assert [p.x for p in P3] == [1, 3, 5] P4 = P[1::2] assert len(P4) == 5 assert isinstance(P3, GeometryArray) assert [p.x for p in P4] == [1, 3, 5, 7, 9] P5 = P[1] assert isinstance(P5, shapely.geometry.Point) assert P5.equals(points[1])
def st_multiline_array(draw, min_size=0, max_size=5, geoseries=False): n = draw(st.integers(min_size, max_size)) multilines = [] for i in range(n): m = draw(st.integers(1, 5)) lines = [] for j in range(m): line_len = draw(st.integers(2, 3)) x_mid = draw(st.floats(-50, 50)) y_mid = draw(st.floats(-50, 50)) points = np.cumsum(np.random.rand(line_len, 2) - 0.5, axis=0) points[:, 0] = points[:, 0] + x_mid points[:, 1] = points[:, 1] + y_mid lines.append(sg.LineString(points)) multilines.append(sg.MultiLineString(lines)) result = from_shapely(multilines) if geoseries: result = GeoSeries(result) return result
def test_total_bounds(): result = T.total_bounds bounds = np.array([ t.bounds if not (t is None or t.is_empty) else [np.nan] * 4 for t in triangles ]) expected = np.array([ np.nanmin(bounds[:, 0]), # minx np.nanmin(bounds[:, 1]), # miny np.nanmax(bounds[:, 2]), # maxx np.nanmax(bounds[:, 3]), # maxy ]) np.testing.assert_allclose(result, expected) # additional check for empty array or one empty / missing for geoms in [[], [None], [shapely.geometry.Polygon()]]: E = from_shapely(geoms) result = E.total_bounds assert result.ndim == 1 assert result.dtype == "float64" np.testing.assert_allclose(result, np.array([np.nan] * 4))
def test_binary_ops(self): arr = self.arr quads = [] while len(quads) < 10: geom = Polygon([(random.random(), random.random()) for i in range(4)]) if geom.is_valid: quads.append(geom) arr2 = from_shapely(quads, crs=27700) difference = arr.difference(arr2) assert difference.crs == self.osgb intersection = arr.intersection(arr2) assert intersection.crs == self.osgb symmetric_difference = arr.symmetric_difference(arr2) assert symmetric_difference.crs == self.osgb union = arr.union(arr2) assert union.crs == self.osgb
def test_binary_project(normalized): na_value = np.nan lines = ( [None] + [ shapely.geometry.LineString( [(random.random(), random.random()) for _ in range(2)] ) for _ in range(len(P) - 2) ] + [None] ) L = from_shapely(lines) result = L.project(P, normalized=normalized) expected = [ l.project(p, normalized=normalized) if l is not None and p is not None else na_value for p, l in zip(points, lines) ] np.testing.assert_allclose(result, expected)
def test_unary_predicates(attr): na_value = False if attr == "is_simple" and geos_version < (3, 8): # poly.is_simple raises an error for empty polygon for GEOS < 3.8 with pytest.raises(Exception): T.is_simple vals = triangle_no_missing V = from_shapely(vals) else: vals = triangles V = T result = getattr(V, attr) if attr == "is_ring": expected = [ getattr(t.exterior, attr) if t is not None and t.exterior is not None else na_value for t in vals ] else: expected = [getattr(t, attr) if t is not None else na_value for t in vals] assert result.tolist() == expected
def test_astype(self): arr = from_shapely(self.geoms, crs=27700) df = GeoDataFrame({"col1": [0, 1]}, geometry=arr) df2 = df.astype({"col1": str}) assert df2.crs == self.osgb
def data_missing(): """Length-2 array with [NA, Valid]""" return from_shapely([None, shapely.geometry.Point(1, 1)])
def make_data(): a = np.array([shapely.geometry.Point(i, i) for i in range(100)], dtype=object) ga = from_shapely(a) return ga
def make_data(): a = np.empty(100, dtype=object) with ignore_shapely2_warnings(): a[:] = [shapely.geometry.Point(i, i) for i in range(100)] ga = from_shapely(a) return ga
inds = np.flipud(np.arange(0, len(points))) result = points.intersects(multipoint, inds) np.testing.assert_equal(result, np.flipud(expected)) # Test GeoSeries.intersects pd.testing.assert_series_equal( points_series.intersects(multipoint), pd.Series(expected, index=points_series.index) ) @given(st_point_array(), st_line_array(min_size=1, max_size=1)) @example( from_shapely([ sg.Point([0.25, 0.25]), # on line sg.Point([1, 1]), # on vertex sg.Point([1.01, 1.01]) # on ray, just past vertex ]), from_shapely([sg.LineString([(0, 0), (1, 1), (2, 0)])]), ) @hyp_settings def test_points_intersects_line(gp_points, gp_line): # Get scalar Line sg_line = gp_line[0] # Compute expected intersection expected = gp_points.intersects(sg_line) # Create spatialpandas objects line = Line.from_shapely(sg_line) points = PointArray.from_geopandas(gp_points)
def test_chaining(): # contains will give False for empty / missing T = from_shapely(triangle_no_missing) assert T.contains(T.centroid).all()
def test_estimate_utm_crs__out_of_bounds(self): with pytest.raises(RuntimeError, match="Unable to determine UTM CRS"): from_shapely( [shapely.geometry.Polygon([(0, 90), (1, 90), (2, 90)])], crs="EPSG:4326" ).estimate_utm_crs()
def setup_method(self): self.esb = shapely.geometry.Point(-73.9847, 40.7484) self.sol = shapely.geometry.Point(-74.0446, 40.6893) self.landmarks = from_shapely([self.esb, self.sol], crs="epsg:4326")
def test_dataframe(self): arr = from_shapely(self.geoms, crs=27700) df = GeoDataFrame(geometry=arr) assert df.crs == self.osgb assert df.geometry.crs == self.osgb assert df.geometry.values.crs == self.osgb arr = from_shapely(self.geoms) s = GeoSeries(arr, crs=27700) df = GeoDataFrame(geometry=s) assert df.crs == self.osgb assert df.geometry.crs == self.osgb assert df.geometry.values.crs == self.osgb # different passed CRS than array CRS is ignored with pytest.warns(FutureWarning): df = GeoDataFrame(geometry=s, crs=4326) assert df.crs == self.osgb assert df.geometry.crs == self.osgb assert df.geometry.values.crs == self.osgb with pytest.warns(FutureWarning): GeoDataFrame(geometry=s, crs=4326) with pytest.warns(FutureWarning): GeoDataFrame({"data": [1, 2], "geometry": s}, crs=4326) with pytest.warns(FutureWarning): GeoDataFrame(df, crs=4326).crs # manually change CRS arr = from_shapely(self.geoms) s = GeoSeries(arr, crs=27700) df = GeoDataFrame(geometry=s) df.crs = 4326 assert df.crs == self.wgs assert df.geometry.crs == self.wgs assert df.geometry.values.crs == self.wgs df = GeoDataFrame(self.geoms, columns=["geom"], crs=27700) assert df.crs == self.osgb df = df.set_geometry("geom") assert df.crs == self.osgb assert df.geometry.crs == self.osgb assert df.geometry.values.crs == self.osgb assert df.geom.crs == self.osgb assert df.geom.values.crs == self.osgb df = GeoDataFrame(geometry=self.geoms, crs=27700) assert df.crs == self.osgb assert df.geometry.crs == self.osgb assert df.geometry.values.crs == self.osgb df = GeoDataFrame(crs=27700) df = df.set_geometry(self.geoms) assert df.crs == self.osgb assert df.geometry.crs == self.osgb assert df.geometry.values.crs == self.osgb # new geometry with set CRS has priority over GDF CRS df = GeoDataFrame(crs=27700) df = df.set_geometry(self.geoms, crs=4326) assert df.crs == self.wgs assert df.geometry.crs == self.wgs assert df.geometry.values.crs == self.wgs df = GeoDataFrame() df = df.set_geometry(s) assert df.crs == self.osgb assert df.geometry.crs == self.osgb assert df.geometry.values.crs == self.osgb arr = from_shapely(self.geoms, crs=27700) df = GeoDataFrame() df = df.set_geometry(arr) assert df.crs == self.osgb assert df.geometry.crs == self.osgb assert df.geometry.values.crs == self.osgb arr = from_shapely(self.geoms) df = GeoDataFrame({"col1": [1, 2], "geometry": arr}, crs=4326) assert df.crs == self.wgs assert df.geometry.crs == self.wgs assert df.geometry.values.crs == self.wgs arr = from_shapely(self.geoms, crs=4326) df = GeoDataFrame({"col1": [1, 2], "geometry": arr}) assert df.crs == self.wgs assert df.geometry.crs == self.wgs assert df.geometry.values.crs == self.wgs # geometry column without geometry df = GeoDataFrame({"geometry": [0, 1]}) df.crs = 27700 assert df.crs == self.osgb
def test_from_shapely(self): arr = from_shapely(self.geoms, crs=27700) assert arr.crs == self.osgb
def test_array_to_crs(self): arr = from_shapely(self.geoms, crs=27700) arr = arr.to_crs(4326) assert arr.crs == self.wgs
def test_unique(): s = GeoSeries([Point(0, 0), Point(0, 0), Point(2, 2)]) exp = from_shapely([Point(0, 0), Point(2, 2)]) # TODO should have specialized GeometryArray assert method assert_array_equal(s.unique(), exp)
def test_estimate_utm_crs__missing_crs(self): with pytest.raises(RuntimeError, match="crs must be set"): from_shapely( [shapely.geometry.Polygon([(0, 90), (1, 90), (2, 90)])] ).estimate_utm_crs()
def _(dtype): return from_shapely( [shapely.geometry.LineString([(i, i), (i, i + 1)]) for i in range(2)])
def test_dataframe(self): arr = from_shapely(self.geoms, crs=27700) df = GeoDataFrame(geometry=arr) assert df.crs == self.osgb assert df.geometry.crs == self.osgb assert df.geometry.values.crs == self.osgb arr = from_shapely(self.geoms) s = GeoSeries(arr, crs=27700) df = GeoDataFrame(geometry=s) assert df.crs == self.osgb assert df.geometry.crs == self.osgb assert df.geometry.values.crs == self.osgb # different passed CRS than array CRS is now an error match_str = "CRS mismatch between CRS of the passed geometries and 'crs'" with pytest.raises(ValueError, match=match_str): df = GeoDataFrame(geometry=s, crs=4326) with pytest.raises(ValueError, match=match_str): GeoDataFrame(geometry=s, crs=4326) with pytest.raises(ValueError, match=match_str): GeoDataFrame({"data": [1, 2], "geometry": s}, crs=4326) with pytest.raises(ValueError, match=match_str): GeoDataFrame(df, crs=4326).crs # manually change CRS arr = from_shapely(self.geoms) s = GeoSeries(arr, crs=27700) df = GeoDataFrame(geometry=s) df.crs = 4326 assert df.crs == self.wgs assert df.geometry.crs == self.wgs assert df.geometry.values.crs == self.wgs with pytest.raises(ValueError, match="Assigning CRS to a GeoDataFrame without"): GeoDataFrame(self.geoms, columns=["geom"], crs=27700) with pytest.raises(ValueError, match="Assigning CRS to a GeoDataFrame without"): GeoDataFrame(crs=27700) df = GeoDataFrame(self.geoms, columns=["geom"]) df = df.set_geometry("geom", crs=27700) assert df.crs == self.osgb assert df.geometry.crs == self.osgb assert df.geometry.values.crs == self.osgb assert df.geom.crs == self.osgb assert df.geom.values.crs == self.osgb df = GeoDataFrame(geometry=self.geoms, crs=27700) assert df.crs == self.osgb assert df.geometry.crs == self.osgb assert df.geometry.values.crs == self.osgb # new geometry with set CRS has priority over GDF CRS df = GeoDataFrame(geometry=self.geoms, crs=27700) df = df.set_geometry(self.geoms, crs=4326) assert df.crs == self.wgs assert df.geometry.crs == self.wgs assert df.geometry.values.crs == self.wgs arr = from_shapely(self.geoms) s = GeoSeries(arr, crs=27700) df = GeoDataFrame() df = df.set_geometry(s) assert df.crs == self.osgb assert df.geometry.crs == self.osgb assert df.geometry.values.crs == self.osgb arr = from_shapely(self.geoms, crs=27700) df = GeoDataFrame() df = df.set_geometry(arr) assert df.crs == self.osgb assert df.geometry.crs == self.osgb assert df.geometry.values.crs == self.osgb arr = from_shapely(self.geoms) df = GeoDataFrame({"col1": [1, 2], "geometry": arr}, crs=4326) assert df.crs == self.wgs assert df.geometry.crs == self.wgs assert df.geometry.values.crs == self.wgs arr = from_shapely(self.geoms, crs=4326) df = GeoDataFrame({"col1": [1, 2], "geometry": arr}) assert df.crs == self.wgs assert df.geometry.crs == self.wgs assert df.geometry.values.crs == self.wgs # geometry column without geometry df = GeoDataFrame({"geometry": [0, 1]}) df.crs = 27700 assert df.crs == self.osgb
def test_original(self): arr = from_shapely(self.geoms) s = GeoSeries(arr, crs=27700) assert arr.crs is None assert s.crs == self.osgb
from_shapely, from_wkb, from_wkt, points_from_xy, to_wkb, to_wkt, ) import pytest triangle_no_missing = [ shapely.geometry.Polygon([(random.random(), random.random()) for i in range(3)]) for _ in range(10) ] triangles = triangle_no_missing + [shapely.geometry.Polygon(), None] T = from_shapely(triangles) points_no_missing = [ shapely.geometry.Point(random.random(), random.random()) for _ in range(20) ] points = points_no_missing + [None] P = from_shapely(points) def equal_geometries(result, expected): for r, e in zip(result, expected): if r is None or e is None: if not (r is None and e is None): return False elif not r.equals(e): return False
s1 = GeoSeries([ Polygon([(0, 0), (2, 0), (2, 2), (0, 2)]), Polygon([(2, 2), (4, 2), (4, 4), (2, 4)]), ]) s2 = GeoSeries([ Polygon([(0, 2), (0, 0), (2, 0), (2, 2)]), Polygon([(2, 2), (4, 2), (4, 4), (2, 4)]), ]) s3 = Series([ Polygon([(0, 2), (0, 0), (2, 0), (2, 2)]), Polygon([(2, 2), (4, 2), (4, 4), (2, 4)]), ]) a = from_shapely([ Polygon([(0, 2), (0, 0), (2, 0), (2, 2)]), Polygon([(2, 2), (4, 2), (4, 4), (2, 4)]), ]) s4 = Series(a) df1 = GeoDataFrame({"col1": [1, 2], "geometry": s1}) df2 = GeoDataFrame({"col1": [1, 2], "geometry": s2}) s4 = s1.copy() s4.crs = 4326 s5 = s2.copy() s5.crs = 27700 s6 = GeoSeries([ Polygon([(0, 3), (0, 0), (2, 0), (2, 2)]), Polygon([(2, 2), (4, 2), (4, 4), (2, 4)]),
def _(dtype): a = np.array( [shapely.geometry.LineString([(i, i), (i, i + 1)]) for i in range(2)], dtype=object, ) return from_shapely(a)