Skip to content

Instantly share code, notes, and snippets.

@jackparmer
Created January 23, 2015 01: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 jackparmer/239c00f721097deb11fd to your computer and use it in GitHub Desktop.
Save jackparmer/239c00f721097deb11fd to your computer and use it in GitHub Desktop.
widgets and 3d ipython notebook
{
"metadata": {
"name": "",
"signature": "sha256:f689918b86e24f125bcb26a630675658126c56a7dc1db1c910a53027fefcee84"
},
"nbformat": 3,
"nbformat_minor": 0,
"worksheets": [
{
"cells": [
{
"cell_type": "heading",
"level": 1,
"metadata": {},
"source": [
"Widgets with 3d Plotly graphs"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"from IPython.display import Image\n",
"Image(url='http://i.imgur.com/PzOz1qc.gif')"
],
"language": "python",
"metadata": {},
"outputs": [
{
"html": [
"<img src=\"http://i.imgur.com/PzOz1qc.gif\"/>"
],
"metadata": {},
"output_type": "pyout",
"prompt_number": 5,
"text": [
"<IPython.core.display.Image at 0x109350b90>"
]
}
],
"prompt_number": 5
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"from plotly.widgets import GraphWidget\n",
"\n",
"from IPython.html import widgets \n",
"from IPython.display import display, clear_output\n",
"import numpy as np"
],
"language": "python",
"metadata": {},
"outputs": [
{
"javascript": [
"window.genUID = function() {\n",
" return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {\n",
" var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);\n",
" return v.toString(16);\n",
" });\n",
"};\n",
"\n",
"require([\"widgets/js/widget\"], function(WidgetManager){\n",
"\n",
" var GraphView = IPython.DOMWidgetView.extend({\n",
" render: function(){\n",
" var that = this;\n",
"\n",
" var graphId = window.genUID();\n",
" var loadingId = 'loading-'+graphId;\n",
"\n",
"\n",
" var _graph_url = that.model.get('_graph_url');\n",
"\n",
" // variable plotlyDomain in the case of enterprise\n",
" var url_parts = _graph_url.split('/');\n",
" var plotlyDomain = url_parts[0] + '//' + url_parts[2];\n",
"\n",
" if(!('plotlyDomains' in window)){\n",
" window.plotlyDomains = {};\n",
" }\n",
" window.plotlyDomains[graphId] = plotlyDomain;\n",
"\n",
" // Place IFrame in output cell div `$el`\n",
" that.$el.css('width', '100%');\n",
" that.$graph = $(['<iframe id=\"'+graphId+'\"',\n",
" 'src=\"'+_graph_url+'.embed\"',\n",
" 'seamless',\n",
" 'style=\"border: none;\"',\n",
" 'width=\"100%\"',\n",
" 'height=\"600\">',\n",
" '</iframe>'].join(' '));\n",
" that.$graph.appendTo(that.$el);\n",
"\n",
" that.$loading = $('<div id=\"'+loadingId+'\">Initializing...</div>')\n",
" .appendTo(that.$el);\n",
"\n",
" // initialize communication with the iframe\n",
" if(!('pingers' in window)){\n",
" window.pingers = {};\n",
" }\n",
"\n",
" window.pingers[graphId] = setInterval(function() {\n",
" that.graphContentWindow = $('#'+graphId)[0].contentWindow;\n",
" that.graphContentWindow.postMessage({task: 'ping'}, plotlyDomain);\n",
" }, 200);\n",
"\n",
" // Assign a message listener to the 'message' events\n",
" // from iframe's postMessage protocol.\n",
" // Filter the messages by iframe src so that the right message\n",
" // gets passed to the right widget\n",
" if(!('messageListeners' in window)){\n",
" window.messageListeners = {};\n",
" }\n",
"\n",
" window.messageListeners[graphId] = function(e) {\n",
" if(_graph_url.indexOf(e.origin)>-1) {\n",
" var frame = document.getElementById(graphId);\n",
"\n",
" if(frame === null){\n",
" // frame doesn't exist in the dom anymore, clean up it's old event listener\n",
" window.removeEventListener('message', window.messageListeners[graphId]);\n",
" clearInterval(window.pingers[graphId]);\n",
" } else if(frame.contentWindow === e.source) {\n",
" // TODO: Stop event propagation, so each frame doesn't listen and filter\n",
" var frameContentWindow = $('#'+graphId)[0].contentWindow;\n",
" var message = e.data;\n",
"\n",
" if('pong' in message && message.pong) {\n",
" $('#loading-'+graphId).hide();\n",
" clearInterval(window.pingers[graphId]);\n",
" that.send({event: 'pong', graphId: graphId});\n",
" } else if (message.type==='hover' ||\n",
" message.type==='zoom' ||\n",
" message.type==='click' ||\n",
" message.type==='unhover') {\n",
"\n",
" // click and hover events contain all of the data in the traces,\n",
" // which can be a very large object and may take a ton of time\n",
" // to pass to the python backend. Strip out the data, and require\n",
" // the user to call get_figure if they need trace information\n",
" if(message.type !== 'zoom') {\n",
" for(var i in message.points) {\n",
" delete message.points[i].data;\n",
" }\n",
" }\n",
" that.send({event: message.type, message: message, graphId: graphId});\n",
" }\n",
" }\n",
" }\n",
" };\n",
"\n",
" window.removeEventListener('message', window.messageListeners[graphId]);\n",
" window.addEventListener('message', window.messageListeners[graphId]);\n",
"\n",
" },\n",
"\n",
" update: function() {\n",
" // Listen for messages from the graph widget in python\n",
" var jmessage = this.model.get('_message');\n",
" var message = JSON.parse(jmessage);\n",
"\n",
" // check for duplicate messages\n",
" if(!('messageIds' in window)){\n",
" window.messageIds = {};\n",
" }\n",
"\n",
" if(!(message.uid in window.messageIds)){\n",
" // message hasn't been received yet, do stuff\n",
" window.messageIds[message.uid] = true;\n",
"\n",
" var plot = $('#'+message.graphId)[0].contentWindow;\n",
" plot.postMessage(message, window.plotlyDomains[message.graphId]);\n",
" }\n",
"\n",
" return GraphView.__super__.update.apply(this);\n",
" }\n",
" });\n",
"\n",
" // Register the GraphView with the widget manager.\n",
" WidgetManager.register_widget_view('GraphView', GraphView);\n",
"});\n",
"\n",
"//@ sourceURL=graphWidget.js\n"
],
"metadata": {},
"output_type": "display_data",
"text": [
"<IPython.core.display.Javascript at 0x109350910>"
]
}
],
"prompt_number": 2
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"g = GraphWidget('https://plot.ly/~jackp/2590')\n",
"x = y = np.arange(-5,5,0.1)\n",
"yt = x[:,np.newaxis]\n",
"\n",
"class z_data:\n",
" def __init__(self):\n",
" self.z = np.cos(x*yt)+np.sin(x*yt)\n",
" \n",
" def on_z_change(self, name, old_value, new_value):\n",
" self.z = np.cos(x*yt*(new_value+1)/100)+np.sin(x*yt*(new_value+1/100))\n",
" self.replot()\n",
" \n",
" def replot(self):\n",
" g.restyle({ 'z': [self.z] })\n",
"\n",
"z_slider = widgets.FloatSliderWidget(min=0,max=3,value=1,step=0.05)\n",
"z_slider.description = 'Frequency'\n",
"z_slider.value = 1\n",
"\n",
"z_state = z_data()\n",
"z_slider.on_trait_change(z_state.on_z_change, 'value')"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 3
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"display(z_slider)\n",
"display(g)"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 4
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# CSS styling within IPython notebook - feel free to re-use\n",
"from IPython.core.display import HTML\n",
"import urllib2\n",
"\n",
"HTML(urllib2.urlopen('http://bit.ly/1Bf5Hft').read())"
],
"language": "python",
"metadata": {},
"outputs": [
{
"html": [
"<style>\n",
"\n",
"html {\n",
" font-size: 62.5% !important; }\n",
"body {\n",
" font-size: 1.5em !important; /* currently ems cause chrome bug misinterpreting rems on body element */\n",
" line-height: 1.6 !important;\n",
" font-weight: 400 !important;\n",
" font-family: \"Raleway\", \"HelveticaNeue\", \"Helvetica Neue\", Helvetica, Arial, sans-serif !important;\n",
" color: #222 !important; }\n",
"\n",
"div{ border-radius: 0px !important; }\n",
"div.CodeMirror-sizer{ background: rgb(244, 244, 248) !important; }\n",
"div.input_area{ background: rgb(244, 244, 248) !important; }\n",
"\n",
"div.out_prompt_overlay:hover{ background: rgb(244, 244, 248) !important; }\n",
"div.input_prompt:hover{ background: rgb(244, 244, 248) !important; }\n",
"\n",
"h1, h2, h3, h4, h5, h6 {\n",
" color: #333 !important;\n",
" margin-top: 0 !important;\n",
" margin-bottom: 2rem !important;\n",
" font-weight: 300 !important; }\n",
"h1 { font-size: 4.0rem !important; line-height: 1.2 !important; letter-spacing: -.1rem !important;}\n",
"h2 { font-size: 3.6rem !important; line-height: 1.25 !important; letter-spacing: -.1rem !important; }\n",
"h3 { font-size: 3.0rem !important; line-height: 1.3 !important; letter-spacing: -.1rem !important; }\n",
"h4 { font-size: 2.4rem !important; line-height: 1.35 !important; letter-spacing: -.08rem !important; }\n",
"h5 { font-size: 1.8rem !important; line-height: 1.5 !important; letter-spacing: -.05rem !important; }\n",
"h6 { font-size: 1.5rem !important; line-height: 1.6 !important; letter-spacing: 0 !important; }\n",
"\n",
"@media (min-width: 550px) {\n",
" h1 { font-size: 5.0rem !important; }\n",
" h2 { font-size: 4.2rem !important; }\n",
" h3 { font-size: 3.6rem !important; }\n",
" h4 { font-size: 3.0rem !important; }\n",
" h5 { font-size: 2.4rem !important; }\n",
" h6 { font-size: 1.5rem !important; }\n",
"}\n",
"\n",
"p {\n",
" margin-top: 0 !important; }\n",
" \n",
"a {\n",
" color: #1EAEDB !important; }\n",
"a:hover {\n",
" color: #0FA0CE !important; }\n",
" \n",
"code {\n",
" padding: .2rem .5rem !important;\n",
" margin: 0 .2rem !important;\n",
" font-size: 90% !important;\n",
" white-space: nowrap !important;\n",
" background: #F1F1F1 !important;\n",
" border: 1px solid #E1E1E1 !important;\n",
" border-radius: 4px !important; }\n",
"pre > code {\n",
" display: block !important;\n",
" padding: 1rem 1.5rem !important;\n",
" white-space: pre !important; }\n",
" \n",
"button{ border-radius: 0px !important; }\n",
".navbar-inner{ background-image: none !important; }\n",
"select, textarea{ border-radius: 0px !important; }\n",
"\n",
"</style>"
],
"metadata": {},
"output_type": "pyout",
"prompt_number": 1,
"text": [
"<IPython.core.display.HTML at 0x103955090>"
]
}
],
"prompt_number": 1
}
],
"metadata": {}
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment