Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix multi edge simplify bug #76

Merged
merged 3 commits into from
Apr 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion genet/use/schedule.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def generate_edge_vph_geodataframe(df, gdf_links):
df = df.groupby(groupby_cols).sum().reset_index()

cols_to_delete = list(set(df.columns) - (set(groupby_cols) | {'vph'}))
df = pd.merge(gpd.GeoDataFrame(df), gdf_links, left_on=['from_stop', 'to_stop'],
df = pd.merge(gpd.GeoDataFrame(df, crs=gdf_links.crs), gdf_links, left_on=['from_stop', 'to_stop'],
right_on=['u', 'v'])
cols_to_delete.extend(['u', 'v', 'key', 'routes', 'services'])
df = df.drop(cols_to_delete, axis=1)
Expand Down
11 changes: 7 additions & 4 deletions genet/utils/simplification.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import genet.utils.parallel as parallel
from math import ceil
from shapely.geometry import LineString, Point
import logging
from math import ceil
from statistics import median

from shapely.geometry import LineString, Point

import genet.utils.parallel as parallel


# rip and monkey patch of a few functions from osmnx.simplification to customise graph simplification

Expand Down Expand Up @@ -195,7 +197,8 @@ def simplify_graph(n, no_processes=1):

logging.info('Generating paths to be simplified')
# generate each path that needs to be simplified
edges_to_simplify = _get_edge_groups_to_simplify(n.graph, no_processes=no_processes)
edges_to_simplify = [list(x) for x in
set(tuple(x) for x in _get_edge_groups_to_simplify(n.graph, no_processes=no_processes))]
logging.info(f'Found {len(edges_to_simplify)} paths to simplify.')

indexed_paths_to_simplify = dict(zip(n.generate_indices_for_n_edges(len(edges_to_simplify)), edges_to_simplify))
Expand Down
60 changes: 50 additions & 10 deletions tests/test_core_network.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
import ast
import json
import os
import sys
import ast
import uuid
import pandas as pd

import lxml
import networkx as nx
import pandas as pd
import pytest
import lxml
import json
from shapely.geometry import LineString, Polygon
from pandas.testing import assert_frame_equal, assert_series_equal
from tests.fixtures import route, stop_epsg_27700, network_object_from_test_data, assert_semantically_equal, \
full_fat_default_config_path, correct_schedule, vehicle_definitions_config_path
from tests.test_outputs_handler_matsim_xml_writer import network_dtd, schedule_dtd
from genet.inputs_handler import matsim_reader
from shapely.geometry import LineString, Polygon

from genet.core import Network
from genet.inputs_handler import matsim_reader
from tests.test_outputs_handler_matsim_xml_writer import network_dtd, schedule_dtd
from genet.schedule_elements import Route, Service, Schedule
from genet.utils import plot, spatial, graph_operations
from genet.utils import plot, spatial
from tests.fixtures import assert_semantically_equal, route, stop_epsg_27700, network_object_from_test_data, \
full_fat_default_config_path, correct_schedule, vehicle_definitions_config_path

sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
pt2matsim_network_test_file = os.path.abspath(
Expand Down Expand Up @@ -487,6 +489,44 @@ def test_simplified_network_saves_to_correct_dtds(tmpdir, network_dtd, schedule_
schedule_dtd.error_log.filter_from_errors())


def test_simplifying_network_with_multi_edges_resulting_in_multi_paths():
n = Network('epsg:27700')
n.add_nodes({
'n_-1': {'x': -1, 'y': -1, 's2_id': -1},
'n_0': {'x': 0, 'y': 0, 's2_id': 0},
'n_1': {'x': 1, 'y': 1, 's2_id': 1},
'n_2': {'x': 2, 'y': 2, 's2_id': 2},
'n_3': {'x': 3, 'y': 3, 's2_id': 3},
'n_4': {'x': 4, 'y': 4, 's2_id': 4},
'n_5': {'x': 5, 'y': 5, 's2_id': 5},
'n_6': {'x': 6, 'y': 5, 's2_id': 6},
})
n.add_links({
'l_-1': {'from': 'n_-1', 'to': 'n_1', 'freespeed': 1, 'capacity': 1, 'permlanes': 1, 'length': 1,
'modes': {'car'}},
'l_0': {'from': 'n_0', 'to': 'n_1', 'freespeed': 1, 'capacity': 1, 'permlanes': 1, 'length': 1,
'modes': {'car'}},
'l_1': {'from': 'n_1', 'to': 'n_2', 'freespeed': 1, 'capacity': 1, 'permlanes': 1, 'length': 1,
'modes': {'car'}},
'l_2': {'from': 'n_1', 'to': 'n_2', 'freespeed': 1, 'capacity': 1, 'permlanes': 1, 'length': 1,
'modes': {'car'}},
'l_3': {'from': 'n_2', 'to': 'n_3', 'freespeed': 1, 'capacity': 1, 'permlanes': 1, 'length': 1,
'modes': {'car'}},
'l_4': {'from': 'n_2', 'to': 'n_3', 'freespeed': 1, 'capacity': 1, 'permlanes': 1, 'length': 1,
'modes': {'car'}},
'l_5': {'from': 'n_3', 'to': 'n_4', 'freespeed': 1, 'capacity': 1, 'permlanes': 1, 'length': 1,
'modes': {'car'}},
'l_6': {'from': 'n_3', 'to': 'n_4', 'freespeed': 1, 'capacity': 1, 'permlanes': 1, 'length': 1,
'modes': {'car'}},
'l_7': {'from': 'n_4', 'to': 'n_5', 'freespeed': 1, 'capacity': 1, 'permlanes': 1, 'length': 1,
'modes': {'car'}},
'l_8': {'from': 'n_4', 'to': 'n_6', 'freespeed': 1, 'capacity': 1, 'permlanes': 1, 'length': 1,
'modes': {'car'}}
})
n.simplify()
assert set(n.link_simplification_map) == {'l_4', 'l_1', 'l_5', 'l_3', 'l_6', 'l_2'}


def test_reading_back_simplified_network():
# simplified networks have additional geometry attribute and some of their attributes are composite, e.g. links
# now refer to a number of osm ways each with a unique id
Expand Down
13 changes: 7 additions & 6 deletions tests/test_outputs_handler_geojson.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,12 +219,13 @@ def test_generating_standard_outputs(network, tmpdir):
'vehicles_per_hour_bus.geojson',
'vehicles_per_hour_rail.geojson'}
assert set(os.listdir(os.path.join(tmpdir, 'schedule', 'vehicles_per_hour', 'shp_files'))) == {
'vehicles_per_hour_rail.cpg', 'vehicles_per_hour_all_modes.cpg', 'vehicles_per_hour_all_modes.dbf',
'vehicles_per_hour_bus.shx', 'vph_all_modes_within_6:30-7:30.cpg', 'vehicles_per_hour_bus.cpg',
'vph_all_modes_within_6:30-7:30.shx', 'vehicles_per_hour_all_modes.shp', 'vehicles_per_hour_all_modes.shx',
'vehicles_per_hour_rail.dbf', 'vehicles_per_hour_rail.shx', 'vph_all_modes_within_6:30-7:30.dbf',
'vehicles_per_hour_bus.shp', 'vehicles_per_hour_bus.dbf', 'vehicles_per_hour_rail.shp',
'vph_all_modes_within_6:30-7:30.shp'}
'vehicles_per_hour_all_modes.cpg', 'vehicles_per_hour_bus.prj', 'vehicles_per_hour_rail.dbf',
'vph_all_modes_within_6:30-7:30.shx', 'vehicles_per_hour_bus.shp', 'vehicles_per_hour_rail.cpg',
'vehicles_per_hour_all_modes.prj', 'vehicles_per_hour_all_modes.shp', 'vehicles_per_hour_rail.shx',
'vehicles_per_hour_rail.prj', 'vph_all_modes_within_6:30-7:30.cpg', 'vehicles_per_hour_bus.shx',
'vehicles_per_hour_bus.dbf', 'vph_all_modes_within_6:30-7:30.shp', 'vph_all_modes_within_6:30-7:30.prj',
'vph_all_modes_within_6:30-7:30.dbf', 'vehicles_per_hour_bus.cpg', 'vehicles_per_hour_all_modes.dbf',
'vehicles_per_hour_rail.shp', 'vehicles_per_hour_all_modes.shx'}
assert set(os.listdir(os.path.join(tmpdir, 'schedule', 'subgraphs'))) == {'schedule_subgraph_links_bus.geojson',
'schedule_subgraph_links_rail.geojson',
'shp_files',
Expand Down
6 changes: 3 additions & 3 deletions tests/test_use_schedule.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ def test_generating_edge_vph_geodataframe(schedule):
10: LineString([(-7.5570681956375, 49.766856648946295),
(-7.557121424907424, 49.76683608549253)]),
11: LineString([(-7.5570681956375, 49.766856648946295),
(-7.557121424907424, 49.76683608549253)])}})
(-7.557121424907424, 49.76683608549253)])}}, crs='epsg:4326')

assert_geodataframe_equal(df.sort_index(axis=1), correct_df.sort_index(axis=1), check_less_precise=True)

Expand Down Expand Up @@ -161,7 +161,7 @@ def test_generating_edge_vph_geodataframe_for_service(schedule):
10: LineString([(-7.5570681956375, 49.766856648946295),
(-7.557121424907424, 49.76683608549253)]),
11: LineString([(-7.5570681956375, 49.766856648946295),
(-7.557121424907424, 49.76683608549253)])}})
(-7.557121424907424, 49.76683608549253)])}}, crs='epsg:4326')

assert_geodataframe_equal(df.sort_index(axis=1), correct_df.sort_index(axis=1), check_less_precise=True)

Expand Down Expand Up @@ -191,7 +191,7 @@ def test_generating_edge_vph_geodataframe_for_route(schedule):
4: LineString([(-7.5570681956375, 49.766856648946295),
(-7.557121424907424, 49.76683608549253)]),
5: LineString([(-7.5570681956375, 49.766856648946295),
(-7.557121424907424, 49.76683608549253)])}})
(-7.557121424907424, 49.76683608549253)])}}, crs='epsg:4326')

assert_geodataframe_equal(df.sort_index(axis=1), correct_df.sort_index(axis=1), check_less_precise=True)

Expand Down