Skip to content

Commit

Permalink
Merge pull request #756 from knaaptime/pdnagraph
Browse files Browse the repository at this point in the history
exposing mapping_distance in travel builder
  • Loading branch information
knaaptime authored Jul 18, 2024
2 parents 01d41cf + 099bcfc commit 0fb5c25
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 11 deletions.
14 changes: 8 additions & 6 deletions libpysal/graph/_network.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,7 @@ def pdna_to_adj(origins, network, node_ids, threshold):
return adj


def build_travel_graph(
df,
network,
threshold,
):
def build_travel_graph(df, network, threshold, mapping_distance):
"""Compute the shortest path between gdf centroids via a pandana.Network
and return an adjacency list with weight=cost. Note unlike distance_band,
:math:`G_{ij}` and :math:`G_{ji}` are often different because travel networks
Expand All @@ -81,6 +77,10 @@ def build_travel_graph(
Network that encodes travel costs. See <https://udst.github.io/pandana/>
threshold : int
maximum travel cost to consider neighbors
mapping_distance : int
snapping tolerance passed to ``pandana.Network.get_node_ids`` that defines
the maximum range at which observations are snapped to nearest nodes in the
network. Default is None
Returns
-------
Expand All @@ -89,7 +89,9 @@ def build_travel_graph(
"""
df = df.copy()
_validate_geometry_input(df.geometry, ids=None, valid_geometry_types="Point")
df["node_ids"] = network.get_node_ids(df.geometry.x, df.geometry.y)
df["node_ids"] = network.get_node_ids(
df.geometry.x, df.geometry.y, mapping_distance
)

# depending on density of the graph nodes / observations, it is common to have
# multiple observations snapped to the same network node, so use the clique
Expand Down
17 changes: 12 additions & 5 deletions libpysal/graph/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -1456,18 +1456,21 @@ def build_h3(cls, ids, order=1, weight="distance"):
raise ValueError("weight must be one of 'distance', 'binary', or 'inverse'")

@classmethod
def build_travel_cost(cls, df, network, threshold, kernel=None):
def build_travel_cost(
cls, df, network, threshold, kernel=None, mapping_distance=None
):
"""Generate a Graph based on shortest travel costs from a pandana.Network
Parameters
----------
df : geopandas.GeoDataFrame
geodataframe representing observations which are snapped to the nearest
node in the pandana.Network. If passing polygon geometries, the spatial
support will be reduced to Points (via centroid) before snapping.
node in the pandana.Network. CRS should be the same as the locations
of ``node_x`` and ``node_y`` in the pandana.Network (usually 4326 if network
comes from OSM, but sometimes projected to improve snapping quality).
network : pandana.Network
pandana Network object describing travel costs between nodes in the study
area
area. See <https://udst.github.io/pandana/> for more
threshold : int
threshold representing maximum cost distances. This is measured in the same
units as the pandana.Network (not influenced by the df.crs in any way). For
Expand All @@ -1480,6 +1483,10 @@ def build_travel_cost(cls, df, network, threshold, kernel=None):
libpysal.graph.Graph.build_kernel for more information on kernel
transformation options. Default is None, in which case the Graph weight
is pure distance between focal and neighbor
mapping_distance : int
snapping tolerance passed to ``pandana.Network.get_node_ids`` that defines
the maximum range at which observations are snapped to nearest nodes in the
network. Default is None
Returns
-------
Expand Down Expand Up @@ -1524,7 +1531,7 @@ def build_travel_cost(cls, df, network, threshold, kernel=None):
117 333.639008
Name: weight, dtype: float64
"""
adj = _build_travel_graph(df, network, threshold)
adj = _build_travel_graph(df, network, threshold, mapping_distance)
g = cls.from_adjacency(adj)
if kernel is not None:
arrays = _kernel(
Expand Down

0 comments on commit 0fb5c25

Please sign in to comment.