diff --git a/cmi_scripts/mpdf/MnOpdfgui.ddp b/cmi_scripts/mpdf/MnOpdfgui.ddp
new file mode 100644
index 0000000..e67f232
Binary files /dev/null and b/cmi_scripts/mpdf/MnOpdfgui.ddp differ
diff --git a/cmi_scripts/mpdf/example_SrFit.ipynb b/cmi_scripts/mpdf/example_SrFit.ipynb
new file mode 100644
index 0000000..1225f7b
--- /dev/null
+++ b/cmi_scripts/mpdf/example_SrFit.ipynb
@@ -0,0 +1,5577 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "### Import the necessary libraries\n",
+ "import numpy as np\n",
+ "import matplotlib.pyplot as plt\n",
+ "from diffpy.mpdf import *\n",
+ "from diffpy.Structure import loadStructure\n",
+ "\n",
+ "### Set all plots to be inline\n",
+ "%matplotlib notebook"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Perform a simple mPDF fit to MnO"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Load the data into a Profile object"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "PDFguiFile = 'MnOpdfgui.ddp'\n",
+ "r,d = getDiffData(PDFguiFile, 0) ### extract the fit residual from the atomic PDF fit done in PDFgui\n",
+ "\n",
+ "from diffpy.srfit.fitbase import Profile\n",
+ "\n",
+ "profile = Profile()\n",
+ "profile.setObservedProfile(r, d)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Make the magnetic structure"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "/home/ben/anaconda/envs/mpdfdev/lib/python2.7/site-packages/diffpy.Structure-1.3.2-py2.7.egg/diffpy/Structure/lattice.py:125: FutureWarning: comparison to `None` will result in an elementwise object comparison in the future.\n",
+ " if [a, b, c, alpha, beta, gamma, base] == 7*[None]:\n"
+ ]
+ },
+ {
+ "data": {
+ "application/javascript": [
+ "/* Put everything inside the global mpl namespace */\n",
+ "window.mpl = {};\n",
+ "\n",
+ "\n",
+ "mpl.get_websocket_type = function() {\n",
+ " if (typeof(WebSocket) !== 'undefined') {\n",
+ " return WebSocket;\n",
+ " } else if (typeof(MozWebSocket) !== 'undefined') {\n",
+ " return MozWebSocket;\n",
+ " } else {\n",
+ " alert('Your browser does not have WebSocket support.' +\n",
+ " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
+ " 'Firefox 4 and 5 are also supported but you ' +\n",
+ " 'have to enable WebSockets in about:config.');\n",
+ " };\n",
+ "}\n",
+ "\n",
+ "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n",
+ " this.id = figure_id;\n",
+ "\n",
+ " this.ws = websocket;\n",
+ "\n",
+ " this.supports_binary = (this.ws.binaryType != undefined);\n",
+ "\n",
+ " if (!this.supports_binary) {\n",
+ " var warnings = document.getElementById(\"mpl-warnings\");\n",
+ " if (warnings) {\n",
+ " warnings.style.display = 'block';\n",
+ " warnings.textContent = (\n",
+ " \"This browser does not support binary websocket messages. \" +\n",
+ " \"Performance may be slow.\");\n",
+ " }\n",
+ " }\n",
+ "\n",
+ " this.imageObj = new Image();\n",
+ "\n",
+ " this.context = undefined;\n",
+ " this.message = undefined;\n",
+ " this.canvas = undefined;\n",
+ " this.rubberband_canvas = undefined;\n",
+ " this.rubberband_context = undefined;\n",
+ " this.format_dropdown = undefined;\n",
+ "\n",
+ " this.image_mode = 'full';\n",
+ "\n",
+ " this.root = $('
');\n",
+ " this._root_extra_style(this.root)\n",
+ " this.root.attr('style', 'display: inline-block');\n",
+ "\n",
+ " $(parent_element).append(this.root);\n",
+ "\n",
+ " this._init_header(this);\n",
+ " this._init_canvas(this);\n",
+ " this._init_toolbar(this);\n",
+ "\n",
+ " var fig = this;\n",
+ "\n",
+ " this.waiting = false;\n",
+ "\n",
+ " this.ws.onopen = function () {\n",
+ " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n",
+ " fig.send_message(\"send_image_mode\", {});\n",
+ " if (mpl.ratio != 1) {\n",
+ " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n",
+ " }\n",
+ " fig.send_message(\"refresh\", {});\n",
+ " }\n",
+ "\n",
+ " this.imageObj.onload = function() {\n",
+ " if (fig.image_mode == 'full') {\n",
+ " // Full images could contain transparency (where diff images\n",
+ " // almost always do), so we need to clear the canvas so that\n",
+ " // there is no ghosting.\n",
+ " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
+ " }\n",
+ " fig.context.drawImage(fig.imageObj, 0, 0);\n",
+ " };\n",
+ "\n",
+ " this.imageObj.onunload = function() {\n",
+ " this.ws.close();\n",
+ " }\n",
+ "\n",
+ " this.ws.onmessage = this._make_on_message_function(this);\n",
+ "\n",
+ " this.ondownload = ondownload;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._init_header = function() {\n",
+ " var titlebar = $(\n",
+ " '');\n",
+ " var titletext = $(\n",
+ " '');\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 = $('');\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 = $('');\n",
+ " canvas.addClass('mpl-canvas');\n",
+ " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n",
+ "\n",
+ " this.canvas = canvas[0];\n",
+ " this.context = canvas[0].getContext(\"2d\");\n",
+ "\n",
+ " var backingStore = this.context.backingStorePixelRatio ||\n",
+ "\tthis.context.webkitBackingStorePixelRatio ||\n",
+ "\tthis.context.mozBackingStorePixelRatio ||\n",
+ "\tthis.context.msBackingStorePixelRatio ||\n",
+ "\tthis.context.oBackingStorePixelRatio ||\n",
+ "\tthis.context.backingStorePixelRatio || 1;\n",
+ "\n",
+ " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n",
+ "\n",
+ " var rubberband = $('');\n",
+ " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n",
+ "\n",
+ " var pass_mouse_events = true;\n",
+ "\n",
+ " canvas_div.resizable({\n",
+ " start: function(event, ui) {\n",
+ " pass_mouse_events = false;\n",
+ " },\n",
+ " resize: function(event, ui) {\n",
+ " fig.request_resize(ui.size.width, ui.size.height);\n",
+ " },\n",
+ " stop: function(event, ui) {\n",
+ " pass_mouse_events = true;\n",
+ " fig.request_resize(ui.size.width, ui.size.height);\n",
+ " },\n",
+ " });\n",
+ "\n",
+ " function mouse_event_fn(event) {\n",
+ " if (pass_mouse_events)\n",
+ " return fig.mouse_event(event, event['data']);\n",
+ " }\n",
+ "\n",
+ " rubberband.mousedown('button_press', mouse_event_fn);\n",
+ " rubberband.mouseup('button_release', mouse_event_fn);\n",
+ " // Throttle sequential mouse events to 1 every 20ms.\n",
+ " rubberband.mousemove('motion_notify', mouse_event_fn);\n",
+ "\n",
+ " rubberband.mouseenter('figure_enter', mouse_event_fn);\n",
+ " rubberband.mouseleave('figure_leave', mouse_event_fn);\n",
+ "\n",
+ " canvas_div.on(\"wheel\", function (event) {\n",
+ " event = event.originalEvent;\n",
+ " event['data'] = 'scroll'\n",
+ " if (event.deltaY < 0) {\n",
+ " event.step = 1;\n",
+ " } else {\n",
+ " event.step = -1;\n",
+ " }\n",
+ " mouse_event_fn(event);\n",
+ " });\n",
+ "\n",
+ " canvas_div.append(canvas);\n",
+ " canvas_div.append(rubberband);\n",
+ "\n",
+ " this.rubberband = rubberband;\n",
+ " this.rubberband_canvas = rubberband[0];\n",
+ " this.rubberband_context = rubberband[0].getContext(\"2d\");\n",
+ " this.rubberband_context.strokeStyle = \"#000000\";\n",
+ "\n",
+ " this._resize_canvas = function(width, height) {\n",
+ " // Keep the size of the canvas, canvas container, and rubber band\n",
+ " // canvas in synch.\n",
+ " canvas_div.css('width', width)\n",
+ " canvas_div.css('height', height)\n",
+ "\n",
+ " canvas.attr('width', width * mpl.ratio);\n",
+ " canvas.attr('height', height * mpl.ratio);\n",
+ " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n",
+ "\n",
+ " rubberband.attr('width', width);\n",
+ " rubberband.attr('height', height);\n",
+ " }\n",
+ "\n",
+ " // Set the figure to an initial 600x600px, this will subsequently be updated\n",
+ " // upon first draw.\n",
+ " this._resize_canvas(600, 600);\n",
+ "\n",
+ " // Disable right mouse context menu.\n",
+ " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n",
+ " return false;\n",
+ " });\n",
+ "\n",
+ " function set_focus () {\n",
+ " canvas.focus();\n",
+ " canvas_div.focus();\n",
+ " }\n",
+ "\n",
+ " window.setTimeout(set_focus, 100);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._init_toolbar = function() {\n",
+ " var fig = this;\n",
+ "\n",
+ " var nav_element = $('')\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 = $('');\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 = $('');\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 = $('');\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 = $('');\n",
+ "\n",
+ " var fmt_picker = $('');\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",
+ " '', {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 = $('');\n",
+ " nav_element.append(status_bar);\n",
+ " this.message = status_bar[0];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n",
+ " // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n",
+ " // which will in turn request a refresh of the image.\n",
+ " this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.send_message = function(type, properties) {\n",
+ " properties['type'] = type;\n",
+ " properties['figure_id'] = this.id;\n",
+ " this.ws.send(JSON.stringify(properties));\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.send_draw_message = function() {\n",
+ " if (!this.waiting) {\n",
+ " this.waiting = true;\n",
+ " this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n",
+ " }\n",
+ "}\n",
+ "\n",
+ "\n",
+ "mpl.figure.prototype.handle_save = function(fig, msg) {\n",
+ " var format_dropdown = fig.format_dropdown;\n",
+ " var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n",
+ " fig.ondownload(fig, format);\n",
+ "}\n",
+ "\n",
+ "\n",
+ "mpl.figure.prototype.handle_resize = function(fig, msg) {\n",
+ " var size = msg['size'];\n",
+ " if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n",
+ " fig._resize_canvas(size[0], size[1]);\n",
+ " fig.send_message(\"refresh\", {});\n",
+ " };\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n",
+ " var x0 = msg['x0'] / mpl.ratio;\n",
+ " var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n",
+ " var x1 = msg['x1'] / mpl.ratio;\n",
+ " var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n",
+ " x0 = Math.floor(x0) + 0.5;\n",
+ " y0 = Math.floor(y0) + 0.5;\n",
+ " x1 = Math.floor(x1) + 0.5;\n",
+ " y1 = Math.floor(y1) + 0.5;\n",
+ " var min_x = Math.min(x0, x1);\n",
+ " var min_y = Math.min(y0, y1);\n",
+ " var width = Math.abs(x1 - x0);\n",
+ " var height = Math.abs(y1 - y0);\n",
+ "\n",
+ " fig.rubberband_context.clearRect(\n",
+ " 0, 0, fig.canvas.width, fig.canvas.height);\n",
+ "\n",
+ " fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n",
+ " // Updates the figure title.\n",
+ " fig.header.textContent = msg['label'];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_cursor = function(fig, msg) {\n",
+ " var cursor = msg['cursor'];\n",
+ " switch(cursor)\n",
+ " {\n",
+ " case 0:\n",
+ " cursor = 'pointer';\n",
+ " break;\n",
+ " case 1:\n",
+ " cursor = 'default';\n",
+ " break;\n",
+ " case 2:\n",
+ " cursor = 'crosshair';\n",
+ " break;\n",
+ " case 3:\n",
+ " cursor = 'move';\n",
+ " break;\n",
+ " }\n",
+ " fig.rubberband_canvas.style.cursor = cursor;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_message = function(fig, msg) {\n",
+ " fig.message.textContent = msg['message'];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_draw = function(fig, msg) {\n",
+ " // Request the server to send over a new figure.\n",
+ " fig.send_draw_message();\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n",
+ " fig.image_mode = msg['mode'];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.updated_canvas_event = function() {\n",
+ " // Called whenever the canvas gets updated.\n",
+ " this.send_message(\"ack\", {});\n",
+ "}\n",
+ "\n",
+ "// A function to construct a web socket function for onmessage handling.\n",
+ "// Called in the figure constructor.\n",
+ "mpl.figure.prototype._make_on_message_function = function(fig) {\n",
+ " return function socket_on_message(evt) {\n",
+ " if (evt.data instanceof Blob) {\n",
+ " /* FIXME: We get \"Resource interpreted as Image but\n",
+ " * transferred with MIME type text/plain:\" errors on\n",
+ " * Chrome. But how to set the MIME type? It doesn't seem\n",
+ " * to be part of the websocket stream */\n",
+ " evt.data.type = \"image/png\";\n",
+ "\n",
+ " /* Free the memory for the previous frames */\n",
+ " if (fig.imageObj.src) {\n",
+ " (window.URL || window.webkitURL).revokeObjectURL(\n",
+ " fig.imageObj.src);\n",
+ " }\n",
+ "\n",
+ " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
+ " evt.data);\n",
+ " fig.updated_canvas_event();\n",
+ " fig.waiting = false;\n",
+ " return;\n",
+ " }\n",
+ " else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n",
+ " fig.imageObj.src = evt.data;\n",
+ " fig.updated_canvas_event();\n",
+ " fig.waiting = false;\n",
+ " return;\n",
+ " }\n",
+ "\n",
+ " var msg = JSON.parse(evt.data);\n",
+ " var msg_type = msg['type'];\n",
+ "\n",
+ " // Call the \"handle_{type}\" callback, which takes\n",
+ " // the figure and JSON message as its only arguments.\n",
+ " try {\n",
+ " var callback = fig[\"handle_\" + msg_type];\n",
+ " } catch (e) {\n",
+ " console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n",
+ " return;\n",
+ " }\n",
+ "\n",
+ " if (callback) {\n",
+ " try {\n",
+ " // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n",
+ " callback(fig, msg);\n",
+ " } catch (e) {\n",
+ " console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n",
+ " }\n",
+ " }\n",
+ " };\n",
+ "}\n",
+ "\n",
+ "// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n",
+ "mpl.findpos = function(e) {\n",
+ " //this section is from http://www.quirksmode.org/js/events_properties.html\n",
+ " var targ;\n",
+ " if (!e)\n",
+ " e = window.event;\n",
+ " if (e.target)\n",
+ " targ = e.target;\n",
+ " else if (e.srcElement)\n",
+ " targ = e.srcElement;\n",
+ " if (targ.nodeType == 3) // defeat Safari bug\n",
+ " targ = targ.parentNode;\n",
+ "\n",
+ " // jQuery normalizes the pageX and pageY\n",
+ " // pageX,Y are the mouse positions relative to the document\n",
+ " // offset() returns the position of the element relative to the document\n",
+ " var x = e.pageX - $(targ).offset().left;\n",
+ " var y = e.pageY - $(targ).offset().top;\n",
+ "\n",
+ " return {\"x\": x, \"y\": y};\n",
+ "};\n",
+ "\n",
+ "/*\n",
+ " * return a copy of an object with only non-object keys\n",
+ " * we need this to avoid circular references\n",
+ " * http://stackoverflow.com/a/24161582/3208463\n",
+ " */\n",
+ "function simpleKeys (original) {\n",
+ " return Object.keys(original).reduce(function (obj, key) {\n",
+ " if (typeof original[key] !== 'object')\n",
+ " obj[key] = original[key]\n",
+ " return obj;\n",
+ " }, {});\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.mouse_event = function(event, name) {\n",
+ " var canvas_pos = mpl.findpos(event)\n",
+ "\n",
+ " if (name === 'button_press')\n",
+ " {\n",
+ " this.canvas.focus();\n",
+ " this.canvas_div.focus();\n",
+ " }\n",
+ "\n",
+ " var x = canvas_pos.x * mpl.ratio;\n",
+ " var y = canvas_pos.y * mpl.ratio;\n",
+ "\n",
+ " this.send_message(name, {x: x, y: y, button: event.button,\n",
+ " step: event.step,\n",
+ " guiEvent: simpleKeys(event)});\n",
+ "\n",
+ " /* This prevents the web browser from automatically changing to\n",
+ " * the text insertion cursor when the button is pressed. We want\n",
+ " * to control all of the cursor setting manually through the\n",
+ " * 'cursor' event from matplotlib */\n",
+ " event.preventDefault();\n",
+ " return false;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._key_event_extra = function(event, name) {\n",
+ " // Handle any extra behaviour associated with a key event\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.key_event = function(event, name) {\n",
+ "\n",
+ " // Prevent repeat events\n",
+ " if (name == 'key_press')\n",
+ " {\n",
+ " if (event.which === this._key)\n",
+ " return;\n",
+ " else\n",
+ " this._key = event.which;\n",
+ " }\n",
+ " if (name == 'key_release')\n",
+ " this._key = null;\n",
+ "\n",
+ " var value = '';\n",
+ " if (event.ctrlKey && event.which != 17)\n",
+ " value += \"ctrl+\";\n",
+ " if (event.altKey && event.which != 18)\n",
+ " value += \"alt+\";\n",
+ " if (event.shiftKey && event.which != 16)\n",
+ " value += \"shift+\";\n",
+ "\n",
+ " value += 'k';\n",
+ " value += event.which.toString();\n",
+ "\n",
+ " this._key_event_extra(event, name);\n",
+ "\n",
+ " this.send_message(name, {key: value,\n",
+ " guiEvent: simpleKeys(event)});\n",
+ " return false;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.toolbar_button_onclick = function(name) {\n",
+ " if (name == 'download') {\n",
+ " this.handle_save(this, null);\n",
+ " } else {\n",
+ " this.send_message(\"toolbar_button\", {name: name});\n",
+ " }\n",
+ "};\n",
+ "\n",
+ "mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n",
+ " this.message.textContent = tooltip;\n",
+ "};\n",
+ "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n",
+ "\n",
+ "mpl.extensions = [\"eps\", \"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(\"\");\n",
+ " if (!fig.cell_info) {\n",
+ " console.error(\"Failed to find cell for figure\", id, fig);\n",
+ " return;\n",
+ " }\n",
+ "\n",
+ " var output_index = fig.cell_info[2]\n",
+ " var cell = fig.cell_info[0];\n",
+ "\n",
+ "};\n",
+ "\n",
+ "mpl.figure.prototype.handle_close = function(fig, msg) {\n",
+ " var width = fig.canvas.width/mpl.ratio\n",
+ " fig.root.unbind('remove')\n",
+ "\n",
+ " // Update the output cell to use the data from the current canvas.\n",
+ " fig.push_to_output();\n",
+ " var dataURL = fig.canvas.toDataURL();\n",
+ " // Re-enable the keyboard manager in IPython - without this line, in FF,\n",
+ " // the notebook keyboard shortcuts fail.\n",
+ " IPython.keyboard_manager.enable()\n",
+ " $(fig.parent_element).html('
');\n",
+ " fig.close_ws(fig, msg);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.close_ws = function(fig, msg){\n",
+ " fig.send_message('closing', msg);\n",
+ " // fig.ws.close()\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.push_to_output = function(remove_interactive) {\n",
+ " // Turn the data on the canvas into data in the output cell.\n",
+ " var width = this.canvas.width/mpl.ratio\n",
+ " var dataURL = this.canvas.toDataURL();\n",
+ " this.cell_info[1]['text/html'] = '
';\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 = $('')\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 = $('');\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 = $('');\n",
+ " nav_element.append(status_bar);\n",
+ " this.message = status_bar[0];\n",
+ "\n",
+ " // Add the close button to the window.\n",
+ " var buttongrp = $('');\n",
+ " var button = $('');\n",
+ " button.click(function (evt) { fig.handle_close(fig, {}); } );\n",
+ " button.mouseover('Stop Interaction', toolbar_mouse_event);\n",
+ " buttongrp.append(button);\n",
+ " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n",
+ " titlebar.prepend(buttongrp);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._root_extra_style = function(el){\n",
+ " var fig = this\n",
+ " el.on(\"remove\", function(){\n",
+ "\tfig.close_ws(fig, {});\n",
+ " });\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._canvas_extra_style = function(el){\n",
+ " // this is important to make the div 'focusable\n",
+ " el.attr('tabindex', 0)\n",
+ " // reach out to IPython and tell the keyboard manager to turn it's self\n",
+ " // off when our div gets focus\n",
+ "\n",
+ " // location in version 3\n",
+ " if (IPython.notebook.keyboard_manager) {\n",
+ " IPython.notebook.keyboard_manager.register_events(el);\n",
+ " }\n",
+ " else {\n",
+ " // location in version 2\n",
+ " IPython.keyboard_manager.register_events(el);\n",
+ " }\n",
+ "\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._key_event_extra = function(event, name) {\n",
+ " var manager = IPython.notebook.keyboard_manager;\n",
+ " if (!manager)\n",
+ " manager = IPython.keyboard_manager;\n",
+ "\n",
+ " // Check for shift+enter\n",
+ " if (event.shiftKey && event.which == 13) {\n",
+ " this.canvas_div.blur();\n",
+ " // select the cell after this one\n",
+ " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n",
+ " IPython.notebook.select(index + 1);\n",
+ " }\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_save = function(fig, msg) {\n",
+ " fig.ondownload(fig, null);\n",
+ "}\n",
+ "\n",
+ "\n",
+ "mpl.find_output_cell = function(html_output) {\n",
+ " // Return the cell and output element which can be found *uniquely* in the notebook.\n",
+ " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n",
+ " // IPython event is triggered only after the cells have been serialised, which for\n",
+ " // our purposes (turning an active figure into a static one), is too late.\n",
+ " var cells = IPython.notebook.get_cells();\n",
+ " var ncells = cells.length;\n",
+ " for (var i=0; i= 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": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/html": [
+ "
"
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "struc = getStrucFromPDFgui(PDFguiFile,0)\n",
+ "\n",
+ "svec = np.array([1.0,-1.0,0.0])\n",
+ "msp = MagSpecies(struc,magIdxs=[0,1,2,3],ffparamkey='Mn2',rmaxAtoms=50,basisvecs=svec,\n",
+ " kvecs=np.array([0.5,0.5,0.5]),label=str(0))\n",
+ "\n",
+ "mstr=MagStructure()\n",
+ "mstr.loadSpecies(msp)\n",
+ "mstr.makeAll()\n",
+ "\n",
+ "### Visualize the magnetic structure\n",
+ "uc = struc[:4].xyz\n",
+ "visatoms = uc.copy()\n",
+ "visatoms = np.concatenate((visatoms,visatoms+np.array([0,0,1]),visatoms+np.array([0,1,0]),visatoms+np.array([0,0,1])))\n",
+ "visatoms = struc.lattice.cartesian(visatoms)\n",
+ "visspins = mstr.spinsFromAtoms(visatoms,fractional=False)\n",
+ "mstr.visualize(visatoms,visspins)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Make the MPDFcalculator"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Warning: Your structure may not be big enough for your\n",
+ "desired calculation range.\n"
+ ]
+ }
+ ],
+ "source": [
+ "mc = MPDFcalculator(mstr,rmin=r.min(),rmax=r.max())"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Set up and perform the fit"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "### Make the FitContribution\n",
+ "\n",
+ "from diffpy.srfit.fitbase import FitContribution\n",
+ "mfit = FitContribution('mfit')\n",
+ "mfit.setProfile(profile)\n",
+ "\n",
+ "# Define the function that will calculate the mPDF\n",
+ "def mpdf(parascale, ordscale, damp):\n",
+ " mc.paraScale, mc.ordScale, mc.dampRate = parascale, ordscale, damp\n",
+ " dr = mc.calc(both=True)[2]\n",
+ " return dr\n",
+ "\n",
+ "mfit.registerFunction(mpdf)\n",
+ "mfit.setEquation(\"mpdf(parascale, ordscale, damp)\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ ""
+ ]
+ },
+ "execution_count": 6,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "### Make the FitRecipe and add the relevant variables\n",
+ "from diffpy.srfit.fitbase import FitRecipe\n",
+ "recipe = FitRecipe()\n",
+ "\n",
+ "# give the PDFContribution to the FitRecipe\n",
+ "recipe.addContribution(mfit)\n",
+ "\n",
+ "# add the mPDF variables\n",
+ "recipe.addVar(mfit.parascale, 4)\n",
+ "recipe.addVar(mfit.ordscale, 0.5)\n",
+ "recipe.addVar(mfit.damp, 0.01)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Refine using scipy's least-squares optimizer:\n",
+ " variables: ['parascale', 'ordscale', 'damp']\n",
+ " initial values: [ 4. 0.5 0.01]\n",
+ " final values: [ 2.8959563 1.23062246 0.00673758]\n"
+ ]
+ }
+ ],
+ "source": [
+ "### Run the refinement\n",
+ "\n",
+ "# Turn off printout of iteration number.\n",
+ "recipe.clearFitHooks()\n",
+ "\n",
+ "# Initial structural fit\n",
+ "print \"Refine using scipy's least-squares optimizer:\"\n",
+ "print \" variables:\", recipe.names\n",
+ "print \" initial values:\", recipe.values\n",
+ "\n",
+ "from scipy.optimize import least_squares\n",
+ "\n",
+ "least_squares(recipe.residual, recipe.values)\n",
+ "print \" final values:\", recipe.values"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Plot the result"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [
+ {
+ "data": {
+ "application/javascript": [
+ "/* Put everything inside the global mpl namespace */\n",
+ "window.mpl = {};\n",
+ "\n",
+ "\n",
+ "mpl.get_websocket_type = function() {\n",
+ " if (typeof(WebSocket) !== 'undefined') {\n",
+ " return WebSocket;\n",
+ " } else if (typeof(MozWebSocket) !== 'undefined') {\n",
+ " return MozWebSocket;\n",
+ " } else {\n",
+ " alert('Your browser does not have WebSocket support.' +\n",
+ " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
+ " 'Firefox 4 and 5 are also supported but you ' +\n",
+ " 'have to enable WebSockets in about:config.');\n",
+ " };\n",
+ "}\n",
+ "\n",
+ "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n",
+ " this.id = figure_id;\n",
+ "\n",
+ " this.ws = websocket;\n",
+ "\n",
+ " this.supports_binary = (this.ws.binaryType != undefined);\n",
+ "\n",
+ " if (!this.supports_binary) {\n",
+ " var warnings = document.getElementById(\"mpl-warnings\");\n",
+ " if (warnings) {\n",
+ " warnings.style.display = 'block';\n",
+ " warnings.textContent = (\n",
+ " \"This browser does not support binary websocket messages. \" +\n",
+ " \"Performance may be slow.\");\n",
+ " }\n",
+ " }\n",
+ "\n",
+ " this.imageObj = new Image();\n",
+ "\n",
+ " this.context = undefined;\n",
+ " this.message = undefined;\n",
+ " this.canvas = undefined;\n",
+ " this.rubberband_canvas = undefined;\n",
+ " this.rubberband_context = undefined;\n",
+ " this.format_dropdown = undefined;\n",
+ "\n",
+ " this.image_mode = 'full';\n",
+ "\n",
+ " this.root = $('');\n",
+ " this._root_extra_style(this.root)\n",
+ " this.root.attr('style', 'display: inline-block');\n",
+ "\n",
+ " $(parent_element).append(this.root);\n",
+ "\n",
+ " this._init_header(this);\n",
+ " this._init_canvas(this);\n",
+ " this._init_toolbar(this);\n",
+ "\n",
+ " var fig = this;\n",
+ "\n",
+ " this.waiting = false;\n",
+ "\n",
+ " this.ws.onopen = function () {\n",
+ " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n",
+ " fig.send_message(\"send_image_mode\", {});\n",
+ " if (mpl.ratio != 1) {\n",
+ " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n",
+ " }\n",
+ " fig.send_message(\"refresh\", {});\n",
+ " }\n",
+ "\n",
+ " this.imageObj.onload = function() {\n",
+ " if (fig.image_mode == 'full') {\n",
+ " // Full images could contain transparency (where diff images\n",
+ " // almost always do), so we need to clear the canvas so that\n",
+ " // there is no ghosting.\n",
+ " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
+ " }\n",
+ " fig.context.drawImage(fig.imageObj, 0, 0);\n",
+ " };\n",
+ "\n",
+ " this.imageObj.onunload = function() {\n",
+ " this.ws.close();\n",
+ " }\n",
+ "\n",
+ " this.ws.onmessage = this._make_on_message_function(this);\n",
+ "\n",
+ " this.ondownload = ondownload;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._init_header = function() {\n",
+ " var titlebar = $(\n",
+ " '');\n",
+ " var titletext = $(\n",
+ " '');\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 = $('');\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 = $('');\n",
+ " canvas.addClass('mpl-canvas');\n",
+ " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n",
+ "\n",
+ " this.canvas = canvas[0];\n",
+ " this.context = canvas[0].getContext(\"2d\");\n",
+ "\n",
+ " var backingStore = this.context.backingStorePixelRatio ||\n",
+ "\tthis.context.webkitBackingStorePixelRatio ||\n",
+ "\tthis.context.mozBackingStorePixelRatio ||\n",
+ "\tthis.context.msBackingStorePixelRatio ||\n",
+ "\tthis.context.oBackingStorePixelRatio ||\n",
+ "\tthis.context.backingStorePixelRatio || 1;\n",
+ "\n",
+ " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n",
+ "\n",
+ " var rubberband = $('');\n",
+ " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n",
+ "\n",
+ " var pass_mouse_events = true;\n",
+ "\n",
+ " canvas_div.resizable({\n",
+ " start: function(event, ui) {\n",
+ " pass_mouse_events = false;\n",
+ " },\n",
+ " resize: function(event, ui) {\n",
+ " fig.request_resize(ui.size.width, ui.size.height);\n",
+ " },\n",
+ " stop: function(event, ui) {\n",
+ " pass_mouse_events = true;\n",
+ " fig.request_resize(ui.size.width, ui.size.height);\n",
+ " },\n",
+ " });\n",
+ "\n",
+ " function mouse_event_fn(event) {\n",
+ " if (pass_mouse_events)\n",
+ " return fig.mouse_event(event, event['data']);\n",
+ " }\n",
+ "\n",
+ " rubberband.mousedown('button_press', mouse_event_fn);\n",
+ " rubberband.mouseup('button_release', mouse_event_fn);\n",
+ " // Throttle sequential mouse events to 1 every 20ms.\n",
+ " rubberband.mousemove('motion_notify', mouse_event_fn);\n",
+ "\n",
+ " rubberband.mouseenter('figure_enter', mouse_event_fn);\n",
+ " rubberband.mouseleave('figure_leave', mouse_event_fn);\n",
+ "\n",
+ " canvas_div.on(\"wheel\", function (event) {\n",
+ " event = event.originalEvent;\n",
+ " event['data'] = 'scroll'\n",
+ " if (event.deltaY < 0) {\n",
+ " event.step = 1;\n",
+ " } else {\n",
+ " event.step = -1;\n",
+ " }\n",
+ " mouse_event_fn(event);\n",
+ " });\n",
+ "\n",
+ " canvas_div.append(canvas);\n",
+ " canvas_div.append(rubberband);\n",
+ "\n",
+ " this.rubberband = rubberband;\n",
+ " this.rubberband_canvas = rubberband[0];\n",
+ " this.rubberband_context = rubberband[0].getContext(\"2d\");\n",
+ " this.rubberband_context.strokeStyle = \"#000000\";\n",
+ "\n",
+ " this._resize_canvas = function(width, height) {\n",
+ " // Keep the size of the canvas, canvas container, and rubber band\n",
+ " // canvas in synch.\n",
+ " canvas_div.css('width', width)\n",
+ " canvas_div.css('height', height)\n",
+ "\n",
+ " canvas.attr('width', width * mpl.ratio);\n",
+ " canvas.attr('height', height * mpl.ratio);\n",
+ " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n",
+ "\n",
+ " rubberband.attr('width', width);\n",
+ " rubberband.attr('height', height);\n",
+ " }\n",
+ "\n",
+ " // Set the figure to an initial 600x600px, this will subsequently be updated\n",
+ " // upon first draw.\n",
+ " this._resize_canvas(600, 600);\n",
+ "\n",
+ " // Disable right mouse context menu.\n",
+ " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n",
+ " return false;\n",
+ " });\n",
+ "\n",
+ " function set_focus () {\n",
+ " canvas.focus();\n",
+ " canvas_div.focus();\n",
+ " }\n",
+ "\n",
+ " window.setTimeout(set_focus, 100);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._init_toolbar = function() {\n",
+ " var fig = this;\n",
+ "\n",
+ " var nav_element = $('')\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 = $('');\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 = $('');\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 = $('');\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 = $('');\n",
+ "\n",
+ " var fmt_picker = $('');\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",
+ " '', {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 = $('');\n",
+ " nav_element.append(status_bar);\n",
+ " this.message = status_bar[0];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n",
+ " // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n",
+ " // which will in turn request a refresh of the image.\n",
+ " this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.send_message = function(type, properties) {\n",
+ " properties['type'] = type;\n",
+ " properties['figure_id'] = this.id;\n",
+ " this.ws.send(JSON.stringify(properties));\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.send_draw_message = function() {\n",
+ " if (!this.waiting) {\n",
+ " this.waiting = true;\n",
+ " this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n",
+ " }\n",
+ "}\n",
+ "\n",
+ "\n",
+ "mpl.figure.prototype.handle_save = function(fig, msg) {\n",
+ " var format_dropdown = fig.format_dropdown;\n",
+ " var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n",
+ " fig.ondownload(fig, format);\n",
+ "}\n",
+ "\n",
+ "\n",
+ "mpl.figure.prototype.handle_resize = function(fig, msg) {\n",
+ " var size = msg['size'];\n",
+ " if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n",
+ " fig._resize_canvas(size[0], size[1]);\n",
+ " fig.send_message(\"refresh\", {});\n",
+ " };\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n",
+ " var x0 = msg['x0'] / mpl.ratio;\n",
+ " var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n",
+ " var x1 = msg['x1'] / mpl.ratio;\n",
+ " var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n",
+ " x0 = Math.floor(x0) + 0.5;\n",
+ " y0 = Math.floor(y0) + 0.5;\n",
+ " x1 = Math.floor(x1) + 0.5;\n",
+ " y1 = Math.floor(y1) + 0.5;\n",
+ " var min_x = Math.min(x0, x1);\n",
+ " var min_y = Math.min(y0, y1);\n",
+ " var width = Math.abs(x1 - x0);\n",
+ " var height = Math.abs(y1 - y0);\n",
+ "\n",
+ " fig.rubberband_context.clearRect(\n",
+ " 0, 0, fig.canvas.width, fig.canvas.height);\n",
+ "\n",
+ " fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n",
+ " // Updates the figure title.\n",
+ " fig.header.textContent = msg['label'];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_cursor = function(fig, msg) {\n",
+ " var cursor = msg['cursor'];\n",
+ " switch(cursor)\n",
+ " {\n",
+ " case 0:\n",
+ " cursor = 'pointer';\n",
+ " break;\n",
+ " case 1:\n",
+ " cursor = 'default';\n",
+ " break;\n",
+ " case 2:\n",
+ " cursor = 'crosshair';\n",
+ " break;\n",
+ " case 3:\n",
+ " cursor = 'move';\n",
+ " break;\n",
+ " }\n",
+ " fig.rubberband_canvas.style.cursor = cursor;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_message = function(fig, msg) {\n",
+ " fig.message.textContent = msg['message'];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_draw = function(fig, msg) {\n",
+ " // Request the server to send over a new figure.\n",
+ " fig.send_draw_message();\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n",
+ " fig.image_mode = msg['mode'];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.updated_canvas_event = function() {\n",
+ " // Called whenever the canvas gets updated.\n",
+ " this.send_message(\"ack\", {});\n",
+ "}\n",
+ "\n",
+ "// A function to construct a web socket function for onmessage handling.\n",
+ "// Called in the figure constructor.\n",
+ "mpl.figure.prototype._make_on_message_function = function(fig) {\n",
+ " return function socket_on_message(evt) {\n",
+ " if (evt.data instanceof Blob) {\n",
+ " /* FIXME: We get \"Resource interpreted as Image but\n",
+ " * transferred with MIME type text/plain:\" errors on\n",
+ " * Chrome. But how to set the MIME type? It doesn't seem\n",
+ " * to be part of the websocket stream */\n",
+ " evt.data.type = \"image/png\";\n",
+ "\n",
+ " /* Free the memory for the previous frames */\n",
+ " if (fig.imageObj.src) {\n",
+ " (window.URL || window.webkitURL).revokeObjectURL(\n",
+ " fig.imageObj.src);\n",
+ " }\n",
+ "\n",
+ " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
+ " evt.data);\n",
+ " fig.updated_canvas_event();\n",
+ " fig.waiting = false;\n",
+ " return;\n",
+ " }\n",
+ " else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n",
+ " fig.imageObj.src = evt.data;\n",
+ " fig.updated_canvas_event();\n",
+ " fig.waiting = false;\n",
+ " return;\n",
+ " }\n",
+ "\n",
+ " var msg = JSON.parse(evt.data);\n",
+ " var msg_type = msg['type'];\n",
+ "\n",
+ " // Call the \"handle_{type}\" callback, which takes\n",
+ " // the figure and JSON message as its only arguments.\n",
+ " try {\n",
+ " var callback = fig[\"handle_\" + msg_type];\n",
+ " } catch (e) {\n",
+ " console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n",
+ " return;\n",
+ " }\n",
+ "\n",
+ " if (callback) {\n",
+ " try {\n",
+ " // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n",
+ " callback(fig, msg);\n",
+ " } catch (e) {\n",
+ " console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n",
+ " }\n",
+ " }\n",
+ " };\n",
+ "}\n",
+ "\n",
+ "// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n",
+ "mpl.findpos = function(e) {\n",
+ " //this section is from http://www.quirksmode.org/js/events_properties.html\n",
+ " var targ;\n",
+ " if (!e)\n",
+ " e = window.event;\n",
+ " if (e.target)\n",
+ " targ = e.target;\n",
+ " else if (e.srcElement)\n",
+ " targ = e.srcElement;\n",
+ " if (targ.nodeType == 3) // defeat Safari bug\n",
+ " targ = targ.parentNode;\n",
+ "\n",
+ " // jQuery normalizes the pageX and pageY\n",
+ " // pageX,Y are the mouse positions relative to the document\n",
+ " // offset() returns the position of the element relative to the document\n",
+ " var x = e.pageX - $(targ).offset().left;\n",
+ " var y = e.pageY - $(targ).offset().top;\n",
+ "\n",
+ " return {\"x\": x, \"y\": y};\n",
+ "};\n",
+ "\n",
+ "/*\n",
+ " * return a copy of an object with only non-object keys\n",
+ " * we need this to avoid circular references\n",
+ " * http://stackoverflow.com/a/24161582/3208463\n",
+ " */\n",
+ "function simpleKeys (original) {\n",
+ " return Object.keys(original).reduce(function (obj, key) {\n",
+ " if (typeof original[key] !== 'object')\n",
+ " obj[key] = original[key]\n",
+ " return obj;\n",
+ " }, {});\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.mouse_event = function(event, name) {\n",
+ " var canvas_pos = mpl.findpos(event)\n",
+ "\n",
+ " if (name === 'button_press')\n",
+ " {\n",
+ " this.canvas.focus();\n",
+ " this.canvas_div.focus();\n",
+ " }\n",
+ "\n",
+ " var x = canvas_pos.x * mpl.ratio;\n",
+ " var y = canvas_pos.y * mpl.ratio;\n",
+ "\n",
+ " this.send_message(name, {x: x, y: y, button: event.button,\n",
+ " step: event.step,\n",
+ " guiEvent: simpleKeys(event)});\n",
+ "\n",
+ " /* This prevents the web browser from automatically changing to\n",
+ " * the text insertion cursor when the button is pressed. We want\n",
+ " * to control all of the cursor setting manually through the\n",
+ " * 'cursor' event from matplotlib */\n",
+ " event.preventDefault();\n",
+ " return false;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._key_event_extra = function(event, name) {\n",
+ " // Handle any extra behaviour associated with a key event\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.key_event = function(event, name) {\n",
+ "\n",
+ " // Prevent repeat events\n",
+ " if (name == 'key_press')\n",
+ " {\n",
+ " if (event.which === this._key)\n",
+ " return;\n",
+ " else\n",
+ " this._key = event.which;\n",
+ " }\n",
+ " if (name == 'key_release')\n",
+ " this._key = null;\n",
+ "\n",
+ " var value = '';\n",
+ " if (event.ctrlKey && event.which != 17)\n",
+ " value += \"ctrl+\";\n",
+ " if (event.altKey && event.which != 18)\n",
+ " value += \"alt+\";\n",
+ " if (event.shiftKey && event.which != 16)\n",
+ " value += \"shift+\";\n",
+ "\n",
+ " value += 'k';\n",
+ " value += event.which.toString();\n",
+ "\n",
+ " this._key_event_extra(event, name);\n",
+ "\n",
+ " this.send_message(name, {key: value,\n",
+ " guiEvent: simpleKeys(event)});\n",
+ " return false;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.toolbar_button_onclick = function(name) {\n",
+ " if (name == 'download') {\n",
+ " this.handle_save(this, null);\n",
+ " } else {\n",
+ " this.send_message(\"toolbar_button\", {name: name});\n",
+ " }\n",
+ "};\n",
+ "\n",
+ "mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n",
+ " this.message.textContent = tooltip;\n",
+ "};\n",
+ "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n",
+ "\n",
+ "mpl.extensions = [\"eps\", \"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(\"\");\n",
+ " if (!fig.cell_info) {\n",
+ " console.error(\"Failed to find cell for figure\", id, fig);\n",
+ " return;\n",
+ " }\n",
+ "\n",
+ " var output_index = fig.cell_info[2]\n",
+ " var cell = fig.cell_info[0];\n",
+ "\n",
+ "};\n",
+ "\n",
+ "mpl.figure.prototype.handle_close = function(fig, msg) {\n",
+ " var width = fig.canvas.width/mpl.ratio\n",
+ " fig.root.unbind('remove')\n",
+ "\n",
+ " // Update the output cell to use the data from the current canvas.\n",
+ " fig.push_to_output();\n",
+ " var dataURL = fig.canvas.toDataURL();\n",
+ " // Re-enable the keyboard manager in IPython - without this line, in FF,\n",
+ " // the notebook keyboard shortcuts fail.\n",
+ " IPython.keyboard_manager.enable()\n",
+ " $(fig.parent_element).html('
');\n",
+ " fig.close_ws(fig, msg);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.close_ws = function(fig, msg){\n",
+ " fig.send_message('closing', msg);\n",
+ " // fig.ws.close()\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.push_to_output = function(remove_interactive) {\n",
+ " // Turn the data on the canvas into data in the output cell.\n",
+ " var width = this.canvas.width/mpl.ratio\n",
+ " var dataURL = this.canvas.toDataURL();\n",
+ " this.cell_info[1]['text/html'] = '
';\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 = $('')\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 = $('');\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 = $('');\n",
+ " nav_element.append(status_bar);\n",
+ " this.message = status_bar[0];\n",
+ "\n",
+ " // Add the close button to the window.\n",
+ " var buttongrp = $('');\n",
+ " var button = $('');\n",
+ " button.click(function (evt) { fig.handle_close(fig, {}); } );\n",
+ " button.mouseover('Stop Interaction', toolbar_mouse_event);\n",
+ " buttongrp.append(button);\n",
+ " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n",
+ " titlebar.prepend(buttongrp);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._root_extra_style = function(el){\n",
+ " var fig = this\n",
+ " el.on(\"remove\", function(){\n",
+ "\tfig.close_ws(fig, {});\n",
+ " });\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._canvas_extra_style = function(el){\n",
+ " // this is important to make the div 'focusable\n",
+ " el.attr('tabindex', 0)\n",
+ " // reach out to IPython and tell the keyboard manager to turn it's self\n",
+ " // off when our div gets focus\n",
+ "\n",
+ " // location in version 3\n",
+ " if (IPython.notebook.keyboard_manager) {\n",
+ " IPython.notebook.keyboard_manager.register_events(el);\n",
+ " }\n",
+ " else {\n",
+ " // location in version 2\n",
+ " IPython.keyboard_manager.register_events(el);\n",
+ " }\n",
+ "\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._key_event_extra = function(event, name) {\n",
+ " var manager = IPython.notebook.keyboard_manager;\n",
+ " if (!manager)\n",
+ " manager = IPython.keyboard_manager;\n",
+ "\n",
+ " // Check for shift+enter\n",
+ " if (event.shiftKey && event.which == 13) {\n",
+ " this.canvas_div.blur();\n",
+ " // select the cell after this one\n",
+ " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n",
+ " IPython.notebook.select(index + 1);\n",
+ " }\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_save = function(fig, msg) {\n",
+ " fig.ondownload(fig, null);\n",
+ "}\n",
+ "\n",
+ "\n",
+ "mpl.find_output_cell = function(html_output) {\n",
+ " // Return the cell and output element which can be found *uniquely* in the notebook.\n",
+ " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n",
+ " // IPython event is triggered only after the cells have been serialised, which for\n",
+ " // our purposes (turning an active figure into a static one), is too late.\n",
+ " var cells = IPython.notebook.get_cells();\n",
+ " var ncells = cells.length;\n",
+ " for (var i=0; i= 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": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/html": [
+ "
"
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "gcalc = mfit.evaluateEquation(\"mpdf\")\n",
+ "\n",
+ "# Plot just the mPDF\n",
+ "ax=plt.figure().add_subplot(111)\n",
+ "ax.plot(r, d, 'bo', label=\"mPDF data\", markerfacecolor='none', markeredgecolor='b')\n",
+ "ax.plot(r, gcalc, 'r-', lw=2, label=\"mPDF fit\")\n",
+ "ax.set_xlabel(r\"r ($\\AA$)\")\n",
+ "ax.set_ylabel(r\"D ($\\AA^{-2}$)\")\n",
+ "ax.set_xlim(xmax=mc.rmax)\n",
+ "plt.legend(loc=1)\n",
+ "\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "plt.close('all')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Now refine spin direction"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Load the data into a Profile object"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "PDFguiFile = 'MnOpdfgui.ddp'\n",
+ "r,d = getDiffData(PDFguiFile, 0) ### extract the fit residual from the atomic PDF fit done in PDFgui\n",
+ "\n",
+ "from diffpy.srfit.fitbase import Profile\n",
+ "\n",
+ "profile = Profile()\n",
+ "profile.setObservedProfile(r, d)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Make the magnetic structure"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [
+ {
+ "data": {
+ "application/javascript": [
+ "/* Put everything inside the global mpl namespace */\n",
+ "window.mpl = {};\n",
+ "\n",
+ "\n",
+ "mpl.get_websocket_type = function() {\n",
+ " if (typeof(WebSocket) !== 'undefined') {\n",
+ " return WebSocket;\n",
+ " } else if (typeof(MozWebSocket) !== 'undefined') {\n",
+ " return MozWebSocket;\n",
+ " } else {\n",
+ " alert('Your browser does not have WebSocket support.' +\n",
+ " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
+ " 'Firefox 4 and 5 are also supported but you ' +\n",
+ " 'have to enable WebSockets in about:config.');\n",
+ " };\n",
+ "}\n",
+ "\n",
+ "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n",
+ " this.id = figure_id;\n",
+ "\n",
+ " this.ws = websocket;\n",
+ "\n",
+ " this.supports_binary = (this.ws.binaryType != undefined);\n",
+ "\n",
+ " if (!this.supports_binary) {\n",
+ " var warnings = document.getElementById(\"mpl-warnings\");\n",
+ " if (warnings) {\n",
+ " warnings.style.display = 'block';\n",
+ " warnings.textContent = (\n",
+ " \"This browser does not support binary websocket messages. \" +\n",
+ " \"Performance may be slow.\");\n",
+ " }\n",
+ " }\n",
+ "\n",
+ " this.imageObj = new Image();\n",
+ "\n",
+ " this.context = undefined;\n",
+ " this.message = undefined;\n",
+ " this.canvas = undefined;\n",
+ " this.rubberband_canvas = undefined;\n",
+ " this.rubberband_context = undefined;\n",
+ " this.format_dropdown = undefined;\n",
+ "\n",
+ " this.image_mode = 'full';\n",
+ "\n",
+ " this.root = $('');\n",
+ " this._root_extra_style(this.root)\n",
+ " this.root.attr('style', 'display: inline-block');\n",
+ "\n",
+ " $(parent_element).append(this.root);\n",
+ "\n",
+ " this._init_header(this);\n",
+ " this._init_canvas(this);\n",
+ " this._init_toolbar(this);\n",
+ "\n",
+ " var fig = this;\n",
+ "\n",
+ " this.waiting = false;\n",
+ "\n",
+ " this.ws.onopen = function () {\n",
+ " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n",
+ " fig.send_message(\"send_image_mode\", {});\n",
+ " if (mpl.ratio != 1) {\n",
+ " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n",
+ " }\n",
+ " fig.send_message(\"refresh\", {});\n",
+ " }\n",
+ "\n",
+ " this.imageObj.onload = function() {\n",
+ " if (fig.image_mode == 'full') {\n",
+ " // Full images could contain transparency (where diff images\n",
+ " // almost always do), so we need to clear the canvas so that\n",
+ " // there is no ghosting.\n",
+ " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
+ " }\n",
+ " fig.context.drawImage(fig.imageObj, 0, 0);\n",
+ " };\n",
+ "\n",
+ " this.imageObj.onunload = function() {\n",
+ " this.ws.close();\n",
+ " }\n",
+ "\n",
+ " this.ws.onmessage = this._make_on_message_function(this);\n",
+ "\n",
+ " this.ondownload = ondownload;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._init_header = function() {\n",
+ " var titlebar = $(\n",
+ " '');\n",
+ " var titletext = $(\n",
+ " '');\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 = $('');\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 = $('');\n",
+ " canvas.addClass('mpl-canvas');\n",
+ " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n",
+ "\n",
+ " this.canvas = canvas[0];\n",
+ " this.context = canvas[0].getContext(\"2d\");\n",
+ "\n",
+ " var backingStore = this.context.backingStorePixelRatio ||\n",
+ "\tthis.context.webkitBackingStorePixelRatio ||\n",
+ "\tthis.context.mozBackingStorePixelRatio ||\n",
+ "\tthis.context.msBackingStorePixelRatio ||\n",
+ "\tthis.context.oBackingStorePixelRatio ||\n",
+ "\tthis.context.backingStorePixelRatio || 1;\n",
+ "\n",
+ " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n",
+ "\n",
+ " var rubberband = $('');\n",
+ " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n",
+ "\n",
+ " var pass_mouse_events = true;\n",
+ "\n",
+ " canvas_div.resizable({\n",
+ " start: function(event, ui) {\n",
+ " pass_mouse_events = false;\n",
+ " },\n",
+ " resize: function(event, ui) {\n",
+ " fig.request_resize(ui.size.width, ui.size.height);\n",
+ " },\n",
+ " stop: function(event, ui) {\n",
+ " pass_mouse_events = true;\n",
+ " fig.request_resize(ui.size.width, ui.size.height);\n",
+ " },\n",
+ " });\n",
+ "\n",
+ " function mouse_event_fn(event) {\n",
+ " if (pass_mouse_events)\n",
+ " return fig.mouse_event(event, event['data']);\n",
+ " }\n",
+ "\n",
+ " rubberband.mousedown('button_press', mouse_event_fn);\n",
+ " rubberband.mouseup('button_release', mouse_event_fn);\n",
+ " // Throttle sequential mouse events to 1 every 20ms.\n",
+ " rubberband.mousemove('motion_notify', mouse_event_fn);\n",
+ "\n",
+ " rubberband.mouseenter('figure_enter', mouse_event_fn);\n",
+ " rubberband.mouseleave('figure_leave', mouse_event_fn);\n",
+ "\n",
+ " canvas_div.on(\"wheel\", function (event) {\n",
+ " event = event.originalEvent;\n",
+ " event['data'] = 'scroll'\n",
+ " if (event.deltaY < 0) {\n",
+ " event.step = 1;\n",
+ " } else {\n",
+ " event.step = -1;\n",
+ " }\n",
+ " mouse_event_fn(event);\n",
+ " });\n",
+ "\n",
+ " canvas_div.append(canvas);\n",
+ " canvas_div.append(rubberband);\n",
+ "\n",
+ " this.rubberband = rubberband;\n",
+ " this.rubberband_canvas = rubberband[0];\n",
+ " this.rubberband_context = rubberband[0].getContext(\"2d\");\n",
+ " this.rubberband_context.strokeStyle = \"#000000\";\n",
+ "\n",
+ " this._resize_canvas = function(width, height) {\n",
+ " // Keep the size of the canvas, canvas container, and rubber band\n",
+ " // canvas in synch.\n",
+ " canvas_div.css('width', width)\n",
+ " canvas_div.css('height', height)\n",
+ "\n",
+ " canvas.attr('width', width * mpl.ratio);\n",
+ " canvas.attr('height', height * mpl.ratio);\n",
+ " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n",
+ "\n",
+ " rubberband.attr('width', width);\n",
+ " rubberband.attr('height', height);\n",
+ " }\n",
+ "\n",
+ " // Set the figure to an initial 600x600px, this will subsequently be updated\n",
+ " // upon first draw.\n",
+ " this._resize_canvas(600, 600);\n",
+ "\n",
+ " // Disable right mouse context menu.\n",
+ " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n",
+ " return false;\n",
+ " });\n",
+ "\n",
+ " function set_focus () {\n",
+ " canvas.focus();\n",
+ " canvas_div.focus();\n",
+ " }\n",
+ "\n",
+ " window.setTimeout(set_focus, 100);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._init_toolbar = function() {\n",
+ " var fig = this;\n",
+ "\n",
+ " var nav_element = $('')\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 = $('');\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 = $('');\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 = $('');\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 = $('');\n",
+ "\n",
+ " var fmt_picker = $('');\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",
+ " '', {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 = $('');\n",
+ " nav_element.append(status_bar);\n",
+ " this.message = status_bar[0];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n",
+ " // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n",
+ " // which will in turn request a refresh of the image.\n",
+ " this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.send_message = function(type, properties) {\n",
+ " properties['type'] = type;\n",
+ " properties['figure_id'] = this.id;\n",
+ " this.ws.send(JSON.stringify(properties));\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.send_draw_message = function() {\n",
+ " if (!this.waiting) {\n",
+ " this.waiting = true;\n",
+ " this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n",
+ " }\n",
+ "}\n",
+ "\n",
+ "\n",
+ "mpl.figure.prototype.handle_save = function(fig, msg) {\n",
+ " var format_dropdown = fig.format_dropdown;\n",
+ " var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n",
+ " fig.ondownload(fig, format);\n",
+ "}\n",
+ "\n",
+ "\n",
+ "mpl.figure.prototype.handle_resize = function(fig, msg) {\n",
+ " var size = msg['size'];\n",
+ " if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n",
+ " fig._resize_canvas(size[0], size[1]);\n",
+ " fig.send_message(\"refresh\", {});\n",
+ " };\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n",
+ " var x0 = msg['x0'] / mpl.ratio;\n",
+ " var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n",
+ " var x1 = msg['x1'] / mpl.ratio;\n",
+ " var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n",
+ " x0 = Math.floor(x0) + 0.5;\n",
+ " y0 = Math.floor(y0) + 0.5;\n",
+ " x1 = Math.floor(x1) + 0.5;\n",
+ " y1 = Math.floor(y1) + 0.5;\n",
+ " var min_x = Math.min(x0, x1);\n",
+ " var min_y = Math.min(y0, y1);\n",
+ " var width = Math.abs(x1 - x0);\n",
+ " var height = Math.abs(y1 - y0);\n",
+ "\n",
+ " fig.rubberband_context.clearRect(\n",
+ " 0, 0, fig.canvas.width, fig.canvas.height);\n",
+ "\n",
+ " fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n",
+ " // Updates the figure title.\n",
+ " fig.header.textContent = msg['label'];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_cursor = function(fig, msg) {\n",
+ " var cursor = msg['cursor'];\n",
+ " switch(cursor)\n",
+ " {\n",
+ " case 0:\n",
+ " cursor = 'pointer';\n",
+ " break;\n",
+ " case 1:\n",
+ " cursor = 'default';\n",
+ " break;\n",
+ " case 2:\n",
+ " cursor = 'crosshair';\n",
+ " break;\n",
+ " case 3:\n",
+ " cursor = 'move';\n",
+ " break;\n",
+ " }\n",
+ " fig.rubberband_canvas.style.cursor = cursor;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_message = function(fig, msg) {\n",
+ " fig.message.textContent = msg['message'];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_draw = function(fig, msg) {\n",
+ " // Request the server to send over a new figure.\n",
+ " fig.send_draw_message();\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n",
+ " fig.image_mode = msg['mode'];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.updated_canvas_event = function() {\n",
+ " // Called whenever the canvas gets updated.\n",
+ " this.send_message(\"ack\", {});\n",
+ "}\n",
+ "\n",
+ "// A function to construct a web socket function for onmessage handling.\n",
+ "// Called in the figure constructor.\n",
+ "mpl.figure.prototype._make_on_message_function = function(fig) {\n",
+ " return function socket_on_message(evt) {\n",
+ " if (evt.data instanceof Blob) {\n",
+ " /* FIXME: We get \"Resource interpreted as Image but\n",
+ " * transferred with MIME type text/plain:\" errors on\n",
+ " * Chrome. But how to set the MIME type? It doesn't seem\n",
+ " * to be part of the websocket stream */\n",
+ " evt.data.type = \"image/png\";\n",
+ "\n",
+ " /* Free the memory for the previous frames */\n",
+ " if (fig.imageObj.src) {\n",
+ " (window.URL || window.webkitURL).revokeObjectURL(\n",
+ " fig.imageObj.src);\n",
+ " }\n",
+ "\n",
+ " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
+ " evt.data);\n",
+ " fig.updated_canvas_event();\n",
+ " fig.waiting = false;\n",
+ " return;\n",
+ " }\n",
+ " else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n",
+ " fig.imageObj.src = evt.data;\n",
+ " fig.updated_canvas_event();\n",
+ " fig.waiting = false;\n",
+ " return;\n",
+ " }\n",
+ "\n",
+ " var msg = JSON.parse(evt.data);\n",
+ " var msg_type = msg['type'];\n",
+ "\n",
+ " // Call the \"handle_{type}\" callback, which takes\n",
+ " // the figure and JSON message as its only arguments.\n",
+ " try {\n",
+ " var callback = fig[\"handle_\" + msg_type];\n",
+ " } catch (e) {\n",
+ " console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n",
+ " return;\n",
+ " }\n",
+ "\n",
+ " if (callback) {\n",
+ " try {\n",
+ " // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n",
+ " callback(fig, msg);\n",
+ " } catch (e) {\n",
+ " console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n",
+ " }\n",
+ " }\n",
+ " };\n",
+ "}\n",
+ "\n",
+ "// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n",
+ "mpl.findpos = function(e) {\n",
+ " //this section is from http://www.quirksmode.org/js/events_properties.html\n",
+ " var targ;\n",
+ " if (!e)\n",
+ " e = window.event;\n",
+ " if (e.target)\n",
+ " targ = e.target;\n",
+ " else if (e.srcElement)\n",
+ " targ = e.srcElement;\n",
+ " if (targ.nodeType == 3) // defeat Safari bug\n",
+ " targ = targ.parentNode;\n",
+ "\n",
+ " // jQuery normalizes the pageX and pageY\n",
+ " // pageX,Y are the mouse positions relative to the document\n",
+ " // offset() returns the position of the element relative to the document\n",
+ " var x = e.pageX - $(targ).offset().left;\n",
+ " var y = e.pageY - $(targ).offset().top;\n",
+ "\n",
+ " return {\"x\": x, \"y\": y};\n",
+ "};\n",
+ "\n",
+ "/*\n",
+ " * return a copy of an object with only non-object keys\n",
+ " * we need this to avoid circular references\n",
+ " * http://stackoverflow.com/a/24161582/3208463\n",
+ " */\n",
+ "function simpleKeys (original) {\n",
+ " return Object.keys(original).reduce(function (obj, key) {\n",
+ " if (typeof original[key] !== 'object')\n",
+ " obj[key] = original[key]\n",
+ " return obj;\n",
+ " }, {});\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.mouse_event = function(event, name) {\n",
+ " var canvas_pos = mpl.findpos(event)\n",
+ "\n",
+ " if (name === 'button_press')\n",
+ " {\n",
+ " this.canvas.focus();\n",
+ " this.canvas_div.focus();\n",
+ " }\n",
+ "\n",
+ " var x = canvas_pos.x * mpl.ratio;\n",
+ " var y = canvas_pos.y * mpl.ratio;\n",
+ "\n",
+ " this.send_message(name, {x: x, y: y, button: event.button,\n",
+ " step: event.step,\n",
+ " guiEvent: simpleKeys(event)});\n",
+ "\n",
+ " /* This prevents the web browser from automatically changing to\n",
+ " * the text insertion cursor when the button is pressed. We want\n",
+ " * to control all of the cursor setting manually through the\n",
+ " * 'cursor' event from matplotlib */\n",
+ " event.preventDefault();\n",
+ " return false;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._key_event_extra = function(event, name) {\n",
+ " // Handle any extra behaviour associated with a key event\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.key_event = function(event, name) {\n",
+ "\n",
+ " // Prevent repeat events\n",
+ " if (name == 'key_press')\n",
+ " {\n",
+ " if (event.which === this._key)\n",
+ " return;\n",
+ " else\n",
+ " this._key = event.which;\n",
+ " }\n",
+ " if (name == 'key_release')\n",
+ " this._key = null;\n",
+ "\n",
+ " var value = '';\n",
+ " if (event.ctrlKey && event.which != 17)\n",
+ " value += \"ctrl+\";\n",
+ " if (event.altKey && event.which != 18)\n",
+ " value += \"alt+\";\n",
+ " if (event.shiftKey && event.which != 16)\n",
+ " value += \"shift+\";\n",
+ "\n",
+ " value += 'k';\n",
+ " value += event.which.toString();\n",
+ "\n",
+ " this._key_event_extra(event, name);\n",
+ "\n",
+ " this.send_message(name, {key: value,\n",
+ " guiEvent: simpleKeys(event)});\n",
+ " return false;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.toolbar_button_onclick = function(name) {\n",
+ " if (name == 'download') {\n",
+ " this.handle_save(this, null);\n",
+ " } else {\n",
+ " this.send_message(\"toolbar_button\", {name: name});\n",
+ " }\n",
+ "};\n",
+ "\n",
+ "mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n",
+ " this.message.textContent = tooltip;\n",
+ "};\n",
+ "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n",
+ "\n",
+ "mpl.extensions = [\"eps\", \"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(\"\");\n",
+ " if (!fig.cell_info) {\n",
+ " console.error(\"Failed to find cell for figure\", id, fig);\n",
+ " return;\n",
+ " }\n",
+ "\n",
+ " var output_index = fig.cell_info[2]\n",
+ " var cell = fig.cell_info[0];\n",
+ "\n",
+ "};\n",
+ "\n",
+ "mpl.figure.prototype.handle_close = function(fig, msg) {\n",
+ " var width = fig.canvas.width/mpl.ratio\n",
+ " fig.root.unbind('remove')\n",
+ "\n",
+ " // Update the output cell to use the data from the current canvas.\n",
+ " fig.push_to_output();\n",
+ " var dataURL = fig.canvas.toDataURL();\n",
+ " // Re-enable the keyboard manager in IPython - without this line, in FF,\n",
+ " // the notebook keyboard shortcuts fail.\n",
+ " IPython.keyboard_manager.enable()\n",
+ " $(fig.parent_element).html('
');\n",
+ " fig.close_ws(fig, msg);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.close_ws = function(fig, msg){\n",
+ " fig.send_message('closing', msg);\n",
+ " // fig.ws.close()\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.push_to_output = function(remove_interactive) {\n",
+ " // Turn the data on the canvas into data in the output cell.\n",
+ " var width = this.canvas.width/mpl.ratio\n",
+ " var dataURL = this.canvas.toDataURL();\n",
+ " this.cell_info[1]['text/html'] = '
';\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 = $('')\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 = $('');\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 = $('');\n",
+ " nav_element.append(status_bar);\n",
+ " this.message = status_bar[0];\n",
+ "\n",
+ " // Add the close button to the window.\n",
+ " var buttongrp = $('');\n",
+ " var button = $('');\n",
+ " button.click(function (evt) { fig.handle_close(fig, {}); } );\n",
+ " button.mouseover('Stop Interaction', toolbar_mouse_event);\n",
+ " buttongrp.append(button);\n",
+ " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n",
+ " titlebar.prepend(buttongrp);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._root_extra_style = function(el){\n",
+ " var fig = this\n",
+ " el.on(\"remove\", function(){\n",
+ "\tfig.close_ws(fig, {});\n",
+ " });\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._canvas_extra_style = function(el){\n",
+ " // this is important to make the div 'focusable\n",
+ " el.attr('tabindex', 0)\n",
+ " // reach out to IPython and tell the keyboard manager to turn it's self\n",
+ " // off when our div gets focus\n",
+ "\n",
+ " // location in version 3\n",
+ " if (IPython.notebook.keyboard_manager) {\n",
+ " IPython.notebook.keyboard_manager.register_events(el);\n",
+ " }\n",
+ " else {\n",
+ " // location in version 2\n",
+ " IPython.keyboard_manager.register_events(el);\n",
+ " }\n",
+ "\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._key_event_extra = function(event, name) {\n",
+ " var manager = IPython.notebook.keyboard_manager;\n",
+ " if (!manager)\n",
+ " manager = IPython.keyboard_manager;\n",
+ "\n",
+ " // Check for shift+enter\n",
+ " if (event.shiftKey && event.which == 13) {\n",
+ " this.canvas_div.blur();\n",
+ " // select the cell after this one\n",
+ " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n",
+ " IPython.notebook.select(index + 1);\n",
+ " }\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_save = function(fig, msg) {\n",
+ " fig.ondownload(fig, null);\n",
+ "}\n",
+ "\n",
+ "\n",
+ "mpl.find_output_cell = function(html_output) {\n",
+ " // Return the cell and output element which can be found *uniquely* in the notebook.\n",
+ " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n",
+ " // IPython event is triggered only after the cells have been serialised, which for\n",
+ " // our purposes (turning an active figure into a static one), is too late.\n",
+ " var cells = IPython.notebook.get_cells();\n",
+ " var ncells = cells.length;\n",
+ " for (var i=0; i= 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": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/html": [
+ "
"
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "struc = getStrucFromPDFgui(PDFguiFile,0)\n",
+ "\n",
+ "svec = np.array([1.0,-1.0,0.0])\n",
+ "msp = MagSpecies(struc,magIdxs=[0,1,2,3],ffparamkey='Mn2',rmaxAtoms=50,basisvecs=svec,\n",
+ " kvecs=np.array([0.5,0.5,0.5]),label=str(0))\n",
+ "\n",
+ "mstr=MagStructure()\n",
+ "mstr.loadSpecies(msp)\n",
+ "mstr.makeAll()\n",
+ "\n",
+ "upMask = (np.apply_along_axis(np.linalg.norm,1,mstr.spins-svec)<0.01)\n",
+ "downMask = ~upMask\n",
+ "\n",
+ "### Visualize the magnetic structure\n",
+ "uc = struc[:4].xyz\n",
+ "visatoms = uc.copy()\n",
+ "visatoms = np.concatenate((visatoms,visatoms+np.array([0,0,1]),visatoms+np.array([0,1,0]),visatoms+np.array([0,0,1])))\n",
+ "visatoms = struc.lattice.cartesian(visatoms)\n",
+ "visspins = mstr.spinsFromAtoms(visatoms,fractional=False)\n",
+ "mstr.visualize(visatoms,visspins)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Make the MPDFcalculator"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "mc = MPDFcalculator(mstr)\n",
+ "mc.rmin = r.min()\n",
+ "mc.rmax = r.max()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Set up and perform the fit"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 16,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "from diffpy.srfit.fitbase import FitContribution\n",
+ "mfit = FitContribution('mfit')\n",
+ "mfit.setProfile(profile)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 17,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [],
+ "source": [
+ "# Define an mPDF function that will be added to the total PDF calculator\n",
+ "def mpdf(parascale, ordscale, damp, th, phi):\n",
+ " mc.paraScale, mc.ordScale, mc.dampRate = parascale, ordscale, damp\n",
+ " newvec = np.array([np.sin(th)*np.cos(phi),np.sin(th)*np.sin(phi),np.cos(th)])\n",
+ " mstr.spins[upMask] = newvec\n",
+ " mstr.spins[downMask] = -newvec\n",
+ " dr = mc.calc(both=True)[2]\n",
+ " return dr\n",
+ "\n",
+ "mfit.registerFunction(mpdf)\n",
+ "mfit.setEquation(\"mpdf(parascale, ordscale, damp, th, phi)\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 18,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [],
+ "source": [
+ "from diffpy.srfit.fitbase import FitRecipe\n",
+ "recipe = FitRecipe()\n",
+ "\n",
+ "# give the PDFContribution to the FitRecipe\n",
+ "recipe.addContribution(mfit)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 19,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ ""
+ ]
+ },
+ "execution_count": 19,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# add the mPDF variables\n",
+ "recipe.addVar(mfit.parascale, 4)\n",
+ "recipe.addVar(mfit.ordscale, 0.5)\n",
+ "recipe.addVar(mfit.damp, 0.01)\n",
+ "recipe.addVar(mfit.th, 0.5)\n",
+ "recipe.addVar(mfit.phi, 0.5)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 20,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Refine using scipy's least-squares optimizer:\n",
+ " variables: ['parascale', 'ordscale', 'damp', 'th', 'phi']\n",
+ " initial values: [ 4. 0.5 0.01 0.5 0.5 ]\n",
+ " final values: [ 2.89532246 2.46122465 0.00673799 0.76372883 -1.60427272]\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Turn off printout of iteration number.\n",
+ "recipe.clearFitHooks()\n",
+ "\n",
+ "# Initial structural fit\n",
+ "print \"Refine using scipy's least-squares optimizer:\"\n",
+ "print \" variables:\", recipe.names\n",
+ "print \" initial values:\", recipe.values\n",
+ "\n",
+ "from scipy.optimize import least_squares\n",
+ "\n",
+ "least_squares(recipe.residual, recipe.values, bounds=[[0,0,0,0,-np.pi],[5,5,1,np.pi,np.pi]])\n",
+ "print \" final values:\", recipe.values"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Plot the result"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 21,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [
+ {
+ "data": {
+ "application/javascript": [
+ "/* Put everything inside the global mpl namespace */\n",
+ "window.mpl = {};\n",
+ "\n",
+ "\n",
+ "mpl.get_websocket_type = function() {\n",
+ " if (typeof(WebSocket) !== 'undefined') {\n",
+ " return WebSocket;\n",
+ " } else if (typeof(MozWebSocket) !== 'undefined') {\n",
+ " return MozWebSocket;\n",
+ " } else {\n",
+ " alert('Your browser does not have WebSocket support.' +\n",
+ " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
+ " 'Firefox 4 and 5 are also supported but you ' +\n",
+ " 'have to enable WebSockets in about:config.');\n",
+ " };\n",
+ "}\n",
+ "\n",
+ "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n",
+ " this.id = figure_id;\n",
+ "\n",
+ " this.ws = websocket;\n",
+ "\n",
+ " this.supports_binary = (this.ws.binaryType != undefined);\n",
+ "\n",
+ " if (!this.supports_binary) {\n",
+ " var warnings = document.getElementById(\"mpl-warnings\");\n",
+ " if (warnings) {\n",
+ " warnings.style.display = 'block';\n",
+ " warnings.textContent = (\n",
+ " \"This browser does not support binary websocket messages. \" +\n",
+ " \"Performance may be slow.\");\n",
+ " }\n",
+ " }\n",
+ "\n",
+ " this.imageObj = new Image();\n",
+ "\n",
+ " this.context = undefined;\n",
+ " this.message = undefined;\n",
+ " this.canvas = undefined;\n",
+ " this.rubberband_canvas = undefined;\n",
+ " this.rubberband_context = undefined;\n",
+ " this.format_dropdown = undefined;\n",
+ "\n",
+ " this.image_mode = 'full';\n",
+ "\n",
+ " this.root = $('');\n",
+ " this._root_extra_style(this.root)\n",
+ " this.root.attr('style', 'display: inline-block');\n",
+ "\n",
+ " $(parent_element).append(this.root);\n",
+ "\n",
+ " this._init_header(this);\n",
+ " this._init_canvas(this);\n",
+ " this._init_toolbar(this);\n",
+ "\n",
+ " var fig = this;\n",
+ "\n",
+ " this.waiting = false;\n",
+ "\n",
+ " this.ws.onopen = function () {\n",
+ " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n",
+ " fig.send_message(\"send_image_mode\", {});\n",
+ " if (mpl.ratio != 1) {\n",
+ " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n",
+ " }\n",
+ " fig.send_message(\"refresh\", {});\n",
+ " }\n",
+ "\n",
+ " this.imageObj.onload = function() {\n",
+ " if (fig.image_mode == 'full') {\n",
+ " // Full images could contain transparency (where diff images\n",
+ " // almost always do), so we need to clear the canvas so that\n",
+ " // there is no ghosting.\n",
+ " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
+ " }\n",
+ " fig.context.drawImage(fig.imageObj, 0, 0);\n",
+ " };\n",
+ "\n",
+ " this.imageObj.onunload = function() {\n",
+ " this.ws.close();\n",
+ " }\n",
+ "\n",
+ " this.ws.onmessage = this._make_on_message_function(this);\n",
+ "\n",
+ " this.ondownload = ondownload;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._init_header = function() {\n",
+ " var titlebar = $(\n",
+ " '');\n",
+ " var titletext = $(\n",
+ " '');\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 = $('');\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 = $('');\n",
+ " canvas.addClass('mpl-canvas');\n",
+ " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n",
+ "\n",
+ " this.canvas = canvas[0];\n",
+ " this.context = canvas[0].getContext(\"2d\");\n",
+ "\n",
+ " var backingStore = this.context.backingStorePixelRatio ||\n",
+ "\tthis.context.webkitBackingStorePixelRatio ||\n",
+ "\tthis.context.mozBackingStorePixelRatio ||\n",
+ "\tthis.context.msBackingStorePixelRatio ||\n",
+ "\tthis.context.oBackingStorePixelRatio ||\n",
+ "\tthis.context.backingStorePixelRatio || 1;\n",
+ "\n",
+ " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n",
+ "\n",
+ " var rubberband = $('');\n",
+ " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n",
+ "\n",
+ " var pass_mouse_events = true;\n",
+ "\n",
+ " canvas_div.resizable({\n",
+ " start: function(event, ui) {\n",
+ " pass_mouse_events = false;\n",
+ " },\n",
+ " resize: function(event, ui) {\n",
+ " fig.request_resize(ui.size.width, ui.size.height);\n",
+ " },\n",
+ " stop: function(event, ui) {\n",
+ " pass_mouse_events = true;\n",
+ " fig.request_resize(ui.size.width, ui.size.height);\n",
+ " },\n",
+ " });\n",
+ "\n",
+ " function mouse_event_fn(event) {\n",
+ " if (pass_mouse_events)\n",
+ " return fig.mouse_event(event, event['data']);\n",
+ " }\n",
+ "\n",
+ " rubberband.mousedown('button_press', mouse_event_fn);\n",
+ " rubberband.mouseup('button_release', mouse_event_fn);\n",
+ " // Throttle sequential mouse events to 1 every 20ms.\n",
+ " rubberband.mousemove('motion_notify', mouse_event_fn);\n",
+ "\n",
+ " rubberband.mouseenter('figure_enter', mouse_event_fn);\n",
+ " rubberband.mouseleave('figure_leave', mouse_event_fn);\n",
+ "\n",
+ " canvas_div.on(\"wheel\", function (event) {\n",
+ " event = event.originalEvent;\n",
+ " event['data'] = 'scroll'\n",
+ " if (event.deltaY < 0) {\n",
+ " event.step = 1;\n",
+ " } else {\n",
+ " event.step = -1;\n",
+ " }\n",
+ " mouse_event_fn(event);\n",
+ " });\n",
+ "\n",
+ " canvas_div.append(canvas);\n",
+ " canvas_div.append(rubberband);\n",
+ "\n",
+ " this.rubberband = rubberband;\n",
+ " this.rubberband_canvas = rubberband[0];\n",
+ " this.rubberband_context = rubberband[0].getContext(\"2d\");\n",
+ " this.rubberband_context.strokeStyle = \"#000000\";\n",
+ "\n",
+ " this._resize_canvas = function(width, height) {\n",
+ " // Keep the size of the canvas, canvas container, and rubber band\n",
+ " // canvas in synch.\n",
+ " canvas_div.css('width', width)\n",
+ " canvas_div.css('height', height)\n",
+ "\n",
+ " canvas.attr('width', width * mpl.ratio);\n",
+ " canvas.attr('height', height * mpl.ratio);\n",
+ " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n",
+ "\n",
+ " rubberband.attr('width', width);\n",
+ " rubberband.attr('height', height);\n",
+ " }\n",
+ "\n",
+ " // Set the figure to an initial 600x600px, this will subsequently be updated\n",
+ " // upon first draw.\n",
+ " this._resize_canvas(600, 600);\n",
+ "\n",
+ " // Disable right mouse context menu.\n",
+ " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n",
+ " return false;\n",
+ " });\n",
+ "\n",
+ " function set_focus () {\n",
+ " canvas.focus();\n",
+ " canvas_div.focus();\n",
+ " }\n",
+ "\n",
+ " window.setTimeout(set_focus, 100);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._init_toolbar = function() {\n",
+ " var fig = this;\n",
+ "\n",
+ " var nav_element = $('')\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 = $('');\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 = $('');\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 = $('');\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 = $('');\n",
+ "\n",
+ " var fmt_picker = $('');\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",
+ " '', {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 = $('');\n",
+ " nav_element.append(status_bar);\n",
+ " this.message = status_bar[0];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n",
+ " // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n",
+ " // which will in turn request a refresh of the image.\n",
+ " this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.send_message = function(type, properties) {\n",
+ " properties['type'] = type;\n",
+ " properties['figure_id'] = this.id;\n",
+ " this.ws.send(JSON.stringify(properties));\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.send_draw_message = function() {\n",
+ " if (!this.waiting) {\n",
+ " this.waiting = true;\n",
+ " this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n",
+ " }\n",
+ "}\n",
+ "\n",
+ "\n",
+ "mpl.figure.prototype.handle_save = function(fig, msg) {\n",
+ " var format_dropdown = fig.format_dropdown;\n",
+ " var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n",
+ " fig.ondownload(fig, format);\n",
+ "}\n",
+ "\n",
+ "\n",
+ "mpl.figure.prototype.handle_resize = function(fig, msg) {\n",
+ " var size = msg['size'];\n",
+ " if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n",
+ " fig._resize_canvas(size[0], size[1]);\n",
+ " fig.send_message(\"refresh\", {});\n",
+ " };\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n",
+ " var x0 = msg['x0'] / mpl.ratio;\n",
+ " var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n",
+ " var x1 = msg['x1'] / mpl.ratio;\n",
+ " var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n",
+ " x0 = Math.floor(x0) + 0.5;\n",
+ " y0 = Math.floor(y0) + 0.5;\n",
+ " x1 = Math.floor(x1) + 0.5;\n",
+ " y1 = Math.floor(y1) + 0.5;\n",
+ " var min_x = Math.min(x0, x1);\n",
+ " var min_y = Math.min(y0, y1);\n",
+ " var width = Math.abs(x1 - x0);\n",
+ " var height = Math.abs(y1 - y0);\n",
+ "\n",
+ " fig.rubberband_context.clearRect(\n",
+ " 0, 0, fig.canvas.width, fig.canvas.height);\n",
+ "\n",
+ " fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n",
+ " // Updates the figure title.\n",
+ " fig.header.textContent = msg['label'];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_cursor = function(fig, msg) {\n",
+ " var cursor = msg['cursor'];\n",
+ " switch(cursor)\n",
+ " {\n",
+ " case 0:\n",
+ " cursor = 'pointer';\n",
+ " break;\n",
+ " case 1:\n",
+ " cursor = 'default';\n",
+ " break;\n",
+ " case 2:\n",
+ " cursor = 'crosshair';\n",
+ " break;\n",
+ " case 3:\n",
+ " cursor = 'move';\n",
+ " break;\n",
+ " }\n",
+ " fig.rubberband_canvas.style.cursor = cursor;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_message = function(fig, msg) {\n",
+ " fig.message.textContent = msg['message'];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_draw = function(fig, msg) {\n",
+ " // Request the server to send over a new figure.\n",
+ " fig.send_draw_message();\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n",
+ " fig.image_mode = msg['mode'];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.updated_canvas_event = function() {\n",
+ " // Called whenever the canvas gets updated.\n",
+ " this.send_message(\"ack\", {});\n",
+ "}\n",
+ "\n",
+ "// A function to construct a web socket function for onmessage handling.\n",
+ "// Called in the figure constructor.\n",
+ "mpl.figure.prototype._make_on_message_function = function(fig) {\n",
+ " return function socket_on_message(evt) {\n",
+ " if (evt.data instanceof Blob) {\n",
+ " /* FIXME: We get \"Resource interpreted as Image but\n",
+ " * transferred with MIME type text/plain:\" errors on\n",
+ " * Chrome. But how to set the MIME type? It doesn't seem\n",
+ " * to be part of the websocket stream */\n",
+ " evt.data.type = \"image/png\";\n",
+ "\n",
+ " /* Free the memory for the previous frames */\n",
+ " if (fig.imageObj.src) {\n",
+ " (window.URL || window.webkitURL).revokeObjectURL(\n",
+ " fig.imageObj.src);\n",
+ " }\n",
+ "\n",
+ " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
+ " evt.data);\n",
+ " fig.updated_canvas_event();\n",
+ " fig.waiting = false;\n",
+ " return;\n",
+ " }\n",
+ " else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n",
+ " fig.imageObj.src = evt.data;\n",
+ " fig.updated_canvas_event();\n",
+ " fig.waiting = false;\n",
+ " return;\n",
+ " }\n",
+ "\n",
+ " var msg = JSON.parse(evt.data);\n",
+ " var msg_type = msg['type'];\n",
+ "\n",
+ " // Call the \"handle_{type}\" callback, which takes\n",
+ " // the figure and JSON message as its only arguments.\n",
+ " try {\n",
+ " var callback = fig[\"handle_\" + msg_type];\n",
+ " } catch (e) {\n",
+ " console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n",
+ " return;\n",
+ " }\n",
+ "\n",
+ " if (callback) {\n",
+ " try {\n",
+ " // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n",
+ " callback(fig, msg);\n",
+ " } catch (e) {\n",
+ " console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n",
+ " }\n",
+ " }\n",
+ " };\n",
+ "}\n",
+ "\n",
+ "// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n",
+ "mpl.findpos = function(e) {\n",
+ " //this section is from http://www.quirksmode.org/js/events_properties.html\n",
+ " var targ;\n",
+ " if (!e)\n",
+ " e = window.event;\n",
+ " if (e.target)\n",
+ " targ = e.target;\n",
+ " else if (e.srcElement)\n",
+ " targ = e.srcElement;\n",
+ " if (targ.nodeType == 3) // defeat Safari bug\n",
+ " targ = targ.parentNode;\n",
+ "\n",
+ " // jQuery normalizes the pageX and pageY\n",
+ " // pageX,Y are the mouse positions relative to the document\n",
+ " // offset() returns the position of the element relative to the document\n",
+ " var x = e.pageX - $(targ).offset().left;\n",
+ " var y = e.pageY - $(targ).offset().top;\n",
+ "\n",
+ " return {\"x\": x, \"y\": y};\n",
+ "};\n",
+ "\n",
+ "/*\n",
+ " * return a copy of an object with only non-object keys\n",
+ " * we need this to avoid circular references\n",
+ " * http://stackoverflow.com/a/24161582/3208463\n",
+ " */\n",
+ "function simpleKeys (original) {\n",
+ " return Object.keys(original).reduce(function (obj, key) {\n",
+ " if (typeof original[key] !== 'object')\n",
+ " obj[key] = original[key]\n",
+ " return obj;\n",
+ " }, {});\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.mouse_event = function(event, name) {\n",
+ " var canvas_pos = mpl.findpos(event)\n",
+ "\n",
+ " if (name === 'button_press')\n",
+ " {\n",
+ " this.canvas.focus();\n",
+ " this.canvas_div.focus();\n",
+ " }\n",
+ "\n",
+ " var x = canvas_pos.x * mpl.ratio;\n",
+ " var y = canvas_pos.y * mpl.ratio;\n",
+ "\n",
+ " this.send_message(name, {x: x, y: y, button: event.button,\n",
+ " step: event.step,\n",
+ " guiEvent: simpleKeys(event)});\n",
+ "\n",
+ " /* This prevents the web browser from automatically changing to\n",
+ " * the text insertion cursor when the button is pressed. We want\n",
+ " * to control all of the cursor setting manually through the\n",
+ " * 'cursor' event from matplotlib */\n",
+ " event.preventDefault();\n",
+ " return false;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._key_event_extra = function(event, name) {\n",
+ " // Handle any extra behaviour associated with a key event\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.key_event = function(event, name) {\n",
+ "\n",
+ " // Prevent repeat events\n",
+ " if (name == 'key_press')\n",
+ " {\n",
+ " if (event.which === this._key)\n",
+ " return;\n",
+ " else\n",
+ " this._key = event.which;\n",
+ " }\n",
+ " if (name == 'key_release')\n",
+ " this._key = null;\n",
+ "\n",
+ " var value = '';\n",
+ " if (event.ctrlKey && event.which != 17)\n",
+ " value += \"ctrl+\";\n",
+ " if (event.altKey && event.which != 18)\n",
+ " value += \"alt+\";\n",
+ " if (event.shiftKey && event.which != 16)\n",
+ " value += \"shift+\";\n",
+ "\n",
+ " value += 'k';\n",
+ " value += event.which.toString();\n",
+ "\n",
+ " this._key_event_extra(event, name);\n",
+ "\n",
+ " this.send_message(name, {key: value,\n",
+ " guiEvent: simpleKeys(event)});\n",
+ " return false;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.toolbar_button_onclick = function(name) {\n",
+ " if (name == 'download') {\n",
+ " this.handle_save(this, null);\n",
+ " } else {\n",
+ " this.send_message(\"toolbar_button\", {name: name});\n",
+ " }\n",
+ "};\n",
+ "\n",
+ "mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n",
+ " this.message.textContent = tooltip;\n",
+ "};\n",
+ "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n",
+ "\n",
+ "mpl.extensions = [\"eps\", \"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(\"\");\n",
+ " if (!fig.cell_info) {\n",
+ " console.error(\"Failed to find cell for figure\", id, fig);\n",
+ " return;\n",
+ " }\n",
+ "\n",
+ " var output_index = fig.cell_info[2]\n",
+ " var cell = fig.cell_info[0];\n",
+ "\n",
+ "};\n",
+ "\n",
+ "mpl.figure.prototype.handle_close = function(fig, msg) {\n",
+ " var width = fig.canvas.width/mpl.ratio\n",
+ " fig.root.unbind('remove')\n",
+ "\n",
+ " // Update the output cell to use the data from the current canvas.\n",
+ " fig.push_to_output();\n",
+ " var dataURL = fig.canvas.toDataURL();\n",
+ " // Re-enable the keyboard manager in IPython - without this line, in FF,\n",
+ " // the notebook keyboard shortcuts fail.\n",
+ " IPython.keyboard_manager.enable()\n",
+ " $(fig.parent_element).html('
');\n",
+ " fig.close_ws(fig, msg);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.close_ws = function(fig, msg){\n",
+ " fig.send_message('closing', msg);\n",
+ " // fig.ws.close()\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.push_to_output = function(remove_interactive) {\n",
+ " // Turn the data on the canvas into data in the output cell.\n",
+ " var width = this.canvas.width/mpl.ratio\n",
+ " var dataURL = this.canvas.toDataURL();\n",
+ " this.cell_info[1]['text/html'] = '
';\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 = $('')\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 = $('');\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 = $('');\n",
+ " nav_element.append(status_bar);\n",
+ " this.message = status_bar[0];\n",
+ "\n",
+ " // Add the close button to the window.\n",
+ " var buttongrp = $('');\n",
+ " var button = $('');\n",
+ " button.click(function (evt) { fig.handle_close(fig, {}); } );\n",
+ " button.mouseover('Stop Interaction', toolbar_mouse_event);\n",
+ " buttongrp.append(button);\n",
+ " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n",
+ " titlebar.prepend(buttongrp);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._root_extra_style = function(el){\n",
+ " var fig = this\n",
+ " el.on(\"remove\", function(){\n",
+ "\tfig.close_ws(fig, {});\n",
+ " });\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._canvas_extra_style = function(el){\n",
+ " // this is important to make the div 'focusable\n",
+ " el.attr('tabindex', 0)\n",
+ " // reach out to IPython and tell the keyboard manager to turn it's self\n",
+ " // off when our div gets focus\n",
+ "\n",
+ " // location in version 3\n",
+ " if (IPython.notebook.keyboard_manager) {\n",
+ " IPython.notebook.keyboard_manager.register_events(el);\n",
+ " }\n",
+ " else {\n",
+ " // location in version 2\n",
+ " IPython.keyboard_manager.register_events(el);\n",
+ " }\n",
+ "\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._key_event_extra = function(event, name) {\n",
+ " var manager = IPython.notebook.keyboard_manager;\n",
+ " if (!manager)\n",
+ " manager = IPython.keyboard_manager;\n",
+ "\n",
+ " // Check for shift+enter\n",
+ " if (event.shiftKey && event.which == 13) {\n",
+ " this.canvas_div.blur();\n",
+ " // select the cell after this one\n",
+ " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n",
+ " IPython.notebook.select(index + 1);\n",
+ " }\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_save = function(fig, msg) {\n",
+ " fig.ondownload(fig, null);\n",
+ "}\n",
+ "\n",
+ "\n",
+ "mpl.find_output_cell = function(html_output) {\n",
+ " // Return the cell and output element which can be found *uniquely* in the notebook.\n",
+ " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n",
+ " // IPython event is triggered only after the cells have been serialised, which for\n",
+ " // our purposes (turning an active figure into a static one), is too late.\n",
+ " var cells = IPython.notebook.get_cells();\n",
+ " var ncells = cells.length;\n",
+ " for (var i=0; i= 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": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/html": [
+ "
"
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "gcalc = mfit.evaluateEquation(\"mpdf\")\n",
+ "\n",
+ "# Plot just the mPDF\n",
+ "ax=plt.figure().add_subplot(111)\n",
+ "ax.plot(r, d, 'bo', label=\"mPDF data\", markerfacecolor='none', markeredgecolor='b')\n",
+ "ax.plot(r, gcalc, 'r-', lw=2, label=\"mPDF fit\")\n",
+ "ax.set_xlabel(r\"r ($\\AA$)\")\n",
+ "ax.set_ylabel(r\"D ($\\AA^{-2}$)\")\n",
+ "ax.set_xlim(xmax=mc.rmax)\n",
+ "plt.legend(loc=1)\n",
+ "\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "plt.close('all')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 41,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "array([-0.0231486 , -0.69123194, 0.72226211])"
+ ]
+ },
+ "execution_count": 41,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "mstr.spins[0]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Now using the fitRecipe restraint function to place bounds"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Load the data into a Profile object"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "PDFguiFile = 'MnOpdfgui.ddp'\n",
+ "r,d = getDiffData(PDFguiFile, 0) ### extract the fit residual from the atomic PDF fit done in PDFgui\n",
+ "\n",
+ "from diffpy.srfit.fitbase import Profile\n",
+ "\n",
+ "profile = Profile()\n",
+ "profile.setObservedProfile(r, d)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Make the magnetic structure"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "/home/ben/anaconda/envs/mpdfdev/lib/python2.7/site-packages/diffpy.Structure-1.3.2-py2.7.egg/diffpy/Structure/lattice.py:125: FutureWarning: comparison to `None` will result in an elementwise object comparison in the future.\n",
+ " if [a, b, c, alpha, beta, gamma, base] == 7*[None]:\n"
+ ]
+ },
+ {
+ "data": {
+ "application/javascript": [
+ "/* Put everything inside the global mpl namespace */\n",
+ "window.mpl = {};\n",
+ "\n",
+ "\n",
+ "mpl.get_websocket_type = function() {\n",
+ " if (typeof(WebSocket) !== 'undefined') {\n",
+ " return WebSocket;\n",
+ " } else if (typeof(MozWebSocket) !== 'undefined') {\n",
+ " return MozWebSocket;\n",
+ " } else {\n",
+ " alert('Your browser does not have WebSocket support.' +\n",
+ " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
+ " 'Firefox 4 and 5 are also supported but you ' +\n",
+ " 'have to enable WebSockets in about:config.');\n",
+ " };\n",
+ "}\n",
+ "\n",
+ "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n",
+ " this.id = figure_id;\n",
+ "\n",
+ " this.ws = websocket;\n",
+ "\n",
+ " this.supports_binary = (this.ws.binaryType != undefined);\n",
+ "\n",
+ " if (!this.supports_binary) {\n",
+ " var warnings = document.getElementById(\"mpl-warnings\");\n",
+ " if (warnings) {\n",
+ " warnings.style.display = 'block';\n",
+ " warnings.textContent = (\n",
+ " \"This browser does not support binary websocket messages. \" +\n",
+ " \"Performance may be slow.\");\n",
+ " }\n",
+ " }\n",
+ "\n",
+ " this.imageObj = new Image();\n",
+ "\n",
+ " this.context = undefined;\n",
+ " this.message = undefined;\n",
+ " this.canvas = undefined;\n",
+ " this.rubberband_canvas = undefined;\n",
+ " this.rubberband_context = undefined;\n",
+ " this.format_dropdown = undefined;\n",
+ "\n",
+ " this.image_mode = 'full';\n",
+ "\n",
+ " this.root = $('');\n",
+ " this._root_extra_style(this.root)\n",
+ " this.root.attr('style', 'display: inline-block');\n",
+ "\n",
+ " $(parent_element).append(this.root);\n",
+ "\n",
+ " this._init_header(this);\n",
+ " this._init_canvas(this);\n",
+ " this._init_toolbar(this);\n",
+ "\n",
+ " var fig = this;\n",
+ "\n",
+ " this.waiting = false;\n",
+ "\n",
+ " this.ws.onopen = function () {\n",
+ " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n",
+ " fig.send_message(\"send_image_mode\", {});\n",
+ " if (mpl.ratio != 1) {\n",
+ " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n",
+ " }\n",
+ " fig.send_message(\"refresh\", {});\n",
+ " }\n",
+ "\n",
+ " this.imageObj.onload = function() {\n",
+ " if (fig.image_mode == 'full') {\n",
+ " // Full images could contain transparency (where diff images\n",
+ " // almost always do), so we need to clear the canvas so that\n",
+ " // there is no ghosting.\n",
+ " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
+ " }\n",
+ " fig.context.drawImage(fig.imageObj, 0, 0);\n",
+ " };\n",
+ "\n",
+ " this.imageObj.onunload = function() {\n",
+ " this.ws.close();\n",
+ " }\n",
+ "\n",
+ " this.ws.onmessage = this._make_on_message_function(this);\n",
+ "\n",
+ " this.ondownload = ondownload;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._init_header = function() {\n",
+ " var titlebar = $(\n",
+ " '');\n",
+ " var titletext = $(\n",
+ " '');\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 = $('');\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 = $('');\n",
+ " canvas.addClass('mpl-canvas');\n",
+ " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n",
+ "\n",
+ " this.canvas = canvas[0];\n",
+ " this.context = canvas[0].getContext(\"2d\");\n",
+ "\n",
+ " var backingStore = this.context.backingStorePixelRatio ||\n",
+ "\tthis.context.webkitBackingStorePixelRatio ||\n",
+ "\tthis.context.mozBackingStorePixelRatio ||\n",
+ "\tthis.context.msBackingStorePixelRatio ||\n",
+ "\tthis.context.oBackingStorePixelRatio ||\n",
+ "\tthis.context.backingStorePixelRatio || 1;\n",
+ "\n",
+ " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n",
+ "\n",
+ " var rubberband = $('');\n",
+ " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n",
+ "\n",
+ " var pass_mouse_events = true;\n",
+ "\n",
+ " canvas_div.resizable({\n",
+ " start: function(event, ui) {\n",
+ " pass_mouse_events = false;\n",
+ " },\n",
+ " resize: function(event, ui) {\n",
+ " fig.request_resize(ui.size.width, ui.size.height);\n",
+ " },\n",
+ " stop: function(event, ui) {\n",
+ " pass_mouse_events = true;\n",
+ " fig.request_resize(ui.size.width, ui.size.height);\n",
+ " },\n",
+ " });\n",
+ "\n",
+ " function mouse_event_fn(event) {\n",
+ " if (pass_mouse_events)\n",
+ " return fig.mouse_event(event, event['data']);\n",
+ " }\n",
+ "\n",
+ " rubberband.mousedown('button_press', mouse_event_fn);\n",
+ " rubberband.mouseup('button_release', mouse_event_fn);\n",
+ " // Throttle sequential mouse events to 1 every 20ms.\n",
+ " rubberband.mousemove('motion_notify', mouse_event_fn);\n",
+ "\n",
+ " rubberband.mouseenter('figure_enter', mouse_event_fn);\n",
+ " rubberband.mouseleave('figure_leave', mouse_event_fn);\n",
+ "\n",
+ " canvas_div.on(\"wheel\", function (event) {\n",
+ " event = event.originalEvent;\n",
+ " event['data'] = 'scroll'\n",
+ " if (event.deltaY < 0) {\n",
+ " event.step = 1;\n",
+ " } else {\n",
+ " event.step = -1;\n",
+ " }\n",
+ " mouse_event_fn(event);\n",
+ " });\n",
+ "\n",
+ " canvas_div.append(canvas);\n",
+ " canvas_div.append(rubberband);\n",
+ "\n",
+ " this.rubberband = rubberband;\n",
+ " this.rubberband_canvas = rubberband[0];\n",
+ " this.rubberband_context = rubberband[0].getContext(\"2d\");\n",
+ " this.rubberband_context.strokeStyle = \"#000000\";\n",
+ "\n",
+ " this._resize_canvas = function(width, height) {\n",
+ " // Keep the size of the canvas, canvas container, and rubber band\n",
+ " // canvas in synch.\n",
+ " canvas_div.css('width', width)\n",
+ " canvas_div.css('height', height)\n",
+ "\n",
+ " canvas.attr('width', width * mpl.ratio);\n",
+ " canvas.attr('height', height * mpl.ratio);\n",
+ " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n",
+ "\n",
+ " rubberband.attr('width', width);\n",
+ " rubberband.attr('height', height);\n",
+ " }\n",
+ "\n",
+ " // Set the figure to an initial 600x600px, this will subsequently be updated\n",
+ " // upon first draw.\n",
+ " this._resize_canvas(600, 600);\n",
+ "\n",
+ " // Disable right mouse context menu.\n",
+ " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n",
+ " return false;\n",
+ " });\n",
+ "\n",
+ " function set_focus () {\n",
+ " canvas.focus();\n",
+ " canvas_div.focus();\n",
+ " }\n",
+ "\n",
+ " window.setTimeout(set_focus, 100);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._init_toolbar = function() {\n",
+ " var fig = this;\n",
+ "\n",
+ " var nav_element = $('')\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 = $('');\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 = $('');\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 = $('');\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 = $('');\n",
+ "\n",
+ " var fmt_picker = $('');\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",
+ " '', {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 = $('');\n",
+ " nav_element.append(status_bar);\n",
+ " this.message = status_bar[0];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n",
+ " // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n",
+ " // which will in turn request a refresh of the image.\n",
+ " this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.send_message = function(type, properties) {\n",
+ " properties['type'] = type;\n",
+ " properties['figure_id'] = this.id;\n",
+ " this.ws.send(JSON.stringify(properties));\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.send_draw_message = function() {\n",
+ " if (!this.waiting) {\n",
+ " this.waiting = true;\n",
+ " this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n",
+ " }\n",
+ "}\n",
+ "\n",
+ "\n",
+ "mpl.figure.prototype.handle_save = function(fig, msg) {\n",
+ " var format_dropdown = fig.format_dropdown;\n",
+ " var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n",
+ " fig.ondownload(fig, format);\n",
+ "}\n",
+ "\n",
+ "\n",
+ "mpl.figure.prototype.handle_resize = function(fig, msg) {\n",
+ " var size = msg['size'];\n",
+ " if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n",
+ " fig._resize_canvas(size[0], size[1]);\n",
+ " fig.send_message(\"refresh\", {});\n",
+ " };\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n",
+ " var x0 = msg['x0'] / mpl.ratio;\n",
+ " var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n",
+ " var x1 = msg['x1'] / mpl.ratio;\n",
+ " var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n",
+ " x0 = Math.floor(x0) + 0.5;\n",
+ " y0 = Math.floor(y0) + 0.5;\n",
+ " x1 = Math.floor(x1) + 0.5;\n",
+ " y1 = Math.floor(y1) + 0.5;\n",
+ " var min_x = Math.min(x0, x1);\n",
+ " var min_y = Math.min(y0, y1);\n",
+ " var width = Math.abs(x1 - x0);\n",
+ " var height = Math.abs(y1 - y0);\n",
+ "\n",
+ " fig.rubberband_context.clearRect(\n",
+ " 0, 0, fig.canvas.width, fig.canvas.height);\n",
+ "\n",
+ " fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n",
+ " // Updates the figure title.\n",
+ " fig.header.textContent = msg['label'];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_cursor = function(fig, msg) {\n",
+ " var cursor = msg['cursor'];\n",
+ " switch(cursor)\n",
+ " {\n",
+ " case 0:\n",
+ " cursor = 'pointer';\n",
+ " break;\n",
+ " case 1:\n",
+ " cursor = 'default';\n",
+ " break;\n",
+ " case 2:\n",
+ " cursor = 'crosshair';\n",
+ " break;\n",
+ " case 3:\n",
+ " cursor = 'move';\n",
+ " break;\n",
+ " }\n",
+ " fig.rubberband_canvas.style.cursor = cursor;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_message = function(fig, msg) {\n",
+ " fig.message.textContent = msg['message'];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_draw = function(fig, msg) {\n",
+ " // Request the server to send over a new figure.\n",
+ " fig.send_draw_message();\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n",
+ " fig.image_mode = msg['mode'];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.updated_canvas_event = function() {\n",
+ " // Called whenever the canvas gets updated.\n",
+ " this.send_message(\"ack\", {});\n",
+ "}\n",
+ "\n",
+ "// A function to construct a web socket function for onmessage handling.\n",
+ "// Called in the figure constructor.\n",
+ "mpl.figure.prototype._make_on_message_function = function(fig) {\n",
+ " return function socket_on_message(evt) {\n",
+ " if (evt.data instanceof Blob) {\n",
+ " /* FIXME: We get \"Resource interpreted as Image but\n",
+ " * transferred with MIME type text/plain:\" errors on\n",
+ " * Chrome. But how to set the MIME type? It doesn't seem\n",
+ " * to be part of the websocket stream */\n",
+ " evt.data.type = \"image/png\";\n",
+ "\n",
+ " /* Free the memory for the previous frames */\n",
+ " if (fig.imageObj.src) {\n",
+ " (window.URL || window.webkitURL).revokeObjectURL(\n",
+ " fig.imageObj.src);\n",
+ " }\n",
+ "\n",
+ " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
+ " evt.data);\n",
+ " fig.updated_canvas_event();\n",
+ " fig.waiting = false;\n",
+ " return;\n",
+ " }\n",
+ " else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n",
+ " fig.imageObj.src = evt.data;\n",
+ " fig.updated_canvas_event();\n",
+ " fig.waiting = false;\n",
+ " return;\n",
+ " }\n",
+ "\n",
+ " var msg = JSON.parse(evt.data);\n",
+ " var msg_type = msg['type'];\n",
+ "\n",
+ " // Call the \"handle_{type}\" callback, which takes\n",
+ " // the figure and JSON message as its only arguments.\n",
+ " try {\n",
+ " var callback = fig[\"handle_\" + msg_type];\n",
+ " } catch (e) {\n",
+ " console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n",
+ " return;\n",
+ " }\n",
+ "\n",
+ " if (callback) {\n",
+ " try {\n",
+ " // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n",
+ " callback(fig, msg);\n",
+ " } catch (e) {\n",
+ " console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n",
+ " }\n",
+ " }\n",
+ " };\n",
+ "}\n",
+ "\n",
+ "// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n",
+ "mpl.findpos = function(e) {\n",
+ " //this section is from http://www.quirksmode.org/js/events_properties.html\n",
+ " var targ;\n",
+ " if (!e)\n",
+ " e = window.event;\n",
+ " if (e.target)\n",
+ " targ = e.target;\n",
+ " else if (e.srcElement)\n",
+ " targ = e.srcElement;\n",
+ " if (targ.nodeType == 3) // defeat Safari bug\n",
+ " targ = targ.parentNode;\n",
+ "\n",
+ " // jQuery normalizes the pageX and pageY\n",
+ " // pageX,Y are the mouse positions relative to the document\n",
+ " // offset() returns the position of the element relative to the document\n",
+ " var x = e.pageX - $(targ).offset().left;\n",
+ " var y = e.pageY - $(targ).offset().top;\n",
+ "\n",
+ " return {\"x\": x, \"y\": y};\n",
+ "};\n",
+ "\n",
+ "/*\n",
+ " * return a copy of an object with only non-object keys\n",
+ " * we need this to avoid circular references\n",
+ " * http://stackoverflow.com/a/24161582/3208463\n",
+ " */\n",
+ "function simpleKeys (original) {\n",
+ " return Object.keys(original).reduce(function (obj, key) {\n",
+ " if (typeof original[key] !== 'object')\n",
+ " obj[key] = original[key]\n",
+ " return obj;\n",
+ " }, {});\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.mouse_event = function(event, name) {\n",
+ " var canvas_pos = mpl.findpos(event)\n",
+ "\n",
+ " if (name === 'button_press')\n",
+ " {\n",
+ " this.canvas.focus();\n",
+ " this.canvas_div.focus();\n",
+ " }\n",
+ "\n",
+ " var x = canvas_pos.x * mpl.ratio;\n",
+ " var y = canvas_pos.y * mpl.ratio;\n",
+ "\n",
+ " this.send_message(name, {x: x, y: y, button: event.button,\n",
+ " step: event.step,\n",
+ " guiEvent: simpleKeys(event)});\n",
+ "\n",
+ " /* This prevents the web browser from automatically changing to\n",
+ " * the text insertion cursor when the button is pressed. We want\n",
+ " * to control all of the cursor setting manually through the\n",
+ " * 'cursor' event from matplotlib */\n",
+ " event.preventDefault();\n",
+ " return false;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._key_event_extra = function(event, name) {\n",
+ " // Handle any extra behaviour associated with a key event\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.key_event = function(event, name) {\n",
+ "\n",
+ " // Prevent repeat events\n",
+ " if (name == 'key_press')\n",
+ " {\n",
+ " if (event.which === this._key)\n",
+ " return;\n",
+ " else\n",
+ " this._key = event.which;\n",
+ " }\n",
+ " if (name == 'key_release')\n",
+ " this._key = null;\n",
+ "\n",
+ " var value = '';\n",
+ " if (event.ctrlKey && event.which != 17)\n",
+ " value += \"ctrl+\";\n",
+ " if (event.altKey && event.which != 18)\n",
+ " value += \"alt+\";\n",
+ " if (event.shiftKey && event.which != 16)\n",
+ " value += \"shift+\";\n",
+ "\n",
+ " value += 'k';\n",
+ " value += event.which.toString();\n",
+ "\n",
+ " this._key_event_extra(event, name);\n",
+ "\n",
+ " this.send_message(name, {key: value,\n",
+ " guiEvent: simpleKeys(event)});\n",
+ " return false;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.toolbar_button_onclick = function(name) {\n",
+ " if (name == 'download') {\n",
+ " this.handle_save(this, null);\n",
+ " } else {\n",
+ " this.send_message(\"toolbar_button\", {name: name});\n",
+ " }\n",
+ "};\n",
+ "\n",
+ "mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n",
+ " this.message.textContent = tooltip;\n",
+ "};\n",
+ "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n",
+ "\n",
+ "mpl.extensions = [\"eps\", \"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(\"\");\n",
+ " if (!fig.cell_info) {\n",
+ " console.error(\"Failed to find cell for figure\", id, fig);\n",
+ " return;\n",
+ " }\n",
+ "\n",
+ " var output_index = fig.cell_info[2]\n",
+ " var cell = fig.cell_info[0];\n",
+ "\n",
+ "};\n",
+ "\n",
+ "mpl.figure.prototype.handle_close = function(fig, msg) {\n",
+ " var width = fig.canvas.width/mpl.ratio\n",
+ " fig.root.unbind('remove')\n",
+ "\n",
+ " // Update the output cell to use the data from the current canvas.\n",
+ " fig.push_to_output();\n",
+ " var dataURL = fig.canvas.toDataURL();\n",
+ " // Re-enable the keyboard manager in IPython - without this line, in FF,\n",
+ " // the notebook keyboard shortcuts fail.\n",
+ " IPython.keyboard_manager.enable()\n",
+ " $(fig.parent_element).html('
');\n",
+ " fig.close_ws(fig, msg);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.close_ws = function(fig, msg){\n",
+ " fig.send_message('closing', msg);\n",
+ " // fig.ws.close()\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.push_to_output = function(remove_interactive) {\n",
+ " // Turn the data on the canvas into data in the output cell.\n",
+ " var width = this.canvas.width/mpl.ratio\n",
+ " var dataURL = this.canvas.toDataURL();\n",
+ " this.cell_info[1]['text/html'] = '
';\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 = $('')\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 = $('');\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 = $('');\n",
+ " nav_element.append(status_bar);\n",
+ " this.message = status_bar[0];\n",
+ "\n",
+ " // Add the close button to the window.\n",
+ " var buttongrp = $('');\n",
+ " var button = $('');\n",
+ " button.click(function (evt) { fig.handle_close(fig, {}); } );\n",
+ " button.mouseover('Stop Interaction', toolbar_mouse_event);\n",
+ " buttongrp.append(button);\n",
+ " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n",
+ " titlebar.prepend(buttongrp);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._root_extra_style = function(el){\n",
+ " var fig = this\n",
+ " el.on(\"remove\", function(){\n",
+ "\tfig.close_ws(fig, {});\n",
+ " });\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._canvas_extra_style = function(el){\n",
+ " // this is important to make the div 'focusable\n",
+ " el.attr('tabindex', 0)\n",
+ " // reach out to IPython and tell the keyboard manager to turn it's self\n",
+ " // off when our div gets focus\n",
+ "\n",
+ " // location in version 3\n",
+ " if (IPython.notebook.keyboard_manager) {\n",
+ " IPython.notebook.keyboard_manager.register_events(el);\n",
+ " }\n",
+ " else {\n",
+ " // location in version 2\n",
+ " IPython.keyboard_manager.register_events(el);\n",
+ " }\n",
+ "\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._key_event_extra = function(event, name) {\n",
+ " var manager = IPython.notebook.keyboard_manager;\n",
+ " if (!manager)\n",
+ " manager = IPython.keyboard_manager;\n",
+ "\n",
+ " // Check for shift+enter\n",
+ " if (event.shiftKey && event.which == 13) {\n",
+ " this.canvas_div.blur();\n",
+ " // select the cell after this one\n",
+ " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n",
+ " IPython.notebook.select(index + 1);\n",
+ " }\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_save = function(fig, msg) {\n",
+ " fig.ondownload(fig, null);\n",
+ "}\n",
+ "\n",
+ "\n",
+ "mpl.find_output_cell = function(html_output) {\n",
+ " // Return the cell and output element which can be found *uniquely* in the notebook.\n",
+ " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n",
+ " // IPython event is triggered only after the cells have been serialised, which for\n",
+ " // our purposes (turning an active figure into a static one), is too late.\n",
+ " var cells = IPython.notebook.get_cells();\n",
+ " var ncells = cells.length;\n",
+ " for (var i=0; i= 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": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/html": [
+ "
"
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "struc = getStrucFromPDFgui(PDFguiFile,0)\n",
+ "\n",
+ "svec = np.array([1.0,-1.0,0.0])\n",
+ "msp = MagSpecies(struc,magIdxs=[0,1,2,3],ffparamkey='Mn2',rmaxAtoms=50,basisvecs=svec,\n",
+ " kvecs=np.array([0.5,0.5,0.5]),label=str(0))\n",
+ "\n",
+ "mstr=MagStructure()\n",
+ "mstr.loadSpecies(msp)\n",
+ "mstr.makeAll()\n",
+ "\n",
+ "upMask = (np.apply_along_axis(np.linalg.norm,1,mstr.spins-svec)<0.01)\n",
+ "downMask = ~upMask\n",
+ "\n",
+ "### Visualize the magnetic structure\n",
+ "uc = struc[:4].xyz\n",
+ "visatoms = uc.copy()\n",
+ "visatoms = np.concatenate((visatoms,visatoms+np.array([0,0,1]),visatoms+np.array([0,1,0]),visatoms+np.array([0,0,1])))\n",
+ "visatoms = struc.lattice.cartesian(visatoms)\n",
+ "visspins = mstr.spinsFromAtoms(visatoms,fractional=False)\n",
+ "mstr.visualize(visatoms,visspins)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Make the MPDFcalculator"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "mc = MPDFcalculator(mstr)\n",
+ "mc.rmin = r.min()\n",
+ "mc.rmax = r.max()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Set up and perform the fit"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "from diffpy.srfit.fitbase import FitContribution\n",
+ "mfit = FitContribution('mfit')\n",
+ "mfit.setProfile(profile)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [],
+ "source": [
+ "# Define an mPDF function that will be added to the total PDF calculator\n",
+ "def mpdf(parascale, ordscale, damp, th, phi):\n",
+ " mc.paraScale, mc.ordScale, mc.dampRate = parascale, ordscale, damp\n",
+ " newvec = np.array([np.sin(th)*np.cos(phi),np.sin(th)*np.sin(phi),np.cos(th)])\n",
+ " mstr.spins[upMask] = newvec\n",
+ " mstr.spins[downMask] = -newvec\n",
+ " dr = mc.calc(both=True)[2]\n",
+ " return dr\n",
+ "\n",
+ "mfit.registerFunction(mpdf)\n",
+ "mfit.setEquation(\"mpdf(parascale, ordscale, damp, th, phi)\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [],
+ "source": [
+ "from diffpy.srfit.fitbase import FitRecipe\n",
+ "recipe = FitRecipe()\n",
+ "\n",
+ "# give the PDFContribution to the FitRecipe\n",
+ "recipe.addContribution(mfit)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ ""
+ ]
+ },
+ "execution_count": 8,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# add the mPDF variables\n",
+ "recipe.addVar(mfit.parascale, 4)\n",
+ "recipe.addVar(mfit.ordscale, 0.5)\n",
+ "recipe.addVar(mfit.damp, 0.01)\n",
+ "recipe.addVar(mfit.th, 0.5)\n",
+ "recipe.addVar(mfit.phi, 0.5)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "thrst = recipe.restrain(recipe.th, lb=0, ub=np.pi, sig=0.0001) \n",
+ "phirst = recipe.restrain(recipe.phi, lb=-np.pi, ub=np.pi, sig=0.0001) "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Refine using scipy's least-squares optimizer:\n",
+ " variables: ['parascale', 'ordscale', 'damp', 'th', 'phi']\n",
+ " initial values: [ 4. 0.5 0.01 0.5 0.5 ]\n",
+ " final values: [ 3.98934342e+00 1.61286874e+00 -6.71623536e-04 -2.28116068e-02\n",
+ " 4.48462494e-01]\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Turn off printout of iteration number.\n",
+ "recipe.clearFitHooks()\n",
+ "\n",
+ "# Initial structural fit\n",
+ "print \"Refine using scipy's least-squares optimizer:\"\n",
+ "print \" variables:\", recipe.names\n",
+ "print \" initial values:\", recipe.values\n",
+ "\n",
+ "from scipy.optimize import least_squares\n",
+ "\n",
+ "least_squares(recipe.residual, recipe.values)\n",
+ "print \" final values:\", recipe.values"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Plot the result"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [
+ {
+ "data": {
+ "application/javascript": [
+ "/* Put everything inside the global mpl namespace */\n",
+ "window.mpl = {};\n",
+ "\n",
+ "\n",
+ "mpl.get_websocket_type = function() {\n",
+ " if (typeof(WebSocket) !== 'undefined') {\n",
+ " return WebSocket;\n",
+ " } else if (typeof(MozWebSocket) !== 'undefined') {\n",
+ " return MozWebSocket;\n",
+ " } else {\n",
+ " alert('Your browser does not have WebSocket support.' +\n",
+ " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
+ " 'Firefox 4 and 5 are also supported but you ' +\n",
+ " 'have to enable WebSockets in about:config.');\n",
+ " };\n",
+ "}\n",
+ "\n",
+ "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n",
+ " this.id = figure_id;\n",
+ "\n",
+ " this.ws = websocket;\n",
+ "\n",
+ " this.supports_binary = (this.ws.binaryType != undefined);\n",
+ "\n",
+ " if (!this.supports_binary) {\n",
+ " var warnings = document.getElementById(\"mpl-warnings\");\n",
+ " if (warnings) {\n",
+ " warnings.style.display = 'block';\n",
+ " warnings.textContent = (\n",
+ " \"This browser does not support binary websocket messages. \" +\n",
+ " \"Performance may be slow.\");\n",
+ " }\n",
+ " }\n",
+ "\n",
+ " this.imageObj = new Image();\n",
+ "\n",
+ " this.context = undefined;\n",
+ " this.message = undefined;\n",
+ " this.canvas = undefined;\n",
+ " this.rubberband_canvas = undefined;\n",
+ " this.rubberband_context = undefined;\n",
+ " this.format_dropdown = undefined;\n",
+ "\n",
+ " this.image_mode = 'full';\n",
+ "\n",
+ " this.root = $('');\n",
+ " this._root_extra_style(this.root)\n",
+ " this.root.attr('style', 'display: inline-block');\n",
+ "\n",
+ " $(parent_element).append(this.root);\n",
+ "\n",
+ " this._init_header(this);\n",
+ " this._init_canvas(this);\n",
+ " this._init_toolbar(this);\n",
+ "\n",
+ " var fig = this;\n",
+ "\n",
+ " this.waiting = false;\n",
+ "\n",
+ " this.ws.onopen = function () {\n",
+ " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n",
+ " fig.send_message(\"send_image_mode\", {});\n",
+ " if (mpl.ratio != 1) {\n",
+ " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n",
+ " }\n",
+ " fig.send_message(\"refresh\", {});\n",
+ " }\n",
+ "\n",
+ " this.imageObj.onload = function() {\n",
+ " if (fig.image_mode == 'full') {\n",
+ " // Full images could contain transparency (where diff images\n",
+ " // almost always do), so we need to clear the canvas so that\n",
+ " // there is no ghosting.\n",
+ " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
+ " }\n",
+ " fig.context.drawImage(fig.imageObj, 0, 0);\n",
+ " };\n",
+ "\n",
+ " this.imageObj.onunload = function() {\n",
+ " this.ws.close();\n",
+ " }\n",
+ "\n",
+ " this.ws.onmessage = this._make_on_message_function(this);\n",
+ "\n",
+ " this.ondownload = ondownload;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._init_header = function() {\n",
+ " var titlebar = $(\n",
+ " '');\n",
+ " var titletext = $(\n",
+ " '');\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 = $('');\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 = $('');\n",
+ " canvas.addClass('mpl-canvas');\n",
+ " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n",
+ "\n",
+ " this.canvas = canvas[0];\n",
+ " this.context = canvas[0].getContext(\"2d\");\n",
+ "\n",
+ " var backingStore = this.context.backingStorePixelRatio ||\n",
+ "\tthis.context.webkitBackingStorePixelRatio ||\n",
+ "\tthis.context.mozBackingStorePixelRatio ||\n",
+ "\tthis.context.msBackingStorePixelRatio ||\n",
+ "\tthis.context.oBackingStorePixelRatio ||\n",
+ "\tthis.context.backingStorePixelRatio || 1;\n",
+ "\n",
+ " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n",
+ "\n",
+ " var rubberband = $('');\n",
+ " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n",
+ "\n",
+ " var pass_mouse_events = true;\n",
+ "\n",
+ " canvas_div.resizable({\n",
+ " start: function(event, ui) {\n",
+ " pass_mouse_events = false;\n",
+ " },\n",
+ " resize: function(event, ui) {\n",
+ " fig.request_resize(ui.size.width, ui.size.height);\n",
+ " },\n",
+ " stop: function(event, ui) {\n",
+ " pass_mouse_events = true;\n",
+ " fig.request_resize(ui.size.width, ui.size.height);\n",
+ " },\n",
+ " });\n",
+ "\n",
+ " function mouse_event_fn(event) {\n",
+ " if (pass_mouse_events)\n",
+ " return fig.mouse_event(event, event['data']);\n",
+ " }\n",
+ "\n",
+ " rubberband.mousedown('button_press', mouse_event_fn);\n",
+ " rubberband.mouseup('button_release', mouse_event_fn);\n",
+ " // Throttle sequential mouse events to 1 every 20ms.\n",
+ " rubberband.mousemove('motion_notify', mouse_event_fn);\n",
+ "\n",
+ " rubberband.mouseenter('figure_enter', mouse_event_fn);\n",
+ " rubberband.mouseleave('figure_leave', mouse_event_fn);\n",
+ "\n",
+ " canvas_div.on(\"wheel\", function (event) {\n",
+ " event = event.originalEvent;\n",
+ " event['data'] = 'scroll'\n",
+ " if (event.deltaY < 0) {\n",
+ " event.step = 1;\n",
+ " } else {\n",
+ " event.step = -1;\n",
+ " }\n",
+ " mouse_event_fn(event);\n",
+ " });\n",
+ "\n",
+ " canvas_div.append(canvas);\n",
+ " canvas_div.append(rubberband);\n",
+ "\n",
+ " this.rubberband = rubberband;\n",
+ " this.rubberband_canvas = rubberband[0];\n",
+ " this.rubberband_context = rubberband[0].getContext(\"2d\");\n",
+ " this.rubberband_context.strokeStyle = \"#000000\";\n",
+ "\n",
+ " this._resize_canvas = function(width, height) {\n",
+ " // Keep the size of the canvas, canvas container, and rubber band\n",
+ " // canvas in synch.\n",
+ " canvas_div.css('width', width)\n",
+ " canvas_div.css('height', height)\n",
+ "\n",
+ " canvas.attr('width', width * mpl.ratio);\n",
+ " canvas.attr('height', height * mpl.ratio);\n",
+ " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n",
+ "\n",
+ " rubberband.attr('width', width);\n",
+ " rubberband.attr('height', height);\n",
+ " }\n",
+ "\n",
+ " // Set the figure to an initial 600x600px, this will subsequently be updated\n",
+ " // upon first draw.\n",
+ " this._resize_canvas(600, 600);\n",
+ "\n",
+ " // Disable right mouse context menu.\n",
+ " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n",
+ " return false;\n",
+ " });\n",
+ "\n",
+ " function set_focus () {\n",
+ " canvas.focus();\n",
+ " canvas_div.focus();\n",
+ " }\n",
+ "\n",
+ " window.setTimeout(set_focus, 100);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._init_toolbar = function() {\n",
+ " var fig = this;\n",
+ "\n",
+ " var nav_element = $('')\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 = $('');\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 = $('');\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 = $('');\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 = $('');\n",
+ "\n",
+ " var fmt_picker = $('');\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",
+ " '', {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 = $('');\n",
+ " nav_element.append(status_bar);\n",
+ " this.message = status_bar[0];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n",
+ " // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n",
+ " // which will in turn request a refresh of the image.\n",
+ " this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.send_message = function(type, properties) {\n",
+ " properties['type'] = type;\n",
+ " properties['figure_id'] = this.id;\n",
+ " this.ws.send(JSON.stringify(properties));\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.send_draw_message = function() {\n",
+ " if (!this.waiting) {\n",
+ " this.waiting = true;\n",
+ " this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n",
+ " }\n",
+ "}\n",
+ "\n",
+ "\n",
+ "mpl.figure.prototype.handle_save = function(fig, msg) {\n",
+ " var format_dropdown = fig.format_dropdown;\n",
+ " var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n",
+ " fig.ondownload(fig, format);\n",
+ "}\n",
+ "\n",
+ "\n",
+ "mpl.figure.prototype.handle_resize = function(fig, msg) {\n",
+ " var size = msg['size'];\n",
+ " if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n",
+ " fig._resize_canvas(size[0], size[1]);\n",
+ " fig.send_message(\"refresh\", {});\n",
+ " };\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n",
+ " var x0 = msg['x0'] / mpl.ratio;\n",
+ " var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n",
+ " var x1 = msg['x1'] / mpl.ratio;\n",
+ " var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n",
+ " x0 = Math.floor(x0) + 0.5;\n",
+ " y0 = Math.floor(y0) + 0.5;\n",
+ " x1 = Math.floor(x1) + 0.5;\n",
+ " y1 = Math.floor(y1) + 0.5;\n",
+ " var min_x = Math.min(x0, x1);\n",
+ " var min_y = Math.min(y0, y1);\n",
+ " var width = Math.abs(x1 - x0);\n",
+ " var height = Math.abs(y1 - y0);\n",
+ "\n",
+ " fig.rubberband_context.clearRect(\n",
+ " 0, 0, fig.canvas.width, fig.canvas.height);\n",
+ "\n",
+ " fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n",
+ " // Updates the figure title.\n",
+ " fig.header.textContent = msg['label'];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_cursor = function(fig, msg) {\n",
+ " var cursor = msg['cursor'];\n",
+ " switch(cursor)\n",
+ " {\n",
+ " case 0:\n",
+ " cursor = 'pointer';\n",
+ " break;\n",
+ " case 1:\n",
+ " cursor = 'default';\n",
+ " break;\n",
+ " case 2:\n",
+ " cursor = 'crosshair';\n",
+ " break;\n",
+ " case 3:\n",
+ " cursor = 'move';\n",
+ " break;\n",
+ " }\n",
+ " fig.rubberband_canvas.style.cursor = cursor;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_message = function(fig, msg) {\n",
+ " fig.message.textContent = msg['message'];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_draw = function(fig, msg) {\n",
+ " // Request the server to send over a new figure.\n",
+ " fig.send_draw_message();\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n",
+ " fig.image_mode = msg['mode'];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.updated_canvas_event = function() {\n",
+ " // Called whenever the canvas gets updated.\n",
+ " this.send_message(\"ack\", {});\n",
+ "}\n",
+ "\n",
+ "// A function to construct a web socket function for onmessage handling.\n",
+ "// Called in the figure constructor.\n",
+ "mpl.figure.prototype._make_on_message_function = function(fig) {\n",
+ " return function socket_on_message(evt) {\n",
+ " if (evt.data instanceof Blob) {\n",
+ " /* FIXME: We get \"Resource interpreted as Image but\n",
+ " * transferred with MIME type text/plain:\" errors on\n",
+ " * Chrome. But how to set the MIME type? It doesn't seem\n",
+ " * to be part of the websocket stream */\n",
+ " evt.data.type = \"image/png\";\n",
+ "\n",
+ " /* Free the memory for the previous frames */\n",
+ " if (fig.imageObj.src) {\n",
+ " (window.URL || window.webkitURL).revokeObjectURL(\n",
+ " fig.imageObj.src);\n",
+ " }\n",
+ "\n",
+ " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
+ " evt.data);\n",
+ " fig.updated_canvas_event();\n",
+ " fig.waiting = false;\n",
+ " return;\n",
+ " }\n",
+ " else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n",
+ " fig.imageObj.src = evt.data;\n",
+ " fig.updated_canvas_event();\n",
+ " fig.waiting = false;\n",
+ " return;\n",
+ " }\n",
+ "\n",
+ " var msg = JSON.parse(evt.data);\n",
+ " var msg_type = msg['type'];\n",
+ "\n",
+ " // Call the \"handle_{type}\" callback, which takes\n",
+ " // the figure and JSON message as its only arguments.\n",
+ " try {\n",
+ " var callback = fig[\"handle_\" + msg_type];\n",
+ " } catch (e) {\n",
+ " console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n",
+ " return;\n",
+ " }\n",
+ "\n",
+ " if (callback) {\n",
+ " try {\n",
+ " // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n",
+ " callback(fig, msg);\n",
+ " } catch (e) {\n",
+ " console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n",
+ " }\n",
+ " }\n",
+ " };\n",
+ "}\n",
+ "\n",
+ "// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n",
+ "mpl.findpos = function(e) {\n",
+ " //this section is from http://www.quirksmode.org/js/events_properties.html\n",
+ " var targ;\n",
+ " if (!e)\n",
+ " e = window.event;\n",
+ " if (e.target)\n",
+ " targ = e.target;\n",
+ " else if (e.srcElement)\n",
+ " targ = e.srcElement;\n",
+ " if (targ.nodeType == 3) // defeat Safari bug\n",
+ " targ = targ.parentNode;\n",
+ "\n",
+ " // jQuery normalizes the pageX and pageY\n",
+ " // pageX,Y are the mouse positions relative to the document\n",
+ " // offset() returns the position of the element relative to the document\n",
+ " var x = e.pageX - $(targ).offset().left;\n",
+ " var y = e.pageY - $(targ).offset().top;\n",
+ "\n",
+ " return {\"x\": x, \"y\": y};\n",
+ "};\n",
+ "\n",
+ "/*\n",
+ " * return a copy of an object with only non-object keys\n",
+ " * we need this to avoid circular references\n",
+ " * http://stackoverflow.com/a/24161582/3208463\n",
+ " */\n",
+ "function simpleKeys (original) {\n",
+ " return Object.keys(original).reduce(function (obj, key) {\n",
+ " if (typeof original[key] !== 'object')\n",
+ " obj[key] = original[key]\n",
+ " return obj;\n",
+ " }, {});\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.mouse_event = function(event, name) {\n",
+ " var canvas_pos = mpl.findpos(event)\n",
+ "\n",
+ " if (name === 'button_press')\n",
+ " {\n",
+ " this.canvas.focus();\n",
+ " this.canvas_div.focus();\n",
+ " }\n",
+ "\n",
+ " var x = canvas_pos.x * mpl.ratio;\n",
+ " var y = canvas_pos.y * mpl.ratio;\n",
+ "\n",
+ " this.send_message(name, {x: x, y: y, button: event.button,\n",
+ " step: event.step,\n",
+ " guiEvent: simpleKeys(event)});\n",
+ "\n",
+ " /* This prevents the web browser from automatically changing to\n",
+ " * the text insertion cursor when the button is pressed. We want\n",
+ " * to control all of the cursor setting manually through the\n",
+ " * 'cursor' event from matplotlib */\n",
+ " event.preventDefault();\n",
+ " return false;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._key_event_extra = function(event, name) {\n",
+ " // Handle any extra behaviour associated with a key event\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.key_event = function(event, name) {\n",
+ "\n",
+ " // Prevent repeat events\n",
+ " if (name == 'key_press')\n",
+ " {\n",
+ " if (event.which === this._key)\n",
+ " return;\n",
+ " else\n",
+ " this._key = event.which;\n",
+ " }\n",
+ " if (name == 'key_release')\n",
+ " this._key = null;\n",
+ "\n",
+ " var value = '';\n",
+ " if (event.ctrlKey && event.which != 17)\n",
+ " value += \"ctrl+\";\n",
+ " if (event.altKey && event.which != 18)\n",
+ " value += \"alt+\";\n",
+ " if (event.shiftKey && event.which != 16)\n",
+ " value += \"shift+\";\n",
+ "\n",
+ " value += 'k';\n",
+ " value += event.which.toString();\n",
+ "\n",
+ " this._key_event_extra(event, name);\n",
+ "\n",
+ " this.send_message(name, {key: value,\n",
+ " guiEvent: simpleKeys(event)});\n",
+ " return false;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.toolbar_button_onclick = function(name) {\n",
+ " if (name == 'download') {\n",
+ " this.handle_save(this, null);\n",
+ " } else {\n",
+ " this.send_message(\"toolbar_button\", {name: name});\n",
+ " }\n",
+ "};\n",
+ "\n",
+ "mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n",
+ " this.message.textContent = tooltip;\n",
+ "};\n",
+ "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n",
+ "\n",
+ "mpl.extensions = [\"eps\", \"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(\"\");\n",
+ " if (!fig.cell_info) {\n",
+ " console.error(\"Failed to find cell for figure\", id, fig);\n",
+ " return;\n",
+ " }\n",
+ "\n",
+ " var output_index = fig.cell_info[2]\n",
+ " var cell = fig.cell_info[0];\n",
+ "\n",
+ "};\n",
+ "\n",
+ "mpl.figure.prototype.handle_close = function(fig, msg) {\n",
+ " var width = fig.canvas.width/mpl.ratio\n",
+ " fig.root.unbind('remove')\n",
+ "\n",
+ " // Update the output cell to use the data from the current canvas.\n",
+ " fig.push_to_output();\n",
+ " var dataURL = fig.canvas.toDataURL();\n",
+ " // Re-enable the keyboard manager in IPython - without this line, in FF,\n",
+ " // the notebook keyboard shortcuts fail.\n",
+ " IPython.keyboard_manager.enable()\n",
+ " $(fig.parent_element).html('
');\n",
+ " fig.close_ws(fig, msg);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.close_ws = function(fig, msg){\n",
+ " fig.send_message('closing', msg);\n",
+ " // fig.ws.close()\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.push_to_output = function(remove_interactive) {\n",
+ " // Turn the data on the canvas into data in the output cell.\n",
+ " var width = this.canvas.width/mpl.ratio\n",
+ " var dataURL = this.canvas.toDataURL();\n",
+ " this.cell_info[1]['text/html'] = '
';\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 = $('')\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 = $('');\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 = $('');\n",
+ " nav_element.append(status_bar);\n",
+ " this.message = status_bar[0];\n",
+ "\n",
+ " // Add the close button to the window.\n",
+ " var buttongrp = $('');\n",
+ " var button = $('');\n",
+ " button.click(function (evt) { fig.handle_close(fig, {}); } );\n",
+ " button.mouseover('Stop Interaction', toolbar_mouse_event);\n",
+ " buttongrp.append(button);\n",
+ " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n",
+ " titlebar.prepend(buttongrp);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._root_extra_style = function(el){\n",
+ " var fig = this\n",
+ " el.on(\"remove\", function(){\n",
+ "\tfig.close_ws(fig, {});\n",
+ " });\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._canvas_extra_style = function(el){\n",
+ " // this is important to make the div 'focusable\n",
+ " el.attr('tabindex', 0)\n",
+ " // reach out to IPython and tell the keyboard manager to turn it's self\n",
+ " // off when our div gets focus\n",
+ "\n",
+ " // location in version 3\n",
+ " if (IPython.notebook.keyboard_manager) {\n",
+ " IPython.notebook.keyboard_manager.register_events(el);\n",
+ " }\n",
+ " else {\n",
+ " // location in version 2\n",
+ " IPython.keyboard_manager.register_events(el);\n",
+ " }\n",
+ "\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._key_event_extra = function(event, name) {\n",
+ " var manager = IPython.notebook.keyboard_manager;\n",
+ " if (!manager)\n",
+ " manager = IPython.keyboard_manager;\n",
+ "\n",
+ " // Check for shift+enter\n",
+ " if (event.shiftKey && event.which == 13) {\n",
+ " this.canvas_div.blur();\n",
+ " // select the cell after this one\n",
+ " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n",
+ " IPython.notebook.select(index + 1);\n",
+ " }\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_save = function(fig, msg) {\n",
+ " fig.ondownload(fig, null);\n",
+ "}\n",
+ "\n",
+ "\n",
+ "mpl.find_output_cell = function(html_output) {\n",
+ " // Return the cell and output element which can be found *uniquely* in the notebook.\n",
+ " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n",
+ " // IPython event is triggered only after the cells have been serialised, which for\n",
+ " // our purposes (turning an active figure into a static one), is too late.\n",
+ " var cells = IPython.notebook.get_cells();\n",
+ " var ncells = cells.length;\n",
+ " for (var i=0; i= 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": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/html": [
+ "
"
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "gcalc = mfit.evaluateEquation(\"mpdf\")\n",
+ "\n",
+ "# Plot just the mPDF\n",
+ "ax=plt.figure().add_subplot(111)\n",
+ "ax.plot(r, d, 'bo', label=\"mPDF data\", markerfacecolor='none', markeredgecolor='b')\n",
+ "ax.plot(r, gcalc, 'r-', lw=2, label=\"mPDF fit\")\n",
+ "ax.set_xlabel(r\"r ($\\AA$)\")\n",
+ "ax.set_ylabel(r\"D ($\\AA^{-2}$)\")\n",
+ "ax.set_xlim(xmax=mc.rmax)\n",
+ "plt.legend(loc=1)\n",
+ "\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "plt.close('all')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "The restraints do not work very well!!! Maybe discuss with Pavol?"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 2",
+ "language": "python",
+ "name": "python2"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 2
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython2",
+ "version": "2.7.11"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 0
+}
diff --git a/cmi_scripts/mpdf/example_corefinement.ipynb b/cmi_scripts/mpdf/example_corefinement.ipynb
new file mode 100644
index 0000000..d25c9e8
--- /dev/null
+++ b/cmi_scripts/mpdf/example_corefinement.ipynb
@@ -0,0 +1,307 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Atomic and magnetic PDF co-refinement using SrFit"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "This notebook provides an example of a simultaneous atomic + magnetic PDF refinement using SrFit. We will again use MnO as our test case."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Import necessary modules"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "### Import the necessary libraries\n",
+ "import numpy as np\n",
+ "import matplotlib.pyplot as plt\n",
+ "\n",
+ "from diffpy.mpdf import *\n",
+ "from diffpy.Structure import loadStructure\n",
+ "from scipy.optimize import least_squares\n",
+ "from diffpy.Structure.Parsers import getParser\n",
+ "from diffpy.srfit.pdf import PDFGenerator, PDFParser\n",
+ "from diffpy.srfit.fitbase import FitRecipe, FitResults\n",
+ "from diffpy.srfit.fitbase import Profile, FitContribution\n",
+ "\n",
+ "### Set all plots to be inline\n",
+ "%matplotlib notebook"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Set up nuclear/magnetic PDF structures and calculators"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [],
+ "source": [
+ "# Files containing our experimental data and structure file\n",
+ "dataFile = \"npdf_07334.gr\"\n",
+ "structureFile = \"MnO_R-3m.cif\"\n",
+ "\n",
+ "# load structure and space group from the CIF file\n",
+ "pcif = getParser('cif')\n",
+ "mno = pcif.parseFile(structureFile)\n",
+ "\n",
+ "# prepare profile object with experimental data\n",
+ "profile = Profile()\n",
+ "parser = PDFParser()\n",
+ "parser.parseFile(dataFile)\n",
+ "profile.loadParsedData(parser)\n",
+ "\n",
+ "# define range for pdf calculation\n",
+ "rmin = 0.01\n",
+ "rmax = 20\n",
+ "rstep = 0.01\n",
+ "\n",
+ "# setup calculation range for the PDF simulation\n",
+ "profile.setCalculationRange(xmin=rmin, xmax=rmax, dx=rstep)\n",
+ "\n",
+ "# prepare nucpdf function that simulates the nuclear PDF\n",
+ "nucpdf = PDFGenerator(\"nucpdf\")\n",
+ "nucpdf.setStructure(mno)\n",
+ "nucpdf.setProfile(profile)\n",
+ "\n",
+ "# prepare mpdf function that simulates the magnetic PDF\n",
+ "\n",
+ "# Create the Mn2+ magnetic species. Note that we are using a different\n",
+ "# setting for the unit cell, so the propagation vector is actually (0,0,3/2)\n",
+ "# instead of the (1/2,1/2,1/2) as it was for the pseudocubic setting.\n",
+ "mn2p = MagSpecies(struc=mno, label='Mn2+', magIdxs=[0,1,2],\n",
+ " basisvecs=np.array([1,0,0]), kvecs=np.array([0,0,1.5]),\n",
+ " ffparamkey='Mn2')\n",
+ "\n",
+ "\n",
+ "# Create and prep the magnetic structure\n",
+ "mstr = MagStructure()\n",
+ "mstr.loadSpecies(mn2p)\n",
+ "mstr.makeAll()\n",
+ "\n",
+ "# Set up the mPDF calculator.\n",
+ "\n",
+ "mc=MPDFcalculator(magstruc=mstr,rmin=rmin,rmax=rmax,rstep=rstep)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Create a \"total PDF\" calculator"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [],
+ "source": [
+ "totpdf = FitContribution('totpdf')\n",
+ "totpdf.addProfileGenerator(nucpdf)\n",
+ "totpdf.setProfile(profile)\n",
+ "\n",
+ "# Define an mPDF function that will be added to the total PDF calculator\n",
+ "def mpdf(parascale, ordscale, damp):\n",
+ " mc.paraScale, mc.ordScale, mc.dampRate = parascale, ordscale, damp\n",
+ " mc.magstruc.makeAll()\n",
+ " dr = mc.calc(both=True)[2]\n",
+ " return dr\n",
+ "\n",
+ "#Add mPDF to the FitContribution\n",
+ "totpdf.registerFunction(mpdf)\n",
+ "totpdf.setEquation(\"nucscale * nucpdf + mpdf(parascale, ordscale, damp)\")\n",
+ "\n",
+ "# Make magnetic PDF depend on any changes to the atomic structure.\n",
+ "# A structure change will now trigger reevaluation of the mPDF.\n",
+ "nucpdf.phase.addObserver(totpdf.ordscale.notify)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Set up the fit recipe and add the parameters"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [],
+ "source": [
+ "# The FitRecipe does the work of calculating the PDF with the fit variable\n",
+ "# that we give it.\n",
+ "mnofit = FitRecipe()\n",
+ "\n",
+ "# give the PDFContribution to the FitRecipe\n",
+ "mnofit.addContribution(totpdf)\n",
+ "\n",
+ "# Configure the fit variables and give them to the recipe. We can use the\n",
+ "# srfit function constrainAsSpaceGroup to constrain the lattice and ADP\n",
+ "# parameters according to the CIF-loaded space group.\n",
+ "from diffpy.srfit.structure import constrainAsSpaceGroup\n",
+ "sgpars = constrainAsSpaceGroup(nucpdf.phase, pcif.spacegroup.short_name)\n",
+ "\n",
+ "# We can now cycle through the parameters and activate them as variables\n",
+ "for par in sgpars.latpars:\n",
+ " mnofit.addVar(par)\n",
+ "# Set initial value for the ADP parameters, because CIF had no ADP data.\n",
+ "for par in sgpars.adppars:\n",
+ " mnofit.addVar(par, value=0.003)\n",
+ "\n",
+ "# As usual, we add variables for the overall scale of the PDF and a delta2\n",
+ "# parameter for correlated motion of neighboring atoms.\n",
+ "mnofit.addVar(totpdf.nucscale, 1)\n",
+ "mnofit.addVar(nucpdf.delta2, 1.5)\n",
+ "\n",
+ "# We fix Qdamp based on prior information about our beamline.\n",
+ "mnofit.addVar(nucpdf.qdamp, 0.03, fixed=True)\n",
+ "\n",
+ "# add the mPDF variables\n",
+ "mnofit.addVar(totpdf.parascale, 4)\n",
+ "mnofit.addVar(totpdf.ordscale, 1.5)\n",
+ "mnofit.addVar(totpdf.damp, 0.01)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Perform the refinement"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [],
+ "source": [
+ "# Turn off printout of iteration number.\n",
+ "mnofit.clearFitHooks()\n",
+ "\n",
+ "# Initial structural fit\n",
+ "print \"Refine PDF using scipy's least-squares optimizer:\"\n",
+ "print \" variables:\", mnofit.names\n",
+ "print \" initial values:\", mnofit.values\n",
+ "least_squares(mnofit.residual, mnofit.values)\n",
+ "print \" final values:\", mnofit.values"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Plot the result"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [],
+ "source": [
+ "r = mnofit.totpdf.profile.x\n",
+ "gobs = mnofit.totpdf.profile.y\n",
+ "\n",
+ "# Get the calculated PDF and compute the difference between the calculated and\n",
+ "# measured PDF\n",
+ "gcalc = mnofit.totpdf.evaluate()\n",
+ "gnuc = mnofit.totpdf.evaluateEquation('nucscale * nucpdf')\n",
+ "gmag = mnofit.totpdf.evaluateEquation('mpdf')\n",
+ "\n",
+ "baseline = 1.1 * gobs.min()\n",
+ "gdiff = gobs - gcalc\n",
+ "baseline2 = 1.1 * (gdiff+baseline).min()\n",
+ "\n",
+ "# Plot the best-fit total PDF\n",
+ "ax=plt.figure().add_subplot(111)\n",
+ "ax.plot(r, gobs, 'bo', label=\"G(r) data\", markerfacecolor='none', markeredgecolor='b')\n",
+ "ax.plot(r, gcalc, 'r-', lw=2, label=\"G(r) fit\")\n",
+ "ax.plot(r, gdiff + baseline,'g-')\n",
+ "ax.plot(r, np.zeros_like(r) + baseline, 'k:')\n",
+ "ax.set_xlabel(r\"r ($\\AA$)\")\n",
+ "ax.set_ylabel(r\"G ($\\AA^{-2}$)\")\n",
+ "ax.set_xlim(xmax=mc.rmax)\n",
+ "plt.legend()\n",
+ "\n",
+ "plt.show()\n",
+ "\n",
+ "\n",
+ "# Plot just the mPDF\n",
+ "ax=plt.figure().add_subplot(111)\n",
+ "ax.plot(r, gobs-gnuc, 'bo', label=\"mPDF data\", markerfacecolor='none', markeredgecolor='b')\n",
+ "ax.plot(r, gmag, 'r-', lw=2, label=\"mPDF fit\")\n",
+ "ax.set_xlabel(r\"r ($\\AA$)\")\n",
+ "ax.set_ylabel(r\"D ($\\AA^{-2}$)\")\n",
+ "ax.set_xlim(xmax=mc.rmax)\n",
+ "plt.legend(loc=1)\n",
+ "\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "plt.close('all')"
+ ]
+ }
+ ],
+ "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.11"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 0
+}
diff --git a/cmi_scripts/mpdf/example_corefinement1.py b/cmi_scripts/mpdf/example_corefinement1.py
deleted file mode 100644
index 8e5aa40..0000000
--- a/cmi_scripts/mpdf/example_corefinement1.py
+++ /dev/null
@@ -1,163 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-'''
-This example will show how to simultaneously refine the atomic and magnetic PDF
-of MnO using SrFit.
-'''
-
-# Import necessary functions
-import numpy as np
-import matplotlib.pyplot as plt
-from scipy.optimize.minpack import leastsq
-
-from diffpy.mpdf import *
-from diffpy.Structure.Parsers import getParser
-from diffpy.srfit.pdf import PDFGenerator, PDFParser
-from diffpy.srfit.fitbase import FitRecipe, FitResults
-from diffpy.srfit.fitbase import Profile, FitContribution
-
-# Files containing our experimental data and structure file
-dataFile = "npdf_07334.gr"
-structureFile = "MnO_R-3m.cif"
-
-# load structure and space group from the CIF file
-pcif = getParser('cif')
-mno = pcif.parseFile(structureFile)
-
-# prepare profile object with experimental data
-profile = Profile()
-parser = PDFParser()
-parser.parseFile(dataFile)
-profile.loadParsedData(parser)
-
-# define range for pdf calculation
-rmin = 0.01
-rmax = 20
-rstep = 0.01
-
-# setup calculation range for the PDF simulation
-profile.setCalculationRange(xmin=rmin, xmax=rmax, dx=rstep)
-
-# prepare nucpdf function that simulates the nuclear PDF
-nucpdf = PDFGenerator("nucpdf")
-nucpdf.setStructure(mno)
-nucpdf.setProfile(profile)
-
-# prepare mpdf function that simulates the magnetic PDF
-
-# Create the Mn2+ magnetic species
-mn2p = MagSpecies(struc=mno, label='Mn2+', magIdxs=[0,1,2],
- basisvecs=2.5*np.array([1,0,0]), kvecs=np.array([0,0,1.5]),
- ffparamkey='Mn2')
-
-# Create and prep the magnetic structure
-mstr = MagStructure()
-mstr.loadSpecies(mn2p)
-mstr.makeAll()
-
-# Set up the mPDF calculator.
-
-mc=MPDFcalculator(magstruc=mstr,rmin=rmin,rmax=rmax,
- rstep=rstep, gaussPeakWidth=0.2)
-
-def mpdf(parascale, ordscale):
- mc.paraScale = parascale
- mc.ordScale = ordscale
- mc.magstruc.makeAtoms()
- mc.magstruc.makeSpins()
- rv = mc.calc(both=True)[2]
- return rv
-
-totpdf = FitContribution('totpdf')
-totpdf.addProfileGenerator(nucpdf)
-totpdf.setProfile(profile)
-
-# Add mPDF to the FitContribution
-totpdf.registerFunction(mpdf)
-totpdf.setEquation("nucscale * nucpdf + mpdf(parascale, ordscale)")
-
-# Make magnetic PDF depend on any changes to the atomic structure.
-# Cover your eyes, but a structure change will now trigger the same
-# reevaluations as if ordscale were modified.
-nucpdf.phase.addObserver(totpdf.ordscale.notify)
-
-# The FitRecipe does the work of calculating the PDF with the fit variable
-# that we give it.
-mnofit = FitRecipe()
-
-# give the PDFContribution to the FitRecipe
-mnofit.addContribution(totpdf)
-
-# Configure the fit variables and give them to the recipe. We can use the
-# srfit function constrainAsSpaceGroup to constrain the lattice and ADP
-# parameters according to the CIF-loaded space group.
-from diffpy.srfit.structure import constrainAsSpaceGroup
-sgpars = constrainAsSpaceGroup(nucpdf.phase, pcif.spacegroup.short_name)
-print "Space group parameters are:",
-print ', '.join([p.name for p in sgpars])
-print
-
-# We can now cycle through the parameters and activate them in the recipe as
-# variables
-for par in sgpars.latpars:
- mnofit.addVar(par)
-# Set initial value for the ADP parameters, because CIF had no ADP data.
-for par in sgpars.adppars:
- mnofit.addVar(par, value=0.003, fixed=True)
-
-# As usual, we add variables for the overall scale of the PDF and a delta2
-# parameter for correlated motion of neighboring atoms.
-mnofit.addVar(totpdf.nucscale, 1)
-mnofit.addVar(nucpdf.delta2, 1.5)
-
-# We fix Qdamp based on prior information about our beamline.
-mnofit.addVar(nucpdf.qdamp, 0.03, fixed=True)
-
-# add the mPDF variables
-mnofit.addVar(totpdf.parascale, 4)
-mnofit.addVar(totpdf.ordscale, 1.5)
-
-# Turn off printout of iteration number.
-mnofit.clearFitHooks()
-
-# Initial structural fit
-print "Refine PDF using scipy's least-squares optimizer:"
-print " variables:", mnofit.names
-print " initial values:", mnofit.values
-leastsq(mnofit.residual, mnofit.values)
-print " final values:", mnofit.values
-print
-# Obtain and display the fit results.
-mnoresults = FitResults(mnofit)
-print "FIT RESULTS\n"
-print mnoresults
-
-
-# Get the experimental data from the recipe
-r = mnofit.totpdf.profile.x
-gobs = mnofit.totpdf.profile.y
-
-# Get the calculated PDF and compute the difference between the calculated and
-# measured PDF
-gcalc = mnofit.totpdf.evaluate()
-gnuc = mnofit.totpdf.evaluateEquation('nucscale * nucpdf')
-gmag = mnofit.totpdf.evaluateEquation('mpdf')
-
-baseline = 1.1 * gobs.min()
-gdiff = gobs - gcalc
-baseline2 = 1.1 * (gdiff+baseline).min()
-magfit=mc.calc(both=True)[2]
-
-# Plot!
-ax=plt.figure().add_subplot(111)
-ax.plot(r, gobs, 'bo', label="G(r) data", markerfacecolor='none', markeredgecolor='b')
-ax.plot(r, gcalc, 'r-', lw=1.5, label="G(r) fit")
-ax.plot(r, gdiff + baseline,'g-')
-ax.plot(r, np.zeros_like(r) + baseline, 'k:')
-ax.set_xlabel(r"r ($\AA$)")
-ax.set_ylabel(r"G ($\AA^{-2}$)")
-ax.set_xlim(xmax=mc.rmax)
-plt.legend()
-
-plt.show()
diff --git a/cmi_scripts/mpdf/example_corefinement2.py b/cmi_scripts/mpdf/example_corefinement2.py
index a4c820b..64b6546 100644
--- a/cmi_scripts/mpdf/example_corefinement2.py
+++ b/cmi_scripts/mpdf/example_corefinement2.py
@@ -14,7 +14,10 @@
from scipy.optimize import leastsq
from diffpy.mpdf import *
-from diffpy.Structure.Parsers import getParser
+try:
+ from diffpy.structure.parsers import getParser
+except:
+ from diffpy.Structure.Parsers import getParser
from diffpy.srfit.pdf import PDFGenerator, PDFParser
from diffpy.srfit.fitbase import FitRecipe, FitResults
from diffpy.srfit.fitbase import Profile, FitContribution
@@ -65,9 +68,9 @@
# parameters according to the CIF-loaded space group.
from diffpy.srfit.structure import constrainAsSpaceGroup
sgpars = constrainAsSpaceGroup(nucpdf.phase, pcif.spacegroup.short_name)
-print "Space group parameters are:",
-print ', '.join([p.name for p in sgpars])
-print
+print("Space group parameters are:",)
+print(', '.join([p.name for p in sgpars]))
+print()
# We can now cycle through the parameters and activate them in the recipe as
# variables
@@ -89,16 +92,19 @@
mnofit.clearFitHooks()
# Initial structural fit
-print "Refine PDF using scipy's least-squares optimizer:"
-print " variables:", mnofit.names
-print " initial values:", mnofit.values
+print("Refine PDF using scipy's least-squares optimizer:")
+print(" variables:")
+print(mnofit.names)
+print(" initial values:")
+print(mnofit.values)
leastsq(mnofit.residual, mnofit.values)
-print " final values:", mnofit.values
-print
+print(" final values:")
+print(mnofit.values)
+print()
# Obtain and display the fit results.
mnoresults = FitResults(mnofit)
-print "FIT RESULTS\n"
-print mnoresults
+print("FIT RESULTS\n")
+print(mnoresults)
# Get the experimental data from the recipe
r = mnofit.totpdf.profile.x
@@ -147,7 +153,7 @@ def magresidual(p, yexp, mcalc):
p0=[5.0,3.0] # initial parameter values (paraScale, ordScale)
pOpt=leastsq(magresidual, p0, args=(gdiff, mc))
-print pOpt
+print(pOpt)
magfit = mc.calc(both=True)[2]
magdiff = gdiff - magfit
@@ -189,15 +195,19 @@ def mpdf(parascale, ordscale):
mnofit.addVar(totpdf.ordscale,value=mc.ordScale)
# do the co-refinement
-print "Refine PDF using scipy's least-squares optimizer:"
-print " variables:", mnofit.names
-print " initial values:", mnofit.values
+print("Refine PDF using scipy's least-squares optimizer:")
+print(" variables:")
+print(mnofit.names)
+print(" initial values:")
+print(mnofit.values)
leastsq(mnofit.residual, mnofit.values)
-print " final values:", mnofit.values
-print
-mnoresults=FitResults(mnofit)
-print "FIT RESULTS\n"
-print mnoresults
+print(" final values:")
+print(mnofit.values)
+print()
+# Obtain and display the fit results.
+mnoresults = FitResults(mnofit)
+print("FIT RESULTS\n")
+print(mnoresults)
# Get the calculated PDF and compute the difference between the calculated and
# measured PDF
diff --git a/cmi_scripts/mpdf/example_fromPDFgui.py b/cmi_scripts/mpdf/example_fromPDFgui.py
deleted file mode 100644
index 7573135..0000000
--- a/cmi_scripts/mpdf/example_fromPDFgui.py
+++ /dev/null
@@ -1,64 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-'''
-This example will show how to perform mPDF refinements after having done the atomic
-PDF refinement in PDFgui. We use data from MnO at 15 K.
-'''
-
-# Import necessary functions
-import numpy as np
-import matplotlib.pyplot as plt
-from scipy.optimize import leastsq
-
-from diffpy.mpdf import *
-from diffpy.Structure import loadStructure
-
-# Create the structure from our cif file, update the lattice params
-structureFile = "MnO_R-3m.cif"
-mnostructure = loadStructure(structureFile)
-lat = mnostructure.lattice
-lat.a,lat.b,lat.c = 3.1505626,3.1505626,7.5936979 ## refined values from PDFgui
-
-# Create the Mn2+ magnetic species
-mn2p = MagSpecies(struc=mnostructure, label='Mn2+', magIdxs=[0,1,2],
- basisvecs=2.5*np.array([1,0,0]), kvecs=np.array([0,0,1.5]),
- ffparamkey='Mn2')
-
-# Create and prep the magnetic structure
-mstr = MagStructure()
-mstr.loadSpecies(mn2p)
-mstr.makeAtoms()
-mstr.makeSpins()
-mstr.makeFF()
-
-# Set up the mPDF calculator
-mc = MPDFcalculator(magstruc=mstr, gaussPeakWidth=0.2)
-
-# Load the data
-PDFfitFile = 'MnOfit_PDFgui.fgr'
-rexp,Drexp = getDiffData([PDFfitFile]) # this reads in the fit file
-mc.rmin = rexp.min()
-mc.rmax = rexp.max()
-
-# Do the refinement
-def residual(p, yexp, mcalc):
- mcalc.paraScale, mcalc.ordScale = p
- return yexp-mcalc.calc(both=True)[2]
-
-p0 = [5.0,3.0] # initial parameter values (paraScale, ordScale)
-pOpt = leastsq(residual, p0, args=(Drexp,mc))
-print pOpt
-
-fit=mc.calc(both=True)[2]
-
-# Plot the results
-fig = plt.figure()
-ax = fig.add_subplot(111)
-ax.plot(rexp, Drexp, marker='o', mfc='none', mec='b', linestyle='none')
-ax.plot(rexp, fit, 'r-', lw=2)
-ax.set_xlim(xmin=mc.rmin, xmax=mc.rmax)
-ax.set_xlabel('r ($\AA$)')
-ax.set_ylabel('d(r) ($\AA^{-2}$)')
-
-plt.show()
diff --git a/cmi_scripts/mpdf/example_fromSrfit.py b/cmi_scripts/mpdf/example_fromSrfit.py
deleted file mode 100644
index 96cc7e2..0000000
--- a/cmi_scripts/mpdf/example_fromSrfit.py
+++ /dev/null
@@ -1,139 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-'''
-This example will show how to perform mPDF refinements after performing the atomic
-PDF refinement in SrFit. We use data from MnO at 15 K.
-'''
-
-# Import necessary functions
-import numpy as np
-import matplotlib.pyplot as plt
-from scipy.optimize import leastsq
-
-from diffpy.mpdf import *
-from diffpy.Structure import loadStructure
-from diffpy.srfit.pdf import PDFContribution
-from diffpy.srfit.fitbase import FitRecipe, FitResults
-
-
-# Files containing our experimental data and structure file
-dataFile = "npdf_07334.gr"
-structureFile = "MnO_R-3m.cif"
-spaceGroup = "H-3m"
-mnostructure = loadStructure(structureFile)
-
-# Create the Mn2+ magnetic species
-mn2p = MagSpecies(struc=mnostructure, label='Mn2+', magIdxs=[0,1,2],
- basisvecs=2.5*np.array([[1,0,0]]), kvecs=np.array([[0,0,1.5]]),
- ffparamkey='Mn2')
-
-# Create and prep the magnetic structure
-mstr = MagStructure()
-mstr.loadSpecies(mn2p)
-mstr.makeAll()
-
-# Set up the mPDF calculator
-mc = MPDFcalculator(magstruc=mstr, gaussPeakWidth=0.2)
-
-### DO THE STRUCTURAL FIT USING SRFIT
-
-# Construct the atomic PDF contribution
-MnOPDF = PDFContribution("MnO")
-
-# Load the data and set the r-range over which we'll fit
-MnOPDF.loadData(dataFile)
-MnOPDF.setCalculationRange(xmin=0.01, xmax=20, dx=0.01)
-
-# Add the structure from our cif file to the contribution
-MnOPDF.addStructure("MnO", mnostructure)
-
-# The FitRecipe does the work of calculating the PDF with the fit variable
-# that we give it.
-MnOFit = FitRecipe()
-
-# give the PDFContribution to the FitRecipe
-MnOFit.addContribution(MnOPDF)
-
-# Configure the fit variables and give them to the recipe. We can use the
-# srfit function constrainAsSpaceGroup to constrain the lattice and ADP
-# parameters according to the H-3m space group.
-from diffpy.srfit.structure import constrainAsSpaceGroup
-spaceGroupParams = constrainAsSpaceGroup(MnOPDF.MnO.phase, spaceGroup)
-print "Space group parameters are:",
-print ', '.join([p.name for p in spaceGroupParams])
-print
-
-# We can now cycle through the parameters and activate them in the recipe as
-# variables
-for par in spaceGroupParams.latpars:
- MnOFit.addVar(par)
-# Set initial value for the ADP parameters, because CIF had no ADP data.
-for par in spaceGroupParams.adppars:
- MnOFit.addVar(par, value=0.003,fixed=True)
-
-# As usual, we add variables for the overall scale of the PDF and a delta2
-# parameter for correlated motion of neighboring atoms.
-MnOFit.addVar(MnOPDF.scale, 1)
-MnOFit.addVar(MnOPDF.MnO.delta2, 1.5)
-
-# We fix Qdamp based on prior information about our beamline.
-MnOFit.addVar(MnOPDF.qdamp, 0.03, fixed=True)
-
-# Turn off printout of iteration number.
-MnOFit.clearFitHooks()
-
-# We can now execute the fit using scipy's least square optimizer.
-print "Refine PDF using scipy's least-squares optimizer:"
-print " variables:", MnOFit.names
-print " initial values:", MnOFit.values
-leastsq(MnOFit.residual, MnOFit.values)
-print " final values:", MnOFit.values
-print
-
-# Obtain and display the fit results.
-MnOResults = FitResults(MnOFit)
-print "FIT RESULTS\n"
-print MnOResults
-
-# Get the experimental data from the recipe
-r = MnOFit.MnO.profile.x
-gobs = MnOFit.MnO.profile.y
-
-# Get the calculated PDF and compute the difference between the calculated and
-# measured PDF
-gcalc = MnOFit.MnO.evaluate()
-baseline = 1.1 * gobs.min()
-gdiff = gobs - gcalc
-baseline2 = 1.2 * (gdiff+baseline).min()
-
-### NOW DO THE MPDF REFINEMENT USING THE RESIDUAL FROM THE ATOMIC PDF
-mc.rmin = r.min()
-mc.rmax = r.max()
-def residual(p, yexp, mcalc):
- mcalc.paraScale, mcalc.ordScale = p
- return yexp - mcalc.calc(both=True)[2]
-
-p0 = [5.0, 3.0] # initial parameter values (parScale, ordScale)
-pOpt = leastsq(residual, p0, args=(gdiff,mc))
-print pOpt
-
-fit=mc.calc(both=True)[2]
-
-# Plot!
-ax=plt.figure().add_subplot(111)
-ax.plot(r, gobs, 'bo', label="Total PDF",markerfacecolor='b', markeredgecolor='b')
-ax.plot(r, gdiff + baseline,mfc='Indigo',mec='Indigo',marker='o',linestyle='none',label='mPDF')
-ax.plot(r, gcalc, 'r-', lw=2.5, label="Fit")
-ax.plot(r, fit+baseline,'r-',lw=2.5)
-ax.plot(r, gdiff - fit + baseline2, 'g-', label='Residual')
-ax.plot(r, np.zeros_like(r) + baseline2, 'k:')
-ax.set_xlabel('r ($\AA$)', fontsize=16)
-ax.set_ylabel('G, d ($\AA^{-2}$)', fontsize=16)
-ax.set_xlim(xmin=0, xmax=20)
-#ax.set_yticks([])
-#ax.set_yticklabels([])
-plt.legend()
-
-plt.tight_layout()
-plt.show()
diff --git a/cmi_scripts/mpdf/example_refineSpinDir.ipynb b/cmi_scripts/mpdf/example_refineSpinDir.ipynb
deleted file mode 100644
index 29f711d..0000000
--- a/cmi_scripts/mpdf/example_refineSpinDir.ipynb
+++ /dev/null
@@ -1,1891 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Refining the spin direction"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "This notebook provides examples of two methods for refining the spin direction: \n",
- " 1. Updating the basis vector(s) and calling the makeSpins() function, which is a very general method and will work for magnetic structures of arbitrary complexity;\n",
- " 2. Storing the locations of the \"up\" spins and \"down\" spins and updating them without calling makeSpins(), which is faster but best suited only for simple collinear magnetic structures."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 1,
- "metadata": {
- "collapsed": false
- },
- "outputs": [
- {
- "name": "stderr",
- "output_type": "stream",
- "text": [
- "/home/ben/anaconda/envs/mpdfdev/lib/python2.7/site-packages/matplotlib/font_manager.py:273: UserWarning: Matplotlib is building the font cache using fc-list. This may take a moment.\n",
- " warnings.warn('Matplotlib is building the font cache using fc-list. This may take a moment.')\n"
- ]
- }
- ],
- "source": [
- "### Import everything we need\n",
- "import numpy as np\n",
- "import matplotlib.pyplot as plt\n",
- "from scipy.optimize import leastsq\n",
- "\n",
- "from diffpy.mpdf import *\n",
- "from diffpy.Structure import loadStructure\n",
- "\n",
- "import time # we will be doing some speed testing\n",
- "\n",
- "%matplotlib notebook"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "metadata": {
- "collapsed": false
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "lattice=Lattice(a=3.15056, b=3.15056, c=7.5937, alpha=90, beta=90, gamma=120)\n",
- "Mn 0.000000 0.000000 0.000000 1.0000\n",
- "Mn 0.333333 0.666667 0.666667 1.0000\n",
- "Mn 0.666667 0.333333 0.333333 1.0000\n",
- "O 0.000000 0.000000 0.500000 1.0000\n",
- "O 0.333333 0.666667 0.166667 1.0000\n",
- "O 0.666667 0.333333 0.833333 1.0000\n"
- ]
- }
- ],
- "source": [
- "### Create the structure from our cif file, update the lattice params\n",
- "structureFile = \"MnO_R-3m.cif\"\n",
- "mnostructure = loadStructure(structureFile)\n",
- "lat = mnostructure.lattice\n",
- "lat.a, lat.b, lat.c = 3.1505626, 3.1505626, 7.5936979 # refined values from PDFgui\n",
- "print mnostructure"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "metadata": {
- "collapsed": false
- },
- "outputs": [],
- "source": [
- "### Set up the magSpecies\n",
- "mn2p=MagSpecies(struc=mnostructure, label='Mn2+')\n",
- "mn2p.magIdxs = [0,1,2]\n",
- "mn2p.kvecs = np.array([0,0,1.5])\n",
- "mn2p.ffparamkey = 'Mn2'\n",
- "\n",
- "# start with a randomly oriented spin basis vector\n",
- "theta0 = np.arccos(np.random.uniform(-1,1))\n",
- "phi0 = np.random.uniform(-np.pi,np.pi)\n",
- "mn2p.basisvecs = 2.5*np.array([[np.sin(theta0)*np.cos(phi0),\n",
- " np.sin(theta0)*np.sin(phi0), np.cos(theta0)]])"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "metadata": {
- "collapsed": false
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Coordinates of atoms and spins for Mn2+\n",
- "have not been loaded because they have not yet been\n",
- "generated and/or do not match in shape.\n",
- "Running checks for Mn2+ MagSpecies object...\n",
- "\n",
- "kvecs and basisvecs must have the same dimensions.\n",
- "Running checks for MagStructure object...\n",
- "\n",
- "All MagStructure checks passed. No obvious problems found.\n",
- "Running checks for Mn2+ MagSpecies object...\n",
- "\n",
- "kvecs and basisvecs must have the same dimensions.\n",
- "Running checks for MagStructure object...\n",
- "\n",
- "All MagStructure checks passed. No obvious problems found.\n"
- ]
- },
- {
- "name": "stderr",
- "output_type": "stream",
- "text": [
- "/home/ben/anaconda/envs/mpdfdev/lib/python2.7/site-packages/diffpy.Structure-1.3.2-py2.7.egg/diffpy/Structure/lattice.py:125: FutureWarning: comparison to `None` will result in an elementwise object comparison in the future.\n",
- " if [a, b, c, alpha, beta, gamma, base] == 7*[None]:\n"
- ]
- }
- ],
- "source": [
- "### Create and prep the magStructure\n",
- "mstr = MagStructure()\n",
- "mstr.loadSpecies(mn2p)\n",
- "mstr.makeAll()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 5,
- "metadata": {
- "collapsed": false
- },
- "outputs": [],
- "source": [
- "### Set up the mPDF calculator\n",
- "mc = MPDFcalculator(magstruc=mstr)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 6,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "### Load the data\n",
- "PDFfitFile = 'MnOfit_PDFgui.fgr'\n",
- "rexp,Drexp = getDiffData([PDFfitFile])\n",
- "mc.rmin = rexp.min()\n",
- "mc.rmax = rexp.max()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Method 1: Update the basis vector directly and call makeSpins() (slower)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 7,
- "metadata": {
- "collapsed": false
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Refined parameters: [ 3.75623138e+00 1.14768778e+00 1.57078652e+00 -8.42358774e+03]\n",
- "Duration of refinement: 2.83608698845\n",
- "Refined spin: [ -1.39704933e+00 2.07322290e+00 2.45182236e-05]\n"
- ]
- },
- {
- "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 = $('');\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",
- " '');\n",
- " var titletext = $(\n",
- " '');\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 = $('');\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 = $('');\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 = $('');\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 = $('')\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 = $('');\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 = $('');\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 = $('');\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 = $('');\n",
- "\n",
- " var fmt_picker = $('');\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",
- " '', {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 = $('');\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(\"\");\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('
');\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'] = '
';\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 = $('')\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 = $('');\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 = $('');\n",
- " nav_element.append(status_bar);\n",
- " this.message = status_bar[0];\n",
- "\n",
- " // Add the close button to the window.\n",
- " var buttongrp = $('');\n",
- " var 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= 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": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/html": [
- "
"
- ],
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
- "source": [
- "# Do the refinement\n",
- "def residual1(p,yexp):\n",
- " mc.paraScale, mc.ordScale, theta, phi = p\n",
- " mn2p.basisvecs = 2.5*np.array([np.sin(theta)*np.cos(phi),\n",
- " np.sin(theta)*np.sin(phi), np.cos(theta)])\n",
- " mstr.makeSpins()\n",
- " return yexp - mc.calc(both=True)[2]\n",
- "\n",
- "p0 = [5.0, 3.0, theta0, phi0] # initial parameter values\n",
- "\n",
- "start = time.time()\n",
- "pOpt = leastsq(residual1, p0, args=(Drexp))\n",
- "end = time.time()\n",
- "\n",
- "print 'Refined parameters: ', pOpt[0]\n",
- "print 'Duration of refinement: ', end-start\n",
- "thetaF, phiF = pOpt[0][2], pOpt[0][3]\n",
- "Sfinal = 2.5*np.array([np.sin(thetaF)*np.cos(phiF),\n",
- " np.sin(thetaF)*np.sin(phiF),np.cos(thetaF)])\n",
- "print 'Refined spin: ', Sfinal\n",
- "\n",
- "fit=mc.calc(both=True)[2]\n",
- "\n",
- "# Plot the results\n",
- "fig=plt.figure()\n",
- "ax=fig.add_subplot(111)\n",
- "ax.plot(rexp,Drexp,marker='o',mfc='none',mec='b',linestyle='none')\n",
- "ax.plot(rexp,fit,'r-',lw=2)\n",
- "ax.set_xlim(xmin=mc.rmin,xmax=mc.rmax)\n",
- "ax.set_xlabel('r ($\\AA$)')\n",
- "ax.set_ylabel('d(r) ($\\AA^{-2}$)')\n",
- "\n",
- "plt.show()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Method 2: Store the indices of the up and down spins and use these to update (faster)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 8,
- "metadata": {
- "collapsed": false
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Refined parameters: [ 3.75623138e+00 1.14768778e+00 1.57078652e+00 -8.42358774e+03]\n",
- "Duration of refinement: 2.67924809456\n",
- "Refined spin: [ -1.39704933e+00 2.07322290e+00 2.45182236e-05]\n"
- ]
- },
- {
- "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 = $('');\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",
- " '');\n",
- " var titletext = $(\n",
- " '');\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 = $('');\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 = $('');\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 = $('');\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 = $('')\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 = $('');\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 = $('');\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 = $('');\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 = $('');\n",
- "\n",
- " var fmt_picker = $('');\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",
- " '', {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 = $('');\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(\"\");\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('
');\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'] = '
';\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 = $('')\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 = $('');\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 = $('');\n",
- " nav_element.append(status_bar);\n",
- " this.message = status_bar[0];\n",
- "\n",
- " // Add the close button to the window.\n",
- " var buttongrp = $('');\n",
- " var 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= 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": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/html": [
- "
"
- ],
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
- "source": [
- "### Reset the magnetic structure to how it was originally\n",
- "mn2p.basisvecs = 2.5*np.array([np.sin(theta0)*np.cos(phi0),\n",
- " np.sin(theta0)*np.sin(phi0), np.cos(theta0)])\n",
- "mstr.makeSpins()\n",
- "\n",
- "### Find the locations of the up and down spins (we are creating boolean masks)\n",
- "upSpins = np.all(mstr.spins==mn2p.basisvecs, axis=1)\n",
- "downSpins = np.all(mstr.spins==-1.0*mn2p.basisvecs, axis=1)\n",
- "# Warning! If you define your basisvecs as a nested array, i.e. np.array([[x,y,z]]),\n",
- "# you will want to use basisvecs[0] instead of basisvecs in the two preceding lines.\n",
- "\n",
- "### Modify the residual function\n",
- "def residual2(p,yexp):\n",
- " mc.paraScale, mc.ordScale, theta, phi = p\n",
- " Svec = 2.5*np.array([np.sin(theta)*np.cos(phi),\n",
- " np.sin(theta)*np.sin(phi), np.cos(theta)])\n",
- " mstr.spins[upSpins] = Svec\n",
- " mstr.spins[downSpins] = -Svec\n",
- " return yexp - mc.calc(both=True)[2]\n",
- "\n",
- "p0=[5.0, 3.0, theta0, phi0] # initial parameter values\n",
- "\n",
- "start = time.time()\n",
- "pOpt = leastsq(residual2, p0, args=(Drexp))\n",
- "end=time.time()\n",
- "\n",
- "print 'Refined parameters: ', pOpt[0]\n",
- "print 'Duration of refinement: ', end-start\n",
- "thetaF, phiF = pOpt[0][2], pOpt[0][3]\n",
- "Sfinal = 2.5*np.array([np.sin(thetaF)*np.cos(phiF),\n",
- " np.sin(thetaF)*np.sin(phiF), np.cos(thetaF)])\n",
- "print 'Refined spin: ', Sfinal\n",
- "\n",
- "### Update the magnetic structure with the refined spin\n",
- "#mn2p.basisvecs = np.array([Sfinal])\n",
- "#mstr.makeSpins()\n",
- "fit = mc.calc(both=True)[2]\n",
- "\n",
- "### Plot the results\n",
- "fig = plt.figure()\n",
- "ax = fig.add_subplot(111)\n",
- "ax.plot(rexp, Drexp, marker='o', mfc='none', mec='b', linestyle='none')\n",
- "ax.plot(rexp, fit, 'r-', lw=2)\n",
- "ax.set_xlim(xmin=mc.rmin, xmax=mc.rmax)\n",
- "ax.set_xlabel('r ($\\AA$)')\n",
- "ax.set_ylabel('d(r) ($\\AA^{-2}$)')\n",
- "\n",
- "plt.show()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 9,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "plt.close('all')"
- ]
- }
- ],
- "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.11"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 0
-}
diff --git a/cmi_scripts/mpdf/example_refineSpinDirection.ipynb b/cmi_scripts/mpdf/example_refineSpinDirection.ipynb
new file mode 100644
index 0000000..390ba43
--- /dev/null
+++ b/cmi_scripts/mpdf/example_refineSpinDirection.ipynb
@@ -0,0 +1,270 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Refining the spin direction"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "This notebook provides examples of two methods for refining the spin direction: \n",
+ " 1. Updating the basis vector(s) and calling the makeSpins() function, which is a very general method and will work for magnetic structures of arbitrary complexity;\n",
+ " 2. Storing the locations of the \"up\" spins and \"down\" spins and updating them without calling makeSpins(), which is faster and well suited for simple collinear magnetic structures."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "### Import the necessary libraries\n",
+ "import numpy as np\n",
+ "import matplotlib.pyplot as plt\n",
+ "from diffpy.mpdf import *\n",
+ "from diffpy.Structure import loadStructure\n",
+ "from scipy.optimize import least_squares\n",
+ "\n",
+ "### Set all plots to be inline\n",
+ "%matplotlib notebook"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [],
+ "source": [
+ "### Make the magnetic structure\n",
+ "PDFguiFile = 'MnOpdfgui.ddp'\n",
+ "struc = getStrucFromPDFgui(PDFguiFile,0)\n",
+ "\n",
+ "th0, phi0 = np.arccos(np.random.uniform(-1,1)),np.random.uniform(-np.pi,np.pi)\n",
+ "svec = np.array([np.sin(th0)*np.cos(phi0),np.sin(th0)*np.sin(phi0),np.cos(th0)])\n",
+ "msp = MagSpecies(struc,magIdxs=[0,1,2,3],ffparamkey='Mn2',rmaxAtoms=50,basisvecs=svec,\n",
+ " kvecs=np.array([0.5,0.5,0.5]),label=str(0))\n",
+ "\n",
+ "mstr=MagStructure()\n",
+ "mstr.loadSpecies(msp)\n",
+ "mstr.makeAll()\n",
+ "\n",
+ "\n",
+ "### Get the data and make the calculator\n",
+ "r,d = getDiffData(PDFguiFile)\n",
+ "\n",
+ "mc = MPDFcalculator(mstr)\n",
+ "mc.rmin = r.min()\n",
+ "mc.rmax = r.max()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Define a residual function that allows moment directions to vary"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [],
+ "source": [
+ "def residual(p,ydata):\n",
+ " oscale,pscale,damp,th,phi = p\n",
+ " newsvec = np.array([np.sin(th)*np.cos(phi),np.sin(th)*np.sin(phi),np.cos(th)])\n",
+ " mstr.species['0'].basisvecs = newsvec\n",
+ " mstr.makeSpins()\n",
+ " mc.ordScale = oscale\n",
+ " mc.paraScale = pscale\n",
+ " mc.dampRate = damp\n",
+ " return ydata - mc.calc(both=True)[2]\n",
+ "\n",
+ "p0 = [0.1,0.1,0.1,np.arccos(np.random.uniform(-1,1)),np.random.uniform(-np.pi,np.pi)]\n",
+ "optimized = least_squares(residual,p0,bounds=[[0,0,0,0,-np.pi],[10,10,10,np.pi,np.pi]],\n",
+ " args=(d,))\n",
+ "fit = mc.calc(both=True)[2]\n",
+ "\n",
+ "fig=plt.figure()\n",
+ "ax=fig.add_subplot(111)\n",
+ "ax.plot(r,d,'bo',linestyle='none')\n",
+ "ax.plot(r,fit,'r-',lw=2)\n",
+ "ax.set_xlabel('r ($\\AA$)')\n",
+ "ax.set_ylabel('D($\\AA^{-2}$)')\n",
+ "\n",
+ "plt.show() "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Visualize the refined magnetic structure"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [],
+ "source": [
+ "### Visualize the magnetic structure\n",
+ "uc = struc[:4].xyz\n",
+ "visatoms = uc.copy()\n",
+ "visatoms = np.concatenate((visatoms,visatoms+np.array([0,0,1]),visatoms+np.array([0,1,0]),visatoms+np.array([0,0,1])))\n",
+ "visatoms = struc.lattice.cartesian(visatoms)\n",
+ "visspins = mstr.spinsFromAtoms(visatoms,fractional=False)\n",
+ "mstr.visualize(visatoms,visspins)\n",
+ "\n",
+ "print mstr.spins[0], (mstr.spins[0]).sum()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "The refined spin direction is nearly perfectly perpendicular to the (111) direction, as expected."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Faster method: Use masking to avoid having to regenerate spins each iteration"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [],
+ "source": [
+ "### Make the magnetic structure\n",
+ "PDFguiFile = 'MnOpdfgui.ddp'\n",
+ "struc = getStrucFromPDFgui(PDFguiFile,0)\n",
+ "\n",
+ "th0, phi0 = np.arccos(np.random.uniform(-1,1)),np.random.uniform(-np.pi,np.pi)\n",
+ "svec = np.array([np.sin(th0)*np.cos(phi0),np.sin(th0)*np.sin(phi0),np.cos(th0)])\n",
+ "msp = MagSpecies(struc,magIdxs=[0,1,2,3],ffparamkey='Mn2',rmaxAtoms=50,basisvecs=svec,\n",
+ " kvecs=np.array([0.5,0.5,0.5]),label=str(0))\n",
+ "\n",
+ "mstr=MagStructure()\n",
+ "mstr.loadSpecies(msp)\n",
+ "mstr.makeAll()\n",
+ "\n",
+ "\n",
+ "### Get the data and make the calculator\n",
+ "r,d = getDiffData(PDFguiFile)\n",
+ "\n",
+ "mc = MPDFcalculator(mstr)\n",
+ "mc.rmin = r.min()\n",
+ "mc.rmax = r.max()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [],
+ "source": [
+ "### Make the masks\n",
+ "upMask = (np.apply_along_axis(np.linalg.norm,1,mstr.spins-svec)<0.1)\n",
+ "downMask = ~upMask\n",
+ "print mstr.spins[upMask][:4]\n",
+ "print mstr.spins[downMask][:4]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [],
+ "source": [
+ "def residual(p,ydata):\n",
+ " oscale,pscale,damp,th,phi = p\n",
+ " newsvec = np.array([np.sin(th)*np.cos(phi),np.sin(th)*np.sin(phi),np.cos(th)])\n",
+ " mstr.spins[upMask]=newsvec\n",
+ " mstr.spins[downMask]=-newsvec\n",
+ " mc.ordScale = oscale\n",
+ " mc.paraScale = pscale\n",
+ " mc.dampRate = damp\n",
+ " return ydata - mc.calc(both=True)[2]\n",
+ "\n",
+ "p0 = [0.1,0.1,0.1,np.arccos(np.random.uniform(-1,1)),np.random.uniform(-np.pi,np.pi)]\n",
+ "optimized = least_squares(residual,p0,bounds=[[0,0,0,0,-np.pi],[10,10,10,np.pi,np.pi]],\n",
+ " args=(d,))\n",
+ "fit = mc.calc(both=True)[2]\n",
+ "\n",
+ "fig=plt.figure()\n",
+ "ax=fig.add_subplot(111)\n",
+ "ax.plot(r,d,'bo',linestyle='none')\n",
+ "ax.plot(r,fit,'r-',lw=2)\n",
+ "ax.set_xlabel('r ($\\AA$)')\n",
+ "ax.set_ylabel('D($\\AA^{-2}$)')\n",
+ "\n",
+ "plt.show() \n",
+ "\n",
+ "print mstr.spins[0],(mstr.spins[0]).sum()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "plt.close('all')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 2",
+ "language": "python",
+ "name": "python2"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 2
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython2",
+ "version": "2.7.11"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 0
+}
diff --git a/cmi_scripts/mpdf/introTutorial.ipynb b/cmi_scripts/mpdf/introTutorial.ipynb
index e04dd4d..403f4d7 100644
--- a/cmi_scripts/mpdf/introTutorial.ipynb
+++ b/cmi_scripts/mpdf/introTutorial.ipynb
@@ -95,7 +95,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "# Simple example: Calculating the mPDF from a spin dimer"
+ "## Simple example: Calculating the mPDF from a pair of spins"
]
},
{
@@ -108,24 +108,38 @@
{
"cell_type": "code",
"execution_count": 1,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "### Import the necessary libraries\n",
+ "import numpy as np\n",
+ "import matplotlib.pyplot as plt\n",
+ "from diffpy.mpdf import *\n",
+ "try:\n",
+ " from diffpy.structure import loadStructure\n",
+ "except:\n",
+ " from diffpy.Structure import loadStructure\n",
+ "\n",
+ "### Set all plots to be inline\n",
+ "%matplotlib notebook"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [
- {
- "name": "stderr",
- "output_type": "stream",
- "text": [
- "/home/ben/anaconda/envs/mpdfdev/lib/python2.7/site-packages/matplotlib/font_manager.py:273: UserWarning: Matplotlib is building the font cache using fc-list. This may take a moment.\n",
- " warnings.warn('Matplotlib is building the font cache using fc-list. This may take a moment.')\n"
- ]
- },
{
"data": {
"application/javascript": [
"/* Put everything inside the global mpl namespace */\n",
"window.mpl = {};\n",
"\n",
+ "\n",
"mpl.get_websocket_type = function() {\n",
" if (typeof(WebSocket) !== 'undefined') {\n",
" return WebSocket;\n",
@@ -184,6 +198,9 @@
" this.ws.onopen = function () {\n",
" fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n",
" fig.send_message(\"send_image_mode\", {});\n",
+ " if (mpl.ratio != 1) {\n",
+ " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n",
+ " }\n",
" fig.send_message(\"refresh\", {});\n",
" }\n",
"\n",
@@ -253,6 +270,15 @@
" this.canvas = canvas[0];\n",
" this.context = canvas[0].getContext(\"2d\");\n",
"\n",
+ " var backingStore = this.context.backingStorePixelRatio ||\n",
+ "\tthis.context.webkitBackingStorePixelRatio ||\n",
+ "\tthis.context.mozBackingStorePixelRatio ||\n",
+ "\tthis.context.msBackingStorePixelRatio ||\n",
+ "\tthis.context.oBackingStorePixelRatio ||\n",
+ "\tthis.context.backingStorePixelRatio || 1;\n",
+ "\n",
+ " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n",
+ "\n",
" var rubberband = $('');\n",
" rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n",
"\n",
@@ -309,8 +335,9 @@
" canvas_div.css('width', width)\n",
" canvas_div.css('height', height)\n",
"\n",
- " canvas.attr('width', width);\n",
- " canvas.attr('height', height);\n",
+ " canvas.attr('width', width * mpl.ratio);\n",
+ " canvas.attr('height', height * mpl.ratio);\n",
+ " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n",
"\n",
" rubberband.attr('width', width);\n",
" rubberband.attr('height', height);\n",
@@ -443,10 +470,10 @@
"}\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",
+ " var x0 = msg['x0'] / mpl.ratio;\n",
+ " var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n",
+ " var x1 = msg['x1'] / mpl.ratio;\n",
+ " var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n",
" x0 = Math.floor(x0) + 0.5;\n",
" y0 = Math.floor(y0) + 0.5;\n",
" x1 = Math.floor(x1) + 0.5;\n",
@@ -602,8 +629,8 @@
" this.canvas_div.focus();\n",
" }\n",
"\n",
- " var x = canvas_pos.x;\n",
- " var y = canvas_pos.y;\n",
+ " var x = canvas_pos.x * mpl.ratio;\n",
+ " var y = canvas_pos.y * mpl.ratio;\n",
"\n",
" this.send_message(name, {x: x, y: y, button: event.button,\n",
" step: event.step,\n",
@@ -724,6 +751,7 @@
"};\n",
"\n",
"mpl.figure.prototype.handle_close = function(fig, msg) {\n",
+ " var width = fig.canvas.width/mpl.ratio\n",
" fig.root.unbind('remove')\n",
"\n",
" // Update the output cell to use the data from the current canvas.\n",
@@ -732,7 +760,7 @@
" // 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('
');\n",
+ " $(fig.parent_element).html('
');\n",
" fig.close_ws(fig, msg);\n",
"}\n",
"\n",
@@ -743,8 +771,9 @@
"\n",
"mpl.figure.prototype.push_to_output = function(remove_interactive) {\n",
" // Turn the data on the canvas into data in the output cell.\n",
+ " var width = this.canvas.width/mpl.ratio\n",
" var dataURL = this.canvas.toDataURL();\n",
- " this.cell_info[1]['text/html'] = '
';\n",
+ " this.cell_info[1]['text/html'] = '
';\n",
"}\n",
"\n",
"mpl.figure.prototype.updated_canvas_event = function() {\n",
@@ -833,12 +862,9 @@
" // 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",
+ " // select the cell after this one\n",
+ " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n",
+ " IPython.notebook.select(index + 1);\n",
" }\n",
"}\n",
"\n",
@@ -887,7 +913,7 @@
{
"data": {
"text/html": [
- "
"
+ "
"
],
"text/plain": [
""
@@ -898,26 +924,18 @@
}
],
"source": [
- "### Import the necessary libraries\n",
- "import numpy as np\n",
- "import matplotlib.pyplot as plt\n",
- "from diffpy.mpdf import *\n",
- "\n",
- "### Set all plots to be inline\n",
- "%matplotlib notebook\n",
- "\n",
"### Create a MagStructure object\n",
- "mstr = MagStructure()\n",
+ "mstruc = MagStructure()\n",
"\n",
"### Create two atoms in the structure\n",
- "mstr.atoms = np.array([[0,0,0],[4,0,0]])\n",
+ "mstruc.atoms = np.array([[0,0,0],[4,0,0]])\n",
"\n",
"### Create two spin vectors corresponding to the atoms. Let's make them antiferromagnetic.\n",
"S=np.array([0,0,1])\n",
- "mstr.spins = np.array([S,-S])\n",
+ "mstruc.spins = np.array([S,-S])\n",
"\n",
"### Create the MPDFcalculator object and load the magnetic structure into it\n",
- "mc = MPDFcalculator(mstr)\n",
+ "mc = MPDFcalculator(mstruc)\n",
"\n",
"### Calculate and plot the mPDF!\n",
"r,fr = mc.calc() # Use calc() if you want to extract the numerical results of the calculation\n",
@@ -935,8392 +953,821 @@
},
{
"cell_type": "code",
- "execution_count": 2,
+ "execution_count": 3,
"metadata": {
"collapsed": false
},
"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 = $('');\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",
- " '');\n",
- " var titletext = $(\n",
- " '');\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 = $('');\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 = $('');\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 = $('');\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 = $('')\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 = $('');\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 = $('');\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 = $('');\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 = $('');\n",
- "\n",
- " var fmt_picker = $('');\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",
- " '', {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 = $('');\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(\"\");\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('
');\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'] = '
';\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 = $('')\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 = $('');\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 = $('');\n",
- " nav_element.append(status_bar);\n",
- " this.message = status_bar[0];\n",
- "\n",
- " // Add the close button to the window.\n",
- " var buttongrp = $('');\n",
- " var 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= 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": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/html": [
- "
"
- ],
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
- "source": [
- "### make a copy of the magnetic structure\n",
- "mstr2 = mstr.copy()\n",
- "\n",
- "### Set the spins to be ferromagnetic\n",
- "mstr2.spins = np.array([S,S])\n",
- "\n",
- "### Create another mPDF calculator\n",
- "mc2 = MPDFcalculator(mstr2)\n",
- "\n",
- "### Calculate the mPDF\n",
- "r2, fr2 = mc2.calc()\n",
- "\n",
- "### Compare the antiferromagnetic and ferromagnetic mPDFs\n",
- "fig = plt.figure()\n",
- "ax = fig.add_subplot(111)\n",
- "\n",
- "ax.plot(r,fr,'b-',label='Antiferro')\n",
- "ax.plot(r2,fr2,'r-',label='Ferro')\n",
- "\n",
- "ax.set_xlabel(r'r ($\\AA$)')\n",
- "ax.set_ylabel(r'f ($\\AA^{-2}$)')\n",
- "\n",
- "plt.legend()\n",
- "\n",
- "plt.show()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Creating a magnetic structure from a CIF file using diffpy.Structure"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "This example will show how to use the MagSpecies class and additional features in the MagStructure class to quickly generate the atomic positions and spin vectors from a diffpy.Structure object. It will also show how to calculate the unnormalized mPDF, which is useful for comparison to and refinement against neutron total scattering data."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Load the atomic structure from the CIF file"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "metadata": {
- "collapsed": false
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "[Mn2+ 0.000000 0.000000 0.000000 1.0000,\n",
- " Mn2+ 0.000000 0.500000 0.500000 1.0000,\n",
- " Mn2+ 0.500000 0.000000 0.500000 1.0000,\n",
- " Mn2+ 0.500000 0.500000 0.000000 1.0000,\n",
- " O2- 0.500000 0.500000 0.500000 1.0000,\n",
- " O2- 0.500000 0.000000 0.000000 1.0000,\n",
- " O2- 0.000000 0.500000 0.000000 1.0000,\n",
- " O2- 0.000000 0.000000 0.500000 1.0000]"
- ]
- },
- "execution_count": 3,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "### First we have to import the loadStructure function from diffpy.Structure\n",
- "from diffpy.Structure import loadStructure\n",
- "\n",
- "### Now let's create a diffpy.Structure object from a CIF file for MnO. This has all the atomic information,\n",
- "### but none of the magnetic information.\n",
- "mno = loadStructure('MnO_cubic.cif')\n",
- "\n",
- "### As a refresher, let's take a look at the mno structure object.\n",
- "mno"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Create the MagSpecies object"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "### We will now create a MagSpecies object to extend the mno structure object.\n",
- "mnoMag = MagSpecies()\n",
- "\n",
- "### Load the mno structure and give the magnetic species a label\n",
- "mnoMag.struc = mno\n",
- "mnoMag.label = 'Mn2+'\n",
- "\n",
- "### Now we need to tell it which atoms in MnO are magnetic. From the printed list in the previous cell,\n",
- "### the magnetic Mn ions are the first four positions in the structure, so we provide the corresponding indices.\n",
- "mnoMag.magIdxs = [0,1,2,3]\n",
- "\n",
- "### Now we provide the magnetic propagation and basis vectors, which are known from previous neutron\n",
- "### diffraction studies of MnO.\n",
- "k = np.array([0.5,0.5,0.5])\n",
- "s = np.array([1,-1,0]) # we won't worry about the magnitude of the basis vector for now\n",
- "mnoMag.kvecs = np.array([k])\n",
- "mnoMag.basisvecs = np.array([s])\n",
- "\n",
- "### Now we provide information about the magnetic form factor. We tell the MagSpecies object the type of magnetic\n",
- "### ion, and it looks up magnetic form factor in a table.\n",
- "mnoMag.ffparamkey = 'Mn2'"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Create the MagStructure object"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 5,
- "metadata": {
- "collapsed": false
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Coordinates of atoms and spins for Mn2+\n",
- "have not been loaded because they have not yet been\n",
- "generated and/or do not match in shape.\n",
- "Running checks for Mn2+ MagSpecies object...\n",
- "\n",
- "All MagSpecies() checks passed. No obvious problems found.\n",
- "\n",
- "Running checks for MagStructure object...\n",
- "\n",
- "All MagStructure checks passed. No obvious problems found.\n"
- ]
- },
- {
- "name": "stderr",
- "output_type": "stream",
- "text": [
- "/home/ben/anaconda/envs/mpdfdev/lib/python2.7/site-packages/diffpy.Structure-1.3.2-py2.7.egg/diffpy/Structure/lattice.py:125: FutureWarning: comparison to `None` will result in an elementwise object comparison in the future.\n",
- " if [a, b, c, alpha, beta, gamma, base] == 7*[None]:\n"
- ]
- }
- ],
- "source": [
- "### Now we can create a MagStructure object and load mnoMag into it.\n",
- "mnoMagStruc = MagStructure()\n",
- "mnoMagStruc.loadSpecies(mnoMag)\n",
- "\n",
- "### Now we will generate the atomic positions and spins. It is important to do the atoms first, since the\n",
- "### spins are generated by applying the propagation and basis vectors to the atomic positions. These methods\n",
- "### use the information contained in the atomic and magnetic structures to generate arrays of atomic positions\n",
- "### and spin vectors.\n",
- "mnoMagStruc.makeAtoms()\n",
- "mnoMagStruc.makeSpins()\n",
- "\n",
- "### And we make the magnetic form factor:\n",
- "mnoMagStruc.makeFF()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 6,
- "metadata": {
- "collapsed": false
- },
- "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 = $('');\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",
- " '');\n",
- " var titletext = $(\n",
- " '');\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 = $('');\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 = $('');\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 = $('');\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 = $('')\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 = $('');\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 = $('');\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 = $('');\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 = $('');\n",
- "\n",
- " var fmt_picker = $('');\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",
- " '', {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 = $('');\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(\"\");\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('
');\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'] = '
';\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 = $('')\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 = $('');\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 = $('');\n",
- " nav_element.append(status_bar);\n",
- " this.message = status_bar[0];\n",
- "\n",
- " // Add the close button to the window.\n",
- " var buttongrp = $('');\n",
- " var 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= 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": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/html": [
- "
"
- ],
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
- "source": [
- "### Now we can create the mPDF calculator and load the magnetic structure\n",
- "mc = MPDFcalculator()\n",
- "mc.magstruc = mnoMagStruc\n",
- "\n",
- "### Plot the mPDf\n",
- "mc.plot()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Creating a magnetic structure by defining your own unit cell"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "This example will show you how to create a magnetic structure from a unit cell that you define yourself. You will have to provide the lattice vectors, the positions of the magnetic atoms in the unit cell, and the magnetic moments corresponding to those atoms."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 7,
- "metadata": {
- "collapsed": false
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Coordinates of atoms and spins for \n",
- "have not been loaded because they have not yet been\n",
- "generated and/or do not match in shape.\n",
- "Running checks for MagSpecies object...\n",
- "\n",
- "All MagSpecies() checks passed. No obvious problems found.\n",
- "\n",
- "Running checks for MagStructure object...\n",
- "\n",
- "All MagStructure checks passed. No obvious problems found.\n",
- "Since you are not using a diffpy Structure object,\n",
- "the spins are generated from the makeAtoms() method.\n",
- "Please call that method if you have not already.\n"
- ]
- },
- {
- "name": "stderr",
- "output_type": "stream",
- "text": [
- "/home/ben/diffpy.mpdf/diffpy/mpdf/magstructure.py:158: VisibleDeprecationWarning: using a non-integer number instead of an integer will result in an error in the future\n",
- " ocoords = np.mgrid[-dim1:dim1+1, -dim2:dim2+1, -dim3:dim3+1].transpose().ravel().reshape((2*dim1+1)*(2*dim2+1)*(2*dim3+1), 3)\n"
- ]
- },
- {
- "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 = $('');\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",
- " '');\n",
- " var titletext = $(\n",
- " '');\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 = $('');\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 = $('');\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 = $('');\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 = $('')\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 = $('');\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 = $('');\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 = $('');\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 = $('');\n",
- "\n",
- " var fmt_picker = $('');\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",
- " '', {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 = $('');\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(\"\");\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('
');\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'] = '
';\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 = $('')\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 = $('');\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 = $('');\n",
- " nav_element.append(status_bar);\n",
- " this.message = status_bar[0];\n",
- "\n",
- " // Add the close button to the window.\n",
- " var buttongrp = $('');\n",
- " var 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= 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": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/html": [
- "
"
- ],
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
- "source": [
- "### Create the magnetic species and turn off the diffpy.structure option.\n",
- "mspec = MagSpecies(useDiffpyStruc=False)\n",
- "\n",
- "### Define the lattice vectors of the unit cell. Let's make a cubic unit cell.\n",
- "a = 4.0\n",
- "mspec.latVecs = np.array([[a,0,0], [0,a,0], [0,0,a]])\n",
- "\n",
- "### Define the positions of the magnetic atoms in the unit cell (in fractional coordinates). Let's make\n",
- "### a body-centered structure.\n",
- "mspec.atomBasis = np.array([[0,0,0], [0.5,0.5,0.5]])\n",
- "\n",
- "### Define the magnetic moments in the same order as the list of atoms. Let's make an antiferromagnet.\n",
- "mspec.spinBasis = np.array([[0,0,1], [0,0,-1]])\n",
- "\n",
- "\n",
- "### Create the magnetic structure object and load mspec.\n",
- "mstruc = MagStructure()\n",
- "mstruc.loadSpecies(mspec)\n",
- "mstruc.makeAtoms()\n",
- "mstruc.makeSpins()\n",
- "\n",
- "### Let's visualize the first unit cell to make sure we have what we expect.\n",
- "visAtoms = np.array([[0,0,0],[a,0,0],[0,a,0],[0,0,a],[a,a,0],\n",
- " [a,0,a],[0,a,a],[a,a,a],[0.5*a,0.5*a,0.5*a]])\n",
- "visSpins = mstruc.spinsFromAtoms(visAtoms, fractional=False)\n",
- "mstruc.visualize(visAtoms, visSpins)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 8,
- "metadata": {
- "collapsed": false
- },
- "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 = $('');\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",
- " '');\n",
- " var titletext = $(\n",
- " '');\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 = $('');\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 = $('');\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 = $('');\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 = $('')\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 = $('');\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 = $('');\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 = $('');\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 = $('');\n",
- "\n",
- " var fmt_picker = $('');\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",
- " '', {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 = $('');\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(\"\");\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('
');\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'] = '
';\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 = $('')\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 = $('');\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 = $('');\n",
- " nav_element.append(status_bar);\n",
- " this.message = status_bar[0];\n",
- "\n",
- " // Add the close button to the window.\n",
- " var buttongrp = $('');\n",
- " var 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= 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": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/html": [
- "
"
- ],
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
- "source": [
- "### Now we can set up the MPDFcalculator and plot the mPDF.\n",
- "mc = MPDFcalculator(mstruc)\n",
- "mc.plot()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Creating a magnetic structure with multiple species: Simple ferrimagnet"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "We will create a ferrimagnetic structure to illustrate the use of multiple magnetic species within a single magnetic structure. Let's build another antiferromagnetic body-centered cubic structure but with two different spin species, one with a large moment and one with a small moment."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 9,
- "metadata": {
- "collapsed": false
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Coordinates of atoms and spins for big\n",
- "have not been loaded because they have not yet been\n",
- "generated and/or do not match in shape.\n",
- "Running checks for big MagSpecies object...\n",
- "\n",
- "All MagSpecies() checks passed. No obvious problems found.\n",
- "\n",
- "Running checks for MagStructure object...\n",
- "\n",
- "All MagStructure checks passed. No obvious problems found.\n",
- "Coordinates of atoms and spins for small\n",
- "have not been loaded because they have not yet been\n",
- "generated and/or do not match in shape.\n",
- "Coordinates of atoms and spins for big\n",
- "have not been loaded because they have not yet been\n",
- "generated and/or do not match in shape.\n",
- "Running checks for small MagSpecies object...\n",
- "\n",
- "All MagSpecies() checks passed. No obvious problems found.\n",
- "\n",
- "Running checks for big MagSpecies object...\n",
- "\n",
- "All MagSpecies() checks passed. No obvious problems found.\n",
- "\n",
- "Running checks for MagStructure object...\n",
- "\n",
- "All MagStructure checks passed. No obvious problems found.\n",
- "Since you are not using a diffpy Structure object,\n",
- "the spins are generated from the makeAtoms() method.\n",
- "Please call that method if you have not already.\n",
- "Since you are not using a diffpy Structure object,\n",
- "the spins are generated from the makeAtoms() method.\n",
- "Please call that method if you have not already.\n",
- "No magnetic form factor found for that element/ion.\n",
- "Using generic magnetic form factor.\n",
- "No magnetic form factor found for that element/ion.\n",
- "Using generic magnetic form factor.\n",
- "Running checks for small MagSpecies object...\n",
- "\n",
- "All MagSpecies() checks passed. No obvious problems found.\n",
- "\n",
- "Running checks for big MagSpecies object...\n",
- "\n",
- "All MagSpecies() checks passed. No obvious problems found.\n",
- "\n",
- "Running checks for MagStructure object...\n",
- "\n",
- "All MagStructure checks passed. No obvious problems found.\n"
- ]
- },
- {
- "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 = $('');\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",
- " '');\n",
- " var titletext = $(\n",
- " '');\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 = $('');\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 = $('');\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 = $('');\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 = $('')\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 = $('');\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 = $('');\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 = $('');\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 = $('');\n",
- "\n",
- " var fmt_picker = $('');\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",
- " '', {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 = $('');\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(\"\");\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('
');\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'] = '
';\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 = $('')\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 = $('');\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 = $('');\n",
- " nav_element.append(status_bar);\n",
- " this.message = status_bar[0];\n",
- "\n",
- " // Add the close button to the window.\n",
- " var buttongrp = $('');\n",
- " var 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= 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": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/html": [
- "
"
- ],
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
- "source": [
- "### Create the first magnetic species and turn off the diffpy.structure option.\n",
- "mspec1 = MagSpecies(useDiffpyStruc=False)\n",
- "\n",
- "### Define the lattice vectors of the unit cell. Let's make a cubic unit cell.\n",
- "a = 4.0\n",
- "mspec1.latVecs = np.array([[a,0,0],[0,a,0],[0,0,a]])\n",
- "\n",
- "### Define the atomic position and magnetic moment.\n",
- "mspec1.atomBasis = np.array([0,0,0])\n",
- "mspec1.spinBasis = np.array([0,0,1])\n",
- "mspec1.label = 'big' ### it is necessary to define unique identifying labels when you have multiple species\n",
- "\n",
- "### Now make the other species, starting with mspec1 as a template\n",
- "mspec2 = mspec1.copy()\n",
- "mspec2.atomBasis = np.array([0.5,0.5,0.5])\n",
- "mspec2.spinBasis = np.array([0,0,-0.5])\n",
- "mspec2.label = 'small'\n",
- "### Create the magnetic structure object and load the species.\n",
- "mstruc = MagStructure()\n",
- "mstruc.loadSpecies(mspec1)\n",
- "mstruc.loadSpecies(mspec2)\n",
- "mstruc.makeAll()\n",
- "\n",
- "### Again, let's visualize the first unit cell to make sure we have what we expect.\n",
- "visAtoms = np.array([[0,0,0],[a,0,0],[0,a,0],[0,0,a],[a,a,0],[a,0,a],[0,a,a],[a,a,a],[0.5*a,0.5*a,0.5*a]])\n",
- "visSpins = mstruc.spinsFromAtoms(visAtoms, fractional=False)\n",
- "mstruc.visualize(visAtoms, visSpins, showcrystalaxes=True, axesorigin=np.array([-1,-1,-1]))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 10,
- "metadata": {
- "collapsed": false
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "{'small': 0, 'big': 3287}\n",
- "[0, 3287]\n"
- ]
- },
- {
- "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 = $('');\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",
- " '');\n",
- " var titletext = $(\n",
- " '');\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 = $('');\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 = $('');\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 = $('');\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 = $('')\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 = $('');\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 = $('');\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 = $('');\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 = $('');\n",
- "\n",
- " var fmt_picker = $('');\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",
- " '', {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 = $('');\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(\"\");\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('
');\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'] = '
';\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 = $('')\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 = $('');\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 = $('');\n",
- " nav_element.append(status_bar);\n",
- " this.message = status_bar[0];\n",
- "\n",
- " // Add the close button to the window.\n",
- " var buttongrp = $('');\n",
- " var 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= 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": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/html": [
- "
"
- ],
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
- "source": [
- "### Now we can set up the MPDFcalculator and plot the mPDF.\n",
- "mc = MPDFcalculator(mstruc)\n",
- "\n",
- "### Important: since we have two different magnetic species, we must be sure that the calculation\n",
- "### uses an equivalent number of spins from each species as the \"center\" of the calculation.\n",
- "### We do this by changing the calcList attribute of the MPDFcalculator, which is a list of the \n",
- "### indices of the atoms/spins to be used as the centers for the calculation. To find the starting\n",
- "### index of each species, use the getSpeciesIdxs method on the magnetic structure.\n",
- "\n",
- "mc.calcList = mstruc.getSpeciesIdxs().values()\n",
- "print mc.calcList\n",
- "\n",
- "### Now we can plot.\n",
- "mc.plot()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Creating more complex magnetic structures: One-dimensional spin helix"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "This example shows how to use multiple magnetic propagation vectors to create a non-collinear magnetic structure--in this case, a one-dimensional spin helix."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 11,
- "metadata": {
- "collapsed": false
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Running checks for helix MagSpecies object...\n",
- "\n",
- "All MagSpecies() checks passed. No obvious problems found.\n",
- "\n",
- "Running checks for MagStructure object...\n",
- "\n",
- "All MagStructure checks passed. No obvious problems found.\n"
- ]
- },
- {
- "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 = $('');\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",
- " '');\n",
- " var titletext = $(\n",
- " '');\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 = $('');\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 = $('');\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 = $('');\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 = $('')\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 = $('');\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 = $('');\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 = $('');\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 = $('');\n",
- "\n",
- " var fmt_picker = $('');\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",
- " '', {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 = $('');\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(\"\");\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('
');\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'] = '
';\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 = $('')\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 = $('');\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 = $('');\n",
- " nav_element.append(status_bar);\n",
- " this.message = status_bar[0];\n",
- "\n",
- " // Add the close button to the window.\n",
- " var buttongrp = $('');\n",
- " var 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= 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": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/html": [
- "
"
- ],
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
- "source": [
- "### We will load in a structure from a CIF file and modify it to simulate a 1-D material.\n",
- "astruc = loadStructure(\"MnO_cubic.cif\")\n",
- "astruc.lattice.a = 3.0\n",
- "astruc.lattice.b = 150.0\n",
- "astruc.lattice.c = 150.0\n",
- "\n",
- "### Create the magnetic species object.\n",
- "helix = MagSpecies(astruc)\n",
- "\n",
- "### Set up the magnetic propagation and basis vectors for a helical spin configuration.\n",
- "k = np.array([np.sqrt(2)/10,0,0]) # make the period incommensurate with the lattice\n",
- "helix.kvecs=np.array([k, -k])\n",
- "\n",
- "Sk = 0.5*(np.array([0,0,1])+0.5j*np.array([0,1,0])) # j is the numpy symbol for the imaginary unit\n",
- "helix.basisvecs = np.array([Sk,Sk.conj()])\n",
- "\n",
- "### Populate with atoms and spins.\n",
- "helix.rmaxAtoms = 70.0\n",
- "helix.makeAtoms()\n",
- "helix.makeSpins()\n",
- "helix.label = 'helix'\n",
- "\n",
- "### Create the magnetic structure object.\n",
- "mstruc = MagStructure()\n",
- "mstruc.loadSpecies(helix)\n",
- "\n",
- "#### Visualize the spins.\n",
- "x,y,z = mstruc.atoms.transpose()\n",
- "mask = np.logical_and(z==0,np.logical_and(y==0,np.abs(x)<30))\n",
- "visatoms = mstruc.atoms[mask]\n",
- "visspins = spinsFromAtoms(mstruc, visatoms, fractional=False)\n",
- "mstruc.visualize(visatoms, visspins)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 12,
- "metadata": {
- "collapsed": false
- },
- "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 = $('');\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",
- " '');\n",
- " var titletext = $(\n",
- " '');\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 = $('');\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 = $('');\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 = $('');\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 = $('')\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 = $('');\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 = $('');\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 = $('');\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 = $('');\n",
- "\n",
- " var fmt_picker = $('');\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",
- " '', {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 = $('');\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(\"\");\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('
');\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'] = '
';\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 = $('')\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 = $('');\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 = $('');\n",
- " nav_element.append(status_bar);\n",
- " this.message = status_bar[0];\n",
- "\n",
- " // Add the close button to the window.\n",
- " var buttongrp = $('');\n",
- " var 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= 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": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/html": [
- "
"
- ],
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
- "source": [
- "### Now plot the mPDF.\n",
- "mc = MPDFcalculator(mstruc)\n",
- "mc.rmax=70.0\n",
- "\n",
- "mc.plot()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Exploring some of the additional parameters in the mPDF"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Now we will take a look at some of the other mPDF parameters that can be adjusted, including:\n",
- "- Qmin and Qmax to simulate experimental conditions.\n",
- "- Parameters that dampen and/or broaden the mPDF, simulating the effects of thermal motion and instrumental resolution.\n",
- "- \"Ordered\" scale factor corresponding to the magnitude of the locally ordered moment, and \"paramagnetic\" scale factor which depends only on the magnitude and spatial extent of a single localized moment, not any correlations between moments.\n",
- "- The r-range for the calculation.\n",
- "\n",
- "For this, we will create the antiferromagnetic MnO structure again."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 13,
- "metadata": {
- "collapsed": false
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Coordinates of atoms and spins for Mn2+\n",
- "have not been loaded because they have not yet been\n",
- "generated and/or do not match in shape.\n",
- "Running checks for Mn2+ MagSpecies object...\n",
- "\n",
- "All MagSpecies() checks passed. No obvious problems found.\n",
- "\n",
- "Running checks for MagStructure object...\n",
- "\n",
- "All MagStructure checks passed. No obvious problems found.\n",
- "Running checks for Mn2+ MagSpecies object...\n",
- "\n",
- "All MagSpecies() checks passed. No obvious problems found.\n",
- "\n",
- "Running checks for MagStructure object...\n",
- "\n",
- "All MagStructure checks passed. No obvious problems found.\n"
- ]
- }
- ],
- "source": [
- "### Create the diffpy structure, MagSpecies, and MagStructure\n",
- "mno = loadStructure('MnO_cubic.cif')\n",
- "\n",
- "mnoMag = MagSpecies(mno, magIdxs=[0,1,2,3], label='Mn2+', ffparamkey='Mn2')\n",
- "mnoMag.kvecs = np.array([0.5,0.5,0.5])\n",
- "mnoMag.basisvecs = np.array([1,-1,0])\n",
- "\n",
- "mnoMagStruc = MagStructure()\n",
- "mnoMagStruc.loadSpecies(mnoMag)\n",
- "mnoMagStruc.makeAll()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Now we'll make the mPDF calculator along with several slightly modified copies so that we can compare them."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 14,
- "metadata": {
- "collapsed": false
- },
- "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 = $('');\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",
- " '');\n",
- " var titletext = $(\n",
- " '');\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 = $('');\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 = $('');\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 = $('');\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 = $('')\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 = $('');\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 = $('');\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 = $('');\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 = $('');\n",
- "\n",
- " var fmt_picker = $('');\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",
- " '', {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 = $('');\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(\"\");\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('
');\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'] = '
';\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 = $('')\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 = $('');\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 = $('');\n",
- " nav_element.append(status_bar);\n",
- " this.message = status_bar[0];\n",
- "\n",
- " // Add the close button to the window.\n",
- " var buttongrp = $('');\n",
- " var 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= 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": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/html": [
- "
"
- ],
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
- "source": [
- "### Default mPDF calculator\n",
- "mc = MPDFcalculator(mnoMagStruc)\n",
- "r, fr, dr = mc.calc(both=True)\n",
- "\n",
- "### Adjust qmin and qmax to simulate termination ripples\n",
- "mcQ = mc.copy()\n",
- "mcQ.qmin, mcQ.qmax = 0.1,25\n",
- "rq,frq = mcQ.calc()\n",
- "sclfactor = fr.max()/frq.max()\n",
- "frq *= sclfactor\n",
- "\n",
- "fig = plt.figure()\n",
- "ax = fig.add_subplot(111)\n",
- "\n",
- "ax.plot(r, fr, 'b-', label='Default')\n",
- "ax.plot(rq, frq, 'r-', label='With qmin/qmax')\n",
- "ax.plot(r, frq-fr-7, 'g-', label='Difference')\n",
- "\n",
- "ax.set_xlabel(r'r ($\\AA$)')\n",
- "ax.set_ylabel(r'f ($\\AA^{-2}$)')\n",
- "\n",
- "plt.legend(loc='best')\n",
- "plt.show()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 15,
- "metadata": {
- "collapsed": false
- },
- "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 = $('');\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",
- " '');\n",
- " var titletext = $(\n",
- " '');\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 = $('');\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 = $('');\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 = $('');\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 = $('')\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 = $('');\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 = $('');\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 = $('');\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 = $('');\n",
- "\n",
- " var fmt_picker = $('');\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",
- " '', {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 = $('');\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(\"\");\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('
');\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'] = '
';\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 = $('')\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 = $('');\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 = $('');\n",
- " nav_element.append(status_bar);\n",
- " this.message = status_bar[0];\n",
- "\n",
- " // Add the close button to the window.\n",
- " var buttongrp = $('');\n",
- " var 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= 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"
- ],
+ "image/png": "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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "### make a copy of the magnetic structure\n",
+ "mstruc2 = mstruc.copy()\n",
+ "\n",
+ "### Set the spins to be ferromagnetic\n",
+ "mstruc2.spins = np.array([S,S])\n",
+ "\n",
+ "### Create another mPDF calculator\n",
+ "mc2 = MPDFcalculator(mstruc2)\n",
+ "\n",
+ "### Calculate the mPDF\n",
+ "r2, fr2 = mc2.calc()\n",
+ "\n",
+ "### Compare the antiferromagnetic and ferromagnetic mPDFs\n",
+ "fig = plt.figure()\n",
+ "ax = fig.add_subplot(111)\n",
+ "\n",
+ "ax.plot(r,fr,'b-',label='Antiferro')\n",
+ "ax.plot(r2,fr2,'r-',label='Ferro')\n",
+ "\n",
+ "ax.set_xlabel(r'r ($\\AA$)')\n",
+ "ax.set_ylabel(r'f ($\\AA^{-2}$)')\n",
+ "\n",
+ "plt.legend()\n",
+ "\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "plt.close('all')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Creating a magnetic structure from a CIF file using diffpy.Structure"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "This example will show how to use the MagSpecies class and additional features in the MagStructure class to quickly generate the atomic positions and spin vectors from a diffpy.Structure object. It will also show how to calculate the unnormalized mPDF, which is useful for comparison to and refinement against neutron total scattering data."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Load the atomic structure from the CIF file"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "### Now let's create a diffpy.Structure object from a CIF file for MnO. This has all the atomic information,\n",
+ "### but none of the magnetic information. Note that a .stru file generated from PDFgui or diffpy.Structure\n",
+ "### would also work just as well.\n",
+ "mno = loadStructure('MnO_cubic.cif')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "lattice=Lattice(a=4.446, b=4.446, c=4.446, alpha=90, beta=90, gamma=90)\n",
+ "Mn2+ 0.000000 0.000000 0.000000 1.0000\n",
+ "Mn2+ 0.000000 0.500000 0.500000 1.0000\n",
+ "Mn2+ 0.500000 0.000000 0.500000 1.0000\n",
+ "Mn2+ 0.500000 0.500000 0.000000 1.0000\n",
+ "O2- 0.500000 0.500000 0.500000 1.0000\n",
+ "O2- 0.500000 0.000000 0.000000 1.0000\n",
+ "O2- 0.000000 0.500000 0.000000 1.0000\n",
+ "O2- 0.000000 0.000000 0.500000 1.0000\n"
+ ]
+ }
+ ],
+ "source": [
+ "### As a refresher, let's take a look at the mno structure object.\n",
+ "print(mno)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Create the MagSpecies object"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "### We will now create a MagSpecies object to extend the mno structure object.\n",
+ "mspec = MagSpecies()\n",
+ "\n",
+ "### Load the mno structure and give the magnetic species a label\n",
+ "mspec.struc = mno\n",
+ "mspec.label = 'Mn2+'\n",
+ "\n",
+ "### Now we need to tell it which atoms in MnO are magnetic. From the printed list in the previous cell,\n",
+ "### the magnetic Mn ions are the first four positions in the structure, so we provide the corresponding indices.\n",
+ "mspec.magIdxs = [0,1,2,3]\n",
+ "\n",
+ "### Now we provide the magnetic propagation and basis vectors, which are known from previous neutron\n",
+ "### diffraction studies of MnO.\n",
+ "k = np.array([0.5,0.5,0.5])\n",
+ "s = np.array([1,-1,0]) # we won't worry about the magnitude of the basis vector for now\n",
+ "mspec.kvecs = np.array([k])\n",
+ "mspec.basisvecs = np.array([s])\n",
+ "\n",
+ "### Now we provide information about the magnetic form factor. We tell the MagSpecies object the type of magnetic\n",
+ "### ion, and it looks up magnetic form factor in a table.\n",
+ "mspec.ffparamkey = 'Mn2'"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Create the MagStructure object"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "### Now we can create a MagStructure object and load mnoMag into it.\n",
+ "mstruc = MagStructure()\n",
+ "mstruc.loadSpecies(mspec)\n",
+ "### Now we will generate the atomic positions and spins. It is important to do the atoms first, since the\n",
+ "### spins are generated by applying the propagation and basis vectors to the atomic positions. These methods\n",
+ "### use the information contained in the atomic and magnetic structures to generate arrays of atomic positions\n",
+ "### and spin vectors.\n",
+ "mstruc.makeAtoms()\n",
+ "mstruc.makeSpins()\n",
+ "\n",
+ "### And we make the magnetic form factor:\n",
+ "mstruc.makeFF()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### View the magnetic structure"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "uc = mno[:4].xyz\n",
+ "visatoms = uc.copy()\n",
+ "visatoms = np.concatenate((visatoms,visatoms+np.array([0,0,1]),visatoms+np.array([0,1,0]),visatoms+np.array([0,0,1])))\n",
+ "visatoms = mno.lattice.cartesian(visatoms)\n",
+ "visspins = mstruc.spinsFromAtoms(visatoms,fractional=False)\n",
+ "mstruc.visualize(visatoms,visspins)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "### Now we can create the mPDF calculator and load the magnetic structure\n",
+ "mc = MPDFcalculator()\n",
+ "mc.magstruc = mstruc\n",
+ "\n",
+ "### Plot the mPDF\n",
+ "mc.plot()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "plt.close('all')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Creating a magnetic structure by defining your own unit cell"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "This example will show you how to create a magnetic structure from a unit cell that you define yourself. You will have to provide the lattice vectors, the positions of the magnetic atoms in the unit cell, and the magnetic moments corresponding to those atoms."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Since you are not using a diffpy Structure object,\n",
+ "the spins are generated from the makeAtoms() method.\n",
+ "Please call that method if you have not already.\n"
+ ]
+ },
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "### Create the magnetic species and turn off the diffpy.structure option.\n",
+ "mspec = MagSpecies(useDiffpyStruc=False)\n",
+ "\n",
+ "### Define the lattice vectors of the unit cell. Let's make a cubic unit cell.\n",
+ "a = 4.0\n",
+ "mspec.latVecs = np.array([[a,0,0], [0,a,0], [0,0,a]])\n",
+ "\n",
+ "### Define the positions of the magnetic atoms in the unit cell (in fractional coordinates). Let's make\n",
+ "### We'll make a body-centered structure.\n",
+ "mspec.atomBasis = np.array([[0,0,0], [0.5,0.5,0.5]])\n",
+ "\n",
+ "### Define the magnetic moments in the same order as the list of atoms.\n",
+ "### Let's make an antiferromagnet.\n",
+ "mspec.spinBasis = np.array([[0,0,1], [0,0,-1]])\n",
+ "\n",
+ "\n",
+ "### Create the magnetic structure object and load mspec.\n",
+ "mstruc = MagStructure()\n",
+ "mstruc.loadSpecies(mspec)\n",
+ "mstruc.makeAtoms()\n",
+ "mstruc.makeSpins()\n",
+ "\n",
+ "### Let's visualize the first unit cell to make sure we have what we expect.\n",
+ "visAtoms = np.array([[0,0,0],[a,0,0],[0,a,0],[0,0,a],[a,a,0],\n",
+ " [a,0,a],[0,a,a],[a,a,a],[0.5*a,0.5*a,0.5*a]])\n",
+ "visSpins = mstruc.spinsFromAtoms(visAtoms, fractional=False)\n",
+ "mstruc.visualize(visAtoms, visSpins)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "### Now we can set up the MPDFcalculator and plot the mPDF.\n",
+ "mc = MPDFcalculator(mstruc)\n",
+ "mc.plot()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "plt.close('all')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Creating a magnetic structure with multiple species: Simple ferrimagnet"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We will create a ferrimagnetic structure to illustrate the use of multiple magnetic species within a single magnetic structure. Let's build another antiferromagnetic body-centered cubic structure but with two different spin species, one with a large moment and one with a small moment."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Make a magnetic species with a large moment"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 16,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "### Create the first magnetic species and turn off the diffpy.structure option.\n",
+ "mspec1 = MagSpecies(useDiffpyStruc=False)\n",
+ "\n",
+ "### Define the lattice vectors of the unit cell. Let's make a cubic unit cell.\n",
+ "a = 4.0\n",
+ "mspec1.latVecs = np.array([[a,0,0],[0,a,0],[0,0,a]])\n",
+ "\n",
+ "### Define the atomic position and magnetic moment.\n",
+ "mspec1.atomBasis = np.array([0,0,0])\n",
+ "mspec1.spinBasis = np.array([0,0,1])\n",
+ "mspec1.label = 'big' ### it is necessary to define unique identifying labels when you have multiple species"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Make a magnetic species with a small moment"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 17,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "### Now make the other species, starting with mspec1 as a template\n",
+ "mspec2 = mspec1.copy()\n",
+ "mspec2.atomBasis = np.array([0.5,0.5,0.5])\n",
+ "mspec2.spinBasis = np.array([0,0,-0.25])\n",
+ "mspec2.label = 'small'"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Create and view the magnetic structure"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 18,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Since you are not using a diffpy Structure object,\n",
+ "the spins are generated from the makeAtoms() method.\n",
+ "Please call that method if you have not already.\n",
+ "Since you are not using a diffpy Structure object,\n",
+ "the spins are generated from the makeAtoms() method.\n",
+ "Please call that method if you have not already.\n",
+ "No magnetic form factor found for that element/ion.\n",
+ "Using generic magnetic form factor.\n",
+ "No magnetic form factor found for that element/ion.\n",
+ "Using generic magnetic form factor.\n",
+ "Please make sure your magnetic structure contains a\n",
+ "magnetic species with MagSpecies.struc set to a diffpy\n",
+ "structure or MagSpecies.latVecs provided and\n",
+ "MagSpecies.useDiffpyStruc set to False.\n"
+ ]
+ },
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "### Create the magnetic structure object and load the species.\n",
+ "mstruc = MagStructure()\n",
+ "mstruc.loadSpecies(mspec1)\n",
+ "mstruc.loadSpecies(mspec2)\n",
+ "mstruc.makeAll()\n",
+ "\n",
+ "### Again, let's visualize the first unit cell to make sure we have what we expect.\n",
+ "visAtoms = np.array([[0,0,0],[a,0,0],[0,a,0],[0,0,a],[a,a,0],[a,0,a],[0,a,a],[a,a,a],[0.5*a,0.5*a,0.5*a]])\n",
+ "visSpins = mstruc.spinsFromAtoms(visAtoms, fractional=False)\n",
+ "mstruc.visualize(visAtoms, visSpins, showcrystalaxes=True, axesorigin=np.array([-1,-1,-1]))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Calculate the mPDF"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 20,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "{'big': 0, 'small': 3287}\n",
+ "dict_values([0, 3287])\n"
+ ]
+ },
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "### Now we can set up the MPDFcalculator and plot the mPDF.\n",
+ "mc = MPDFcalculator(mstruc)\n",
+ "\n",
+ "### Important: since we have two different magnetic species, we must be sure that the calculation\n",
+ "### uses an equivalent number of spins from each species as the \"center\" of the calculation.\n",
+ "### We do this by changing the calcList attribute of the MPDFcalculator, which is a list of the \n",
+ "### indices of the atoms/spins to be used as the centers for the calculation. To find the starting\n",
+ "### index of each species, use the getSpeciesIdxs method on the magnetic structure.\n",
+ "\n",
+ "mc.calcList = mstruc.getSpeciesIdxs().values()\n",
+ "print(mc.calcList)\n",
+ "\n",
+ "### Now we can plot.\n",
+ "mc.plot()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 21,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "plt.close('all')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Creating more complex magnetic structures: One-dimensional spin helix"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "This example shows how to use multiple magnetic propagation vectors to create a non-collinear magnetic structure--in this case, a one-dimensional spin helix."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 22,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [
+ {
+ "data": {
+ "image/png": "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tLQUf/7znwEAv/jFL7Bq1SrU1NQgPz8fUqkUL7/8stfHhjAVIUI+iRUrVmBwcHDK7Y8++iiuuuoq+m+RSER9jkOYGcrLy1FbW4vIyEh6G5He1dXV4ZNPPsGOHTtgNBqdDP7T0tJgNBrR29sbEOmdXq9HU1MTYmNjsXjx4oCQnUQiQXJyspNhvtFohFarxcjICNrb23ltLkajEb///e/R0NCAvXv3orCwcMZr84SxsTHccMMNUCqVyM7Oxr59+5zGUK1atQplZWVYt24d3njjDbz55pu44447sHHjRgDA7373O7z77rvUy3l4eNjpsatWrQra2ucKQjpknnjllVfw4osv4tNPP6Um8K4uVpdddhm2bdvmV8rib3/7G7Zt24ampibU19c7GYWfa4VDV1gsFhw9epT6dRw/fhwSiYQa/FdWViIhIYE2VrimDDxJ70gRUaVS0c6/2QS3iYVM2WYYBmazGUePHkVcXByef/55/OxnP8OGDRuCHhXff//9iI+Px+bNm7Fjxw6Mj4/j8ccfd7rPwMAABgYGUFlZCZ1Oh6qqKrz77rsoKSnBtm3bEBkZifvuuy+o6zxLEWoMCRQ++ugj3Hvvvfjiiy/o7g8AJ06cwE033YT6+nr09/fjkksugUKh8OvCIcY0d955J5588klKyI2NjVi7di19jXO1cMgFy7LQaDROBv8dHR1IT09HZWUlFi9ejIULFzoZ/LtK7xwOB9ra2pCSkuK182+2Ybfb0djYiEceeQQnTpxAeHg4UlNTccstt9Bhu8FCUVERPv/8c6SlpWFgYADLly9HS0uL18dcddVVuPvuu7Fy5coQIXtHqDEkULj77rthNpuxcuVKAJOFvT//+c8oLS3F9ddfj5KSEohEIjz//PN+E6Un2VKocDgVDMMgNjYWK1eupH8TMnC2rq4OBw4cwLPPPovx8XEng//09HSMjY2htrYWEokEERERMBqNGBgYCPjAWX/AsiwOHDiABx54AOvXr8e7774LoVCI0dFRqNXqoL/+0NAQ0tLSAACpqakYGhryen+lUonvvvsO5513Hr1t165deO2111BdXY2dO3cGbbL3XEWIkHmgra3N4/9t2bIlqL32ocIhPzAMg6ysLGRlZeH6668HMNk0ceLECdTV1WHfvn34/PPPodFosHz5clx88cWoqqpCamoqdDodOjs7odfrERYW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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "### We will load in a structure from a CIF file and modify it to simulate a 1-D material.\n",
+ "astruc = loadStructure(\"MnO_cubic.cif\")\n",
+ "astruc.lattice.a = 3.0\n",
+ "astruc.lattice.b = 150.0\n",
+ "astruc.lattice.c = 150.0\n",
+ "\n",
+ "### Create the magnetic species object.\n",
+ "helix = MagSpecies(astruc)\n",
+ "\n",
+ "### Set up the magnetic propagation and basis vectors for a helical spin configuration.\n",
+ "k = np.array([np.sqrt(2)/10,0,0]) # make the period incommensurate with the lattice\n",
+ "helix.kvecs=np.array([k, -k])\n",
+ "\n",
+ "Sk = 0.5*(np.array([0,0,1])+0.5j*np.array([0,1,0])) # j is the numpy symbol for the imaginary unit\n",
+ "helix.basisvecs = np.array([Sk,Sk.conj()])\n",
+ "\n",
+ "### Populate with atoms and spins.\n",
+ "helix.rmaxAtoms = 70.0\n",
+ "helix.makeAtoms()\n",
+ "helix.makeSpins()\n",
+ "helix.label = 'helix'\n",
+ "\n",
+ "### Create the magnetic structure object.\n",
+ "mstruc = MagStructure()\n",
+ "mstruc.loadSpecies(helix)\n",
+ "\n",
+ "#### Visualize the spins.\n",
+ "x,y,z = mstruc.atoms.transpose()\n",
+ "mask = np.logical_and(z==0,np.logical_and(y==0,np.abs(x)<30))\n",
+ "visatoms = mstruc.atoms[mask]\n",
+ "visspins = spinsFromAtoms(mstruc, visatoms, fractional=False)\n",
+ "mstruc.visualize(visatoms, visspins)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 23,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "### Now plot the mPDF.\n",
+ "mc = MPDFcalculator(mstruc)\n",
+ "mc.rmax=70.0\n",
+ "\n",
+ "mc.plot()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 24,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "plt.close('all')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Exploring some of the additional parameters in the mPDF"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Now we will take a look at some of the other aspects of the mPDF that can be adjusted, including:\n",
+ "- Whether the normalized mPDF, unnormalized mPDF, or both are calculated (see Acta A REF)\n",
+ "- Qmax to simulate experimental conditions.\n",
+ "- Parameters that dampen and/or broaden the mPDF, simulating the effects of thermal motion and instrumental resolution.\n",
+ "- \"Ordered\" scale factor corresponding to the magnitude of the locally ordered moment, and \"paramagnetic\" scale factor which depends only on the magnitude and spatial extent of a single localized moment, not any correlations between moments.\n",
+ "- The r-range for the calculation.\n",
+ "\n",
+ "For this, we will create the antiferromagnetic MnO structure again."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Create the MnO magnetic structure"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 25,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "### Create the diffpy structure, MagSpecies, and MagStructure\n",
+ "mno = loadStructure('MnO_cubic.cif')\n",
+ "\n",
+ "mspec = MagSpecies(mno, magIdxs=[0,1,2,3], label='Mn2+', ffparamkey='Mn2')\n",
+ "mspec.kvecs = np.array([0.5,0.5,0.5])\n",
+ "mspec.basisvecs = np.array([1,-1,0])\n",
+ "\n",
+ "mstruc = MagStructure()\n",
+ "mstruc.loadSpecies(mspec)\n",
+ "mstruc.makeAll()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Calculate the normalized and unnormalized mPDFs"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 26,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [
+ {
+ "data": {
+ "image/png": "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\n",
"text/plain": [
- ""
+ ""
]
},
"metadata": {},
"output_type": "display_data"
- },
+ }
+ ],
+ "source": [
+ "mc = MPDFcalculator(mstruc)\n",
+ "r, fr = mc.calc() ### by default, just the normalized mPDF is calculated\n",
+ "r, dr = mc.calc(normalized=False) ### setting the normalized arg to False calculates the unnormalized mPDF\n",
+ "\n",
+ "### Let's compare the two quantities\n",
+ "\n",
+ "fig = plt.figure()\n",
+ "ax = fig.add_subplot(111)\n",
+ "\n",
+ "ax.plot(r, fr/fr.max(), 'b-', label='Normalized')\n",
+ "ax.plot(r, dr/dr.max(), 'r-', label='Unnormalized')\n",
+ "\n",
+ "ax.set_xlabel(r'r ($\\AA$)')\n",
+ "ax.set_ylabel(r'f ($\\AA^{-2}$)')\n",
+ "\n",
+ "plt.legend(loc='best')\n",
+ "plt.tight_layout()\n",
+ "plt.show()\n",
+ "\n",
+ "### Or you can calculate them both together:\n",
+ "r, fr, dr = mc.calc(both=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Model the effect of finite Qmax"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 27,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [
{
"data": {
- "text/html": [
- "
"
- ],
+ "image/png": "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\n",
"text/plain": [
- ""
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "### Default mPDF calculator\n",
+ "mc = MPDFcalculator(mstruc)\n",
+ "r, fr = mc.calc()\n",
+ "\n",
+ "### Adjust qmax to simulate termination ripples\n",
+ "mcQ = mc.copy()\n",
+ "mcQ.qmax = 25.0\n",
+ "rq,frq = mcQ.calc()\n",
+ "\n",
+ "fig = plt.figure()\n",
+ "ax = fig.add_subplot(111)\n",
+ "\n",
+ "ax.plot(r, fr, 'b-', label='Default')\n",
+ "ax.plot(rq, frq, 'r-', label='With qmax')\n",
+ "ax.plot(r, frq-fr-35, 'g-', label='Difference')\n",
+ "\n",
+ "ax.set_xlabel(r'r ($\\AA$)')\n",
+ "ax.set_ylabel(r'f ($\\AA^{-2}$)')\n",
+ "\n",
+ "plt.legend(loc='best')\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Change the intrinisic mPDF peak width"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 28,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ ""
]
},
"metadata": {},
@@ -9329,25 +1776,155 @@
],
"source": [
"### Change the intrinsic mPDF peak width to simulate thermal motion\n",
- "### and/or instrumental resolution effects.\n",
+ "### and/or instrumental limitations.\n",
"mcB = mc.copy()\n",
- "mcB.gaussPeakWidth = 0.2 # in Angstroms; default is 0.1\n",
+ "mcB.gaussPeakWidth = 0.15 # in Angstroms; default is 0.1\n",
"rB, frB = mcB.calc()\n",
"\n",
+ "fig = plt.figure()\n",
+ "ax = fig.add_subplot(111)\n",
+ "\n",
+ "ax.plot(r, fr, 'b-', label='Default')\n",
+ "ax.plot(rB, frB, 'r-', label='Broadened')\n",
+ "ax.plot(r,frB - fr - 35, 'g-', label='Difference')\n",
+ "ax.set_xlabel(r'r ($\\AA$)')\n",
+ "ax.set_ylabel(r'f ($\\AA^{-2}$)')\n",
+ "\n",
+ "plt.legend(loc='best')\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Introduce a damping envelope"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 29,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [
+ {
+ "data": {
+ "image/png": "iVBORw0KGgoAAAANSUhEUgAAAY8AAAEPCAYAAAC6Kkg/AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAIABJREFUeJzsvXl83FW9//88M5lkksxk39qk6UZX2lIKpSAoAmVRVERRREURN1RQLlcuqFeF68/7xSu4IIogLsDVqyjKomUtbYEC3fc1TZu2adYmmWS2TDIz798fZyYzk3UmmWQm7ef5eMzj85nPfJbz+czMeZ33+7zP+ygRwcDAwMDAIBFMqS6AgYGBgcHkwxAPAwMDA4OEMcTDwMDAwCBhDPEwMDAwMEgYQzwMDAwMDBLGEA8DAwMDg4QxxMPAwMDAIGEM8TAwMDAwSBhDPAwMDAwMEiYj1QUYL0pKSmTGjBmpLoaBgYHBpGLLli0nRaR0pP1OWfGYMWMGmzdvTnUxDAwMDCYVSqmj8exnuK0MDAwMDBLGEA8DAwMDg4QxxMPAwMDAIGFO2T6Pwejt7aW+vp7u7u5UF2VSYbVaqaqqwmKxpLooBgYGacJpJR719fXY7XZmzJiBUirVxZkUiAhtbW3U19czc+bMVBfHwMAgTTit3Fbd3d0UFxcbwpEASimKi4sNa83AwCCG00o8AEM4RoHxzAwMDPqTVuKhlLIqpTYqpXYopfYope4NbS9SSr2ilKoJLQtTXVYDA4NTh2eegWPHUl2KyUVaiQfgAy4VkbOApcBVSqnzgbuB1SIyB1gdej8pMZvNLF26lDPPPJOzzjqLBx54gGAwOOJxd955J2eeeSZ33nnnqK5rs9kAqKur409/+tOozmFgcCridsO118JFF6W6JJOLtOowFxEBXKG3ltBLgGuA94a2Pw6sBe6a4OIlhezsbLZv3w5AS0sLn/zkJ+nq6uLee+8d9rhHH32U9vZ2zGbzmK4fFo9PfvKTYzqPgcGpwr59enn8eGrLMdlIN8sDpZRZKbUdaAFeEZENQLmINIZ2aQLKU1bAJFJWVsajjz7KQw89hIgQCAS48847Wb58OUuWLOGRRx4B4EMf+hAul4tzzjmHv/zlLzz//POsWLGCs88+m5UrV9Lc3AzAPffcw/333993/kWLFlFXVxdzzbvvvps33niDpUuX8tOf/nTC7tXAIF05cUIvTWlXG6Y3aWV5AIhIAFiqlCoA/qGUWtTvc1FKyWDHKqW+BHwJoLq6etjr3H47hAyApLF0KfzsZ4kdM2vWLAKBAC0tLTz77LPk5+ezadMmfD4fF154IVdccQXPPfccNputz2Lp6OjgnXfeQSnFY489xv/8z//wwAMPxHW9++67j/vvv59//vOfid6egcEpiSvk64jDe2wQRdqJRxgRcSil1gBXAc1KqSki0qiUmoK2SgY75lHgUYBzzz13UIFJZ15++WV27tzJ3/72NwA6OzupqakZML6ivr6e66+/nsbGRnp6eozxFwYGYyAsHgaJkVbioZQqBXpDwpENXA78CHgO+CxwX2j57FivlaiFMF4cPnwYs9lMWVkZIsIvfvELrrzyymGPue2227jjjjv40Ic+xNq1a7nnnnsAyMjIiOl8N8ZmGBiMTLR4iIARmR4f6eblmwKsUUrtBDah+zz+iRaNy5VSNcDK0PtJT2trK7fccgu33norSimuvPJKHn74YXp7ewE4ePAgbrd7wHGdnZ1UVlYC8Pjjj/dtnzFjBlu3bgVg69atHDlyZMCxdrsdp9M5HrdjYDApiRaPnp7UlWOykVaWh4jsBM4eZHsbcNnElyj5eL1eli5dSm9vLxkZGdx4443ccccdAHzhC1+grq6OZcuWISKUlpbyzDPPDDjHPffcw8c+9jEKCwu59NJL+0Tiox/9KE888QRnnnkmK1asYO7cuQOOXbJkCWazmbPOOoubbrqJf/u3fxvfGzYwSHOixcPrhays1JVlMqF0dOypx7nnniv9J4Pat28fCxYsSFGJJjfGszM4VfnKV+DXv9brDQ0wZUpqy5NqlFJbROTckfZLN7eVgYGBwYTS3/IwiA9DPAwMDE5rDPEYHYZ4GBgYnNYY4jE6DPEwMDA4rYkWDEM84scQDwMDg9Manw/sdr1uiEf8GOJhYGBwWuPzQUGBXjfEI34M8ZhgRpuSfSK46aab+lKjGBicLvh8UBiaIcgQj/hJq0GCpwOjTcluYGAwPvh8UFGh1w3xiB/D8kgh/VOy19XV8e53v5tly5axbNky3nrrLQDWrl3LxRdfzDXXXMOsWbO4++67+eMf/8h5553H4sWLqa2tBbTlcMstt3Duuecyd+7cvsy5Q6V6FxFuvfVW5s2bx8qVK2lpGTTfpIHBKY3hthodp6/lkSY52aNTspeVlfHKK69gtVqpqanhhhtuIDxKfseOHezbt4+ioiJmzZrFF77wBTZu3MjPf/5zfvGLX/Cz0HXr6urYuHEjtbW1XHLJJRw6dIgnnnhi0FTv27Zt48CBA+zdu5fm5mYWLlzIzTffnNxnYmCQ5vh8kJ+v141covFz+opHGtLb28utt97K9u3bMZvNHDx4sO+z5cuXMyWUN2H27NlcccUVACxevJg1a9b07ffxj38ck8nEnDlzmDVrFvv37x8y1fvrr7/ODTfcgNlsZurUqVx66aUTeLcGBulBdLSVkRgxfk5f8UiTnOzRKdnvvfdeysvL2bFjB8FgEKvV2rdfVlS2NpPJ1PfeZDLh9/v7PlP98kkrpYZM9b5q1arxuCUDg0mFIR6jw+jzSCH9U7J3dnYyZcoUTCYTTz75JIFAIOFz/vWvfyUYDFJbW8vhw4eZN2/ekKne3/Oe9/CXv/yFQCBAY2NjjAVjYHA6EAjoV06OnobWEI/4OX0tjxQxXEr2r371q31p1a+66ipyc3MTPn91dTXnnXceXV1d/PrXv8ZqtQ6Z6v3aa6/ltddeY+HChVRXV3PBBRck+3YNDNIan08vs7L0yxCP+DFSsp9C3HTTTXzgAx/guuuuS/q5T/VnZ3B60tEBRUXw05/CPffATTeljUc7ZRgp2Q0MTiF27ID//E89TapB8oi2PDIzI+8NRsZwW51C/OEPf0h1EQzGiU98AvbvhxtvhHnzUl2aU4f+4mG4reLntLM8TlU33XhiPLPUs3+/XtbXp7YcpxpGn8foOa3Ew2q10tbWZlSGCSAitLW1xYQNG6SOpqZUl+DUwrA8Rs9p5baqqqqivr6e1tbWVBdlUmG1Wqmqqkp1MU5rzGYdUtrYmOqSnFoY4jF6TivxsFgszJw5M9XFMDBIiPBYBICurtSW5VQjLB5Wq9FhniinldvKwGAy0tkZWY+eMtVg7BiWx+gxxMPAIM2JFgxDPJKL0WE+egzxMDBIc6LThBvikVwMy2P0pJV4KKWmKaXWKKX2KqX2KKW+EdpepJR6RSlVE1oWprqsBgYThSEe44chHqMnrcQD8AP/LiILgfOBrymlFgJ3A6tFZA6wOvTewOC0wBCP8SPdRpiHcpdOCtJKPESkUUS2htadwD6gErgGeDy02+PAh1NTQoPx5umn4aqrICrL/GlPWDxycgzxSDbpZHnU1uoyPP106sqQCGklHtEopWYAZwMbgHIRCUe4NwHlKSqWwThz3XXw0kuwe3eqS5I+hMWjtNQQj2STTh3mq1fr5R//mLoyJEJaiodSygY8DdwuIjGR7aKHhw86RFwp9SWl1Gal1GZjIODkxkjDEcEQj/EjnSyPujq9nCzJHNJOPJRSFrRw/FFE/h7a3KyUmhL6fArQMtixIvKoiJwrIueWlpZOTIENxoUTJ1JdgvQhWjycztSW5VQjncTD4dDLyfLbTyvxUHoO1d8C+0TkJ1EfPQd8NrT+WeDZiS6bwfgTPXFiy6DNg9OTsHgUF8d2nhuMnbB4WCyp7zDv6NDL6EGh6Uy6pSe5ELgR2KWU2h7a9m3gPuAppdTngaPAx1NUPoNxJPznAaOFHU20ePh8EAzqKVMNxk53t7Y6lEofy2OypKBJK/EQkTcBNcTHl01kWQwmnmjBmCx/oIkgLB5FRZH3o5ih2GAQfD4tHqCXvb16wi01VC00joQbT5Plt2+0XwzSBo8HlrOR73EvXZ1G2vwwHo9ehsUj/H4y0d4On/scNDenuiSxRItHZqZepmqsRbTlMRlmjTDEwyBtcLvhn3yAe7mH/IZ9qS5O2uD16gicnJzI+8nGH/6gX+k2P7jPF4luCotHqlxXYfHo7U39YMV4MMTDIG3weKAMHWJtb6tLbWHSCK8XsrMj4jEZLY8jR/Syuzu15ejPYJZHqiruzs7IdzwZXFeGeBikDW53ZD2/81jqCpJmeL26UsnOjryfbITdVUePprYc/RlMPFJheQSDWlgrKvR7QzwMDBLA4wr2ree608w5nkK8XsjP6qa44xAwOS2PsHicPJnacvSnf4c5pEY8whZZWDwmQ7iuIR4GaUNvq6NvPcs7Cf49E4TXC/d2fJ2LPjeHMponpXiEEz6kW6WYLpZH9EBQiLXC0xVDPAzSBmmNNEuze9OslkkhXi9c1/EbABaxe1K6rcKi4XAMv99Ek27iUVysl5OhgWCIh0HaoNoi4mEPOGJGnJ/ORIvFDOomRcXSn/AYnnSzPMKDBCG1Hebh7zQsHpOhgWCIh0HaEHToXsKgMpFP56SsJMcDnyeiolXUT4qKJRqRSELHri7dOZwuGJbH6DHEwyB9CNUwnvyp5NM5Kfy+E0GWq61vvQDHpKhYovF4tICUlellOqWeSZcOc0M8DAzGgLi0WniLKw3xiCLDE4nbLKRj0lkeYbGYNk0v08l1lS6WR3+3lSEeBgaJEFKLnpJKCnAY4hHC7I001Sej5RF2WVVW6qUhHgMJNwhKSvRyMnzHhngYpA0mj65l/KUV2HAZ4hHCEiUeRapjUlQs0YQtj/AYhnT6XtNlhHlYPAoKdMbkyWBdGuJhkDaYvG6CKCgtIwcv7k5jInMAiy/UdJ8yhSLlmBQVSzSTQjx27SLL7+7bNtGEGwTZ2fo1GRoIhngYpA0Z3S66TTmYC/MA6G5Lo1omRYhAVm+o9q2uppDJZ3mE3Vbl5XqZTuX3+aDCewSWLKHyR18HUuu2ysnRr3R6RkNhiIdB2mD2uenOsJFRYAOgpy2NwnJSRHc32Ak9h6oq8mXyWh5h8UgXyyMY1BlsZ7RtAcD+j8eB1LqtwgkwDfEwMEiAzB4XPRm5WIrsAPQ6XCkuUerxesFG6DlMnUqOuPC4J8FkD1Gkq9sqbGEUu+oAUKFRqal2WxniYWCQIJk9bnyZNrKKteURMMQDrzfK8pg6FRNC0JkmtW+c9HdbpYt4hJMRFjkjGZyz6E6Z20op3f+SnW10mBsYJESW34U/MzdKPAy3lcejxcNvsUJhIQAm1yTI1x1FWCzKyvQyXVrVYQsj19fet62YtpS5rbKztYAYloeBQYJYA278Vluf2yrYZVgeYcvDn20Hu34uJvfkElW3GzIydPGVSh/LIywSVl8kW2OqxQNGLx5HjsCmTckt13AY4mGQFoho8QhYc8GmLY+0ymORIsJ9HsFsG+TpKLToEeeTAY9HV4hKQW5uGopHd6cuHFBhPpmyPo/wLIKjFY8PfQjOO2/inq8hHgZpQW9vuJLM7Wth9znLT2PClkcwN2J5mD2TS1SjK8Z0FI8srwNmzwag3JIelkeifR4isHu3Xj9wILllGwpDPAzSArcbcnETzLH1WR7KY4hHn3jY7H2Wh8U7uSwPt1uLBqSXPz8sEpmeKPEwp148RjNIsD3SbUNdXdKKNSyGeBikBR5PKCTVlttX00y2FvZ40Beqa7P1WR6Zvsn1XNLd8rB4O2HGDAAKTZ0pc1uNpc+jpSWyfuzY0PslE0M8DNICjytIDh5dSZrNeE05ZHgNyyNseai8iNsqq8cQj2Tg84EZPxkepx6EYjZTYOpKWajuWPo8oj28bW1D75dM0k48lFK/U0q1KKV2R20rUkq9opSqCS0LU1lGg+TjbfdiQjDZtNXRnWHD0j25KsnxIByqa8qPuK1yg1309qa4YAng8aSn28rrhTxCLsDCQsjLI085U+62ysnRwpbITJrR4hHtwhpP0k48gD8AV/XbdjewWkTmAKtD7w1OIXztujlqztf9Hd0WO5k9huURtjzM+XawWgmazNhxjtsgsr//Hf7xj+Se0+2GSlMj3HYbleamtLE8PB6d4h6A/Hyw28lTXWnhtoLIIMZ4iA5MPG3FQ0ReB/rf/jXA46H1x4EPT2ihDMYdX5sWCnOebqL2ZNoM8QA8bsGGS4uqUvRY88ija1zEw+2Gj34UPvKR5E4V6/HABxsegYce4urm36aVeOQTmlykoADy8rCTessjvEzEQgtbHoWFp7HbagjKRaQxtN4ElA+2k1LqS0qpzUqpza2trRNXOoMx09OhaxRLgRaP3iwbVr/htup1dpNBgIxC3d/hz7Zjxzkurp99+yLryQz39HjgDOc2AM7o2ppW4tFneRQUgN2OXVJjefTv8wiXL17Clsf06aex5TESIiLAoJnhRORRETlXRM4tLS2d4JIZjAV/KI9VXyVptZMdMCyPcIoWlaefS2AcxSNaMJIZ7ul2Q0FPMwBlnqNp0+cxQDzy8rAFU295jEY8wpZHdbVhefSnWSk1BSC0bBlhf4NJRqBT//qzirTlEci2kRt0JtV9MhkRZ6hWCEVaBWzj57Zqaoqs19cn77weD9h9ukYr8JxIK8ujz20V6vPIDabO8hiLeIQtj8rKiZvmd7KIx3PAZ0PrnwWeTWFZDMaBQJeuUcJJEYM5Nmy40qaVmjLCtUJo4KTkjp/l0dqqs3QolTzxCAZ1x29u90kA7J5mAj1+/GkwSaTHA8WmWMsjJzDxlkdvL/j9A8UjkQaCy6WPKyyEri494ny8STvxUEr9H/A2ME8pVa+U+jxwH3C5UqoGWBl6b3AKEU6CaC0JVZI2uzGPOaBcIfEIWR6SN36WR2srTJmiX8ePJ+ecXi9k0Et2twOmTkWJUEF6RFx5PFBqCYlHXh7Y7eT4J36cR/QsghARkUSekdOpfyJ5eTrEdyJSumeM/yUSQ0RuGOKjyya0IAYTStg9k1kUSopos2HHyXGXQLlKYclSS18G3ZB4qLzxszxaWqC0VGfAbW5OzjndbigKB08uWgQNDSHxqCI/PznXGFPZMjohKw/MZsjLw9rrxNctwMT95qJnEYRIXtBExMMVSkIQGgqE0xkRo/Ei7SwPg9MTCf1TVGiQoMqzY8GPx5GC4b5pRH/xMI2jeLS2avEoK0ueeHg8UIJ2WTF3LqDFJF0sjyKTgz4Vs9sxIZi7J7ZwQ4lHInlB+4tH1wSkPzPEwyAtUOF/Sqi51DdYsPX0DtfN8PYTj0I9FsHrSb5Tu7VVC0dZWWyupLEQIx7z5gF6zox0SJjs8UChcuj+DuireSc6d1gyxCPabQWGeBicRpi8LjwqR7sPiIhHePDg6UpGd6x4ZBTYMROkx5F80yNseZSXa/FIRqer263FAuizPNJFPNxuKJAo8QjnDvNNbNbisHgUuuvh6qux12wBDMvDwCAuzF4XXrOt7314vEdPexrUMiECAfjSl+Dxx0feN1lk9hMPS7GuHYKO5NYO3d269Rp2W/l8yZmLayi3VTqIR2cn5BPltgrVvBOdeDIsHnNW/xpWrcL60P0oZVgeBgZxkdHtxpeR2/c+3HHe254+bqvXXoPf/AZuumliQiEBMnuc9JituhebiKgGO5P7XMIJGcqKA5SV6ptLRr9HjHhUVBCw5aWN5eFwQH6go29u+LBA5wa7EkpKOFbC4pFftx0AtXMnNlti4m1YHganLRafC58lYnlkFocGxXWmQS0T4u23I+snTkzMNa29TnwWe997U34oZLcr+eJhIsBHfvZu3v8THdiYjH6PsHgEsnN1YsfC4rQRj85OsPVGiUeo5p3o/FZh8bAd2aVXDh0iLzdgWB4GBvGQ2euiJzMiHuHxHuH0HOnA4cOR9Yma6tPa04XPmhfZME61Q2srLGYXxQfepnjHGmZzKCni4XZr8QgWlQCgiorSxm3V1REgu7drgOWRT+eIYz2CQZ1E8j/+Y+zl8Hj0WJispmN6iHhPD3Osx+N+RiKG5WFwGmPtdeHPjLitwuIRdKZBLRPi+HGdeA4mRjz8fsgJOOm1RiyPvvEeruRbHhcQMa3OZlvS3FbFtEGxFg9TaXpYHt3dYO0J5fEIi0eo7yOfkWcTfOcdnb7+xz8e+4BKrxcqCOWGec97AJifcSjuZ9Tdrfvj7HbIyoLMzDQXD6VUrlLKnMzCGJy+ZAXc+LMHuq0YRjzq63X/w96941y4EO1HOlnbuZT7M+6mtnb8r+dyaRdKICdKPEJNS7M7ubVDSwssYjditSImE2eyJ6luK1UasjxC4pGMzvix0NkJhXToN4OIx0gjtLdsiay//vrYyuL1wlQa9JsLLgBguil+yyO8XzjENy8vzcRDKWVSSn1SKfUvpVQLsB9oVErtVUr9WCl1xvgV0+BUJyfgIhAlHsqu14drYf/61zry6e4JmBpMBM49/g9mOHbw7/4f0XA4gZl6RklXlxYPyR1oefQNHkwSra0wSx2BhQtRs2ax1LI3qW4rU2kxoN1WxSo5bqv//V944YXRHetwRIlHOFQ3MxN/ZnZc4lFbC1ar/jrefHN0ZQgTIx7LlwNQJcfjFtjwswz9NCZMPBJJT7IGeBX4FrBbRIKgp4gFLgF+pJT6h4j8b/KLaXAq09sLubjoyIm4rcjOJoAJ5R66lnlhlTCf/ax/Yx7BoAnTODphT56EZf4Nfe8z9u8Gzh2/CxLqBMWJ2KLaZeHxHkmeore1Fc4wHUHNWAgeD3OO1/KnJFoepjJteVBcTL44cHcFgNE7Lg4dghtv1OtOZ6TVHS/NzYNYHoA/N5/8ns4RR8DX1sKcOVBSAps2JXbt/sSIx8yZUFHBVP+xuAW2X+5MbroJqqrGVqZ4SOTvtlJEfiAiO8PCASAi7SLytIh8FPhL8otocKrjdmtXQdBeENmoFB6TDbNn8EoyGIRzdj/OPhZym+O/qKkZ3zIeOwZzqMFn1y3okvptSb/GU0/BJZdEwmbD4hGeywOAnBwCmMj0Jrdp2dwkTAvW6cpr9myqA4eT0ufhc/aQT5euZQGKizEh0NExpvOuXh1Zf+edxI9vbBxcPAK2fPLpHDH9y+HDMHs2nHce7NzJmKKzvF6oUg2I2awH2lRXU+6LXzz6Wx7f/S587nOjL0+8xC0eItKbjH0MDPrT1ezFig9VWBCz3WuyYe4e/B/U0AAf6f0zADfyZMwseOPB8eNaPNzvuoKezFymu/YkNT+TCNx2G6xdq8eSgBaPQjpQRZHKDaXwZtixJDmFhv9EM1bp1uIxaxZ2vwNf49inpDN1hEaXR4kHgMkxtnO/8452GykFb72V+PEnTgwuHkH7yOIRDGrxmDVLe5l6e2HHjsTLEMbrhWnmBtSUKWAyQXU1Jd7RWx4TxYjioZS6XCn1G6XU0tD7L41/sQxOJ7qO6bTY5pJ+4mGxYxlCPGpqdGgpwGwO07gxSTnEh+BEbTfTOE7W4rm4ps5lHgc4dix55z9yJDKuYt06vXS1esmmG3NpUcy+3RY71p7kWh7WxiN6ZcYM3aQGbM1jjwoYIB5F+l4snSfHdN6DB2HFCpg/HzZvTvz4Q4dgelbItIqedTQvnwIcwzYMGht1hFPY8oCxua68XqhUDToXPkB1NYXOY7icEtdg1LDIFJ08ODolHSXxWB43A3cCn1ZKXQosHd8iGZxuuOt1CzCzrDBmu89iI3OIVBHHtrdTSQPu930UAP+m5LuRovHsPowJIeesOQRmz2MeBzh6NHnn3xUaH7ZsmR6MGAxCT5NunVvKY8XDl5mHNYkpNEQgry0kHiG3FUBJVy29Y/Ql9IlEWDzKygDI6mod03kPHdJ9DmefDdtCX72IdmfFYxHu3Qvz8xu1JZSZ2bddFYxseYQj7WbP1n0L5eXw3HNwzjnwiU+Q8OyXHg+U0xQjHpl+LwXBNrrjiMtwOsGMnzM+/x648EL9cCaAeMTDKSIOEfkmcAWwfJzLZHCKcOwYfPGLjOhS6m7Sloe1Itby8GXayeoZ3PJwb9wDQPZnPg5AVs3uMZZ2BEKdKmruHLKWzGMGddQfSl7E1a5dsJid/Lzyf/A5fdTWgrdet9pzp8WKR4/VjrV39OIRCMDXvgb//d/6fVcXVPrr9JsZM7Q/BpjF4b7+l9HSJx4hd1VYPHJco++N7+rSVtoZZ2jxqK/XAQ2//z2sXAnf+Mbwx3u9sGEDzLE1RirsEKqoYETxCA8WnT1bu81WroSXX4atW+Evf4E33kjsftxuKAvGigdANcfi6hpyueA8NpJxMmRJPfdcYgUYJfGIx7/CKyJyN/DE+BXH4FTiZ7ce4r2PfYoHPz+8Q9jXpP8hOVNjxcOfZcPqH7ySNO3VYmG68AJO2qZT3LwnCSUeGmt9qEd+zhxs58zDhODanrwW3q5d8JTl01z0/F18jV+ybRt0N2jLw1pZHLNvIDePbP/o8y/985/wq1/Bd76jW+3NzTCTI3jzynRK/JwcugsqmE3tmMN1s5yDWx65rtH3xocb1mHxAH0fTz6p1//xj+Fzj735pnY7TbM0DRAPc1F8lofZHBkw+qMfwe23w0svaSPm+ecTux93p5+iQCtUVOgN06bpBcc5GYd3z+mEMwn9/i2WiN9znBlRPETkWQClVEno/S/Gu1AGpwaXv/IffIo/8Ym3v0Fn59D79Z7Uloetqp94ZNvI9g9ueeQf3407Iw+qquisWsQZ3btxOJJW9AEUttbgzCqGwkJMC/S8FJLEYebHdzmY26sF8Xr1FFu3gr9ZWx6qONbywKYnhBptwNLatZH1P/9ZBwPMoI6eypl9233TZidFPLLd/SyPrCy8WfnYvS0Ju3fChMVj9uyIeLz8sh6sV14O7e26D2koXnlF17F5znqYOjXmM0txPrl48HYN7a+rrdXGgcWi31dWwk9/CldcoftAonOgxYOlo0VHoIXFI8ryiEc8XC6Yp2qQzEy49tqx9d4nQCKhur8bt1IYnHL4fWdWAAAgAElEQVQ0ngiyonstAO/mdba90DTkvipUQ+XOLIvdbreTG+zC74/dPxiEKsduWssWgVLImYuYz3727xqfYD+fD6Z6augsCY23CKUWzzmWHPHw+6Gk5m1dgVx8MctlIwc3OlAnQz6jcKs9hCnfTh5dcVUsg/HGG3DxxXDZZfCvf+nKcCZHyJgTEQ9mJ0c8crrb8FpCeTNCePPKKaN51KPMDx+GbDyc+Z8fpuj7t1E9Tbj/fv27+Na3IvsMxauvwsoVTkwNJ/q+yzDmIj3KPNgxdGunthZmzRS4//4B+fmXLYPt20nIKrQ6Qv+NsBVUWkowMysx8cg4hJo9G5YsgaNHk5NPfwQSEY/TdyJpg4TZ9+xBiujg2Pu+hAnh5DNDD8M1tTTRTRamoljLQ8rLKaWVk82x/8RjR4UFsgfv7EUA5F+0mCx6qF89Pgmnjh4NjfGYPkdvsNloz6mkqDU51ztyBM7zrydoMsNdd2FCyN78Bjltxwkoc6RFGsJUWkwJJznZmnheeKcTtm8N8h3139xd9Ch79sCaVwNUc4ycBTP69staMJtKTtB6fGz9OnbfSTzZseLXU1BGGS2jtpwOH4bbcx/D8q9n4aGH+MrslwFYuBA+/OHIPoPhcmkX14cXhL67BQtidwhFg6mOoUOJDx2CT8mTcOedekRelCm3bJnuAE/EKLU5G/VK+HtWimBVddzi4XTCHKnRfrxF+j8xETl7EhGPCZrBwOBUoPMFHTJY+v2v0a2sZGwaOoQws62R9swK3fsYhblqKmaCtO2Lbf4eeaeZEtqwnK3/KMWXLwOg+62tybyFPo7vczGNekwL5/dtc5TPY5r3wIjZV+Nh3z64iDfxzDsbLrkEv8XKMudazI3HceRM7ZtdMUzGjCpy8NJZl3jt+847cLM8xuVrv8PKv36ZS1nNlr/Wkkkval6kFZ61cLYW/c11+P3w7LOJJwAMBqHI34LXFisegZJyymmmfZRDPWpr4eOmv+qKsqiIW3Ie54IL4IEHdPSTxTK0eOzfr5fLTaHkVOHKNkyoT8bSPnifTFubdoutPPY7HVxQWalH5YU6WcJutO3b478fuztkeUQ1Ekwz4hcPtzPI9EBoyPuZZ+qNu8c5gATD8pg0+HuCHHmjng33rWH1DY+xasW9rJr2ZZ6deyf71zSmungDsG57m05zIdnLF1FXdh7Vx9YP2YmZ3dVEV07FgO1ZM7U/uutAQ8x2x5v6j1H0Hv3HN82fi8eUS86+LYwHjg26xrEvj7RSfTN0uG798bG3qQ7s6uE8NmK5+EKwWnEvvoD3spZpHMdTPG3A/jlzde4J1/76hK/1xhvwZR4hMG8BUlnJvVn/j7MI+cjPOqtvPzVbR1w5t9fy7/+uW/Tnn8+II6+jcbuhjBZ8+eUx21XZ2CyPpkMuFrnegQ9+EK6/noI1z/DWi11c1fs85soKfpB7Hw0Ngx+rG+TC/I1P6B7vM/ql5CvXZc1yDC4eBw/qsNqqw6/DZz8Ld92le+DXrQOvl/kzfVgsiXU75HcPIh7Tq5mu4hOPzJMNZItX38vMmXoy9D3jG0ACieW2+ta4lcIAgEBvkPqNDTSvP4RrWw1SU0N2/SGKO2qY1lPLTLxEeaVpzyjF7u+g7op/4jm5k5x8S8rKHo0IzGx6i2NTzmexyYRn6YUsfunH1O31MPPMnAH7F3oa8FbNGbA9b74WD3dNP3EMBfYXvmexfm8201C6lCmNW/D7+ybdSxq+7TrWuPBdEfHIWDiPwjUOdm9vZdbssqEOjQvvW9vIwQuXXQRA9vvey9lb78FNLp0zrxmwf8FiLSjOffXAkoSudfzFPZzDVvjqz8Hr5aK776Y3OxPpzUAtXBjZMTTWw3S4hp8/qHVlxw7dwX7zzfFdy+mEcprpLDonZru5soIS2nA0dQPWhMrf2wszj79Ohvh1p01uLjz8sH7dfz+cPMkd6ntcX38LUDDg+MOH4TqeJnvbW/DoowOs3bB4WLsG7+w5cAA+yPMoET2hxxlnwA9/CNdcAz09ZBYWcsXsN9ixY3Zc9+P3Q6m/EW92IdlR/UJUV1MhjbQ39wLD/68LToYiCObM0Vbq0qXxDXYZI4mkJxl/O+g0IOAXjr9zgs0PrGPtpx/jteV38daUj3Agawm+TBvTL5rGeXddwqV//hIXbfk5FY79dBXPYst5X+GtGx9m109fpXXjEcTXQ1FvC3u/+2fm+Pez5b9fSvWt9XF0h4P5gb14l70LgKJrL8aCn0N/GNjv4XEGmBE4hLdyYFLmihU6FrJ7T+xI5/yaTZzImtmX5hvAv+JCzglsZPOryQ+5yti7i15lwTw3UiHYztERV87NY+/3yNu1Xq9ceCEAmVe8FxOCHRelV5w9YH/TrBkAqEOJJfTq7oa52/5CUJng+uv1IJzsbC7xvoB697t1vo8wpaX4q6ZztfU17jzzX2zNOI+HbXfy4qr4Q6S6HEFKaSVYHCuulrm6CeSvTXyU5bFjcKm8it9i1c9rxQrd2XH33VqtHnkEi/Qy9/CLgx5/ol74gfke7d4ZTAVLSgiiyHYObnns3g3XmJ5Hpk/XLq/sbJ2U7IIL4NOfBpeLHzhvj9vycLl0SK67oDL2g+pqTAjeQyNPWVnqCP0OwlbU+vXwyCPxFWAsiMiYX0BBMs4Tx3WuAg4Ah4C7h9v3nHPOkVQR8AelfuMJ2fKTtbLmxsdk9fK7ZP2Uj8i+rCXiIkdEN85FQLrJlNqs+bKx4oPy+vI75M1P/Up2PPCKNG+sk2Cvf8Rr+b094lD5smbOFyfgzuJjzX+sEgE5+PCrIiIS6HKJD4usWnzngH13PnNIBGTTV3478ETBoLSZS+SVGV/o29TbK3JEzZCtcz4Ws2vnS2+LgDyx8vGk3kswKPJ2xkVyqHRFzPaeA4dFQP6y8tExn//ZjGulJW9WZGN3twQLCvRvZP/+QQ9qzyyTp/M/l9C1Xn4pKHuZL61LLols/OEPRcrLRV57beABt98e+a0WFoqA3Gr/Q9zX2/LySRGQ3V/8Wcz27tfWi4D832dWJVR+EZGXXhLZySJpX3ZZ1IW2iFx+ucif/yzi94s3I1d+k/v1QY+/8/x1+n5+//shr+GwlMjfSr486GeXXuARrylb5NZbBz/4hz8UATmbLdLcPPL9HDum76furA/FfvDGGyIgNxU+M+I5fl3wH9JjyhTxj1xfxAOwWeKoj0c08JVS5wAfAB4E/MCZ/V6LgFwGsxGTSGjiqV8ClwP1wCal1HMiMkFTAcUiQaFpexNNb9Tg3FqD/8AhrMdrKG6rocp3iEo8hNsSPVioz5xFW+EctlRdhmneGdjPnkP5RXMoP3caszLMzBplOcxWC7VFyyk/PooEP+NE76vr6CWDmTecD4DJnsvBkncxa9+/CPh/hDkj4ipoeWUnAGUXLxh4IqU4UbiI0sZIM27n0zUskzo6Lvy3mF3zVp5HQ/4CLnr1+/zfd8/luu8t7IvDH4pgkBHTuO/b0MVS/yZqzr41ZrvljOl0WoqxbVkLfHH4kwzDiXphhX897fOvpC/DUlYWav16PXpv3ryBBylFx/SzmV/zDs1NQnlFfN2RO36zkcvZT8/no4Zgf/vb+jUY3/62dvJPnQo//Smt8y7i5oaf0dz82bB3Z1h66rXrR1XEWh5ZC/Sv3XQk8dxZdW8c5wp24/rgZyMbly3TAz1CNFUsZUH9FkQGeqXmHHmFgDJj/uhHh7xGV045du9Ay8PphOpNT2MNeiNhXf352tfw//A+7vT8mB07/o/LLx/+fpxdwkyOcGLqytgPli/Hn5HFoo7X8XqvITt76HNUeWs4mTeLKf0CK8adkdQF2AycAziBBuAV4BfAV0Pvy+JRqbG+gAuAl6Lefwv41lD7J8PyCAaC0rS9UbY9+Lqsu+m38tr535L1ldfJPutZ4iQ3xoLwYZHazHmysfxqWbfsdnn9E7+UbT96SU68eVgCPclpEQzF2vPvEh8W8Tl943qdeNmRs0J2510Qs23zLb8RAXnzB7Et3NWzvygucsTv7h70XG9f+X0JoOTwW40iIrLq3O+KgHTuODJg366X3xanOU8CKHm+6EZxtvcMWca/f/YZWaPeK09c8CsJBoe+l7+v/KUISPM/1g/4bOu5X5AubHJ0d9fQJxiBN39/UARk3x2PJHTcsW/9SgTkkWn/Jb8puVt+mfF1eWjFE7L9xcZB92+s98tr5pXizCwU6RpdeQ9++X4RkDeeOBzX/m/8YI0IyIGHV8d+EAyKR+XIs7NuT7gMv7/gEf2f27NnyH22veur0kG+dLQP/GLfsrxbDpcuH/Yau6uvku3mswds/8OjPtnBYnFPmysSCAx5vPur35RezPLIt44Mex0RkS0vNGvr7MsPDvisaf7FspNFsn/fMD9QEdmlFsvu2R8c8VrxQpyWRzyV9oPAn4F1wCbg41GfHYnnIsl4AdcBj0W9vxF4aKj9Rysetf/aJ+urPib7rEulC1uMQPSQIYctc2Vj2dWy7uxvyLrrH5It/+8lqX+9VvzdvaO6XjJ44+bfiYDUrT6UsjKEOb7+qAjIust/ELPd1+GWhowqaTJVyLrL7pU3r39Q1r37O+LDIm8tuHnI851YvU/8mGRzwaWy7l13i5cs2Tz9I0PuH2xukT3v/6YIyKvvf2DwMr51TDxYpYcMEZCN/7NmyHvpxC57yy+WwRSm8bmN+jrn/MeQ5RmJlz/5exGQ1rW7Ezuwq0saSxfr36WyiNcS+a0eyF4ib1ddJ+tn3CBvzbhBNky5Rg5mzBcBafjew6Mua9PLO/T93vRkXPu//rU/69/lvwbe2/785bLJ9t6Ey7DBfqmcyJ416PcR5p3rfyICcmzbyZjtPm9A3GTL2yu+Mew13jr3NunCJsFA6BrBoNQ/+LTsMp8lAhL4+wiupOPHpYcMeXHe4K6zmLL+9C0tHvc9P+CzQ998WARk/c82Dnm8v0ff01vn/9uI14qXpImHPhc5oWUR8BPgbeB9wOF4jk/GKx7xAL4UspQ2V1dXj+rB1a7aL4ctc2Rj6ftl7dKvy7qP/UI2/X8vytHXDkmvN3UCMRxbH3hNBGTL/7w66Oe9rm7Z+4tXZeu3/yrbvvd32XXfP2Xvz1+Wg79ZK7VPrpejT2+Shhd3iKemftg/5Yj4/fLOvM9IDxly/I0jAz6u/ccO2Z1zbowgby14rzgOtw172jdu+GWfpbep6HLpqGkdsShb8y+Ww5lzB/3szQ/eJwJy6Lk90qzKZcO0jw6637bK90sXNjnx5tAt7XVzbpZezNL0/NB/8OF4c/7npUMVSNA/dEt2SHw+kX379DIQkK51W2XN++6TzQWXySHLfDmScYYcyZgt+7OWyNaSlXLgnj+Nqoxh/D6/OMmVt84Zwt/fjzc+9nMRkKZdLQM+W73wVnEqW0J+evc7O0VAXnjPD4fd7627ntEi+uSGmO1NG+pEQNZ+cngrb/WHHxQB6TrQICIirpu+pn8v5jlS/7On4irrK1M/Ix6VI9I4uCUYZuPNWiAOvlI34LPmmk5xkiu7L/jCIEdqunbpe3rpusQs1+FIqngMOAimA08CbuCS0ZxjFNeccLfVZOHY60dEQF6/6bEBn7XtbpCjmbNjKuzhXketc6Rp3SCdtFHs/faTcij/bGmxTJX2jBLpNBeIy2QTHxb95z73O8Me7zjhkoadreJocMd9jz6PX7paB3dtDcaLV/1UBMSx69iAz3aUXCq7M7Vb4uUzviJulSPB7liXX/uLG0RAnn3XfcNe5+iODjnBFDlQdcmw+w3F4ZwzZX3B+0d1bCrYknm+7Kq4bOQdReTt99wpXrLE4x7YIHn6w0+IgPRs2BrfhWtqpHP22dJKsbz215PD7vrOY7tEQPZ8N1YsjzzyogjI6u+vG/b4f35zjQhIy2+fE3lCl/NB8zdk1/b4he4nXzkoPizS85nPD7vf7nd9UU5SJM1NA59RMCjyRMbntFXpdA56fOsfX9K/038f/p4SIV7xGNWszyJyVERuBC4E7lJKTUQax03AHKXUTKVUJvAJYGJyD6c5FedWEUQRODxwdqL9n/wvKnqO8dpX/sqOJ3ey7ffb2fTLjbz94zd58wdrWPftl1hzx/O8esvfWHXVg+R0d9B+zU1DXuvon99mwX/fiNctbCm9ivWVH2dd9WdYPetLvDD3dp77zN+4bP0Phi1v/tRcpiwuIX/KwDEfQ5GZbcZekjXyjuFrfODdABx7qt8cpSJMb99KQ5WexSd48SXkiIfmUMd9mKM/fgofmZzxk68Oe53qJQWsW3wbc+vX4K/pl43vySfhU5/Sw5IHw+ejynOAturJM0VOa8EZlHTEFyJsbTnOCarIzhnYoe+/9Ar8mOn6TRwzV//Xf8G8eVjr9vHFjD9w3vuKh909c77ukFf9hpkH9uqw6uhMAYMRWH4+3WSR/fP7kC9/mbXqvRz+yv0sOiv+Dul5H5jDg3ydjCd/F5lwpD8iTNn/Gu9wPoVFA5+RUrB+xqew9rpgzZpBT+HfrQewBs4YJLBivIlHYbQYoYb57JKR9knGC3g/cBCoBb4z3L6nk+UhItKiSuX1hbHhhcFev7SrQllX/em4z/PCFdpffHLD4P0nm+Z9StoolKZa15jKO97UH3RLACUbPnBvzHbvfm3mP3+19v1veEq/3/3VX8bsd7RgsbyeeWlcXrznHtCd3se++fPIRqdTAsokAuL8t+8Oepxvs3bD/O26sbmTJpKnzrxHAigRr3fEfWvK3iVvZA5ukW3dKvIsHxRfboHIj38s8vbbg5/koH623qs/KnPtDXL99SOX8dAhkVaKZf+lX4nZXvuBr0sXNtm4YfgvddMmkT9ygwiIu7BSymiS9QPjJYalvV0kD4f0WIYJ692/XwTkDusvB/9cRD71Ua94lVXkG4P30zRf80Vpo1BW/WsM7uZ+MA6Wxxql1G1KqerojSErwKSUehz47OCHJgcRWSUic0Vktoj8cDyvNdlwZJaR6YgdFVv79DYKpYPgVe+P+zxVn78SgEO/GaSlI8K02jXsmPo+ymfljqm8482U2TkcZQaWmtiZqJq36kFXOQtnADDnsmoc5NOzLSqdQ2cn1Y5dHD/j0gGhnoOx9GNz2M88gv9c1bet58XXMIkeUNf51OADONvW6XG3lqWLBv08HfGUz9TZf+NIdJXvPM7J7IHpVUDnI7zLdD/dphydYPCiiwafNeyppxCluHTXzznaM4XvfW/kMhYUQCNTyGiNzUxgajpBPVUUFQ//pU6bBl/hYdZc/zC3n/cW5inlnH/+yNeNprAQpp2Zz9aCy+DFwQcs8i89VdKGkquHPM/0eVbWcyGy7vVBP8/e+Q4bOY+8/InPHpWIeFwFBID/U0o1KKX2KqUOAzVoF9LPROQP41BGgzhwWsvI7jc7W+srenxE5bXnxX2eudcswEE+snWgqd215zjl/ga6QyPH0xmTCRpyzyCnJdaV5K7VeYRyZuk8QoVFilrzPLKj0quHZym0nHsW8TBtGmywraT80JuE521t/+MLOLHxS75KceOuQXN0u3bocQ5FKwamZklbQmnDAyeGTrEPgN9PkfcEnfbBxcNq1TnJPrGiTmcrVAqeGGSeuXfeoc66gIPuSl57TQ8mH4n8fC0e1vbYBFeZJxtoYCqFhUMcGKK0FLoz8/lb8S387+vVXHvtyOOBBuPCC+Glrgt0Gt6uQeacf/FFjuYupGfK9CHPMWcObJFlOldV/zmBW1ux1e3mbS4gPz/x8o2VRNKTdIvIr0TkQnSH+WXAMhGZLiJfFJHxnUTaYFi89jLyvLHiEdixGzc5zLhk5hBHDSQzS3HMOg/rsYMDPjvxmq5g884/c2yFnSBcBVUUuGKTB/Yc05We7YxIErqm/HkUn9zf9z5sEdgviN8iaF10CVa/GzZtAhGy173Aai6jZ94SPaiscWDySt/RJtopZMb8xPI7pRJzlRYPT+0IyTgbGzETxFlYPeQuV10Fq1+3cLJ4np5FaZD5WwNbt7Peezbf/Ca8K842S0YGtGZMJacrtow5HSc4QeWIFa3JpBPm/upXesraYcYTDsuFF8ImXyj/Wv8st93d8PrrrM26kqqqoc9RVQU7WYLq7dEDNqP57W9RIvyDa8nLG10Zx8JoO8x7RaRRRMZx7jaDROgpLKfIHzsqNvv4QY5lzcWSldjX3FE6lzLHQPEIt5RLVsSX9C3VdBdVUtzbRPRsUsGGJgKYKJjTN56bzinzKfWd0ImGAN+W3TixMfX8oSu+/mSsfC8A3lVrYP9+8juOsrH4fZSerWuG3iMDM+CaWxppoiKu0drpgnWGFl3v4RHEo65O71c69DP83Of0KP/SUlh1YgmyZ0/s/LEeD+aGevaykPe+N7FydmRP0anOw9MVBoPYnQ2czKrsn+F+UFas0MuKCj1x1mi48ELYQ6ihtX9/7Id79oDPx6ued4VnnR2UigrYQcgC3hkV1LFlC3z/+9Qu/CC7WJzelodBehMsKSNPuvC7IpP32JyNdNmmDnPU4HinzKLCf5z+U/gFag7TTRaV51UOcWR6EaioJIMA0hQRVdXSRCullJRHahD/LD2PRfCAjiKyHNzNXhYye078f4+F7y5mO2fhXfUavPACAM4L30f2HC0enXsHJrizOhppNU8ZMY1KOmGbXkwPFnqODSIejz2mJ9WAvtmQPNOGjgJatAhWrYKVK2HV0TNRDgcxudSb9ffWwFQWL06snJ25U8kI9kYi3VpbMQf9dNri++1+9as6we4PfzhgOpW4mTkTmjN0JCTH+kVC7toFwMbuxcOKR3k5HGAeAXNUnncRuOUWKCnhb1f/HlDYbKMr41iI+9+hlHoytPzGSPsaTDymKTp/UPuB1r5tBb4mvAVTEj6XmjoFE4LrcL+01M1NNJumYMubHG0ONS0078WBSMVtaWuixVQRk0A2a7EWj85N2trKbzpAXfYCchOICTjnHFjDJdh3vYXvz/9gDwuZu7Ka7DN0ZeWtGWh52Loa6bAm/v2kksIiRRvFBFv7hR87HDpL7ze/Cfv3E9x3gG6y+ubjHorLL4c//hFqCPX7RE8+3qRdjN78ioS+CwCXLfRcw+7CE/o30GWPTzzOP18fGm/6+cEwmaCiOhNH9pSBAQYHDhDMsHCIM4Z1WxUXQ9CcSWvR/D7B4cAB2LwZvvUtmnqLsdtHL3BjIZFa4Byl1FTgZqVUoVKqKPo1XgU0iI/MKTo9ufOInj1G/AGKAy34SwZOsjQSWdP1MSd3xbYuLa4OXJYRehvTiKxZuqLo2hupuLM7m+jIjH0mect0KmvXthpwuSj0NNBZFju39UgUF8Pu0kux+LvJ2vQmf+cjXHAB5M/SLXX/sX6zE4mQ723EaUv8+0kldjt0UIjqP5NTdA7yv/4V/54DHOIMCopHrtXKysATTkl+IspCC4lHRmXiz8idFxKPsCUTWrrz47ea44m0G4nqamjMmDbQ8mhuxldQThDzsJaHyaSfT13e4oh4vBSK3rv6arq6SEl/ByQmHr8GVgPzgS39XumT0vU0xVqlxcN9VIuH62gbGQRQUxL/49nn6j9e54HYiJosjwNv5rgmT04qtjmhzt3Dkfuwu5tw5sY+k2nzcjhOFYF9B6FGu658MxITDwDvBZfSkDENnyWXP2XdzFlnQWmZop0i/K39Klunk8ygj+68SdThga6o2inC1NXvfkLPjYoKePZZ1J5d7GPBiJFNYXLmDC0e1umJP6Puwikx5wif11uYuBt3LEybBkcDVbH3BdDSgiunrG+f4aiogP0Zi7X14nDo0N+5c2HmTDo7SUl/ByQWbfWgiCwAficis0RkZtRrtBnFDZJE7nQtHt31Wjza9ug/jWVa4uKRO1sf09vPr53t66A7e/JYHoVzSwlgoud4qAIRodDXhCc/9plUV8NB5mI5WoN/r3ZdqcFSoY/AohW5LPDv4uLqOkrPm4nFojuD2ylC+rfUQ53zpnx74jeWQsKWh6Wr3wTkNTWQmQm33QZbtmCpr2M9F1IUp08it7IAr8oeIB5BFOaK0qEPHAJ/cXnfOQBobCSIimyfIEpLoaGnFFpbYz9oacFhKUOpvujnISkvh+2BUKfPli16yturrgK0lqS9eIQRka+MR0EMxkbeLC0evY1aPJyhqVutsxL3qefN1n/WQEvsBMq23g56cieP5VFaYeYkJX0dr3R0YJFeeov6ua3y4FjmHPKbD+LcosXDtnTgzIYjcc450EU+G2pLWBmanqGgABwUYnb0q2xD04RmFKSgp3MM2GxaPDLd/cSwoQEqK+EjH+nbtJrLKItzht6KKYpGVTlAPE6qUmwFic8rbCnIxansEfFoaqLdVEJ23sRGJxQVQYO/FGlrix3r09JCiyqjooIRAyYKC2Frb0g8HnpIxw9feWX4NHE/42QzOXo+DUakcHYRQRTBUIXvDblq8ucmbnkUTs3GRybSFltB2AMO/PbJY3kUF0MTFWScjFQgAIGygc+krWQuNl87wbfe5hjTmDZ3mNl3huD88yPzp197rV4qBV2WIjI9sc8y0Kktj8zC9B6p3x+zGVwZhWR5+4mHw0GnqYCnds6He+9l29X/yW4Wxx2GXFEBx4KVBOsj4iGNTTRKBfZRGGc2GzQxJdJh3tREM6M711goKoJWSvWc5+HILxFobqbRX0ZlHF0wBQWwzzVN+7eeeQZycgjHLre2GuJhMEaybWbti27X4uGv1xVl0YLEzfTsHKU7RR1RFURPDzniIZg3ecTDYoG2jHKyOrTlER4gaBqkH8hbpfs4ije8wHaWMn3oQb9Dkp+vPQrPP09MaKnbUki2J9by8LRqy8NSOLksDwCvtZDsnq6YlrQ4HGypLeD668Hzze+x6gKdHDNe8Sgv1yG5waiR68GGJpqoGFWHsM0GDVKBhBoM0tREQ7BiwkNaCwuhhVDtHnZduVzQ3c1Rb9mwkUZQmMMAAB2SSURBVFZhCgrA0amQD12jN3zoQ5CTQzCYWvFI3B40SFscGSVkOELRVk1NOLFRVD26f0tXRhFmZ0Q8fE0dZAGqcPK4rQA6rRXkurQrylnTRDGQWT1QPPwLl8BGvb6BFVw5QifmUAw2CtqTXUR2Z2xLvbcj1Odhn1yWB4A3uwhcaId7sc5w29viwBEKt92wQXsK8/KICYkejrIyOEIFqjnSzybNzTQxf1TWQm6utjqlcTuKkBXD3AkXj7DlAUTEo0WHwB9yxmd5FBbqIVfuu3+AbdZM+PSnAejo0PptWB4GY8aZVYLVpcXDcrKRFvOUUcd/uy2FZLoirWVXvU4mYCqePJYHgNteTp63GUTorovNaxVN3qJqdqHTkWws/QBZ8Wd/H5Ge7Hyy/c7IaGeg16EtD3P+5LM8enJDv4GoIADpcOBANyx27NDikcjI+fx8XdmbvW7dMhfB1DI2y6OJCu22EkE163Olym0FDBCPOk/8bitAP9877uhTi3B3jiEeBmPGm1NCjleLR7ajiU7r6McQeLMLsUb5td31ej2jdHKJh6+ggqxgN3R10VvfRDdZ5FcPDE+prob3s4qrrGvxzY8vIWK8BLNtOhOt19u3ze/Qloc5b/JZHr3hoAlHJDuRydUZIx4tLaMTD0DXip2dmHp8o67wbTadHNHkckJDA8rno5EpE255FBREiUdINMLLZsopjSOQrGDg4wYgPF3JzPhT1yUVQzxOIXz2Euw+LR52TxOuMQxA68kpJNcXEQ9vo/7lZpZNLrdVX2hmczMS8qGXlg0c/TVzJtQzjZe6L+as5GoHfTVWKDwXINA1OaOtAPy5IfHt7Axt8GPxOnFQwJIlOgVTff3IIajRDBCPULN6LOLRd77QAMYmJr7Pw2aDNkKTV4U7zEPi0UJZXKHMQ4lHeGjNnBQlZTbE4xTCX1BCUaC1bzyDr3D04tFrL8Tmj+3zAMieOrksDymPVEjmVi0eJSUD91sUlUA32eIh4drP6ezbFuzSQmIpmHyWR8DWTzxC6cYdFHDppbquPnQIzkgg2jkvb2jxGJPbCmD79r5zTbTbymYDPxa6swsGuK1aKY1rEGXhQC8hoLOUFBYS91iaZGOIxymEFJeQSS+9J1rIl85BQ1LjJZBXRL509kXUhEdI51ZOLssjo1JbHr6jTWR2aPEY7A9rteoZY/Py4IMfTG4ZTPaBlkfQqS2PzIL4p+JNF4L2fuIRahIHcvNZtiwShJVIi3goy6OZ8jG5rQDYulWfNgWWR07o63Vnl8DJ0LiplhZ6cvLpISsu8RjK8njzTVi+PHllTRRDPE4hTGW6Sd30qp47QE0dQ9K90C820KFblYE2/cvNrZpclkc4T5fnSDO5ziYcWRVDBhH87nc6L1+yU6T3dYpHiYc4XbjJwZozCf+C4SHN4dostOzN1W6rMHMTyPCSlQXOzBICypx8y2P9egDqmDHh4mEyaQFxZsWKh9eue7lH67ZqaIC9e+Gyy5Jc4ASYhL9cg6HInKrFo/11LR5Zg4Skxks4JNd9Qv9ipb0DD9kUlCcxDGkCsE0vxo+ZnsP15HpPDtsPlJk5Ti6AkOUR7iQHwO3GhY3sxMcipp5wbd7P8ujJKWDBgshuibaK8wpMOLPLdYRUUxMBs4UOCkdteZykBL/FCk1NeAqm0k12SlKX22zQZYkVD2e2Fo/RWh6hGWx5f/wzTCcdQzxOIbKqQmlFdmrxGCwkNV4ySvQvti9Et7MDBwUJp8ZONSVlJloow7xnJyYEX8HEJyIMu6162iPiodyuSSse2TYzTmwDxKM3t4DMTJ38dfNmLcaJkJ8P7VkVfZaHM7eCjAw1qrDp3FwIYqa9Qk/G5CjW6fcmus8DQildMkoj4tHcTGdWGWYzcYlZRkboHFF9Hi+9pCMEz0zhpJ6GeJxC2GZoyyPviI4uyZs/+gyilhLtmvA06grC7HLQZS5MSprqiaSkJOTrPqATP3eXjnL03xgIu63CAwMBlMeNm9zJKR7Z0Ek+QUdIPEIiEg7hXbRI5/lKlPx8OJkREQ+HVbusRvObC1fKzWU6EqKxbGnM9okkNxfaTSHLQwRaWujMLCMnJ/57KyiItTx27tQz96by/2iIxylEODni9PZt+MhkypLEs5GGySrXFUF3UyhE19WBK2Ny9XeAFo9myrE6Q2lbpsY/tWyy6BOPKLeV2astj3hHYKcTOTkh8Wjv12FuH1swRX4+NKuIeHRkjq6zHLTAKQXrl34NlizhnQWfw2QiJWIddqHRrccbcfIkjsyyhL77aPHwenU0WyqtDjDE45SieGYevWRgwU+DqiSvYPRfb85UXRH0ntQVRJbXgTdrckVagfYp93WcAqp64i2P8FiOQJR4mLonr+XRJx4dEfEIosbsE7LboUkq9PD0o0dpskwb9URHJpNu8R/MWw47dlBjX4bNlpqWus0GLcFQfPiBAyBCW0Z5Qt99tHgcPqwNmFHMGpBUDPE4hcjJVbShf6QnrdPG9EfJnardVv6T+hebM8nm8giTkQFdVt3P4SIXW9XEC6A1P4teMvrGdgBkdE9eyyPstpKoPg+XKY/s3LFVJ3Y7nAhU6Fhfh4N60/Qx6ZHNFglwc7lIWX9dTg40B0LisXcvACfNo7c8womC40ltMp4Y4nGKcTxrNgCthWMbdmqv1E2+YLv+xdp6OyJpKSYZJwq0fd/A1EFHl4832TkKFzaCnZFBghafm25T7qTrQ4KI5RHdYd5JQd+YhtHy/7d37jFy3dUd/5x9zcw+7I1f8TuOVZM0RiFx3YggAkFEJQkRLtBCAoIEGkJEQCRSixwF0fRhUUp5CAhtg4iAKm2SqglEPNpglDZ/tAYSywl2nASDncTGazv2Pmffu6d//O7dvR7P7O7M3LmvPR9pde/MvTNz/LvXv+895/f7ndPVBa+Mz3qJL+vGukqslopHHIPl4MS2Z8oLIfviIatq9jz8nFarY65gnBjxEJE/FZEDIjItIttLjt0tIodE5EUReUdcNqaBk8svAaB/S32rh5Yub2GALvd0OT1N53R/qmp5BHluwzvZyzbu5V7WRluFFHCdR5EO1CsABdA6PsRoS/pSk8Cs59E0OCsefXTXHYLr6oLDo7Nrk347uTE0z6NYjGewHNwC1J5Jz/M4cACAE1qd53Heeed6HnGLR5JSsu8H3gP8c/BNEbkEuBHYCqwFdovI61R16tyvMH7xzr9i37dWsvkDH6jre9ra4KQspWmgDwYGaEKZ7k6neOTWLOMPeAaAz9axbrJWfPHoCIhH20SRsVzK5j17+J5H89CseJzRcDyPZycvmXn99MQbuKpO8fCbPM6wVaEAxyc88fDybP2OtVV7Ht5zHD097hrE5Un5JEY8VPUggJzrx+8AHlLVMeCwiBwCrgD+L1oL08FffHkND12xi/d+uP7vGmzupmWwj8lTvbQA0p3OsFUwl1U1yfrColCAYdrp9Huy6Wnyk0XG43oUrpP2dpfHqml8DMbG0L5+enVTKOLRyzJGPv5pCgWh59uddYetznhVBYaGWFAG20aQz8PJsaWuDOOxY9DRwWvjS1hRRe3x7m4nHENDTjxWr453mi4kKGw1B+uAVwOvj3rvGWXo7IRbb61+gVY5iq3dtI70z6wyT1stDx9fPHK52dW6UeJ7HjLiiYeXmn2iLZ2ehx+2AqC/Hw0xbAVwYudXmf7SV+oep+joOHvMI86w1fBo00zhLNatY2RUqh4wBxe6On48/pAVRCweIrJbRPaX+dsR0vffJiJPi8jTp/wMlkbNjOaWkh/pm6nl0boqneKx0VvaUc2irDBpb3fi0TQSiKEAE7l0eh6l4uEGzJeG4nmASz5cLLrpqGEOmMcpHpOToOu9aeLr1jE6Wt2ak6B49PTE40GXEql4qOo1qvr6Mn8/mONjx4Dg5Pz13nvlvv9+Vd2uqttXxuWjZoixQjeF8b6ZhYL+wsG0cdVVbnvDDfH8vu95NI964uGFr6byGfA8enuRwYFQPY/Bwdns9VkYMPfbZWqzNwPyoosYGVl4iV6YFY/e3kXqedTI48CNIpITkQuBLcxUmzYayURHNx2T/YyfcJ5Hfk06PY9LL4Unn4RvfCOe3/fFo2XsbM9jMp8Bz+PVVxFV+kKaqgtni0dWPA+A0bd6E0WvvLJmz6Onx3kfJh4BROTdInIUuBL4kYj8F4CqHgAeAZ4H/hO4w2ZaRcN051K6pvqYOJnOWh5Brr66vo6oHlpaYEQ6aB072/PQ9nR6Hvl8QDxefhkgdPHw6kvV7XmMj7vmnpiIb7aVLx59O26G/fvhQx9iZKQ28XjxRbdNgngkabbVY8BjFY7tAnZFa5GhS7tpYYqm48eYpJkl62KeG5hixlo6aJkYdi+8x+Hp9gx4HkeOACQ2bAUu20nwddT47TI6JrB1K+qVs68lbHXwoNsmQTwS43kYyUO6XQfRdvS39NHN0u4ULodOCBOt7bRNeKPA/pTdtOW392hthaEmTzxeeQVonOdRb9gK4hePmbDVqNtOTLjboBqx9etv+eIRd2oSMPEw5qBpmXvc6ej5Da+xIrawTxaYaOugCXU9iB+IT+k6D4CJgnczHD4MhC8eYXoefjqPpIiHN1O7Ks+judkJqZfdZPHNtjLSRetKJx4r+g9xpnllxfKtxvzMrOkoFmc8D+lMp+cBkGtvZrS106V4xaUcrzds1dbm/sL2POIWD79dfNHwRaTa9lq2zHktzc3xLXgMYuJhVKRtpRe2mh5zNZiNmjlLPDzPo2lJej2PfB6GW5fO/FtOs7xuzwOcpxGW5+FHBeMWjzA8D4BNm9x29WoS8SBn4mFUJL96dnbVcLuJRz3MrOkoFpkadJ5HU1d6PY9CAYot7uFiorXACO2h1CYJikdLS/UdbJBSzyPu2Val4lFte114odtecEE4dtWLiYdRkfb1y2b2x7oS4CenmLPEo2+IEfLkOxLw+FgjhQIUm514jHgPFmF6HgMDbr+ejABJC1v54lFr2Mr3PDZvDsWsujHxMCri10QHGF+WgLmBKWa6EBCPgSJDdKayiqBPoQCD3oyrYsHlbAqjsFXQ86g3a6wvFkePum1ceT39dvE9jlrDVtdf79rkppvCs60eErPOw0gewam5Q+tirnmZcrTgPZYXi0wPDKW2BK1PPg+9TU40+gtryOdd6dd66epyKTgGBupf1OmLx6teWtXzYkqQUCoetXoe27e7VGJxZ9P1Mc/DqMiSJfAw7wNg+HWXxWxNuplZTV4sMj1UTG0JWp9CAQ63uFxNpwvrQwlZQWM8j1OnXEgtl6vfvlrwr/PYmNvW6nlAcoQDTDyMOWhqglv4DhdwhBVbz4/bnHTjj9YOD6OD6fc8CgXYk3srAHvXvLMh4lGv59HaOhuqisvrgHMHzGv1PJKGiYcxJ6MUeIUL2FJfSfRFz8yaDm+dRxbGPJ5quhoGBvjflTtC+7eUDpjXi78eIk7x8D2eeqfqJg0TD2NO7rsPtm2Dyy+P25J0MzMtt1hEis7zSHPnUSh4nWBXFyMj4cy0glnx6O0Np8Nftcpt4xSP5mbnBZWGrdL88AAmHsY8fOIT8Mwz4XUOi5XmTq+nKBZpGk6/55HPz3aCw8PhdYRdXbN1usOYHeWLx4qYlynl8xa2MgyjBnKFJoq0Mz1YpGkkG2MewTBMmJ6HTxjegi8aca+NyOUsbGUYRg0UCjBMO1MDRZpH0+95+OKh6jyPRohHGJ7HxRe7bRI9j7SLh63zMIwIyOddNcGuwSJto9kY8wDXEYYdtvIJw/P42Mfc4Psdd9T/XfUQFI+RETcGkoT8VPVg4mEYEeCLh752miadTr3nEVz41qiwVRieR1cX3Htv/d9TL6XikeZr72NhK8OIAF88pOc4AAMsSXUHEkwzHmbYKri2I84ZUmGTy83Otqq2fnlSMfEwjAjwxaP5xO8AV8Y1K2GrMJ+kN2yY3fcTAWaBUs8jzdfex8TDMCKgUHDi0Xra1UQtNi2hJcVB40Z5HucHEhn402yzQOmAeRY8jxTfvoaRHvJ5OM1sQYmxXLpr+vqdX3+/W5cRVmcoAjt3uu9MUh6nesnnoa/P7WfF8zDxMIwIyOfdVF2fsfzSGK2pH7/zO33abcNcRPr5z4f3XUnBBswNw6gJf8zDZ7yQDc/jzBm3tQwEc1M6YJ4Fz8PEwzAioFCAPmbnnk5mTDyy8CTdSMzzMAyjJvJ5OMVsKd+pjmyIRyPCVlkkiwPmiREPEfmiiLwgIs+JyGMi0h04dreIHBKRF0XkHXHaaRi1kM/DSWanD7W0t8VoTf34YRfzPBaGTdVtLD8FXq+qlwIvAXcDiMglwI3AVuBa4JsikvKF/cZiI5+HE8zOQ017Z2ueR3VY2KqBqOoTqjrpvdwDrPf2dwAPqeqYqh4GDgFXxGGjYdRKoQAH+X0AXmi/PPWdh415VEcuB5OTMDVlA+aN5qPAT7z9dcCrgWNHvfcMIzXkctDDGh5+/6PctfaR1He2vv2nTrltGFX/skywjnlWPI9I13mIyG5gdZlD96jqD7xz7gEmgQdr+P7bgNsANm7cWIelhhEufjW5fRe+m5d+CVem/MmztdUt4vPFo7MzXnuSTjCRZFYGzCMVD1W9Zq7jInILcAPwdlVV7+1jQCDjDeu998p9//3A/QDbt2/XcucYRlz4ce8sdB4i7t9g4rEwfPHo7z/7dZpJTNhKRK4FPgO8S1WHA4ceB24UkZyIXAhsAX4Rh42GUQ++eGQlbFEouDg+mHjMhy8Wvb1um4Xrn6T0JN8AcsBPxSW12aOqt6vqARF5BHgeF866Q1WnYrTTMGqiUJitf5GFJ0+/A2xthbZ0zzxuOLmc2/r5rbJw/RMjHqr6e3Mc2wXsitAcwwidfD5bMW//32Bex/z4YuGLRxauf2LCVoaRdYKZVbPQeZh4LJxS8ciC52HiYRgRkc/PLqrr6Jj73DTgV/0z8ZifLI55mHgYRkQUCtkSD79MrInH/PhjHiYehmFUTdY8D188lqa7NEkkWNjKMIyayedhcNDtZ0E8li1z2zVr4rUjDdiAuWEYNRN82syCePj1xrPwFN1ozPMwDKNmgk+bWRCPiy922yz8WxpNaQr7LGQhTsw6D8PIOlnzPG64Ab7yFbj11rgtST7+gHmWxrxMPAwjIrImHi0tcOedcVuRDvxrn6X6Jxa2MoyIWBKoPJsF8TAWju95ZClsZeJhGBHR3T27b+KxuGhqms3/lc+7FP1px8TDMCIiKB5ZmKppVIcfusqC1wEmHoYRGf6iOnD1MIzFhR+6yorXaeJhGBHhL6ozFie+52HiYRhGVWzdGrcFRpz4OcCyErayqbqGERHLl8NHPgLXXRe3JUYc+DnAsuJ5mHgYRoQ88EDcFhhx4U/VzornYWErwzCMCPA9j6yMfZl4GIZhRIAvHqtWxWtHWJh4GIZhREDW6p+YeBiGYUTA+vVum5U1PjZgbhiGEQG33AKHD8Ndd8VtSTiYeBiGYUTAkiUuhX1WsLCVYRiGUTUmHoZhGEbVJEY8RORvROQ5EdknIk+IyNrAsbtF5JCIvCgi74jTTsMwDCNB4gF8UVUvVdXLgB8CnwMQkUuAG4GtwLXAN0UkA9nwDcMw0ktixENVBwIvOwD19ncAD6nqmKoeBg4BV0Rtn2EYhjFLomZbicgu4MNAP/A27+11wJ7AaUe998p9/jbgNoCNGzc2zlDDMIxFTqSeh4jsFpH9Zf52AKjqPaq6AXgQ+GS136+q96vqdlXdvnLlyrDNNwzDMDwi9TxU9ZoFnvog8GPgL4FjwIbAsfXee4ZhGEZMiKrOf1YEiMgWVf21t/8p4K2q+icishX4V9w4x1rgZ8AWVZ2a5/tOAS/XYdIK4LU6Pt8ozK7qMLuqw+yqjizadYGqzhu6SdKYx9+JyEXANK7Tvx1AVQ+IyCPA88AkcMd8wuF9rq64lYg8rarb6/mORmB2VYfZVR1mV3UsZrsSIx6q+t45ju0CdkVojmEYhjEHiZmqaxiGYaQHE4/K3B+3ARUwu6rD7KoOs6s6Fq1diRkwNwzDMNKDeR6GYRhG1Sxq8RCRa71ki4dEZGeZ4yIiX/OOPyci2yKwaYOIPCkiz4vIARH5dJlzrhaRfi+J5D4R+Vyj7fJ+94iI/Mr7zafLHI+jvS4KtMM+ERkQkTtLzomsvUTkARE5KSL7A+8tE5Gfisivve15FT475/3YALu+KCIveNfqMRHprvDZOa97A+y6V0SOBa7X9RU+G3V7PRyw6YiI7Kvw2Ya0V6W+Ibb7S1UX5R/QDPwG2Ay0Ac8Cl5Sccz3wE0CANwI/j8CuNcA2b78LeKmMXVcDP4yhzY4AK+Y4Hnl7lbmmPbh56rG0F/AWYBuwP/De3wM7vf2dwBdquR8bYNcfAS3e/hfK2bWQ694Au+4F/nwB1zrS9io5/iXgc1G2V6W+Ia77azF7HlcAh1T1t6o6DjyES8IYZAfwPXXsAbpFZE0jjVLV46q619sfBA5SIZdXAom8vUp4O/AbVa1ncWhdqOpTwJmSt3cA3/X2vwv8cZmPLuR+DNUuVX1CVSe9l3tw2RsipUJ7LYTI28tHRAR4H/BvYf3eAm2q1DfEcn8tZvFYB7waeF0u4eJCzmkYIrIJuBz4eZnDb/LCDT/xVuFHgQK7ReQZcUkoS4m1vXCp+yv9h46jvXzOV9Xj3n4PcH6Zc+Juu4/ivMZyzHfdG8GnvOv1QIUwTJztdRVwQr2MGGVoeHuV9A2x3F+LWTwSjYh0Av8B3Klnp6sH2AtsVNVLga8D34/IrDerq7dyHXCHiLwlot+dFxFpA94F/HuZw3G11zmoiyEkaoqjiNyDy97wYIVTor7u/4gLr1wGHMeFiJLETcztdTS0vebqG6K8vxazeCwk4WIsSRlFpBV3czyoqo+WHlfVAVUd8vZ/DLSKyIpG26Wqx7ztSeAxzq2rEmcSy+uAvap6ovRAXO0V4IQfvvO2J8ucE9e9dgtwA/BBr+M5hwVc91BR1ROqOqWq08C3KvxeXO3VArwHeLjSOY1srwp9Qyz312IWj18CW0TkQu+p9Ubg8ZJzHgc+7M0ieiPQH3APG4IXT/02cFBVv1zhnNXeeYjIFbjreLrBdnWISJe/jxts3V9yWuTtFaDi02Ac7VXC48DN3v7NwA/KnLOQ+zFURORa4DPAu1R1uMI5C7nuYdsVHCd7d4Xfi7y9PK4BXlDVo+UONrK95ugb4rm/wp4RkKY/3Oygl3CzEO7x3rsduN3bF+A+7/ivgO0R2PRmnNv5HLDP+7u+xK5PAgdwMyb2AG+KwK7N3u896/12ItrL+90OnBgsDbwXS3vhBOw4MIGLK/8ZsByXDfrXwG5gmXfuWuDHc92PDbbrEC4O7t9n/1RqV6Xr3mC7/sW7f57DdXBrktBe3vvf8e+rwLmRtNccfUMs95etMDcMwzCqZjGHrQzDMIwaMfEwDMMwqsbEwzAMw6gaEw/DMAyjakw8DMMwjKox8TAMwzCqxsTDMAzDqBoTD8OIGRH5uojsFZE/jNsWw1goJh6GESNeCotVwMdxOaYMIxWYeBhGRIhIQUT+R0Sa/fdUtYgr8vPfwNe889pE5CkvCZ9hJBITD8NoAF5yyNL/Xx8FHlXVqcB5y4F2YBCXFh11xXp+Brw/InMNo2pMPAwjJERkk1cj+nu4TKobSk75IOdmPP0s8A+4JHrBIlXf9843jERi4mEY4bIF+KaqbtVAOVwvDfZmVT0SeG8T8CZcbYiDnC0e+wEbQDcSi4mHYYTLy+rqt5eyAugree9vgb9Wl9r6LPHwQlvjfm0Iw0gaNiBnGOFSrPD+CJD3X4jIZbiKdG8Wkfu8Y78q+UwOGG2EkYZRL+Z5GEYEqGov0CwivoB8AVfBb5OqbgLeQMDz8AbSX1PViciNNYwFYJ6HYUTHEzhPYxpoV9Xd/gFVPSEinSKyTFXPAG8DfhSXoYYxH1ZJ0DAiQkS2AXep6ocWcO6jwE5VfanxlhlG9VjYyjAiQlX3Ak8GFwmWw5uZ9X0TDiPJmOdhGIZhVI15HoZhGEbVmHgYhmEYVWPiYRiGYVSNiYdhGIZRNSYehmEYRtWYeBiGYRhVY+JhGIZhVM3/A4BsAR4PZXpqAAAAAElFTkSuQmCC\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
"### Include a damping factor to simulate a finite correlation length\n",
"### and/or instrumental resolution effects.\n",
"mcD = mc.copy()\n",
- "mcD.dampRate = 0.1 # in inverse Angstroms\n",
+ "mcD.dampRate = 0.075 # in inverse Angstroms\n",
"rD, frD = mcD.calc()\n",
"\n",
"fig = plt.figure()\n",
"ax = fig.add_subplot(111)\n",
"\n",
- "ax.plot(r, fr, 'b-', label='Default')\n",
- "ax.plot(rB, frB, 'r-', label='Broadened')\n",
- "ax.plot(rD, frD, 'g-', label='Damped')\n",
+ "ax.plot(r, fr, 'b-', label='Default')\n",
+ "ax.plot(rD, frD, 'r-', label='Damped')\n",
+ "ax.set_xlabel(r'r ($\\AA$)')\n",
+ "ax.set_ylabel(r'f ($\\AA^{-2}$)')\n",
+ "\n",
+ "plt.legend(loc='best')\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Change the ordered scale factor"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 30,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "### Reduce the ordered scale factor, simulating a reduced ordered moment.\n",
+ "mcS = mc.copy()\n",
+ "mcS.ordScale = 0.5*mc.ordScale\n",
+ "rS, frS, drS = mcS.calc(both=True) # both the normalized and unnormalized mPDF\n",
+ "\n",
+ "fig = plt.figure()\n",
+ "ax = fig.add_subplot(111)\n",
+ "\n",
+ "ax.plot(r, dr, 'b-', label='Default')\n",
+ "ax.plot(rS, drS, 'r-', label='Reduced scale factor')\n",
+ "ax.set_xlabel(r'r ($\\AA$)')\n",
+ "ax.set_ylabel(r'd ($\\AA^{-2}$)')\n",
+ "\n",
+ "plt.legend(loc='best')\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Change the calculation range"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 31,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "### Change the r-range for the calculation from 20 Angstroms (default) to 40.\n",
+ "mcL = mc.copy()\n",
+ "mcL.rmax = 40 # in Angstroms\n",
+ "\n",
+ "### Since the r-range is longer, we also need to re-generate the atoms and spins\n",
+ "### to fill a sphere of at least radius 40 Angstroms. The code below does this.\n",
+ "mcL.magstruc.species['Mn2+'].rmaxAtoms = 50\n",
+ "mcL.magstruc.makeAll()\n",
+ "\n",
+ "rL,frL,drL = mcL.calc(both=True)\n",
+ "\n",
+ "fig = plt.figure()\n",
+ "ax = fig.add_subplot(111)\n",
+ "\n",
+ "ax.plot(r, dr, 'bo', label='Default')\n",
+ "ax.plot(rL, drL, 'r-', label='Longer r-grid',lw=2)\n",
"ax.set_xlabel(r'r ($\\AA$)')\n",
- "ax.set_ylabel(r'f ($\\AA^{-2}$)')\n",
+ "ax.set_ylabel(r'd ($\\AA^{-2}$)')\n",
"\n",
"plt.legend(loc='best')\n",
"plt.show()"
@@ -9355,17 +1932,77 @@
},
{
"cell_type": "code",
- "execution_count": 16,
+ "execution_count": 32,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "plt.close('all')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Simple example of an mPDF fit"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Here, we will provide an example of doing a very basic mPDF fit to actual experimental data taken on MnO. The initial structural PDF was refined using PDFgui, and now we use the residual of that structural fit as the dataset against which the mPDF will be refined. To keep things simple, we will just refine the scale factors and an overall damping envelope here."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Extract the refined atomic structure from the PDFgui file"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [],
+ "source": [
+ "PDFguiFile = 'MnOpdfgui.ddp'\n",
+ "struc = getStrucFromPDFgui(PDFguiFile,0)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Make the magnetic structure"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
"metadata": {
"collapsed": false
},
"outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "/home/ben/anaconda/envs/mpdfdev/lib/python2.7/site-packages/diffpy.Structure-1.3.2-py2.7.egg/diffpy/Structure/lattice.py:125: FutureWarning: comparison to `None` will result in an elementwise object comparison in the future.\n",
+ " if [a, b, c, alpha, beta, gamma, base] == 7*[None]:\n"
+ ]
+ },
{
"data": {
"application/javascript": [
"/* Put everything inside the global mpl namespace */\n",
"window.mpl = {};\n",
"\n",
+ "\n",
"mpl.get_websocket_type = function() {\n",
" if (typeof(WebSocket) !== 'undefined') {\n",
" return WebSocket;\n",
@@ -9424,6 +2061,9 @@
" this.ws.onopen = function () {\n",
" fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n",
" fig.send_message(\"send_image_mode\", {});\n",
+ " if (mpl.ratio != 1) {\n",
+ " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n",
+ " }\n",
" fig.send_message(\"refresh\", {});\n",
" }\n",
"\n",
@@ -9493,6 +2133,15 @@
" this.canvas = canvas[0];\n",
" this.context = canvas[0].getContext(\"2d\");\n",
"\n",
+ " var backingStore = this.context.backingStorePixelRatio ||\n",
+ "\tthis.context.webkitBackingStorePixelRatio ||\n",
+ "\tthis.context.mozBackingStorePixelRatio ||\n",
+ "\tthis.context.msBackingStorePixelRatio ||\n",
+ "\tthis.context.oBackingStorePixelRatio ||\n",
+ "\tthis.context.backingStorePixelRatio || 1;\n",
+ "\n",
+ " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n",
+ "\n",
" var rubberband = $('');\n",
" rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n",
"\n",
@@ -9549,8 +2198,9 @@
" canvas_div.css('width', width)\n",
" canvas_div.css('height', height)\n",
"\n",
- " canvas.attr('width', width);\n",
- " canvas.attr('height', height);\n",
+ " canvas.attr('width', width * mpl.ratio);\n",
+ " canvas.attr('height', height * mpl.ratio);\n",
+ " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n",
"\n",
" rubberband.attr('width', width);\n",
" rubberband.attr('height', height);\n",
@@ -9683,10 +2333,10 @@
"}\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",
+ " var x0 = msg['x0'] / mpl.ratio;\n",
+ " var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n",
+ " var x1 = msg['x1'] / mpl.ratio;\n",
+ " var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n",
" x0 = Math.floor(x0) + 0.5;\n",
" y0 = Math.floor(y0) + 0.5;\n",
" x1 = Math.floor(x1) + 0.5;\n",
@@ -9842,8 +2492,8 @@
" this.canvas_div.focus();\n",
" }\n",
"\n",
- " var x = canvas_pos.x;\n",
- " var y = canvas_pos.y;\n",
+ " var x = canvas_pos.x * mpl.ratio;\n",
+ " var y = canvas_pos.y * mpl.ratio;\n",
"\n",
" this.send_message(name, {x: x, y: y, button: event.button,\n",
" step: event.step,\n",
@@ -9964,6 +2614,7 @@
"};\n",
"\n",
"mpl.figure.prototype.handle_close = function(fig, msg) {\n",
+ " var width = fig.canvas.width/mpl.ratio\n",
" fig.root.unbind('remove')\n",
"\n",
" // Update the output cell to use the data from the current canvas.\n",
@@ -9972,7 +2623,7 @@
" // 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('
');\n",
+ " $(fig.parent_element).html('
');\n",
" fig.close_ws(fig, msg);\n",
"}\n",
"\n",
@@ -9983,8 +2634,9 @@
"\n",
"mpl.figure.prototype.push_to_output = function(remove_interactive) {\n",
" // Turn the data on the canvas into data in the output cell.\n",
+ " var width = this.canvas.width/mpl.ratio\n",
" var dataURL = this.canvas.toDataURL();\n",
- " this.cell_info[1]['text/html'] = '
';\n",
+ " this.cell_info[1]['text/html'] = '
';\n",
"}\n",
"\n",
"mpl.figure.prototype.updated_canvas_event = function() {\n",
@@ -10073,12 +2725,9 @@
" // 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",
+ " // select the cell after this one\n",
+ " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n",
+ " IPython.notebook.select(index + 1);\n",
" }\n",
"}\n",
"\n",
@@ -10127,7 +2776,7 @@
{
"data": {
"text/html": [
- "
"
+ "
"
],
"text/plain": [
""
@@ -10138,27 +2787,135 @@
}
],
"source": [
- "### Change the ordered scale factor relative to the paramagnetic scale factor, simulating\n",
- "### a reduction in the size of the ordered moment relative to the total local moment.\n",
- "mcS = mc.copy()\n",
- "mcS.ordScale = 0.5*mc.ordScale\n",
- "rS, frS, drS = mcS.calc(both=True) # both the normalized and unnormalized mPDF\n",
+ "svec = np.array([1.0,-1.0,0.0])\n",
+ "msp = MagSpecies(struc,magIdxs=[0,1,2,3],ffparamkey='Mn2',rmaxAtoms=50,basisvecs=svec,\n",
+ " kvecs=np.array([0.5,0.5,0.5]),label=str(0))\n",
"\n",
- "fig = plt.figure()\n",
- "ax = fig.add_subplot(111)\n",
+ "mstr=MagStructure()\n",
+ "mstr.loadSpecies(msp)\n",
+ "mstr.makeAll()\n",
"\n",
- "ax.plot(r, dr, 'b-', label='Default')\n",
- "ax.plot(rS, drS, 'r-', label='Reduced scale factor')\n",
- "ax.set_xlabel(r'r ($\\AA$)')\n",
- "ax.set_ylabel(r'd ($\\AA^{-2}$)')\n",
+ "### Visualize the magnetic structure\n",
+ "uc = struc[:4].xyz\n",
+ "visatoms = uc.copy()\n",
+ "visatoms = np.concatenate((visatoms,visatoms+np.array([0,0,1]),visatoms+np.array([0,1,0]),visatoms+np.array([0,0,1])))\n",
+ "visatoms = struc.lattice.cartesian(visatoms)\n",
+ "visspins = mstr.spinsFromAtoms(visatoms,fractional=False)\n",
+ "mstr.visualize(visatoms,visspins)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Extract the data, load it into a Profile object"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "PDFguiFile = 'MnOpdfgui.ddp'\n",
+ "r,d = getDiffData(PDFguiFile, 0) ### extract the fit residual from the atomic PDF fit done in PDFgui\n",
"\n",
- "plt.legend(loc='best')\n",
- "plt.show()"
+ "from diffpy.srfit.fitbase import Profile\n",
+ "\n",
+ "profile = Profile()\n",
+ "profile.setObservedProfile(r, d)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Make the MPDFcalculator, set up the fit"
]
},
{
"cell_type": "code",
- "execution_count": 17,
+ "execution_count": 8,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "### Create the MPDFcalculator\n",
+ "mc = MPDFcalculator(mstr)\n",
+ "mc.rmin = profile.xobs.min()\n",
+ "mc.rmax = profile.xobs.max()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "### Make the FitContribution\n",
+ "\n",
+ "from diffpy.srfit.fitbase import FitContribution\n",
+ "mfit = FitContribution('mfit')\n",
+ "mfit.setProfile(profile)\n",
+ "\n",
+ "# Define the function that will calculate the mPDF\n",
+ "def mpdf(parascale, ordscale, damp):\n",
+ " mc.paraScale, mc.ordScale, mc.dampRate = parascale, ordscale, damp\n",
+ " dr = mc.calc(both=True)[2]\n",
+ " return dr\n",
+ "\n",
+ "mfit.registerFunction(mpdf)\n",
+ "mfit.setEquation(\"mpdf(parascale, ordscale, damp)\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ ""
+ ]
+ },
+ "execution_count": 11,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "### Make the FitRecipe\n",
+ "### Make the FitRecipe and add the relevant variables\n",
+ "from diffpy.srfit.fitbase import FitRecipe\n",
+ "recipe = FitRecipe()\n",
+ "\n",
+ "# give the PDFContribution to the FitRecipe\n",
+ "recipe.addContribution(mfit)\n",
+ "\n",
+ "# add the mPDF variables\n",
+ "recipe.addVar(mfit.parascale, 4)\n",
+ "recipe.addVar(mfit.ordscale, 0.5)\n",
+ "recipe.addVar(mfit.damp, 0.01)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Run the refinement"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
"metadata": {
"collapsed": false
},
@@ -10167,13 +2924,10 @@
"name": "stdout",
"output_type": "stream",
"text": [
- "Running checks for Mn2+ MagSpecies object...\n",
- "\n",
- "All MagSpecies() checks passed. No obvious problems found.\n",
- "\n",
- "Running checks for MagStructure object...\n",
- "\n",
- "All MagStructure checks passed. No obvious problems found.\n"
+ "Refine using scipy's least-squares optimizer:\n",
+ " variables: ['parascale', 'ordscale', 'damp']\n",
+ " initial values: [ 2.8959563 1.23062246 0.00673758]\n",
+ " final values: [ 2.8959563 1.23062245 0.00673758]\n"
]
},
{
@@ -10182,6 +2936,7 @@
"/* Put everything inside the global mpl namespace */\n",
"window.mpl = {};\n",
"\n",
+ "\n",
"mpl.get_websocket_type = function() {\n",
" if (typeof(WebSocket) !== 'undefined') {\n",
" return WebSocket;\n",
@@ -10240,6 +2995,9 @@
" this.ws.onopen = function () {\n",
" fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n",
" fig.send_message(\"send_image_mode\", {});\n",
+ " if (mpl.ratio != 1) {\n",
+ " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n",
+ " }\n",
" fig.send_message(\"refresh\", {});\n",
" }\n",
"\n",
@@ -10309,6 +3067,15 @@
" this.canvas = canvas[0];\n",
" this.context = canvas[0].getContext(\"2d\");\n",
"\n",
+ " var backingStore = this.context.backingStorePixelRatio ||\n",
+ "\tthis.context.webkitBackingStorePixelRatio ||\n",
+ "\tthis.context.mozBackingStorePixelRatio ||\n",
+ "\tthis.context.msBackingStorePixelRatio ||\n",
+ "\tthis.context.oBackingStorePixelRatio ||\n",
+ "\tthis.context.backingStorePixelRatio || 1;\n",
+ "\n",
+ " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n",
+ "\n",
" var rubberband = $('');\n",
" rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n",
"\n",
@@ -10365,8 +3132,9 @@
" canvas_div.css('width', width)\n",
" canvas_div.css('height', height)\n",
"\n",
- " canvas.attr('width', width);\n",
- " canvas.attr('height', height);\n",
+ " canvas.attr('width', width * mpl.ratio);\n",
+ " canvas.attr('height', height * mpl.ratio);\n",
+ " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n",
"\n",
" rubberband.attr('width', width);\n",
" rubberband.attr('height', height);\n",
@@ -10499,10 +3267,10 @@
"}\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",
+ " var x0 = msg['x0'] / mpl.ratio;\n",
+ " var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n",
+ " var x1 = msg['x1'] / mpl.ratio;\n",
+ " var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n",
" x0 = Math.floor(x0) + 0.5;\n",
" y0 = Math.floor(y0) + 0.5;\n",
" x1 = Math.floor(x1) + 0.5;\n",
@@ -10658,8 +3426,8 @@
" this.canvas_div.focus();\n",
" }\n",
"\n",
- " var x = canvas_pos.x;\n",
- " var y = canvas_pos.y;\n",
+ " var x = canvas_pos.x * mpl.ratio;\n",
+ " var y = canvas_pos.y * mpl.ratio;\n",
"\n",
" this.send_message(name, {x: x, y: y, button: event.button,\n",
" step: event.step,\n",
@@ -10780,6 +3548,7 @@
"};\n",
"\n",
"mpl.figure.prototype.handle_close = function(fig, msg) {\n",
+ " var width = fig.canvas.width/mpl.ratio\n",
" fig.root.unbind('remove')\n",
"\n",
" // Update the output cell to use the data from the current canvas.\n",
@@ -10788,7 +3557,7 @@
" // 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('
');\n",
+ " $(fig.parent_element).html('
');\n",
" fig.close_ws(fig, msg);\n",
"}\n",
"\n",
@@ -10799,8 +3568,9 @@
"\n",
"mpl.figure.prototype.push_to_output = function(remove_interactive) {\n",
" // Turn the data on the canvas into data in the output cell.\n",
+ " var width = this.canvas.width/mpl.ratio\n",
" var dataURL = this.canvas.toDataURL();\n",
- " this.cell_info[1]['text/html'] = '
';\n",
+ " this.cell_info[1]['text/html'] = '
';\n",
"}\n",
"\n",
"mpl.figure.prototype.updated_canvas_event = function() {\n",
@@ -10889,12 +3659,9 @@
" // 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",
+ " // select the cell after this one\n",
+ " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n",
+ " IPython.notebook.select(index + 1);\n",
" }\n",
"}\n",
"\n",
@@ -10943,7 +3710,7 @@
{
"data": {
"text/html": [
- "
"
+ "
"
],
"text/plain": [
""
@@ -10954,80 +3721,49 @@
}
],
"source": [
- "### Change the r-range for the calculation from 20 Angstroms (default) to 40.\n",
- "mcL = mc.copy()\n",
- "mcL.rmax = 40 # in Angstroms\n",
+ "### Run the refinement\n",
"\n",
- "### Since the r-range is longer, we also need to re-generate the atoms and spins\n",
- "### to fill a sphere of at least radius 40 Angstroms. The code below does this.\n",
- "mcL.magstruc.species['Mn2+'].rmaxAtoms = 50\n",
- "mcL.magstruc.makeAll()\n",
+ "# Turn off printout of iteration number.\n",
+ "recipe.clearFitHooks()\n",
"\n",
- "rL,frL,drL = mcL.calc(both=True)\n",
+ "# Initial structural fit\n",
+ "print \"Refine using scipy's least-squares optimizer:\"\n",
+ "print \" variables:\", recipe.names\n",
+ "print \" initial values:\", recipe.values\n",
"\n",
- "fig = plt.figure()\n",
- "ax = fig.add_subplot(111)\n",
+ "from scipy.optimize import least_squares\n",
"\n",
- "ax.plot(r, dr, 'bo', label='Default')\n",
- "ax.plot(rL, drL, 'r-', label='Longer r-grid',lw=2)\n",
- "ax.set_xlabel(r'r ($\\AA$)')\n",
- "ax.set_ylabel(r'd ($\\AA^{-2}$)')\n",
+ "least_squares(recipe.residual, recipe.values)\n",
+ "print \" final values:\", recipe.values\n",
+ "\n",
+ "### Plot the results\n",
+ "fit = mfit.evaluateEquation(\"mpdf\")\n",
+ "\n",
+ "ax=plt.figure().add_subplot(111)\n",
+ "ax.plot(r, d, 'bo', label=\"mPDF data\", markerfacecolor='none', markeredgecolor='b')\n",
+ "ax.plot(r, fit, 'r-', lw=2, label=\"mPDF fit\")\n",
+ "ax.set_xlabel(r\"r ($\\AA$)\")\n",
+ "ax.set_ylabel(r\"D ($\\AA^{-2}$)\")\n",
+ "ax.set_xlim(xmax=mc.rmax)\n",
+ "plt.legend(loc=1)\n",
"\n",
- "plt.legend(loc='best')\n",
"plt.show()"
]
},
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Simple example of an mPDF fit"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Here, we will provide an example of doing a very basic mPDF fit to actual experimental data taken on MnO. The initial structural PDF was refined using PDFgui, and now we use the residual of that structural fit as the dataset against which the mPDF will be refined. To keep things simple, we will just refine the scale factors here."
- ]
- },
{
"cell_type": "code",
- "execution_count": 18,
+ "execution_count": 14,
"metadata": {
"collapsed": false
},
"outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Coordinates of atoms and spins for Mn2+\n",
- "have not been loaded because they have not yet been\n",
- "generated and/or do not match in shape.\n",
- "Running checks for Mn2+ MagSpecies object...\n",
- "\n",
- "All MagSpecies() checks passed. No obvious problems found.\n",
- "\n",
- "Running checks for MagStructure object...\n",
- "\n",
- "All MagStructure checks passed. No obvious problems found.\n",
- "Running checks for Mn2+ MagSpecies object...\n",
- "\n",
- "All MagSpecies() checks passed. No obvious problems found.\n",
- "\n",
- "Running checks for MagStructure object...\n",
- "\n",
- "All MagStructure checks passed. No obvious problems found.\n",
- "(array([ 3.75623147, 1.14768791]), 3)\n"
- ]
- },
{
"data": {
"application/javascript": [
"/* Put everything inside the global mpl namespace */\n",
"window.mpl = {};\n",
"\n",
+ "\n",
"mpl.get_websocket_type = function() {\n",
" if (typeof(WebSocket) !== 'undefined') {\n",
" return WebSocket;\n",
@@ -11086,6 +3822,9 @@
" this.ws.onopen = function () {\n",
" fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n",
" fig.send_message(\"send_image_mode\", {});\n",
+ " if (mpl.ratio != 1) {\n",
+ " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n",
+ " }\n",
" fig.send_message(\"refresh\", {});\n",
" }\n",
"\n",
@@ -11155,6 +3894,15 @@
" this.canvas = canvas[0];\n",
" this.context = canvas[0].getContext(\"2d\");\n",
"\n",
+ " var backingStore = this.context.backingStorePixelRatio ||\n",
+ "\tthis.context.webkitBackingStorePixelRatio ||\n",
+ "\tthis.context.mozBackingStorePixelRatio ||\n",
+ "\tthis.context.msBackingStorePixelRatio ||\n",
+ "\tthis.context.oBackingStorePixelRatio ||\n",
+ "\tthis.context.backingStorePixelRatio || 1;\n",
+ "\n",
+ " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n",
+ "\n",
" var rubberband = $('');\n",
" rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n",
"\n",
@@ -11211,8 +3959,9 @@
" canvas_div.css('width', width)\n",
" canvas_div.css('height', height)\n",
"\n",
- " canvas.attr('width', width);\n",
- " canvas.attr('height', height);\n",
+ " canvas.attr('width', width * mpl.ratio);\n",
+ " canvas.attr('height', height * mpl.ratio);\n",
+ " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n",
"\n",
" rubberband.attr('width', width);\n",
" rubberband.attr('height', height);\n",
@@ -11345,10 +4094,10 @@
"}\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",
+ " var x0 = msg['x0'] / mpl.ratio;\n",
+ " var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n",
+ " var x1 = msg['x1'] / mpl.ratio;\n",
+ " var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n",
" x0 = Math.floor(x0) + 0.5;\n",
" y0 = Math.floor(y0) + 0.5;\n",
" x1 = Math.floor(x1) + 0.5;\n",
@@ -11504,8 +4253,8 @@
" this.canvas_div.focus();\n",
" }\n",
"\n",
- " var x = canvas_pos.x;\n",
- " var y = canvas_pos.y;\n",
+ " var x = canvas_pos.x * mpl.ratio;\n",
+ " var y = canvas_pos.y * mpl.ratio;\n",
"\n",
" this.send_message(name, {x: x, y: y, button: event.button,\n",
" step: event.step,\n",
@@ -11626,6 +4375,7 @@
"};\n",
"\n",
"mpl.figure.prototype.handle_close = function(fig, msg) {\n",
+ " var width = fig.canvas.width/mpl.ratio\n",
" fig.root.unbind('remove')\n",
"\n",
" // Update the output cell to use the data from the current canvas.\n",
@@ -11634,7 +4384,7 @@
" // 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('
');\n",
+ " $(fig.parent_element).html('
');\n",
" fig.close_ws(fig, msg);\n",
"}\n",
"\n",
@@ -11645,8 +4395,9 @@
"\n",
"mpl.figure.prototype.push_to_output = function(remove_interactive) {\n",
" // Turn the data on the canvas into data in the output cell.\n",
+ " var width = this.canvas.width/mpl.ratio\n",
" var dataURL = this.canvas.toDataURL();\n",
- " this.cell_info[1]['text/html'] = '
';\n",
+ " this.cell_info[1]['text/html'] = '
';\n",
"}\n",
"\n",
"mpl.figure.prototype.updated_canvas_event = function() {\n",
@@ -11735,12 +4486,9 @@
" // 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",
+ " // select the cell after this one\n",
+ " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n",
+ " IPython.notebook.select(index + 1);\n",
" }\n",
"}\n",
"\n",
@@ -11789,7 +4537,7 @@
{
"data": {
"text/html": [
- "
"
+ "
"
],
"text/plain": [
""
@@ -11800,89 +4548,102 @@
}
],
"source": [
- "# Create the structure from our cif file, update the lattice according to the PDFgui fit.\n",
- "structureFile = \"MnO_R-3m.cif\" # note we are not using the cubic structure now\n",
- "mnostructure = loadStructure(structureFile)\n",
- "lat = mnostructure.lattice\n",
- "lat.a, lat.b, lat.c = 3.1505626, 3.1505626, 7.5936979 # these are the refined values from PDFgui\n",
- "\n",
- "### Create the Mn2+ magnetic species.\n",
- "msp = MagSpecies(struc=mnostructure, label='Mn2+', ffparamkey='Mn2')\n",
- "msp.magIdxs = [0,1,2] # these indices correspond to the Mn atoms in the rhombohedral unit cell\n",
- "msp.basisvecs = 2.5*np.array([1,0,0]) # spin direction in coordinate system of rhombohedral structure\n",
- "msp.kvecs = np.array([0,0,1.5]) # propagation vector in the rhombohedral structure\n",
- "\n",
- "### Create and prep the magnetic structure.\n",
- "mstr = MagStructure()\n",
- "mstr.loadSpecies(msp)\n",
- "mstr.makeAll()\n",
+ "### Plot the total PDF (atomic + magnetic) with the total fit\n",
+ "from diffpy.pdfgui import tui ### useful library to interact with PDFgui projects\n",
+ "prj = tui.LoadProject(PDFguiFile)\n",
+ "fitObj = prj.getFits()[0]\n",
+ "dataSet = fitObj.getDataSet(0)\n",
+ "gobs = np.array(dataSet.Gobs)\n",
+ "robs = np.array(dataSet.robs)\n",
+ "mask = np.logical_and(robs>r.min()-0.001,robs