Skip to content

Instantly share code, notes, and snippets.

@kevincolten
Last active August 29, 2015 14:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kevincolten/f44c274064cd4745415a to your computer and use it in GitHub Desktop.
Save kevincolten/f44c274064cd4745415a to your computer and use it in GitHub Desktop.
Tornado Sandbox

ClientDataStore operations

Stores actual columns of data on the client. Used by lightweight "data source" models. Supports performing the following CRUD operations.

  • create new columns

  • replace all columns

  • replace selected columns

  • append to all columns

  • append to all columns, roll buffer

  • patch arbitrary indices

  • delete columns

Bokeh._data_store

Index of to ClientDataStore, does not live in any Bokeh Document.

ClientDataSource

A lightweight data source object that lives in a Bokeh Document. Is configured with, or can reference a ClientDataStore in Bokeh._data_store

Column Header

{ type: "COLUMN" name: # column name dtype: # float32, float64, int32, int64, int8, uint8 size: # array size in bytes shape: [, , ...] }

WebSocket Protocol

"\0"

# utf-8 header, interpreted as JSON

[] # optional JSON+binary payload described by header

{ action: "CREATE_S" docid: modelid: columns: ["foo", "bar", "baz"] }

{ action: "REPLACE" docid: modelid: columns: ["foo", "bar", "baz"] }

{ action: "APPEND" docid: modelid: columns: ["foo", "bar", "baz"] }

{ action: "ROLLOVER" docid: modelid: columns: ["foo", "bar", "baz"] }

{ action: "DELETE" docid: modelid: columns: ["foo", "bar", "baz"] }

{ action: "PATCH" docid: modelid: updates: { "foo": [ [, data], [, data], ... ], "bar": [ [, data], [, data], ... ], "baz": [ [, data], [, data], ... ] ] }

from __future__ import print_function
from flask import Flask, render_template
from tornado.wsgi import WSGIContainer
from tornado.web import Application, FallbackHandler
from tornado.websocket import WebSocketHandler
from tornado.ioloop import IOLoop
import numpy as np
arr = np.arange(10, dtype=np.float32)
arr_bytes = arr.tobytes()
shp = [0,0,0][:len(arr.shape)] = arr.shape
meta = {
"size": len(arr_bytes),
"shape": shp,
"type": "float32",
}
class WebSocket(WebSocketHandler):
def open(self):
print("Socket opened.")
def on_message(self, message):
self.write_message("\0")
self.write_message(meta)
self.write_message(arr_bytes, binary=True)
def on_close(self):
print("Socket closed.")
app = Flask('flasknado')
@app.route('/')
def index():
return ('''
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Flasknado!</title>
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
<script>
/* Client-side component for the Flasknado! demo application. */
var socket = null;
var state = 0;
var header = null;
var array = null;
$(document).ready(function() {
socket = new WebSocket("ws://" + document.domain + ":8080/array/");
socket.binaryType = 'arraybuffer';
socket.onopen = function() {
socket.send("Joined");
}
socket.onmessage = function(message) {
if (state == 0 && message.data == "\0") {
state = 1;
}
else if (state == 1) {
header = message.data;
state = 2;
}
else if (state == 2) {
array = new Float32Array(message.data);
state = 0;
}
}
});
function submit() {
var text = $("input#message").val();
socket.send(text);
$("input#message").val('');
}
</script>
</head>
<body>
<h1>Flasknado!</h1>
<div class="container">
<p>Send a message:</p>
<input id="message" type="text">
<button id="submit" type="button" onclick="submit()">Submit</button>
<p>Messages received:</p>
</div>
</body>
</html>
''')
if __name__ == "__main__":
container = WSGIContainer(app)
server = Application([
(r'/array/', WebSocket),
(r'.*', FallbackHandler, dict(fallback=container))
])
server.listen(8080)
IOLoop.instance().start()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment