Created
June 21, 2015 12:18
-
-
Save martindurant/1d9c78ef7a8263c27977 to your computer and use it in GitHub Desktop.
interactive mandelbrot-julia
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
{ | |
"cells": [ | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"%load_ext Cython\n", | |
"%matplotlib inline\n", | |
"from IPython.html import widgets # Widget definitions\n", | |
"from IPython.display import display, Javascript # Used to display widgets in the notebook\n", | |
"from IPython.utils.traitlets import Unicode # Used to declare attributes of our widget\n", | |
"from IPython.html.widgets import interact, interactive, fixed\n", | |
"from mpld3 import plugins, utils\n", | |
"import mpld3" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"%%cython\n", | |
"import numpy as N\n", | |
"cimport numpy as N # this Cython-side numpy import is needed\n", | |
" # to declare the types and dimensions of arrays\n", | |
"\n", | |
"def mandel_cython(x0, x1, y0, y1, int n=400,int maxi=512):\n", | |
" cdef N.ndarray[double,ndim=1] xs = N.linspace(x0,x1,n)\n", | |
" cdef N.ndarray[double,ndim=1] ys = N.linspace(y0,y1,n)\n", | |
" cdef N.ndarray[int,ndim=2] escape = N.empty((n,n),'int32')\n", | |
" cdef int i,j,it,esc\n", | |
" cdef double complex z,c\n", | |
"\n", | |
" for i in range(n):\n", | |
" for j in range(n):\n", | |
" z = 0 + 0j\n", | |
" c = xs[i] + 1j * ys[j]\n", | |
"\n", | |
" esc = maxi\n", | |
" for it in range(maxi):\n", | |
" z = z*z + c\n", | |
" if z.real*z.real + z.imag*z.imag > 4:\n", | |
" esc = it\n", | |
" break\n", | |
"\n", | |
" escape[j,i] = esc\n", | |
"\n", | |
" return escape\n", | |
"\n", | |
"def julia_cython(double complex c, int n=400, int maxi=512):\n", | |
" cdef N.ndarray[double,ndim=1] xs = N.linspace(-1.0, 1.0, n)\n", | |
" cdef N.ndarray[double,ndim=1] ys = N.linspace(-1.0, 1.0, n)\n", | |
" cdef N.ndarray[int,ndim=2] escape = N.empty((n,n),'int32')\n", | |
" cdef int i,j,it,esc\n", | |
" cdef double complex z\n", | |
"\n", | |
" for i in range(n):\n", | |
" for j in range(n):\n", | |
" z = xs[i] + 1j * ys[j]\n", | |
"\n", | |
" esc = maxi\n", | |
" for it in range(maxi):\n", | |
" z = z*z + c\n", | |
" if z.real*z.real + z.imag*z.imag > 4:\n", | |
" esc = it\n", | |
" break\n", | |
"\n", | |
" escape[j,i] = esc\n", | |
"\n", | |
" return escape" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"x0, x1 = -2.0, 1.0\n", | |
"y0, y1 = -1.0, 1.0\n", | |
"im = mandel_cython(x0, x1, y0, y1, n=1200)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"# widget sync'd python side\n", | |
"class GraphWidget(widgets.DOMWidget):\n", | |
" _view_name = Unicode('GraphView', sync=True)\n", | |
" description = 'x' \n", | |
" value = Unicode(sync=True)\n", | |
" js = \"\"\"require([\"widgets/js/widget\", \"widgets/js/manager\"], function(widget, manager){\n", | |
" // is based on the DatePickerView\n", | |
" var GraphView = widget.DOMWidgetView.extend({\n", | |
" render: function() {\n", | |
" //@ attr id : this is the id we reach to in the dragended function in the DragPlugin\n", | |
" this.$text = $('<input />')\n", | |
" .attr('type', 'text')\n", | |
" .attr('id', 'feedback_widget') \n", | |
" .appendTo(this.$el);\n", | |
" },\n", | |
" \n", | |
" update: function() {\n", | |
" this.$text.val(this.model.get('value'));\n", | |
" return GraphView.__super__.update.apply(this);\n", | |
" },\n", | |
" \n", | |
" events: {\"change\": \"handle_change\"},\n", | |
" \n", | |
" handle_change: function(event) {\n", | |
" this.model.set('value', this.$text.val());\n", | |
" this.touch();\n", | |
" },\n", | |
" });\n", | |
" \n", | |
" manager.WidgetManager.register_widget_view('GraphView', GraphView);\n", | |
"});\"\"\"\n", | |
" def cascase_events(self):\n", | |
" for dep in self.dependents:\n", | |
" display(Javascript(\"\"\"$('#{}').val(\"{}\").trigger(\"change\").hide();\"\"\".format(dep.ref_name, self.value)))\n", | |
"\n", | |
" def __init__(self, *args, **kwarg):\n", | |
" if kwarg.get('widgen_name'):\n", | |
" self._view_name = kwarg.get('widgen_name')\n", | |
" self.js = self.js.replace('GraphView', kwarg.pop('widgen_name'))\n", | |
" self.ref_name = self._view_name + \"_id\"\n", | |
" self.js = self.js.replace('feedback_widget', self.ref_name)\n", | |
" self.dependents = [] # other GraphWidget-like objects to cascade events to\n", | |
" self.on_trait_change(self.cascase_events)\n", | |
" display(Javascript(self.js))\n", | |
" widgets.DOMWidget.__init__(self, *args, **kwarg)\n", | |
" \n", | |
"class Selector(plugins.PluginBase): # inherit from PluginBase\n", | |
" piece = \"$('#feedback_widget').hide(); \"\n", | |
" JAVASCRIPT = r\"\"\"\n", | |
"mpld3.register_plugin(\"selector\", Selector);\n", | |
"Selector.prototype = Object.create(mpld3.Plugin.prototype);\n", | |
"Selector.prototype.constructor = Selector;\n", | |
"Selector.prototype.requiredProps = [\"id\"];\n", | |
"Selector.prototype.defaultProps = {}\n", | |
"function Selector(fig, props){\n", | |
" mpld3.Plugin.call(this, fig, props);\n", | |
" mpld3.insert_css(\"#\" + fig.figid + \" path.dragging\",\n", | |
" {\"fill-opacity\": \"1.0 !important\",\n", | |
" \"stroke-opacity\": \"1.0 !important\"});\n", | |
"};$\n", | |
"\n", | |
"Selector.prototype.draw = function(){\n", | |
" var obj = mpld3.get_element(this.props.id);\n", | |
"\n", | |
" var drag = d3.behavior.drag()\n", | |
" .origin(function(d) { return {x:obj.ax.x(d[0]),\n", | |
" y:obj.ax.y(d[1])}; })\n", | |
" .on(\"dragstart\", dragstarted)\n", | |
" .on(\"drag\", dragged)\n", | |
" .on(\"dragend\", dragended);\n", | |
"\n", | |
" obj.elements()\n", | |
" .data(obj.offsets)\n", | |
" .style(\"cursor\", \"default\")\n", | |
" .call(drag);\n", | |
"\n", | |
" function dragstarted(d) {\n", | |
" d3.event.sourceEvent.stopPropagation();\n", | |
" d3.select(this).classed(\"dragging\", true);\n", | |
" }\n", | |
"\n", | |
" function dragged(d, i) {\n", | |
" d[0] = obj.ax.x.invert(d3.event.x);\n", | |
" d[1] = obj.ax.y.invert(d3.event.y);\n", | |
" d3.select(this)\n", | |
" .attr(\"transform\", \"translate(\" + [d3.event.x,d3.event.y] + \")\");\n", | |
" }\n", | |
"\n", | |
" function dragended(d,i) {\n", | |
" d3.select(this).classed(\"dragging\", false);\n", | |
" // feed back the new position to python, triggering 'change' on the widget\n", | |
" $('#feedback_widget').val(\"(\" + i + \",\" + d[0] + \",\" + d[1] + \")\").trigger(\"change\");\n", | |
" }\n", | |
"}\"\"\"\n", | |
"\n", | |
" def __init__(self, points, ref=None):\n", | |
" if ref:\n", | |
" self.JAVASCRIPT = self.JAVASCRIPT.replace('feedback_widget', ref)\n", | |
" if isinstance(points, mpl.lines.Line2D):\n", | |
" suffix = \"pts\"\n", | |
" else:\n", | |
" suffix = None\n", | |
"\n", | |
" self.dict_ = {\"type\": \"selector\",\n", | |
" \"id\": utils.get_id(points, suffix)}" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"w = GraphWidget(widgen_name='GraphView01')\n", | |
"w.value = \"(0,0,0)\"" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false, | |
"scrolled": false | |
}, | |
"outputs": [], | |
"source": [ | |
"\n", | |
"def f(x):\n", | |
" x = eval(x)\n", | |
" fig, ax = subplots(figsize=(9, 6))\n", | |
" ax.imshow(im, vmax=20, cmap=cm.hot_r, interpolation='nearest',\n", | |
" extent=[x0, x1, y0, y1])\n", | |
" plugins.connect(fig, plugins.MousePosition())\n", | |
" pts = ax.plot(x[1], x[2], 'go', alpha=0.5)\n", | |
" sel = Selector(pts[0], ref=w.ref_name)\n", | |
" plugins.connect(fig, sel)\n", | |
" display(mpld3.display(fig))\n", | |
"\n", | |
"interact(f, x=w)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"w2 = GraphWidget(widgen_name='GraphView02')\n", | |
"w.dependents.append(w2)\n", | |
"w2.value = \"(0,0,0)\"\n", | |
"\n", | |
"def julia(x):\n", | |
" x = eval(w2.value)\n", | |
" fig, ax = subplots(figsize=(9, 6))\n", | |
" im = julia_cython(x[1] + 1j*x[2], 1200, 20)\n", | |
" ax.imshow(im, vmax=20, cmap=cm.hot_r, interpolation='nearest',\n", | |
" extent=[-1, 1, -1, 1])\n", | |
" plugins.connect(fig, plugins.MousePosition())\n", | |
" display(mpld3.display(fig)) \n", | |
" \n", | |
"interact(julia, x=w2)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [] | |
} | |
], | |
"metadata": { | |
"kernelspec": { | |
"display_name": "Python 2", | |
"language": "python", | |
"name": "python2" | |
}, | |
"language_info": { | |
"codemirror_mode": { | |
"name": "ipython", | |
"version": 2 | |
}, | |
"file_extension": ".py", | |
"mimetype": "text/x-python", | |
"name": "python", | |
"nbconvert_exporter": "python", | |
"pygments_lexer": "ipython2", | |
"version": "2.7.10" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 0 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment