Source code for vtra.failure.failure_estimation_provinces

"""Failure analysis of province-scale road networks
To estimate changing accessibility to commune points

Input data requirements
-----------------------

1. Correct paths to all files and correct input parameters
2. Excel sheets with results of flow mapping based on MIN-MAX generalised costs estimates

    - origin - String node ID of Origin
    - destination - String node ID of Destination
    - min_edge_path - List of string of edge ID's for paths with minimum generalised cost flows
    - max_edge_path - List of string of edge ID's for paths with maximum generalised cost flows
    - min_distance - Float values of estimated distance for paths with minimum generalised cost flows
    - max_distance - Float values of estimated distance for paths with maximum generalised cost flows
    - min_time - Float values of estimated time for paths with minimum generalised cost flows
    - max_time - Float values of estimated time for paths with maximum generalised cost flows
    - min_gcost - Float values of estimated generalised cost for paths with minimum generalised cost flows
    - max_gcost - Float values of estimated generalised cost for paths with maximum generalised cost flows
    - min_vehicle_nums - Float values of estimated vehicle numbers for paths with minimum generalised cost flows
    - max_vehicle_nums - Float values of estimated vehicle numbers for paths with maximum generalised cost flows
    - industry_columns - All daily tonnages of industry columns given in the OD matrix data

3. Shapefiles

    - edge_id - String/Integer/Float Edge ID
    - geometry - Shapely LineString geomtry of edges

Results
-------
Csv sheets with results of failure analysis

1. All failure scenarios

    - edge_id - String name or list of failed edges
    - origin - String node ID of Origin of disrupted OD flow
    - destination - String node ID of Destination of disrupted OD flow
    - o_region - String name of Province of Origin node ID of disrupted OD flow
    - d_region - String name of Province of Destination node ID of disrupted OD flow
    - no_access - Boolean 1 (no reroutng) or 0 (rerouting)
    - min/max_distance - Float value of estimated distance of OD journey before disruption
    - min/max_time - Float value of estimated time of OD journey before disruption
    - min/max_gcost - Float value of estimated travel cost of OD journey before disruption
    - min/max_vehicle_nums - Float value of estimated vehicles of OD journey before disruption
    - new_cost - Float value of estimated cost of OD journey after disruption
    - new_distance - Float value of estimated distance of OD journey after disruption
    - new_path - List of string edge ID's of estimated new route of OD journey after disruption
    - new_time - Float value of estimated time of OD journey after disruption
    - dist_diff - Float value of Post disruption minus per-disruption distance
    - time_diff - Float value Post disruption minus per-disruption timee
    - min/max_tr_loss - Float value of estimated change in rerouting cost
    - min/max_netrev - Float values of total daily net revenues along disrupted OD pairs
    - min/max_tons - Float values of total daily crop tonnages along disrupted OD pairs
    - min_max_econ_impact - Float values of total daily economic impact of disrupted OD pairs

2. Min-max combined scenarios - Combined min-max results of total network impacts of each edge

    - edge_id - String name or list of failed edges
    - no_access - Boolean 1 (no reroutng) or 0 (rerouting)
    - min/max_tr_loss - Float values of estimated change in rerouting cost
    - min/max_tons - Float values of total daily tonnages along edge
    - min/max_netrev - Float values of total daily net revenues along edge
    - min/max_econ_impact - Float value of total daily economic impact of edge

3. Shapefiles - Combined min-max reults of total network impacts of each edge

    - edge_id - String name or list of failed edges
    - no_access - Boolean 1 (no reroutng) or 0 (rerouting)
    - min/max_tr_loss - Float values of estimated change in rerouting cost
    - min/max_tons - Float values of total daily tonnages along edge
    - min/max_netrev - Float values of total daily net revenues along edge
    - min/max_econ_impact - Float value of total daily economic impact of edge
    - geometry - Shapely LineString geomtry of edges

"""
import ast
import copy
import csv
import itertools
import math
import operator
import os
import sys

import igraph as ig
import networkx as nx
import numpy as np
import pandas as pd
from vtra.utils import *
from vtra.transport_flow_and_failure_functions import *


