diff options
Diffstat (limited to 'python')
| -rw-r--r-- | python/exploration/curve_trades.py | 7 | ||||
| -rw-r--r-- | python/notebooks/Curve Trades.ipynb | 5948 |
2 files changed, 5894 insertions, 61 deletions
diff --git a/python/exploration/curve_trades.py b/python/exploration/curve_trades.py index 7a7d29c2..963aac27 100644 --- a/python/exploration/curve_trades.py +++ b/python/exploration/curve_trades.py @@ -82,10 +82,11 @@ def on_the_run_theta(index='IG', rolling=6): def curve_returns(index='IG', rolling=6): ## look at returns otr = on_the_run(index) - df = index_returns(index= index, series=list(range(otr - rolling, otr + 1)), + df = index_returns(index=index, series=list(range(otr - rolling, otr + 1)), tenor=['3yr', '5yr', '7yr', '10yr']) ## on-the-run returns - returns = df.price_return.unstack(-1).dropna().groupby(level='date').nth(-1) + df = df.reset_index().set_index(['date', 'series', 'tenor']) + returns = df.price_return.dropna().unstack(-1).groupby(level='date').nth(-1) strategies_return = pd.DataFrame( {'5-10': 1.78 * returns['5yr'] - returns['10yr'], @@ -114,6 +115,7 @@ def cross_series_curve(index='IG', rolling=6): df = index_returns(index= index, series=list(range(otr - rolling, otr + 1)), tenor=['3yr', '5yr', '7yr', '10yr']) ## look cross series - 3y to 5y + df = df.reset_index().set_index(['date', 'index', 'tenor', 'series']) returns1 = df.xs(['5yr', index], level = ['tenor','index']).price_return.unstack(-1) price_diff = pd.DataFrame() for ind in list(range(otr - 2, otr + 1)): @@ -166,6 +168,7 @@ def curve_model(tenor_1='5yr', tenor_2='10yr'): return df, ols_model def curve_model_results(df, model): + df = df.dropna() prstd_ols, df['down_2_stdev'], df['up_2_stdev'] = wls_prediction_std(model) #dr/dspread = exp(k) + spread_coeff * duration ^ dur_coeff * spread ^ (spread_coeff-1) cols = ['ratio', 'closespread', 'down_2_stdev', 'up_2_stdev'] diff --git a/python/notebooks/Curve Trades.ipynb b/python/notebooks/Curve Trades.ipynb index 501c9876..0c74fa21 100644 --- a/python/notebooks/Curve Trades.ipynb +++ b/python/notebooks/Curve Trades.ipynb @@ -2,8 +2,10 @@ "cells": [ { "cell_type": "code", - "execution_count": null, - "metadata": {}, + "execution_count": 135, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "import curve_trades as ct\n", @@ -14,9 +16,19 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 136, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "4060cfed86a945959e7a8d607ef720cf" + } + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "w = widgets.Dropdown(\n", " options=['IG', 'EU'],\n", @@ -29,8 +41,10 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, + "execution_count": 137, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "index = w.value" @@ -38,9 +52,809 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 138, "metadata": {}, - "outputs": [], + "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", + " this.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 overriden (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", + " // select the cell after this one\n", + " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", + " IPython.notebook.select(index + 1);\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": [ + "<div id='3d60632c-39b7-41a7-8940-7945ba0f2ef7'></div>" + ], + "text/plain": [ + "<IPython.core.display.HTML object>" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "<matplotlib.axes._subplots.AxesSubplot at 0x7f3cb485f860>" + ] + }, + "execution_count": 138, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "#On the run spread differences\n", "spreads_diff = ct.curve_spread_diff(index, 6)\n", @@ -49,9 +863,879 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 139, "metadata": {}, - "outputs": [], + "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", + " this.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 overriden (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", + " // select the cell after this one\n", + " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", + " IPython.notebook.select(index + 1);\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": [ + "<div id='39eae58f-8f02-47ff-8844-d8df779a40fe'></div>" + ], + "text/plain": [ + "<IPython.core.display.HTML object>" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "<div>\n", + "<style>\n", + " .dataframe thead tr:only-child th {\n", + " text-align: right;\n", + " }\n", + "\n", + " .dataframe thead th {\n", + " text-align: left;\n", + " }\n", + "\n", + " .dataframe tbody tr th {\n", + " vertical-align: top;\n", + " }\n", + "</style>\n", + "<table border=\"1\" class=\"dataframe\">\n", + " <thead>\n", + " <tr style=\"text-align: right;\">\n", + " <th></th>\n", + " <th>3-5</th>\n", + " <th>5-7</th>\n", + " <th>7-10</th>\n", + " <th>5-10</th>\n", + " </tr>\n", + " </thead>\n", + " <tbody>\n", + " <tr>\n", + " <th>min</th>\n", + " <td>24.179207</td>\n", + " <td>18.932223</td>\n", + " <td>12.110608</td>\n", + " <td>31.924565</td>\n", + " </tr>\n", + " <tr>\n", + " <th>max</th>\n", + " <td>34.068608</td>\n", + " <td>27.213778</td>\n", + " <td>22.397303</td>\n", + " <td>48.664671</td>\n", + " </tr>\n", + " <tr>\n", + " <th>mean</th>\n", + " <td>29.358655</td>\n", + " <td>23.756332</td>\n", + " <td>18.035087</td>\n", + " <td>41.791419</td>\n", + " </tr>\n", + " <tr>\n", + " <th>current</th>\n", + " <td>27.712660</td>\n", + " <td>24.911450</td>\n", + " <td>18.992275</td>\n", + " <td>43.903725</td>\n", + " </tr>\n", + " <tr>\n", + " <th>zscore</th>\n", + " <td>-0.749325</td>\n", + " <td>0.503029</td>\n", + " <td>0.610201</td>\n", + " <td>0.641449</td>\n", + " </tr>\n", + " </tbody>\n", + "</table>\n", + "</div>" + ], + "text/plain": [ + " 3-5 5-7 7-10 5-10\n", + "min 24.179207 18.932223 12.110608 31.924565\n", + "max 34.068608 27.213778 22.397303 48.664671\n", + "mean 29.358655 23.756332 18.035087 41.791419\n", + "current 27.712660 24.911450 18.992275 43.903725\n", + "zscore -0.749325 0.503029 0.610201 0.641449" + ] + }, + "execution_count": 139, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "#Table of Spread Differences, and Z-score of current spread differences\n", "ct.spreads_diff_table(spreads_diff)" @@ -59,9 +1743,114 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 140, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "<div>\n", + "<style>\n", + " .dataframe thead tr:only-child th {\n", + " text-align: right;\n", + " }\n", + "\n", + " .dataframe thead th {\n", + " text-align: left;\n", + " }\n", + "\n", + " .dataframe tbody tr th {\n", + " vertical-align: top;\n", + " }\n", + "</style>\n", + "<table border=\"1\" class=\"dataframe\">\n", + " <thead>\n", + " <tr style=\"text-align: right;\">\n", + " <th>tenor</th>\n", + " <th>3yr</th>\n", + " <th>5yr</th>\n", + " <th>7yr</th>\n", + " <th>10yr</th>\n", + " </tr>\n", + " <tr>\n", + " <th>series</th>\n", + " <th></th>\n", + " <th></th>\n", + " <th></th>\n", + " <th></th>\n", + " </tr>\n", + " </thead>\n", + " <tbody>\n", + " <tr>\n", + " <th>23</th>\n", + " <td>NaN</td>\n", + " <td>NaN</td>\n", + " <td>NaN</td>\n", + " <td>NaN</td>\n", + " </tr>\n", + " <tr>\n", + " <th>24</th>\n", + " <td>NaN</td>\n", + " <td>NaN</td>\n", + " <td>NaN</td>\n", + " <td>NaN</td>\n", + " </tr>\n", + " <tr>\n", + " <th>25</th>\n", + " <td>NaN</td>\n", + " <td>NaN</td>\n", + " <td>NaN</td>\n", + " <td>NaN</td>\n", + " </tr>\n", + " <tr>\n", + " <th>26</th>\n", + " <td>NaN</td>\n", + " <td>NaN</td>\n", + " <td>NaN</td>\n", + " <td>NaN</td>\n", + " </tr>\n", + " <tr>\n", + " <th>27</th>\n", + " <td>NaN</td>\n", + " <td>NaN</td>\n", + " <td>NaN</td>\n", + " <td>NaN</td>\n", + " </tr>\n", + " <tr>\n", + " <th>28</th>\n", + " <td>NaN</td>\n", + " <td>NaN</td>\n", + " <td>NaN</td>\n", + " <td>NaN</td>\n", + " </tr>\n", + " <tr>\n", + " <th>29</th>\n", + " <td>NaN</td>\n", + " <td>NaN</td>\n", + " <td>NaN</td>\n", + " <td>NaN</td>\n", + " </tr>\n", + " </tbody>\n", + "</table>\n", + "</div>" + ], + "text/plain": [ + "tenor 3yr 5yr 7yr 10yr\n", + "series \n", + "23 NaN NaN NaN NaN\n", + "24 NaN NaN NaN NaN\n", + "25 NaN NaN NaN NaN\n", + "26 NaN NaN NaN NaN\n", + "27 NaN NaN NaN NaN\n", + "28 NaN NaN NaN NaN\n", + "29 NaN NaN NaN NaN" + ] + }, + "execution_count": 140, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "#Theta per unit duration\n", "ct.theta_matrix_by_series(index)" @@ -69,9 +1858,799 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 141, "metadata": {}, - "outputs": [], + "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", + " this.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 overriden (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", + " // select the cell after this one\n", + " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", + " IPython.notebook.select(index + 1);\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": [ + "<div id='d78eb7f9-6ece-4fcb-b2a9-ef50a8332aaf'></div>" + ], + "text/plain": [ + "<IPython.core.display.HTML object>" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "#on the run theta\n", "ct.on_the_run_theta(index)" @@ -79,9 +2658,78 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 142, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "<div>\n", + "<style>\n", + " .dataframe thead tr:only-child th {\n", + " text-align: right;\n", + " }\n", + "\n", + " .dataframe thead th {\n", + " text-align: left;\n", + " }\n", + "\n", + " .dataframe tbody tr th {\n", + " vertical-align: top;\n", + " }\n", + "</style>\n", + "<table border=\"1\" class=\"dataframe\">\n", + " <thead>\n", + " <tr style=\"text-align: right;\">\n", + " <th></th>\n", + " <th>3-5</th>\n", + " <th>3-5-10</th>\n", + " <th>3-7</th>\n", + " <th>5-10</th>\n", + " <th>7-10</th>\n", + " </tr>\n", + " </thead>\n", + " <tbody>\n", + " <tr>\n", + " <th>Sharpe</th>\n", + " <td>0.211386</td>\n", + " <td>1.523687</td>\n", + " <td>-0.491073</td>\n", + " <td>2.592219</td>\n", + " <td>1.341185</td>\n", + " </tr>\n", + " <tr>\n", + " <th>Mean Worst 10 Days DrawDown</th>\n", + " <td>-0.000748</td>\n", + " <td>-0.001212</td>\n", + " <td>-0.000872</td>\n", + " <td>-0.000646</td>\n", + " <td>-0.000639</td>\n", + " </tr>\n", + " <tr>\n", + " <th>Monthly Sharpe</th>\n", + " <td>0.365536</td>\n", + " <td>1.795681</td>\n", + " <td>-0.536642</td>\n", + " <td>1.834057</td>\n", + " <td>1.236990</td>\n", + " </tr>\n", + " </tbody>\n", + "</table>\n", + "</div>" + ], + "text/plain": [ + " 3-5 3-5-10 3-7 5-10 7-10\n", + "Sharpe 0.211386 1.523687 -0.491073 2.592219 1.341185\n", + "Mean Worst 10 Days DrawDown -0.000748 -0.001212 -0.000872 -0.000646 -0.000639\n", + "Monthly Sharpe 0.365536 1.795681 -0.536642 1.834057 1.236990" + ] + }, + "execution_count": 142, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "#Curve Trade returns\n", "ct.curve_returns()" @@ -89,7 +2737,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 143, "metadata": {}, "outputs": [], "source": [ @@ -98,9 +2746,799 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 144, "metadata": {}, - "outputs": [], + "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", + " this.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 overriden (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", + " // select the cell after this one\n", + " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", + " IPython.notebook.select(index + 1);\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": [ + "<div id='c679d979-e016-4b8b-a8a1-595330c18d29'></div>" + ], + "text/plain": [ + "<IPython.core.display.HTML object>" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "#Theta with 3-5-10 Strategy\n", "df = ct.ratio_within_series(param='duration')\n", @@ -109,18 +3547,799 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 145, "metadata": {}, - "outputs": [], - "source": [ - "%debug" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "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", + " this.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 overriden (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", + " // select the cell after this one\n", + " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", + " IPython.notebook.select(index + 1);\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": [ + "<div id='f8e66a92-1610-4a0c-a3a7-64d3207c77dd'></div>" + ], + "text/plain": [ + "<IPython.core.display.HTML object>" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "#Theta with 5-10 Strategy\n", "df = ct.ratio_within_series(param='duration')\n", @@ -129,9 +4348,809 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 149, "metadata": {}, - "outputs": [], + "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", + " this.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 overriden (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", + " // select the cell after this one\n", + " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", + " IPython.notebook.select(index + 1);\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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gAiIgAj4mIAEoASg3SUnAWiXoMaLgAiIgAiIgI8JSABKANpdchKAdglqvAiIgAiIgAj4mIAEoH8JwNoA3gZQAUA2AK0BTA9nTdUBMBRACQAnAHwO4LsIrEMJwAjA0qEiIAIiIAIiEBsISAD6lwBsCqAGgA0ApnghAPMB2AZgNIDvnWNHAujgHO/NGpUA9IaSjhEBERABERCBWERAAtC/BKD70nrghQD8DEBLAMXcBtL7VwZANS/XqUMAnj2BgAD+UyYCIiACIiACIhDbCRgBmCk7bzMNgMux/X6j4/4SRMdJY8E5vRGASwBsBNDD7X65bTwJQAoAdzzMIxkA/s+y1ACOBb6XGgHJ/BVlLHiaugUREAEREAERiEICl289QJpPr0gARiHT2HIqbwTgHgA/AxjkdtPVASwHwJ8FJz1Mph+Aj4L/XQIwtjx23YcIiIAIiIAIhE9AAjB+bwFTAI4FMNhtqTCGcJkzieSU1x5AbQGH/27TESIgAiIgAiIQSwhoCzh+C8DIbAEHX7pKAoklb2bdhgiIgAiIgAh4S0BJIPFbADIJpAWA4m4LZhSAshFOAgkMVBKIt+86HScCIiACIiACMUxAAtC/BGAqAAWda4rJHb0ALARwAcAR51ZvDgDPOI+xysCwBAxLwTDzl1nAKgMTw29MXV4EREAEREAEopOABKB/CcC6TsEXfM2MA9DFmfCRFwCPs4yFoIe5FYKmV1CFoKPzXadzi4AIiIAIiEAME5AA9C8BGBPLSTGAMUFd1xQBERABERABGwQkACUAbSwfM1QC0C5BjRcBERABERABHxOQAJQAtLvkJADtEtR4ERABERABEfAxAQlACUC7S04C0C5BjRcBERABERABHxOQAJQAtLvkJADtEtR4ERABERABEfAxAQlACUC7S04C0C5BjRcBERABERABHxOQAJQAtLvkJADtEtR4ERABERABEfAxAQlACUC7S04C0C5BjRcBERABERABHxOQAJQAtLvkJADtEtR4ERABERABEfAxAQlACUC7S04C0C5BjRcBERABERABHxOQAJQAtLvkJADtEtR4ERABERABEfAxAQlACUC7S04C0C5BjRcBERABERABHxOQAJQAtLvkJADtEtR4ERABERABEfAxAQlACUC7S04C0C5BjRcBERABERABHxOQAJQAtLvkJADtEtR4ERABERABEfAxAQlACUC7S04C0C5BjRcBERABERABHxOQAJQAtLvkJADtEtR4ERABERABEfAxAQlACUC7S04C0C5BjRcBERABERABHxOQAJQAtLvkJADtEtR4ERABERABEfAxAQlACUC7S04C0C5BjRcBERABERABHxOQAJQAtLvkJADtEtR4ERABERABEfAxAQlACUC7S04C0C5BjRcBERABERABHxOQAJQAtLvkJADtEtR4ERABERABEfAxAQlACUC7S04C0C5BjRcBERABERABHxOQAJQAtLvkJADtEtR4ERABERABEfAxAQlACUC7S04C0C5BjRcBERABERABHxOQAJQAtLvkJADtEtR4ERABERABEfAxAQlACUC7S04C0C5BjRcBERABERABHxOQAJQAtLvkJADtEtR4ERABERABEfAxAQlACUC7S04C0C5BjRcBERABERABHxOQAJQAtLvkJADtEtR4ERABERABEfAxAQlA/xOArwB4G0A2ANsB9ASwNIx1xddfBpAbwDkAkwH0BnDTy7UoAeglKB0mAiIgAiIgArGFgASgfwnAdgDGA6AIXA6gG4AXABQHcMTDousEYAyA5wGsAFAYwM8A/gDwppeLVALQS1A6TAREQAREQARiCwEJQP8SgKsBbHB69Kw1thPAdKdXL/i6GwGgGIAGbi8MAVAZQC0vF6kEoJegdJgIiIAIiIAIxBYCEoD+IwCTArgOoA2AaW4L7GsAZQHU8bDo2gP4DkBjAGsA5AfwL4BxAD71cpFKAHoJSoeJgAiIgAiIQGwhIAHoPwIwO4DjAGo4t3OtNdYHwLMAioSy6F4HQK9fAgCJAYxybiGHtkaTAeD/LEsN4FhgYCACAqgFZSIgAiIgAiIgArGdgASg/wnA6gBWui289wF0BlDUw2KsC2AigL4AuH1cEAA9hqMBfBzK4u0H4KPgr0kAxva3uu5PBERABERABB4SkAD0HwEYmS1gZgevcmYNW6viaQA/AEgF4L6HN4s8gPoEEQEREAEREIE4TkAC0H8EIJcivXjrg23h7gDwVyhJIDx2HoB33dZxBwA/OQXgPS/Wt2IAvYCkQ0QgsgQePHiABAkYoSETAREQgagjIAHoXwLQKgPT3bkN/BKAFwGUAHAYwC/OOEHW+aNxO7cXAB5nbQEzBpDCkOfyxiQAvaGkY0QgEgRu372PVt8uR76M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\" width=\"640\">" + ], + "text/plain": [ + "<IPython.core.display.HTML object>" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "<matplotlib.axes._subplots.AxesSubplot at 0x7f3cb4e33358>" + ] + }, + "execution_count": 149, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "#Relative Spread Difference\n", "spread_ratio = ct.ratio_within_series(param = 'closespread')\n", @@ -140,9 +5159,835 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 150, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/edwin/projects/code/python/exploration/curve_trades.py:172: SettingWithCopyWarning: \n", + "A value is trying to be set on a copy of a slice from a DataFrame.\n", + "Try using .loc[row_indexer,col_indexer] = value instead\n", + "\n", + "See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy\n", + " #dr/dspread = exp(k) + spread_coeff * duration ^ dur_coeff * spread ^ (spread_coeff-1)\n", + "/usr/lib/python3.6/site-packages/pandas/core/frame.py:2450: SettingWithCopyWarning: \n", + "A value is trying to be set on a copy of a slice from a DataFrame.\n", + "Try using .loc[row_indexer,col_indexer] = value instead\n", + "\n", + "See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy\n", + " self[k1] = value[k2]\n", + "/home/edwin/projects/code/python/exploration/curve_trades.py:176: SettingWithCopyWarning: \n", + "A value is trying to be set on a copy of a slice from a DataFrame.\n", + "Try using .loc[row_indexer,col_indexer] = value instead\n", + "\n", + "See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy\n", + " df[['predicted', 'down_2_stdev', 'up_2_stdev']]=\\\n" + ] + }, + { + "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", + " this.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 overriden (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", + " // select the cell after this one\n", + " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", + " IPython.notebook.select(index + 1);\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,iVBORw0KGgoAAAANSUhEUgAAAoAAAAHgCAYAAAA10dzkAAAgAElEQVR4XuydBXRURxuG37gQgeAJUNzd+XGXQnFa3K1A0UILFHeKU4q7e5DgWty1eJHgkJCEuP7nu8nGSMjCzYZk951zaGH3ztz5njuXPIwagYkESIAESIAESIAESMCgCBgZVLQMlgRIgARIgARIgARIABRANgISIAESIAESIAESMDACFEADe+AMlwRIgARIgARIgAQogGwDJEACJEACJEACJGBgBCiABvbAGS4JkAAJkAAJkAAJUADZBkiABEiABEiABEjAwAhQAA3sgTNcEiABEiABEiABEqAAsg2QAAmQAAmQAAmQgIERoAAa2ANnuCRAAiRAAiRAAiRAAWQbIAESIAESIAESIAEDI0ABNLAHznBJgARIgARIgARIgALINkACJEACJEACJEACBkaAAmhgD5zhkgAJkAAJkAAJkAAFkG2ABEiABEiABEiABAyMAAXQwB44wyUBEiABEiABEiABCiDbAAmQAAmQAAmQAAkYGAEKoIE9cIZLAiRAAiRAAiRAAhRAtgESIAESIAESIAESMDACFEADe+AMlwRIgARIgARIgAQogGwDJEACJEACJEACJGBgBCiABvbAGS4JkAAJkAAJkAAJUADZBkiABEiABEiABEjAwAhQAA3sgTNcEiABEiABEiABEqAAsg2QAAmQAAmQAAmQgIERoAAa2ANnuCRAAiRAAiRAAiRAAWQbIAESIAESIAESIAEDI0ABNLAHznBJgARIgARIgARIgALINkACJEACJEACJEACBkaAAmhgD5zhkgAJkAAJkAAJkAAFkG2ABEiABEiABEiABAyMAAXQwB44wyUBEiABEiABEiABCiDbAAmQAAmQAAmQAAkYGAEKoIE9cIZLAiRAAiRAAiRAAhRAtgESIAESIAESIAESMDACFEADe+AMlwRIgARIgARIgAQogGwDJEACJEACJEACJGBgBCiABvbAGS4JkAAJkAAJkAAJUADZBkiABEiABEiABEjAwAhQAA3sgTNcEiABEiABEiABEqAAsg2QAAmQAAmQAAmQgIERoAAa2ANnuCRAAiRAAiRAAiRAAWQbIAESIAESIAESIAEDI0ABNLAHznBJgARIgARIgARIgALINkACJEACJEACJEACBkaAAmhgD5zhkgAJkAAJkAAJ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\" width=\"640\">" + ], + "text/plain": [ + "<IPython.core.display.HTML object>" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/edwin/projects/code/python/exploration/curve_trades.py:180: SettingWithCopyWarning: \n", + "A value is trying to be set on a copy of a slice from a DataFrame.\n", + "Try using .loc[row_indexer,col_indexer] = value instead\n", + "\n", + "See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy\n", + " return df\n" + ] + } + ], "source": [ "model = ct.curve_model()\n", "model_results = ct.curve_model_results(model[0], model[1])" @@ -160,28 +6005,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np\n", - "ax = model_results[['ratio','predicted']].plot()\n", - "ax.plot(model_results.index, model_results.up_2_stdev, 'r--')\n", - "ax.plot(model_results.index, model_results.down_2_stdev, 'b--')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "model_results.iloc[-1]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "#Var on current position\n", @@ -191,7 +6017,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "results\n", @@ -203,7 +6031,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [] } @@ -224,7 +6054,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.2" + "version": "3.6.1" } }, "nbformat": 4, |
