duffing-stuffing/duffing-response.ipynb
2019-05-21 23:02:54 +02:00

892 lines
73 KiB
Plaintext

{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"%matplotlib notebook\n",
"\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Frequency response\n",
"\n",
"Implicitly plot the function\n",
"\n",
"\\begin{align}\n",
"\\frac{\\gamma^2}{z^2} &= (\\omega^2 - \\alpha - \\frac{3}{4}\\beta z^2)^2 + (\\delta \\omega)^2 \\implies \\\\\n",
"\\frac{z}{\\gamma} &= \\frac{1}{\\sqrt{(\\omega^2 - \\alpha - \\frac{3}{4}\\beta z^2)^2 + (\\delta \\omega)^2}} \\implies \\\\\n",
"F &= G\n",
"\\end{align}\n"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"def left(gamma, z):\n",
" return z / gamma\n",
"\n",
"def right(alpha, beta, delta, z, omega):\n",
" denom = (omega**2 - alpha - (3/4)*beta*z**2)**2 + (delta*omega)**2\n",
" return 1/np.sqrt(denom)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"application/javascript": [
"/* Put everything inside the global mpl namespace */\n",
"window.mpl = {};\n",
"\n",
"\n",
"mpl.get_websocket_type = function() {\n",
" if (typeof(WebSocket) !== 'undefined') {\n",
" return WebSocket;\n",
" } else if (typeof(MozWebSocket) !== 'undefined') {\n",
" return MozWebSocket;\n",
" } else {\n",
" alert('Your browser does not have WebSocket support.' +\n",
" 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
" 'Firefox 4 and 5 are also supported but you ' +\n",
" 'have to enable WebSockets in about:config.');\n",
" };\n",
"}\n",
"\n",
"mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n",
" this.id = figure_id;\n",
"\n",
" this.ws = websocket;\n",
"\n",
" this.supports_binary = (this.ws.binaryType != undefined);\n",
"\n",
" if (!this.supports_binary) {\n",
" var warnings = document.getElementById(\"mpl-warnings\");\n",
" if (warnings) {\n",
" warnings.style.display = 'block';\n",
" warnings.textContent = (\n",
" \"This browser does not support binary websocket messages. \" +\n",
" \"Performance may be slow.\");\n",
" }\n",
" }\n",
"\n",
" this.imageObj = new Image();\n",
"\n",
" this.context = undefined;\n",
" this.message = undefined;\n",
" this.canvas = undefined;\n",
" this.rubberband_canvas = undefined;\n",
" this.rubberband_context = undefined;\n",
" this.format_dropdown = undefined;\n",
"\n",
" this.image_mode = 'full';\n",
"\n",
" this.root = $('<div/>');\n",
" this._root_extra_style(this.root)\n",
" this.root.attr('style', 'display: inline-block');\n",
"\n",
" $(parent_element).append(this.root);\n",
"\n",
" this._init_header(this);\n",
" this._init_canvas(this);\n",
" this._init_toolbar(this);\n",
"\n",
" var fig = this;\n",
"\n",
" this.waiting = false;\n",
"\n",
" this.ws.onopen = function () {\n",
" fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n",
" fig.send_message(\"send_image_mode\", {});\n",
" if (mpl.ratio != 1) {\n",
" fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n",
" }\n",
" fig.send_message(\"refresh\", {});\n",
" }\n",
"\n",
" this.imageObj.onload = function() {\n",
" if (fig.image_mode == 'full') {\n",
" // Full images could contain transparency (where diff images\n",
" // almost always do), so we need to clear the canvas so that\n",
" // there is no ghosting.\n",
" fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
" }\n",
" fig.context.drawImage(fig.imageObj, 0, 0);\n",
" };\n",
"\n",
" this.imageObj.onunload = function() {\n",
" fig.ws.close();\n",
" }\n",
"\n",
" this.ws.onmessage = this._make_on_message_function(this);\n",
"\n",
" this.ondownload = ondownload;\n",
"}\n",
"\n",
"mpl.figure.prototype._init_header = function() {\n",
" var titlebar = $(\n",
" '<div class=\"ui-dialog-titlebar ui-widget-header ui-corner-all ' +\n",
" 'ui-helper-clearfix\"/>');\n",
" var titletext = $(\n",
" '<div class=\"ui-dialog-title\" style=\"width: 100%; ' +\n",
" 'text-align: center; padding: 3px;\"/>');\n",
" titlebar.append(titletext)\n",
" this.root.append(titlebar);\n",
" this.header = titletext[0];\n",
"}\n",
"\n",
"\n",
"\n",
"mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n",
"\n",
"}\n",
"\n",
"\n",
"mpl.figure.prototype._root_extra_style = function(canvas_div) {\n",
"\n",
"}\n",
"\n",
"mpl.figure.prototype._init_canvas = function() {\n",
" var fig = this;\n",
"\n",
" var canvas_div = $('<div/>');\n",
"\n",
" canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n",
"\n",
" function canvas_keyboard_event(event) {\n",
" return fig.key_event(event, event['data']);\n",
" }\n",
"\n",
" canvas_div.keydown('key_press', canvas_keyboard_event);\n",
" canvas_div.keyup('key_release', canvas_keyboard_event);\n",
" this.canvas_div = canvas_div\n",
" this._canvas_extra_style(canvas_div)\n",
" this.root.append(canvas_div);\n",
"\n",
" var canvas = $('<canvas/>');\n",
" canvas.addClass('mpl-canvas');\n",
" canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n",
"\n",
" this.canvas = canvas[0];\n",
" this.context = canvas[0].getContext(\"2d\");\n",
"\n",
" var backingStore = this.context.backingStorePixelRatio ||\n",
"\tthis.context.webkitBackingStorePixelRatio ||\n",
"\tthis.context.mozBackingStorePixelRatio ||\n",
"\tthis.context.msBackingStorePixelRatio ||\n",
"\tthis.context.oBackingStorePixelRatio ||\n",
"\tthis.context.backingStorePixelRatio || 1;\n",
"\n",
" mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n",
"\n",
" var rubberband = $('<canvas/>');\n",
" rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n",
"\n",
" var pass_mouse_events = true;\n",
"\n",
" canvas_div.resizable({\n",
" start: function(event, ui) {\n",
" pass_mouse_events = false;\n",
" },\n",
" resize: function(event, ui) {\n",
" fig.request_resize(ui.size.width, ui.size.height);\n",
" },\n",
" stop: function(event, ui) {\n",
" pass_mouse_events = true;\n",
" fig.request_resize(ui.size.width, ui.size.height);\n",
" },\n",
" });\n",
"\n",
" function mouse_event_fn(event) {\n",
" if (pass_mouse_events)\n",
" return fig.mouse_event(event, event['data']);\n",
" }\n",
"\n",
" rubberband.mousedown('button_press', mouse_event_fn);\n",
" rubberband.mouseup('button_release', mouse_event_fn);\n",
" // Throttle sequential mouse events to 1 every 20ms.\n",
" rubberband.mousemove('motion_notify', mouse_event_fn);\n",
"\n",
" rubberband.mouseenter('figure_enter', mouse_event_fn);\n",
" rubberband.mouseleave('figure_leave', mouse_event_fn);\n",
"\n",
" canvas_div.on(\"wheel\", function (event) {\n",
" event = event.originalEvent;\n",
" event['data'] = 'scroll'\n",
" if (event.deltaY < 0) {\n",
" event.step = 1;\n",
" } else {\n",
" event.step = -1;\n",
" }\n",
" mouse_event_fn(event);\n",
" });\n",
"\n",
" canvas_div.append(canvas);\n",
" canvas_div.append(rubberband);\n",
"\n",
" this.rubberband = rubberband;\n",
" this.rubberband_canvas = rubberband[0];\n",
" this.rubberband_context = rubberband[0].getContext(\"2d\");\n",
" this.rubberband_context.strokeStyle = \"#000000\";\n",
"\n",
" this._resize_canvas = function(width, height) {\n",
" // Keep the size of the canvas, canvas container, and rubber band\n",
" // canvas in synch.\n",
" canvas_div.css('width', width)\n",
" canvas_div.css('height', height)\n",
"\n",
" canvas.attr('width', width * mpl.ratio);\n",
" canvas.attr('height', height * mpl.ratio);\n",
" canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n",
"\n",
" rubberband.attr('width', width);\n",
" rubberband.attr('height', height);\n",
" }\n",
"\n",
" // Set the figure to an initial 600x600px, this will subsequently be updated\n",
" // upon first draw.\n",
" this._resize_canvas(600, 600);\n",
"\n",
" // Disable right mouse context menu.\n",
" $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n",
" return false;\n",
" });\n",
"\n",
" function set_focus () {\n",
" canvas.focus();\n",
" canvas_div.focus();\n",
" }\n",
"\n",
" window.setTimeout(set_focus, 100);\n",
"}\n",
"\n",
"mpl.figure.prototype._init_toolbar = function() {\n",
" var fig = this;\n",
"\n",
" var nav_element = $('<div/>')\n",
" nav_element.attr('style', 'width: 100%');\n",
" this.root.append(nav_element);\n",
"\n",
" // Define a callback function for later on.\n",
" function toolbar_event(event) {\n",
" return fig.toolbar_button_onclick(event['data']);\n",
" }\n",
" function toolbar_mouse_event(event) {\n",
" return fig.toolbar_button_onmouseover(event['data']);\n",
" }\n",
"\n",
" for(var toolbar_ind in mpl.toolbar_items) {\n",
" var name = mpl.toolbar_items[toolbar_ind][0];\n",
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
" var image = mpl.toolbar_items[toolbar_ind][2];\n",
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
"\n",
" if (!name) {\n",
" // put a spacer in here.\n",
" continue;\n",
" }\n",
" var button = $('<button/>');\n",
" button.addClass('ui-button ui-widget ui-state-default ui-corner-all ' +\n",
" 'ui-button-icon-only');\n",
" button.attr('role', 'button');\n",
" button.attr('aria-disabled', 'false');\n",
" button.click(method_name, toolbar_event);\n",
" button.mouseover(tooltip, toolbar_mouse_event);\n",
"\n",
" var icon_img = $('<span/>');\n",
" icon_img.addClass('ui-button-icon-primary ui-icon');\n",
" icon_img.addClass(image);\n",
" icon_img.addClass('ui-corner-all');\n",
"\n",
" var tooltip_span = $('<span/>');\n",
" tooltip_span.addClass('ui-button-text');\n",
" tooltip_span.html(tooltip);\n",
"\n",
" button.append(icon_img);\n",
" button.append(tooltip_span);\n",
"\n",
" nav_element.append(button);\n",
" }\n",
"\n",
" var fmt_picker_span = $('<span/>');\n",
"\n",
" var fmt_picker = $('<select/>');\n",
" fmt_picker.addClass('mpl-toolbar-option ui-widget ui-widget-content');\n",
" fmt_picker_span.append(fmt_picker);\n",
" nav_element.append(fmt_picker_span);\n",
" this.format_dropdown = fmt_picker[0];\n",
"\n",
" for (var ind in mpl.extensions) {\n",
" var fmt = mpl.extensions[ind];\n",
" var option = $(\n",
" '<option/>', {selected: fmt === mpl.default_extension}).html(fmt);\n",
" fmt_picker.append(option)\n",
" }\n",
"\n",
" // Add hover states to the ui-buttons\n",
" $( \".ui-button\" ).hover(\n",
" function() { $(this).addClass(\"ui-state-hover\");},\n",
" function() { $(this).removeClass(\"ui-state-hover\");}\n",
" );\n",
"\n",
" var status_bar = $('<span class=\"mpl-message\"/>');\n",
" nav_element.append(status_bar);\n",
" this.message = status_bar[0];\n",
"}\n",
"\n",
"mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n",
" // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n",
" // which will in turn request a refresh of the image.\n",
" this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n",
"}\n",
"\n",
"mpl.figure.prototype.send_message = function(type, properties) {\n",
" properties['type'] = type;\n",
" properties['figure_id'] = this.id;\n",
" this.ws.send(JSON.stringify(properties));\n",
"}\n",
"\n",
"mpl.figure.prototype.send_draw_message = function() {\n",
" if (!this.waiting) {\n",
" this.waiting = true;\n",
" this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n",
" }\n",
"}\n",
"\n",
"\n",
"mpl.figure.prototype.handle_save = function(fig, msg) {\n",
" var format_dropdown = fig.format_dropdown;\n",
" var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n",
" fig.ondownload(fig, format);\n",
"}\n",
"\n",
"\n",
"mpl.figure.prototype.handle_resize = function(fig, msg) {\n",
" var size = msg['size'];\n",
" if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n",
" fig._resize_canvas(size[0], size[1]);\n",
" fig.send_message(\"refresh\", {});\n",
" };\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n",
" var x0 = msg['x0'] / mpl.ratio;\n",
" var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n",
" var x1 = msg['x1'] / mpl.ratio;\n",
" var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n",
" x0 = Math.floor(x0) + 0.5;\n",
" y0 = Math.floor(y0) + 0.5;\n",
" x1 = Math.floor(x1) + 0.5;\n",
" y1 = Math.floor(y1) + 0.5;\n",
" var min_x = Math.min(x0, x1);\n",
" var min_y = Math.min(y0, y1);\n",
" var width = Math.abs(x1 - x0);\n",
" var height = Math.abs(y1 - y0);\n",
"\n",
" fig.rubberband_context.clearRect(\n",
" 0, 0, fig.canvas.width, fig.canvas.height);\n",
"\n",
" fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n",
" // Updates the figure title.\n",
" fig.header.textContent = msg['label'];\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_cursor = function(fig, msg) {\n",
" var cursor = msg['cursor'];\n",
" switch(cursor)\n",
" {\n",
" case 0:\n",
" cursor = 'pointer';\n",
" break;\n",
" case 1:\n",
" cursor = 'default';\n",
" break;\n",
" case 2:\n",
" cursor = 'crosshair';\n",
" break;\n",
" case 3:\n",
" cursor = 'move';\n",
" break;\n",
" }\n",
" fig.rubberband_canvas.style.cursor = cursor;\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_message = function(fig, msg) {\n",
" fig.message.textContent = msg['message'];\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_draw = function(fig, msg) {\n",
" // Request the server to send over a new figure.\n",
" fig.send_draw_message();\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n",
" fig.image_mode = msg['mode'];\n",
"}\n",
"\n",
"mpl.figure.prototype.updated_canvas_event = function() {\n",
" // Called whenever the canvas gets updated.\n",
" this.send_message(\"ack\", {});\n",
"}\n",
"\n",
"// A function to construct a web socket function for onmessage handling.\n",
"// Called in the figure constructor.\n",
"mpl.figure.prototype._make_on_message_function = function(fig) {\n",
" return function socket_on_message(evt) {\n",
" if (evt.data instanceof Blob) {\n",
" /* FIXME: We get \"Resource interpreted as Image but\n",
" * transferred with MIME type text/plain:\" errors on\n",
" * Chrome. But how to set the MIME type? It doesn't seem\n",
" * to be part of the websocket stream */\n",
" evt.data.type = \"image/png\";\n",
"\n",
" /* Free the memory for the previous frames */\n",
" if (fig.imageObj.src) {\n",
" (window.URL || window.webkitURL).revokeObjectURL(\n",
" fig.imageObj.src);\n",
" }\n",
"\n",
" fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
" evt.data);\n",
" fig.updated_canvas_event();\n",
" fig.waiting = false;\n",
" return;\n",
" }\n",
" else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n",
" fig.imageObj.src = evt.data;\n",
" fig.updated_canvas_event();\n",
" fig.waiting = false;\n",
" return;\n",
" }\n",
"\n",
" var msg = JSON.parse(evt.data);\n",
" var msg_type = msg['type'];\n",
"\n",
" // Call the \"handle_{type}\" callback, which takes\n",
" // the figure and JSON message as its only arguments.\n",
" try {\n",
" var callback = fig[\"handle_\" + msg_type];\n",
" } catch (e) {\n",
" console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n",
" return;\n",
" }\n",
"\n",
" if (callback) {\n",
" try {\n",
" // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n",
" callback(fig, msg);\n",
" } catch (e) {\n",
" console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n",
" }\n",
" }\n",
" };\n",
"}\n",
"\n",
"// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n",
"mpl.findpos = function(e) {\n",
" //this section is from http://www.quirksmode.org/js/events_properties.html\n",
" var targ;\n",
" if (!e)\n",
" e = window.event;\n",
" if (e.target)\n",
" targ = e.target;\n",
" else if (e.srcElement)\n",
" targ = e.srcElement;\n",
" if (targ.nodeType == 3) // defeat Safari bug\n",
" targ = targ.parentNode;\n",
"\n",
" // jQuery normalizes the pageX and pageY\n",
" // pageX,Y are the mouse positions relative to the document\n",
" // offset() returns the position of the element relative to the document\n",
" var x = e.pageX - $(targ).offset().left;\n",
" var y = e.pageY - $(targ).offset().top;\n",
"\n",
" return {\"x\": x, \"y\": y};\n",
"};\n",
"\n",
"/*\n",
" * return a copy of an object with only non-object keys\n",
" * we need this to avoid circular references\n",
" * http://stackoverflow.com/a/24161582/3208463\n",
" */\n",
"function simpleKeys (original) {\n",
" return Object.keys(original).reduce(function (obj, key) {\n",
" if (typeof original[key] !== 'object')\n",
" obj[key] = original[key]\n",
" return obj;\n",
" }, {});\n",
"}\n",
"\n",
"mpl.figure.prototype.mouse_event = function(event, name) {\n",
" var canvas_pos = mpl.findpos(event)\n",
"\n",
" if (name === 'button_press')\n",
" {\n",
" this.canvas.focus();\n",
" this.canvas_div.focus();\n",
" }\n",
"\n",
" var x = canvas_pos.x * mpl.ratio;\n",
" var y = canvas_pos.y * mpl.ratio;\n",
"\n",
" this.send_message(name, {x: x, y: y, button: event.button,\n",
" step: event.step,\n",
" guiEvent: simpleKeys(event)});\n",
"\n",
" /* This prevents the web browser from automatically changing to\n",
" * the text insertion cursor when the button is pressed. We want\n",
" * to control all of the cursor setting manually through the\n",
" * 'cursor' event from matplotlib */\n",
" event.preventDefault();\n",
" return false;\n",
"}\n",
"\n",
"mpl.figure.prototype._key_event_extra = function(event, name) {\n",
" // Handle any extra behaviour associated with a key event\n",
"}\n",
"\n",
"mpl.figure.prototype.key_event = function(event, name) {\n",
"\n",
" // Prevent repeat events\n",
" if (name == 'key_press')\n",
" {\n",
" if (event.which === this._key)\n",
" return;\n",
" else\n",
" this._key = event.which;\n",
" }\n",
" if (name == 'key_release')\n",
" this._key = null;\n",
"\n",
" var value = '';\n",
" if (event.ctrlKey && event.which != 17)\n",
" value += \"ctrl+\";\n",
" if (event.altKey && event.which != 18)\n",
" value += \"alt+\";\n",
" if (event.shiftKey && event.which != 16)\n",
" value += \"shift+\";\n",
"\n",
" value += 'k';\n",
" value += event.which.toString();\n",
"\n",
" this._key_event_extra(event, name);\n",
"\n",
" this.send_message(name, {key: value,\n",
" guiEvent: simpleKeys(event)});\n",
" return false;\n",
"}\n",
"\n",
"mpl.figure.prototype.toolbar_button_onclick = function(name) {\n",
" if (name == 'download') {\n",
" this.handle_save(this, null);\n",
" } else {\n",
" this.send_message(\"toolbar_button\", {name: name});\n",
" }\n",
"};\n",
"\n",
"mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n",
" this.message.textContent = tooltip;\n",
"};\n",
"mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n",
"\n",
"mpl.extensions = [\"eps\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
"\n",
"mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n",
" // Create a \"websocket\"-like object which calls the given IPython comm\n",
" // object with the appropriate methods. Currently this is a non binary\n",
" // socket, so there is still some room for performance tuning.\n",
" var ws = {};\n",
"\n",
" ws.close = function() {\n",
" comm.close()\n",
" };\n",
" ws.send = function(m) {\n",
" //console.log('sending', m);\n",
" comm.send(m);\n",
" };\n",
" // Register the callback with on_msg.\n",
" comm.on_msg(function(msg) {\n",
" //console.log('receiving', msg['content']['data'], msg);\n",
" // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
" ws.onmessage(msg['content']['data'])\n",
" });\n",
" return ws;\n",
"}\n",
"\n",
"mpl.mpl_figure_comm = function(comm, msg) {\n",
" // This is the function which gets called when the mpl process\n",
" // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
"\n",
" var id = msg.content.data.id;\n",
" // Get hold of the div created by the display call when the Comm\n",
" // socket was opened in Python.\n",
" var element = $(\"#\" + id);\n",
" var ws_proxy = comm_websocket_adapter(comm)\n",
"\n",
" function ondownload(figure, format) {\n",
" window.open(figure.imageObj.src);\n",
" }\n",
"\n",
" var fig = new mpl.figure(id, ws_proxy,\n",
" ondownload,\n",
" element.get(0));\n",
"\n",
" // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n",
" // web socket which is closed, not our websocket->open comm proxy.\n",
" ws_proxy.onopen();\n",
"\n",
" fig.parent_element = element.get(0);\n",
" fig.cell_info = mpl.find_output_cell(\"<div id='\" + id + \"'></div>\");\n",
" if (!fig.cell_info) {\n",
" console.error(\"Failed to find cell for figure\", id, fig);\n",
" return;\n",
" }\n",
"\n",
" var output_index = fig.cell_info[2]\n",
" var cell = fig.cell_info[0];\n",
"\n",
"};\n",
"\n",
"mpl.figure.prototype.handle_close = function(fig, msg) {\n",
" var width = fig.canvas.width/mpl.ratio\n",
" fig.root.unbind('remove')\n",
"\n",
" // Update the output cell to use the data from the current canvas.\n",
" fig.push_to_output();\n",
" var dataURL = fig.canvas.toDataURL();\n",
" // Re-enable the keyboard manager in IPython - without this line, in FF,\n",
" // the notebook keyboard shortcuts fail.\n",
" IPython.keyboard_manager.enable()\n",
" $(fig.parent_element).html('<img src=\"' + dataURL + '\" width=\"' + width + '\">');\n",
" fig.close_ws(fig, msg);\n",
"}\n",
"\n",
"mpl.figure.prototype.close_ws = function(fig, msg){\n",
" fig.send_message('closing', msg);\n",
" // fig.ws.close()\n",
"}\n",
"\n",
"mpl.figure.prototype.push_to_output = function(remove_interactive) {\n",
" // Turn the data on the canvas into data in the output cell.\n",
" var width = this.canvas.width/mpl.ratio\n",
" var dataURL = this.canvas.toDataURL();\n",
" this.cell_info[1]['text/html'] = '<img src=\"' + dataURL + '\" width=\"' + width + '\">';\n",
"}\n",
"\n",
"mpl.figure.prototype.updated_canvas_event = function() {\n",
" // Tell IPython that the notebook contents must change.\n",
" IPython.notebook.set_dirty(true);\n",
" this.send_message(\"ack\", {});\n",
" var fig = this;\n",
" // Wait a second, then push the new image to the DOM so\n",
" // that it is saved nicely (might be nice to debounce this).\n",
" setTimeout(function () { fig.push_to_output() }, 1000);\n",
"}\n",
"\n",
"mpl.figure.prototype._init_toolbar = function() {\n",
" var fig = this;\n",
"\n",
" var nav_element = $('<div/>')\n",
" nav_element.attr('style', 'width: 100%');\n",
" this.root.append(nav_element);\n",
"\n",
" // Define a callback function for later on.\n",
" function toolbar_event(event) {\n",
" return fig.toolbar_button_onclick(event['data']);\n",
" }\n",
" function toolbar_mouse_event(event) {\n",
" return fig.toolbar_button_onmouseover(event['data']);\n",
" }\n",
"\n",
" for(var toolbar_ind in mpl.toolbar_items){\n",
" var name = mpl.toolbar_items[toolbar_ind][0];\n",
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
" var image = mpl.toolbar_items[toolbar_ind][2];\n",
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
"\n",
" if (!name) { continue; };\n",
"\n",
" var button = $('<button class=\"btn btn-default\" href=\"#\" title=\"' + name + '\"><i class=\"fa ' + image + ' fa-lg\"></i></button>');\n",
" button.click(method_name, toolbar_event);\n",
" button.mouseover(tooltip, toolbar_mouse_event);\n",
" nav_element.append(button);\n",
" }\n",
"\n",
" // Add the status bar.\n",
" var status_bar = $('<span class=\"mpl-message\" style=\"text-align:right; float: right;\"/>');\n",
" nav_element.append(status_bar);\n",
" this.message = status_bar[0];\n",
"\n",
" // Add the close button to the window.\n",
" var buttongrp = $('<div class=\"btn-group inline pull-right\"></div>');\n",
" var button = $('<button class=\"btn btn-mini btn-primary\" href=\"#\" title=\"Stop Interaction\"><i class=\"fa fa-power-off icon-remove icon-large\"></i></button>');\n",
" button.click(function (evt) { fig.handle_close(fig, {}); } );\n",
" button.mouseover('Stop Interaction', toolbar_mouse_event);\n",
" buttongrp.append(button);\n",
" var titlebar = this.root.find($('.ui-dialog-titlebar'));\n",
" titlebar.prepend(buttongrp);\n",
"}\n",
"\n",
"mpl.figure.prototype._root_extra_style = function(el){\n",
" var fig = this\n",
" el.on(\"remove\", function(){\n",
"\tfig.close_ws(fig, {});\n",
" });\n",
"}\n",
"\n",
"mpl.figure.prototype._canvas_extra_style = function(el){\n",
" // this is important to make the div 'focusable\n",
" el.attr('tabindex', 0)\n",
" // reach out to IPython and tell the keyboard manager to turn it's self\n",
" // off when our div gets focus\n",
"\n",
" // location in version 3\n",
" if (IPython.notebook.keyboard_manager) {\n",
" IPython.notebook.keyboard_manager.register_events(el);\n",
" }\n",
" else {\n",
" // location in version 2\n",
" IPython.keyboard_manager.register_events(el);\n",
" }\n",
"\n",
"}\n",
"\n",
"mpl.figure.prototype._key_event_extra = function(event, name) {\n",
" var manager = IPython.notebook.keyboard_manager;\n",
" if (!manager)\n",
" manager = IPython.keyboard_manager;\n",
"\n",
" // Check for shift+enter\n",
" if (event.shiftKey && event.which == 13) {\n",
" this.canvas_div.blur();\n",
" event.shiftKey = false;\n",
" // Send a \"J\" for go to next cell\n",
" event.which = 74;\n",
" event.keyCode = 74;\n",
" manager.command_mode();\n",
" manager.handle_keydown(event);\n",
" }\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_save = function(fig, msg) {\n",
" fig.ondownload(fig, null);\n",
"}\n",
"\n",
"\n",
"mpl.find_output_cell = function(html_output) {\n",
" // Return the cell and output element which can be found *uniquely* in the notebook.\n",
" // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n",
" // IPython event is triggered only after the cells have been serialised, which for\n",
" // our purposes (turning an active figure into a static one), is too late.\n",
" var cells = IPython.notebook.get_cells();\n",
" var ncells = cells.length;\n",
" for (var i=0; i<ncells; i++) {\n",
" var cell = cells[i];\n",
" if (cell.cell_type === 'code'){\n",
" for (var j=0; j<cell.output_area.outputs.length; j++) {\n",
" var data = cell.output_area.outputs[j];\n",
" if (data.data) {\n",
" // IPython >= 3 moved mimebundle to data attribute of output\n",
" data = data.data;\n",
" }\n",
" if (data['text/html'] == html_output) {\n",
" return [cell, data, j];\n",
" }\n",
" }\n",
" }\n",
" }\n",
"}\n",
"\n",
"// Register the function which deals with the matplotlib target/channel.\n",
"// The kernel may be null if the page has been refreshed.\n",
"if (IPython.notebook.kernel != null) {\n",
" IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n",
"}\n"
],
"text/plain": [
"<IPython.core.display.Javascript object>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"<img src=\"data:image/png;base64,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\" width=\"640\">"
],
"text/plain": [
"<IPython.core.display.HTML object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"gamma = 1\n",
"alpha = 1\n",
"beta = 0.01\n",
"delta = 0.1\n",
"\n",
"z, omega = np.meshgrid(\n",
" np.linspace(0, 15, 100),\n",
" np.linspace(0, 2.5, 100)\n",
")\n",
"\n",
"for beta in (-3e-3, 0.0, 1e-2, 4e-2):\n",
" F = left(gamma, z)\n",
" G = right(alpha, beta, delta, z, omega)\n",
" plt.contour(omega, z, (F-G), [0])\n",
" plt.xlabel(\"$\\omega$\")\n",
" plt.ylabel(\"$z/\\gamma$\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"anaconda-cloud": {},
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.2"
}
},
"nbformat": 4,
"nbformat_minor": 1
}