Skip to content

Commit

Permalink
feat: add possibility of generating an empty graph (#69)
Browse files Browse the repository at this point in the history
to do so, provide null/None as value for the corresponding topology key in the parameters
for instance: parameters = {" topologies": { "walk": null, "bike": [...] }, ... }
  • Loading branch information
leo-desbureaux-tellae authored Sep 15, 2022
1 parent 972ed1c commit d08b0f2
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 21 deletions.
49 changes: 32 additions & 17 deletions starling_sim/basemodel/environment/environment.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import logging
import sys
from starling_sim.basemodel.topology.osm_network import OSMNetwork
from starling_sim.basemodel.topology.empty_network import EmptyNetwork
from starling_sim.utils.config import config
from geopy import distance

Expand Down Expand Up @@ -33,11 +34,6 @@ def __init__(self, scenario, network="osm"):

for mode, info in topologies_dict.items():

network_file = info[0]
speeds_file = info[1]
if len(info) == 3:
weight_class = info[2]

# see if paths of this topology should be stored
if isinstance(store_paths, dict):
if mode not in store_paths:
Expand All @@ -47,8 +43,14 @@ def __init__(self, scenario, network="osm"):
else:
store = store_paths

if info is None:
topology = EmptyNetwork(mode, store_paths=store)
# create a topology object according to the given network type
if network == "osm":
elif network == "osm":
network_file = info[0]
speeds_file = info[1]
if len(info) == 3:
weight_class = info[2]
topology = OSMNetwork(
mode,
network_file=network_file,
Expand Down Expand Up @@ -491,9 +493,15 @@ def localisations_nearest_nodes(self, x_coordinates, y_coordinates, modes):
"""
Call the topology localisations_nearest_nodes method.
If a list of modes is provided, consider only nodes that are present
in all provided topologies.
If a node as no neighbour, assign None
:param x_coordinates: list of X coordinates of the localisations
:param y_coordinates: list of Y coordinates of the localisations
:param modes: topology modes
:return: list of nearest nodes
"""

Expand All @@ -510,6 +518,10 @@ def localisations_nearest_nodes(self, x_coordinates, y_coordinates, modes):
else:
target_graph = self.topologies[modes].graph

# if there is no candidate nodes, the nearest node is None
if len(target_graph.nodes) == 0:
return

target_topology = OSMNetwork(modes, graph=target_graph)

return target_topology.localisations_nearest_nodes(x_coordinates, y_coordinates)
Expand Down Expand Up @@ -621,23 +633,26 @@ def add_stops_correspondence(
latitudes = stops_table["stop_lat"].values
longitudes = stops_table["stop_lon"].values

# compute the stops nearest nodes
# compute each stop nearest node
stops_table["nearest_node"] = self.localisations_nearest_nodes(longitudes, latitudes, modes)

for index, row in stops_table.iterrows():
# extend graph with stops if asked
if extend_graph:

# get stop and node information
nearest_node = row["nearest_node"]
for index, row in stops_table.iterrows():

# compute euclidean distance
nearest_loc = self.get_localisation(nearest_node, modes[0])
stop_loc = [row["stop_lat"], row["stop_lon"]]
eucl_dist = 1000 * distance.great_circle(nearest_loc, stop_loc).kilometers
# get stop and node information
nearest_node = row["nearest_node"]

# set correspondence
if eucl_dist > max_distance and extend_graph:
# if the node has a close neighbour, don't add a node
if nearest_node is not None:
nearest_loc = self.get_localisation(nearest_node, modes[0])
stop_loc = [row["stop_lat"], row["stop_lon"]]
eucl_dist = 1000 * distance.great_circle(nearest_loc, stop_loc).kilometers
if eucl_dist <= max_distance:
continue

# extend the graph : add a new node at stop location
# otherwise, extend the graph : add a new node at stop location
self.add_node(
row["stop_id"],
{"y": row["stop_lat"], "x": row["stop_lon"], "osmid": row["stop_id"]},
Expand Down
51 changes: 51 additions & 0 deletions starling_sim/basemodel/topology/empty_network.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import logging
import osmnx as ox
import networkx as nx
import numpy as np

from starling_sim.basemodel.topology.topology import Topology


class EmptyNetwork(Topology):
"""
An initially empty topology
"""

def __init__(self, transport_mode, weight_class=None, store_paths=False):
"""
Create the topology structure, without initializing the network
:param transport_mode: type of the given network
:param weight_class: class used for defining weight
:param store_paths: boolean indicating if shortest paths should be stored
"""
super().__init__(transport_mode, weight_class=weight_class, store_paths=store_paths)

self.graph = None
self.speeds = None

def init_graph(self):
# initialise an empty graph object
logging.debug("Generating an empty graph for mode '{}'".format(self.mode))
self.graph = nx.MultiDiGraph()

def add_time_and_length(self, u, v, d):
pass

def position_localisation(self, position):

return [self.graph.nodes[position]["y"], self.graph.nodes[position]["x"]]

def nearest_position(self, localisation):

position = ox.get_nearest_node(self.graph, (float(localisation[0]), float(localisation[1])))
return position

def localisations_nearest_nodes(self, x_coordinates, y_coordinates, method="balltree"):

# convert coordinate lists to np.array
x_array = np.array(x_coordinates, dtype=np.float32)
y_array = np.array(y_coordinates, dtype=np.float32)

# we use osmnx get_nearest_nodes function, with method='balltree' [uses scikit_learn]
return ox.get_nearest_nodes(self.graph, x_array, y_array, method=method)
1 change: 0 additions & 1 deletion starling_sim/basemodel/topology/osm_network.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ def init_graph(self):
if self.network_file is None:
logging.error("No network file provided for topology initialisation")
raise ValueError("Network file provided is {}".format(self.network_file))

else:
logging.debug(
"Importing OSM graph for mode '{}' from file {}".format(
Expand Down
6 changes: 3 additions & 3 deletions starling_sim/schemas/parameters.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,13 @@
"description": "Files for initialising the topologies",
"properties": {
"additional_properties": {
"description": "Array of two string items, the network file and the speeds file",
"type": "array",
"description": "Array of two string items, the network file and the speeds file, or null to generate an empty graph",
"type": ["array", "null"],
"items": {
"type": "string"
},
"minItems": 2,
"maxItems": 2
"maxItems": 3
}
},
"required": ["walk"]
Expand Down

0 comments on commit d08b0f2

Please sign in to comment.