|
| 1 | +import os |
| 2 | +import pyodbc |
| 3 | +import sqlalchemy |
| 4 | +import time |
| 5 | +from pandas import read_sql |
| 6 | +from shapely import wkt |
| 7 | +from shapely.geometry import Point |
| 8 | +import geopandas as gpd |
| 9 | +from geopandas import GeoDataFrame |
| 10 | +import pandas as pd |
| 11 | +import os |
| 12 | +import numpy as np |
| 13 | +import yaml |
| 14 | +import time |
| 15 | +import sys |
| 16 | +import transit_service_analyst as tsa |
| 17 | + |
| 18 | +def read_from_sde(connection_string, feature_class_name, version, |
| 19 | + crs={'init': 'epsg:2285'}, is_table=False): |
| 20 | + """ |
| 21 | + Returns the specified feature class as a geodataframe from ElmerGeo. |
| 22 | +
|
| 23 | + Parameters |
| 24 | + ---------- |
| 25 | + connection_string : SQL connection string that is read by geopandas |
| 26 | + read_sql function |
| 27 | +
|
| 28 | + feature_class_name: the name of the featureclass in PSRC's ElmerGeo |
| 29 | + Geodatabase |
| 30 | +
|
| 31 | + cs: cordinate system |
| 32 | + """ |
| 33 | + |
| 34 | + engine = sqlalchemy.create_engine(connection_string) |
| 35 | + con = engine.connect() |
| 36 | + con.execute("sde.set_current_version {0}".format(version)) |
| 37 | + |
| 38 | + if is_table: |
| 39 | + gdf = pd.read_sql('select * from %s' % |
| 40 | + (feature_class_name), con=con) |
| 41 | + con.close() |
| 42 | + |
| 43 | + else: |
| 44 | + df = pd.read_sql('select *, Shape.STAsText() as geometry from %s' % |
| 45 | + (feature_class_name), con=con) |
| 46 | + con.close() |
| 47 | + |
| 48 | + df['geometry'] = df['geometry'].apply(wkt.loads) |
| 49 | + gdf = gpd.GeoDataFrame(df, geometry='geometry') |
| 50 | + gdf.crs = crs |
| 51 | + cols = [col for col in gdf.columns if col not in |
| 52 | + ['Shape', 'GDB_GEOMATTR_DATA', 'SDE_STATE_ID']] |
| 53 | + gdf = gdf[cols] |
| 54 | + |
| 55 | + return gdf |
| 56 | + |
| 57 | +def get_points_by_transit_type(tsa_instance, route_type): |
| 58 | + transit_lines = tsa_instance.get_lines_gdf() |
| 59 | + transit_lines = transit_lines[transit_lines['route_type']== route_type] |
| 60 | + route_stops = tsa_instance.get_line_stops_gdf() |
| 61 | + route_stops = route_stops[route_stops['rep_trip_id'].isin(transit_lines['rep_trip_id'])] |
| 62 | + stops = tsa_instance.stops |
| 63 | + stops = stops[stops['stop_id'].isin(route_stops['stop_id'])] |
| 64 | + return stops |
| 65 | + |
| 66 | +def get_transit_stops_by_route_frequency(gsu_instance, route_type, min_tph, list_of_hrs, min_hrs): |
| 67 | + freq = gsu_instance.get_tph_by_line() |
| 68 | + # create binary column for each our |
| 69 | + cols = [] |
| 70 | + for hour in list_of_hours: |
| 71 | + print (len(freq)) |
| 72 | + new_col = hour + '_recode' |
| 73 | + cols.append(new_col) |
| 74 | + freq[new_col] = np.where(freq[hour]>=min_tph, 1 ,0) |
| 75 | + freq['total_hours'] = freq[cols].sum(axis=1) |
| 76 | + freq = freq[freq['total_hours']>=min_hrs] |
| 77 | + route_stops = gsu_instance.get_line_stops_gdf() |
| 78 | + route_stops = route_stops[route_stops['rep_trip_id'].isin(freq['rep_trip_id'])] |
| 79 | + stops = gsu_instance.stops |
| 80 | + stops = stops[stops['stop_id'].isin(route_stops['stop_id'])] |
| 81 | + return stops |
| 82 | + |
| 83 | +def get_transit_stops_by_stop_frequency(gsu_instance, route_type, min_tph, list_of_hrs): |
| 84 | + freq = gsu_instance.get_tph_at_stops() |
| 85 | + for hour in list_of_hours: |
| 86 | + print (len(freq)) |
| 87 | + freq = freq[freq[hour]>=min_tph] |
| 88 | + stops = gsu_instance.stops |
| 89 | + stops = stops[stops['stop_id'].isin(freq['stop_id'])] |
| 90 | + |
| 91 | + transit_lines = gsu_instance.get_routes_gdf() |
| 92 | + transit_lines = transit_lines[transit_lines['route_type']== route_type] |
| 93 | + route_stops = gsu_instance.get_route_stops_gdf() |
| 94 | + route_stops = route_stops[route_stops['rep_trip_id'].isin(transit_lines['rep_trip_id'])] |
| 95 | + stops = stops[stops['stop_id'].isin(route_stops['stop_id'])] |
| 96 | + return stops |
| 97 | + # now only keep the stops that belong to routes with |
| 98 | + # the route_type parameter |
| 99 | + |
| 100 | + |
| 101 | + |
| 102 | +model_year = 2050 |
| 103 | +high_regular_junction = 199262 |
| 104 | +model_dir = '//modelstation1/c$/workspace/sc_rtp_2050_constrained_final/soundcast' |
| 105 | +#model_dir = '//modelstation2/c$/Workspace/sc_2018_rtp_final/soundcast' |
| 106 | + |
| 107 | +list_of_hours = ['hour_6', 'hour_7', 'hour_8', 'hour_15', 'hour_16', 'hour_17'] |
| 108 | + |
| 109 | +route_type_dict = {0: 'streetcar', 1: 'light_rail', 2: 'commuter_rail', 4:'ferry', 5: 'BRT'} |
| 110 | + |
| 111 | +buffer_dict = {'streetcar' : 2640, 'light_rail' : 2640, 'commuter_rail' : 2640, 'ferry' : 2640, 'BRT' : 1320} |
| 112 | + |
| 113 | +server= 'AWS-Prod-SQL\Sockeye' |
| 114 | + |
| 115 | +elmer_geo_database= 'ElmerGeo' |
| 116 | +osm_geo_database = 'OSMTest' |
| 117 | + |
| 118 | +version= "'sde.DEFAULT'" |
| 119 | + |
| 120 | +elmer_geo_conn_string = '''mssql+pyodbc://%s/%s?driver=SQL Server? |
| 121 | + Trusted_Connection=yes''' % (server, elmer_geo_database) |
| 122 | + |
| 123 | +osm_geo_conn_string = '''mssql+pyodbc://%s/%s?driver=SQL Server? |
| 124 | + Trusted_Connection=yes''' % (server, osm_geo_database) |
| 125 | + |
| 126 | +crs = {'init' : 'EPSG:2285'} |
| 127 | + |
| 128 | + |
| 129 | +# 2050: |
| 130 | +path = r'Y:\2022 RTP\Future Transit Network\newest\2050\model_import\revised_routes_new_stop_ids\merged\test' |
| 131 | +#path = r'R:\e2projects_two\Angela\transit_routes_2018\latest_combined' |
| 132 | + |
| 133 | +gtfs_util = tsa.load_gtfs(path, '20210707', 0, 1680) |
| 134 | +#gtfs_util = gsu.load_gtfs(path, '20180417', 0, 1680) |
| 135 | + |
| 136 | + |
| 137 | +gdf_parcels = read_from_sde(elmer_geo_conn_string, |
| 138 | + 'parcels_urbansim_2018_pts', |
| 139 | + version, crs=crs, is_table=False) |
| 140 | + |
| 141 | +gdf_transit_lines = read_from_sde(osm_geo_conn_string, |
| 142 | + 'TransitLines_evw', |
| 143 | + version, crs=crs, is_table=False) |
| 144 | + |
| 145 | +gdf_transit_lines = gdf_transit_lines[gdf_transit_lines['InServiceDate']==model_year] |
| 146 | + |
| 147 | +transit_segments = pd.read_csv(os.path.join(model_dir, 'outputs/transit/transit_segment_results.csv')) |
| 148 | +transit_segments = transit_segments[(transit_segments['i_node'] > high_regular_junction) | (transit_segments['j_node'] > high_regular_junction)] |
| 149 | +hov_routes = gdf_transit_lines[gdf_transit_lines['LineID'].isin(transit_segments['line_id'])]['RouteID'] |
| 150 | +hov_gtfs_routes = gtfs_util.get_lines_gdf() |
| 151 | +#hov_gtfs_routes = hov_gtfs_routes[hov_gtfs_routes['route_id'].isin(hov_routes)] |
| 152 | +#hov_gtfs_routes = hov_gtfs_routes[~hov_gtfs_routes.geometry==None] |
| 153 | +hov_route_stops = gtfs_util.get_line_stops_gdf() |
| 154 | +hov_route_stops = hov_route_stops[hov_route_stops['route_id'].isin(hov_routes)] |
| 155 | +stops = gtfs_util.stops |
| 156 | +hov_stops = stops[stops['stop_id'].isin(hov_route_stops['stop_id'])] |
| 157 | +hov_stops.to_crs(crs, inplace = True) |
| 158 | +hov_stops.geometry = hov_stops.geometry.buffer(2640) |
| 159 | +join_left_df = gpd.sjoin(hov_stops, gdf_parcels, how="left") |
| 160 | +gdf_parcels['hov_bus'] = np.where(gdf_parcels['parcel_id'].isin(join_left_df['parcel_id']), 1, 0) |
| 161 | + |
| 162 | + |
| 163 | + |
| 164 | + |
| 165 | +for route_type_id, route_type_name in route_type_dict.items(): |
| 166 | + if 5 not in gtfs_util.routes.route_type.values: |
| 167 | + brt_routes = gdf_transit_lines[gdf_transit_lines['TransitType']==3]['RouteID'] |
| 168 | + gtfs_util.routes['route_type'] = np.where(gtfs_util.routes['route_id'].isin(brt_routes), 5, gtfs_util.routes['route_type']) |
| 169 | + stops = get_points_by_transit_type(gtfs_util, route_type_id) |
| 170 | + stops.to_crs(crs, inplace = True) |
| 171 | + stops.geometry = stops.geometry.buffer(buffer_dict[route_type_name]) |
| 172 | + #stops.to_file('T:/2021December/Stefan/parcel_transit_proximity/shapefiles/' + route_type_name + str(buffer_dict[route_type_name]) + '.shp') |
| 173 | + join_left_df = gpd.sjoin(stops, gdf_parcels, how="left") |
| 174 | + gdf_parcels[route_type_name] = np.where(gdf_parcels['parcel_id'].isin(join_left_df['parcel_id']), 1, 0) |
| 175 | + |
| 176 | +# now do frequent bus |
| 177 | +stops = get_transit_stops_by_route_frequency(gtfs_util, 3, 4, list_of_hours, 5) |
| 178 | +stops.to_crs(crs, inplace = True) |
| 179 | +stops.geometry = stops.geometry.buffer(2640) |
| 180 | +join_left_df = gpd.sjoin(stops, gdf_parcels, how="left") |
| 181 | +gdf_parcels['frequent_bus'] = np.where(gdf_parcels['parcel_id'].isin(join_left_df['parcel_id']), 1, 0) |
| 182 | + |
| 183 | +cols = ['parcel_id', 'hov_bus', 'frequent_bus'] |
| 184 | +cols.extend(list(route_type_dict.values())) |
| 185 | +gdf_parcels = gdf_parcels[cols] |
| 186 | + |
| 187 | + |
| 188 | +gdf_parcels.to_csv(r'T:\2022January\Stefan\parcel_transit_proximity\parcels_transit_centroids_brt_qmile_2018.csv', index = False) |
| 189 | + |
| 190 | +#gdf_parcels.to_csv(r'T:\2021December\Stefan\parcel_transit_proximity\parcels_transit_polys.csv', index = False) |
| 191 | + |
| 192 | + |
| 193 | + |
| 194 | + |
| 195 | + |
0 commit comments