Last active
October 17, 2019 10:36
-
-
Save pieterdavid/ddb47786c59a4db7794f3a66b2588cc8 to your computer and use it in GitHub Desktop.
mplbplot examples
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"cells": [ | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"This notebook shows a few simple examples of how to draw a 1-dimensional ROOT histogram\n", | |
"([TH1F](https://root.cern.ch/doc/master/classTH1F.html)) in [matplotlib](http://matplotlib.org)\n", | |
"using [mplbplot](https://github.com/pieterdavid/mplbplot)." | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"The following lines set up the Jupyter notebook to show both the ROOT and matplotlib plots\n", | |
"that are created \"inline\".\n", | |
"\n", | |
"The ROOT, matplotlib.pyplot, and mplbplot modules are also loaded. The `mplbplot.decorateAxes`\n", | |
"API is chosen here because it is more consistent with the (recommended) object-oriented matplotlib\n", | |
"API, but alternatives are available\n", | |
"(see [the mplbplot README](https://github.com/pieterdavid/mplbplot/blob/master/README.rst))." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 1, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"Welcome to JupyROOT 6.11/01\n" | |
] | |
} | |
], | |
"source": [ | |
"%jsroot on\n", | |
"%matplotlib notebook\n", | |
"import ROOT\n", | |
"from matplotlib import pyplot as plt\n", | |
"import mplbplot.decorateAxes" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"We will need `TH1F` objects to play with, e.g. a small sample drawn from a Gaussian distribution" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 2, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"h1 = ROOT.TH1F(\"aHisto\", \"\", 20, -5., 5.)\n", | |
"h1.FillRandom(\"gaus\", 250)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"The most basic way to draw a histogram is with a histogram line, which is done in ROOT as follows\n", | |
"(see [THistPainter](https://root.cern.ch/doc/master/classTHistPainter.html) for documentation\n", | |
"on styling such histogram plots; the `TCanvas::Draw` call is needed for the JupyROOT notebook)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 3, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"image/png": "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\nYII=\n", | |
"text/plain": [ | |
"<IPython.core.display.Image object>" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
} | |
], | |
"source": [ | |
"cHIST = ROOT.TCanvas(\"cHIST\")\n", | |
"h1.SetLineColor(ROOT.kBlue)\n", | |
"h1.Draw(\"HIST\")\n", | |
"cHIST.Draw()" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"The minimal code for doing the same in matplotlib using mplbplot is also very short" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 4, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"application/javascript": [ | |
"/* Put everything inside the global mpl namespace */\n", | |
"window.mpl = {};\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", | |
" 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 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);\n", | |
" canvas.attr('height', height);\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'];\n", | |
" var y0 = fig.canvas.height - msg['y0'];\n", | |
" var x1 = msg['x1'];\n", | |
" var y1 = fig.canvas.height - msg['y1'];\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;\n", | |
" var y = canvas_pos.y;\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\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\"];\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", | |
" 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 + '\">');\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 dataURL = this.canvas.toDataURL();\n", | |
" this.cell_info[1]['text/html'] = '<img src=\"' + dataURL + '\">';\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.updated_canvas_event = function() {\n", | |
" // Tell IPython that the notebook contents must change.\n", | |
" IPython.notebook.set_dirty(true);\n", | |
" this.send_message(\"ack\", {});\n", | |
" var fig = this;\n", | |
" // Wait a second, then push the new image to the DOM so\n", | |
" // that it is saved nicely (might be nice to debounce this).\n", | |
" setTimeout(function () { fig.push_to_output() }, 1000);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._init_toolbar = function() {\n", | |
" var fig = this;\n", | |
"\n", | |
" var nav_element = $('<div/>')\n", | |
" nav_element.attr('style', 'width: 100%');\n", | |
" this.root.append(nav_element);\n", | |
"\n", | |
" // Define a callback function for later on.\n", | |
" function toolbar_event(event) {\n", | |
" return fig.toolbar_button_onclick(event['data']);\n", | |
" }\n", | |
" function toolbar_mouse_event(event) {\n", | |
" return fig.toolbar_button_onmouseover(event['data']);\n", | |
" }\n", | |
"\n", | |
" for(var toolbar_ind in mpl.toolbar_items){\n", | |
" var name = mpl.toolbar_items[toolbar_ind][0];\n", | |
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", | |
" var image = mpl.toolbar_items[toolbar_ind][2];\n", | |
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n", | |
"\n", | |
" if (!name) { continue; };\n", | |
"\n", | |
" var button = $('<button class=\"btn btn-default\" href=\"#\" title=\"' + name + '\"><i class=\"fa ' + image + ' fa-lg\"></i></button>');\n", | |
" button.click(method_name, toolbar_event);\n", | |
" button.mouseover(tooltip, toolbar_mouse_event);\n", | |
" nav_element.append(button);\n", | |
" }\n", | |
"\n", | |
" // Add the status bar.\n", | |
" var status_bar = $('<span class=\"mpl-message\" style=\"text-align:right; float: right;\"/>');\n", | |
" nav_element.append(status_bar);\n", | |
" this.message = status_bar[0];\n", | |
"\n", | |
" // Add the close button to the window.\n", | |
" var buttongrp = $('<div class=\"btn-group inline pull-right\"></div>');\n", | |
" var button = $('<button class=\"btn btn-mini btn-primary\" href=\"#\" title=\"Stop Interaction\"><i class=\"fa fa-power-off icon-remove icon-large\"></i></button>');\n", | |
" button.click(function (evt) { fig.handle_close(fig, {}); } );\n", | |
" button.mouseover('Stop Interaction', toolbar_mouse_event);\n", | |
" buttongrp.append(button);\n", | |
" var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", | |
" titlebar.prepend(buttongrp);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._root_extra_style = function(el){\n", | |
" var fig = this\n", | |
" el.on(\"remove\", function(){\n", | |
"\tfig.close_ws(fig, {});\n", | |
" });\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._canvas_extra_style = function(el){\n", | |
" // this is important to make the div 'focusable\n", | |
" el.attr('tabindex', 0)\n", | |
" // reach out to IPython and tell the keyboard manager to turn it's self\n", | |
" // off when our div gets focus\n", | |
"\n", | |
" // location in version 3\n", | |
" if (IPython.notebook.keyboard_manager) {\n", | |
" IPython.notebook.keyboard_manager.register_events(el);\n", | |
" }\n", | |
" else {\n", | |
" // location in version 2\n", | |
" IPython.keyboard_manager.register_events(el);\n", | |
" }\n", | |
"\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._key_event_extra = function(event, name) {\n", | |
" var manager = IPython.notebook.keyboard_manager;\n", | |
" if (!manager)\n", | |
" manager = IPython.keyboard_manager;\n", | |
"\n", | |
" // Check for shift+enter\n", | |
" if (event.shiftKey && event.which == 13) {\n", | |
" this.canvas_div.blur();\n", | |
" event.shiftKey = false;\n", | |
" // Send a \"J\" for go to next cell\n", | |
" event.which = 74;\n", | |
" event.keyCode = 74;\n", | |
" manager.command_mode();\n", | |
" manager.handle_keydown(event);\n", | |
" }\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_save = function(fig, msg) {\n", | |
" fig.ondownload(fig, null);\n", | |
"}\n", | |
"\n", | |
"\n", | |
"mpl.find_output_cell = function(html_output) {\n", | |
" // Return the cell and output element which can be found *uniquely* in the notebook.\n", | |
" // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", | |
" // IPython event is triggered only after the cells have been serialised, which for\n", | |
" // our purposes (turning an active figure into a static one), is too late.\n", | |
" var cells = IPython.notebook.get_cells();\n", | |
" var ncells = cells.length;\n", | |
" for (var i=0; i<ncells; i++) {\n", | |
" var cell = cells[i];\n", | |
" if (cell.cell_type === 'code'){\n", | |
" for (var j=0; j<cell.output_area.outputs.length; j++) {\n", | |
" var data = cell.output_area.outputs[j];\n", | |
" if (data.data) {\n", | |
" // IPython >= 3 moved mimebundle to data attribute of output\n", | |
" data = data.data;\n", | |
" }\n", | |
" if (data['text/html'] == html_output) {\n", | |
" return [cell, data, j];\n", | |
" }\n", | |
" }\n", | |
" }\n", | |
" }\n", | |
"}\n", | |
"\n", | |
"// Register the function which deals with the matplotlib target/channel.\n", | |
"// The kernel may be null if the page has been refreshed.\n", | |
"if (IPython.notebook.kernel != null) {\n", | |
" IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", | |
"}\n" | |
], | |
"text/plain": [ | |
"<IPython.core.display.Javascript object>" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
}, | |
{ | |
"data": { | |
"text/html": [ | |
"<img src=\"data:image/png;base64,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z71kyB26NQECSACrASWAVYLqlySwqgiteu4lQ+7QrQkQQAJYDSgBrBJUvySBVUVo1XMvGXKHbk2AABLAakAJYJWg+iUJrCpCq557yZA7dGsCBJAAVgNKAKsE1S9JYFURWvXcS4bcoVsTIIAEsBpQAlglqH5JAquK0KrnXjLkDt2aAAEkgNWAEsAqQfVLElhVhFY995Ihd+jWBAggAawGlABWCapfksCqIrTquZcMuUO3JkAACWA1oASwSlD9kgRWFaFVz71kyB26NQECSACrASWAVYLqlySwqgiteu4lQ+7QrQkQQAJYDSgBrBJUvySBVUVo1XMvGXKHbk2AABLAakAJYJWg+iUJrCpCq557yZA7dGsCBJAAVgNKAKsE1S9JYFURWvXcS4bcoVsTIIAEsBpQAlglqH5JAquK0KrnXjLkDt2aAAEkgNWAEsAqQfVLElhVhFY995Ihd+jWBAggAawGlABWCapfksCqIrTquZcMuUO3JkAACWA1oASwSlD9kgRWFaFVz71kyB26NQECSACrASWAVYLqlySwqgiteu4lQ+7QrQkQQAJYDSgBrBJUvySBVUVo1XMvGXKHbk2AABLAakAJYJWg+iUJrCpCq557yZA7dGsCBJAAVgNKAKsE1S9JYFURWvXcS4bcoVsTIIAEsBpQAlglqH5JAquK0KrnXjLkDt2aAAEkgNWAEsAqQfVLElhVhFY995Ihd+jWBAggAawGlABWCapfksCqIrTquZcMuUO3JkAACWA1oASwSlD9kgRWFaFVz71kyB26NQECSACrASWAVYLqlySwqgiteu4lQ+7QrQkQQAJYDSgBrBJUvySBVUVo1XMvGXKHbk2AABLAakAJYJWg+iUJrCpCq557yZA7dGsCBJAAVgNKAKsE1S9JYFURWvXcS4bcoVsTIIAEsBpQAlglqH5JAquK0KrnXjLkDt2aAAEkgNWAEsAqQfVLElhVhFY995Ihd+jWBAggAawGlABWCapfksCqIrTquZcMuUO3JkAACWA1oASwSlD9kgRWFaFVz71kyB26NQECSACrASWAVYLqlySwqgiteu4lQ+7QrQkQQAJYDSgBrBJUvySBVUVo1XMvGXKHbk2AABLAakAJYJWg+iUJrCpCq557yZA7dGsCBJAAVgNKAKsE1S9JYFURWvXcS4bcoVsTIIAEsBpQAlglqH5JAquK0KrnXjLkDt2aAAEkgNWAEsAqQfVLElhVhFY995Ihd+jWBAggAawGlABWCapfksCqIrTquZcMuUO3JkAACWA1oASwSlD9kgRWFaFVz71kyB26NQECuKYAPjfJs5LcI8nfJ/mtJP82yR9v0nrvJK9I8rAk1yd5YZIrbiLJBLD1U9xwXQmsKkKrnrtrDs21LgECuKYAPiXJR5K8P8ntkzwvyflJvjDJLZK8K8nbkzw/yUOTvCbJhUnecoKnCgFc9/uHkxcIrCpCq567EBWlCOwKAQK4pgAeH6bzkvyvJAc2wvfaJOck+fjmC1+Z5I5JnkoAd+V5qOmCBFYVoVXPvWDEHbk5AQJIAG+zudL3+CQP3Lzc+/Akj9mR3YuSvDjJ3Qhg82e08baGwKoitOq5tyaYBl2GAAFcVwCfkORnktx281Lw45L8n817/26X5Bk7ngWPTfKGJGcSwGW+NzjoLhNYVYRWPfcux0l7BE6ZAAFcVwDHlb+7bF7qHR8AuX+ShyT5kSTHC+C4GvhGAnjKzy8F+4TAu9+dvHK8EWLiY/R705uSgwcnNt2CVkMAL7gguetd5w17/vnJ058+r59OCKxAgACuK4A7833LJB9O8q+SPCjJKb8EfPjw4Zx55mcuEB46dOjGPx4I7BcCF1+cXHVV8qhHzTvRWWcl3/M9ya1vPa/nNnR63euSq6+eN+mHPpS87W3JddfN66kTAvuVwJEjRzL+jMfRo0dz+eWXj/94dpIb9uuZP9e5zljx0Med+VYbARy3hhm3hRkfArnzjg+BvDzJnXwIRFJWJTAEcDwuu2xVAn3P/Y53JE97GgHsuyGTdSXgCuCaVwDH7V1+McmfbV4C/s4kX5HkPkn+Nsk1m9vAvGDzqeBXb24Dc9UJguw2MF2f3eaaRoAATkM5vREBnI5Uw0UIEMA1BfBnkzxic1Xvo0l+I8klSd69yf29krxqc2/AcSPoIYJDAk/0IICLfLNY+ZgEsO/2CWDf3ZisNwECuKYAzkwlAZxJU6+WBAhgy7XcOBQB7Lsbk/UmQAAJYDWhBLBKUH17AgSw74oIYN/dmKw3AQJIAKsJJYBVgurbEyCAfVdEAPvuxmS9CRBAAlhNKAGsElTfngAB7LsiAth3NybrTYAAEsBqQglglaD69gQIYN8VEcC+uzFZbwIEkABWE0oAqwTVtydAAPuuiAD23Y3JehMggASwmlACWCWovj0BAth3RQSw725M1psAASSA1YQSwCpB9e0JEMC+KyKAfXdjst4ECCABrCaUAFYJqm9PgAD2XREB7Lsbk/UmQAAJYDWhBLBKUH17AgSw74oIYN/dmKw3AQJIAKsJJYBVgurbEyCAfVdEAPvuxmS9CRBAAlhNKAGsElTfngAB7LsiAth3NybrTYAAEsBqQglglaD69gQIYN8VEcC+uzFZbwIEkABWE0oAqwTVtydAAPuuiAD23Y3JehMggASwmlACWCWovj0BAth3RQSw725M1psAASSA1YQSwCpB9e0JEMC+KyKAfXdjst4ECCABrCaUAFYJqm9PgAD2XREB7Lsbk/UmQAAJYDWhBLBKUH17AgSw74oIYN/dmKw3AQJIAKsJJYBVgurbEyCAfVdEAPvuxmS9CRBAAlhNKAGsElTfngAB7LsiAth3NybrTYAAEsBqQglglaD69gQIYN8VEcC+uzFZbwIEkABWE0oAqwTVtydAAPuuiAD23Y3JehMggASwmlACWCWovj0BAth3RQSw725M1psAASSA1YQSwCpB9e0JEMC+KyKAfXdjst4ECCABrCaUAFYJqm9PgAD2XREB7Lsbk/UmQAAJYDWhBLBKUH17AgSw74oIYN/dmKw3AQJIAKsJJYBVgurbEyCAfVdEAPvuxmS9CRBAAlhNKAGsElTfngAB7LsiAth3NybrTYAAEsBqQglglaD69gQIYN8VEcC+uzFZbwIEkABWE0oAqwTVtydAAPuuiAD23Y3JehMggASwmlACWCWovj0BAth3RQSw725M1psAASSA1YQSwCpB9e0JEMC+KyKAfXdjst4ECCABrCaUAFYJqm9PgAD2XREB7Lsbk/UmQAAJYDWhBLBKUH17AgSw74oIYN/dmKw3AQJIAKsJJYBVgurbEyCAfVdEAPvuxmS9CRBAAlhNKAGsElTfngAB7LsiAth3NybrTYAAEsBqQglglaD69gQIYN8VEcC+uzFZbwIEkABWE0oAqwTVtydAAPuuiAD23Y3JehMggASwmlACWCWovj0BAth3RQSw725M1psAASSA1YQSwCpB9e0JEMC+KyKAfXdjst4ECCABrCaUAFYJqm9PgAD2XREB7Lsbk/UmQAAJYDWhBLBKUH17AgSw74oIYN/dmKw3AQJIAKsJJYBVgurbEyCAfVdEAPvu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+hzHBz/Gz+g7bX5pw7ga+Pun3277Kgng9u3MxAgggAACCCCAQIkAASzhU4wAAggggAACCGwfAQK4fTszMQIIIIAAAgggUCJAAEv4FCOAAAIIIIAAAttHgABu385MjAACCCCAAAIIlAgQwBI+xQgggAACCCCAwPYRIIDbtzMTI4AAAggggAACJQIEsIRPMQIIIIAAAgggsH0ECOD27czECCCAAAIIIIBAiQABLOFTjAACCCCAAAIIbB8BArh9OzMxAggggAACCCBQIkAAS/gUI4AAAggggAAC20eAAG7fzkyMAAIIIIAAAgiUCBDAEj7FCCCAAAIIIIDA9hEggNu3MxMjgAACCCCAAAIlAgSwhE8xAggggAACCCCwfQQI4PbtzMQIIIAAAggggECJAAEs4VOMAAIIIIAAAghsHwECuH07MzECCCCAAAIIIFAiQABL+BQjgAACCCCAAALbR4AAbt/OTIwAAggggAACCJQIEMASPsUIIIAAAggggMD2ESCA27czEyOAAAIIIIAAAiUCBLCETzECCCCAAAIIILB9BAjg9u3MxAgggAACCCCAQIkAASzhU4wAAggggAACCGwfAQK4fTszMQIIIIAAAgggUCJAAEv4FCOAAAIIIIAAAttHgABu385MjAACCCCAAAIIlAgQwBI+xQgggAACCCCAwPYRIIDbtzMTI4AAAggggAACJQIEsIRPMQIIIIAAAgggsH0ECOD27czECCCAAAIIIIBAicD/A/ejUjrLA0DoAAAAAElFTkSuQmCC\">" | |
], | |
"text/plain": [ | |
"<IPython.core.display.HTML object>" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
}, | |
{ | |
"data": { | |
"text/plain": [ | |
"(array([ 0., 0., 0., 1., 1., 2., 8., 30., 41., 50., 56.,\n", | |
" 30., 9., 14., 5., 2., 1., 0., 0., 0.]),\n", | |
" array([-5. , -4.5, -4. , -3.5, -3. , -2.5, -2. , -1.5, -1. , -0.5, 0. ,\n", | |
" 0.5, 1. , 1.5, 2. , 2.5, 3. , 3.5, 4. , 4.5, 5. ]),\n", | |
" <a list of 1 Patch objects>)" | |
] | |
}, | |
"execution_count": 4, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"fig,ax = plt.subplots(num=\"HIST\")\n", | |
"ax.rhist(h1, histtype=\"step\", color=\"b\")" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"The `rhist` method mimics the\n", | |
"[`Axes.hist`](http://matplotlib.org/api/_as_gen/matplotlib.axes.Axes.hist.html#matplotlib.axes.Axes.hist)\n", | |
"method from matplotlib as closely as possible, but all arguments related to binning\n", | |
"the dataset are not necessary in this case, since an exsiting histogram object is passed.\n", | |
"`histtye=\"step\"` is the matplotlib value that corresponds to `HIST` (the default is `bar`).\n", | |
"\n", | |
"Another thing to note here is that the defaults for chosing the axis limits and tick frequency\n", | |
"are quite different in matplotlib than in ROOT. Fortunately this is entirely customisable,\n", | |
"see e.g. [the official examples](http://matplotlib.org/gallery.html#ticks_and_spines).\n", | |
"The following method brings them closer to the ROOT default choices" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 5, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"def ticks_like_root(axes):\n", | |
" import matplotlib.ticker\n", | |
" axes.xaxis.set_major_locator(matplotlib.ticker.MaxNLocator(nbins=12, min_n_tickes=5))\n", | |
" axes.xaxis.set_minor_locator(matplotlib.ticker.AutoMinorLocator())\n", | |
" axes.yaxis.set_minor_locator(matplotlib.ticker.AutoMinorLocator())" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 6, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"application/javascript": [ | |
"/* Put everything inside the global mpl namespace */\n", | |
"window.mpl = {};\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", | |
" 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 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);\n", | |
" canvas.attr('height', height);\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'];\n", | |
" var y0 = fig.canvas.height - msg['y0'];\n", | |
" var x1 = msg['x1'];\n", | |
" var y1 = fig.canvas.height - msg['y1'];\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;\n", | |
" var y = canvas_pos.y;\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\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\"];\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", | |
" 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 + '\">');\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 dataURL = this.canvas.toDataURL();\n", | |
" this.cell_info[1]['text/html'] = '<img src=\"' + dataURL + '\">';\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.updated_canvas_event = function() {\n", | |
" // Tell IPython that the notebook contents must change.\n", | |
" IPython.notebook.set_dirty(true);\n", | |
" this.send_message(\"ack\", {});\n", | |
" var fig = this;\n", | |
" // Wait a second, then push the new image to the DOM so\n", | |
" // that it is saved nicely (might be nice to debounce this).\n", | |
" setTimeout(function () { fig.push_to_output() }, 1000);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._init_toolbar = function() {\n", | |
" var fig = this;\n", | |
"\n", | |
" var nav_element = $('<div/>')\n", | |
" nav_element.attr('style', 'width: 100%');\n", | |
" this.root.append(nav_element);\n", | |
"\n", | |
" // Define a callback function for later on.\n", | |
" function toolbar_event(event) {\n", | |
" return fig.toolbar_button_onclick(event['data']);\n", | |
" }\n", | |
" function toolbar_mouse_event(event) {\n", | |
" return fig.toolbar_button_onmouseover(event['data']);\n", | |
" }\n", | |
"\n", | |
" for(var toolbar_ind in mpl.toolbar_items){\n", | |
" var name = mpl.toolbar_items[toolbar_ind][0];\n", | |
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", | |
" var image = mpl.toolbar_items[toolbar_ind][2];\n", | |
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n", | |
"\n", | |
" if (!name) { continue; };\n", | |
"\n", | |
" var button = $('<button class=\"btn btn-default\" href=\"#\" title=\"' + name + '\"><i class=\"fa ' + image + ' fa-lg\"></i></button>');\n", | |
" button.click(method_name, toolbar_event);\n", | |
" button.mouseover(tooltip, toolbar_mouse_event);\n", | |
" nav_element.append(button);\n", | |
" }\n", | |
"\n", | |
" // Add the status bar.\n", | |
" var status_bar = $('<span class=\"mpl-message\" style=\"text-align:right; float: right;\"/>');\n", | |
" nav_element.append(status_bar);\n", | |
" this.message = status_bar[0];\n", | |
"\n", | |
" // Add the close button to the window.\n", | |
" var buttongrp = $('<div class=\"btn-group inline pull-right\"></div>');\n", | |
" var button = $('<button class=\"btn btn-mini btn-primary\" href=\"#\" title=\"Stop Interaction\"><i class=\"fa fa-power-off icon-remove icon-large\"></i></button>');\n", | |
" button.click(function (evt) { fig.handle_close(fig, {}); } );\n", | |
" button.mouseover('Stop Interaction', toolbar_mouse_event);\n", | |
" buttongrp.append(button);\n", | |
" var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", | |
" titlebar.prepend(buttongrp);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._root_extra_style = function(el){\n", | |
" var fig = this\n", | |
" el.on(\"remove\", function(){\n", | |
"\tfig.close_ws(fig, {});\n", | |
" });\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._canvas_extra_style = function(el){\n", | |
" // this is important to make the div 'focusable\n", | |
" el.attr('tabindex', 0)\n", | |
" // reach out to IPython and tell the keyboard manager to turn it's self\n", | |
" // off when our div gets focus\n", | |
"\n", | |
" // location in version 3\n", | |
" if (IPython.notebook.keyboard_manager) {\n", | |
" IPython.notebook.keyboard_manager.register_events(el);\n", | |
" }\n", | |
" else {\n", | |
" // location in version 2\n", | |
" IPython.keyboard_manager.register_events(el);\n", | |
" }\n", | |
"\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._key_event_extra = function(event, name) {\n", | |
" var manager = IPython.notebook.keyboard_manager;\n", | |
" if (!manager)\n", | |
" manager = IPython.keyboard_manager;\n", | |
"\n", | |
" // Check for shift+enter\n", | |
" if (event.shiftKey && event.which == 13) {\n", | |
" this.canvas_div.blur();\n", | |
" event.shiftKey = false;\n", | |
" // Send a \"J\" for go to next cell\n", | |
" event.which = 74;\n", | |
" event.keyCode = 74;\n", | |
" manager.command_mode();\n", | |
" manager.handle_keydown(event);\n", | |
" }\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_save = function(fig, msg) {\n", | |
" fig.ondownload(fig, null);\n", | |
"}\n", | |
"\n", | |
"\n", | |
"mpl.find_output_cell = function(html_output) {\n", | |
" // Return the cell and output element which can be found *uniquely* in the notebook.\n", | |
" // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", | |
" // IPython event is triggered only after the cells have been serialised, which for\n", | |
" // our purposes (turning an active figure into a static one), is too late.\n", | |
" var cells = IPython.notebook.get_cells();\n", | |
" var ncells = cells.length;\n", | |
" for (var i=0; i<ncells; i++) {\n", | |
" var cell = cells[i];\n", | |
" if (cell.cell_type === 'code'){\n", | |
" for (var j=0; j<cell.output_area.outputs.length; j++) {\n", | |
" var data = cell.output_area.outputs[j];\n", | |
" if (data.data) {\n", | |
" // IPython >= 3 moved mimebundle to data attribute of output\n", | |
" data = data.data;\n", | |
" }\n", | |
" if (data['text/html'] == html_output) {\n", | |
" return [cell, data, j];\n", | |
" }\n", | |
" }\n", | |
" }\n", | |
" }\n", | |
"}\n", | |
"\n", | |
"// Register the function which deals with the matplotlib target/channel.\n", | |
"// The kernel may be null if the page has been refreshed.\n", | |
"if (IPython.notebook.kernel != null) {\n", | |
" IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", | |
"}\n" | |
], | |
"text/plain": [ | |
"<IPython.core.display.Javascript object>" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
}, | |
{ | |
"data": { | |
"text/html": [ | |
"<img src=\"data:image/png;base64,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\">" | |
], | |
"text/plain": [ | |
"<IPython.core.display.HTML object>" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
} | |
], | |
"source": [ | |
"fig,ax = plt.subplots(num=\"HIST2\")\n", | |
"ax.rhist(h1, histtype=\"step\", color=\"b\")\n", | |
"ax.set_xlim(-5.,5.)\n", | |
"ticks_like_root(ax)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Very often, histograms also have systematic uncertainties, or are scaled, so the uncertainty\n", | |
"also needs to be displayed. A simple way to do this is by drawing a point with error bars\n", | |
"for each bin (with the x-axis error bars usually indicating the bin width)." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 7, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"image/png": "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\njoB3oO+g0gAAAABJRU5ErkJggg==\n", | |
"text/plain": [ | |
"<IPython.core.display.Image object>" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
} | |
], | |
"source": [ | |
"cE1P = ROOT.TCanvas(\"cE1P\")\n", | |
"h1.SetLineColor(ROOT.kRed)\n", | |
"h1.SetMarkerColor(ROOT.kRed)\n", | |
"h1.SetMarkerStyle(ROOT.kFullCircle)\n", | |
"h1.Draw(\"P,E1\")\n", | |
"cE1P.Draw()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 8, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"application/javascript": [ | |
"/* Put everything inside the global mpl namespace */\n", | |
"window.mpl = {};\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", | |
" 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 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);\n", | |
" canvas.attr('height', height);\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'];\n", | |
" var y0 = fig.canvas.height - msg['y0'];\n", | |
" var x1 = msg['x1'];\n", | |
" var y1 = fig.canvas.height - msg['y1'];\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;\n", | |
" var y = canvas_pos.y;\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\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\"];\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", | |
" 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 + '\">');\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 dataURL = this.canvas.toDataURL();\n", | |
" this.cell_info[1]['text/html'] = '<img src=\"' + dataURL + '\">';\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.updated_canvas_event = function() {\n", | |
" // Tell IPython that the notebook contents must change.\n", | |
" IPython.notebook.set_dirty(true);\n", | |
" this.send_message(\"ack\", {});\n", | |
" var fig = this;\n", | |
" // Wait a second, then push the new image to the DOM so\n", | |
" // that it is saved nicely (might be nice to debounce this).\n", | |
" setTimeout(function () { fig.push_to_output() }, 1000);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._init_toolbar = function() {\n", | |
" var fig = this;\n", | |
"\n", | |
" var nav_element = $('<div/>')\n", | |
" nav_element.attr('style', 'width: 100%');\n", | |
" this.root.append(nav_element);\n", | |
"\n", | |
" // Define a callback function for later on.\n", | |
" function toolbar_event(event) {\n", | |
" return fig.toolbar_button_onclick(event['data']);\n", | |
" }\n", | |
" function toolbar_mouse_event(event) {\n", | |
" return fig.toolbar_button_onmouseover(event['data']);\n", | |
" }\n", | |
"\n", | |
" for(var toolbar_ind in mpl.toolbar_items){\n", | |
" var name = mpl.toolbar_items[toolbar_ind][0];\n", | |
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", | |
" var image = mpl.toolbar_items[toolbar_ind][2];\n", | |
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n", | |
"\n", | |
" if (!name) { continue; };\n", | |
"\n", | |
" var button = $('<button class=\"btn btn-default\" href=\"#\" title=\"' + name + '\"><i class=\"fa ' + image + ' fa-lg\"></i></button>');\n", | |
" button.click(method_name, toolbar_event);\n", | |
" button.mouseover(tooltip, toolbar_mouse_event);\n", | |
" nav_element.append(button);\n", | |
" }\n", | |
"\n", | |
" // Add the status bar.\n", | |
" var status_bar = $('<span class=\"mpl-message\" style=\"text-align:right; float: right;\"/>');\n", | |
" nav_element.append(status_bar);\n", | |
" this.message = status_bar[0];\n", | |
"\n", | |
" // Add the close button to the window.\n", | |
" var buttongrp = $('<div class=\"btn-group inline pull-right\"></div>');\n", | |
" var button = $('<button class=\"btn btn-mini btn-primary\" href=\"#\" title=\"Stop Interaction\"><i class=\"fa fa-power-off icon-remove icon-large\"></i></button>');\n", | |
" button.click(function (evt) { fig.handle_close(fig, {}); } );\n", | |
" button.mouseover('Stop Interaction', toolbar_mouse_event);\n", | |
" buttongrp.append(button);\n", | |
" var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", | |
" titlebar.prepend(buttongrp);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._root_extra_style = function(el){\n", | |
" var fig = this\n", | |
" el.on(\"remove\", function(){\n", | |
"\tfig.close_ws(fig, {});\n", | |
" });\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._canvas_extra_style = function(el){\n", | |
" // this is important to make the div 'focusable\n", | |
" el.attr('tabindex', 0)\n", | |
" // reach out to IPython and tell the keyboard manager to turn it's self\n", | |
" // off when our div gets focus\n", | |
"\n", | |
" // location in version 3\n", | |
" if (IPython.notebook.keyboard_manager) {\n", | |
" IPython.notebook.keyboard_manager.register_events(el);\n", | |
" }\n", | |
" else {\n", | |
" // location in version 2\n", | |
" IPython.keyboard_manager.register_events(el);\n", | |
" }\n", | |
"\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._key_event_extra = function(event, name) {\n", | |
" var manager = IPython.notebook.keyboard_manager;\n", | |
" if (!manager)\n", | |
" manager = IPython.keyboard_manager;\n", | |
"\n", | |
" // Check for shift+enter\n", | |
" if (event.shiftKey && event.which == 13) {\n", | |
" this.canvas_div.blur();\n", | |
" event.shiftKey = false;\n", | |
" // Send a \"J\" for go to next cell\n", | |
" event.which = 74;\n", | |
" event.keyCode = 74;\n", | |
" manager.command_mode();\n", | |
" manager.handle_keydown(event);\n", | |
" }\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_save = function(fig, msg) {\n", | |
" fig.ondownload(fig, null);\n", | |
"}\n", | |
"\n", | |
"\n", | |
"mpl.find_output_cell = function(html_output) {\n", | |
" // Return the cell and output element which can be found *uniquely* in the notebook.\n", | |
" // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", | |
" // IPython event is triggered only after the cells have been serialised, which for\n", | |
" // our purposes (turning an active figure into a static one), is too late.\n", | |
" var cells = IPython.notebook.get_cells();\n", | |
" var ncells = cells.length;\n", | |
" for (var i=0; i<ncells; i++) {\n", | |
" var cell = cells[i];\n", | |
" if (cell.cell_type === 'code'){\n", | |
" for (var j=0; j<cell.output_area.outputs.length; j++) {\n", | |
" var data = cell.output_area.outputs[j];\n", | |
" if (data.data) {\n", | |
" // IPython >= 3 moved mimebundle to data attribute of output\n", | |
" data = data.data;\n", | |
" }\n", | |
" if (data['text/html'] == html_output) {\n", | |
" return [cell, data, j];\n", | |
" }\n", | |
" }\n", | |
" }\n", | |
" }\n", | |
"}\n", | |
"\n", | |
"// Register the function which deals with the matplotlib target/channel.\n", | |
"// The kernel may be null if the page has been refreshed.\n", | |
"if (IPython.notebook.kernel != null) {\n", | |
" IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", | |
"}\n" | |
], | |
"text/plain": [ | |
"<IPython.core.display.Javascript object>" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
}, | |
{ | |
"data": { | |
"text/html": [ | |
"<img src=\"data:image/png;base64,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\">" | |
], | |
"text/plain": [ | |
"<IPython.core.display.HTML object>" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
} | |
], | |
"source": [ | |
"fig,ax = plt.subplots(num=\"E1P\")\n", | |
"ax.rerrorbar(h1, kind=\"bar\", fmt=\"ro\", mec=\"r\")\n", | |
"ax.set_xlim(-5., 5.)\n", | |
"ax.set_ylim(ymin=0.)\n", | |
"ticks_like_root(ax)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"In addition to the options known from\n", | |
"[`Axes.errorbar`](http://matplotlib.org/api/_as_gen/matplotlib.axes.Axes.errorbar.html#matplotlib.axes.Axes.errorbar),\n", | |
"with the `kind=\"bar\"` option, `rerrorbar` can also be used to draw error \"boxes\" (`E2`),\n", | |
"with `kind='box'`, and error bands (`E3`), with `kind=\"band\"`, e.g." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 9, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"image/png": "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\nRU5ErkJggg==\n", | |
"text/plain": [ | |
"<IPython.core.display.Image object>" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
} | |
], | |
"source": [ | |
"cE2H = ROOT.TCanvas(\"cE2H\")\n", | |
"h1.SetMarkerStyle(0)\n", | |
"h1.SetLineColor(ROOT.kGreen)\n", | |
"h1.DrawCopy(\"HIST\")\n", | |
"h1.SetFillColorAlpha(ROOT.kGreen, .3)\n", | |
"h1.Draw(\"E2,SAME\")\n", | |
"cE2H.Draw()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 10, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"application/javascript": [ | |
"/* Put everything inside the global mpl namespace */\n", | |
"window.mpl = {};\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", | |
" 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 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);\n", | |
" canvas.attr('height', height);\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'];\n", | |
" var y0 = fig.canvas.height - msg['y0'];\n", | |
" var x1 = msg['x1'];\n", | |
" var y1 = fig.canvas.height - msg['y1'];\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;\n", | |
" var y = canvas_pos.y;\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\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\"];\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", | |
" 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 + '\">');\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 dataURL = this.canvas.toDataURL();\n", | |
" this.cell_info[1]['text/html'] = '<img src=\"' + dataURL + '\">';\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.updated_canvas_event = function() {\n", | |
" // Tell IPython that the notebook contents must change.\n", | |
" IPython.notebook.set_dirty(true);\n", | |
" this.send_message(\"ack\", {});\n", | |
" var fig = this;\n", | |
" // Wait a second, then push the new image to the DOM so\n", | |
" // that it is saved nicely (might be nice to debounce this).\n", | |
" setTimeout(function () { fig.push_to_output() }, 1000);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._init_toolbar = function() {\n", | |
" var fig = this;\n", | |
"\n", | |
" var nav_element = $('<div/>')\n", | |
" nav_element.attr('style', 'width: 100%');\n", | |
" this.root.append(nav_element);\n", | |
"\n", | |
" // Define a callback function for later on.\n", | |
" function toolbar_event(event) {\n", | |
" return fig.toolbar_button_onclick(event['data']);\n", | |
" }\n", | |
" function toolbar_mouse_event(event) {\n", | |
" return fig.toolbar_button_onmouseover(event['data']);\n", | |
" }\n", | |
"\n", | |
" for(var toolbar_ind in mpl.toolbar_items){\n", | |
" var name = mpl.toolbar_items[toolbar_ind][0];\n", | |
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", | |
" var image = mpl.toolbar_items[toolbar_ind][2];\n", | |
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n", | |
"\n", | |
" if (!name) { continue; };\n", | |
"\n", | |
" var button = $('<button class=\"btn btn-default\" href=\"#\" title=\"' + name + '\"><i class=\"fa ' + image + ' fa-lg\"></i></button>');\n", | |
" button.click(method_name, toolbar_event);\n", | |
" button.mouseover(tooltip, toolbar_mouse_event);\n", | |
" nav_element.append(button);\n", | |
" }\n", | |
"\n", | |
" // Add the status bar.\n", | |
" var status_bar = $('<span class=\"mpl-message\" style=\"text-align:right; float: right;\"/>');\n", | |
" nav_element.append(status_bar);\n", | |
" this.message = status_bar[0];\n", | |
"\n", | |
" // Add the close button to the window.\n", | |
" var buttongrp = $('<div class=\"btn-group inline pull-right\"></div>');\n", | |
" var button = $('<button class=\"btn btn-mini btn-primary\" href=\"#\" title=\"Stop Interaction\"><i class=\"fa fa-power-off icon-remove icon-large\"></i></button>');\n", | |
" button.click(function (evt) { fig.handle_close(fig, {}); } );\n", | |
" button.mouseover('Stop Interaction', toolbar_mouse_event);\n", | |
" buttongrp.append(button);\n", | |
" var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", | |
" titlebar.prepend(buttongrp);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._root_extra_style = function(el){\n", | |
" var fig = this\n", | |
" el.on(\"remove\", function(){\n", | |
"\tfig.close_ws(fig, {});\n", | |
" });\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._canvas_extra_style = function(el){\n", | |
" // this is important to make the div 'focusable\n", | |
" el.attr('tabindex', 0)\n", | |
" // reach out to IPython and tell the keyboard manager to turn it's self\n", | |
" // off when our div gets focus\n", | |
"\n", | |
" // location in version 3\n", | |
" if (IPython.notebook.keyboard_manager) {\n", | |
" IPython.notebook.keyboard_manager.register_events(el);\n", | |
" }\n", | |
" else {\n", | |
" // location in version 2\n", | |
" IPython.keyboard_manager.register_events(el);\n", | |
" }\n", | |
"\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._key_event_extra = function(event, name) {\n", | |
" var manager = IPython.notebook.keyboard_manager;\n", | |
" if (!manager)\n", | |
" manager = IPython.keyboard_manager;\n", | |
"\n", | |
" // Check for shift+enter\n", | |
" if (event.shiftKey && event.which == 13) {\n", | |
" this.canvas_div.blur();\n", | |
" event.shiftKey = false;\n", | |
" // Send a \"J\" for go to next cell\n", | |
" event.which = 74;\n", | |
" event.keyCode = 74;\n", | |
" manager.command_mode();\n", | |
" manager.handle_keydown(event);\n", | |
" }\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_save = function(fig, msg) {\n", | |
" fig.ondownload(fig, null);\n", | |
"}\n", | |
"\n", | |
"\n", | |
"mpl.find_output_cell = function(html_output) {\n", | |
" // Return the cell and output element which can be found *uniquely* in the notebook.\n", | |
" // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", | |
" // IPython event is triggered only after the cells have been serialised, which for\n", | |
" // our purposes (turning an active figure into a static one), is too late.\n", | |
" var cells = IPython.notebook.get_cells();\n", | |
" var ncells = cells.length;\n", | |
" for (var i=0; i<ncells; i++) {\n", | |
" var cell = cells[i];\n", | |
" if (cell.cell_type === 'code'){\n", | |
" for (var j=0; j<cell.output_area.outputs.length; j++) {\n", | |
" var data = cell.output_area.outputs[j];\n", | |
" if (data.data) {\n", | |
" // IPython >= 3 moved mimebundle to data attribute of output\n", | |
" data = data.data;\n", | |
" }\n", | |
" if (data['text/html'] == html_output) {\n", | |
" return [cell, data, j];\n", | |
" }\n", | |
" }\n", | |
" }\n", | |
" }\n", | |
"}\n", | |
"\n", | |
"// Register the function which deals with the matplotlib target/channel.\n", | |
"// The kernel may be null if the page has been refreshed.\n", | |
"if (IPython.notebook.kernel != null) {\n", | |
" IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", | |
"}\n" | |
], | |
"text/plain": [ | |
"<IPython.core.display.Javascript object>" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
}, | |
{ | |
"data": { | |
"text/html": [ | |
"<img src=\"data:image/png;base64,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\">" | |
], | |
"text/plain": [ | |
"<IPython.core.display.HTML object>" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
} | |
], | |
"source": [ | |
"fig,ax = plt.subplots(num=\"E2H\")\n", | |
"ax.rhist(h1, histtype=\"step\", color=\"g\")\n", | |
"ax.rerrorbar(h1, kind=\"box\", color=\"green\", alpha=.3, lw=0)\n", | |
"ax.set_xlim(-5., 5.)\n", | |
"ax.set_ylim(ymin=0.)\n", | |
"ticks_like_root(ax)" | |
] | |
} | |
], | |
"metadata": { | |
"kernelspec": { | |
"display_name": "Python 2", | |
"language": "python", | |
"name": "python2" | |
}, | |
"language_info": { | |
"codemirror_mode": { | |
"name": "ipython", | |
"version": 2 | |
}, | |
"file_extension": ".py", | |
"mimetype": "text/x-python", | |
"name": "python", | |
"nbconvert_exporter": "python", | |
"pygments_lexer": "ipython2", | |
"version": "2.7.16" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 2 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment