# imports # standard import random from math import isclose import uuid # local, external import osmnx as ox import networkx as nx from shapely.geometry import Point, LineString # local, internal import src.topupopt.data.gis.identify as gis_iden import src.topupopt.data.gis.osm as gis_osm # ***************************************************************************** # ***************************************************************************** class TestGisIdentify: # ************************************************************************* # ************************************************************************* def straight_path_validator( self, network: nx.MultiDiGraph, path: list, protected_nodes: list, consider_reversed_edges: bool, ignore_self_loops: bool, ): # find out the unique nodes set_nodes = set(path) # at least three nodes assert len(path) >= 3 # no repeated nodes unless they appear first and last for node in set_nodes: # count the nodes node_count = path.count(node) if node_count >= 3: # the same node cannot appear three or more times assert False elif node_count == 2: # cycle: the first and last nodes must match assert path[0] == path[-1] and path[0] == node # cycle: make sure # no excluded nodes in the intermediate positions for node in protected_nodes: assert node not in path[1:-1] # intermediate nodes can only have two neighbours for node_key in path[1:-1]: assert ( len(set(gis_iden.neighbours(network, node_key, ignore_self_loops=True))) == 2 ) # end nodes need to have at least one neighbour, except in loops, # wherein they need to have two neighbours if path[0] == path[-1]: # end nodes in loops need to have at least two neighbours assert ( len(set(gis_iden.neighbours(network, path[0], ignore_self_loops=True))) >= 2 ) else: # end nodes need to have at least one neighbour assert ( len(set(gis_iden.neighbours(network, path[0], ignore_self_loops=True))) >= 1 ) assert ( len(set(gis_iden.neighbours(network, path[-1], ignore_self_loops=True))) >= 1 ) # if ignore_self_loops=False, intermediate nodes cannot have self-loops if not ignore_self_loops: for node in path[1:-1]: assert not network.has_edge(node, node) # if path[0] == path[-1]: # # loop, applies to all nodes # for node in path: # assert not network.has_edge(node, node) # else: # # not a loop, applies only to intermediate nodes # for node in path[1:-1]: # assert not network.has_edge(node, node) # make sure it qualifies as a path assert gis_iden.is_node_path( network, path, consider_reversed_edges=consider_reversed_edges ) # make sure it is a straight path assert gis_iden.is_path_straight( network, path, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # ************************************************************************* # ************************************************************************* def test_finding_simplifiable_paths_osmnx(self): # network should be a OSM-nx formatted graph network = ox.graph_from_point( (55.71654, 9.11728), network_type="drive", custom_filter='["highway"~"residential|tertiary|unclassified|service"]', truncate_by_edge=True, ) # ********************************************************************* # ********************************************************************* consider_reversed_edges = False ignore_self_loops = False # paths paths = gis_iden.find_simplifiable_paths( network, protected_nodes=[], consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # verify the paths for path in paths: self.straight_path_validator( network, path, protected_nodes=[], consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # ********************************************************************* # ********************************************************************* consider_reversed_edges = False ignore_self_loops = True # paths paths = gis_iden.find_simplifiable_paths( network, protected_nodes=[], consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # verify the paths for path in paths: self.straight_path_validator( network, path, protected_nodes=[], consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # ********************************************************************* # ********************************************************************* consider_reversed_edges = True ignore_self_loops = False # paths paths = gis_iden.find_simplifiable_paths( network, protected_nodes=[], consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # verify the paths for path in paths: self.straight_path_validator( network, path, protected_nodes=[], consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # ********************************************************************* # ********************************************************************* consider_reversed_edges = True ignore_self_loops = True # paths paths = gis_iden.find_simplifiable_paths( network, protected_nodes=[], consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # verify the paths for path in paths: self.straight_path_validator( network, path, protected_nodes=[], consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # ********************************************************************* # ********************************************************************* # ************************************************************************* # ************************************************************************* def test_find_straight_path_empty_graph(self): # test variations: # 1) excluded nodes # 2) self loops # 3) reversed edges # ********************************************************************* # ********************************************************************* # network with a two edge path network = nx.MultiDiGraph() # no reversed edges, no self loops, no excluded nodes consider_reversed_edges = False ignore_self_loops = False protected_nodes = [] # test path validator with non-path error_raised = False try: assert not self.straight_path_validator( network, [1, 1, 1], protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) except AssertionError: error_raised = True assert error_raised straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [] assert len(straight_paths) == len(true_straight_paths) assert len(straight_paths) == 0 # ********************************************************************* # ********************************************************************* # no reversed edges, no self loops, no excluded nodes consider_reversed_edges = False ignore_self_loops = True protected_nodes = [] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [] assert len(straight_paths) == len(true_straight_paths) assert len(straight_paths) == 0 # ********************************************************************* # ********************************************************************* # network with a two edge path network = nx.MultiDiGraph() # no reversed edges, no self loops, no excluded nodes consider_reversed_edges = True ignore_self_loops = False protected_nodes = [] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [] assert len(straight_paths) == len(true_straight_paths) assert len(straight_paths) == 0 # ********************************************************************* # ********************************************************************* # network with a two edge path network = nx.MultiDiGraph() # no reversed edges, no self loops, no excluded nodes consider_reversed_edges = True ignore_self_loops = True protected_nodes = [] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [] assert len(straight_paths) == len(true_straight_paths) assert len(straight_paths) == 0 # ********************************************************************* # ********************************************************************* # enhance test coverage # add single node network.add_node(0) path = gis_iden._find_path_direction_insensitive(network, [], 0, False) assert type(path) == list assert len(path) == 1 assert repr(path) == repr([0]) # ************************************************************************* # ************************************************************************* def test_find_one_edge_path(self): # ********************************************************************* # ********************************************************************* # network with a two edge path network = nx.MultiDiGraph() network.add_edges_from([(0, 1, 0)]) # ********************************************************************* # ********************************************************************* # do not consider reversed edges consider_reversed_edges = False # ********************************************************************* # ********************************************************************* # no reversed edges, no self loops, no excluded nodes ignore_self_loops = False protected_nodes = [] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [] assert len(straight_paths) == len(true_straight_paths) # ********************************************************************* # ********************************************************************* # no reversed edges, allow self loops, no excluded nodes ignore_self_loops = True protected_nodes = [] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [] assert len(straight_paths) == len(true_straight_paths) # ********************************************************************* # ********************************************************************* # do not allow reversed edges, no self loops, excluded the middle node ignore_self_loops = False protected_nodes = [1] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [] assert len(straight_paths) == len(true_straight_paths) # ********************************************************************* # ********************************************************************* # do not allow reversed edges, no self loops, excluded the start node ignore_self_loops = False protected_nodes = [0] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [] assert len(straight_paths) == len(true_straight_paths) # ********************************************************************* # ********************************************************************* # do not allow reversed edges, no self loops, excluded the end node ignore_self_loops = False protected_nodes = [2] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [] assert len(straight_paths) == len(true_straight_paths) # ********************************************************************* # ********************************************************************* # consider reversed edges consider_reversed_edges = True # ********************************************************************* # ********************************************************************* # allow reversed edges, allow self loops, no excluded nodes ignore_self_loops = True protected_nodes = [] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [] assert len(straight_paths) == len(true_straight_paths) # ********************************************************************* # ********************************************************************* # allow reversed edges, no self loops, no excluded nodes ignore_self_loops = False protected_nodes = [] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [] assert len(straight_paths) == len(true_straight_paths) # ********************************************************************* # ********************************************************************* # allow reversed edges, no self loops, excluded the middle node ignore_self_loops = False protected_nodes = [1] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [] assert len(straight_paths) == len(true_straight_paths) # ********************************************************************* # ********************************************************************* # allow reversed edges, no self loops, excluded the start node ignore_self_loops = False protected_nodes = [0] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [] assert len(straight_paths) == len(true_straight_paths) # ********************************************************************* # ********************************************************************* # allow reversed edges, no self loops, excluded the end node ignore_self_loops = False protected_nodes = [2] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [] assert len(straight_paths) == len(true_straight_paths) # ********************************************************************* # ********************************************************************* # ************************************************************************* # ************************************************************************* def test_find_one_edge_path_w_reversed_edge(self): # ********************************************************************* # ********************************************************************* # network with a two edge path network = nx.MultiDiGraph() network.add_edges_from([(0, 1, 0), (1, 0, 0)]) # ********************************************************************* # ********************************************************************* # do not consider reversed edges consider_reversed_edges = False # ********************************************************************* # ********************************************************************* # no reversed edges, no self loops, no excluded nodes ignore_self_loops = False protected_nodes = [] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [] assert len(straight_paths) == len(true_straight_paths) # ********************************************************************* # ********************************************************************* # no reversed edges, allow self loops, no excluded nodes ignore_self_loops = True protected_nodes = [] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [] assert len(straight_paths) == len(true_straight_paths) # ********************************************************************* # ********************************************************************* # do not allow reversed edges, no self loops, excluded the middle node ignore_self_loops = False protected_nodes = [1] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [] assert len(straight_paths) == len(true_straight_paths) # ********************************************************************* # ********************************************************************* # do not allow reversed edges, no self loops, excluded the start node ignore_self_loops = False protected_nodes = [0] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [] assert len(straight_paths) == len(true_straight_paths) # ********************************************************************* # ********************************************************************* # do not allow reversed edges, no self loops, excluded the end node ignore_self_loops = False protected_nodes = [2] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [] assert len(straight_paths) == len(true_straight_paths) # ********************************************************************* # ********************************************************************* # consider reversed edges consider_reversed_edges = True # ********************************************************************* # ********************************************************************* # allow reversed edges, allow self loops, no excluded nodes ignore_self_loops = True protected_nodes = [] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [] assert len(straight_paths) == len(true_straight_paths) # ********************************************************************* # ********************************************************************* # allow reversed edges, no self loops, no excluded nodes ignore_self_loops = False protected_nodes = [] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [] assert len(straight_paths) == len(true_straight_paths) # ********************************************************************* # ********************************************************************* # allow reversed edges, no self loops, excluded the middle node ignore_self_loops = False protected_nodes = [1] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [] assert len(straight_paths) == len(true_straight_paths) # ********************************************************************* # ********************************************************************* # allow reversed edges, no self loops, excluded the start node ignore_self_loops = False protected_nodes = [0] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [] assert len(straight_paths) == len(true_straight_paths) # ********************************************************************* # ********************************************************************* # allow reversed edges, no self loops, excluded the end node ignore_self_loops = False protected_nodes = [2] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [] assert len(straight_paths) == len(true_straight_paths) # ********************************************************************* # ********************************************************************* # ************************************************************************* # ************************************************************************* def test_find_simple_straight_path(self): # ********************************************************************* # ********************************************************************* # network with a two edge path network = nx.MultiDiGraph() network.add_edges_from([(0, 1, 0), (1, 2, 0)]) # ********************************************************************* # ********************************************************************* # do not consider reversed edges consider_reversed_edges = False # ********************************************************************* # ********************************************************************* # no reversed edges, no self loops, no excluded nodes ignore_self_loops = False protected_nodes = [] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [[0, 1, 2]] assert len(straight_paths) == len(true_straight_paths) for straight_path in straight_paths: assert straight_path in true_straight_paths self.straight_path_validator( network, straight_path, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # ********************************************************************* # ********************************************************************* # no reversed edges, allow self loops, no excluded nodes ignore_self_loops = True protected_nodes = [] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [[0, 1, 2]] assert len(straight_paths) == len(true_straight_paths) for straight_path in straight_paths: assert straight_path in true_straight_paths self.straight_path_validator( network, straight_path, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # ********************************************************************* # ********************************************************************* # do not allow reversed edges, no self loops, excluded the middle node ignore_self_loops = False protected_nodes = [1] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [] assert len(straight_paths) == len(true_straight_paths) # ********************************************************************* # ********************************************************************* # do not allow reversed edges, no self loops, excluded the start node ignore_self_loops = False protected_nodes = [0] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [[0, 1, 2]] assert len(straight_paths) == len(true_straight_paths) for straight_path in straight_paths: assert straight_path in true_straight_paths self.straight_path_validator( network, straight_path, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # ********************************************************************* # ********************************************************************* # do not allow reversed edges, no self loops, excluded the end node ignore_self_loops = False protected_nodes = [2] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [[0, 1, 2]] assert len(straight_paths) == len(true_straight_paths) for straight_path in straight_paths: assert straight_path in true_straight_paths self.straight_path_validator( network, straight_path, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # ********************************************************************* # ********************************************************************* # consider reversed edges consider_reversed_edges = True # ********************************************************************* # ********************************************************************* # allow reversed edges, allow self loops, no excluded nodes ignore_self_loops = True protected_nodes = [] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [[0, 1, 2], [2, 1, 0]] assert len(straight_paths) == len(true_straight_paths) - 1 for straight_path in straight_paths: assert straight_path in true_straight_paths self.straight_path_validator( network, straight_path, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # ********************************************************************* # ********************************************************************* # allow reversed edges, no self loops, no excluded nodes ignore_self_loops = False protected_nodes = [] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [[0, 1, 2], [2, 1, 0]] assert len(straight_paths) == len(true_straight_paths) - 1 for straight_path in straight_paths: assert straight_path in true_straight_paths self.straight_path_validator( network, straight_path, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # ********************************************************************* # ********************************************************************* # allow reversed edges, no self loops, excluded the middle node ignore_self_loops = False protected_nodes = [1] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [] assert len(straight_paths) == len(true_straight_paths) # ********************************************************************* # ********************************************************************* # allow reversed edges, no self loops, excluded the start node ignore_self_loops = False protected_nodes = [0] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [[0, 1, 2], [2, 1, 0]] assert len(straight_paths) == len(true_straight_paths) - 1 for straight_path in straight_paths: assert straight_path in true_straight_paths self.straight_path_validator( network, straight_path, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # ********************************************************************* # ********************************************************************* # allow reversed edges, no self loops, excluded the end node ignore_self_loops = False protected_nodes = [2] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [[0, 1, 2], [2, 1, 0]] assert len(straight_paths) == len(true_straight_paths) - 1 for straight_path in straight_paths: assert straight_path in true_straight_paths self.straight_path_validator( network, straight_path, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # ********************************************************************* # ********************************************************************* # ************************************************************************* # ************************************************************************* def test_find_simple_straight_path_with_antiparallel_edge(self): # ********************************************************************* # ********************************************************************* # network with a two edge path network = nx.MultiDiGraph() network.add_edges_from([(0, 1, 0), (1, 2, 0), (2, 1, 0)]) # ********************************************************************* # ********************************************************************* # do not consider reversed edges consider_reversed_edges = False # ********************************************************************* # ********************************************************************* # no reversed edges, no self loops, no excluded nodes ignore_self_loops = False protected_nodes = [] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [[0, 1, 2]] assert len(straight_paths) == len(true_straight_paths) for straight_path in straight_paths: assert straight_path in true_straight_paths self.straight_path_validator( network, straight_path, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # ********************************************************************* # ********************************************************************* # no reversed edges, allow self loops, no excluded nodes ignore_self_loops = True protected_nodes = [] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [[0, 1, 2]] assert len(straight_paths) == len(true_straight_paths) for straight_path in straight_paths: assert straight_path in true_straight_paths self.straight_path_validator( network, straight_path, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # ********************************************************************* # ********************************************************************* # do not allow reversed edges, no self loops, excluded the middle node ignore_self_loops = False protected_nodes = [1] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [] assert len(straight_paths) == len(true_straight_paths) # ********************************************************************* # ********************************************************************* # do not allow reversed edges, no self loops, excluded the start node ignore_self_loops = False protected_nodes = [0] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [[0, 1, 2]] assert len(straight_paths) == len(true_straight_paths) for straight_path in straight_paths: assert straight_path in true_straight_paths self.straight_path_validator( network, straight_path, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # ********************************************************************* # ********************************************************************* # do not allow reversed edges, no self loops, excluded the end node ignore_self_loops = False protected_nodes = [2] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [[0, 1, 2]] assert len(straight_paths) == len(true_straight_paths) for straight_path in straight_paths: assert straight_path in true_straight_paths self.straight_path_validator( network, straight_path, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # ********************************************************************* # ********************************************************************* # consider reversed edges consider_reversed_edges = True # ********************************************************************* # ********************************************************************* # allow reversed edges, allow self loops, no excluded nodes ignore_self_loops = True protected_nodes = [] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [[0, 1, 2], [2, 1, 0]] assert len(straight_paths) == len(true_straight_paths) - 1 for straight_path in straight_paths: assert straight_path in true_straight_paths self.straight_path_validator( network, straight_path, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # ********************************************************************* # ********************************************************************* # allow reversed edges, no self loops, no excluded nodes ignore_self_loops = False protected_nodes = [] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [[0, 1, 2], [2, 1, 0]] assert len(straight_paths) == len(true_straight_paths) - 1 for straight_path in straight_paths: assert straight_path in true_straight_paths self.straight_path_validator( network, straight_path, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # ********************************************************************* # ********************************************************************* # allow reversed edges, no self loops, excluded the middle node ignore_self_loops = False protected_nodes = [1] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [] assert len(straight_paths) == len(true_straight_paths) # ********************************************************************* # ********************************************************************* # allow reversed edges, no self loops, excluded the start node ignore_self_loops = False protected_nodes = [0] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [[0, 1, 2], [2, 1, 0]] assert len(straight_paths) == len(true_straight_paths) - 1 for straight_path in straight_paths: assert straight_path in true_straight_paths self.straight_path_validator( network, straight_path, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # ********************************************************************* # ********************************************************************* # allow reversed edges, no self loops, excluded the end node ignore_self_loops = False protected_nodes = [2] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [[0, 1, 2], [2, 1, 0]] assert len(straight_paths) == len(true_straight_paths) - 1 for straight_path in straight_paths: assert straight_path in true_straight_paths self.straight_path_validator( network, straight_path, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # ********************************************************************* # ********************************************************************* # ************************************************************************* # ************************************************************************* def test_find_straight_path_cycle(self): # ********************************************************************* # ********************************************************************* # network with a two edge path network = nx.MultiDiGraph() network.add_edges_from([(0, 1, 0), (1, 2, 0), (2, 0, 0), (0, 2, 0), (1, 1, 0)]) # ********************************************************************* # ********************************************************************* # do not consider reversed edges consider_reversed_edges = False # ********************************************************************* # ********************************************************************* # no self loops, no excluded nodes ignore_self_loops = False protected_nodes = [] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [[1, 2, 0, 1]] assert len(straight_paths) == len(true_straight_paths) for straight_path in straight_paths: assert straight_path in true_straight_paths self.straight_path_validator( network, straight_path, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # ********************************************************************* # ********************************************************************* # allow self loops, no excluded nodes ignore_self_loops = True protected_nodes = [] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [[0, 1, 2, 0], [1, 2, 0, 1], [2, 1, 0, 2]] assert len(straight_paths) == len(true_straight_paths) - 2 for straight_path in straight_paths: assert straight_path in true_straight_paths self.straight_path_validator( network, straight_path, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # ********************************************************************* # ********************************************************************* # no self loops, excluded the "middle" node ignore_self_loops = False protected_nodes = [1] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [[1, 2, 0, 1]] assert len(straight_paths) == len(true_straight_paths) for straight_path in straight_paths: assert straight_path in true_straight_paths self.straight_path_validator( network, straight_path, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # ********************************************************************* # ********************************************************************* # no self loops, excluded the start node ignore_self_loops = False protected_nodes = [0] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [[1, 2, 0]] assert len(straight_paths) == len(true_straight_paths) for straight_path in straight_paths: assert straight_path in true_straight_paths self.straight_path_validator( network, straight_path, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # ********************************************************************* # ********************************************************************* # do not allow reversed edges, no self loops, excluded the end node ignore_self_loops = False protected_nodes = [2] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [[2, 0, 1]] assert len(straight_paths) == len(true_straight_paths) for straight_path in straight_paths: assert straight_path in true_straight_paths self.straight_path_validator( network, straight_path, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # ********************************************************************* # ********************************************************************* # consider reversed edges consider_reversed_edges = True # ********************************************************************* # ********************************************************************* # allow reversed edges, allow self loops, no excluded nodes ignore_self_loops = True protected_nodes = [] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [[0, 1, 2, 0], [1, 2, 0, 1], [2, 1, 0, 2]] assert len(straight_paths) == len(true_straight_paths) - 2 for straight_path in straight_paths: assert straight_path in true_straight_paths self.straight_path_validator( network, straight_path, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # ********************************************************************* # ********************************************************************* # allow reversed edges, no self loops, no excluded nodes ignore_self_loops = False protected_nodes = [] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [[1, 2, 0, 1], [1, 0, 2, 1]] assert len(straight_paths) == len(true_straight_paths) - 1 for straight_path in straight_paths: assert straight_path in true_straight_paths self.straight_path_validator( network, straight_path, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # ********************************************************************* # ********************************************************************* # allow reversed edges, no self loops, excluded the middle node ignore_self_loops = False protected_nodes = [1] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [[1, 2, 0, 1], [1, 0, 2, 1]] assert len(straight_paths) == len(true_straight_paths) - 1 for straight_path in straight_paths: assert straight_path in true_straight_paths self.straight_path_validator( network, straight_path, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # ********************************************************************* # ********************************************************************* # allow reversed edges, no self loops, excluded the start node ignore_self_loops = False protected_nodes = [0] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [[1, 2, 0], [0, 2, 1]] assert len(straight_paths) == len(true_straight_paths) - 1 for straight_path in straight_paths: assert straight_path in true_straight_paths self.straight_path_validator( network, straight_path, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # ********************************************************************* # ********************************************************************* # allow reversed edges, no self loops, excluded the end node ignore_self_loops = False protected_nodes = [2] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [[1, 0, 2], [2, 0, 1]] assert len(straight_paths) == len(true_straight_paths) - 1 for straight_path in straight_paths: assert straight_path in true_straight_paths self.straight_path_validator( network, straight_path, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # ********************************************************************* # ********************************************************************* # ************************************************************************* # ************************************************************************* def test_find_simple_straight_path_w_reversed_edge(self): # ********************************************************************* # ********************************************************************* # network with a two edge path network = nx.MultiDiGraph() network.add_edges_from([(0, 1, 0), (2, 1, 0)]) # ********************************************************************* # ********************************************************************* # consider reversed edges consider_reversed_edges = False # ********************************************************************* # ********************************************************************* # no reversed edges, no self loops, no excluded nodes ignore_self_loops = False protected_nodes = [] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [] assert len(straight_paths) == len(true_straight_paths) # ********************************************************************* # ********************************************************************* # no reversed edges, allow self loops, no excluded nodes ignore_self_loops = True protected_nodes = [] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [] assert len(straight_paths) == len(true_straight_paths) # ********************************************************************* # ********************************************************************* # do not allow reversed edges, no self loops, excluded the middle node ignore_self_loops = False protected_nodes = [1] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [] assert len(straight_paths) == len(true_straight_paths) # ********************************************************************* # ********************************************************************* # do not allow reversed edges, no self loops, excluded the start node ignore_self_loops = False protected_nodes = [0] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [] assert len(straight_paths) == len(true_straight_paths) # ********************************************************************* # ********************************************************************* # do not allow reversed edges, no self loops, excluded the end node ignore_self_loops = False protected_nodes = [2] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [] assert len(straight_paths) == len(true_straight_paths) # ********************************************************************* # ********************************************************************* # consider reversed edges consider_reversed_edges = True # ********************************************************************* # ********************************************************************* # allow reversed edges, allow self loops, no excluded nodes ignore_self_loops = True protected_nodes = [] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [[0, 1, 2], [2, 1, 0]] assert len(straight_paths) == len(true_straight_paths) - 1 for straight_path in straight_paths: assert straight_path in true_straight_paths self.straight_path_validator( network, straight_path, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # ********************************************************************* # ********************************************************************* # allow reversed edges, no self loops, no excluded nodes ignore_self_loops = False protected_nodes = [] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [[0, 1, 2], [2, 1, 0]] assert len(straight_paths) == len(true_straight_paths) - 1 for straight_path in straight_paths: assert straight_path in true_straight_paths self.straight_path_validator( network, straight_path, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # ********************************************************************* # ********************************************************************* # allow reversed edges, no self loops, excluded the middle node ignore_self_loops = False protected_nodes = [1] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [] assert len(straight_paths) == len(true_straight_paths) # ********************************************************************* # ********************************************************************* # allow reversed edges, no self loops, excluded the start node ignore_self_loops = False protected_nodes = [0] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [[0, 1, 2], [2, 1, 0]] assert len(straight_paths) == len(true_straight_paths) - 1 for straight_path in straight_paths: assert straight_path in true_straight_paths self.straight_path_validator( network, straight_path, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # ********************************************************************* # ********************************************************************* # allow reversed edges, no self loops, excluded the end node ignore_self_loops = False protected_nodes = [2] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [[0, 1, 2], [2, 1, 0]] assert len(straight_paths) == len(true_straight_paths) - 1 for straight_path in straight_paths: assert straight_path in true_straight_paths self.straight_path_validator( network, straight_path, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # ********************************************************************* # ********************************************************************* # ************************************************************************* # ************************************************************************* def test_find_simple_straight_path_w_reversed_edge2(self): # ********************************************************************* # ********************************************************************* # network with a two edge path network = nx.MultiDiGraph() network.add_edges_from([(1, 0, 0), (1, 2, 0)]) # ********************************************************************* # ********************************************************************* # consider reversed edges consider_reversed_edges = False # ********************************************************************* # ********************************************************************* # no reversed edges, no self loops, no excluded nodes ignore_self_loops = False protected_nodes = [] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [] assert len(straight_paths) == len(true_straight_paths) # ********************************************************************* # ********************************************************************* # no reversed edges, allow self loops, no excluded nodes ignore_self_loops = True protected_nodes = [] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [] assert len(straight_paths) == len(true_straight_paths) # ********************************************************************* # ********************************************************************* # do not allow reversed edges, no self loops, excluded the middle node ignore_self_loops = False protected_nodes = [1] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [] assert len(straight_paths) == len(true_straight_paths) # ********************************************************************* # ********************************************************************* # do not allow reversed edges, no self loops, excluded the start node ignore_self_loops = False protected_nodes = [0] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [] assert len(straight_paths) == len(true_straight_paths) # ********************************************************************* # ********************************************************************* # do not allow reversed edges, no self loops, excluded the end node ignore_self_loops = False protected_nodes = [2] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [] assert len(straight_paths) == len(true_straight_paths) # ********************************************************************* # ********************************************************************* # consider reversed edges consider_reversed_edges = True # ********************************************************************* # ********************************************************************* # allow reversed edges, allow self loops, no excluded nodes ignore_self_loops = True protected_nodes = [] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [[0, 1, 2], [2, 1, 0]] assert len(straight_paths) == len(true_straight_paths) - 1 for straight_path in straight_paths: assert straight_path in true_straight_paths self.straight_path_validator( network, straight_path, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # ********************************************************************* # ********************************************************************* # allow reversed edges, no self loops, no excluded nodes ignore_self_loops = False protected_nodes = [] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [[0, 1, 2], [2, 1, 0]] assert len(straight_paths) == len(true_straight_paths) - 1 for straight_path in straight_paths: assert straight_path in true_straight_paths self.straight_path_validator( network, straight_path, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # ********************************************************************* # ********************************************************************* # allow reversed edges, no self loops, excluded the middle node ignore_self_loops = False protected_nodes = [1] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [] assert len(straight_paths) == len(true_straight_paths) # ********************************************************************* # ********************************************************************* # allow reversed edges, no self loops, excluded the start node ignore_self_loops = False protected_nodes = [0] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [[0, 1, 2], [2, 1, 0]] assert len(straight_paths) == len(true_straight_paths) - 1 for straight_path in straight_paths: assert straight_path in true_straight_paths self.straight_path_validator( network, straight_path, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # ********************************************************************* # ********************************************************************* # allow reversed edges, no self loops, excluded the end node ignore_self_loops = False protected_nodes = [2] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [[0, 1, 2], [2, 1, 0]] assert len(straight_paths) == len(true_straight_paths) - 1 for straight_path in straight_paths: assert straight_path in true_straight_paths self.straight_path_validator( network, straight_path, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # ********************************************************************* # ********************************************************************* # ************************************************************************* # ************************************************************************* def test_find_simplifiable_path_four_nodes(self): # ********************************************************************* # ********************************************************************* # network with a two edge path network = nx.MultiDiGraph() network.add_edges_from([(1, 0, 0), (1, 2, 0), (2, 3, 0)]) # ********************************************************************* # ********************************************************************* # do not consider reversed edges consider_reversed_edges = False # ********************************************************************* # ********************************************************************* # no reversed edges, no self loops, no excluded nodes ignore_self_loops = False protected_nodes = [] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [[1, 2, 3]] assert len(straight_paths) == len(true_straight_paths) for straight_path in straight_paths: assert straight_path in true_straight_paths self.straight_path_validator( network, straight_path, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # ********************************************************************* # ********************************************************************* # consider reversed edges consider_reversed_edges = True # ********************************************************************* # ********************************************************************* # no reversed edges, no self loops, no excluded nodes ignore_self_loops = False protected_nodes = [] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [[0, 1, 2, 3], [3, 2, 1, 0]] assert len(straight_paths) == len(true_straight_paths) - 1 for straight_path in straight_paths: assert straight_path in true_straight_paths self.straight_path_validator( network, straight_path, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # ********************************************************************* # ********************************************************************* # no reversed edges, no self loops, no excluded nodes ignore_self_loops = False protected_nodes = [] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, include_both_directions=True, ) true_straight_paths = [[0, 1, 2, 3], [3, 2, 1, 0]] assert len(straight_paths) == len(true_straight_paths) for straight_path in straight_paths: assert straight_path in true_straight_paths self.straight_path_validator( network, straight_path, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # ********************************************************************* # ********************************************************************* # ************************************************************************* # ************************************************************************* def test_find_simplifiable_path_four_node_cycle(self): # ********************************************************************* # ********************************************************************* # network with a two edge path network = nx.MultiDiGraph() network.add_edges_from([(0, 1, 0), (1, 2, 0), (2, 3, 0), (0, 3, 0)]) # ********************************************************************* # ********************************************************************* # do not consider reversed edges consider_reversed_edges = False # ********************************************************************* # ********************************************************************* # no reversed edges, no self loops, no excluded nodes ignore_self_loops = False protected_nodes = [] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [[0, 1, 2, 3]] assert len(straight_paths) == len(true_straight_paths) for straight_path in straight_paths: assert straight_path in true_straight_paths self.straight_path_validator( network, straight_path, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # ********************************************************************* # ********************************************************************* # consider reversed edges consider_reversed_edges = True # ********************************************************************* # ********************************************************************* # no reversed edges, no self loops, no excluded nodes ignore_self_loops = False protected_nodes = [] straight_paths = gis_iden.find_simplifiable_paths( network, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) true_straight_paths = [ [0, 1, 2, 3, 0], [1, 2, 3, 0, 1], [2, 3, 0, 1, 2], [3, 0, 1, 2, 3], ] assert len(straight_paths) == len(true_straight_paths) - 3 for straight_path in straight_paths: assert straight_path in true_straight_paths self.straight_path_validator( network, straight_path, protected_nodes, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # ********************************************************************* # ********************************************************************* # ************************************************************************* # ************************************************************************* def test_start_end_points_identification(self): # create LineString object line = LineString([(0, 0), (1, 0), (2, 0)]) # tolerance proximity_tolerance = 1e-3 # start point point_a = Point(0, 0) # end point point_b = Point(2, 0) # approximately the start point point_c = Point(0 + proximity_tolerance / 2, 0) # approximately the end point point_d = Point(2 + proximity_tolerance / 2, 0) # close, but not quite the start point point_e = Point(0 + 2 * proximity_tolerance, 0) # close, but not quite the end point point_f = Point(2 + 2 * proximity_tolerance, 0) # another point on the line other than the start and end points point_g = Point(1, 0) # tests assert gis_iden.is_start_or_end_point_or_close( line, point_a, tolerance=proximity_tolerance ) assert gis_iden.is_start_or_end_point_or_close( line, point_b, tolerance=proximity_tolerance ) assert gis_iden.is_start_or_end_point_or_close( line, point_c, tolerance=proximity_tolerance ) assert gis_iden.is_start_or_end_point_or_close( line, point_d, tolerance=proximity_tolerance ) assert not gis_iden.is_start_or_end_point_or_close( line, point_e, tolerance=proximity_tolerance ) assert not gis_iden.is_start_or_end_point_or_close( line, point_f, tolerance=proximity_tolerance ) assert not gis_iden.is_start_or_end_point_or_close( line, point_g, tolerance=proximity_tolerance ) # other method assert gis_iden.is_start_or_end_point(line, point_a) assert gis_iden.is_start_or_end_point(line, point_b) assert not gis_iden.is_start_or_end_point(line, point_c) assert not gis_iden.is_start_or_end_point(line, point_d) assert not gis_iden.is_start_or_end_point(line, point_e) assert not gis_iden.is_start_or_end_point(line, point_f) assert not gis_iden.is_start_or_end_point(line, point_g) # ************************************************************************* # ************************************************************************* def test_find_unconnected_nodes(self): G = nx.MultiDiGraph() G.add_edges_from([(0, 1), (1, 2), (2, 3), (3, 1), (2, 0)]) G.add_nodes_from([4, 5]) node_keys = gis_iden.find_unconnected_nodes(G) true_node_keys = [4, 5] assert len(node_keys) == len(true_node_keys) for node_key in node_keys: assert node_key in true_node_keys # ************************************************************************* # ************************************************************************* def test_identify_get_from_a_to_b(self): # edge_keys = gis_iden.get_edges_from_a_to_b(G, 0, 1) G = nx.MultiDiGraph() G.add_edges_from( [ (0, 1, {"a": 1}), (1, 2, {"b": 2}), (2, 3, {"c": 3}), (2, 3, {"d": 4}), (1, 0, {"e": 5}), (3, 2, {"f": 6}), ] ) # from node 0 to node 1 edge_keys = gis_iden.get_edges_from_a_to_b(G, 0, 1) true_edge_keys = [(0, 1, 0)] assert len(true_edge_keys) == len(edge_keys) for edge_key in edge_keys: assert edge_key in true_edge_keys # from node 1 to node 0 edge_keys = gis_iden.get_edges_from_a_to_b(G, 1, 0) true_edge_keys = [(1, 0, 0)] assert len(true_edge_keys) == len(edge_keys) for edge_key in edge_keys: assert edge_key in true_edge_keys # from node 1 to node 2 edge_keys = gis_iden.get_edges_from_a_to_b(G, 1, 2) true_edge_keys = [(1, 2, 0)] assert len(true_edge_keys) == len(edge_keys) for edge_key in edge_keys: assert edge_key in true_edge_keys # from node 2 to node 1 edge_keys = gis_iden.get_edges_from_a_to_b(G, 2, 1) true_edge_keys = [] assert len(true_edge_keys) == len(edge_keys) # from node 2 to node 3 edge_keys = gis_iden.get_edges_from_a_to_b(G, 2, 3) true_edge_keys = [(2, 3, 0), (2, 3, 1)] assert len(true_edge_keys) == len(edge_keys) for edge_key in edge_keys: assert edge_key in true_edge_keys # from node 3 to node 2 true_edge_keys = [(3, 2, 0)] edge_keys = gis_iden.get_edges_from_a_to_b(G, 3, 2) assert len(true_edge_keys) == len(edge_keys) for edge_key in edge_keys: assert edge_key in true_edge_keys # ************************************************************************* # ************************************************************************* def test_identify_get_edges_involving_nodes(self): G = nx.MultiDiGraph() G.add_node("noedges") G.add_edges_from([(0, 1, 0), (1, 2, 0), (1, 2, 1)]) # no edges node_key = "noedges" edges = gis_iden.get_edges_involving_node(G, node_key) assert len(edges) == 0 # one edge node_key = 0 true_edges = [(0, 1, 0)] edges = gis_iden.get_edges_involving_node(G, node_key) assert len(edges) == len(true_edges) for edge in edges: assert edge in true_edges # multiple edges node_key = 1 true_edges = [(0, 1, 0), (1, 2, 1), (1, 2, 0)] edges = gis_iden.get_edges_involving_node(G, node_key) assert len(edges) == len(true_edges) for edge in edges: assert edge in true_edges # ************************************************************************* # ************************************************************************* def test_identify_get_edges_between_nodes(self): G = nx.MultiDiGraph() G.add_edges_from( [ (0, 1, {"a": 1}), (1, 2, {"b": 2}), (2, 3, {"c": 3}), (2, 3, {"d": 4}), (1, 0, {"e": 5}), (3, 2, {"f": 6}), (4, 1, {"f": 6}), ] ) # between two nodes that are not connected edge_keys = gis_iden.get_edges_between_two_nodes(G, 2, 4) assert 0 == len(edge_keys) # between nodes 0 and 1, nominal direction edge_keys = gis_iden.get_edges_between_two_nodes(G, 0, 1) true_edge_keys = [(0, 1, 0), (1, 0, 0)] assert len(true_edge_keys) == len(edge_keys) for edge_key in edge_keys: assert edge_key in true_edge_keys # between nodes 0 and 1, reverse direction edge_keys = gis_iden.get_edges_between_two_nodes(G, 1, 0) assert len(true_edge_keys) == len(edge_keys) for edge_key in edge_keys: assert edge_key in true_edge_keys # between nodes 1 and 2, nominal direction edge_keys = gis_iden.get_edges_between_two_nodes(G, 1, 2) true_edge_keys = [(1, 2, 0)] assert len(true_edge_keys) == len(edge_keys) for edge_key in edge_keys: assert edge_key in true_edge_keys # between nodes 1 and 2, reverse direction edge_keys = gis_iden.get_edges_between_two_nodes(G, 2, 1) assert len(true_edge_keys) == len(edge_keys) for edge_key in edge_keys: assert edge_key in true_edge_keys # between nodes 2 and 3, nominal direction edge_keys = gis_iden.get_edges_between_two_nodes(G, 2, 3) true_edge_keys = [(2, 3, 0), (2, 3, 1), (3, 2, 0)] assert len(true_edge_keys) == len(edge_keys) for edge_key in edge_keys: assert edge_key in true_edge_keys # between nodes 2 and 3, reverse direction edge_keys = gis_iden.get_edges_between_two_nodes(G, 3, 2) assert len(true_edge_keys) == len(edge_keys) for edge_key in edge_keys: assert edge_key in true_edge_keys # ************************************************************************* # ************************************************************************* def test_identify_edges_closest_to_nodes(self): # network should be a OSM-nx formatted graph network = ox.graph_from_point( (55.71654, 9.11728), network_type="drive", custom_filter='["highway"~"residential|tertiary|unclassified|service"]', truncate_by_edge=True, ) # pick a certain number of nodes randomly number_nodes = 3 node_keys = list(network.nodes()) while len(node_keys) > number_nodes: node_keys.pop(random.randint(0, len(node_keys) - 1)) # find out which edges are closest edge_keys, projected_network = gis_iden.identify_edge_closest_to_node( network=network, node_keys=node_keys ) # for each node, verify that there is no closer edge # prepare the edge geometries edge_key_geos = [ ( projected_network.edges[edge_key][gis_osm.KEY_OSMNX_GEOMETRY] if gis_osm.KEY_OSMNX_GEOMETRY in projected_network.edges[edge_key] else LineString( [ ( projected_network.nodes[edge_key[0]][gis_osm.KEY_OSMNX_X], projected_network.nodes[edge_key[0]][gis_osm.KEY_OSMNX_Y], ), ( projected_network.nodes[edge_key[1]][gis_osm.KEY_OSMNX_X], projected_network.nodes[edge_key[1]][gis_osm.KEY_OSMNX_Y], ), ] ) ) for edge_key in edge_keys ] for node_index, node_key in enumerate(node_keys): # prepare the node geometry the_point = Point( projected_network.nodes[node_key][gis_osm.KEY_OSMNX_X], projected_network.nodes[node_key][gis_osm.KEY_OSMNX_Y], ) # calculate the distances to every edge edge_point_distances = the_point.distance(edge_key_geos) # find the distance to the edge identified as the closest one shortest_distance = edge_point_distances[node_index] # the edge identified must lead to the shortest distance assert shortest_distance == min(edge_point_distances) # find out which edges are closest using the projected network edge_keys_proj, _ = gis_iden.identify_edge_closest_to_node( network=projected_network, node_keys=node_keys ) # assert that the same edges have been returned (with the projected network) assert len(edge_keys) == len(edge_keys_proj) for edge_key1, edge_key2 in zip(edge_keys, edge_keys_proj): assert edge_key1 == edge_key2 # ************************************************************************* # ************************************************************************* def test_identify_roundabouts(self): # ********************************************************************* # ********************************************************************* edge_container = [ # roundabout with 2 nodes (0, 1, {"length": 3, "oneway": True}), (1, 0, {"length": 5, "oneway": True}), # roundabout with 3 nodes (2, 3, {"length": 8, "oneway": True}), (3, 4, {"length": 19, "oneway": True}), (4, 2, {"length": 4, "oneway": True}), # roundabout with 4 nodes (5, 6, {"length": 8, "oneway": True}), (6, 7, {"length": 5, "oneway": True}), (7, 8, {"length": 10, "oneway": True}), (8, 5, {"length": 7, "oneway": True}), # roundabout within roundabout 2 (2, 4, {"length": 6, "oneway": True}), # roundabout overlapping with roundabouts 1 and 3 (9, 10, {"length": 14, "oneway": True}), (10, 11, {"length": 57, "oneway": True}), (11, 9, {"length": 13, "oneway": True}), # fake roundabouts # self loop (12, 12, {"length": 0, "oneway": True}), # no oneway attr (13, 14, {"length": 9}), (14, 15, {"length": 6, "oneway": True}), (15, 13, {"length": 7, "oneway": True}), # oneway = False (16, 17, {"length": 9, "oneway": True}), (17, 18, {"length": 5, "oneway": False}), (18, 19, {"length": 3, "oneway": True}), (19, 16, {"length": 2, "oneway": True}), # connect roundabouts 1 and 3 with a edge (1, 6, {"length": 9, "oneway": False}), (6, 1, {"length": 24, "oneway": False}), # create an edge between node 7 and 5 that cannot be used, (7, 5, {"length": 6, "oneway": False}), ] network = nx.MultiDiGraph() network.add_edges_from(edge_container) # ********************************************************************* # ********************************************************************* # true roundabouts: must be oneway streets forming an endless loop true_roundabouts = [ # roundabout with 2 nodes [0, 1], # roundabout with 3 nodes [2, 3, 4], # roundabout with 4 nodes [5, 6, 7, 8], # roundabout within roundabout 2 [2, 4], # roundabout overlapping with roundabouts 1 and 3 [9, 10, 11], ] for roundabout in true_roundabouts: assert gis_iden.is_roundabout(network, path=roundabout) # ********************************************************************* # ********************************************************************* # fake roundabouts fake_roundabouts = [ # self loop [12, 12], # no oneway attr [13, 14, 15], # oneway = False [16, 17, 18, 19], # true roundabout with one non-existent node added [2, 3, "h", 4], # path whose last node does not lead to the first through a valid edge [5, 6, 7], # true roundabout without the last node (8) [5, 6, 7, 19], # # connect 1 and 3 with a edge # [1, 6] # why? ] for roundabout in fake_roundabouts: assert not gis_iden.is_roundabout(network, path=roundabout) # ********************************************************************* # ********************************************************************* # errors # incorrect path error_raised = False try: gis_iden.is_roundabout(network, path=[1]) except ValueError: error_raised = True assert error_raised # ************************************************************************* # ************************************************************************* def test_identify_points_extremities(self): # ********************************************************************* # ********************************************************************* # redundant points line_coords = tuple([(1.0, 1.0), (2.0, 2.0), (3.0, 0.0)]) line = LineString(line_coords) close_to_start, close_to_end = gis_iden.close_to_extremities( line=line, points=[Point(1, 1), Point(2, 2), Point(3, 0)], ) assert repr(close_to_start) == repr([0]) assert repr(close_to_end) == repr([2]) # redundant points, with distance ( close_to_start, close_to_end, line_distances, start_distances, end_distances, ) = gis_iden.close_to_extremities( line=line, points=[Point(1, 1), Point(2, 2), Point(3, 0)], return_distances=True, ) assert repr(close_to_start) == repr([0]) assert repr(close_to_end) == repr([2]) abs_tols = [1e-3, 1e-3, 1e-3] true_line_distances = [0, 0, 0] true_start_distances = [0, 1.41421356, 2.23606798] true_end_distances = [2.23606798, 2.23606798, 0] for ( line_d, start_d, end_d, true_line_d, true_start_d, true_end_d, abs_tol, ) in zip( line_distances, start_distances, end_distances, true_line_distances, true_start_distances, true_end_distances, abs_tols, ): assert isclose(line_d, true_line_d, abs_tol=abs_tol) assert isclose(start_d, true_start_d, abs_tol=abs_tol) assert isclose(end_d, true_end_d, abs_tol=abs_tol) # ********************************************************************* # ********************************************************************* # redundant points, different order close_to_start, close_to_end = gis_iden.close_to_extremities( line=line, points=[Point(3, 0), Point(2, 2), Point(1, 1)] ) assert repr(close_to_start) == repr([2]) assert repr(close_to_end) == repr([0]) # redundant points, different order, with distance ( close_to_start, close_to_end, line_distances, start_distances, end_distances, ) = gis_iden.close_to_extremities( line=line, points=[Point(3, 0), Point(2, 2), Point(1, 1)], return_distances=True, ) assert repr(close_to_start) == repr([2]) assert repr(close_to_end) == repr([0]) abs_tols = [1e-3, 1e-3, 1e-3] true_line_distances = [0, 0, 0] true_start_distances = [2.23606798, 1.41421356, 0] true_end_distances = [0, 2.23606798, 2.23606798] for ( line_d, start_d, end_d, true_line_d, true_start_d, true_end_d, abs_tol, ) in zip( line_distances, start_distances, end_distances, true_line_distances, true_start_distances, true_end_distances, abs_tols, ): assert isclose(line_d, true_line_d, abs_tol=abs_tol) assert isclose(start_d, true_start_d, abs_tol=abs_tol) assert isclose(end_d, true_end_d, abs_tol=abs_tol) # ********************************************************************* # ********************************************************************* # redundant points, yet another order close_to_start, close_to_end = gis_iden.close_to_extremities( line=line, points=[Point(2, 2), Point(3, 0), Point(1, 1)] ) assert repr(close_to_start) == repr([2]) assert repr(close_to_end) == repr([1]) # redundant points, yet another order, with distance ( close_to_start, close_to_end, line_distances, start_distances, end_distances, ) = gis_iden.close_to_extremities( line=line, points=[Point(2, 2), Point(3, 0), Point(1, 1)], return_distances=True, ) assert repr(close_to_start) == repr([2]) assert repr(close_to_end) == repr([1]) abs_tols = [1e-3, 1e-3, 1e-3] true_line_distances = [0, 0, 0] true_start_distances = [1.41421356, 2.23606798, 0] true_end_distances = [2.23606798, 0, 2.23606798] for ( line_d, start_d, end_d, true_line_d, true_start_d, true_end_d, abs_tol, ) in zip( line_distances, start_distances, end_distances, true_line_distances, true_start_distances, true_end_distances, abs_tols, ): assert isclose(line_d, true_line_d, abs_tol=abs_tol) assert isclose(start_d, true_start_d, abs_tol=abs_tol) assert isclose(end_d, true_end_d, abs_tol=abs_tol) # ********************************************************************* # ********************************************************************* # new points, directly on the line close_to_start, close_to_end = gis_iden.close_to_extremities( line=line, points=[Point(1.2, 1.2), Point(3, 0), Point(1.5, 1.5)], ) assert repr(close_to_start) == repr([]) assert repr(close_to_end) == repr([1]) # new points, directly on the line, with distance ( close_to_start, close_to_end, line_distances, start_distances, end_distances, ) = gis_iden.close_to_extremities( line=line, points=[Point(1.2, 1.2), Point(3, 0), Point(1.5, 1.5)], return_distances=True, ) assert repr(close_to_start) == repr([]) assert repr(close_to_end) == repr([1]) abs_tols = [1e-3, 1e-3, 1e-3] true_line_distances = [0, 0, 0] true_start_distances = [0.28284271, 2.23606798, 0.70710678] true_end_distances = [2.16333077, 0, 2.12132034] for ( line_d, start_d, end_d, true_line_d, true_start_d, true_end_d, abs_tol, ) in zip( line_distances, start_distances, end_distances, true_line_distances, true_start_distances, true_end_distances, abs_tols, ): assert isclose(line_d, true_line_d, abs_tol=abs_tol) assert isclose(start_d, true_start_d, abs_tol=abs_tol) assert isclose(end_d, true_end_d, abs_tol=abs_tol) # ********************************************************************* # ********************************************************************* # new points, extending beyond the line close_to_start, close_to_end = gis_iden.close_to_extremities( line=line, points=[Point(0.5, 0.5), Point(3, 0), Point(4, -2)], ) assert repr(close_to_start) == repr([0]) assert repr(close_to_end) == repr([1, 2]) # new points, extending beyond the line, with distance ( close_to_start, close_to_end, line_distances, start_distances, end_distances, ) = gis_iden.close_to_extremities( line=line, points=[Point(0.5, 0.5), Point(3, 0), Point(4, -2)], return_distances=True, ) assert repr(close_to_start) == repr([0]) assert repr(close_to_end) == repr([1, 2]) abs_tols = [1e-3, 1e-3, 1e-3] true_line_distances = [0.70710678, 0, 2.23606798] true_start_distances = [0.70710678, 2.23606798, 4.24264069] true_end_distances = [2.54950976, 0, 2.23606798] for ( line_d, start_d, end_d, true_line_d, true_start_d, true_end_d, abs_tol, ) in zip( line_distances, start_distances, end_distances, true_line_distances, true_start_distances, true_end_distances, abs_tols, ): assert isclose(line_d, true_line_d, abs_tol=abs_tol) assert isclose(start_d, true_start_d, abs_tol=abs_tol) assert isclose(end_d, true_end_d, abs_tol=abs_tol) # ********************************************************************* # ********************************************************************* # new points, extending beyond the line close_to_start, close_to_end = gis_iden.close_to_extremities( line=line, points=[Point(0.5, 0.5), Point(1.0, 1.0), Point(4, -2)], ) assert repr(close_to_start) == repr([0, 1]) assert repr(close_to_end) == repr([2]) # new points, extending beyond the line, with distance ( close_to_start, close_to_end, line_distances, start_distances, end_distances, ) = gis_iden.close_to_extremities( line=line, points=[Point(0.5, 0.5), Point(1.0, 1.0), Point(4, -2)], return_distances=True, ) assert repr(close_to_start) == repr([0, 1]) assert repr(close_to_end) == repr([2]) abs_tols = [1e-3, 1e-3, 1e-3] true_line_distances = [0.70710678, 0, 2.23606798] true_start_distances = [0.70710678, 0, 4.24264069] true_end_distances = [2.54950976, 2.23606798, 2.23606798] for ( line_d, start_d, end_d, true_line_d, true_start_d, true_end_d, abs_tol, ) in zip( line_distances, start_distances, end_distances, true_line_distances, true_start_distances, true_end_distances, abs_tols, ): assert isclose(line_d, true_line_d, abs_tol=abs_tol) assert isclose(start_d, true_start_d, abs_tol=abs_tol) assert isclose(end_d, true_end_d, abs_tol=abs_tol) # ********************************************************************* # ********************************************************************* # new points, not on the line # expected result: the new points appear on the geometry close_to_start, close_to_end = gis_iden.close_to_extremities( line=line, points=[Point(0.5, 0.75), Point(3.0, -0.5)], ) assert repr(close_to_start) == repr([0]) assert repr(close_to_end) == repr([1]) # new points, not on the line, with distance ( close_to_start, close_to_end, line_distances, start_distances, end_distances, ) = gis_iden.close_to_extremities( line=line, points=[Point(0.5, 0.75), Point(3.0, -0.5)], return_distances=True, ) assert repr(close_to_start) == repr([0]) assert repr(close_to_end) == repr([1]) abs_tols = [1e-3, 1e-3] true_line_distances = [0.55901699, 0.5] true_start_distances = [0.55901699, 2.5] true_end_distances = [2.61007663, 0.5] for ( line_d, start_d, end_d, true_line_d, true_start_d, true_end_d, abs_tol, ) in zip( line_distances, start_distances, end_distances, true_line_distances, true_start_distances, true_end_distances, abs_tols, ): assert isclose(line_d, true_line_d, abs_tol=abs_tol) assert isclose(start_d, true_start_d, abs_tol=abs_tol) assert isclose(end_d, true_end_d, abs_tol=abs_tol) # ********************************************************************* # ********************************************************************* # new points, close to multiple segments line_coords = tuple([(0.0, 0.0), (0.0, 1.0), (1.0, 1.0), (1.0, 0.0)]) line = LineString(line_coords) close_to_start, close_to_end = gis_iden.close_to_extremities( line=line, points=[Point(0.5, 0.5)], ) assert repr(close_to_start) == repr([]) assert repr(close_to_end) == repr([]) # new points, close to multiple segments, with distance ( close_to_start, close_to_end, line_distances, start_distances, end_distances, ) = gis_iden.close_to_extremities( line=line, points=[Point(0.5, 0.5)], return_distances=True ) assert repr(close_to_start) == repr([]) assert repr(close_to_end) == repr([]) abs_tols = [1e-3] true_line_distances = [0.5] true_start_distances = [0.70710678] true_end_distances = [0.70710678] for ( line_d, start_d, end_d, true_line_d, true_start_d, true_end_d, abs_tol, ) in zip( line_distances, start_distances, end_distances, true_line_distances, true_start_distances, true_end_distances, abs_tols, ): assert isclose(line_d, true_line_d, abs_tol=abs_tol) assert isclose(start_d, true_start_d, abs_tol=abs_tol) assert isclose(end_d, true_end_d, abs_tol=abs_tol) # ********************************************************************* # ********************************************************************* # point equidistant to start and end, favour start line_coords = tuple([(0.0, 0.0), (0.0, 1.0), (1.0, 1.0), (1.0, 0.0)]) line = LineString(line_coords) close_to_start, close_to_end = gis_iden.close_to_extremities( line=line, points=[Point(0.5, -0.5)], use_start_point_equidistant=True ) assert repr(close_to_start) == repr([0]) assert repr(close_to_end) == repr([]) # ********************************************************************* # ********************************************************************* # point equidistant to start and end, favour end line_coords = tuple([(0.0, 0.0), (0.0, 1.0), (1.0, 1.0), (1.0, 0.0)]) line = LineString(line_coords) close_to_start, close_to_end = gis_iden.close_to_extremities( line=line, points=[Point(0.5, -0.5)], use_start_point_equidistant=False ) assert repr(close_to_start) == repr([]) assert repr(close_to_end) == repr([0]) # ************************************************************************* # ************************************************************************* def test_identify_self_loops(self): # find one self-loop network = nx.MultiDiGraph() network.add_edges_from([(0, 1, 0), (1, 2, 0), (2, 0, 0), (1, 1, 0)]) true_selflooping_nodes = [1] selflooping_nodes = list(gis_iden.find_self_loops(network)) assert len(selflooping_nodes) == len(true_selflooping_nodes) for node_key in selflooping_nodes: assert node_key in true_selflooping_nodes # find two self-loops network = nx.MultiDiGraph() network.add_edges_from([(0, 1, 0), (1, 2, 0), (2, 0, 0), (1, 1, 0), (2, 2, 0)]) true_selflooping_nodes = [1, 2] selflooping_nodes = list(gis_iden.find_self_loops(network)) assert len(selflooping_nodes) == len(true_selflooping_nodes) for node_key in selflooping_nodes: assert node_key in true_selflooping_nodes # find no self-loops network = nx.MultiDiGraph() network.add_edges_from([(0, 1, 0), (1, 2, 0), (2, 0, 0)]) true_selflooping_nodes = [] selflooping_nodes = list(gis_iden.find_self_loops(network)) assert len(selflooping_nodes) == len(true_selflooping_nodes) assert len(true_selflooping_nodes) == 0 # ************************************************************************* # ************************************************************************* def test_reversed_edges(self): # network = nx.MultiDiGraph() network.add_nodes_from( [ (0, {gis_osm.KEY_OSMNX_X: 0, gis_osm.KEY_OSMNX_Y: 0}), (1, {gis_osm.KEY_OSMNX_X: 0, gis_osm.KEY_OSMNX_Y: 1}), (2, {gis_osm.KEY_OSMNX_X: 0, gis_osm.KEY_OSMNX_Y: 1}), (3, {gis_osm.KEY_OSMNX_X: 0, gis_osm.KEY_OSMNX_Y: 2}), ] ) network.add_edges_from( [ # reversed, without geometry ( 0, 1, 0, { gis_osm.KEY_OSMNX_OSMID: 1, gis_osm.KEY_OSMNX_LENGTH: 1, gis_osm.KEY_OSMNX_ONEWAY: False, gis_osm.KEY_OSMNX_REVERSED: False, }, ), ( 1, 0, 0, { gis_osm.KEY_OSMNX_OSMID: 1, gis_osm.KEY_OSMNX_LENGTH: 1, gis_osm.KEY_OSMNX_ONEWAY: False, gis_osm.KEY_OSMNX_REVERSED: True, }, ), # reversed with geometry ( 2, 3, 0, { gis_osm.KEY_OSMNX_OSMID: 2, gis_osm.KEY_OSMNX_LENGTH: 1, gis_osm.KEY_OSMNX_ONEWAY: False, gis_osm.KEY_OSMNX_GEOMETRY: LineString([(0, 1), (0, 2)]), gis_osm.KEY_OSMNX_REVERSED: False, }, ), ( 3, 2, 0, { gis_osm.KEY_OSMNX_OSMID: 2, gis_osm.KEY_OSMNX_LENGTH: 1, gis_osm.KEY_OSMNX_ONEWAY: False, gis_osm.KEY_OSMNX_GEOMETRY: LineString([(0, 2), (0, 1)]), gis_osm.KEY_OSMNX_REVERSED: True, }, ), # parallel to (0,1,0) but with different osmid ( 0, 1, 1, { gis_osm.KEY_OSMNX_OSMID: 3, gis_osm.KEY_OSMNX_LENGTH: 3, gis_osm.KEY_OSMNX_ONEWAY: False, gis_osm.KEY_OSMNX_GEOMETRY: LineString( [(0, 0), (1, 0), (1, 1), (0, 1)] ), gis_osm.KEY_OSMNX_REVERSED: False, }, ), # parallel to (2,3,0) but with different osmid ( 2, 3, 1, { gis_osm.KEY_OSMNX_OSMID: 4, gis_osm.KEY_OSMNX_LENGTH: 3, gis_osm.KEY_OSMNX_ONEWAY: False, gis_osm.KEY_OSMNX_GEOMETRY: LineString( [(0, 1), (1, 1), (1, 2), (0, 2)] ), gis_osm.KEY_OSMNX_REVERSED: False, }, ), # parallel to (2,3,0) but with a different geometry ( 2, 3, 2, { gis_osm.KEY_OSMNX_OSMID: 2, gis_osm.KEY_OSMNX_LENGTH: 1, gis_osm.KEY_OSMNX_ONEWAY: False, gis_osm.KEY_OSMNX_GEOMETRY: LineString( [(0, 1), (1, 1), (1, 2), (0, 2)] ), gis_osm.KEY_OSMNX_REVERSED: False, }, ), # parallel to (2,3,0) but without a geometry ( 2, 3, 3, { gis_osm.KEY_OSMNX_OSMID: 2, gis_osm.KEY_OSMNX_LENGTH: 1, gis_osm.KEY_OSMNX_ONEWAY: False, gis_osm.KEY_OSMNX_REVERSED: False, }, ), # parallel to (3,2,0) but without a geometry ( 3, 2, 1, { gis_osm.KEY_OSMNX_OSMID: 4, gis_osm.KEY_OSMNX_LENGTH: 3, gis_osm.KEY_OSMNX_ONEWAY: False, gis_osm.KEY_OSMNX_REVERSED: True, }, ), # parallel to (3,2,0) but with a different geometry ( 3, 2, 2, { gis_osm.KEY_OSMNX_OSMID: 2, gis_osm.KEY_OSMNX_LENGTH: 1, gis_osm.KEY_OSMNX_ONEWAY: False, gis_osm.KEY_OSMNX_GEOMETRY: LineString([(0, 0), (0, 1)]), gis_osm.KEY_OSMNX_REVERSED: True, }, ), # edge sharing one node with (0,1,0) and (2,3,0) ( 0, 2, 0, { gis_osm.KEY_OSMNX_OSMID: 5, gis_osm.KEY_OSMNX_ONEWAY: False, gis_osm.KEY_OSMNX_LENGTH: 4, }, ), # edge that is identical to (1,0,0) but has the opposite reversed attr. ( 1, 0, 1, { gis_osm.KEY_OSMNX_OSMID: 1, gis_osm.KEY_OSMNX_LENGTH: 1, gis_osm.KEY_OSMNX_ONEWAY: False, gis_osm.KEY_OSMNX_REVERSED: False, }, ), # edge that is identical to (1,0,0) but has a different length ( 1, 0, 2, { gis_osm.KEY_OSMNX_OSMID: 1, gis_osm.KEY_OSMNX_LENGTH: 3, gis_osm.KEY_OSMNX_ONEWAY: False, gis_osm.KEY_OSMNX_REVERSED: True, }, ), # edges with different list sizes for 'reversed' ( 5, 0, 0, { gis_osm.KEY_OSMNX_OSMID: 1, gis_osm.KEY_OSMNX_LENGTH: 3, gis_osm.KEY_OSMNX_ONEWAY: False, gis_osm.KEY_OSMNX_REVERSED: True, }, ), # simplified edges with the wrong number of osmids ( 6, 7, 0, { gis_osm.KEY_OSMNX_OSMID: [1, 2], gis_osm.KEY_OSMNX_LENGTH: 3, gis_osm.KEY_OSMNX_ONEWAY: False, gis_osm.KEY_OSMNX_REVERSED: False, }, ), ( 7, 6, 0, { gis_osm.KEY_OSMNX_OSMID: [1, 2, 3], gis_osm.KEY_OSMNX_LENGTH: 3, gis_osm.KEY_OSMNX_ONEWAY: False, gis_osm.KEY_OSMNX_REVERSED: True, }, ), # simplified edges with different osmids ( 6, 7, 1, { gis_osm.KEY_OSMNX_OSMID: [1, 3], gis_osm.KEY_OSMNX_LENGTH: 3, gis_osm.KEY_OSMNX_ONEWAY: False, gis_osm.KEY_OSMNX_REVERSED: False, }, ), ( 7, 6, 1, { gis_osm.KEY_OSMNX_OSMID: [1, 2], gis_osm.KEY_OSMNX_LENGTH: 3, gis_osm.KEY_OSMNX_ONEWAY: False, gis_osm.KEY_OSMNX_REVERSED: True, }, ), # edges without a 'reversed' attribute ( 7, 6, 2, { gis_osm.KEY_OSMNX_OSMID: [1, 2], gis_osm.KEY_OSMNX_ONEWAY: False, gis_osm.KEY_OSMNX_REVERSED: True, gis_osm.KEY_OSMNX_LENGTH: 3, }, ), # edges with different 'osmid' attribute types ( 7, 6, 3, { gis_osm.KEY_OSMNX_OSMID: {1, 2}, gis_osm.KEY_OSMNX_LENGTH: 3, gis_osm.KEY_OSMNX_ONEWAY: False, gis_osm.KEY_OSMNX_REVERSED: True, }, ), # simplified edges with non-boolean types ( 7, 8, 0, { gis_osm.KEY_OSMNX_OSMID: [1, 2], gis_osm.KEY_OSMNX_LENGTH: 3, gis_osm.KEY_OSMNX_ONEWAY: False, gis_osm.KEY_OSMNX_REVERSED: 0, }, ), ( 8, 7, 0, { gis_osm.KEY_OSMNX_OSMID: [2, 1], gis_osm.KEY_OSMNX_LENGTH: 3, gis_osm.KEY_OSMNX_ONEWAY: False, gis_osm.KEY_OSMNX_REVERSED: 1, }, ), # simplified edges without True or without False ( 7, 8, 1, { gis_osm.KEY_OSMNX_OSMID: [1, 2], gis_osm.KEY_OSMNX_LENGTH: 3, gis_osm.KEY_OSMNX_ONEWAY: False, gis_osm.KEY_OSMNX_REVERSED: [True], }, ), ( 8, 7, 1, { gis_osm.KEY_OSMNX_OSMID: [2, 1], gis_osm.KEY_OSMNX_LENGTH: 3, gis_osm.KEY_OSMNX_ONEWAY: False, gis_osm.KEY_OSMNX_REVERSED: [False], }, ), # simplified edges ( 7, 8, 2, { gis_osm.KEY_OSMNX_OSMID: [1, 2], gis_osm.KEY_OSMNX_LENGTH: 3, gis_osm.KEY_OSMNX_ONEWAY: False, gis_osm.KEY_OSMNX_REVERSED: [True, False], }, ), ( 8, 7, 2, { gis_osm.KEY_OSMNX_OSMID: [2, 1], gis_osm.KEY_OSMNX_LENGTH: 3, gis_osm.KEY_OSMNX_ONEWAY: False, gis_osm.KEY_OSMNX_REVERSED: [True, False], }, ), ] ) # test reversed edges without geometry assert gis_iden.edges_are_in_reverse( network, edge_a=(0, 1, 0), edge_b=(1, 0, 0) ) assert gis_iden.edges_are_in_reverse( network, edge_a=(1, 0, 0), edge_b=(0, 1, 0) ) # test reversed edges with geometry assert gis_iden.edges_are_in_reverse( network, edge_a=(2, 3, 0), edge_b=(3, 2, 0) ) assert gis_iden.edges_are_in_reverse( network, edge_a=(3, 2, 0), edge_b=(2, 3, 0) ) # test non-reversed edges between the same nodes assert not gis_iden.edges_are_in_reverse( network, edge_a=(1, 0, 0), edge_b=(0, 1, 1) ) assert not gis_iden.edges_are_in_reverse( network, edge_a=(0, 1, 1), edge_b=(1, 0, 0) ) assert not gis_iden.edges_are_in_reverse( network, edge_a=(0, 1, 0), edge_b=(0, 1, 1) ) assert not gis_iden.edges_are_in_reverse( network, edge_a=(0, 1, 1), edge_b=(0, 1, 0) ) # test non-reversed edges between the same nodes assert not gis_iden.edges_are_in_reverse( network, edge_a=(3, 2, 0), edge_b=(2, 3, 1) ) assert not gis_iden.edges_are_in_reverse( network, edge_a=(2, 3, 1), edge_b=(3, 2, 0) ) assert not gis_iden.edges_are_in_reverse( network, edge_a=(2, 3, 0), edge_b=(2, 3, 1) ) assert not gis_iden.edges_are_in_reverse( network, edge_a=(2, 3, 1), edge_b=(2, 3, 0) ) # test edges that are not parallel/anti-parallel assert not gis_iden.edges_are_in_reverse( network, edge_a=(0, 1, 0), edge_b=(0, 2, 0) ) assert not gis_iden.edges_are_in_reverse( network, edge_a=(0, 2, 0), edge_b=(0, 1, 0) ) assert not gis_iden.edges_are_in_reverse( network, edge_a=(0, 1, 0), edge_b=(2, 3, 0) ) assert not gis_iden.edges_are_in_reverse( network, edge_a=(2, 3, 0), edge_b=(0, 1, 0) ) # test edges with the same osmid but whose reversed attribues are the same assert not gis_iden.edges_are_in_reverse( network, edge_a=(0, 1, 0), edge_b=(1, 0, 1) ) assert not gis_iden.edges_are_in_reverse( network, edge_a=(1, 0, 1), edge_b=(0, 1, 0) ) # test edges that have the same osmid but somehow have different lengths assert not gis_iden.edges_are_in_reverse( network, edge_a=(0, 1, 0), edge_b=(1, 0, 2) ) # test edges that have the different geometries assert not gis_iden.edges_are_in_reverse( network, edge_a=(2, 3, 2), edge_b=(3, 2, 0) ) assert not gis_iden.edges_are_in_reverse( network, edge_a=(3, 2, 0), edge_b=(2, 3, 2) ) # # old: # # test one edge with a simple geometry against one without a geometry (False case: no match) # assert not gis_iden.edges_are_in_reverse( # network, edge_a=(2, 3, 3), edge_b=(3, 2, 2)) # assert not gis_iden.edges_are_in_reverse( # network, edge_a=(3, 2, 2), edge_b=(2, 3, 3)) # # test one edge with a simple geometry against one without a geometry (True case: match) # assert gis_iden.edges_are_in_reverse( # network, edge_a=(2, 3, 3), edge_b=(3, 2, 0)) # assert gis_iden.edges_are_in_reverse( # network, edge_a=(3, 2, 0), edge_b=(2, 3, 3)) # new: geometries should exist in both or not at all # test one edge with a simple geometry against one without a geometry (False case: no match) assert not gis_iden.edges_are_in_reverse( network, edge_a=(2, 3, 3), edge_b=(3, 2, 2) ) assert not gis_iden.edges_are_in_reverse( network, edge_a=(3, 2, 2), edge_b=(2, 3, 3) ) # test one edge with a simple geometry against one without a geometry (True case: match) assert not gis_iden.edges_are_in_reverse( network, edge_a=(2, 3, 3), edge_b=(3, 2, 0) ) assert not gis_iden.edges_are_in_reverse( network, edge_a=(3, 2, 0), edge_b=(2, 3, 3) ) # test one edge with a simplified geometry against one without a geometry (False) assert not gis_iden.edges_are_in_reverse( network, edge_a=(2, 3, 1), edge_b=(3, 2, 1) ) assert not gis_iden.edges_are_in_reverse( network, edge_a=(3, 2, 1), edge_b=(2, 3, 1) ) # test non-inexistent edges error_raised = False try: gis_iden.edges_are_in_reverse(network, edge_a=(5, 0, 0), edge_b=(0, 5, 0)) except ValueError: error_raised = True assert error_raised # test simplified edges with the wrong number of osmids assert not gis_iden.edges_are_in_reverse( network, edge_a=(6, 7, 0), edge_b=(7, 6, 0) ) assert not gis_iden.edges_are_in_reverse( network, edge_a=(7, 6, 0), edge_b=(6, 7, 0) ) # test simplified edges with thedifferent osmids assert not gis_iden.edges_are_in_reverse( network, edge_a=(6, 7, 1), edge_b=(7, 6, 1) ) assert not gis_iden.edges_are_in_reverse( network, edge_a=(7, 6, 1), edge_b=(6, 7, 1) ) # test simplified edges assert gis_iden.edges_are_in_reverse( network, edge_a=(6, 7, 0), edge_b=(7, 6, 1) ) assert gis_iden.edges_are_in_reverse( network, edge_a=(7, 6, 1), edge_b=(6, 7, 0) ) # test edges with a 'reversed' attribute assert gis_iden.edges_are_in_reverse( network, edge_a=(6, 7, 0), edge_b=(7, 6, 2) ) assert gis_iden.edges_are_in_reverse( network, edge_a=(7, 6, 2), edge_b=(6, 7, 0) ) # test simplified edges without True or without False assert not gis_iden.edges_are_in_reverse( network, edge_a=(7, 8, 1), edge_b=(8, 7, 1) ) assert not gis_iden.edges_are_in_reverse( network, edge_a=(8, 7, 1), edge_b=(7, 8, 1) ) # test simplified edges assert gis_iden.edges_are_in_reverse( network, edge_a=(7, 8, 2), edge_b=(8, 7, 2) ) assert gis_iden.edges_are_in_reverse( network, edge_a=(8, 7, 2), edge_b=(7, 8, 2) ) # errors # test edges with different 'osmid' attribute types error_raised = False try: assert not gis_iden.edges_are_in_reverse( network, edge_a=(6, 7, 0), edge_b=(7, 6, 3) ) except ValueError: error_raised = True assert error_raised # test edges with different 'osmid' attribute types error_raised = False try: assert not gis_iden.edges_are_in_reverse( network, edge_a=(7, 6, 3), edge_b=(6, 7, 0) ) except ValueError: error_raised = True assert error_raised # test simplified edges with non-boolean types error_raised = False try: assert not gis_iden.edges_are_in_reverse( network, edge_a=(7, 8, 0), edge_b=(8, 7, 0) ) except ValueError: error_raised = True assert error_raised # test simplified edges with non-boolean types, reverse error_raised = False try: assert not gis_iden.edges_are_in_reverse( network, edge_a=(8, 7, 0), edge_b=(7, 8, 0) ) except ValueError: error_raised = True assert error_raised # test simplified edges with non-boolean types assert not gis_iden.edges_are_in_reverse( network, edge_a=(6, 7, 0), edge_b=(8, 7, 0) ) # test simplified edges with non-boolean types, reverse assert not gis_iden.edges_are_in_reverse( network, edge_a=(8, 7, 0), edge_b=(6, 7, 0) ) # test simplified edges with non-boolean types assert not gis_iden.edges_are_in_reverse( network, edge_a=(6, 7, 0), edge_b=(7, 8, 0) ) # test simplified edges with non-boolean types, reverse assert not gis_iden.edges_are_in_reverse( network, edge_a=(7, 8, 0), edge_b=(6, 7, 0) ) # ************************************************************************* # ************************************************************************* def test_osmnx_compliance(self): # get the network network = ox.graph_from_point( (55.71654, 9.11728), network_type="drive", custom_filter=('["highway"~"residential|tertiary|unclassified|service"]'), truncate_by_edge=True, ) for edge_key in network.edges(keys=True): assert gis_iden.is_edge_osmnx_compliant(network, edge_key) # try a non-existent edge edge_key = ("a", "b", "c") assert not network.has_edge(*edge_key) error_raised = False try: assert not gis_iden.is_edge_osmnx_compliant(network, edge_key) except ValueError: error_raised = True assert error_raised # add uncompliant edges network.add_edges_from( [ # edge with non-integer osmids ( "a", "b", 0, { gis_osm.KEY_OSMNX_OSMID: "hello", gis_osm.KEY_OSMNX_LENGTH: 3, gis_osm.KEY_OSMNX_ONEWAY: False, gis_osm.KEY_OSMNX_REVERSED: [True, False], }, ), # edge with non-integer osmids in a list ( "a", "b", 1, { gis_osm.KEY_OSMNX_OSMID: [1, "a"], gis_osm.KEY_OSMNX_LENGTH: 3, gis_osm.KEY_OSMNX_ONEWAY: False, gis_osm.KEY_OSMNX_REVERSED: [True, False], }, ), # edge with non-numeric lengths ( "a", "b", 2, { gis_osm.KEY_OSMNX_OSMID: [1, 2], gis_osm.KEY_OSMNX_LENGTH: "three", gis_osm.KEY_OSMNX_ONEWAY: False, gis_osm.KEY_OSMNX_REVERSED: [True, False], }, ), # edge with non-LineString geometries ( "a", "b", 3, { gis_osm.KEY_OSMNX_OSMID: [1, 2], gis_osm.KEY_OSMNX_LENGTH: 3, gis_osm.KEY_OSMNX_ONEWAY: False, gis_osm.KEY_OSMNX_REVERSED: [True, False], gis_osm.KEY_OSMNX_GEOMETRY: Point((1, 0)), }, ), # edge with non-boolean reversed attr in a list ( "a", "b", 4, { gis_osm.KEY_OSMNX_OSMID: [1, 2], gis_osm.KEY_OSMNX_LENGTH: 3, gis_osm.KEY_OSMNX_ONEWAY: False, gis_osm.KEY_OSMNX_REVERSED: ["True", False], }, ), # edge with non-boolean oneway ( "a", "b", 5, { gis_osm.KEY_OSMNX_OSMID: [1, 2], gis_osm.KEY_OSMNX_LENGTH: 3, gis_osm.KEY_OSMNX_REVERSED: [True, False], gis_osm.KEY_OSMNX_ONEWAY: "True", }, ), # edge with non-boolean oneway in a list ( "a", "b", 6, { gis_osm.KEY_OSMNX_OSMID: [1, 2], gis_osm.KEY_OSMNX_LENGTH: 3, gis_osm.KEY_OSMNX_REVERSED: [True, False], gis_osm.KEY_OSMNX_ONEWAY: [False, "True"], }, ), # edge without all the essential attributes ( "a", "b", 7, { gis_osm.KEY_OSMNX_OSMID: [1, 2], gis_osm.KEY_OSMNX_REVERSED: [True, False], gis_osm.KEY_OSMNX_ONEWAY: False, }, ), ] ) # edge with non-integer osmids edge_key = ("a", "b", 0) assert not gis_iden.is_edge_osmnx_compliant(network, edge_key) edge_key = ("a", "b", 1) assert not gis_iden.is_edge_osmnx_compliant(network, edge_key) edge_key = ("a", "b", 2) assert not gis_iden.is_edge_osmnx_compliant(network, edge_key) edge_key = ("a", "b", 3) assert not gis_iden.is_edge_osmnx_compliant(network, edge_key) edge_key = ("a", "b", 4) assert not gis_iden.is_edge_osmnx_compliant(network, edge_key) edge_key = ("a", "b", 5) assert not gis_iden.is_edge_osmnx_compliant(network, edge_key) edge_key = ("a", "b", 6) assert not gis_iden.is_edge_osmnx_compliant(network, edge_key) edge_key = ("a", "b", 7) assert not gis_iden.is_edge_osmnx_compliant(network, edge_key) # error_raised = False # try: # edge_key = ('a', 'b', 'c') # assert not gis_iden.is_edge_osmnx_compliant(network, edge_key) # except ValueError: # error_raised = True # assert error_raised # ************************************************************************* # ************************************************************************* def test_reversed_edges_osmnx(self): # get the network network = ox.graph_from_point( (55.71654, 9.11728), network_type="drive", custom_filter=('["highway"~"residential|tertiary|unclassified|service"]'), truncate_by_edge=True, ) # create edge to trigger the negative case with a different length # (317812803, 317812802, 2) edge_k = network.add_edge( 317812803, 317812802, **{ "osmid": 28913471, "name": "Tingstedet", "highway": "residential", "maxspeed": "50", "oneway": False, "reversed": True, "length": 27.601 + 1, } ) assert edge_k == 2 # create edge tp trigger the negative case with a different geometry # (317812802, 317812803, 2) edge_k = network.add_edge( 317812802, 317812803, **{ "osmid": 28913483, "name": "Tingstedet", "highway": "residential", "maxspeed": "50", "oneway": False, "reversed": False, "length": 99.155, "geometry": LineString([(1, 3), (2, 4)]), } ) assert edge_k == 2 # find edges that have matching edges in the reverse direction for edge_key in network.edges(keys=True): edge_dict = network.get_edge_data(*edge_key) for _attr in gis_osm.KEYS_OSMNX_EDGES_ESSENTIAL: assert _attr in edge_dict.keys() # for each edge, find if there is one in the opposite direction if network.has_edge(u=edge_key[1], v=edge_key[0]): # there is an edge in the opposite sense for other_edge_key in gis_iden.get_edges_from_a_to_b( network=network, node_start=edge_key[1], node_end=edge_key[0] ): # check if the edges are the same but in reverse if gis_iden.edges_are_in_reverse( network, edge_a=edge_key, edge_b=other_edge_key ): # the edges are the same but in reverse: # - all attributes have to be the same or lists with # the same content, as in a set, except for # the geometry and reversed attributes fw_dict = network.get_edge_data(*edge_key) rv_dict = network.get_edge_data(*other_edge_key) # should have the same attributes assert set(fw_dict.keys()) == set(rv_dict.keys()) # the attributes must be identical except if they are # lists or if they geometries or reversed arguments for attr_key, attr_value in fw_dict.items(): if type(attr_value) == list: # the dict values are lists, their equivalent # sets must match (they cannot be geometries) assert set(attr_value) == set(rv_dict[attr_key]) elif attr_key == gis_osm.KEY_OSMNX_GEOMETRY: # the dict values are geometries, they must be # the reverse of one another assert tuple(attr_value.coords) == tuple( rv_dict[attr_key].reverse().coords ) elif attr_key == gis_osm.KEY_OSMNX_REVERSED: # the dict values are the reversed attributes, # they must be opposites (since type(..)!=list) assert not attr_value == rv_dict[attr_key] elif attr_key == gis_osm.KEY_OSMNX_LENGTH: # the dict values are the reversed attributes, # they must be opposites (since type(..)!=list) assert isclose( attr_value, rv_dict[attr_key], abs_tol=1e-3 ) else: # the dict values are not lists, nor geometries # nor reversed attributes: they must match assert attr_value == rv_dict[attr_key] else: # the edges are not the same in reverse # at least one of their attributes must be different or # incompatible fw_dict = network.get_edge_data(*edge_key) rv_dict = network.get_edge_data(*other_edge_key) error_raised = False try: # should have the same attributes assert set(fw_dict.keys()) == set(rv_dict.keys()) # the attributes must be identical except if they are # lists or if they geometries or reversed arguments for attr_key, attr_value in fw_dict.items(): if type(attr_value) == list: # the dict values are lists, their equivalent # sets must match (they cannot be geometries) assert set(attr_value) == set(rv_dict[attr_key]) elif attr_key == gis_osm.KEY_OSMNX_GEOMETRY: # the dict values are geometries, they must be # the reverse of one another assert tuple(attr_value.coords) == tuple( rv_dict[attr_key].reverse().coords ) elif attr_key == gis_osm.KEY_OSMNX_REVERSED: # the dict values are the reversed attributes, # they must be opposites (since type(..)!=list) assert not attr_value == rv_dict[attr_key] elif attr_key == gis_osm.KEY_OSMNX_LENGTH: # the dict values are the reversed attributes, # they must be opposites (since type(..)!=list) assert isclose( attr_value, rv_dict[attr_key], abs_tol=1e-3 ) else: # the dict values are not lists, nor geometries # nor reversed attributes: they must match assert attr_value == rv_dict[attr_key] except Exception: error_raised = True assert error_raised # ************************************************************************* # ************************************************************************* def test_edge_geometry_consistency(self): network = nx.MultiDiGraph() node_key0 = 0 node_key0_dict = {gis_osm.KEY_OSMNX_X: 55, gis_osm.KEY_OSMNX_Y: 25} node_key1 = 1 node_key1_dict = {gis_osm.KEY_OSMNX_X: 55.001, gis_osm.KEY_OSMNX_Y: 25.001} network.add_node(node_key0, **node_key0_dict) network.add_node(node_key1, **node_key1_dict) # create a line between node 0 and node 1 geo_line = LineString( [ ( node_key0_dict[gis_osm.KEY_OSMNX_X], node_key0_dict[gis_osm.KEY_OSMNX_Y], ), ( node_key1_dict[gis_osm.KEY_OSMNX_X], node_key1_dict[gis_osm.KEY_OSMNX_Y], ), ] ) # the same line, reversed geo_line_reversed = geo_line.reverse() k_no_geo = network.add_edge(0, 1, **{gis_osm.KEY_OSMNX_LENGTH: 3}) k_normal = network.add_edge( 0, 1, **{gis_osm.KEY_OSMNX_LENGTH: 3, gis_osm.KEY_OSMNX_GEOMETRY: geo_line} ) k_reversed = network.add_edge( 0, 1, **{ gis_osm.KEY_OSMNX_LENGTH: 3, gis_osm.KEY_OSMNX_GEOMETRY: geo_line_reversed, } ) # edge without geometry should be consistent edge_key = (node_key0, node_key1, k_no_geo) assert gis_iden.is_edge_consistent_with_geometry(network, edge_key) # edge with normal geometry should be consistent edge_key = (node_key0, node_key1, k_normal) assert gis_iden.is_edge_consistent_with_geometry(network, edge_key) # edge with reversed geometry should not be consistent edge_key = (node_key0, node_key1, k_reversed) assert not gis_iden.is_edge_consistent_with_geometry(network, edge_key) # trigger no edge found error error_raised = False try: edge_key = (node_key0, node_key1, k_no_geo - 1) gis_iden.is_edge_consistent_with_geometry(network, edge_key) except ValueError: error_raised = True assert error_raised # ************************************************************************* # ************************************************************************* def test_edge_geometry_consistency_osmnx(self): # get the network network = ox.graph_from_point( (55.71654, 9.11728), network_type="drive", custom_filter=('["highway"~"residential|tertiary|unclassified|service"]'), truncate_by_edge=True, ) for edge_key in network.edges(keys=True): assert gis_iden.is_edge_consistent_with_geometry(network, edge_key) edge_key = (115831, 1104936963, 0) assert gis_iden.is_edge_consistent_with_geometry(network, edge_key) edge_key = (1104936963, 115831, 0) assert gis_iden.is_edge_consistent_with_geometry(network, edge_key) # ************************************************************************* # ************************************************************************* def test_valid_node_paths(self): # ********************************************************************* # ********************************************************************* # create network network = nx.MultiDiGraph() # define and add edges list_edges = [ (0, 1), (1, 2), (2, 3), # path 1 (4, 3), (5, 4), (6, 5), # path 2 (6, 7), (7, 8), (8, 9), # path 3 (2, 2), # self loop on path 1 (4, 4), # self loop on path 2 (9, 9), # self loop on path 3 (10, 8), # extra lone neighbour for node 8 on ] network.add_edges_from(list_edges) # ********************************************************************* # ********************************************************************* valid_node_paths = [[0, 1, 2, 3], [6, 5, 4, 3], [6, 7, 8, 9], [10, 8, 9]] invalid_node_paths = [ [], # empty list [1], # single node path [-1, 0, 1, 2, 3], # nodes do not belong to the network [3, 2, 1, 0], # path 1 reversed [3, 4, 5, 6], # path 2 reversed [9, 8, 7, 6], # path 3 reversed [6, 7, 8, 10], # node 10 is connected to node 8 but not the other way arou. ] # make sure valid node paths are valid for path in valid_node_paths: assert gis_iden.is_node_path(network, path) # make sure invalid node paths are invalid for path in invalid_node_paths: assert not gis_iden.is_node_path(network, path) # ********************************************************************* # ********************************************************************* consider_reversed_edges = True valid_node_paths = [ [0, 1, 2, 3], [6, 5, 4, 3], [6, 7, 8, 9], [10, 8, 9], [3, 2, 1, 0], # path 1 reversed [3, 4, 5, 6], # path 2 reversed [9, 8, 7, 6], # path 3 reversed [6, 7, 8, 10], # node 10 is connected to node 8 but not the other way arou. ] invalid_node_paths = [ [], # empty list [1], # single node path [-1, 0, 1, 2, 3], # nodes do not belong to the network ] # make sure valid node paths are valid for path in valid_node_paths: assert gis_iden.is_node_path(network, path, consider_reversed_edges) # make sure invalid node paths are invalid for path in invalid_node_paths: assert not gis_iden.is_node_path(network, path, consider_reversed_edges) # ************************************************************************* # ************************************************************************* def test_valid_edge_paths(self): # ********************************************************************* # ********************************************************************* # create network network = nx.MultiDiGraph() # define and add edges list_edges = [ (0, 1), (1, 2), (2, 3), # path 1 (4, 3), (5, 4), (6, 5), # path 2 (6, 7), (7, 8), (8, 9), # path 3 (2, 2), # self loop on path 1 (4, 4), # self loop on path 2 (9, 9), # self loop on path 3 (10, 8), # extra lone neighbour for node 8 on ] network.add_edges_from(list_edges) # ********************************************************************* # ********************************************************************* valid_edge_paths = [ [(0, 1), (1, 2), (2, 3)], [(6, 5), (5, 4), (4, 3)], [(6, 7), (7, 8), (8, 9)], [(10, 8), (8, 9)], [(0, 1, 0), (1, 2, 0), (2, 3, 0)], # with keys [(6, 5, 0), (5, 4, 0), (4, 3, 0)], # with keys [(6, 7, 0), (7, 8, 0), (8, 9, 0)], # with keys [(10, 8, 0), (8, 9, 0)], # with keys ] invalid_edge_paths = [ [(0, 1, 1), (1, 2, 0), (2, 3, 3)], # with incorrect keys [(6, 5, 2), (5, 4, 0), (4, 3, 2)], # with incorrect keys [(6, 7, 3), (7, 8, 0), (8, 9, 1)], # with incorrect keys [(10, 8, 0), (8, 9, 2)], # with incorrect keys [], # empty list [(-1, 0), (0, 1), (1, 2), (2, 3)], # nodes do not belong to the network [(3, 2), (2, 1), (1, 0)], # path 1 reversed [(3, 4), (4, 5), (5, 6)], # path 2 reversed [(9, 8), (8, 7), (7, 6)], # path 3 reversed [ (6, 7), (7, 8), (8, 10), ], # node 10 is connected to node 8 but not the other way [(), (7, 8), (8)], # unknown format # [(6,5,0),(5,4),(4,3,0)], # inconsistent edge key format [(6, 5), (9, 9), (5, 4), (4, 3)], # no sequence due to (9,9) ] for path in valid_edge_paths: assert gis_iden.is_edge_path(network, path) # make sure invalid node paths are invalid for path in invalid_edge_paths: assert not gis_iden.is_edge_path(network, path) # ********************************************************************* # ********************************************************************* # inconsistent edge key format # allowed assert gis_iden.is_edge_path( network, path=[(6, 5, 0), (5, 4), (4, 3, 0)], allow_multiple_formats=True ) # not allowed error_raised = False try: # inconsistent edge key format gis_iden.is_edge_path( network, path=[(6, 5, 0), (5, 4), (4, 3, 0)], allow_multiple_formats=False, ) except ValueError: error_raised = True assert error_raised # ********************************************************************* # ********************************************************************* ignore_edge_direction = True valid_edge_paths = [ [(0, 1), (1, 2), (2, 3)], [(6, 5), (5, 4), (4, 3)], [(6, 7), (7, 8), (8, 9)], [(10, 8), (8, 9)], [(0, 1, 0), (1, 2, 0), (2, 3, 0)], # with keys [(6, 5, 0), (5, 4, 0), (4, 3, 0)], # with keys [(6, 7, 0), (7, 8, 0), (8, 9, 0)], # with keys [(10, 8, 0), (8, 9, 0)], # with keys [(2, 3), (1, 2), (0, 1)], # path 1 reversed [(4, 3), (5, 4), (6, 5)], # path 2 reversed [(8, 9), (7, 8), (6, 7)], # path 3 reversed [ (6, 7), (7, 8), (10, 8), ], # node 10 is connected to node 8 but not the other way ] invalid_edge_paths = [ [(0, 1, 1), (1, 2, 0), (2, 3, 3)], # with incorrect keys [(6, 5, 2), (5, 4, 0), (4, 3, 2)], # with incorrect keys [(6, 7, 3), (7, 8, 0), (8, 9, 1)], # with incorrect keys [(10, 8, 0), (8, 9, 2)], # with incorrect keys [], # empty list [ (-1, 0), (0, 1), (1, 2), (2, 3), ], # nodes do not belong to the network arou. # [(10,8,0),(8,9)], # different key formats # [(6,5),(5,4,0),(4,3)], # different key formats [(), (5, 4, 0), (4, 3)], # unknown key formats [(6, 5), (9, 9), (5, 4, 0), (4, 3)], # no sequence due to (9,9) ] for path in valid_edge_paths: assert gis_iden.is_edge_path( network, path, ignore_edge_direction=ignore_edge_direction ) # make sure invalid node paths are invalid for path in invalid_edge_paths: assert not gis_iden.is_edge_path( network, path, ignore_edge_direction=ignore_edge_direction ) # ********************************************************************* # ********************************************************************* # inconsistent edge key format # allowed assert gis_iden.is_edge_path( network, path=[(10, 8, 0), (8, 9)], allow_multiple_formats=True ) # not allowed error_raised = False try: # inconsistent edge key format gis_iden.is_edge_path( network, path=[(10, 8, 0), (8, 9)], allow_multiple_formats=False ) except ValueError: error_raised = True assert error_raised # inconsistent edge key format # allowed assert gis_iden.is_edge_path( network, path=[(6, 5), (5, 4, 0), (4, 3)], allow_multiple_formats=True ) # not allowed error_raised = False try: # inconsistent edge key format gis_iden.is_edge_path( network, path=[(6, 5), (5, 4, 0), (4, 3)], allow_multiple_formats=False ) except ValueError: error_raised = True assert error_raised # ********************************************************************* # ********************************************************************* # ************************************************************************* # ************************************************************************* def test_straight_paths_reversed_edges_self_loops(self): # create network network = nx.MultiDiGraph() # define and add edges list_edges = [ (0, 1), (1, 2), (2, 3), # path 1 (4, 3), (5, 4), (6, 5), # path 2 (6, 7), (7, 8), (8, 9), # path 3 (2, 2), # self loop on path 1 (4, 4), # self loop on path 2 (9, 9), # self loop on path 3 (10, 8), # extra lone neighbour for node 8 on ] network.add_edges_from(list_edges) # reversed edges are okay, self loops too ignore_self_loops = True consider_reversed_edges = True # valid node paths valid_straight_node_paths = [ [0, 1, 2], [1, 2, 3], [0, 1, 2, 3], [5, 4, 3], [6, 5, 4], [6, 5, 4, 3], [0, 1], # just two nodes [0, 1, 2, 3, 4], # node 4 is connected using an edge in the opposite dir. [6, 5, 4, 3, 2], # node 2 is connected using an edge in the opposite dir. [3, 4, 5, 6], # the path is reversed ] # invalid node paths invalid_straight_node_paths = [ [6, 7, 8, 9], # node 8 has three neighbours (7, 9 and 10) [0, 4, 1], # node 4 is not a neighbour of nodes 0 and 1 [11, 3, 4, 5, 6], # there is no node 11 ] # make sure valid node paths are valid for path in valid_straight_node_paths: assert gis_iden.is_path_straight( network, path, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # make sure invalid node paths are invalid for path in invalid_straight_node_paths: assert not gis_iden.is_path_straight( network, path, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # ********************************************************************* # ********************************************************************* # ************************************************************************* # ************************************************************************* def test_straight_paths_no_reversed_edges_self_loops(self): # create network network = nx.MultiDiGraph() # define and add edges list_edges = [ (0, 1), (1, 2), (2, 3), # path 1 (4, 3), (5, 4), (6, 5), # path 2 (6, 7), (7, 8), (8, 9), # path 3 (2, 2), # self loop on path 1 (4, 4), # self loop on path 2 (9, 9), # self loop on path 3 (10, 8), # extra lone neighbour for node 8 on ] network.add_edges_from(list_edges) # no reversed edges, self loops are okay ignore_self_loops = True consider_reversed_edges = False # valid node paths valid_straight_node_paths = [ [0, 1, 2], [1, 2, 3], [0, 1, 2, 3], [5, 4, 3], [6, 5, 4], [6, 5, 4, 3], [0, 1], # just two nodes ] # invalid node paths invalid_straight_node_paths = [ [2, 1, 0], # reversed path [3, 2, 1], # reversed path [3, 2, 1, 0], # reversed path [3, 4, 5], # reversed path [4, 5, 6], # reversed path [3, 4, 5, 6], # reversed path [0, 1, 2, 3, 4, 5, 6, 7, 8], # path with reversed elements [8, 7, 6, 5, 4, 3, 2, 1, 0], # path with reversed element [0, 1, 2, 3, 4], # path with reversed elements [6, 5, 4, 3, 2], # the last edge is reversed [6, 7, 8, 9], # node 8 has three neighbours (7, 9 and 10) [0, 4, 1], # node 4 is not a neighbour of nodes 0 and 1 [11, 3, 4, 5, 6], # there is no node 11 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], # node 8 has three neighbours (7, 9 and 10) [9, 8, 7, 6, 5, 4, 3, 2, 1, 0], # node 8 has three neighbours (7, 9 and 10) ] # make sure valid node paths are valid for path in valid_straight_node_paths: assert gis_iden.is_path_straight( network, path, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # make sure invalid node paths are invalid for path in invalid_straight_node_paths: assert not gis_iden.is_path_straight( network, path, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # ********************************************************************* # ********************************************************************* # ************************************************************************* # ************************************************************************* def test_straight_paths_no_reversed_edges_no_self_loops(self): # create network network = nx.MultiDiGraph() # define and add edges list_edges = [ (0, 1), (1, 2), (2, 3), # path 1 (4, 3), (5, 4), (6, 5), # path 2 (6, 7), (7, 8), (8, 9), # path 3 (2, 2), # self loop on path 1 (4, 4), # self loop on path 2 (9, 9), # self loop on path 3 (10, 8), # extra lone neighbour for node 8 on ] network.add_edges_from(list_edges) # no reversed edges, self loops are not okay ignore_self_loops = False consider_reversed_edges = False # (0,1),(1,2),(2,3), # path 1 # (4,3),(5,4),(6,5), # path 2 # (6,7),(7,8),(8,9), # path 3 # (2,2), # self loop on path 1 # (4,4), # self loop on path 2 # (9,9), # self loop on path 3 # valid node paths valid_straight_node_paths = [[6, 5, 4], [6, 7, 8], [0, 1, 2]] # invalid node paths invalid_straight_node_paths = [ [1, 2, 3], [0, 1, 2, 3], [5, 4, 3], [6, 5, 4, 3], [4, 5, 6], [8, 7, 6], [2, 1, 0], ] # make sure valid node paths are valid for path in valid_straight_node_paths: assert gis_iden.is_path_straight( network, path, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # make sure invalid node paths are invalid for path in invalid_straight_node_paths: assert not gis_iden.is_path_straight( network, path, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # ********************************************************************* # ********************************************************************* # ************************************************************************* # ************************************************************************* def test_straight_paths_reversed_edges_no_self_loops(self): # create network network = nx.MultiDiGraph() # define and add edges list_edges = [ (0, 1), (1, 2), (2, 3), # path 1 (4, 3), (5, 4), (6, 5), # path 2 (6, 7), (7, 8), (8, 9), # path 3 (2, 2), # self loop on path 1 (4, 4), # self loop on path 2 (9, 9), # self loop on path 3 (10, 8), # extra lone neighbour for node 8 on ] network.add_edges_from(list_edges) # reversed edges are okay, self loops are not ignore_self_loops = False consider_reversed_edges = True # valid node paths valid_straight_node_paths = [ [4, 5, 6], [6, 5, 4], [6, 7, 8], [8, 7, 6], [0, 1, 2], [2, 1, 0], ] # invalid node paths invalid_straight_node_paths = [[1, 2, 3], [0, 1, 2, 3], [5, 4, 3], [6, 5, 4, 3]] # make sure valid node paths are valid for path in valid_straight_node_paths: assert gis_iden.is_path_straight( network, path, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # make sure invalid node paths are invalid for path in invalid_straight_node_paths: assert not gis_iden.is_path_straight( network, path, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # ********************************************************************* # ********************************************************************* # ************************************************************************* # ************************************************************************* def test_straight_path_parallel_antiparallel_edges(self): # create network network = nx.MultiDiGraph() # define and add edges list_edges = [ (0, 1, 0), (1, 2, 0), (2, 3, 0), # path 1 (4, 5, 0), (5, 6, 0), (6, 7, 0), # path 2 (8, 9, 0), (9, 10, 0), (10, 11, 0), # path 3 # extra edges (0, 1, 0), # path 1 (5, 4, 0), # path 2 (8, 9, 0), (11, 10, 0), # path 3 ] network.add_edges_from(list_edges) # reversed edges are okay, self loops are not ignore_self_loops = True consider_reversed_edges = True # valid node paths valid_straight_node_paths = [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]] # make sure valid node paths are valid for path in valid_straight_node_paths: assert gis_iden.is_path_straight( network, path, consider_reversed_edges=consider_reversed_edges, ignore_self_loops=ignore_self_loops, ) # ********************************************************************* # ********************************************************************* # ************************************************************************* # ************************************************************************* def test_nearest_node_keys(self): # ********************************************************************* # create a network network = nx.MultiDiGraph() network.graph["crs"] = "EPSG:4326" # network.graph['crs'] = 'init' # add edges and nodes number_edges = random.randint(3, 10) edge_keys = [ (random.randint(0, number_edges), random.randint(0, number_edges)) for edge_index in range(number_edges) ] network.add_edges_from(edge_keys) # add attributes to the nodes used in the edges for node_key in network.nodes(): _xy = (random.random(), random.random()) network.add_node(node_key, x=_xy[0], y=_xy[0]) # add new (unconnected) nodes number_new_nodes = random.randint(3, 5) unconnected_node_keys = [] for node_index in range(number_new_nodes): new_node_key = uuid.uuid4() _xy = (random.random(), random.random()) network.add_node(new_node_key, x=_xy[0], y=_xy[0]) unconnected_node_keys.append(new_node_key) # ********************************************************************* # find the nearest nodes using the osmnx method nearest_node_keys = gis_iden.nearest_nodes( network, [network.nodes[node_key]["x"] for node_key in unconnected_node_keys], [network.nodes[node_key]["y"] for node_key in unconnected_node_keys], ) # assert that the test is meaningful assert len(nearest_node_keys) != 0 assert len(nearest_node_keys) == len(unconnected_node_keys) # assert that the nodes are the same for i, node_key in enumerate(unconnected_node_keys): assert node_key == nearest_node_keys[i] # ********************************************************************* # find the nodes nearest to select nodes excluding themselves nearest_node_keys = gis_iden.nearest_nodes_other_than_themselves( network, unconnected_node_keys ) # assert that the test is meaningful assert len(nearest_node_keys) != 0 assert len(nearest_node_keys) == len(unconnected_node_keys) all_node_keys = list(network.nodes()) list_all_geos = [] for node_key in all_node_keys: list_all_geos.append( Point((network.nodes[node_key]["x"], network.nodes[node_key]["y"])) ) all_node_geos = { node_key: list_all_geos[i] for i, node_key in enumerate(all_node_keys) } # for each node for i, node_key in enumerate(unconnected_node_keys): # assert that they are not the same assert node_key != nearest_node_keys[i] # verify that the distance between is the lowest among all unconnected_node_geo = all_node_geos[node_key] all_distances = [ unconnected_node_geo.distance(all_node_geos[other_node_key]) for other_node_key in all_node_keys if other_node_key != node_key ] actual_distance = unconnected_node_geo.distance( all_node_geos[nearest_node_keys[i]] ) assert isclose(min(all_distances), actual_distance, abs_tol=1) # ************************************************************************* # ************************************************************************* def test_finding_roundabouts(self): # network should be a OSM-nx formatted graph network = ox.graph_from_point( (55.71654, 9.11728), network_type="drive", custom_filter='["highway"~"residential|tertiary|unclassified|service"]', truncate_by_edge=True, ) # find all roundabouts roundabouts = gis_iden.find_roundabouts(network) # confirm they are roundabouts for roundabout in roundabouts: assert gis_iden.is_roundabout(network, roundabout) # find roundabouts with constraints roundabouts = gis_iden.find_roundabouts( network, maximum_perimeter=200, minimum_perimeter=25, maximum_number_nodes=6, minimum_number_nodes=4, ) # confirm they are roundabouts for roundabout in roundabouts: assert gis_iden.is_roundabout(network, roundabout) # ************************************************************************* # ************************************************************************* def test_finding_reversed_edges(self): # network should be a OSM-nx formatted graph network = ox.graph_from_point( (55.71654, 9.11728), network_type="drive", custom_filter=('["highway"~"residential|tertiary|unclassified|service"]'), truncate_by_edge=True, ) # find edges in reverse edges_in_rev = gis_iden.find_edges_in_reverse(network) # confirm for edge_key, reversed_edge_keys in edges_in_rev.items(): for _edge_key in reversed_edge_keys: assert gis_iden.edges_are_in_reverse(network, edge_key, _edge_key) # ************************************************************************* # ************************************************************************* # ***************************************************************************** # *****************************************************************************