-
-
Save ngoldbaum/7457006 to your computer and use it in GitHub Desktop.
This file contains hidden or 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