def create_sub_graph(self, poi) -> cugraph.Graph: """ Create a subgraph of road nodes based on buffer distance The subgraph is created using euclidean distance and `cuspatial.points_in_spatial_window`. If buffers are not large enough to include all nodes identified as important to that particular POI, it is increased in size. Parameters ---------- poi : namedtuple Single POI created by `df.itertuples()` Returns ------- cugraph.Graph: Graph object that is a subset of all road nodes """ buffer = max(poi.buffer, self.buffer) while True: node_subset = cuspatial.points_in_spatial_window( min_x=poi.easting - buffer, max_x=poi.easting + buffer, min_y=poi.northing - buffer, max_y=poi.northing + buffer, xs=self.nodes["easting"], ys=self.nodes["northing"], ) node_subset = node_subset.merge(self.nodes, left_on=["x", "y"], right_on=["easting", "northing" ]).drop(["x", "y"], axis=1) sub_source = self.edges.merge(node_subset, left_on="source", right_on="node_id") sub_target = self.edges.merge(node_subset, left_on="target", right_on="node_id") sub_edges = sub_source.append(sub_target).drop_duplicates( ["source", "target"]) sub_graph = cugraph.Graph() sub_graph.from_cudf_edgelist( sub_edges, source="source", destination="target", edge_attr=self.weights, renumber=False, ) pc_nodes = cudf.Series(poi.pc_node).isin(sub_graph.nodes()).sum() poi_node = sub_graph.nodes().isin([poi.node_id]).sum() # ensure all postcode nodes in + poi node # don't incrase buffer for large pois lists if poi_node & ((pc_nodes == len(poi.pc_node)) or (len(self.pois) > 100_000)): return sub_graph buffer = buffer * 2 print(f"{poi.Index=}: increasing {buffer=}")
def test_pair(): result = cuspatial.points_in_spatial_window(-1.1, 1.1, -1.1, 1.1, cudf.Series([0.0, 1.0]), cudf.Series([1.0, 0.0])) cudf.testing.assert_frame_equal( result, cudf.DataFrame({ "x": [0.0, 1.0], "y": [1.0, 0.0] }))
def test_corners(coords): x, y = coords result = cuspatial.points_in_spatial_window(-1.1, 1.1, -1.1, 1.1, cudf.Series([x]), cudf.Series([y])) cudf.testing.assert_frame_equal(result, cudf.DataFrame({ "x": [x], "y": [y] }))
def test_half(): result = cuspatial.points_in_spatial_window( -2, 2, -2, 2, cudf.Series([-1.0, 1.0, 3.0, -3.0]), cudf.Series([1.0, -1.0, 3.0, -3.0]), ) print(result) assert_eq(result, cudf.DataFrame({"x": [-1.0, 1.0], "y": [1.0, -1.0]}))
def test_zeros(): result = cuspatial.points_in_spatial_window( # noqa: F841 0, 0, 0, 0, cudf.Series([0.0]), cudf.Series([0.0])) assert result.empty
def test_oob(): result = cuspatial.points_in_spatial_window(-1, 1, -1, 1, cudf.Series([-2.0, 2.0]), cudf.Series([2.0, -2.0])) cudf.testing.assert_frame_equal(result, cudf.DataFrame({"x": [], "y": []}))
def test_centered(): result = cuspatial.points_in_spatial_window(-1, 1, -1, 1, cudf.Series([0.0]), cudf.Series([0.0])) assert_eq(result, cudf.DataFrame({"x": [0.0], "y": [0.0]}))