commit ae7799d775dfc1bda5aca4916b8470dd93ed979c Author: Sven Geboers Date: Sat Aug 6 18:43:59 2022 +0200 included code and requirements, next step is to make a button that can toggle between busses and trams diff --git a/main.py b/main.py new file mode 100644 index 0000000..4d9b7e6 --- /dev/null +++ b/main.py @@ -0,0 +1,68 @@ +from google.transit import gtfs_realtime_pb2 +import requests +import pandas as pd +import numpy as np + +from bokeh.layouts import column +from bokeh.palettes import brewer +from bokeh.plotting import figure, curdoc +from bokeh.models import GeoJSONDataSource, Button, HoverTool, LinearColorMapper, LabelSet, ColumnDataSource +from bokeh.tile_providers import get_provider #, Vendors +from bokeh.transform import factor_cmap +import time + +def lonlattowebmercator(df, lon="LON", lat="LAT"): + k = 6378137 + df["x"] = df[lon] * (k * np.pi/180.0) + df["y"] = np.log(np.tan((90+df[lat]) * np.pi/360.0)) * k + return df + +def getPositions(): + ## Get the live locations of the vehicles + feed = gtfs_realtime_pb2.FeedMessage() + response = requests.get('http://gtfs.ovapi.nl/nl/vehiclePositions.pb') + feed.ParseFromString(response.content) + vehicle_positions = [] + + for entity in feed.entity: + entry = [entity.vehicle.vehicle.label, int(entity.vehicle.trip.route_id), float(entity.vehicle.position.latitude), float(entity.vehicle.position.longitude)] + vehicle_positions.append(entry) + df_vehiclePositions = pd.DataFrame(vehicle_positions, columns=["vehicle_label", "route_id", "latitude", "longitude"]) + df_vehiclePositions = df_vehiclePositions[df_vehiclePositions["longitude"]!=0] + df_vehiclePositions = lonlattowebmercator(df_vehiclePositions, lon="longitude", lat="latitude") + return(df_vehiclePositions) + +def update(): + df_vehiclePositions = getPositions() + df_routes = pd.read_csv("gtfs-data/routes.txt") + + ## Merge tables + df = df_vehiclePositions.merge(df_routes, on="route_id", how="right") + df = df[(df["route_type"]==1) | (df["route_type"]==2) | (df["route_type"]==3)] + print(df["longitude"]) + Source.stream(df, rollover=len(df["longitude"])) + labels = LabelSet(x='x',y='y',x_offset=5,y_offset=5,source=Source,render_mode='canvas') + + +## Get initial values +df_vehiclePositions = getPositions() +df_routes = pd.read_csv("gtfs-data/routes.txt") + +## Merge tables +df = df_vehiclePositions.merge(df_routes, on="route_id", how="right") +Source = ColumnDataSource(df) + +## Plot +## Initialize our plot figure +x_range,y_range=([400000,700000], [6500000, 7500000]) +OSM = get_provider('OSM') +p = figure(title="A gtfs feed",x_range=x_range, y_range=y_range, x_axis_type='mercator',y_axis_type='mercator',sizing_mode='stretch_both',plot_width=1500,plot_height=1000) +p.add_tile(OSM) +my_hover=HoverTool() +my_hover.tooltips=[('route_id','@route_id'),('Type','@route_type'),('Route','@route_long_name')] +p.add_tools(my_hover) + +p.circle('x', 'y', source=Source) +curdoc().add_root(p) +curdoc().add_periodic_callback(update,1000) +p.legend.location = "top_left" diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..6a8b11d --- /dev/null +++ b/requirements.txt @@ -0,0 +1,29 @@ +attrs==22.1.0 +bokeh==2.4.3 +certifi==2022.6.15 +charset-normalizer==2.1.0 +click==8.1.3 +click-plugins==1.1.1 +cligj==0.7.2 +Fiona==1.8.21 +gtfs-realtime-bindings==0.0.7 +idna==3.3 +Jinja2==3.1.2 +MarkupSafe==2.1.1 +munch==2.5.0 +numpy==1.23.1 +packaging==21.3 +pandas==1.4.3 +Pillow==9.2.0 +protobuf==3.20.1 +pyparsing==3.0.9 +pyproj==3.3.1 +python-dateutil==2.8.2 +pytz==2022.1 +PyYAML==6.0 +requests==2.28.1 +Shapely==1.8.2 +six==1.16.0 +tornado==6.2 +typing_extensions==4.3.0 +urllib3==1.26.11