-
-
Save ngoldbaum/7457006 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"metadata": { | |
"gist_id": "6547109", | |
"name": "" | |
}, | |
"nbformat": 3, | |
"nbformat_minor": 0, | |
"worksheets": [ | |
{ | |
"cells": [ | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"import sys, time\n", | |
"\n", | |
"from IPython.utils.traitlets import HasTraits, Integer, Unicode, Bool, Instance, Float\n", | |
"from IPython.display import *\n", | |
"\n", | |
"from IPython.kernel.comm import Comm" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 12 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"%%javascript\n", | |
"\n", | |
"var TestWidget = function (comm) {\n", | |
" this.comm = comm;\n", | |
" this.comm.on_msg($.proxy(this.handler, this));\n", | |
" // get the cell that was probably executed\n", | |
" // msg_id:cell mapping will make this possible without guessing\n", | |
" this.cell = IPython.notebook.get_cell(IPython.notebook.get_selected_index()-1);\n", | |
" this.callbacks = {\n", | |
" iopub : {\n", | |
" output : $.proxy(this.cell.output_area.handle_output, this.cell.output_area)\n", | |
" }\n", | |
" };\n", | |
"};\n", | |
"\n", | |
"TestWidget.prototype.handler = function(msg) {\n", | |
" console.log('handle', this, msg, this.cell.output_area);\n", | |
" this.comm.send({ b:10 }, this.callbacks);\n", | |
"};\n", | |
"\n", | |
"IPython.notebook.kernel.comm_manager.register_target('test', IPython.utils.always_new(TestWidget));" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"javascript": [ | |
"\n", | |
"var TestWidget = function (comm) {\n", | |
" this.comm = comm;\n", | |
" this.comm.on_msg($.proxy(this.handler, this));\n", | |
" // get the cell that was probably executed\n", | |
" // msg_id:cell mapping will make this possible without guessing\n", | |
" this.cell = IPython.notebook.get_cell(IPython.notebook.get_selected_index()-1);\n", | |
" this.callbacks = {\n", | |
" iopub : {\n", | |
" output : $.proxy(this.cell.output_area.handle_output, this.cell.output_area)\n", | |
" }\n", | |
" };\n", | |
"};\n", | |
"\n", | |
"TestWidget.prototype.handler = function(msg) {\n", | |
" console.log('handle', this, msg, this.cell.output_area);\n", | |
" this.comm.send({ b:10 }, this.callbacks);\n", | |
"};\n", | |
"\n", | |
"IPython.notebook.kernel.comm_manager.register_target('test', IPython.utils.always_new(TestWidget));" | |
], | |
"metadata": {}, | |
"output_type": "display_data", | |
"text": [ | |
"<IPython.core.display.Javascript at 0x10befe510>" | |
] | |
} | |
], | |
"prompt_number": 13 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"comm = Comm(target_name='test')" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"{'parent_header': {}, 'msg_type': u'comm_msg', 'msg_id': u'A122E95D77AF4CBB8A7217FB545CE6D9', 'content': {u'data': {u'b': 10}, u'comm_id': u'fe2aadee4edd447eab4e70db35329167'}, 'header': {u'username': u'username', u'msg_id': u'A122E95D77AF4CBB8A7217FB545CE6D9', u'msg_type': u'comm_msg', u'session': u'10E950937F064BF189265D59D6AD2262'}, 'buffers': [], 'metadata': {}}\n" | |
] | |
} | |
], | |
"prompt_number": 14 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"comm.send(dict(a=5))" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 15 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"def handler(msg):\n", | |
" print >> sys.__stderr__, msg\n", | |
" print msg\n", | |
"\n", | |
"comm.on_msg(handler)" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 16 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"comm.send(dict(a=10))" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 17 | |
}, | |
{ | |
"cell_type": "heading", | |
"level": 2, | |
"metadata": {}, | |
"source": [ | |
"Range widget" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"import uuid\n", | |
"\n", | |
"class Widget(HasTraits):\n", | |
" target_name = Unicode(\"widget\")\n", | |
" id = Unicode()\n", | |
" def _id_default(self):\n", | |
" return 'widget-%s' % uuid.uuid4().hex\n", | |
" \n", | |
" comm = Instance(Comm)\n", | |
" def _comm_default(self):\n", | |
" data = self.data\n", | |
" data['id'] = self.id\n", | |
" return Comm(data=data, target_name=self.target_name)\n", | |
" \n", | |
" @property\n", | |
" def data(self):\n", | |
" return {}\n" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 18 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"class RangeWidget(Widget):\n", | |
" target_name = Unicode(\"range\")\n", | |
" min = Float(0)\n", | |
" max = Float(100)\n", | |
" value = Float(50)\n", | |
" step = Float(1)\n", | |
" _keys = ['min', 'max', 'value', 'step']\n", | |
" _in_handler = Bool(False)\n", | |
" \n", | |
" def _validate_and_update(self, name, old, new):\n", | |
" if self.value > self.max:\n", | |
" raise ValueError(\"value %d exceeds max %d\" % (self.value, self.max))\n", | |
" if new < self.min:\n", | |
" raise ValueError(\"value %d below min %d\" % (self.value, self.min))\n", | |
" \n", | |
" if not self._in_handler:\n", | |
" self.update()\n", | |
" \n", | |
" def __init__(self, **kwargs):\n", | |
" super(RangeWidget, self).__init__(**kwargs)\n", | |
" self.comm.on_msg(self.handle_msg)\n", | |
" # register on_trait_change after init\n", | |
" # otherwise default values can't be specified\n", | |
" self.on_trait_change(self._validate_and_update, self._keys)\n", | |
" \n", | |
" @property\n", | |
" def data(self):\n", | |
" return {key:getattr(self, key) for key in self._keys}\n", | |
" \n", | |
" def update(self):\n", | |
" self.comm.send(self.data)\n", | |
" \n", | |
" def __repr__(self):\n", | |
" return \"<Range (%.1f) %.1f:%.1f:%.1f>\" % (self.value, self.min, self.max, self.step)\n", | |
" \n", | |
" def handle_msg(self, msg):\n", | |
" self._in_handler = True\n", | |
" data = msg['content']['data']\n", | |
" try:\n", | |
" for key in self._keys:\n", | |
" if key in data:\n", | |
" setattr(self, key, data[key])\n", | |
" finally:\n", | |
" self._in_handler = False\n", | |
" sys.stdout.write('\\r%s' % self)\n", | |
" sys.stdout.flush()\n", | |
" \n", | |
" def _repr_html_(self):\n", | |
" return \"\"\"<div class=\"%s\"></div>\"\"\" % self.id\n", | |
" \n", | |
" def display(self):\n", | |
" display(self)\n", | |
" self.update()\n" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 19 | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"The Javascript side" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"%%javascript\n", | |
"var RangeWidget = function (comm, msg) {\n", | |
" this.comm = comm;\n", | |
" comm.on_msg($.proxy(this.handle_msg, this));\n", | |
" // get the cell that was probably executed\n", | |
" // msg_id:cell mapping will make this possible without guessing\n", | |
" this.cell = IPython.notebook.get_cell(IPython.notebook.get_selected_index()-1);\n", | |
" this.callbacks = {\n", | |
" iopub : {\n", | |
" output : $.proxy(this.cell.output_area.handle_output, this.cell.output_area)\n", | |
" }\n", | |
" };\n", | |
"\n", | |
" this.keys = ['min', 'max', 'step'];\n", | |
" this.data = msg.content.data;\n", | |
" this.id = this.data.id;\n", | |
" this.get_div();\n", | |
"};\n", | |
"\n", | |
"RangeWidget.prototype.get_div = function () {\n", | |
" var div = $(\"div.\" + this.id);\n", | |
" if (div.length === 0) {\n", | |
" return null;\n", | |
" }\n", | |
" if (div.find(\"input\").length === 0) {\n", | |
" this.create_range(div);\n", | |
" }\n", | |
" return div;\n", | |
"};\n", | |
"\n", | |
"RangeWidget.prototype.create_range = function (thediv) {\n", | |
" var range = $('<input></input>').attr('type', 'range');\n", | |
" var data = this.data;\n", | |
" \n", | |
" for (var i=0; i < this.keys.length; i++) {\n", | |
" var key = this.keys[i];\n", | |
" range.attr(key, data[key]);\n", | |
" }\n", | |
" range.val(data.value);\n", | |
" \n", | |
" thediv.append(\n", | |
" $(\"<span/>\").addClass(\"min\").text(data.min)\n", | |
" ).append(\n", | |
" range\n", | |
" ).append(\n", | |
" $(\"<span/>\").addClass(\"max\").text(data.max)\n", | |
" ).append(\n", | |
" $(\"<br/>\")\n", | |
" ).append(\n", | |
" $(\"<span/>\").addClass(\"value\").text(data.value)\n", | |
" );\n", | |
" range.on(\"change\", $.proxy(this.value_changed, this));\n", | |
"}\n", | |
"\n", | |
"RangeWidget.prototype.value_changed = function (evt) {\n", | |
" var now = new Date();\n", | |
" if (now - this.last_changed < 100) {\n", | |
" // only update every 0.1s, max\n", | |
"// return;\n", | |
" }\n", | |
" var div = this.get_div();\n", | |
" var range = div.find(\"input\");\n", | |
" var data = {};\n", | |
" for (var i=0; i < this.keys.length; i++) {\n", | |
" var key = this.keys[i];\n", | |
" data[key] = parseFloat(range.attr(key));\n", | |
" }\n", | |
" data.value = parseFloat(range.val());\n", | |
" div.find(\"span.min\").text(data.min);\n", | |
" div.find(\"span.max\").text(data.max);\n", | |
" div.find(\"span.value\").text(data.value);\n", | |
" this.comm.send(data, this.callbacks);\n", | |
" this.last_changed = now;\n", | |
"};\n", | |
"\n", | |
"RangeWidget.prototype.handle_msg = function (msg) {\n", | |
" var data = msg.content.data;\n", | |
" this.data = data;\n", | |
" var div = this.get_div();\n", | |
" if (!div) {\n", | |
" return;\n", | |
" }\n", | |
" var range = div.find(\"input\");\n", | |
"\n", | |
" for (var i=0; i < this.keys.length; i++) {\n", | |
" var key = this.keys[i];\n", | |
" range.attr(key, data[key]);\n", | |
" }\n", | |
" div.find(\"span.min\").text(data.min);\n", | |
" div.find(\"span.max\").text(data.max);\n", | |
" div.find(\"span.value\").text(data.value);\n", | |
" range.val(data.value);\n", | |
"};\n", | |
"\n", | |
"IPython.notebook.kernel.comm_manager.register_target('range', IPython.utils.always_new(RangeWidget));" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"javascript": [ | |
"var RangeWidget = function (comm, msg) {\n", | |
" this.comm = comm;\n", | |
" comm.on_msg($.proxy(this.handle_msg, this));\n", | |
" // get the cell that was probably executed\n", | |
" // msg_id:cell mapping will make this possible without guessing\n", | |
" this.cell = IPython.notebook.get_cell(IPython.notebook.get_selected_index()-1);\n", | |
" this.callbacks = {\n", | |
" iopub : {\n", | |
" output : $.proxy(this.cell.output_area.handle_output, this.cell.output_area)\n", | |
" }\n", | |
" };\n", | |
"\n", | |
" this.keys = ['min', 'max', 'step'];\n", | |
" this.data = msg.content.data;\n", | |
" this.id = this.data.id;\n", | |
" this.get_div();\n", | |
"};\n", | |
"\n", | |
"RangeWidget.prototype.get_div = function () {\n", | |
" var div = $(\"div.\" + this.id);\n", | |
" if (div.length === 0) {\n", | |
" return null;\n", | |
" }\n", | |
" if (div.find(\"input\").length === 0) {\n", | |
" this.create_range(div);\n", | |
" }\n", | |
" return div;\n", | |
"};\n", | |
"\n", | |
"RangeWidget.prototype.create_range = function (thediv) {\n", | |
" var range = $('<input></input>').attr('type', 'range');\n", | |
" var data = this.data;\n", | |
" \n", | |
" for (var i=0; i < this.keys.length; i++) {\n", | |
" var key = this.keys[i];\n", | |
" range.attr(key, data[key]);\n", | |
" }\n", | |
" range.val(data.value);\n", | |
" \n", | |
" thediv.append(\n", | |
" $(\"<span/>\").addClass(\"min\").text(data.min)\n", | |
" ).append(\n", | |
" range\n", | |
" ).append(\n", | |
" $(\"<span/>\").addClass(\"max\").text(data.max)\n", | |
" ).append(\n", | |
" $(\"<br/>\")\n", | |
" ).append(\n", | |
" $(\"<span/>\").addClass(\"value\").text(data.value)\n", | |
" );\n", | |
" range.on(\"change\", $.proxy(this.value_changed, this));\n", | |
"}\n", | |
"\n", | |
"RangeWidget.prototype.value_changed = function (evt) {\n", | |
" var now = new Date();\n", | |
" if (now - this.last_changed < 100) {\n", | |
" // only update every 0.1s, max\n", | |
"// return;\n", | |
" }\n", | |
" var div = this.get_div();\n", | |
" var range = div.find(\"input\");\n", | |
" var data = {};\n", | |
" for (var i=0; i < this.keys.length; i++) {\n", | |
" var key = this.keys[i];\n", | |
" data[key] = parseFloat(range.attr(key));\n", | |
" }\n", | |
" data.value = parseFloat(range.val());\n", | |
" div.find(\"span.min\").text(data.min);\n", | |
" div.find(\"span.max\").text(data.max);\n", | |
" div.find(\"span.value\").text(data.value);\n", | |
" this.comm.send(data, this.callbacks);\n", | |
" this.last_changed = now;\n", | |
"};\n", | |
"\n", | |
"RangeWidget.prototype.handle_msg = function (msg) {\n", | |
" var data = msg.content.data;\n", | |
" this.data = data;\n", | |
" var div = this.get_div();\n", | |
" if (!div) {\n", | |
" return;\n", | |
" }\n", | |
" var range = div.find(\"input\");\n", | |
"\n", | |
" for (var i=0; i < this.keys.length; i++) {\n", | |
" var key = this.keys[i];\n", | |
" range.attr(key, data[key]);\n", | |
" }\n", | |
" div.find(\"span.min\").text(data.min);\n", | |
" div.find(\"span.max\").text(data.max);\n", | |
" div.find(\"span.value\").text(data.value);\n", | |
" range.val(data.value);\n", | |
"};\n", | |
"\n", | |
"IPython.notebook.kernel.comm_manager.register_target('range', IPython.utils.always_new(RangeWidget));" | |
], | |
"metadata": {}, | |
"output_type": "display_data", | |
"text": [ | |
"<IPython.core.display.Javascript at 0x10c22d950>" | |
] | |
} | |
], | |
"prompt_number": 20 | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Create the Python object, and register it with the WidgetManager.\n", | |
"Registration triggers creation of the javascript-side counterpart." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"r = RangeWidget()\n", | |
"r.display()" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"html": [ | |
"<div class=\"widget-97f2297fe8014206aeb1de9d0aaa8219\"></div>" | |
], | |
"metadata": {}, | |
"output_type": "display_data", | |
"text": [ | |
"<Range (50.0) 0.0:100.0:1.0>" | |
] | |
}, | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"\r", | |
"<Range (47.0) 0.0:100.0:1.0>" | |
] | |
}, | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"\r", | |
"<Range (26.0) 0.0:100.0:1.0>" | |
] | |
}, | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"\r", | |
"<Range (15.0) 0.0:100.0:1.0>" | |
] | |
}, | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"\r", | |
"<Range (12.0) 0.0:100.0:1.0>" | |
] | |
}, | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"\r", | |
"<Range (13.0) 0.0:100.0:1.0>" | |
] | |
}, | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"\r", | |
"<Range (15.0) 0.0:100.0:1.0>" | |
] | |
}, | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"\r", | |
"<Range (18.0) 0.0:100.0:1.0>" | |
] | |
}, | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"\r", | |
"<Range (23.0) 0.0:100.0:1.0>" | |
] | |
}, | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"\r", | |
"<Range (29.0) 0.0:100.0:1.0>" | |
] | |
}, | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"\r", | |
"<Range (33.0) 0.0:100.0:1.0>" | |
] | |
}, | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"\r", | |
"<Range (44.0) 0.0:100.0:1.0>" | |
] | |
}, | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"\r", | |
"<Range (49.0) 0.0:100.0:1.0>" | |
] | |
}, | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"\r", | |
"<Range (52.0) 0.0:100.0:1.0>" | |
] | |
}, | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"\r", | |
"<Range (53.0) 0.0:100.0:1.0>" | |
] | |
}, | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"\r", | |
"<Range (54.0) 0.0:100.0:1.0>" | |
] | |
} | |
], | |
"prompt_number": 25 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"r.value = 10" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 26 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"print r" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"<Range (10.0) 0.0:100.0:1.0>\n" | |
] | |
} | |
], | |
"prompt_number": 27 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"import math, time\n", | |
"import numpy as np\n", | |
"x = np.linspace(0,10,1000)\n", | |
"y = 50 + (np.sin(x) * 50)\n", | |
"for n in y:\n", | |
" r.value = (n)\n", | |
" time.sleep(0.005)\n", | |
" " | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 28 | |
}, | |
{ | |
"cell_type": "heading", | |
"level": 1, | |
"metadata": {}, | |
"source": [ | |
"Now demo flot plots using Widget APIs" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"from IPython.utils.traitlets import List" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 29 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"class FlotWidget(Widget):\n", | |
" lines = List()\n", | |
" target_name = Unicode('flotplot')\n", | |
" \n", | |
" def show(self):\n", | |
" self.comm.send(dict(lines=self.lines))\n", | |
" \n", | |
" def plot(self, x, y):\n", | |
" self.lines.append(list(zip(x,y)))\n", | |
" self.show()\n", | |
" \n", | |
" def clear(self):\n", | |
" self.lines = []\n", | |
" self.show()\n", | |
" \n", | |
" def display(self):\n", | |
" display(self)\n", | |
" self.clear()\n", | |
" \n", | |
" def _repr_html_(self):\n", | |
" return '<div id=\"%s\" class=\"flotwidget\"></div>' % self.id" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 30 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"%%javascript\n", | |
"$.getScript('//cdnjs.cloudflare.com/ajax/libs/flot/0.8.1/jquery.flot.min.js');\n", | |
"$(\"<style type='text/css'> .flotwidget{ width: 100%; height: 300px;}</style>\").appendTo(\"head\");\n", | |
"\n", | |
"var FlotWidget = function (comm, msg) {\n", | |
" this.comm = comm;\n", | |
" this.id = msg.content.data.id;\n", | |
" comm.on_msg($.proxy(this.handle_msg, this));\n", | |
"};\n", | |
"\n", | |
"FlotWidget.prototype.handle_msg = function (msg) {\n", | |
" console.log(msg)\n", | |
" $.plot($('#' + this.id), msg.content.data.lines);\n", | |
"}\n", | |
"\n", | |
"IPython.notebook.kernel.comm_manager.register_target('flotplot', IPython.utils.always_new(FlotWidget));" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"javascript": [ | |
"$.getScript('//cdnjs.cloudflare.com/ajax/libs/flot/0.8.1/jquery.flot.min.js');\n", | |
"$(\"<style type='text/css'> .flotwidget{ width: 100%; height: 300px;}</style>\").appendTo(\"head\");\n", | |
"\n", | |
"var FlotWidget = function (comm, msg) {\n", | |
" this.comm = comm;\n", | |
" this.id = msg.content.data.id;\n", | |
" comm.on_msg($.proxy(this.handle_msg, this));\n", | |
"};\n", | |
"\n", | |
"FlotWidget.prototype.handle_msg = function (msg) {\n", | |
" console.log(msg)\n", | |
" $.plot($('#' + this.id), msg.content.data.lines);\n", | |
"}\n", | |
"\n", | |
"IPython.notebook.kernel.comm_manager.register_target('flotplot', IPython.utils.always_new(FlotWidget));" | |
], | |
"metadata": {}, | |
"output_type": "display_data", | |
"text": [ | |
"<IPython.core.display.Javascript at 0x10c22dd50>" | |
] | |
} | |
], | |
"prompt_number": 33 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"flt = FlotWidget()\n", | |
"flt.display()" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"html": [ | |
"<div id=\"widget-68fce499faff4c2a88fdbca4bb32813d\" class=\"flotwidget\"></div>" | |
], | |
"metadata": {}, | |
"output_type": "display_data", | |
"text": [ | |
"<__main__.FlotWidget at 0x10c22dd50>" | |
] | |
} | |
], | |
"prompt_number": 34 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"x = np.linspace(0,5,200)\n", | |
"y = np.sin(x)\n", | |
"flt.plot(x,np.sin(x))\n", | |
"flt.plot(x,np.cos(x))\n" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 35 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"flt.plot(x, np.sin(2*x))" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 36 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"flt.plot(x, np.sin(3*x))" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 37 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"flt.clear()" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 38 | |
}, | |
{ | |
"cell_type": "heading", | |
"level": 2, | |
"metadata": {}, | |
"source": [ | |
"Using two widgets together" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"from IPython.utils.traitlets import HasTraits, Instance, Any\n", | |
"\n", | |
"class SineOmegaT(HasTraits):\n", | |
" omega = Instance(RangeWidget, kw=dict(min=0, max=10, step=0.1, value=1), allow_none=False)\n", | |
" flot = Instance(FlotWidget, args=())\n", | |
" # can't use traitlets with numpy arrays\n", | |
" t = None\n", | |
" y = None\n", | |
" _in_omega_changed = False\n", | |
" \n", | |
" def _omega_value_changed(self, name, old, new):\n", | |
" self.y = np.sin(new * self.t)\n", | |
" self.show()\n", | |
" \n", | |
" def __init__(self):\n", | |
" super(SineOmegaT, self).__init__()\n", | |
" self.omega.on_trait_change(self._omega_value_changed, 'value')\n", | |
" self.t = np.linspace(0,10,200)\n", | |
" self.y = np.sin(self.omega.value * self.t)\n", | |
" # add HTML to the dom\n", | |
" display(self)\n", | |
" # ensure omega slider is drawn\n", | |
" self.omega.update()\n", | |
" self.last_draw = 0\n", | |
" self.show()\n", | |
" \n", | |
" \n", | |
" def show(self):\n", | |
" now = time.time()\n", | |
" if False and (now - self.last_draw) < 0.1:\n", | |
" return\n", | |
" self.last_draw = now\n", | |
" self.flot.lines = []\n", | |
" self.flot.plot(self.t, self.y)\n", | |
" \n", | |
" def display(self):\n", | |
" display(self)\n", | |
" self.show()\n", | |
" \n", | |
" def _repr_html_(self):\n", | |
" return u\"<div style='text-align: center; font-size: 200%%;'>$sin(\\omega t)$</div><br>%s<br>$\\omega$: %s\" % (self.flot._repr_html_(), self.omega._repr_html_())\n", | |
" " | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 39 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"sino = SineOmegaT()" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"html": [ | |
"<div style='text-align: center; font-size: 200%;'>$sin(\\omega t)$</div><br><div id=\"widget-ea3d7868a4654c82abaf297e83088355\" class=\"flotwidget\"></div><br>$\\omega$: <div class=\"widget-772c063c88d74da086090c477bb63855\"></div>" | |
], | |
"metadata": {}, | |
"output_type": "display_data", | |
"text": [ | |
"<__main__.SineOmegaT at 0x10c23a250>" | |
] | |
}, | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"\r", | |
"<Range (2.0) 0.0:30.0:1.0>" | |
] | |
}, | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"\r", | |
"<Range (4.0) 0.0:30.0:1.0>" | |
] | |
}, | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"\r", | |
"<Range (7.0) 0.0:30.0:1.0>" | |
] | |
}, | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"\r", | |
"<Range (21.0) 0.0:30.0:1.0>" | |
] | |
} | |
], | |
"prompt_number": 40 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"sino.omega.max = 30\n", | |
"sino.omega.step = 1" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 41 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"sino.t = np.linspace(0,10,10)\n", | |
"sino.show()" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 27 | |
}, | |
{ | |
"cell_type": "heading", | |
"level": 1, | |
"metadata": {}, | |
"source": [ | |
"Widgets created in Javascript" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"class RPCWidget(object):\n", | |
" def __init__(self, comm, msg):\n", | |
" self.comm = comm\n", | |
" self.comm.on_msg(self.handle_msg)\n", | |
" \n", | |
" @property\n", | |
" def shell(self):\n", | |
" return get_ipython()\n", | |
" \n", | |
" def add(self, a, b):\n", | |
" return a + b\n", | |
" \n", | |
" def mul(self, x, y):\n", | |
" return x * y\n", | |
" \n", | |
" def get_execution_count(self):\n", | |
" return self.shell.execution_count\n", | |
" \n", | |
" def handle_msg(self, msg):\n", | |
" data = msg['content']['data']\n", | |
" method = getattr(self, data['method'])\n", | |
" args = data.get('args', ())\n", | |
" kwargs = data.get('kwargs', {})\n", | |
" result = method(*args, **kwargs)\n", | |
" self.comm.send(dict(result=result, method=data['method']))\n", | |
"\n", | |
"get_ipython().comm_manager.register_target('rpc', RPCWidget)" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 42 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"%%javascript\n", | |
"var RPCWidget = function (comm) {\n", | |
" this.comm = comm;\n", | |
" // get the cell that was probably executed\n", | |
" // msg_id:cell mapping will make this possible without guessing\n", | |
" this.comm.on_msg($.proxy(this.handle_msg, this));\n", | |
" this.cell = IPython.notebook.get_cell(IPython.notebook.get_selected_index()-1);\n", | |
" this.callbacks = {\n", | |
" iopub : {\n", | |
" output : $.proxy(this.cell.output_area.handle_output, this.cell.output_area)\n", | |
" }\n", | |
" };\n", | |
" \n", | |
" this.target = 'rpc';\n", | |
"};\n", | |
"\n", | |
"RPCWidget.prototype.handle_msg = function (msg) {\n", | |
" this.cell.output_area.handle_output({\n", | |
" header : {\n", | |
" msg_type : 'stream',\n", | |
" msg_id : '',\n", | |
" },\n", | |
" parent_header : msg.parent_header,\n", | |
" content : {\n", | |
" name: 'stdout',\n", | |
" data: JSON.stringify(msg.content.data) + \"\\n\"\n", | |
" }\n", | |
" });\n", | |
"}\n", | |
"RPCWidget.prototype.add = function (a,b) {\n", | |
" this.comm.send({method : 'add', args : [a,b]}, this.callbacks);\n", | |
"}\n", | |
"RPCWidget.prototype.mul = function (a,b) {\n", | |
" this.comm.send({method : 'mul', args : [a,b]}, this.callbacks);\n", | |
"}\n", | |
"RPCWidget.prototype.get_ec = function () {\n", | |
" this.comm.send({method : 'get_execution_count'}, this.callbacks);\n", | |
"}\n", | |
"\n", | |
"\n", | |
"var comm = new IPython.Comm(IPython.utils.uuid(), 'rpc');\n", | |
"IPython.notebook.kernel.comm_manager.register_comm(comm);\n", | |
"comm.open();\n", | |
"var rpc = new RPCWidget(comm);\n", | |
"\n", | |
"rpc.add(5,3);\n", | |
"rpc.get_ec();\n", | |
"rpc.mul(6,6);\n", | |
"window.rpc = rpc;" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"javascript": [ | |
"var RPCWidget = function (comm) {\n", | |
" this.comm = comm;\n", | |
" // get the cell that was probably executed\n", | |
" // msg_id:cell mapping will make this possible without guessing\n", | |
" this.comm.on_msg($.proxy(this.handle_msg, this));\n", | |
" this.cell = IPython.notebook.get_cell(IPython.notebook.get_selected_index()-1);\n", | |
" this.callbacks = {\n", | |
" iopub : {\n", | |
" output : $.proxy(this.cell.output_area.handle_output, this.cell.output_area)\n", | |
" }\n", | |
" };\n", | |
" \n", | |
" this.target = 'rpc';\n", | |
"};\n", | |
"\n", | |
"RPCWidget.prototype.handle_msg = function (msg) {\n", | |
" this.cell.output_area.handle_output({\n", | |
" header : {\n", | |
" msg_type : 'stream',\n", | |
" msg_id : '',\n", | |
" },\n", | |
" parent_header : msg.parent_header,\n", | |
" content : {\n", | |
" name: 'stdout',\n", | |
" data: JSON.stringify(msg.content.data) + \"\\n\"\n", | |
" }\n", | |
" });\n", | |
"}\n", | |
"RPCWidget.prototype.add = function (a,b) {\n", | |
" this.comm.send({method : 'add', args : [a,b]}, this.callbacks);\n", | |
"}\n", | |
"RPCWidget.prototype.mul = function (a,b) {\n", | |
" this.comm.send({method : 'mul', args : [a,b]}, this.callbacks);\n", | |
"}\n", | |
"RPCWidget.prototype.get_ec = function () {\n", | |
" this.comm.send({method : 'get_execution_count'}, this.callbacks);\n", | |
"}\n", | |
"\n", | |
"\n", | |
"var comm = new IPython.Comm(IPython.utils.uuid(), 'rpc');\n", | |
"IPython.notebook.kernel.comm_manager.register_comm(comm);\n", | |
"comm.open();\n", | |
"var rpc = new RPCWidget(comm);\n", | |
"\n", | |
"rpc.add(5,3);\n", | |
"rpc.get_ec();\n", | |
"rpc.mul(6,6);\n", | |
"window.rpc = rpc;" | |
], | |
"metadata": {}, | |
"output_type": "display_data", | |
"text": [ | |
"<IPython.core.display.Javascript at 0x10c22d7d0>" | |
] | |
}, | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"{\"method\":\"add\",\"result\":8}\n" | |
] | |
}, | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"{\"method\":\"get_execution_count\",\"result\":44}\n" | |
] | |
}, | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"{\"method\":\"mul\",\"result\":36}\n" | |
] | |
}, | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"{\"method\":\"mul\",\"result\":5000}\n" | |
] | |
} | |
], | |
"prompt_number": 43 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"%%javascript\n", | |
"window.rpc.mul(10,500);" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"javascript": [ | |
"window.rpc.mul(10,500);" | |
], | |
"metadata": {}, | |
"output_type": "display_data", | |
"text": [ | |
"<IPython.core.display.Javascript at 0x10c22df10>" | |
] | |
} | |
], | |
"prompt_number": 44 | |
} | |
], | |
"metadata": {} | |
} | |
] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment