diff --git a/python/cuspatial/cuspatial/core/binops/intersection.py b/python/cuspatial/cuspatial/core/binops/intersection.py index b043121aa..06e23a4e8 100644 --- a/python/cuspatial/cuspatial/core/binops/intersection.py +++ b/python/cuspatial/cuspatial/core/binops/intersection.py @@ -53,7 +53,7 @@ def pairwise_linestring_intersection( if len(linestrings1) == 0 and len(linestrings2) == 0: return ( - cudf.Series([0]), + cudf.Series([0], dtype="i4"), GeoSeries([]), cudf.DataFrame( { @@ -61,7 +61,8 @@ def pairwise_linestring_intersection( "lhs_segment_id": [], "rhs_linestring_id": [], "rhs_segment_id": [], - } + }, + dtype="i4", ), ) diff --git a/python/cuspatial/cuspatial/core/geoseries.py b/python/cuspatial/cuspatial/core/geoseries.py index 9fa1e316b..64a977ec5 100644 --- a/python/cuspatial/cuspatial/core/geoseries.py +++ b/python/cuspatial/cuspatial/core/geoseries.py @@ -698,7 +698,11 @@ def from_points_xy(cls, points_xy): GeoSeries: A GeoSeries made of the points. """ - return cls(GeoColumn._from_points_xy(as_column(points_xy))) + coords_dtype = _check_coords_dtype(points_xy) + + return cls( + GeoColumn._from_points_xy(as_column(points_xy, dtype=coords_dtype)) + ) @classmethod def from_multipoints_xy(cls, multipoints_xy, geometry_offset): @@ -707,8 +711,9 @@ def from_multipoints_xy(cls, multipoints_xy, geometry_offset): Parameters ---------- - points_xy: array-like - Coordinates of the points, interpreted as interleaved x-y coords. + multipoints_xy: array-like + Coordinates of the multipoints, interpreted as interleaved x-y + coords. geometry_offset: array-like Offsets indicating the starting index of the multipoint. Multiply the index by 2 results in the starting index of the coordinate. @@ -729,9 +734,10 @@ def from_multipoints_xy(cls, multipoints_xy, geometry_offset): 1 MULTIPOINT (2.00000 2.00000, 3.00000 3.00000) dtype: geometry """ + coords_dtype = coords_dtype = _check_coords_dtype(multipoints_xy) return cls( GeoColumn._from_multipoints_xy( - as_column(multipoints_xy), + as_column(multipoints_xy, dtype=coords_dtype), as_column(geometry_offset, dtype="int32"), ) ) @@ -746,7 +752,8 @@ def from_linestrings_xy( Parameters ---------- linestrings_xy : array-like - Coordinates of the points, interpreted as interleaved x-y coords. + Coordinates of the linestring, interpreted as interleaved x-y + coords. geometry_offset : array-like Offsets of the first coordinate of each geometry. The length of this array is the number of geometries. Offsets with a difference @@ -773,9 +780,10 @@ def from_linestrings_xy( 0 LINESTRING (0 0, 1 1, 2 2, 3 3, 4 4, 5 5) dtype: geometry """ + coords_dtype = _check_coords_dtype(linestrings_xy) return cls( GeoColumn._from_linestrings_xy( - as_column(linestrings_xy), + as_column(linestrings_xy, dtype=coords_dtype), as_column(part_offset, dtype="int32"), as_column(geometry_offset, dtype="int32"), ) @@ -822,9 +830,10 @@ def from_polygons_xy( 0 POLYGON (0 0, 1 1, 2 2, 3 3, 4 4, 5 5) dtype: geometry """ + coords_dtype = _check_coords_dtype(polygons_xy) return cls( GeoColumn._from_polygons_xy( - as_column(polygons_xy), + as_column(polygons_xy, dtype=coords_dtype), as_column(ring_offset, dtype="int32"), as_column(part_offset, dtype="int32"), as_column(geometry_offset, dtype="int32"), @@ -1001,15 +1010,14 @@ def reset_index( # The columns of the `cudf.DataFrame` are the new # columns of the `GeoDataFrame`. columns = { - col: cudf_result[col] for col in cudf_result.columns + col: cudf_result[col] + for col in cudf_result.columns + if col is not None } geo_result = GeoDataFrame(columns) geo_series.index = geo_result.index # Add the original `GeoSeries` as a column. - if name: - geo_result[name] = geo_series - else: - geo_result[0] = geo_series + geo_result[name] = geo_series return geo_result else: self.index = cudf_series.index @@ -1483,3 +1491,10 @@ def distance(self, other, align=True): if other_is_scalar: res.index = self.index return res + + +def _check_coords_dtype(coords): + if hasattr(coords, "dtype"): + return coords.dtype + else: + return "f8" if len(coords) == 0 else None diff --git a/python/cuspatial/cuspatial/core/spatial/nearest_points.py b/python/cuspatial/cuspatial/core/spatial/nearest_points.py index 7b65155a8..9098d7864 100644 --- a/python/cuspatial/cuspatial/core/spatial/nearest_points.py +++ b/python/cuspatial/cuspatial/core/spatial/nearest_points.py @@ -1,5 +1,6 @@ import cupy as cp +import cudf from cudf.core.column import as_column import cuspatial._lib.nearest_points as nearest_points @@ -51,9 +52,9 @@ def pairwise_point_linestring_nearest_points( if len(points) == 0: data = { - "point_geometry_id": [], - "linestring_geometry_id": [], - "segment_id": [], + "point_geometry_id": cudf.Series([], dtype="i4"), + "linestring_geometry_id": cudf.Series([], dtype="i4"), + "segment_id": cudf.Series([], dtype="i4"), "geometry": GeoSeries([]), } return GeoDataFrame._from_data(data) diff --git a/python/cuspatial/cuspatial/core/trajectory.py b/python/cuspatial/cuspatial/core/trajectory.py index b62fead9f..be779313f 100644 --- a/python/cuspatial/cuspatial/core/trajectory.py +++ b/python/cuspatial/cuspatial/core/trajectory.py @@ -122,6 +122,16 @@ def trajectory_bounding_boxes(num_trajectories, object_ids, points: GeoSeries): 1 1.0 1.0 3.0 3.0 """ + if len(points) == 0: + return DataFrame( + { + "x_min": Series([], dtype=points.points.x.dtype), + "y_min": Series([], dtype=points.points.x.dtype), + "x_max": Series([], dtype=points.points.x.dtype), + "y_max": Series([], dtype=points.points.x.dtype), + } + ) + if len(points) > 0 and not contains_only_points(points): raise ValueError("`points` must only contain point geometries.") diff --git a/python/cuspatial/cuspatial/tests/basicpreds/test_intersections.py b/python/cuspatial/cuspatial/tests/basicpreds/test_intersections.py index 37891366a..993eb72a8 100644 --- a/python/cuspatial/cuspatial/tests/basicpreds/test_intersections.py +++ b/python/cuspatial/cuspatial/tests/basicpreds/test_intersections.py @@ -22,7 +22,7 @@ def test_empty(): s1 = gpd.GeoSeries([]) s2 = gpd.GeoSeries([]) - expect_offset = pd.Series([0]) + expect_offset = pd.Series([0], dtype="i4") expect_geom = gpd.GeoSeries([]) expect_ids = pd.DataFrame( { @@ -30,7 +30,8 @@ def test_empty(): "lhs_segment_id": [], "rhs_linestring_id": [], "rhs_segment_id": [], - } + }, + dtype="i4", ) run_test(s1, s2, expect_offset, expect_geom, expect_ids) diff --git a/python/cuspatial/cuspatial/tests/spatial/bounding/test_linestring_bounding_boxes.py b/python/cuspatial/cuspatial/tests/spatial/bounding/test_linestring_bounding_boxes.py index 154f6a22c..73984782b 100644 --- a/python/cuspatial/cuspatial/tests/spatial/bounding/test_linestring_bounding_boxes.py +++ b/python/cuspatial/cuspatial/tests/spatial/bounding/test_linestring_bounding_boxes.py @@ -18,10 +18,10 @@ def test_linestring_bounding_boxes_empty(): result, cudf.DataFrame( { - "minx": cudf.Series([]), - "miny": cudf.Series([]), - "maxx": cudf.Series([]), - "maxy": cudf.Series([]), + "minx": cudf.Series([], dtype=np.float64), + "miny": cudf.Series([], dtype=np.float64), + "maxx": cudf.Series([], dtype=np.float64), + "maxy": cudf.Series([], dtype=np.float64), } ), ) diff --git a/python/cuspatial/cuspatial/tests/spatial/join/test_point_in_polygon.py b/python/cuspatial/cuspatial/tests/spatial/join/test_point_in_polygon.py index 89f076c17..d4fb1d819 100644 --- a/python/cuspatial/cuspatial/tests/spatial/join/test_point_in_polygon.py +++ b/python/cuspatial/cuspatial/tests/spatial/join/test_point_in_polygon.py @@ -247,7 +247,7 @@ def test_pip_bitmap_column_to_binary_array(): ) np.testing.assert_array_equal(got.copy_to_host(), expected) - col = cudf.Series([])._column + col = cudf.Series([], dtype="i8")._column got = pip_bitmap_column_to_binary_array(col, width=0) expected = np.array([], dtype="int8").reshape(0, 0) np.testing.assert_array_equal(got.copy_to_host(), expected) diff --git a/python/cuspatial/cuspatial/tests/spatial/nearest_points/test_nearest_points.py b/python/cuspatial/cuspatial/tests/spatial/nearest_points/test_nearest_points.py index 9c94a1106..77280ac50 100644 --- a/python/cuspatial/cuspatial/tests/spatial/nearest_points/test_nearest_points.py +++ b/python/cuspatial/cuspatial/tests/spatial/nearest_points/test_nearest_points.py @@ -1,4 +1,5 @@ import geopandas as gpd +import pandas as pd import pytest import shapely from geopandas.testing import assert_geodataframe_equal @@ -73,9 +74,9 @@ def test_empty_input(): ) expected = gpd.GeoDataFrame( { - "point_geometry_id": [], - "linestring_geometry_id": [], - "segment_id": [], + "point_geometry_id": pd.Series([], dtype="i4"), + "linestring_geometry_id": pd.Series([], dtype="i4"), + "segment_id": pd.Series([], dtype="i4"), "geometry": gpd.GeoSeries(), } ) diff --git a/python/cuspatial/cuspatial/tests/test_geodataframe.py b/python/cuspatial/cuspatial/tests/test_geodataframe.py index a3e96a0fb..f49708cf8 100644 --- a/python/cuspatial/cuspatial/tests/test_geodataframe.py +++ b/python/cuspatial/cuspatial/tests/test_geodataframe.py @@ -435,8 +435,20 @@ def test_reset_index(level, drop, inplace, col_level, col_fill): index=midx, ) gdf = cuspatial.from_geopandas(gpdf) - expected = gpdf.reset_index(level, drop, inplace, col_level, col_fill) - got = gdf.reset_index(level, drop, inplace, col_level, col_fill) + expected = gpdf.reset_index( + level=level, + drop=drop, + inplace=inplace, + col_level=col_level, + col_fill=col_fill, + ) + got = gdf.reset_index( + level=level, + drop=drop, + inplace=inplace, + col_level=col_level, + col_fill=col_fill, + ) if inplace: expected = gpdf got = gdf diff --git a/python/cuspatial/cuspatial/tests/test_geoseries.py b/python/cuspatial/cuspatial/tests/test_geoseries.py index ce2f8ff3a..a865049a8 100644 --- a/python/cuspatial/cuspatial/tests/test_geoseries.py +++ b/python/cuspatial/cuspatial/tests/test_geoseries.py @@ -576,8 +576,10 @@ def test_reset_index(level, drop, name, inplace): [Point(0, 0), Point(0, 1), Point(2, 2), Point(3, 3)], index=midx ) gs = cuspatial.from_geopandas(gps) - expected = gps.reset_index(level, drop, name, inplace) - got = gs.reset_index(level, drop, name, inplace) + expected = gps.reset_index( + level=level, drop=drop, name=name, inplace=inplace + ) + got = gs.reset_index(level=level, drop=drop, name=name, inplace=inplace) if inplace: expected = gps got = gs