Skip to content

Instantly share code, notes, and snippets.

@martindurant
Created June 21, 2015 12:18
Show Gist options
  • Save martindurant/1d9c78ef7a8263c27977 to your computer and use it in GitHub Desktop.
Save martindurant/1d9c78ef7a8263c27977 to your computer and use it in GitHub Desktop.
interactive mandelbrot-julia
{
"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