Skip to content

Commit

Permalink
add intermodal checks to validation report
Browse files Browse the repository at this point in the history
  • Loading branch information
KasiaKoz committed Aug 18, 2023
1 parent 0fb9ecd commit 4ab6653
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 22 deletions.
15 changes: 15 additions & 0 deletions genet/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -2126,6 +2126,7 @@ def generate_validation_report(self, modes_for_strong_connectivity=None, link_me
logging.info('Checking validity of the Network')
logging.info('Checking validity of the Network graph')
report = {}
is_valid_network = True

# describe network connectivity
if modes_for_strong_connectivity is None:
Expand All @@ -2135,6 +2136,8 @@ def generate_validation_report(self, modes_for_strong_connectivity=None, link_me
graph_connectivity = {}
for mode in modes_for_strong_connectivity:
graph_connectivity[mode] = self.check_connectivity_for_mode(mode)
if graph_connectivity[mode]['number_of_connected_subgraphs'] not in {0, 1}:
is_valid_network = False
report['graph'] = {'graph_connectivity': graph_connectivity}

isolated_nodes = self.isolated_nodes()
Expand All @@ -2144,6 +2147,7 @@ def generate_validation_report(self, modes_for_strong_connectivity=None, link_me
}
if self.has_isolated_nodes():
logging.warning('This Network has isolated nodes! Consider cleaning it up with `remove_isolated_nodes`')
is_valid_network = False

# attribute checks
conditions_toolbox = network_validation.ConditionsToolbox()
Expand Down Expand Up @@ -2191,6 +2195,17 @@ def links_over_threshold_length(value):
'service_routes_with_invalid_network_route': self.invalid_network_routes(),
'route_to_crow_fly_ratio': route_to_crow_fly_ratio
}
if not (report['routing']['services_have_routes_in_the_graph']):
is_valid_network = False

report['intermodal_access_egress'] = {
'has_valid_intermodal_connections': self.has_valid_intermodal_access_egress_connections(),
'invalid_intermodal_connections': self.invalid_intermodal_access_egress_connections()
}
if not (report['schedule']['schedule_level']['is_valid_schedule'] and report['intermodal_access_egress'][
'has_valid_intermodal_connections']):
is_valid_network = False
report['is_valid_network'] = is_valid_network
return report

def report_on_link_attribute_condition(self, attribute, condition):
Expand Down
58 changes: 36 additions & 22 deletions tests/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,30 +258,44 @@ def __init__(self):
'lat': 51.52228713323965,
's2_id': 5221390328605860387}
})
self.network.add_link('link_0', 'A', 'B',
attribs={
'id': 'link_0',
'from': 'A',
'to': 'B',
'freespeed': 10,
'capacity': 600,
'permlanes': 1,
'oneway': '1',
'modes': ['car'],
's2_from': 5221390329378179879,
's2_to': 5221390328605860387,
'length': 53
})
self.network.add_links({
'link_AB': {
'id': 'link_AB',
'from': 'A',
'to': 'B',
'freespeed': 10,
'capacity': 600,
'permlanes': 1,
'oneway': '1',
'modes': ['car', 'bus'],
's2_from': 5221390329378179879,
's2_to': 5221390328605860387,
'length': 53
},
'link_BA': {
'id': 'link_BA',
'from': 'B',
'to': 'A',
'freespeed': 10,
'capacity': 600,
'permlanes': 1,
'oneway': '1',
'modes': ['car', 'bus'],
's2_from': 5221390329378179879,
's2_to': 5221390328605860387,
'length': 53
}
})
self.network.schedule = Schedule(epsg='epsg:27700', services=[
Service(id='service',
routes=[
Route(id='route', route_short_name='route', mode='bus',
stops=[Stop(id='Stop_A', x=528705, y=182069, epsg='epsg:27700', linkRefId='link_0'),
Stop(id='Stop_B', x=528836, y=182007, epsg='epsg:27700', linkRefId='link_0')],
stops=[Stop(id='Stop_A', x=528705, y=182069, epsg='epsg:27700', linkRefId='link_AB'),
Stop(id='Stop_B', x=528836, y=182007, epsg='epsg:27700', linkRefId='link_BA')],
trips={'trip_id': ['trip_id_04:40:00'],
'trip_departure_time': ['04:40:00'],
'vehicle_id': ['veh_1_bus']},
route=['link_0'],
route=['link_AB', 'link_BA'],
arrival_offsets=['00:00:00', '00:02:00'],
departure_offsets=['00:00:00', '00:02:00'])
])
Expand Down Expand Up @@ -316,14 +330,14 @@ def with_valid_car_intermodal_access_egress(self):
new_stops_data = {
'Stop_A': {
'attributes': {
access_link_id_tag: 'link_0',
access_link_id_tag: 'link_AB',
accessible_tag: 'true',
distance_catchment_tag: 10
}
},
'Stop_B': {
'attributes': {
access_link_id_tag: 'link_0',
access_link_id_tag: 'link_BA',
accessible_tag: 'true',
distance_catchment_tag: 10
}
Expand All @@ -332,7 +346,7 @@ def with_valid_car_intermodal_access_egress(self):
self.schedule.apply_attributes_to_stops(new_stops_data)
self.intermodal_access_egress_attribute_keys = [access_link_id_tag]
self.intermodal_access_egress_connections_dataframe = pd.DataFrame(
{'attributes::accessLinkId_car': {'Stop_A': 'link_0', 'Stop_B': 'link_0'}})
{'attributes::accessLinkId_car': {'Stop_A': 'link_AB', 'Stop_B': 'link_BA'}})
self.invalid_intermodal_access_egress_connections = {
'car': {
'stops_with_links_not_in_network': set(),
Expand All @@ -355,7 +369,7 @@ def with_invalid_intermodal_access_egress(self):
},
'Stop_B': {
'attributes': {
access_link_id_tag: 'link_0', # stop with link that doesn't have the right mode on it
access_link_id_tag: 'link_BA', # stop with link that doesn't have the right mode on it
accessible_tag: 'true',
distance_catchment_tag: 10
}
Expand All @@ -364,7 +378,7 @@ def with_invalid_intermodal_access_egress(self):
self.schedule.apply_attributes_to_stops(new_stops_data)
self.intermodal_access_egress_attribute_keys = [access_link_id_tag]
self.intermodal_access_egress_connections_dataframe = pd.DataFrame(
{'attributes::accessLinkId_piggyback': {'Stop_A': 'non_existent_link', 'Stop_B': 'link_0'}})
{'attributes::accessLinkId_piggyback': {'Stop_A': 'non_existent_link', 'Stop_B': 'link_BA'}})
self.invalid_intermodal_access_egress_connections = {
'piggyback': {
'stops_with_links_not_in_network': {'Stop_A'},
Expand Down
12 changes: 12 additions & 0 deletions tests/test_core_network.py
Original file line number Diff line number Diff line change
Expand Up @@ -3132,6 +3132,18 @@ def test_nested_values_show_up_in_validation_report():
}
)

@pytest.mark.parametrize(
"fixture,is_valid_network",
[
(NetworkForIntermodalAccessEgressTesting().without_intermodal_access_egress(), True),
(NetworkForIntermodalAccessEgressTesting().with_valid_car_intermodal_access_egress(), True),
(NetworkForIntermodalAccessEgressTesting().with_invalid_intermodal_access_egress(), False),
]
)
def test_intermodal_access_egress_reporting(fixture, is_valid_network):
report = fixture.network.generate_validation_report()
assert report['is_valid_network'] == is_valid_network


def test_check_connectivity_for_mode_warns_of_graphs_with_more_than_single_component(mocker, caplog):
mocker.patch.object(network_validation, 'describe_graph_connectivity',
Expand Down

0 comments on commit 4ab6653

Please sign in to comment.