[docs]def main(): """Estimate provincial road failures Specify the paths from where you want to read and write: 1. Input data 2. Intermediate calcuations data 3. Output results Supply input data and parameters 1. Names of Provinces List of strings 2. Unit weight of vehicle assumed for each mode List of float types 3. Min-max names of names of different types of attributes - paths, distance, time, cost, vehicles, tons, revenue List of string types 4. Percentage of OD flows that are assumed disrupted List of float type 5. Condition on whether analysis is single failure or multiple failure Boolean condition True or False Give the paths to the input data files: 1. Network edges Excel and shapefiles 2. OD flows Excel file 3. Failure scenarios Excel file Specify the output files and paths to be created """ data_path, calc_path, output_path = load_config()['paths']['data'], load_config()[ 'paths']['calc'], load_config()['paths']['output'] # Supply input data and parameters province_list = ['Lao Cai', 'Binh Dinh', 'Thanh Hoa'] truck_unit_wt = [5.0] types = ['min', 'max'] path_types = ['min_edge_path', 'max_edge_path'] dist_types = ['min_distance', 'max_distance'] time_types = ['min_time', 'max_time'] cost_types = ['min_gcost', 'max_gcost'] vehicle_types = ['min_vehicle_nums', 'max_vehicle_nums'] tons_types = ['min_croptons', 'max_croptons'] rev_types = ['min_netrev', 'max_netrev'] percentage = [100.0] single_edge = True # Give the paths to the input data files network_data_path = os.path.join(data_path,'post_processed_networks') network_data_excel = os.path.join(data_path,'post_processed_networks','province_roads_edges.xlsx') flow_paths_data = os.path.join(output_path, 'flow_mapping_paths') fail_scenarios_data = os.path.join( output_path, 'hazard_scenarios', 'province_roads_hazard_intersections.xlsx') # Specify the output files and paths to be created shp_output_path = os.path.join(output_path, 'failure_shapefiles') if os.path.exists(shp_output_path) == False: os.mkdir(shp_output_path) fail_output_path = os.path.join(output_path, 'failure_results') if os.path.exists(fail_output_path) == False: os.mkdir(fail_output_path) all_fail_scenarios = os.path.join(fail_output_path,'all_fail_scenarios') if os.path.exists(all_fail_scenarios) == False: os.mkdir(all_fail_scenarios) isolated_ods = os.path.join(fail_output_path,'isolated_od_scenarios') if os.path.exists(isolated_ods) == False: os.mkdir(isolated_ods) rerouting = os.path.join(fail_output_path,'rerouting_scenarios') if os.path.exists(rerouting) == False: os.mkdir(rerouting) minmax_combine = os.path.join(fail_output_path,'minmax_combined_scenarios') if os.path.exists(minmax_combine) == False: os.mkdir(minmax_combine) # Path OD flow disruptions for prn in range(len(province_list)): province = province_list[prn] province_name = province.replace(' ', '').lower() # Load igraph network and GeoDataFrame print ('* Loading {} igraph network and GeoDataFrame'.format(province)) G_df = pd.read_excel(network_data_excel,sheet_name = province_name,encoding='utf-8') gdf_edges = gpd.read_file(os.path.join(network_data_path,'{}_roads_edges.shp'.format(province_name)),encoding='utf-8') gdf_edges = gdf_edges[['edge_id','geometry']] # Create failure scenarios print ('* Creating {} failure scenarios'.format(province)) fail_df = pd.read_excel(fail_scenarios_data, sheet_name=province_name) ef_sc_list = edge_failure_sampling(fail_df,'edge_id') for perct in percentage: for tr_wt in truck_unit_wt: # Load flow paths print ('* Loading {} flow paths'.format(province)) flow_excel_file = 'province_roads_commune_center_access_flow_paths_{}_percent.xlsx'.format(int(perct)) flow_df = pd.read_excel( os.path.join(flow_paths_data,flow_excel_file), sheet_name = province_name + '_{}_tons'.format(int(tr_wt))) # Perform failure analysis edge_fail_ranges = [] for t in range(len(types)): print ('* Performing {} {} failure analysis'.format(types[t],province)) ef_list = [] for fail_edge in ef_sc_list: if isinstance(fail_edge,list) == False: fail_edge = [fail_edge] ef_dict = igraph_scenario_edge_failures( G_df, fail_edge, flow_df, tr_wt,path_types[t], tons_types[t], cost_types[t], time_types[t]) if ef_dict: ef_list += ef_dict print('Done with province {0} edge {1} type {2}'.format( province, fail_edge, types[t])) df = pd.DataFrame(ef_list) print ('* Assembling {} {} failure results'.format(types[t],province)) ic_cols = [rev_types[t],tons_types[t]] select_cols = ['origin', 'destination', dist_types[t], time_types[t], cost_types[t], vehicle_types[t]] + ic_cols flow_df_select = flow_df[select_cols] flow_df_select = merge_failure_results(flow_df_select,df,tons_types[t], dist_types[t],time_types[t],cost_types[t],vehicle_types[t],changing_tonnages=False) del df tr_loss = '{}_tr_loss'.format(types[t]) econ_impact = '{}_econ_impact'.format(types[t]) flow_df_select.rename(columns={'tr_loss': tr_loss}, inplace=True) flow_df_select[econ_impact] = flow_df_select['no_access']*flow_df_select[rev_types[t]] + \ flow_df_select[tr_loss] if single_edge == True: file_name = 'single_edge_failures_all_{0}_{1}_tons_{2}_percent_disrupt.csv'.format(province_name, int(tr_wt),int(perct)) else: file_name = 'multiple_edge_failures_all_{0}_{1}_tons_{2}_percent_disrupt.csv'.format(province_name, int(tr_wt),int(perct)) df_path = os.path.join(all_fail_scenarios,file_name) flow_df_select.to_csv(df_path, index=False) print ('* Combining {} {} rerouting and isolation failure results'.format(types[t],province)) edge_impact = flow_df_select[['edge_id','no_access',tr_loss,tons_types[t],rev_types[t],econ_impact]] edge_impact = edge_impact.groupby( ['edge_id','no_access'])[tr_loss,tons_types[t],rev_types[t],econ_impact].sum().reset_index() edge_fail_ranges.append(edge_impact) print ('* Assembling {} min-max failure results'.format(province)) edge_impact = edge_fail_ranges[0] edge_impact = pd.merge(edge_impact, edge_fail_ranges[1], how='left', on=[ 'edge_id','no_access']).fillna(0) del edge_fail_ranges if single_edge == True: file_name = 'single_edge_failures_minmax_{0}_{1}_tons_{2}_percent_disrupt'.format(province_name, int(tr_wt),int(perct)) else: file_name = 'multiple_edge_failures_minmax_{0}_{1}_tons_{2}_percent_disrupt'.format(province_name, int(tr_wt),int(perct)) df_path = os.path.join(minmax_combine,file_name + '.csv') edge_impact.to_csv(df_path, index=False) # Create network shapefiles with flows print ('* Creating {} network shapefiles with flows'.format(province)) shp_path = os.path.join( shp_output_path,file_name + '.shp') network_failure_assembly_shapefiles(edge_impact,gdf_edges, save_edges=True, shape_output_path=shp_path)
if __name__ == "__main__": main()