Internal API

This is the complete metroscore internals reference for developers, including private internal modules and functions. If you are instead looking for a user guide to metroscore’s public API, see the API.

metroscore.point_selection module

class metroscore.point_selection.Coordinate(lon, lat)
_asdict()

Return a new dict which maps field names to their values.

classmethod _make(iterable)

Make a new Coordinate object from a sequence or iterable

_replace(**kwds)

Return a new Coordinate object replacing specified fields with new values

lat

Alias for field number 1

lon

Alias for field number 0

metroscore.point_selection.make_hex_points(polygon, N=10)

Creates N points that form a tessellating hex pattern within the provided polygon.

Parameters:
  • polygon (Polygon) – shapely.geometry.Polygon

  • N (int, optional) – Number of points to generate. Defaults to 10.

Returns:

List[Coordinate] – List of Coordinate (longitude, latitude) points.

Return type:

List[Coordinate]

metroscore.point_selection.make_random_points(polygon, N=10)

Creates N random points within the polygon polygon.

Parameters:
  • polygon (Polygon) – shapely.geometry.Polygon

  • N (int, optional) – Number of points to generate. Defaults to 10.

Returns:

List[Coordinate] – List of Coordinate (longitude, latitude) points.

Return type:

List[Coordinate]

metroscore.network_builder module

metroscore.network_builder.deduplicate_stops(stops, tol=100)

Combine stops if they are within tol meters of each other and they have the same name If not, give them each a unique name by adding a number to the end

Returns a DataFrame with the deduplicated stops and a dict that maps the original stop names to the new stop names

metroscore.service_areas module

metroscore.service_areas.get_next_departure_time(curr_time, origin_id, dest_id, timetable)

Get the departure time from origin node to destination node.

Parameters:
  • curr_time (float)

  • origin_id (int)

  • dest_id (int)

  • timetable (pandas.Series)

metroscore.service_areas.get_transit_areas(travel_times, cutoffs, node_gdf, use_walking_buffer=False)

Get the polygons of reachable areas from a given origin.

Parameters:
  • travel_times (Dict[int, float]) – Dictionary of node IDs and travel times.

  • cutoffs (List[float]) – List of travel time cutoffs.

  • node_gdf (gpd.GeoDataFrame) – GeoDataFrame of nodes and their locations (Points). Should be indexed by stop_id.

  • use_walking_buffer (bool, optional) – Whether to use a walking buffer around nodes. Defaults to False. If true, buffers are computed around all reachable nodes using the remaining time until the cutoff is reached. This can result in overly “spherical” transit areas that ignore geographical features like bodies of water. If false, the buffer around each reachable node is constant and small. When used with a properly configured graph that contains walking nodes, this can result in more realistic transit areas.

Return type:

geopandas.GeoSeries

Note that it is assumed that the travel times in travel_times and cutoffs are in the same units.

Returns:

GeoSeries – GeoSeries of travel time cutoffs and reachable areas.

Parameters:
  • travel_times (Dict[int, float])

  • cutoffs (List[float])

  • node_gdf (geopandas.GeoDataFrame)

  • use_walking_buffer (bool)

Return type:

geopandas.GeoSeries

metroscore.service_areas.time_dependent_a_star(G, timetable, start_time, origin_id)

Implements a modified A* algorithm that finds the time-dependent shortest path from origin node to all other nodes in the graph.

Parameters:
  • G (Graph) – NetworkX Graph object.

  • timetable (pd.Series) – Departure times. Index is a tuple of (from, to) node IDs. Values are in seconds (since midnight).

  • start_time (float) – Current time.

  • origin_id (Any) – Origin node ID.

Returns:

Dict[int, float] – Dictionary of node IDs and arrival times, in seconds.

Return type:

Dict[int, float]

metroscore.service_areas.time_dependent_dijkstra(G, timetable, start_time, origin_id)

Implements a modified Djikstra algorithm that finds the time-dependent shortest path from origin node to all other nodes in the graph.

Parameters:
  • G (Graph) – NetworkX Graph object.

  • stop_times (pd.Series) – Departure times. Index is a tuple of (from, to) node IDs. Values are in seconds (since midnight.)

  • start_time (float) – Current time.

  • origin_id (Any) – Origin node ID.

  • timetable (pandas.Series)

Returns:

Dict[int, float] – Dictionary of node IDs and arrival times, in seconds.

Return type:

Dict[int, float]

Based on algorithm outlined in Stephen Boyles’ lecture: https://sboyles.github.io/teaching/ce392d/8-tdsp.pdf

metroscore.service_areas.validate_adjacency_matrix(adj)

Validate the adjacency matrix for Modified Floyd-Warshall algorithm.

Parameters:

adj (ndarray)

metroscore.analysis module

metroscore.analysis.compute_metroscore(transit_areas, drive_areas, bonus_weight=2.0, return_all=False)

Computes the row-wise metroscore for each computed service area.

Parameters:
  • transit_areas (pandas.DataFrame) – DataFrame with shapes of transit service areas and unique names of format “<Facility ID> : <FromBreak> - <ToBreak>”.

  • drive_areas (pandas.DataFrame) – DataFrame with shapes of drive-time service areas and unique names matching those in transit_areas.

  • bonus_weight (float, optional) – Weightage to give to transit bonus. Defaults to 2.0.

  • return_all (bool, optional) – Whether to return all columns (including intermediate steps) or just the final metroscore. Defaults to False.

Returns:

pandas.DataFrame – DataFrame with schema:

