PageRenderTime 52ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

/calculate_path.py

https://gitlab.com/mdornfe1/busy_cab
Python | 174 lines | 117 code | 40 blank | 17 comment | 6 complexity | f24ceb4490fe721868ce977927843954 MD5 | raw file
  1. import sqlalchemy as sa
  2. import psycopg2
  3. import pandas.io.sql as sqlio
  4. import pandas as pd
  5. import matplotlib.pyplot as plt
  6. import numpy as np
  7. import folium
  8. import json
  9. import requests
  10. from IPython import embed
  11. import datetime
  12. from folium import plugins
  13. from passwords import postgres_password
  14. plt.style.use('bmh')
  15. MAP_CONN = psycopg2.connect(host='localhost', dbname='nyc_routing', user='postgres', password=postgres_password)
  16. day_names = ['sun', 'mon', 'tues', 'wed', 'thurs', 'fri', 'sat']
  17. DEGREES_PER_KM = 1 / 111.
  18. def get_gps_from_address(address):
  19. response = requests.get('https://maps.googleapis.com/maps/api/geocode/json?address=' + str(address))
  20. resp_json_payload = response.json()
  21. lat = resp_json_payload['results'][0]['geometry']['location']['lat']
  22. lon = resp_json_payload['results'][0]['geometry']['location']['lng']
  23. return lon, lat
  24. def calc_busiest_path_in_radius(source_id, target_id, source_lon, source_lat, r, day, hour, weight):
  25. """Input source node id, target node id, source gps, day of week, hour
  26. of day returns busiest path within r kms between source and target.
  27. """
  28. r_degrees = r * DEGREES_PER_KM
  29. sql = ("DROP TABLE IF EXISTS d_path; DROP TABLE IF EXISTS d_path2;" +
  30. "CREATE TABLE d_path AS SELECT seq, id1 AS node, id2 AS edge, cost FROM pgr_dijkstra('SELECT ways.gid as id, source::int4, target::int4, ways.cost / %(weight)s / (taxi_pickup_counts.green_%(day)s_%(hour)s + taxi_pickup_counts.yellow_%(day)s_%(hour)s)::float8 AS cost, ways.reverse_cost / %(weight)s / (taxi_pickup_counts.green_%(day)s_%(hour)s + taxi_pickup_counts.yellow_%(day)s_%(hour)s) AS reverse_cost FROM ways INNER JOIN taxi_pickup_counts ON ways.gid = taxi_pickup_counts.gid WHERE ((ways.x1 - %(source_lon)s)^2 + (ways.y1 - %(source_lat)s)^2 ) < %(r_degrees)s^2', %(source_id)s, %(target_id)s, True, True);" +
  31. "CREATE TABLE d_path2 AS SELECT node, lon, lat, edge FROM ways_vertices_pgr, d_path where ways_vertices_pgr.id = d_path.node;" +
  32. "SELECT node, lon, lat, edge, ST_AsGeoJSON(the_geom) as geojson FROM d_path2, ways_costs WHERE ways_costs.gid=d_path2.edge;")
  33. df = sqlio.read_sql(sql % {'source_id':source_id, 'target_id': target_id,
  34. 'source_lon': source_lon, 'source_lat': source_lat, 'r_degrees':r_degrees,
  35. 'day':day_names[day], 'hour':hour, 'weight': weight}, MAP_CONN)
  36. df.geojson = [json.loads(gj.replace("'", "\"")) for gj in df.geojson]
  37. df.geojson = [gj for gj in df.geojson]
  38. return df
  39. def calc_astar_path(source_id, target_id, source_lon, source_lat, r, day, hour, weight):
  40. sql = "SELECT seq, id1 AS node, id2 AS edge, cost FROM pgr_AStar('SELECT ways.gid::INTEGER as id, source::INTEGER, target::INTEGER, ways.cost / %(weight)s / (taxi_pickup_counts.green_%(day)s_%(hour)s + taxi_pickup_counts.yellow_%(day)s_%(hour)s)::float8 AS cost, x1, y1, x2, y2, ways.reverse_cost / %(weight)s / (taxi_pickup_counts.green_%(day)s_%(hour)s + taxi_pickup_counts.yellow_%(day)s_%(hour)s) AS reverse_cost FROM ways INNER JOIN taxi_pickup_counts ON ways.gid = taxi_pickup_counts.gid WHERE ((ways.x1 - %(source_lon)s)^2 + (ways.y1 - %(source_lat)s)^2 ) < %(r_degrees)s^2', %(source_id)s, %(target_id)s, True, True);"
  41. r_degrees = r * DEGREES_PER_KM
  42. df = sqlio.read_sql(sql % {'source_id':source_id, 'target_id': target_id,
  43. 'source_lon': source_lon, 'source_lat': source_lat, 'r_degrees':r_degrees,
  44. 'day':day_names[day], 'hour':hour, 'weight': weight}, MAP_CONN)
  45. df['geojson'] = pd.Series([json.loads(gj.replace("'", "\"")) for gj in df['geojson']], index=df.index)
  46. df['geojson'] = pd.Series([gj for gj in df.geojson], index=df.index)
  47. return path
  48. def get_pickups_in_radius(lon, lat, r, hour, day):
  49. r_degrees = r * DEGREES_PER_KM
  50. sql = "SELECT pickup_longitude, pickup_latitude FROM yellow_trip_data WHERE pickup_hour=%(pickup_hour)s AND day_of_week=%(day_of_week)s AND ((pickup_longitude - %(lon)s)^2 + (pickup_latitude - %(lat)s)^2 ) < %(r_degrees)s^2;"
  51. df = sqlio.read_sql(sql % {'pickup_hour':hour, 'day_of_week':1, 'lon':lon, 'lat':lat, 'r_degrees':r_degrees}, MAP_CONN)
  52. df['latlon'] = zip(df['pickup_latitude'], df['pickup_longitude'])
  53. #df['geometry'] = df[['latlon']].applymap(lambda x:geometry.Point(x))
  54. return df
  55. def get_ways_pickups_in_radius(lon, lat, r, hour, day):
  56. """
  57. Takes lon, lat and returns all ways and pickup counts for
  58. given hour of the day and day of the week.
  59. """
  60. r_degrees = r * DEGREES_PER_KM
  61. sql = "SELECT ways.*, taxi_pickup_counts.%(day)s_%(hour)s_counts FROM ways INNER JOIN taxi_pickup_counts ON ways.gid=taxi_pickup_counts.gid WHERE ((ways.x1 - %(lon)s)^2 + (ways.y1 - %(lat)s)^2 ) < %(r_degrees)s^2;"
  62. df = sqlio.read_sql(sql % {'lon': lon, 'lat': lat, 'r_degrees': r_degrees, 'day': day_names[day], 'hour':hour}, MAP_CONN)
  63. return df
  64. def get_busiest_node_id_in_radius(lon, lat, r, hour, day):
  65. r_degrees = r * DEGREES_PER_KM
  66. sql = ("SELECT ways.* FROM " +
  67. "ways INNER JOIN taxi_pickup_counts ON ways.gid=taxi_pickup_counts.gid " +
  68. "WHERE taxi_pickup_counts.yellow_%(day)s_%(hour)s + taxi_pickup_counts.green_%(day)s_%(hour)s = " +
  69. "( SELECT max(taxi_pickup_counts.yellow_%(day)s_%(hour)s+taxi_pickup_counts.green_%(day)s_%(hour)s) FROM ways INNER JOIN taxi_pickup_counts ON ways.gid=taxi_pickup_counts.gid WHERE ((ways.x1 - %(lon)s)^2 + (ways.y1 - %(lat)s)^2 ) < %(r_degrees)s^2 );")
  70. busiest_ways = sqlio.read_sql(sql % {'lon': lon, 'lat': lat, 'r_degrees': r_degrees, 'day': day_names[day], 'hour':hour}, MAP_CONN)
  71. d2 = ((busiest_ways.x1 - lon)**2 + (busiest_ways.y1 - lat)**2)
  72. #print(busiest_ways[d2 == d2.min()].source)
  73. return busiest_ways[d2 == d2.min()]['source'].iloc[0]
  74. def get_nearest_node(lon, lat):
  75. """Input lon, lat returns nearest osm_node"""
  76. sql = "SELECT * FROM ways_vertices_pgr ORDER BY the_geom <-> ST_GeometryFromText('POINT(%(lon)s %(lat)s )',4326) LIMIT 1;"
  77. df = sqlio.read_sql(sql % {'lon':lon, 'lat': lat}, MAP_CONN)
  78. return df['id'][0], df
  79. def get_way(gid):
  80. sql = "SELECT * FROM ways WHERE gid=%(gid)s;"
  81. df = sqlio.read_sql(sql % {'gid':gid}, MAP_CONN)
  82. return df
  83. def get_node(id):
  84. sql = "SELECT * FROM ways_vertices_pgr WHERE id=%(id)s;"
  85. df = sqlio.read_sql(sql % {'id':id}, MAP_CONN)
  86. return df
  87. def get_nearest_way(lon, lat):
  88. """Input lon, lat returns nearest osm_way"""
  89. sql = "SELECT * FROM ways ORDER BY the_geom <-> ST_GeometryFromText('POINT(%(lon)s %(lat)s )',4326) LIMIT 1;"
  90. df = sqlio.read_sql(sql % {'lon':lon, 'lat': lat}, MAP_CONN)
  91. return df['gid'][0], df
  92. def generate_map(source_lon, source_lat, target_lon, target_lat, df_path, df_pickups):
  93. nyc_map = folium.Map(location=[source_lat, source_lon], zoom_start=15)
  94. grad={0: 'yellow', 0.5: 'blue', 1: 'green'}
  95. #pickups_map = plugins.HeatMap(df_pickups.latlon, gradient=grad, min_opacity=0.5, radius=5, blur=10)
  96. #nyc_map.add_children(pickups_map)
  97. [folium.PolyLine(np.array(gj['coordinates'])[:,[1,0]]).add_to(nyc_map) for gj in df_path.geojson]
  98. dt_string = str(datetime.datetime.today()).replace(' ', '_')
  99. route_template = './taxi_path_app/templates/tmp/route_' + dt_string + '.html'
  100. nyc_map.simple_marker([source_lat, source_lon], marker_color='green')
  101. nyc_map.simple_marker([target_lat, target_lon], marker_color='red')
  102. nyc_map.save(route_template)
  103. return route_template
  104. def main(source_lon, source_lat, day, hour, weight, target_lon=None, target_lat=None, r=2.0):
  105. source_id, df_source = get_nearest_node(source_lon, source_lat)
  106. #target_id, df_target = get_nearest_node(target_lon, target_lat)
  107. target_id = get_busiest_node_id_in_radius(source_lon, source_lat, r, hour, day)
  108. target_df = get_node(target_id)
  109. target_lon = target_df['lon'][0]; target_lat = target_df['lat'][0]
  110. df_path = calc_busiest_path_in_radius(source_id, target_id, source_lon, source_lat, r, day, hour, weight)
  111. #df_pickups = get_pickups_in_radius(source_lon, source_lat, r, hour, day)
  112. df_pickups = []
  113. route_template = generate_map(source_lon, source_lat, target_lon, target_lat, df_path, df_pickups)
  114. return route_template
  115. if __name__ == '__main__':
  116. lon_insight = -73.9861860
  117. lat_insight = 40.7419650
  118. lon_home = -73.9576270
  119. lat_home = 40.7607880
  120. lon_world_trade = -74.0131
  121. lat_world_trade = 40.7130
  122. lon_bedford = -73.957504
  123. lat_bedford = 40.717883
  124. hour = 9
  125. day = 1
  126. r = 1.0
  127. source_id = 44670
  128. target_id = 29971
  129. weight = 1
  130. #df_path = calc_shortest_path(source_id, target_id, day=day, hour=hour, weight=weight)
  131. source_lon = -73.9861860
  132. source_lat = 40.7419650
  133. #df_pickups=get_pickups_in_radius(lon, lat, r, hour, day)
  134. main(source_lon, source_lat, day, hour, weight, target_lon=None, target_lat=None, r=2.0)