Skip to content

Commit

Permalink
Switching to Dash for client visualization
Browse files Browse the repository at this point in the history
  • Loading branch information
pgrandinetti committed May 7, 2018
1 parent 608d41a commit eef5c3f
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 68 deletions.
82 changes: 82 additions & 0 deletions python/app.py
@@ -0,0 +1,82 @@
import dash
import dash_html_components as html
import dash_core_components as dcc
from dash.dependencies import Input, Output
import plotly.graph_objs as go

import ws_listener
import threading
import argparse

import datastorage
import params


def create_app():
app = dash.Dash('KatieDJ-app')

app.layout = html.Div([
html.Div([
html.H2('Katie DJ - Data Broadcast')
], className='banner'),
html.Div([
html.Div([
html.H3('Traffic time series')
], className='Title'),
html.Div([
dcc.Graph(id='traffic-data'),
], className='twelve columns wind-speed'),
dcc.Interval(id='traffic-data-update', interval=5000, n_intervals=0)
], className='row wind-speed-row')
])
external_css = [
"https://cdnjs.cloudflare.com/ajax/libs/skeleton/2.0.4/skeleton.min.css",
"https://cdn.rawgit.com/plotly/dash-app-stylesheets/737dc4ab11f7a1a8d6b5645d26f69133d97062ae/dash-wind-streaming.css",
"https://fonts.googleapis.com/css?family=Raleway:400,400i,700,700i",
"https://fonts.googleapis.com/css?family=Product+Sans:400,400i,700,700i",
]
for css in external_css:
app.css.append_css({"external_url": css})
return app


if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('-s', '--storage',
action='store',
required=False,
dest='storage',
default=None,
help='Path to storage file (sqlite)')
args = parser.parse_args()
data_store = datastorage.DataObj(storage=args.storage)
arguments = {'ping_timeout': 5,
'reply_timeout': 10,
'sleep_time': 5}
client = ws_listener.WSClient(
params.URL, **arguments)
client.register(data_store)
wst = threading.Thread(
target=ws_listener.start_ws_client, args=(client,))
wst.daemon = True
wst.start()
app = create_app()

@app.callback(Output('traffic-data', 'figure'), [Input('traffic-data-update', 'n_intervals')])
def get_new_data(interval):
traces = []
for k, val in data_store.lines.items():
traces.append(
go.Scatter(
y=val,
mode='lines',
name='Road {}'.format(k)
)
)
layout = go.Layout(
xaxis=dict(title='Time [steps from start]'),
yaxis=dict(title='Number of vehicles')
)
return go.Figure(data=traces, layout=layout)

app.run_server()
74 changes: 8 additions & 66 deletions python/visualize.py → python/datastorage.py
@@ -1,16 +1,10 @@
import matplotlib.pyplot as plt
import seaborn
import params
import json
import numpy
import ws_listener
import logging
import time
import threading

import sqlite3
import argparse
import logging
import json
from pathlib import Path
#import requests


logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
Expand All @@ -20,14 +14,10 @@
streamHandler.setFormatter(formatter)
logger.addHandler(streamHandler)

class DataObj():

class DataObj:

def __init__(self, storage=None):
# Query the server to get the num of roads
#endpoint = params.URL
#resp = requests.get(
# endpoint + '/api/macro/sample/info')
#numLines = resp->numLines
numLines = params.sample_net['numLines']
self.lines = {k: [] for k in range(numLines)}
self.xdata = []
Expand Down Expand Up @@ -148,9 +138,9 @@ def __store_sample(self, state, timestamp):
except Exception as e:
logger.warning('Cannot save to storage the new data')
logger.warning(str(e))
conn.close()
return False
conn.close()
finally:
conn.close()
return True

def create_connection(self):
Expand Down Expand Up @@ -181,51 +171,3 @@ def notify(self, notifier, message):
except:
self.xdata.append(0)
self.__store_sample(body, timestamp)


if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('-s', '--storage',
action='store',
required=False,
dest='storage',
default=None,
help='Path to storage file (sqlite)')
args = parser.parse_args()
data_store = DataObj(storage=args.storage)
arguments = {'ping_timeout': 5,
'reply_timeout': 10,
'sleep_time': 5}
client = ws_listener.WSClient(
params.URL, **arguments)
client.register(data_store)
wst = threading.Thread(
target=ws_listener.start_ws_client, args=(client,))
wst.daemon = True
wst.start()
plt.ion()
seaborn.set()
axes = plt.gca()
axes.set_xlabel('Time [steps from start]')
axes.set_ylabel('Veh.')
lines2D = {}
for k in data_store.lines:
lines2D[k] = axes.plot([], [], label=k)[0]
plt.legend(loc='upper center', bbox_to_anchor=(0.5, 1.05),
ncol=4, fancybox=True, shadow=True, frameon=True)
time.sleep(5)
while True:
time.sleep(10)
if not any(len(x) > 0 for x in data_store.lines.values()):
continue
try:
xmax = data_store.xdata[-1] + 5
except:
xmax = 5
ymax = max([x for l in data_store.lines.values() for x in l]) + 5
axes.set_xlim(0, xmax)
axes.set_ylim(0, ymax)
for k in lines2D:
lines2D[k].set_data(
data_store.xdata, data_store.lines[k])
plt.pause(0.01)
4 changes: 2 additions & 2 deletions python/params.py
@@ -1,5 +1,5 @@
URL = 'ws://127.0.0.1:8000/macro/sample/'

URL = 'ws://127.0.0.1:8080/macro/sample/'
#172.104.155.87
sample_net = {
'numLines': 13,
}
23 changes: 23 additions & 0 deletions python/requirements.txt
@@ -1,12 +1,35 @@
certifi==2018.4.16
chardet==3.0.4
click==6.7
cycler==0.10.0
dash==0.21.1
dash-core-components==0.22.1
dash-html-components==0.10.1
dash-renderer==0.12.1
decorator==4.3.0
Flask==1.0.2
Flask-Compress==1.4.0
idna==2.6
ipython-genutils==0.2.0
itsdangerous==0.24
Jinja2==2.10
jsonschema==2.6.0
jupyter-core==4.4.0
kiwisolver==1.0.1
MarkupSafe==1.0
matplotlib==2.2.2
nbformat==4.4.0
numpy==1.14.2
pandas==0.22.0
plotly==2.5.1
pyparsing==2.2.0
python-dateutil==2.7.0
pytz==2018.3
requests==2.18.4
scipy==1.0.0
seaborn==0.8.1
six==1.11.0
traitlets==4.3.2
urllib3==1.22
websockets==4.0.1
Werkzeug==0.14.1

0 comments on commit eef5c3f

Please sign in to comment.