From 2cc9292a426e51c63c0c1277fd5b8aae53c209cd Mon Sep 17 00:00:00 2001 From: Pedro Camargo Date: Tue, 7 Jul 2020 13:49:09 +1000 Subject: [PATCH] Addresses issue 158 (#159) * Addresses issue 158 * Style changes --- aequilibrae/paths/AoN.pyx | 22 ++++++--- aequilibrae/paths/all_or_nothing.py | 6 +-- aequilibrae/paths/linear_approximation.py | 2 +- aequilibrae/paths/network_skimming.py | 6 +-- aequilibrae/paths/parameters.pxi | 2 +- aequilibrae/paths/results/path_results.py | 8 ++- aequilibrae/project/network/network.py | 4 +- .../project/network/osm_utils/place_getter.py | 2 +- tests/aequilibrae/paths/test_pathResults.py | 46 +++++++++++------- tests/data/test_graph.aeg | Bin 26023 -> 26023 bytes 10 files changed, 61 insertions(+), 37 deletions(-) diff --git a/aequilibrae/paths/AoN.pyx b/aequilibrae/paths/AoN.pyx index 025aa4472..9a383fcab 100644 --- a/aequilibrae/paths/AoN.pyx +++ b/aequilibrae/paths/AoN.pyx @@ -20,7 +20,6 @@ include 'basic_path_finding.pyx' include 'bpr.pyx' include 'parallel_numpy.pyx' -from libc.stdlib cimport abort, malloc, free from .__version__ import binary_version as VERSION_COMPILED def one_to_all(origin, matrix, graph, result, aux_result, curr_thread): @@ -209,14 +208,14 @@ def path_computation(origin, destination, graph, results): origin_index = graph.nodes_to_indices[orig] dest_index = graph.nodes_to_indices[dest] if results.__graph_id__ != graph.__id__: - return "Results object not prepared. Use --> results.prepare(graph)" + raise ValueError("Results object not prepared. Use --> results.prepare(graph)") # Consistency checks # if origin >= graph.fs.shape[0]: # raise ValueError ("Node " + str(origin) + " is outside the range of nodes in the graph") if VERSION_COMPILED != graph.__version__: - return 'This graph was created for a different version of AequilibraE. Please re-create it' + raise ValueError('This graph was created for a different version of AequilibraE. Please re-create it') #We transform the python variables in Cython variables nodes = graph.num_nodes @@ -286,6 +285,7 @@ def path_computation(origin, destination, graph, results): if predecessors_view[dest_index] > 0: all_connectors = [] + link_directions = [] all_nodes = [dest_index] mileposts = [] p = dest_index @@ -294,11 +294,13 @@ def path_computation(origin, destination, graph, results): p = predecessors_view[p] connector = conn_view[dest_index] all_connectors.append(graph.graph['link_id'][connector]) + link_directions.append(graph.graph['direction'][connector]) mileposts.append(g_view[connector]) all_nodes.append(p) dest_index = p results.path = np.asarray(all_connectors, graph.default_types('int'))[::-1] results.path_nodes = graph.all_nodes[np.asarray(all_nodes, graph.default_types('int'))][::-1] + results.path_link_directions = np.asarray(link_directions, graph.default_types('int'))[::-1] mileposts.append(0) results.milepost = np.cumsum(mileposts[::-1]) @@ -328,6 +330,7 @@ def update_path_trace(results, destination, graph): results.path_nodes = None if results.predecessors[dest_index] > 0: all_connectors = [] + link_directions = [] all_nodes = [dest_index] mileposts = [] p = dest_index @@ -336,10 +339,12 @@ def update_path_trace(results, destination, graph): p = results.predecessors[p] connector = results.connectors[dest_index] all_connectors.append(graph.graph['link_id'][connector]) + link_directions.append(graph.graph['direction'][connector]) mileposts.append(graph.cost[connector]) all_nodes.append(p) dest_index = p results.path = np.asarray(all_connectors, graph.default_types('int'))[::-1] + results.path_link_directions = np.asarray(link_directions, graph.default_types('int'))[::-1] results.path_nodes = graph.all_nodes[np.asarray(all_nodes, graph.default_types('int'))][::-1] mileposts.append(0) results.milepost = np.cumsum(mileposts[::-1]) @@ -359,19 +364,20 @@ def skimming_single_origin(origin, graph, result, aux_result, curr_thread): graph_fs = graph.fs if result.__graph_id__ != graph.__id__: - return "Results object not prepared. Use --> results.prepare(graph)" + + raise ValueError("Results object not prepared. Use --> results.prepare(graph)") if orig not in graph.centroids: - return "Centroid " + str(orig) + " is outside the range of zones in the graph" + raise ValueError("Centroid " + str(orig) + " is outside the range of zones in the graph") if origin_index > graph.num_nodes: - return "Centroid " + str(orig) + " does not exist in the graph" + raise ValueError("Centroid " + str(orig) + " does not exist in the graph") if graph_fs[origin_index] == graph_fs[origin_index + 1]: - return "Centroid " + str(orig) + " does not exist in the graph" + raise ValueError("Centroid " + str(orig) + " does not exist in the graph") if VERSION_COMPILED != graph.__version__: - return 'This graph was created for a different version of AequilibraE. Please re-create it' + raise ValueError('This graph was created for a different version of AequilibraE. Please re-create it') nodes = graph.num_nodes + 1 zones = graph.num_zones diff --git a/aequilibrae/paths/all_or_nothing.py b/aequilibrae/paths/all_or_nothing.py index 64b30af0e..844b13464 100644 --- a/aequilibrae/paths/all_or_nothing.py +++ b/aequilibrae/paths/all_or_nothing.py @@ -80,16 +80,16 @@ def execute(self): if pyqt: self.assignment.emit(["finished_threaded_procedure", None]) - def func_assig_thread(self, O, all_threads): + def func_assig_thread(self, origin, all_threads): thread_id = threading.get_ident() th = all_threads.get(thread_id, all_threads["count"]) if th == all_threads["count"]: all_threads[thread_id] = all_threads["count"] all_threads["count"] += 1 - x = one_to_all(O, self.matrix, self.graph, self.results, self.aux_res, th) + x = one_to_all(origin, self.matrix, self.graph, self.results, self.aux_res, th) self.cumulative += 1 - if x != O: + if x != origin: self.report.append(x) if pyqt: self.assignment.emit(["zones finalized", self.cumulative]) diff --git a/aequilibrae/paths/linear_approximation.py b/aequilibrae/paths/linear_approximation.py index 00d6cefcf..3e43793e2 100644 --- a/aequilibrae/paths/linear_approximation.py +++ b/aequilibrae/paths/linear_approximation.py @@ -25,7 +25,7 @@ from scipy.optimize import root as root_scalar recent_scipy = False - logger.warning(f"Using older version of Scipy. For better performance, use Scipy >= 1.4") + logger.warning("Using older version of Scipy. For better performance, use Scipy >= 1.4") if False: from aequilibrae.paths.traffic_assignment import TrafficAssignment diff --git a/aequilibrae/paths/network_skimming.py b/aequilibrae/paths/network_skimming.py index dda782d36..637513680 100644 --- a/aequilibrae/paths/network_skimming.py +++ b/aequilibrae/paths/network_skimming.py @@ -68,16 +68,16 @@ def execute(self): self.skimming.emit(["text skimming", "Saving Outputs"]) self.skimming.emit(["finished_threaded_procedure", None]) - def func_skim_thread(self, O, all_threads): + def func_skim_thread(self, origin, all_threads): if threading.get_ident() in all_threads: th = all_threads[threading.get_ident()] else: all_threads[threading.get_ident()] = all_threads["count"] th = all_threads["count"] all_threads["count"] += 1 - x = skimming_single_origin(O, self.graph, self.results, self.aux_res, th) + x = skimming_single_origin(origin, self.graph, self.results, self.aux_res, th) self.cumulative += 1 - if x != O: + if x != origin: self.report.append(x) if pyqt: self.skimming.emit(["zones finalized", self.cumulative]) diff --git a/aequilibrae/paths/parameters.pxi b/aequilibrae/paths/parameters.pxi index cc35225e4..5f2caa2b4 100644 --- a/aequilibrae/paths/parameters.pxi +++ b/aequilibrae/paths/parameters.pxi @@ -16,5 +16,5 @@ cdef double INFINITE = 1.79769313e+308 VERSION = 0.6 MINOR_VRSN = 5 -binary_version = "0.6.1" +binary_version = "0.6.2" release_name = "Rio de Janeiro" \ No newline at end of file diff --git a/aequilibrae/paths/results/path_results.py b/aequilibrae/paths/results/path_results.py index a76c86574..bfa2e6606 100644 --- a/aequilibrae/paths/results/path_results.py +++ b/aequilibrae/paths/results/path_results.py @@ -30,7 +30,11 @@ class PathResults: res.prepare(car_graph) res.compute_path(17, 13199) - # res.milepost, res.path_nodes, res.path, res.skims contain all results + # res.milepost contains the milepost corresponding to each node along the path + # res.path_nodes contains the sequence of nodes that form the path + # res.path contains the sequence of links that form the path + # res.path_link_directions contains the link directions corresponding to the above links + # res.skims contain all skims requested when preparing the graph # Update all the outputs mentioned above for destination 1265. Same origin: 17 res.update_trace(1265) @@ -45,6 +49,7 @@ def __init__(self) -> None: self.skims = None self.path = None self.path_nodes = None + self.path_link_directions = None self.milepost = None self.reached_first = None self.origin = None @@ -105,6 +110,7 @@ def reset(self) -> None: self.skims.fill(np.inf) self.path = None self.path_nodes = None + self.path_link_directions = None self.milepost = None else: diff --git a/aequilibrae/project/network/network.py b/aequilibrae/project/network/network.py index 2978b84b5..fc7c18456 100644 --- a/aequilibrae/project/network/network.py +++ b/aequilibrae/project/network/network.py @@ -262,8 +262,8 @@ def build_graphs(self) -> None: raw_links = curr.execute(f"select {','.join(all_fields)} from links").fetchall() links = [] - for l in raw_links: - lk = list(map(lambda x: np.nan if x is None else x, l)) + for link in raw_links: + lk = list(map(lambda x: np.nan if x is None else x, link)) links.append(lk) data = np.core.records.fromrecords(links, names=all_fields) diff --git a/aequilibrae/project/network/osm_utils/place_getter.py b/aequilibrae/project/network/osm_utils/place_getter.py index 51fa4cddd..42f157caa 100644 --- a/aequilibrae/project/network/osm_utils/place_getter.py +++ b/aequilibrae/project/network/osm_utils/place_getter.py @@ -69,6 +69,6 @@ def placegetter(place: str) -> Tuple[Union[None, List[float]], list]: if attempts == max_attempts - 1 and bbox is None: report.append("Reached maximum download attempts. Please wait a few minutes and try again") else: - report.append(f"We got an error for place query.") + report.append("We got an error for place query.") return (bbox, report) diff --git a/tests/aequilibrae/paths/test_pathResults.py b/tests/aequilibrae/paths/test_pathResults.py index cb22848f5..e5cf41d08 100644 --- a/tests/aequilibrae/paths/test_pathResults.py +++ b/tests/aequilibrae/paths/test_pathResults.py @@ -5,6 +5,7 @@ from aequilibrae.paths import path_computation, Graph from aequilibrae.paths.results import PathResults from ...data import test_graph +import numpy as np # Adds the folder with the data to the path and collects the paths to the files lib_path = os.path.abspath(os.path.join("..", "../tests")) @@ -15,7 +16,7 @@ class TestPathResults(TestCase): - def test_prepare(self): + def setUp(self) -> None: # graph self.g = Graph() self.g.load_from_disk(test_graph) @@ -28,18 +29,25 @@ def test_prepare(self): self.fail("Path result preparation failed - {}".format(err.__str__())) def test_reset(self): - self.test_prepare() - try: - self.r.reset() - except Exception as err: - self.fail("Path result resetting failed - {}".format(err.__str__())) + self.r.compute_path(dest, origin) + self.r.reset() + + self.assertEqual(self.r.path, None, 'Fail to reset the Path computation object') + self.assertEqual(self.r.path_nodes, None, 'Fail to reset the Path computation object') + self.assertEqual(self.r.path_link_directions, None, 'Fail to reset the Path computation object') + self.assertEqual(self.r.milepost, None, 'Fail to reset the Path computation object') + self.assertEqual(self.r.predecessors.max(), -1, 'Fail to reset the Path computation object') + self.assertEqual(self.r.predecessors.min(), -1, 'Fail to reset the Path computation object') + self.assertEqual(self.r.connectors.max(), -1, 'Fail to reset the Path computation object') + self.assertEqual(self.r.connectors.min(), -1, 'Fail to reset the Path computation object') + self.assertEqual(self.r.skims.max(), np.inf, 'Fail to reset the Path computation object') + self.assertEqual(self.r.skims.min(), np.inf, 'Fail to reset the Path computation object') + + new_r = PathResults() + with self.assertRaises(ValueError): + new_r.reset() def test_compute_paths(self): - self.test_prepare() - try: - self.r.reset() - except Exception as err: - self.fail("Path result resetting failed - {}".format(err.__str__())) path_computation(origin, dest, self.g, self.r) @@ -63,13 +71,14 @@ def test_compute_paths(self): if list(self.r.milepost) != [0, 341, 1398, 2162]: self.fail("Path computation failed. Wrong milepost results") - def test_update_trace(self): - self.test_prepare() - try: - self.r.reset() - except Exception as err: - self.fail("Path result resetting failed - {}".format(err.__str__())) + if list(self.r.path_link_directions) != [-1, -1, -1]: + self.fail("Path computation failed. Wrong link directions") + + self.r.compute_path(dest, origin) + if list(self.r.path_link_directions) != [1, 1, 1]: + self.fail("Path computation failed. Wrong link directions") + def test_update_trace(self): self.r.compute_path(origin, dest - 1) self.r.update_trace(dest) @@ -82,3 +91,6 @@ def test_update_trace(self): if list(self.r.milepost) != [0, 341, 1398, 2162]: self.fail("Path computation failed. Wrong milepost results") + + if list(self.r.path_link_directions) != [-1, -1, -1]: + self.fail("Path computation failed. Wrong link directions") diff --git a/tests/data/test_graph.aeg b/tests/data/test_graph.aeg index d0aa4d984d6d3b2d08a4b7e3535f4c6eaee7404c..39d2f48dd1e112fb15cc4a4b3d60194742f9c9bd 100644 GIT binary patch delta 15 WcmZ2}nsNDQ#tqG>j7F1NQk4NXW(H9J delta 15 WcmZ2}nsNDQ#tqG>jE0k2Qk4NXVFpkD