Skip to content

Commit

Permalink
Ensure Cython bindings only interact with pylibcudf objects (#1523)
Browse files Browse the repository at this point in the history
Follow up to #1514

Addressing the review in #1514 (comment) by ensuring the Cython bindings return pylibcudf objects where possible instead of python objects (like cudf Python columns) so we can also have better return annotations for these methods where appropriate. Subsequently, the conversion from pylibcudf to cudf Python has been moved to the cuspatial Python layer.

Additionally, this PR will be necessary for rapidsai/cudf#17760 not to break cuspatial

Authors:
  - Matthew Roeschke (https://github.com/mroeschke)
  - Michael Wang (https://github.com/isVoid)
  - Bradley Dice (https://github.com/bdice)

Approvers:
  - Michael Wang (https://github.com/isVoid)
  - Bradley Dice (https://github.com/bdice)

URL: #1523
  • Loading branch information
mroeschke authored Feb 3, 2025
1 parent 536075f commit 57a34d7
Show file tree
Hide file tree
Showing 25 changed files with 313 additions and 307 deletions.
26 changes: 11 additions & 15 deletions python/cuspatial/cuspatial/_lib/distance.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
from libcpp.memory cimport make_shared, shared_ptr, unique_ptr
from libcpp.utility cimport move, pair

from cudf.core.column.column import Column
from pylibcudf cimport Column as plc_Column, Table as plc_Table
from pylibcudf.libcudf.column.column cimport column
from pylibcudf.libcudf.column.column_view cimport column_view
Expand All @@ -26,7 +25,7 @@ from cuspatial._lib.cpp.types cimport collection_type_id, geometry_type_id
from cuspatial._lib.types cimport collection_type_py_to_c


cpdef haversine_distance(
cpdef plc_Column haversine_distance(
plc_Column x1,
plc_Column y1,
plc_Column x2,
Expand All @@ -42,7 +41,7 @@ cpdef haversine_distance(
with nogil:
c_result = move(cpp_haversine_distance(c_x1, c_y1, c_x2, c_y2))

return Column.from_pylibcudf(plc_Column.from_libcudf(move(c_result)))
return plc_Column.from_libcudf(move(c_result))


def directed_hausdorff_distance(
Expand All @@ -65,17 +64,14 @@ def directed_hausdorff_distance(
)
)

owner_col = Column.from_pylibcudf(
plc_Column.from_libcudf(move(result.first)),
data_ptr_exposed=True
)
cdef plc_Column owner_col = plc_Column.from_libcudf(move(result.first))
cdef plc_Table plc_owner_table = plc_Table(
[owner_col.to_pylibcudf(mode="read")] * result.second.num_columns()
[owner_col] * result.second.num_columns()
)
cdef plc_Table plc_result_table = plc_Table.from_table_view(
result.second, plc_owner_table
)
return [Column.from_pylibcudf(col) for col in plc_result_table.columns()]
return plc_result_table.columns()


def pairwise_point_distance(
Expand Down Expand Up @@ -108,7 +104,7 @@ def pairwise_point_distance(
c_multipoints_lhs.get()[0],
c_multipoints_rhs.get()[0],
))
return Column.from_pylibcudf(plc_Column.from_libcudf(move(c_result)))
return plc_Column.from_libcudf(move(c_result))


def pairwise_linestring_distance(
Expand All @@ -134,7 +130,7 @@ def pairwise_linestring_distance(
c_multilinestring_rhs.get()[0],
))

return Column.from_pylibcudf(plc_Column.from_libcudf(move(c_result)))
return plc_Column.from_libcudf(move(c_result))


def pairwise_point_linestring_distance(
Expand Down Expand Up @@ -164,7 +160,7 @@ def pairwise_point_linestring_distance(
c_multilinestrings.get()[0],
))

return Column.from_pylibcudf(plc_Column.from_libcudf(move(c_result)))
return plc_Column.from_libcudf(move(c_result))


def pairwise_point_polygon_distance(
Expand Down Expand Up @@ -195,7 +191,7 @@ def pairwise_point_polygon_distance(
c_multipoints.get()[0], c_multipolygons.get()[0]
))

return Column.from_pylibcudf(plc_Column.from_libcudf(move(c_result)))
return plc_Column.from_libcudf(move(c_result))


def pairwise_linestring_polygon_distance(
Expand All @@ -221,7 +217,7 @@ def pairwise_linestring_polygon_distance(
c_multilinestrings.get()[0], c_multipolygons.get()[0]
))

return Column.from_pylibcudf(plc_Column.from_libcudf(move(c_result)))
return plc_Column.from_libcudf(move(c_result))


def pairwise_polygon_distance(plc_Column lhs, plc_Column rhs):
Expand All @@ -244,4 +240,4 @@ def pairwise_polygon_distance(plc_Column lhs, plc_Column rhs):
c_lhs.get()[0], c_rhs.get()[0]
))

return Column.from_pylibcudf(plc_Column.from_libcudf(move(c_result)))
return plc_Column.from_libcudf(move(c_result))
45 changes: 12 additions & 33 deletions python/cuspatial/cuspatial/_lib/intersection.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
from libcpp.memory cimport make_shared, shared_ptr
from libcpp.utility cimport move

from cudf.core.column.column import Column
from pylibcudf cimport Column as plc_Column

from cuspatial._lib.types import CollectionType, GeometryType
Expand All @@ -26,8 +25,6 @@ def pairwise_linestring_intersection(plc_Column lhs, plc_Column rhs):
"""
Compute the intersection of two (multi)linestrings.
"""
from cuspatial.core._column.geometa import Feature_Enum

cdef linestring_intersection_column_result c_result
cdef collection_type_id multi_type = <collection_type_id>(
<underlying_collection_type_id_t>(CollectionType.MULTI.value)
Expand All @@ -52,39 +49,21 @@ def pairwise_linestring_intersection(plc_Column lhs, plc_Column rhs):
c_lhs.get()[0], c_rhs.get()[0]
))

geometry_collection_offset = Column.from_pylibcudf(
plc_Column.from_libcudf(move(c_result.geometry_collection_offset))
)

types_buffer = Column.from_pylibcudf(
plc_Column.from_libcudf(move(c_result.types_buffer))
)
offset_buffer = Column.from_pylibcudf(
plc_Column.from_libcudf(move(c_result.offset_buffer))
)
points = Column.from_pylibcudf(
plc_Column.from_libcudf(move(c_result.points))
geometry_collection_offset = plc_Column.from_libcudf(
move(c_result.geometry_collection_offset)
)
segments = Column.from_pylibcudf(
plc_Column.from_libcudf(move(c_result.segments))
types_buffer = plc_Column.from_libcudf(move(c_result.types_buffer))
offset_buffer = plc_Column.from_libcudf(move(c_result.offset_buffer))
points = plc_Column.from_libcudf(move(c_result.points))
segments = plc_Column.from_libcudf(move(c_result.segments))
lhs_linestring_id = plc_Column.from_libcudf(
move(c_result.lhs_linestring_id)
)
lhs_linestring_id = Column.from_pylibcudf(
plc_Column.from_libcudf(move(c_result.lhs_linestring_id))
)
lhs_segment_id = Column.from_pylibcudf(
plc_Column.from_libcudf(move(c_result.lhs_segment_id))
)
rhs_linestring_id = Column.from_pylibcudf(
plc_Column.from_libcudf(move(c_result.rhs_linestring_id))
)
rhs_segment_id = Column.from_pylibcudf(
plc_Column.from_libcudf(move(c_result.rhs_segment_id))
)

# Map linestring type codes from libcuspatial to cuspatial
types_buffer[types_buffer == GeometryType.LINESTRING.value] = (
Feature_Enum.LINESTRING.value
lhs_segment_id = plc_Column.from_libcudf(move(c_result.lhs_segment_id))
rhs_linestring_id = plc_Column.from_libcudf(
move(c_result.rhs_linestring_id)
)
rhs_segment_id = plc_Column.from_libcudf(move(c_result.rhs_segment_id))

return ((geometry_collection_offset,
types_buffer,
Expand Down
15 changes: 7 additions & 8 deletions python/cuspatial/cuspatial/_lib/linestring_bounding_boxes.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
from libcpp.memory cimport unique_ptr
from libcpp.utility cimport move

from cudf.core.column.column import Column
from pylibcudf cimport Column as plc_Column, Table as plc_Table
from pylibcudf.libcudf.column.column_view cimport column_view
from pylibcudf.libcudf.table.table cimport table
Expand All @@ -13,9 +12,12 @@ from cuspatial._lib.cpp.linestring_bounding_boxes cimport (
)


cpdef linestring_bounding_boxes(plc_Column poly_offsets,
plc_Column x, plc_Column y,
double R):
cpdef list linestring_bounding_boxes(
plc_Column poly_offsets,
plc_Column x,
plc_Column y,
double R
):
cdef column_view c_poly_offsets = poly_offsets.view()
cdef column_view c_x = x.view()
cdef column_view c_y = y.view()
Expand All @@ -25,7 +27,4 @@ cpdef linestring_bounding_boxes(plc_Column poly_offsets,
c_poly_offsets, c_x, c_y, R
))
cdef plc_Table plc_table = plc_Table.from_libcudf(move(result))
return [
Column.from_pylibcudf(col)
for col in plc_table.columns()
]
return plc_table.columns()
19 changes: 7 additions & 12 deletions python/cuspatial/cuspatial/_lib/nearest_points.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

from libcpp.utility cimport move

from cudf.core.column.column import Column
from pylibcudf cimport Column as plc_Column
from pylibcudf.libcudf.column.column_view cimport column_view

Expand Down Expand Up @@ -42,22 +41,18 @@ def pairwise_point_linestring_nearest_points(

multipoint_geometry_id = None
if multipoint_geometry_offset is not None:
multipoint_geometry_id = Column.from_pylibcudf(plc_Column.from_libcudf(
move(c_result.nearest_point_geometry_id.value())))
multipoint_geometry_id = plc_Column.from_libcudf(
move(c_result.nearest_point_geometry_id.value()))

multilinestring_geometry_id = None
if multilinestring_geometry_offset is not None:
multilinestring_geometry_id = Column.from_pylibcudf(
plc_Column.from_libcudf(
move(c_result.nearest_linestring_geometry_id.value())
)
multilinestring_geometry_id = plc_Column.from_libcudf(
move(c_result.nearest_linestring_geometry_id.value())
)

segment_id = Column.from_pylibcudf(
plc_Column.from_libcudf(move(c_result.nearest_segment_id))
)
point_on_linestring_xy = Column.from_pylibcudf(plc_Column.from_libcudf(
move(c_result.nearest_point_on_linestring_xy)))
segment_id = plc_Column.from_libcudf(move(c_result.nearest_segment_id))
point_on_linestring_xy = plc_Column.from_libcudf(
move(c_result.nearest_point_on_linestring_xy))

return (
multipoint_geometry_id,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
from libcpp.memory cimport make_shared, shared_ptr, unique_ptr
from libcpp.utility cimport move

from cudf.core.column.column import Column
from pylibcudf cimport Column as plc_Column
from pylibcudf.libcudf.column.column cimport column

Expand Down Expand Up @@ -42,4 +41,4 @@ def pairwise_multipoint_equals_count(
)
)

return Column.from_pylibcudf(plc_Column.from_libcudf(move(result)))
return plc_Column.from_libcudf(move(result))
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
from libcpp.memory cimport unique_ptr
from libcpp.utility cimport move

from cudf.core.column.column import Column
from pylibcudf cimport Column as plc_Column
from pylibcudf.libcudf.column.column cimport column
from pylibcudf.libcudf.column.column_view cimport column_view
Expand Down Expand Up @@ -42,4 +41,4 @@ def pairwise_point_in_polygon(
)
)

return Column.from_pylibcudf(plc_Column.from_libcudf(move(result)))
return plc_Column.from_libcudf(move(result))
3 changes: 1 addition & 2 deletions python/cuspatial/cuspatial/_lib/point_in_polygon.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
from libcpp.memory cimport unique_ptr
from libcpp.utility cimport move

from cudf.core.column.column import Column
from pylibcudf cimport Column as plc_Column
from pylibcudf.libcudf.column.column cimport column
from pylibcudf.libcudf.column.column_view cimport column_view
Expand Down Expand Up @@ -42,4 +41,4 @@ def point_in_polygon(
)
)

return Column.from_pylibcudf(plc_Column.from_libcudf(move(result)))
return plc_Column.from_libcudf(move(result))
13 changes: 2 additions & 11 deletions python/cuspatial/cuspatial/_lib/points_in_range.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
from libcpp.memory cimport unique_ptr
from libcpp.utility cimport move

from cudf.core.column.column import Column
from pylibcudf cimport Column as plc_Column, Table as plc_Table
from pylibcudf.libcudf.column.column_view cimport column_view
from pylibcudf.libcudf.table.table cimport table
Expand All @@ -13,7 +12,7 @@ from cuspatial._lib.cpp.points_in_range cimport (
)


cpdef points_in_range(
cpdef plc_Table points_in_range(
double range_min_x,
double range_max_x,
double range_min_y,
Expand All @@ -37,12 +36,4 @@ cpdef points_in_range(
y_v
)
)

cdef plc_Table plc_table = plc_Table.from_libcudf(move(c_result))
return (
{
name: Column.from_pylibcudf(col)
for name, col in zip(["x", "y"], plc_table.columns())
},
None
)
return plc_Table.from_libcudf(move(c_result))
15 changes: 7 additions & 8 deletions python/cuspatial/cuspatial/_lib/polygon_bounding_boxes.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
from libcpp.memory cimport unique_ptr
from libcpp.utility cimport move

from cudf.core.column.column import Column
from pylibcudf cimport Column as plc_Column, Table as plc_Table
from pylibcudf.libcudf.column.column_view cimport column_view
from pylibcudf.libcudf.table.table cimport table
Expand All @@ -13,9 +12,12 @@ from cuspatial._lib.cpp.polygon_bounding_boxes cimport (
)


cpdef polygon_bounding_boxes(plc_Column poly_offsets,
plc_Column ring_offsets,
plc_Column x, plc_Column y):
cpdef list polygon_bounding_boxes(
plc_Column poly_offsets,
plc_Column ring_offsets,
plc_Column x,
plc_Column y,
):
cdef column_view c_poly_offsets = poly_offsets.view()
cdef column_view c_ring_offsets = ring_offsets.view()
cdef column_view c_x = x.view()
Expand All @@ -26,7 +28,4 @@ cpdef polygon_bounding_boxes(plc_Column poly_offsets,
c_poly_offsets, c_ring_offsets, c_x, c_y
))
cdef plc_Table table_result = plc_Table.from_libcudf(move(result))
return [
Column.from_pylibcudf(col)
for col in table_result.columns()
]
return table_result.columns()
36 changes: 13 additions & 23 deletions python/cuspatial/cuspatial/_lib/quadtree.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ from libcpp.memory cimport unique_ptr
from libcpp.pair cimport pair
from libcpp.utility cimport move

from cudf.core.column.column import Column
from pylibcudf cimport Column as plc_Column, Table as plc_Table
from pylibcudf.libcudf.column.column cimport column
from pylibcudf.libcudf.column.column_view cimport column_view
Expand All @@ -17,34 +16,25 @@ from cuspatial._lib.cpp.quadtree cimport (
)


cpdef quadtree_on_points(plc_Column x, plc_Column y,
double x_min, double x_max,
double y_min, double y_max,
double scale,
int8_t max_depth,
size_type min_size):
cpdef tuple quadtree_on_points(
plc_Column x,
plc_Column y,
double x_min,
double x_max,
double y_min,
double y_max,
double scale,
int8_t max_depth,
size_type min_size,
):
cdef column_view c_x = x.view()
cdef column_view c_y = y.view()
cdef pair[unique_ptr[column], unique_ptr[table]] result
with nogil:
result = move(cpp_quadtree_on_points(
c_x, c_y, x_min, x_max, y_min, y_max, scale, max_depth, min_size
))
cdef plc_Table plc_table = plc_Table.from_libcudf(move(result.second))
result_names = [
"key",
"level",
"is_internal_node",
"length",
"offset"
]
return (
Column.from_pylibcudf(plc_Column.from_libcudf(move(result.first))),
(
{
name: Column.from_pylibcudf(col)
for name, col in zip(result_names, plc_table.columns())
},
None
)
plc_Column.from_libcudf(move(result.first)),
plc_Table.from_libcudf(move(result.second))
)
Loading

0 comments on commit 57a34d7

Please sign in to comment.