{
    "name": <unique service area names of format "<facility id> : <frombreak> - <tobreak>".>
    "metroscore": <metroscore of service area.>
}

metroscore.utils module

class metroscore.utils.MergeMapping(n2n, n2e=None, e2n=None, e2e=None)

Defines mapping of nodes in graph a to nodes/edges in graph b.

Parameters:
  • n2n (Dict[int, Tuple[int, float]])

  • n2e (Dict[int, Tuple[Tuple[int, int], float]] | None)

  • e2n (Dict[Tuple[int, int], Tuple[int, float]] | None)

  • e2e (Dict[Tuple[int, int], Tuple[Tuple[int, int], float]] | None)

n2n

Dict[int, Tuple[int, float]] Mapping of nodes ids in graph a to node ids in graph b, along with their distances.

n2e

Dict[int, Tuple[Tuple[int, int], float] Mapping of node ids in graph a to (node id, node id) edges in graph b, along with distances.

Type:

Optional

e2n

Dict[Tuple[int, int], Tuple[int, float]] Mapping of (node id, node id) edges in graph a to node ids in graph b, along with distances.

Type:

Optional

e2e

Dict[Tuple[int, int], Tuple[Tuple[int, int], float]] Mapping of (node id, node id) edges in graph a to (node id, node id) edges in graph b, along with distances.

Type:

Optional

class metroscore.utils.NodeToEdgeMergeResult(projected_node, projected_edge, partitioned_edges)

Result of merging a node to an edge.

Parameters:
  • projected_node (Tuple[int, Dict])

  • projected_edge (Tuple[int, int, Dict])

  • partitioned_edges (List[Tuple[int, int, Dict]])

projected_node

OSMNode New node projected onto edge.

projected_edge

OSMEdge New edge from projected node to original node. Will have length 0.

partitioned_edges

List[OSMEdge] List of edges in other graph partitioned at the projected node.

metroscore.utils.__fill_missing_geometries(graph)

Fill missing edge geometries in graph using the geometry of the nodes.

metroscore.utils.get_closest_node(start_points, graph)

Get closest node to graph and how long it’ll take to get there, in seconds.

Return type:

List[Tuple[int, float]]

Parameters:

start_points (List[Tuple[float, float]])

metroscore.utils.get_dampened_speeds_per_road_type(G)

Returns dampened speeds per road type in graph G.

Parameters:

G (Graph) – Graph

Returns:

Dict – Dampened speeds per road type.

Return type:

Dict

metroscore.utils.get_merge_mapping(a, b)

Returns which nodes in graph b are closest to each node in graph a. Distances will be returned in meters.

Return type:

MergeMapping

Parameters:
  • a (networkx.Graph)

  • b (networkx.Graph)

metroscore.utils.merge_dicts_on_key(a, b, overwrite_if)

Merge dict b into dict a. When encountering a key that already exists in a, take the values of the conflicting key and compare them using a function key. If the output of the key function is True, prefer the original value from a. If the output is False, prefer the value from b.

Parameters:
  • a (dict) – dict

  • b (dict) – dict

  • overwrite_if (Callable[[Any, Any], bool]) – Callable[[Any, Any], bool] Function that takes two values and returns True if the new value is preferred, False otherwise.

Returns:

dict – Merged dictionary.

Return type:

dict

metroscore.utils.merge_edge_to_node(edge, node)

Constructs a new edge between edge and node. Returns new projected node along edge and edge from projected node to node (with length 0).

Return type:

NodeToEdgeMergeResult

Parameters:
  • edge (Tuple[int, int, Dict])

  • node (Tuple[int, Dict])

metroscore.utils.merge_graphs(a, other, tol=100.0, a_board_anywhere=False, b_board_anywhwere=False)

Merge other into a by connecting nodes and edges that are within tol meters of each other.

Parameters:
  • a (Optional[MultiGraph]) – MultiDiGraph, typically the graph with higher transit precedence (i.e. rail)

  • other (MultiGraph) – MultiDiGraph, typically the graph with lower transit precedence (i.e. walking)

  • tol (float) – float, default 100.0. Tolerance in meters for merging nodes and edges. A good heuristic is to set this to the number of meters an average person would be willing to walk on “non-walkable” surfaces (i.e. through a grassy field or parking lot).

  • a_board_anywhere (bool) – bool, default False. If true, edges in a will be considered as potential boarding edges. This means that nodes in other will be merged to edges in a if they are within tol meters of the edge.

  • b_board_anywhere – bool, default False. If true, edges in other will be considered as potential boarding edges. This means that nodes in a will be merged to edges in other if they are within tol meters of the edge. Note that if both a_board_anywhere and b_board_anywhere are set to True, the function will merge edges in a to edges in other along intersection points (ignoring tol for now).

  • b_board_anywhwere (bool)

Returns:

MultiDiGraph – Merged graph.

Return type:

networkx.MultiGraph

metroscore.utils.merge_node_to_node(a, b)

Constructs a new edge between nodes a and b. Returns tuple of new edge (with length 0).

Return type:

Tuple[int, int, Dict]

Parameters:
  • a (Tuple[int, Dict])

  • b (Tuple[int, Dict])

metroscore.utils.project_node_to_edge(node, edge)

Returns point on edge that is closest to node.

Parameters:
  • node (Tuple[int, Dict]) – dict representing node data

  • edge (Tuple[int, int, Dict]) – tuple representing edge’s data

Returns:

Point – Point object representing point along edge

Return type:

shapely.geometry.Point