geojson_from_gtfs_txt.py 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. #!/usr/bin/python3
  2. #
  3. #
  4. # Copyright (c) 2021 Clementine Computing LLC.
  5. #
  6. # This file is part of RideLogic.
  7. #
  8. # RideLogic is free software: you can redistribute it and/or modify
  9. # it under the terms of the GNU Affero General Public License as published by
  10. # the Free Software Foundation, either version 3 of the License, or
  11. # (at your option) any later version.
  12. #
  13. # RideLogic is distributed in the hope that it will be useful,
  14. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. # GNU Affero General Public License for more details.
  17. #
  18. # You should have received a copy of the GNU Affero General Public License
  19. # along with RideLogic. If not, see <https://www.gnu.org/licenses/>.
  20. #
  21. import os
  22. import sys
  23. import csv
  24. import json
  25. if len(sys.argv) < 6:
  26. print("provide routes.txt stops.txt shapes.txt trips.txt stop_times.txt")
  27. sys.exit(-1)
  28. routes_fn = sys.argv[1]
  29. stops_fn = sys.argv[2]
  30. shapes_fn = sys.argv[3]
  31. trips_fn = sys.argv[4]
  32. stop_times_fn = sys.argv[5]
  33. route_info = {}
  34. stop_info = {}
  35. shape_info = {}
  36. trip_info = {}
  37. stop_time_info = {}
  38. with open(routes_fn) as fp:
  39. fpcsv = csv.reader(fp, delimiter=',', quotechar='"')
  40. next(fpcsv)
  41. for row in fpcsv:
  42. route_info[row[0]] = {
  43. "route_id" : row[0],
  44. "agency_id" : row[1],
  45. "route_short_name": row[2],
  46. "route_long_name" : row[3],
  47. "route_desc" : row[4],
  48. "route_type": row[5],
  49. "route_url" : row[6],
  50. "route_color" : row[7],
  51. "route_text_color" : row[8],
  52. "route_sort_order" : row[9]
  53. }
  54. with open(stops_fn) as fp:
  55. fpcsv = csv.reader(fp, delimiter=',', quotechar='"')
  56. next(fpcsv)
  57. for row in fpcsv:
  58. stop_info[row[0]] = {
  59. "stop_id" : row[0],
  60. "stop_code" : row[1],
  61. "stop_name": row[2],
  62. "stop_desc" : row[3],
  63. "stop_lat" : row[4],
  64. "stop_lon": row[5],
  65. "zone_id" : row[6],
  66. "stop_url" : row[7],
  67. "location_type" : row[8],
  68. "parent_station" : row[9],
  69. "wheelchair_boarding" : row[10]
  70. }
  71. with open(shapes_fn) as fp:
  72. fpcsv = csv.reader(fp, delimiter=',', quotechar='"')
  73. next(fpcsv)
  74. for row in fpcsv:
  75. if not (row[0] in shape_info):
  76. shape_info[row[0]] = []
  77. shape_info[row[0]].append({
  78. "shape_id" : row[0],
  79. "shape_pt_lat" : row[1],
  80. "shape_pt_lon": row[2],
  81. "shape_pt_sequence" : row[3],
  82. "shape_dist_traveled" : row[4]
  83. })
  84. with open(trips_fn) as fp:
  85. fpcsv = csv.reader(fp, delimiter=',', quotechar='"')
  86. next(fpcsv)
  87. for row in fpcsv:
  88. trip_info[row[2]] = {
  89. "route_id" : row[0],
  90. "service_id": row[1],
  91. "trip_id" : row[2],
  92. "trip_headsign" : row[3],
  93. "direction_id" : row[4],
  94. "block_id": row[5],
  95. "shape_id" : row[6],
  96. "wheelchair_accessible" : row[7],
  97. "bikes_allowed" : row[8]
  98. }
  99. trip_stops_map = {}
  100. with open(stop_times_fn) as fp:
  101. fpcsv = csv.reader(fp, delimiter=',', quotechar='"')
  102. next(fpcsv)
  103. for row in fpcsv:
  104. trip_id = row[0]
  105. stop_id = row[3]
  106. if not (trip_id in stop_time_info):
  107. stop_time_info[trip_id] = []
  108. stop_time_info[trip_id].append({
  109. "trip_id" : row[0],
  110. "arrival_time" : row[1],
  111. "departure_time": row[2],
  112. "stop_id" : row[3],
  113. "stop_sequence" : row[4],
  114. "stop_headsign" : row[5],
  115. "pickup_type" : row[6],
  116. "srop_off_type" : row[7],
  117. "shape_dist_traveled" : row[8],
  118. "timepoint" : row[9]
  119. })
  120. if not (trip_id in trip_stops_map):
  121. trip_stops_map[trip_id] = {}
  122. if not (stop_id in trip_stops_map[trip_id]):
  123. trip_stops_map[trip_id][stop_id] = True
  124. geojson_info = {
  125. "type" : "FeatureCollection",
  126. "features" : []
  127. }
  128. for trip_id in trip_info:
  129. geojson_trip = {
  130. "type" : "trip",
  131. "geometry": {
  132. "type": "Polygon",
  133. "coordinates": []
  134. },
  135. "properties" : {}
  136. }
  137. trip = trip_info[trip_id]
  138. shape_id = trip["shape_id"]
  139. for shape_ele in shape_info[shape_id]:
  140. #geojson_trip["geometry"]["coordinates"].append( [ shape_ele["shape_pt_lat"], shape_ele["shape_pt_lon"] ] )
  141. geojson_trip["geometry"]["coordinates"].append( [ shape_ele["shape_pt_lon"], shape_ele["shape_pt_lat"] ] )
  142. #geojson_trip["properties"]["route_id"] = trip["route_id"]
  143. geojson_trip["properties"]["trip_id"] = trip["trip_id"]
  144. geojson_trip["properties"]["service_id"] = trip["service_id"]
  145. geojson_trip["properties"]["block_id"] = trip["block_id"]
  146. geojson_trip["properties"]["trip_headsign"] = trip["trip_headsign"]
  147. geojson_trip["properties"]["bikes_allowed"] = trip["bikes_allowed"]
  148. geojson_trip["properties"]["wheelchair_accessible"] = trip["wheelchair_accessible"]
  149. route_ele = route_info[ trip["route_id"] ]
  150. route_stops = []
  151. for stop_id in trip_stops_map[trip_id]:
  152. stop_ele = stop_info[stop_id]
  153. gj_stop_ele = {
  154. "stop" : {
  155. "geometry": {
  156. "coordinates" : [stop_ele["stop_lon"], stop_ele["stop_lat"] ]
  157. }
  158. }
  159. }
  160. route_stops.append( gj_stop_ele )
  161. geojson_trip["properties"]["route"] = {
  162. "route_id" : route_ele["route_id"],
  163. "agency_id" : route_ele["agency_id"],
  164. "route_short_name" : route_ele["route_short_name"],
  165. "route_long_name" : route_ele["route_long_name"],
  166. "route_desc" : route_ele["route_desc"],
  167. "route_type" : route_ele["route_type"],
  168. "route_url" : route_ele["route_url"],
  169. "route_color" : route_ele["route_color"],
  170. "route_text_color" : route_ele["route_text_color"],
  171. "route_sort_order" : route_ele["route_sort_order"],
  172. }
  173. geojson_trip["properties"]["route_stops"] = route_stops
  174. geojson_info["features"].append(geojson_trip)
  175. #print( json.dumps(geojson_trip, indent=2) )
  176. #print( json.dumps(trip_info[trip_id], indent=2) )
  177. #print(json.dumps(route_info, indent=2))
  178. #print(json.dumps(stop_info, indent=2))
  179. #print(json.dumps(shape_info, indent=2))
  180. #print(json.dumps(trip_info, indent=2))
  181. print(json.dumps(geojson_info, indent=2))