What is the best way to use Dash with Websockets to build a real-time dashboard ? I would like to update a graph everytime a message is received but the only thing I've found is calling the callback every x seconds like the example below.
import dash
import dash_core_components as dcc
import dash_html_components as html
import dash_daq as daq
from dash.dependencies import Input, Output
import plotly
import plotly.graph_objs as go
from websocket import create_connection
from tinydb import TinyDB, Query
import json
import ssl
# Setting up the websocket and the necessary web handles
ws = create_connection(address, sslopt={"cert_reqs": ssl.CERT_NONE})
app = dash.Dash(__name__)
app.layout = html.Div(
[
dcc.Graph(id='live-graph', animate=True),
dcc.Interval(
id='graph-update',
interval=1*1000,
n_intervals=0)
]
)
#app.callback(Output('live-graph', 'figure'),
[Input('graph-update', 'n_intervals')])
def update_graph_live(n):
message = ws.recv()
x=message.get('data1')
y=message.get('data2')
.....
fig = go.Figure(
data = [go.Bar(x=x,y=y)],
layout=go.Layout(
title=go.layout.Title(text="Bar Chart")
)
)
)
return fig
if __name__ == '__main__':
app.run_server(debug=True)
Is there a way to trigger the callback everytime a message is received (maybe storing them in a database before) ?
This forum post describes a method to use websocket callbacks with Dash:
https://community.plot.ly/t/triggering-callback-from-within-python/23321/6
Update
Tried it, it works well. Environment is Windows 10 x64 + Python 3.7.
To test, download the .tar.gz file and run python usage.py. It will complain about some missing packages, install these. Might have to edit the address from 0.0.0.0 to 127.0.0.1 in usage.py. Browse to http://127.0.0.1:5000 to see the results. If I had more time, I'd put this example up on GitHub (ping me if you're having trouble getting it to work, or the original gets lost).
I had two separate servers: one for dash, the other one as a socket server. They are running on different ports. On receiving a message, I edited a common json file to share information to dash's callback. That's how I did it.
Related
I'm trying to call gdal2tiles.py in AWS Lambda function using GeoLambda layer.
I can't figure out how to call this script form the lambda function.
My lambda function looks like this so far:
import json
import os
from osgeo import gdal
def lambda_handler(event, context):
os.system("gdal2tiles.py -p -z [0-6] test.jpg")
In the log I have this error: sh: gdal2tiles.py: command not found
Any idea how to solve this? Thank you.
one way to do it is to import gdal2tiles utilities from the GeoLambda layer that you added to your lambda function.
For example:
gdal2tiles.generate_tiles('/path/to/input_file', '/path/to/output_dir/'), nb_processes=2, zoom='0-6')
Read more about in gdal2tiles
Edit:
Ok i made it to work with these set of layer attached to the lambda.
The first 2 layers were straight from the Github
arn:aws:lambda:us-east-1:552188055668:layer:geolambda-python:3
arn:aws:lambda:us-east-1:552188055668:layer:geolambda:4
The 3rd layer is our gdal2tiles which is created locally and attached to lambda fucntion
arn:aws:lambda:us-east-1:246990787935:layer:gdaltiles:1
you can download the zip from here
And i hope you added the below Environment vairable to your lambda function configuration
GDAL_DATA=/opt/share/gdal
PROJ_LIB=/opt/share/proj (only needed for GeoLambda 2.0.0+)
I just ran into issues where I am writing small web service with Go Iris framework. Iris has few useful packages for HTTP request error handling.
Namely, I wanted to use "github.com/kataras/iris/middleware/logger" and
"github.com/kataras/iris/middleware/recover" however when I start typing app.Use(logger....) VSCode auto imported "github.com/hashicorp/consul/logger" which is also in my path.
Simply copy-pasting right path will solve the issue, but is there a way to force VSCode to make a manual choice where multiple packages names are matched or even fully disable goimports for these cases.
Example below:
package main
import (
// "github.com/hashicorp/consul/logger" ! incorrect package
"github.com/kataras/iris"
"github.com/kataras/iris/middleware/logger"
"github.com/kataras/iris/middleware/recover"
)
func main() {
app := iris.New()
app.Logger().SetLevel("debug")
// Optionally, add 2 built'n handlers
// that can recover from any http-related error
// and log the requests in terminal
app.Use(recover.New())
app.Use(logger.New())
}
If you start typing in the import () declaration, it will give you suggestions that match. So if you were to type logger it would give you the suggestion of:
github.com/kataras/iris/middleware/logger
and
github.com/hashicorp/consul/logger
Just put the "" in the import and start typing the package you want.
I'm working on a django project with channels involved in different apps. The first app (receiving data from a sensor) has it's own consumer and routing, as well as the second one (updates a list of logged in users).
Within the first app everything works fine.
In the second app the handshake is completed and the connection is established, but the function, that is linked to websocket.receive is not executed.
from channels.routing import route, route_class
from channels.staticfiles import StaticFilesConsumer
from users.consumer import ws_connect, ws_disconnect
channel_routing = [
route('websocket.connect', ws_connect, path=r'^/users/lobby/'),
...
]
and the ws_connect
import json
from channels import Group
from channels.handler import AsgiHandler
from channels.auth import channel_session_user,
channel_session_user_from_http, channel_session
#channel_session_user_from_http
def ws_connect(message):
print('test')
The print('test') of ws_connect is never executed. Additionally it even doesn't matter what url ending I'm using in javascript.
var ws = new WebSocket('ws://127.0.0.1:8000/users/lobby/');
ws.onopen = function() {
console.log('connect');
ws.send('connect');
}
The ws of the javascript will connect with .../users/lobby/ or .../lobby/ of .../users/.
Thanks for any hints on this!
Since i apparently need 50 reputation to make a comment i'm just gonna make an answer instead even tho i am not sure this is the solution for you.
I had the same exact problem when copying parts of the the github multichat project made by the guy whom made channels.
My issue was apparently that i hade miss spelled the routing with a slight misstake and therefor it didn't call the correct function i had setup for that routing.
So my advice is that you trippel check the routing everywhere to see if you've messed up. I personally only checked my APP routing when error checking but it was in my project folder i had messed upp my routing.
Another thing that might be cauzing this issue is that you only have a routing in your app, but not in the main folder. In that case you need to include the other app routing with the path you want for it just like a view:
from channels import include
channel_routing = [
include("crypto_chat.routing.websocket_routing", path=r"^/chat/stream/$"),
include("crypto_chat.routing.chat_routing"),
]
App routing:
from channels import route
from .consumers import ws_connect, ws_receive, ws_disconnect, user_offline, user_online, chat_send
websocket_routing = [
route("websocket.connect", ws_connect),
route("websocket.receive", ws_receive),
route("websocket.disconnect", ws_disconnect),
]
chat_routing = [
route("chat.receive", chat_send, command="^send$"),
route("chat.receive", user_online, command="^online$"),
route("chat.receive",user_offline, command="^offline$"),
]
If that doesnt help then i suggest you head over to the github channel page for examples and compare the two. Keep in mind tho that the project is probably made from an erlier version of channels (and maybe django aswell).
https://github.com/andrewgodwin/channels-examples
Hope it helps and as i said i would have made a comment but i can't since of my rep apparently...
How can I access an unsupported Wand API via the Python Wand interface? For example, I wish to call the Wand API MagickAddNoiseImage but it is not available in the Python interface.
Accessing unsupported APIs is pretty easy with wand.api, but you will need to open-up ImageMagick's docs/header files for reference.
from wand.api import library
import ctypes
# Re-create NoiseType enum
NOISE_TYPES = ('undefined', 'uniform', 'gaussian', 'multiplicative_gaussian',
'impulse', 'laplacian', 'poisson', 'random')
# Map API i/o
library.MagickAddNoiseImage.argtypes = [ctypes.c_void_p,
ctypes.c_uint]
library.MagickAddNoiseImage.restype = ctypes.c_int
# Extend wand's Image class with your new API
from wand.image import Image
class MySupportedImage(Image):
def add_noise(self, noise_type):
"""My MagickAddNoiseImage"""
if noise_type not in NOISE_TYPES:
self.raise_exception()
return library.MagickAddNoiseImage.argtypes(self.resource,
NOISE_TYPES.index(noise_type))
If your solution works out, think about submitting your solution back to the community (after you've created a solid unit test.)
Is there a way to save and recover a trained Neural Network in PyBrain, so that I don't have to retrain it each time I run the script?
PyBrain's Neural Networks can be saved and loaded using either python's built in pickle/cPickle module, or by using PyBrain's XML NetworkWriter.
# Using pickle
from pybrain.tools.shortcuts import buildNetwork
import pickle
net = buildNetwork(2,4,1)
fileObject = open('filename', 'w')
pickle.dump(net, fileObject)
fileObject.close()
fileObject = open('filename','r')
net = pickle.load(fileObject)
Note cPickle is implemented in C, and therefore should be much faster than pickle. Usage should mostly be the same as pickle, so just import and use cPickle instead.
# Using NetworkWriter
from pybrain.tools.shortcuts import buildNetwork
from pybrain.tools.customxml.networkwriter import NetworkWriter
from pybrain.tools.customxml.networkreader import NetworkReader
net = buildNetwork(2,4,1)
NetworkWriter.writeToFile(net, 'filename.xml')
net = NetworkReader.readFrom('filename.xml')
The NetworkWriter and NetworkReader work great. I noticed that upon saving and loading via pickle, that the network is no longer changeable via training-functions. Thus, I would recommend using the NetworkWriter-method.
NetworkWriter is the way to go. Using Pickle you can't retrain network as Jorg tells.
You need something like this:
from pybrain.tools.shortcuts import buildNetwork
from pybrain.tools.customxml import NetworkWriter
from pybrain.tools.customxml import NetworkReader
net = buildNetwork(4,6,1)
NetworkWriter.writeToFile(net, 'filename.xml')
net = NetworkReader.readFrom('filename.xml')