1738 lines
		
	
	
		
			152 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			1738 lines
		
	
	
		
			152 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| {
 | |
|  "cells": [
 | |
|   {
 | |
|    "cell_type": "code",
 | |
|    "execution_count": 4,
 | |
|    "metadata": {},
 | |
|    "outputs": [],
 | |
|    "source": [
 | |
|     "%matplotlib notebook\n",
 | |
|     "\n",
 | |
|     "import numpy as np\n",
 | |
|     "import toolz\n",
 | |
|     "import matplotlib.pyplot as plt"
 | |
|    ]
 | |
|   },
 | |
|   {
 | |
|    "cell_type": "markdown",
 | |
|    "metadata": {},
 | |
|    "source": [
 | |
|     "## Frequency response\n",
 | |
|     "\n",
 | |
|     "Implicitly plot the function\n",
 | |
|     "\n",
 | |
|     "\\begin{align}\n",
 | |
|     "\\frac{\\gamma^2}{z^2} &= (\\omega^2 - \\alpha - \\frac{3}{4}\\beta z^2)^2 + (\\delta \\omega)^2 \\implies \\\\\n",
 | |
|     "\\frac{z}{\\gamma} &= \\frac{1}{\\sqrt{(\\omega^2 - \\alpha - \\frac{3}{4}\\beta z^2)^2 + (\\delta \\omega)^2}} \\implies \\\\\n",
 | |
|     "F &= G\n",
 | |
|     "\\end{align}\n"
 | |
|    ]
 | |
|   },
 | |
|   {
 | |
|    "cell_type": "code",
 | |
|    "execution_count": 2,
 | |
|    "metadata": {},
 | |
|    "outputs": [],
 | |
|    "source": [
 | |
|     "def left(gamma, z):\n",
 | |
|     "    return z / gamma\n",
 | |
|     "\n",
 | |
|     "def right(alpha, beta, delta, z, omega):\n",
 | |
|     "    denom = (omega**2 - alpha - (3/4)*beta*z**2)**2 + (delta*omega)**2\n",
 | |
|     "    return 1/np.sqrt(denom)"
 | |
|    ]
 | |
|   },
 | |
|   {
 | |
|    "cell_type": "code",
 | |
|    "execution_count": 66,
 | |
|    "metadata": {},
 | |
|    "outputs": [
 | |
|     {
 | |
|      "data": {
 | |
|       "application/javascript": [
 | |
|        "/* Put everything inside the global mpl namespace */\n",
 | |
|        "window.mpl = {};\n",
 | |
|        "\n",
 | |
|        "\n",
 | |
|        "mpl.get_websocket_type = function() {\n",
 | |
|        "    if (typeof(WebSocket) !== 'undefined') {\n",
 | |
|        "        return WebSocket;\n",
 | |
|        "    } else if (typeof(MozWebSocket) !== 'undefined') {\n",
 | |
|        "        return MozWebSocket;\n",
 | |
|        "    } else {\n",
 | |
|        "        alert('Your browser does not have WebSocket support.' +\n",
 | |
|        "              'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
 | |
|        "              'Firefox 4 and 5 are also supported but you ' +\n",
 | |
|        "              'have to enable WebSockets in about:config.');\n",
 | |
|        "    };\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n",
 | |
|        "    this.id = figure_id;\n",
 | |
|        "\n",
 | |
|        "    this.ws = websocket;\n",
 | |
|        "\n",
 | |
|        "    this.supports_binary = (this.ws.binaryType != undefined);\n",
 | |
|        "\n",
 | |
|        "    if (!this.supports_binary) {\n",
 | |
|        "        var warnings = document.getElementById(\"mpl-warnings\");\n",
 | |
|        "        if (warnings) {\n",
 | |
|        "            warnings.style.display = 'block';\n",
 | |
|        "            warnings.textContent = (\n",
 | |
|        "                \"This browser does not support binary websocket messages. \" +\n",
 | |
|        "                    \"Performance may be slow.\");\n",
 | |
|        "        }\n",
 | |
|        "    }\n",
 | |
|        "\n",
 | |
|        "    this.imageObj = new Image();\n",
 | |
|        "\n",
 | |
|        "    this.context = undefined;\n",
 | |
|        "    this.message = undefined;\n",
 | |
|        "    this.canvas = undefined;\n",
 | |
|        "    this.rubberband_canvas = undefined;\n",
 | |
|        "    this.rubberband_context = undefined;\n",
 | |
|        "    this.format_dropdown = undefined;\n",
 | |
|        "\n",
 | |
|        "    this.image_mode = 'full';\n",
 | |
|        "\n",
 | |
|        "    this.root = $('<div/>');\n",
 | |
|        "    this._root_extra_style(this.root)\n",
 | |
|        "    this.root.attr('style', 'display: inline-block');\n",
 | |
|        "\n",
 | |
|        "    $(parent_element).append(this.root);\n",
 | |
|        "\n",
 | |
|        "    this._init_header(this);\n",
 | |
|        "    this._init_canvas(this);\n",
 | |
|        "    this._init_toolbar(this);\n",
 | |
|        "\n",
 | |
|        "    var fig = this;\n",
 | |
|        "\n",
 | |
|        "    this.waiting = false;\n",
 | |
|        "\n",
 | |
|        "    this.ws.onopen =  function () {\n",
 | |
|        "            fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n",
 | |
|        "            fig.send_message(\"send_image_mode\", {});\n",
 | |
|        "            if (mpl.ratio != 1) {\n",
 | |
|        "                fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n",
 | |
|        "            }\n",
 | |
|        "            fig.send_message(\"refresh\", {});\n",
 | |
|        "        }\n",
 | |
|        "\n",
 | |
|        "    this.imageObj.onload = function() {\n",
 | |
|        "            if (fig.image_mode == 'full') {\n",
 | |
|        "                // Full images could contain transparency (where diff images\n",
 | |
|        "                // almost always do), so we need to clear the canvas so that\n",
 | |
|        "                // there is no ghosting.\n",
 | |
|        "                fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
 | |
|        "            }\n",
 | |
|        "            fig.context.drawImage(fig.imageObj, 0, 0);\n",
 | |
|        "        };\n",
 | |
|        "\n",
 | |
|        "    this.imageObj.onunload = function() {\n",
 | |
|        "        fig.ws.close();\n",
 | |
|        "    }\n",
 | |
|        "\n",
 | |
|        "    this.ws.onmessage = this._make_on_message_function(this);\n",
 | |
|        "\n",
 | |
|        "    this.ondownload = ondownload;\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype._init_header = function() {\n",
 | |
|        "    var titlebar = $(\n",
 | |
|        "        '<div class=\"ui-dialog-titlebar ui-widget-header ui-corner-all ' +\n",
 | |
|        "        'ui-helper-clearfix\"/>');\n",
 | |
|        "    var titletext = $(\n",
 | |
|        "        '<div class=\"ui-dialog-title\" style=\"width: 100%; ' +\n",
 | |
|        "        'text-align: center; padding: 3px;\"/>');\n",
 | |
|        "    titlebar.append(titletext)\n",
 | |
|        "    this.root.append(titlebar);\n",
 | |
|        "    this.header = titletext[0];\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n",
 | |
|        "\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n",
 | |
|        "\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype._init_canvas = function() {\n",
 | |
|        "    var fig = this;\n",
 | |
|        "\n",
 | |
|        "    var canvas_div = $('<div/>');\n",
 | |
|        "\n",
 | |
|        "    canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n",
 | |
|        "\n",
 | |
|        "    function canvas_keyboard_event(event) {\n",
 | |
|        "        return fig.key_event(event, event['data']);\n",
 | |
|        "    }\n",
 | |
|        "\n",
 | |
|        "    canvas_div.keydown('key_press', canvas_keyboard_event);\n",
 | |
|        "    canvas_div.keyup('key_release', canvas_keyboard_event);\n",
 | |
|        "    this.canvas_div = canvas_div\n",
 | |
|        "    this._canvas_extra_style(canvas_div)\n",
 | |
|        "    this.root.append(canvas_div);\n",
 | |
|        "\n",
 | |
|        "    var canvas = $('<canvas/>');\n",
 | |
|        "    canvas.addClass('mpl-canvas');\n",
 | |
|        "    canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n",
 | |
|        "\n",
 | |
|        "    this.canvas = canvas[0];\n",
 | |
|        "    this.context = canvas[0].getContext(\"2d\");\n",
 | |
|        "\n",
 | |
|        "    var backingStore = this.context.backingStorePixelRatio ||\n",
 | |
|        "\tthis.context.webkitBackingStorePixelRatio ||\n",
 | |
|        "\tthis.context.mozBackingStorePixelRatio ||\n",
 | |
|        "\tthis.context.msBackingStorePixelRatio ||\n",
 | |
|        "\tthis.context.oBackingStorePixelRatio ||\n",
 | |
|        "\tthis.context.backingStorePixelRatio || 1;\n",
 | |
|        "\n",
 | |
|        "    mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n",
 | |
|        "\n",
 | |
|        "    var rubberband = $('<canvas/>');\n",
 | |
|        "    rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n",
 | |
|        "\n",
 | |
|        "    var pass_mouse_events = true;\n",
 | |
|        "\n",
 | |
|        "    canvas_div.resizable({\n",
 | |
|        "        start: function(event, ui) {\n",
 | |
|        "            pass_mouse_events = false;\n",
 | |
|        "        },\n",
 | |
|        "        resize: function(event, ui) {\n",
 | |
|        "            fig.request_resize(ui.size.width, ui.size.height);\n",
 | |
|        "        },\n",
 | |
|        "        stop: function(event, ui) {\n",
 | |
|        "            pass_mouse_events = true;\n",
 | |
|        "            fig.request_resize(ui.size.width, ui.size.height);\n",
 | |
|        "        },\n",
 | |
|        "    });\n",
 | |
|        "\n",
 | |
|        "    function mouse_event_fn(event) {\n",
 | |
|        "        if (pass_mouse_events)\n",
 | |
|        "            return fig.mouse_event(event, event['data']);\n",
 | |
|        "    }\n",
 | |
|        "\n",
 | |
|        "    rubberband.mousedown('button_press', mouse_event_fn);\n",
 | |
|        "    rubberband.mouseup('button_release', mouse_event_fn);\n",
 | |
|        "    // Throttle sequential mouse events to 1 every 20ms.\n",
 | |
|        "    rubberband.mousemove('motion_notify', mouse_event_fn);\n",
 | |
|        "\n",
 | |
|        "    rubberband.mouseenter('figure_enter', mouse_event_fn);\n",
 | |
|        "    rubberband.mouseleave('figure_leave', mouse_event_fn);\n",
 | |
|        "\n",
 | |
|        "    canvas_div.on(\"wheel\", function (event) {\n",
 | |
|        "        event = event.originalEvent;\n",
 | |
|        "        event['data'] = 'scroll'\n",
 | |
|        "        if (event.deltaY < 0) {\n",
 | |
|        "            event.step = 1;\n",
 | |
|        "        } else {\n",
 | |
|        "            event.step = -1;\n",
 | |
|        "        }\n",
 | |
|        "        mouse_event_fn(event);\n",
 | |
|        "    });\n",
 | |
|        "\n",
 | |
|        "    canvas_div.append(canvas);\n",
 | |
|        "    canvas_div.append(rubberband);\n",
 | |
|        "\n",
 | |
|        "    this.rubberband = rubberband;\n",
 | |
|        "    this.rubberband_canvas = rubberband[0];\n",
 | |
|        "    this.rubberband_context = rubberband[0].getContext(\"2d\");\n",
 | |
|        "    this.rubberband_context.strokeStyle = \"#000000\";\n",
 | |
|        "\n",
 | |
|        "    this._resize_canvas = function(width, height) {\n",
 | |
|        "        // Keep the size of the canvas, canvas container, and rubber band\n",
 | |
|        "        // canvas in synch.\n",
 | |
|        "        canvas_div.css('width', width)\n",
 | |
|        "        canvas_div.css('height', height)\n",
 | |
|        "\n",
 | |
|        "        canvas.attr('width', width * mpl.ratio);\n",
 | |
|        "        canvas.attr('height', height * mpl.ratio);\n",
 | |
|        "        canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n",
 | |
|        "\n",
 | |
|        "        rubberband.attr('width', width);\n",
 | |
|        "        rubberband.attr('height', height);\n",
 | |
|        "    }\n",
 | |
|        "\n",
 | |
|        "    // Set the figure to an initial 600x600px, this will subsequently be updated\n",
 | |
|        "    // upon first draw.\n",
 | |
|        "    this._resize_canvas(600, 600);\n",
 | |
|        "\n",
 | |
|        "    // Disable right mouse context menu.\n",
 | |
|        "    $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n",
 | |
|        "        return false;\n",
 | |
|        "    });\n",
 | |
|        "\n",
 | |
|        "    function set_focus () {\n",
 | |
|        "        canvas.focus();\n",
 | |
|        "        canvas_div.focus();\n",
 | |
|        "    }\n",
 | |
|        "\n",
 | |
|        "    window.setTimeout(set_focus, 100);\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype._init_toolbar = function() {\n",
 | |
|        "    var fig = this;\n",
 | |
|        "\n",
 | |
|        "    var nav_element = $('<div/>')\n",
 | |
|        "    nav_element.attr('style', 'width: 100%');\n",
 | |
|        "    this.root.append(nav_element);\n",
 | |
|        "\n",
 | |
|        "    // Define a callback function for later on.\n",
 | |
|        "    function toolbar_event(event) {\n",
 | |
|        "        return fig.toolbar_button_onclick(event['data']);\n",
 | |
|        "    }\n",
 | |
|        "    function toolbar_mouse_event(event) {\n",
 | |
|        "        return fig.toolbar_button_onmouseover(event['data']);\n",
 | |
|        "    }\n",
 | |
|        "\n",
 | |
|        "    for(var toolbar_ind in mpl.toolbar_items) {\n",
 | |
|        "        var name = mpl.toolbar_items[toolbar_ind][0];\n",
 | |
|        "        var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
 | |
|        "        var image = mpl.toolbar_items[toolbar_ind][2];\n",
 | |
|        "        var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
 | |
|        "\n",
 | |
|        "        if (!name) {\n",
 | |
|        "            // put a spacer in here.\n",
 | |
|        "            continue;\n",
 | |
|        "        }\n",
 | |
|        "        var button = $('<button/>');\n",
 | |
|        "        button.addClass('ui-button ui-widget ui-state-default ui-corner-all ' +\n",
 | |
|        "                        'ui-button-icon-only');\n",
 | |
|        "        button.attr('role', 'button');\n",
 | |
|        "        button.attr('aria-disabled', 'false');\n",
 | |
|        "        button.click(method_name, toolbar_event);\n",
 | |
|        "        button.mouseover(tooltip, toolbar_mouse_event);\n",
 | |
|        "\n",
 | |
|        "        var icon_img = $('<span/>');\n",
 | |
|        "        icon_img.addClass('ui-button-icon-primary ui-icon');\n",
 | |
|        "        icon_img.addClass(image);\n",
 | |
|        "        icon_img.addClass('ui-corner-all');\n",
 | |
|        "\n",
 | |
|        "        var tooltip_span = $('<span/>');\n",
 | |
|        "        tooltip_span.addClass('ui-button-text');\n",
 | |
|        "        tooltip_span.html(tooltip);\n",
 | |
|        "\n",
 | |
|        "        button.append(icon_img);\n",
 | |
|        "        button.append(tooltip_span);\n",
 | |
|        "\n",
 | |
|        "        nav_element.append(button);\n",
 | |
|        "    }\n",
 | |
|        "\n",
 | |
|        "    var fmt_picker_span = $('<span/>');\n",
 | |
|        "\n",
 | |
|        "    var fmt_picker = $('<select/>');\n",
 | |
|        "    fmt_picker.addClass('mpl-toolbar-option ui-widget ui-widget-content');\n",
 | |
|        "    fmt_picker_span.append(fmt_picker);\n",
 | |
|        "    nav_element.append(fmt_picker_span);\n",
 | |
|        "    this.format_dropdown = fmt_picker[0];\n",
 | |
|        "\n",
 | |
|        "    for (var ind in mpl.extensions) {\n",
 | |
|        "        var fmt = mpl.extensions[ind];\n",
 | |
|        "        var option = $(\n",
 | |
|        "            '<option/>', {selected: fmt === mpl.default_extension}).html(fmt);\n",
 | |
|        "        fmt_picker.append(option)\n",
 | |
|        "    }\n",
 | |
|        "\n",
 | |
|        "    // Add hover states to the ui-buttons\n",
 | |
|        "    $( \".ui-button\" ).hover(\n",
 | |
|        "        function() { $(this).addClass(\"ui-state-hover\");},\n",
 | |
|        "        function() { $(this).removeClass(\"ui-state-hover\");}\n",
 | |
|        "    );\n",
 | |
|        "\n",
 | |
|        "    var status_bar = $('<span class=\"mpl-message\"/>');\n",
 | |
|        "    nav_element.append(status_bar);\n",
 | |
|        "    this.message = status_bar[0];\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n",
 | |
|        "    // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n",
 | |
|        "    // which will in turn request a refresh of the image.\n",
 | |
|        "    this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype.send_message = function(type, properties) {\n",
 | |
|        "    properties['type'] = type;\n",
 | |
|        "    properties['figure_id'] = this.id;\n",
 | |
|        "    this.ws.send(JSON.stringify(properties));\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype.send_draw_message = function() {\n",
 | |
|        "    if (!this.waiting) {\n",
 | |
|        "        this.waiting = true;\n",
 | |
|        "        this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n",
 | |
|        "    }\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype.handle_save = function(fig, msg) {\n",
 | |
|        "    var format_dropdown = fig.format_dropdown;\n",
 | |
|        "    var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n",
 | |
|        "    fig.ondownload(fig, format);\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype.handle_resize = function(fig, msg) {\n",
 | |
|        "    var size = msg['size'];\n",
 | |
|        "    if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n",
 | |
|        "        fig._resize_canvas(size[0], size[1]);\n",
 | |
|        "        fig.send_message(\"refresh\", {});\n",
 | |
|        "    };\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n",
 | |
|        "    var x0 = msg['x0'] / mpl.ratio;\n",
 | |
|        "    var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n",
 | |
|        "    var x1 = msg['x1'] / mpl.ratio;\n",
 | |
|        "    var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n",
 | |
|        "    x0 = Math.floor(x0) + 0.5;\n",
 | |
|        "    y0 = Math.floor(y0) + 0.5;\n",
 | |
|        "    x1 = Math.floor(x1) + 0.5;\n",
 | |
|        "    y1 = Math.floor(y1) + 0.5;\n",
 | |
|        "    var min_x = Math.min(x0, x1);\n",
 | |
|        "    var min_y = Math.min(y0, y1);\n",
 | |
|        "    var width = Math.abs(x1 - x0);\n",
 | |
|        "    var height = Math.abs(y1 - y0);\n",
 | |
|        "\n",
 | |
|        "    fig.rubberband_context.clearRect(\n",
 | |
|        "        0, 0, fig.canvas.width, fig.canvas.height);\n",
 | |
|        "\n",
 | |
|        "    fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n",
 | |
|        "    // Updates the figure title.\n",
 | |
|        "    fig.header.textContent = msg['label'];\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype.handle_cursor = function(fig, msg) {\n",
 | |
|        "    var cursor = msg['cursor'];\n",
 | |
|        "    switch(cursor)\n",
 | |
|        "    {\n",
 | |
|        "    case 0:\n",
 | |
|        "        cursor = 'pointer';\n",
 | |
|        "        break;\n",
 | |
|        "    case 1:\n",
 | |
|        "        cursor = 'default';\n",
 | |
|        "        break;\n",
 | |
|        "    case 2:\n",
 | |
|        "        cursor = 'crosshair';\n",
 | |
|        "        break;\n",
 | |
|        "    case 3:\n",
 | |
|        "        cursor = 'move';\n",
 | |
|        "        break;\n",
 | |
|        "    }\n",
 | |
|        "    fig.rubberband_canvas.style.cursor = cursor;\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype.handle_message = function(fig, msg) {\n",
 | |
|        "    fig.message.textContent = msg['message'];\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype.handle_draw = function(fig, msg) {\n",
 | |
|        "    // Request the server to send over a new figure.\n",
 | |
|        "    fig.send_draw_message();\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n",
 | |
|        "    fig.image_mode = msg['mode'];\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype.updated_canvas_event = function() {\n",
 | |
|        "    // Called whenever the canvas gets updated.\n",
 | |
|        "    this.send_message(\"ack\", {});\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "// A function to construct a web socket function for onmessage handling.\n",
 | |
|        "// Called in the figure constructor.\n",
 | |
|        "mpl.figure.prototype._make_on_message_function = function(fig) {\n",
 | |
|        "    return function socket_on_message(evt) {\n",
 | |
|        "        if (evt.data instanceof Blob) {\n",
 | |
|        "            /* FIXME: We get \"Resource interpreted as Image but\n",
 | |
|        "             * transferred with MIME type text/plain:\" errors on\n",
 | |
|        "             * Chrome.  But how to set the MIME type?  It doesn't seem\n",
 | |
|        "             * to be part of the websocket stream */\n",
 | |
|        "            evt.data.type = \"image/png\";\n",
 | |
|        "\n",
 | |
|        "            /* Free the memory for the previous frames */\n",
 | |
|        "            if (fig.imageObj.src) {\n",
 | |
|        "                (window.URL || window.webkitURL).revokeObjectURL(\n",
 | |
|        "                    fig.imageObj.src);\n",
 | |
|        "            }\n",
 | |
|        "\n",
 | |
|        "            fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
 | |
|        "                evt.data);\n",
 | |
|        "            fig.updated_canvas_event();\n",
 | |
|        "            fig.waiting = false;\n",
 | |
|        "            return;\n",
 | |
|        "        }\n",
 | |
|        "        else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n",
 | |
|        "            fig.imageObj.src = evt.data;\n",
 | |
|        "            fig.updated_canvas_event();\n",
 | |
|        "            fig.waiting = false;\n",
 | |
|        "            return;\n",
 | |
|        "        }\n",
 | |
|        "\n",
 | |
|        "        var msg = JSON.parse(evt.data);\n",
 | |
|        "        var msg_type = msg['type'];\n",
 | |
|        "\n",
 | |
|        "        // Call the  \"handle_{type}\" callback, which takes\n",
 | |
|        "        // the figure and JSON message as its only arguments.\n",
 | |
|        "        try {\n",
 | |
|        "            var callback = fig[\"handle_\" + msg_type];\n",
 | |
|        "        } catch (e) {\n",
 | |
|        "            console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n",
 | |
|        "            return;\n",
 | |
|        "        }\n",
 | |
|        "\n",
 | |
|        "        if (callback) {\n",
 | |
|        "            try {\n",
 | |
|        "                // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n",
 | |
|        "                callback(fig, msg);\n",
 | |
|        "            } catch (e) {\n",
 | |
|        "                console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n",
 | |
|        "            }\n",
 | |
|        "        }\n",
 | |
|        "    };\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n",
 | |
|        "mpl.findpos = function(e) {\n",
 | |
|        "    //this section is from http://www.quirksmode.org/js/events_properties.html\n",
 | |
|        "    var targ;\n",
 | |
|        "    if (!e)\n",
 | |
|        "        e = window.event;\n",
 | |
|        "    if (e.target)\n",
 | |
|        "        targ = e.target;\n",
 | |
|        "    else if (e.srcElement)\n",
 | |
|        "        targ = e.srcElement;\n",
 | |
|        "    if (targ.nodeType == 3) // defeat Safari bug\n",
 | |
|        "        targ = targ.parentNode;\n",
 | |
|        "\n",
 | |
|        "    // jQuery normalizes the pageX and pageY\n",
 | |
|        "    // pageX,Y are the mouse positions relative to the document\n",
 | |
|        "    // offset() returns the position of the element relative to the document\n",
 | |
|        "    var x = e.pageX - $(targ).offset().left;\n",
 | |
|        "    var y = e.pageY - $(targ).offset().top;\n",
 | |
|        "\n",
 | |
|        "    return {\"x\": x, \"y\": y};\n",
 | |
|        "};\n",
 | |
|        "\n",
 | |
|        "/*\n",
 | |
|        " * return a copy of an object with only non-object keys\n",
 | |
|        " * we need this to avoid circular references\n",
 | |
|        " * http://stackoverflow.com/a/24161582/3208463\n",
 | |
|        " */\n",
 | |
|        "function simpleKeys (original) {\n",
 | |
|        "  return Object.keys(original).reduce(function (obj, key) {\n",
 | |
|        "    if (typeof original[key] !== 'object')\n",
 | |
|        "        obj[key] = original[key]\n",
 | |
|        "    return obj;\n",
 | |
|        "  }, {});\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype.mouse_event = function(event, name) {\n",
 | |
|        "    var canvas_pos = mpl.findpos(event)\n",
 | |
|        "\n",
 | |
|        "    if (name === 'button_press')\n",
 | |
|        "    {\n",
 | |
|        "        this.canvas.focus();\n",
 | |
|        "        this.canvas_div.focus();\n",
 | |
|        "    }\n",
 | |
|        "\n",
 | |
|        "    var x = canvas_pos.x * mpl.ratio;\n",
 | |
|        "    var y = canvas_pos.y * mpl.ratio;\n",
 | |
|        "\n",
 | |
|        "    this.send_message(name, {x: x, y: y, button: event.button,\n",
 | |
|        "                             step: event.step,\n",
 | |
|        "                             guiEvent: simpleKeys(event)});\n",
 | |
|        "\n",
 | |
|        "    /* This prevents the web browser from automatically changing to\n",
 | |
|        "     * the text insertion cursor when the button is pressed.  We want\n",
 | |
|        "     * to control all of the cursor setting manually through the\n",
 | |
|        "     * 'cursor' event from matplotlib */\n",
 | |
|        "    event.preventDefault();\n",
 | |
|        "    return false;\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype._key_event_extra = function(event, name) {\n",
 | |
|        "    // Handle any extra behaviour associated with a key event\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype.key_event = function(event, name) {\n",
 | |
|        "\n",
 | |
|        "    // Prevent repeat events\n",
 | |
|        "    if (name == 'key_press')\n",
 | |
|        "    {\n",
 | |
|        "        if (event.which === this._key)\n",
 | |
|        "            return;\n",
 | |
|        "        else\n",
 | |
|        "            this._key = event.which;\n",
 | |
|        "    }\n",
 | |
|        "    if (name == 'key_release')\n",
 | |
|        "        this._key = null;\n",
 | |
|        "\n",
 | |
|        "    var value = '';\n",
 | |
|        "    if (event.ctrlKey && event.which != 17)\n",
 | |
|        "        value += \"ctrl+\";\n",
 | |
|        "    if (event.altKey && event.which != 18)\n",
 | |
|        "        value += \"alt+\";\n",
 | |
|        "    if (event.shiftKey && event.which != 16)\n",
 | |
|        "        value += \"shift+\";\n",
 | |
|        "\n",
 | |
|        "    value += 'k';\n",
 | |
|        "    value += event.which.toString();\n",
 | |
|        "\n",
 | |
|        "    this._key_event_extra(event, name);\n",
 | |
|        "\n",
 | |
|        "    this.send_message(name, {key: value,\n",
 | |
|        "                             guiEvent: simpleKeys(event)});\n",
 | |
|        "    return false;\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype.toolbar_button_onclick = function(name) {\n",
 | |
|        "    if (name == 'download') {\n",
 | |
|        "        this.handle_save(this, null);\n",
 | |
|        "    } else {\n",
 | |
|        "        this.send_message(\"toolbar_button\", {name: name});\n",
 | |
|        "    }\n",
 | |
|        "};\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n",
 | |
|        "    this.message.textContent = tooltip;\n",
 | |
|        "};\n",
 | |
|        "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n",
 | |
|        "\n",
 | |
|        "mpl.extensions = [\"eps\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
 | |
|        "\n",
 | |
|        "mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n",
 | |
|        "    // Create a \"websocket\"-like object which calls the given IPython comm\n",
 | |
|        "    // object with the appropriate methods. Currently this is a non binary\n",
 | |
|        "    // socket, so there is still some room for performance tuning.\n",
 | |
|        "    var ws = {};\n",
 | |
|        "\n",
 | |
|        "    ws.close = function() {\n",
 | |
|        "        comm.close()\n",
 | |
|        "    };\n",
 | |
|        "    ws.send = function(m) {\n",
 | |
|        "        //console.log('sending', m);\n",
 | |
|        "        comm.send(m);\n",
 | |
|        "    };\n",
 | |
|        "    // Register the callback with on_msg.\n",
 | |
|        "    comm.on_msg(function(msg) {\n",
 | |
|        "        //console.log('receiving', msg['content']['data'], msg);\n",
 | |
|        "        // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
 | |
|        "        ws.onmessage(msg['content']['data'])\n",
 | |
|        "    });\n",
 | |
|        "    return ws;\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.mpl_figure_comm = function(comm, msg) {\n",
 | |
|        "    // This is the function which gets called when the mpl process\n",
 | |
|        "    // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
 | |
|        "\n",
 | |
|        "    var id = msg.content.data.id;\n",
 | |
|        "    // Get hold of the div created by the display call when the Comm\n",
 | |
|        "    // socket was opened in Python.\n",
 | |
|        "    var element = $(\"#\" + id);\n",
 | |
|        "    var ws_proxy = comm_websocket_adapter(comm)\n",
 | |
|        "\n",
 | |
|        "    function ondownload(figure, format) {\n",
 | |
|        "        window.open(figure.imageObj.src);\n",
 | |
|        "    }\n",
 | |
|        "\n",
 | |
|        "    var fig = new mpl.figure(id, ws_proxy,\n",
 | |
|        "                           ondownload,\n",
 | |
|        "                           element.get(0));\n",
 | |
|        "\n",
 | |
|        "    // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n",
 | |
|        "    // web socket which is closed, not our websocket->open comm proxy.\n",
 | |
|        "    ws_proxy.onopen();\n",
 | |
|        "\n",
 | |
|        "    fig.parent_element = element.get(0);\n",
 | |
|        "    fig.cell_info = mpl.find_output_cell(\"<div id='\" + id + \"'></div>\");\n",
 | |
|        "    if (!fig.cell_info) {\n",
 | |
|        "        console.error(\"Failed to find cell for figure\", id, fig);\n",
 | |
|        "        return;\n",
 | |
|        "    }\n",
 | |
|        "\n",
 | |
|        "    var output_index = fig.cell_info[2]\n",
 | |
|        "    var cell = fig.cell_info[0];\n",
 | |
|        "\n",
 | |
|        "};\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype.handle_close = function(fig, msg) {\n",
 | |
|        "    var width = fig.canvas.width/mpl.ratio\n",
 | |
|        "    fig.root.unbind('remove')\n",
 | |
|        "\n",
 | |
|        "    // Update the output cell to use the data from the current canvas.\n",
 | |
|        "    fig.push_to_output();\n",
 | |
|        "    var dataURL = fig.canvas.toDataURL();\n",
 | |
|        "    // Re-enable the keyboard manager in IPython - without this line, in FF,\n",
 | |
|        "    // the notebook keyboard shortcuts fail.\n",
 | |
|        "    IPython.keyboard_manager.enable()\n",
 | |
|        "    $(fig.parent_element).html('<img src=\"' + dataURL + '\" width=\"' + width + '\">');\n",
 | |
|        "    fig.close_ws(fig, msg);\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype.close_ws = function(fig, msg){\n",
 | |
|        "    fig.send_message('closing', msg);\n",
 | |
|        "    // fig.ws.close()\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype.push_to_output = function(remove_interactive) {\n",
 | |
|        "    // Turn the data on the canvas into data in the output cell.\n",
 | |
|        "    var width = this.canvas.width/mpl.ratio\n",
 | |
|        "    var dataURL = this.canvas.toDataURL();\n",
 | |
|        "    this.cell_info[1]['text/html'] = '<img src=\"' + dataURL + '\" width=\"' + width + '\">';\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype.updated_canvas_event = function() {\n",
 | |
|        "    // Tell IPython that the notebook contents must change.\n",
 | |
|        "    IPython.notebook.set_dirty(true);\n",
 | |
|        "    this.send_message(\"ack\", {});\n",
 | |
|        "    var fig = this;\n",
 | |
|        "    // Wait a second, then push the new image to the DOM so\n",
 | |
|        "    // that it is saved nicely (might be nice to debounce this).\n",
 | |
|        "    setTimeout(function () { fig.push_to_output() }, 1000);\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype._init_toolbar = function() {\n",
 | |
|        "    var fig = this;\n",
 | |
|        "\n",
 | |
|        "    var nav_element = $('<div/>')\n",
 | |
|        "    nav_element.attr('style', 'width: 100%');\n",
 | |
|        "    this.root.append(nav_element);\n",
 | |
|        "\n",
 | |
|        "    // Define a callback function for later on.\n",
 | |
|        "    function toolbar_event(event) {\n",
 | |
|        "        return fig.toolbar_button_onclick(event['data']);\n",
 | |
|        "    }\n",
 | |
|        "    function toolbar_mouse_event(event) {\n",
 | |
|        "        return fig.toolbar_button_onmouseover(event['data']);\n",
 | |
|        "    }\n",
 | |
|        "\n",
 | |
|        "    for(var toolbar_ind in mpl.toolbar_items){\n",
 | |
|        "        var name = mpl.toolbar_items[toolbar_ind][0];\n",
 | |
|        "        var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
 | |
|        "        var image = mpl.toolbar_items[toolbar_ind][2];\n",
 | |
|        "        var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
 | |
|        "\n",
 | |
|        "        if (!name) { continue; };\n",
 | |
|        "\n",
 | |
|        "        var button = $('<button class=\"btn btn-default\" href=\"#\" title=\"' + name + '\"><i class=\"fa ' + image + ' fa-lg\"></i></button>');\n",
 | |
|        "        button.click(method_name, toolbar_event);\n",
 | |
|        "        button.mouseover(tooltip, toolbar_mouse_event);\n",
 | |
|        "        nav_element.append(button);\n",
 | |
|        "    }\n",
 | |
|        "\n",
 | |
|        "    // Add the status bar.\n",
 | |
|        "    var status_bar = $('<span class=\"mpl-message\" style=\"text-align:right; float: right;\"/>');\n",
 | |
|        "    nav_element.append(status_bar);\n",
 | |
|        "    this.message = status_bar[0];\n",
 | |
|        "\n",
 | |
|        "    // Add the close button to the window.\n",
 | |
|        "    var buttongrp = $('<div class=\"btn-group inline pull-right\"></div>');\n",
 | |
|        "    var button = $('<button class=\"btn btn-mini btn-primary\" href=\"#\" title=\"Stop Interaction\"><i class=\"fa fa-power-off icon-remove icon-large\"></i></button>');\n",
 | |
|        "    button.click(function (evt) { fig.handle_close(fig, {}); } );\n",
 | |
|        "    button.mouseover('Stop Interaction', toolbar_mouse_event);\n",
 | |
|        "    buttongrp.append(button);\n",
 | |
|        "    var titlebar = this.root.find($('.ui-dialog-titlebar'));\n",
 | |
|        "    titlebar.prepend(buttongrp);\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype._root_extra_style = function(el){\n",
 | |
|        "    var fig = this\n",
 | |
|        "    el.on(\"remove\", function(){\n",
 | |
|        "\tfig.close_ws(fig, {});\n",
 | |
|        "    });\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype._canvas_extra_style = function(el){\n",
 | |
|        "    // this is important to make the div 'focusable\n",
 | |
|        "    el.attr('tabindex', 0)\n",
 | |
|        "    // reach out to IPython and tell the keyboard manager to turn it's self\n",
 | |
|        "    // off when our div gets focus\n",
 | |
|        "\n",
 | |
|        "    // location in version 3\n",
 | |
|        "    if (IPython.notebook.keyboard_manager) {\n",
 | |
|        "        IPython.notebook.keyboard_manager.register_events(el);\n",
 | |
|        "    }\n",
 | |
|        "    else {\n",
 | |
|        "        // location in version 2\n",
 | |
|        "        IPython.keyboard_manager.register_events(el);\n",
 | |
|        "    }\n",
 | |
|        "\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype._key_event_extra = function(event, name) {\n",
 | |
|        "    var manager = IPython.notebook.keyboard_manager;\n",
 | |
|        "    if (!manager)\n",
 | |
|        "        manager = IPython.keyboard_manager;\n",
 | |
|        "\n",
 | |
|        "    // Check for shift+enter\n",
 | |
|        "    if (event.shiftKey && event.which == 13) {\n",
 | |
|        "        this.canvas_div.blur();\n",
 | |
|        "        event.shiftKey = false;\n",
 | |
|        "        // Send a \"J\" for go to next cell\n",
 | |
|        "        event.which = 74;\n",
 | |
|        "        event.keyCode = 74;\n",
 | |
|        "        manager.command_mode();\n",
 | |
|        "        manager.handle_keydown(event);\n",
 | |
|        "    }\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype.handle_save = function(fig, msg) {\n",
 | |
|        "    fig.ondownload(fig, null);\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "\n",
 | |
|        "mpl.find_output_cell = function(html_output) {\n",
 | |
|        "    // Return the cell and output element which can be found *uniquely* in the notebook.\n",
 | |
|        "    // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n",
 | |
|        "    // IPython event is triggered only after the cells have been serialised, which for\n",
 | |
|        "    // our purposes (turning an active figure into a static one), is too late.\n",
 | |
|        "    var cells = IPython.notebook.get_cells();\n",
 | |
|        "    var ncells = cells.length;\n",
 | |
|        "    for (var i=0; i<ncells; i++) {\n",
 | |
|        "        var cell = cells[i];\n",
 | |
|        "        if (cell.cell_type === 'code'){\n",
 | |
|        "            for (var j=0; j<cell.output_area.outputs.length; j++) {\n",
 | |
|        "                var data = cell.output_area.outputs[j];\n",
 | |
|        "                if (data.data) {\n",
 | |
|        "                    // IPython >= 3 moved mimebundle to data attribute of output\n",
 | |
|        "                    data = data.data;\n",
 | |
|        "                }\n",
 | |
|        "                if (data['text/html'] == html_output) {\n",
 | |
|        "                    return [cell, data, j];\n",
 | |
|        "                }\n",
 | |
|        "            }\n",
 | |
|        "        }\n",
 | |
|        "    }\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "// Register the function which deals with the matplotlib target/channel.\n",
 | |
|        "// The kernel may be null if the page has been refreshed.\n",
 | |
|        "if (IPython.notebook.kernel != null) {\n",
 | |
|        "    IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n",
 | |
|        "}\n"
 | |
|       ],
 | |
|       "text/plain": [
 | |
|        "<IPython.core.display.Javascript object>"
 | |
|       ]
 | |
|      },
 | |
|      "metadata": {},
 | |
|      "output_type": "display_data"
 | |
|     },
 | |
|     {
 | |
|      "data": {
 | |
|       "text/html": [
 | |
|        "<img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAoAAAAHgCAYAAAA10dzkAAAgAElEQVR4nOzdd3xUVdoH8BxQwbb2Arqi7uoWXd1Vd93dd5vrEUQQAQ+B0EIv0qVJDUgT6dKbSJfQe69SQwkQegkloUNII3Vmfu8fs/dISJuZe28myfy+n8983vczc++5B3zW5/Hee54TBCIiIiIKKEH+ngARERERFSwWgEREREQBhgUgERERUYBhAUhEREQUYFgAEhEREQUYFoBEREREAYYFIBEREVGAYQFIREREFGBYABIREREFGBaARERERAGGBSARERFRgGEBSERERBRgWAASERERBRgWgEREREQBhgUgERERUYBhAUhEREQUYFgAEhEREQUYFoBEREREAYYFIBEREVGAYQFIREREFGBYABIREREFGBaARERERAGGBSARERFRgGEBSERERBRgWAASERERBRgWgEREREQBhgUgERERUYBhAUhEREQUYFgAEhEREQUYFoBEREREAYYFIBEREVGAYQFIREREFGBYABIREREFGBaARERERAGGBSARERFRgGEBSERERBRgWAASERERBRgWgEREREQBhgUgERERUYBhAUhEREQUYFgAEhEREQUYFoBEREREAYYFIBEREVGAYQFIREREFGBYABIREREFGBaARERERAGGBSARERFRgGEBSERERBRgWAASERERBRgWgEREREQBhgUgERERUYBhAUhEREQUYFgAEhEREQUYFoBEREREAYYFIBEREVGAYQFIREREFGBYAJrgdDoRExOD+Ph4JCQk8MMPP/zwww8/ReATHx+PmJgYOJ1Of5cSfsMC0ISYmBgEBQXxww8//PDDDz9F8BMTE+PvUsJvWACaEB8frwPI3/81ww8//PDDDz/8ePYxbuDEx8f7u5TwGxaAJiQkJCAoKAgJCQn+ngoRERF5iPmbBaApDCAiIqKih/mbBaApDCAiIqKih/mbBaApDCAiIqKih/mbBaApDCAiIqKih/mbBaApDCAiIqKih/mbBaApDCAiIqKih/mbBaApDCAiIqKih/mbBaApDCAiIqKih/mbBaApDCAiIqKih/mbBaApDCAiIqKih/mbBaApDCAiIqKih/mbBaApDCAiIqKih/mbBaApDCAiIqKih/mbBaApDCAiIqKih/mbBaApDCAiIqKih/mbBaApDCAiIqKih/mbBaApDCAiIqKih/m7GBeAW7duReXKlVGmTBkEBQVh8eLFuR7bvHlzBAUFYcSIEV5dgwFERERU9DB/F+MCcNWqVejRowcWLVqUZwG4aNEivP322yhbtiwLQCIiogDA/F2MC8C75VYAxsbG4oUXXsCRI0dQrlw5FoBEREQBgPk7gAtAp9OJDz74ACNHjgQAjwrAtLQ0JCQk6E9MTEzABxAREVFRwwIwgAvAgQMH4qOPPoLL5QLgWQEYFhaGoKCgbJ9ADiAiIqKihgVggBaA+/btw3PPPYdLly7p73gHkIiIKDCwAAzQAnDEiBEQQqBkyZL6ExQUhBIlSqBcuXIej8sAIiIiKnqYvwO0ALx58yaioqKyfMqWLYuuXbvixIkTHo/LACIiIip6mL+LcQGYlJSEyMhIREZGIigoCMOHD0dkZCQuXLiQ4/FcBUxERBQYmL+LcQG4efPmHBdshIaG5ng8C0AiIqLAwPxdjAvAgsAAIiIiKnqYv1kAmsIAIiIiKnqYv1kAmsIAIiIiKnqYv1kAmsIAIiIiKnqYv1kAmsIAIiIiKnqYv1kAmsIAIiIiKnqYv1kAmsIAIiIiKnqYv1kAmsIAIiIiKnqYv1kAmsIAIiIiKnqYv1kAmsIAIiIiKnqYv1kAmsIAIiIiKnqYv1kAmsIAIiIiKnqYv1kAmsIAIiIiKnqYv1kAmsIAIiIiKnqYv1kAmsIAIiIiKnqYv1kAmsIAIiIiKnqYv1kAmsIAIiIiKnqYv1kAmsIAIiIiKnqYv1kAmsIAIiIiKnqYv1kAmsIAIiIiKnqYv1kAmsIAIiIiKnqYv1kAmsIAIiIiKnqYv1kAmsIAIiIiKnqYv1kAmsIAIiIiKnqYv1kAmsIAIiIiKnqYv1kAmsIAIiIiKnqYv1kAmsIAIiIiKnqYv1kAmsIAIiIiKnqYv1kAmsIAIiIiKnqYv1kAmsIAIiIiKnqYv1kAmsIAIiIiKnqYv1kAmsIAIiIiKnqYv1kAmsIAIiIiKnqYv1kAmsIAIsqZ0+nEnIGLsHX+TjgcDn9Ph4goC+ZvFoCmMICIcnZg42FIoSCFwtfBw/w9HSKiLJi/WQCawgAiytnW+Tt1ASiFwoZZ2/w9JSIijfmbBaApDCCinO1avi9LAfj5Mw2Rkpzq72kREQFg/gZYAJrCACLK2dlD5yGFQqWHaqPuKy0hhcL3Peb4e1pERACYvwEWgKYwgIhylpmRiYqlakEKhfChyyCFQuWH6yDhVqK/p0ZExPyNYlwAbt26FZUrV0aZMmUQFBSExYsX698yMjLQpUsXvPnmm3jooYdQpkwZ1KtXD5cuXfLqGgwgotw1e7sjpFDYsSQCzf7o/v8ndJzu72kRETF/oxgXgKtWrUKPHj2waNGibAVgfHw8pJSYN28eTpw4gV27duEvf/kL3n33Xa+uwQAiyt3AOiMhhcKcgYuwe4X7ncDKj9RBYlySv6dGRAGO+bsYF4B3u7cAzElERASCgoJw4cIFj8dlABHlbvaAhZBCYVDdUXC5XGj61peQQmFaz7n+nhoRBTjmbxaA2vr16yGE8CoYGEBEuduxJAJSKDR7uyMAYNuCXZBCodqToUi9k+bn2RFRIGP+ZgEIAEhNTcU777yD2rVr5zlOWloaEhIS9CcmJibgA4goNzcu3YIUCuVL1kBywh04HA7U+1UrSKGwaNRKf0+PiAIYC0AWgMjIyMCnn36KP/3pT/kGQlhYGIKCgrJ9AjmAiPJSu1wLSKFwYONhAMDyCesghULIS825RRwR+Q0LwAAvADMyMlC1alW89dZbuHnzZr7j8A4gkXf6qiGQQmHet0sAAOmp6aj+dENIobB1/k4/z46IAhULwAAuAI3i74033sD169d9GpcBRJS3OQMXQQqFAbVH6O+m9ZoLKRRa/aWrH2dGRIGM+bsYF4BJSUmIjIxEZGQkgoKCMHz4cERGRuLChQvIyMhAlSpV8OKLL+LgwYO4cuWK/qSnp3t8DQYQUd72rDoAKRRCX2+jv7t9PR4fP1ATUiic2HvGj7MjokDF/F2MC8DNmzfn+L5eaGgozp07l+NvQUFB2Lx5s8fXYAAR5S0xLknvBxx3LV5/P6jeKEih0L/WcD/OjogCFfN3MS4ACwIDiCh/jd9oDykUdi7bq787HRkNKRQ+fqAm4q7e9uPsiCgQMX+zADSFAUSUv28bjnE3gO6VtQF02793hxQKP/T+0U8zI6JAxfzNAtAUBhBR/haPXgUpFLpXGpDl+y3zdkAKheAyTZCZkemn2RFRIGL+ZgFoCgOIKH9Hd52EFArVn24Il8ulv8/MyESN5xtDCoUt4WwJQ0QFh/mbBaApDCCi/GWkZ+CTB0MghcLFE7FZfpvW090Spv0/e/ppdkQUiJi/WQCawgAi8ky7f/SAFArrZmzJ8v2NS7dQvmQNSKFw/liMn2ZHRIGG+ZsFoCkMICLPjGs/DVIojGkzNdtvvasOhhQK37Wa7IeZEVEgYv5mAWgKA4jIM+tnboUUCm3/3j3bb/vXH4IUClUeq4fUO2l+mB0RBRrmbxaApjCAiDwTe/oypFCoWKoW0tMysvzmdDpR99UvIIXC6u83+WmGRBRImL9ZAJrCACLyjMvlwufPNIQUCsd2n8r2+9xvFkMKhdbvf+WH2RFRoGH+ZgFoCgOIyHPdKw2AFAqLv1uV7be4a/GocL97f+DoqAt+mB0RBRLmbxaApjCAiDw3PWwepFAYHDo6x9/7fD4EUiiM+oKLQYjIXszfLABNYQAReW7nsr2QQqHR79vl+Pu+dQchhcJnj9dHemp6Ac+OiAIJ8zcLQFMYQESeu309HlIoSKGQdDs52+9OpxO1y7WAFAobZ2/zwwyJKFAwf7MANIUBROSder9qBSkU9q8/lOPvM/qGQwqFDv/uVcAzI6JAwvzNAtAUBhCRd/rVHAYpFOYMXJTj79djbuKjEu6dQS6duVLAsyOiQMH8zQLQFAYQkXfmfbsEUij0rTE012O6VugHKRSmdp9dgDMjokDC/M0C0BQGEJF3Dmw8DCkU6rzcMtdjts7fCSkUar3YDA6HowBnR0SBgvmbBaApDCAi7yQn3NGPeOOu3s7xmPS0DFR7MhRSKESsiSzgGRJRIGD+ZgFoCgOIyHuNft8OUijsXrEv12NGt54CKRS+Dh5WgDMjokDB/M0C0BQGEJH3BtUbBSkUZvQNz/WY05HR7r2DS4cgMS6pAGdHRIGA+ZsFoCkMICLvLRi+HFIo9K46ONdjXC4Xmr71JaRQWDZuTQHOjogCAfM3C0BTGEBE3ju45QikUAj5ZfM8jzMKxdbvf1VAMyOiQMH8zQLQFAYQkfdSklL0QpBbV+JyPS7uWjzK3xcMKRQunogtwBkSUXHH/M0C0BQGEJFvPFkIAgDdKw2AFApTvppVQDMjokDA/M0C0BQGEJFvBtV1LwSZ1W9BnscZPQFDftkcTqezgGZHRMUd8zcLQFMYQES+CR+6DFIo9Pl8SJ7Hpaem47PH60MKhchNUQU0OyIq7pi/WQCawgAi8s3+De4dQeq++kW+xw5vOh5SKAwOHV0AMyOiQMD8zQLQFAYQkW8S45IghYIUCgm3EvM8Nmr7cUih8OmjdZF6J62AZkhExRnzNwtAUxhARL6r++oXkELhwMbDeR7ncrlQ95WWkEJh45yfCmh2RFScMX+zADSFAUTku7Dq30IKhfnDluV77LSecyGFQrdPBhTAzIiouGP+ZgFoCgOIyHcz+oZ7/G7fxROxkEKh/H3BuH09vgBmR0TFGfM3C0BTGEBEvtuxJAJSKDR7u6NHx7d8rwukUFg8epXNMyOi4o75mwWgKQwgIt9du3AdUihUuL8m0tMy8j1+4YgV7q3h/tqtAGZHRMUZ8zcLQFMYQES+c7lcqPZkKKRQOH0gOt/jb12JQ/mS7i3kLp+9WgAzJKLiivmbBaApDCAiczp+EAYpFNZM2+TR8V0+6uvRDiJERHlh/mYBaAoDiMicMW2nQgqF8R2meXT8mmmbIIVCo9+3g8vlsndyRFRsMX+zADSFAURkzsrJGyCFQpeP+np0fHJ8MiqWDoEUCmcOnrN3ckRUbDF/swA0hQFEZM7xPacghYJ6rrHH5xj9Ayd1mWnjzIioOGP+LsYF4NatW1G5cmWUKVMGQUFBWLx4cZbfXS4XevXqheeffx6lS5fGhx9+iFOnTnl1DQYQkTmpd9LwUQn3wo64q7c9Omfr/J2QQqHOyy35GJiIfML8XYwLwFWrVqFHjx5YtGhRjgXgN998g8ceewxLlizBoUOHUKVKFbzyyitITU31+BoMICLz6r/WGlIo7F9/yKPj01LS8OmjdSGFwtGdJ2yeHREVR8zfxbgAvNu9BaDL5cLzzz+PIUOG6O/i4+NRqlQpzJ071+NxGUBE5hmPdBeOWOHxOYPqjoIUCmPaTLV0LryjSBQYmL8DtAA8e/YsgoKCEBkZmeW4f/3rX2jbtq3H4zKAiMyb1su9z+/QxuM8Pmf3in2QQiG4TBM4HA7L5uJyueByuRBz6jLmfbsENy/HWTY2ERUezN8BWgDu2LEDQUFBuHz5cpbjatSogeDg4FzHSUtLQ0JCgv7ExMQEfAARmbX5x+2QQqHN3zzf4SMjPQNVn3A3kY7cFGXpfHav3I+PH6gJKRTq/aoVbsTetHR8IvI/FoAsALMcl18BGBYWhqCgoGyfQA4gIrPOH70IKRQ+fbSuV49ghzYaCykURjSbYNlcnE4nGr/RHlIo/fm24RjLxieiwoEFYIAWgL4+AuYdQCLrZWZk6jtuV89f9/i8fesOQgqFz59pCEemNY+BdyyNgBQKVR6rpx8zV3qoNpLjky0Zn4gKBxaAAVoAGotAhg4dqr9LSEjgIhAiP2nyZgdIobB75X6Pz3FkOvD5Mw0hhcK+dQctmUf/kBGQQmFCx+lwuVz6buDyCessGZ+ICgfm72JcACYlJSEyMhKRkZEICgrC8OHDERkZiQsXLgBwt4F5/PHHsXTpUhw+fBifffYZ28AQ+cnXwcMghUL4kKVenTei+USvF5DkxuFwoNpTDSCFQtT24wCAOQMXQQqFXp99Y3p8Iio8mL+LcQG4efPmHN/XCw0NBfBzI+jnnnsOpUqVwocffoiTJ096dQ0GEJE1pofN86mQO7DxMKRQqPZUA2RmZJqaw9FdJyGFQtUnQvUjZWOnkqpPhFq62piI/Iv5uxgXgAWBAURkDWMlcNu/d/fqPEemA+rZRpBCIWJNZP4n5GFGn3BIofB18LAs41f5RT1IoXD6QLSp8Ymo8GD+ZgFoCgOIyBpnD53Xd9q8bcY8ssX/HgM3GmtqDt0+GQApFJaMWZ3l++6V3N8vGL7c1PhEVHgwf7MANIUBRGSN9NR0lC/p3hP41hXvmi9b8RjY5XKh+tPuBSXH92TdE9x4D7B/yAifxiaiwof5mwWgKQwgIuvU/3Urnxo7Oxw/Pwbeu9a31cCXzlyBFAoVS9VCelpGlt8iVh+AFAoNf+v5LkFEVLgxf7MANIUBRGQd41HrsvFrvT53RLMJkEJhWJPxPl1745yfIIVC6/e/yvZb3NXbkELhoxI1kJKU4tP4RFS4MH+zADSFAURknfFf/gApFMa1n+b1ufs3HDbVFNq49netJuf4e3DZplnawxBR0cb8zQLQFAYQkXVWTFwHKRS6fTLA63MdmQ79Dt/+DYe9Pr9L+a8hhcLKSetz/N24O7l49Cqvxyaiwof5mwWgKQwgIusc3HIEUijU+1Urn84f2ngcpFAY1XKS1+cad/iO7sq5F+jU7rMt33eYiPyH+ZsFoCkMICLr3LoSBykUypeskW0hhieMxRrBZZp41bQ54WYipFCQQuFOYs7v+G2YtQ1SKHT4Vy+v50VEhQ/zNwtAUxhARNZxuVy66fL5YzFen5+RnoHPHq/vflfvp2Men3dws/vOY91Xv8j1mFP7z+p3DImo6GP+ZgFoCgOIyFot3+0MKRR2LInw6fxB9UZ5vZBk8XerIIVCzyqDcj0mJTlV3yWMv8H/vRMVdczfLABNYQARWat/reGQQiF86DKfzt+xJAJSKNQu18LjHUWMnUSmdJud53F1X2kJKRQObT3q09yIqPBg/mYBaAoDiMha3/eY415s0XyiT+enpaSh8iN1IIXCib1nPDqn4wdhkEJh3fQteR5nbBW3fMI6n+ZGRIUH8zcLQFMYQETWWvvDZkih0Fn29XmMvmqIR3f0DMYK4GO7T+V53PgO03zuU0hEhQvzNwtAUxhARNaK+ukYpFCo83JLn8cwdvXwZOu25Phk/W5fcnxynscuG7fG/a7gp7m/K0hERQPzNwtAUxhARNa6eTlOb7vmSysYAEhOuIOPH6jp0Wri43tOuVvHlG2a77j71x/insBExQTzNwtAUxhARNZyuVyo/LD7Hb6Yk5d8Hsd4X29W/wV5Hrdu+hZIodDxg7B8x7x6/jqkUPj4gZpe9RkkosKH+ZsFoCkMICLrNflDB0ihELH6gM9jrJy8AVIotHyvS57H6R0+PFh04nA4ULFULUihcDn6qs9zIyL/Y/5mAWgKA4jIer0++wZSKCwdu8bnMeKuxeOjEjUghcK1izdyPe7r4GGQQmH+MM/azjT6fTtIobB37UGf50ZE/sf8zQLQFAYQkfXGtXevtp3Qcbqpcdr/syekUFj83apcj2n+p06QQmHnsr0ejWkUp0vGrDY1NyLyL+ZvFoCmMICIrLdo1EpIodDn8yGmxpk/bBmkUOj037Acf3e5XPj00bqQQuHC8ViPxhz/5Q9sBUNUDDB/swA0hQFEZL2dy/ZCCoUW73Q2Nc7ls1chhUL5+4KRcCsx2++3rrhXHJcv6fmK4yVjVkMKhV6ffWNqbkTkX8zfLABNYQARWS866gKkUKj2ZKjpsZq+9aV7l48Z2Xf5OLzN3XOw7iue9xyMWH0AUig0+UMH03MjIv9h/mYBaAoDiMh6dxJTfm7OnHDH1FjTes2FFAph1b/N9tvqqRshhULXCv08Hi/m5CVIoVD54Toe7zVMRIUP8zcLQFMYQET2qPZkKKRQiD583tQ4J/ed0QVbWkpalt+mfDULUiiM+mKyx+NlpGfo1cW3rsSZmhsR+Q/zNwtAUxhARPZo8U5nSKGwe8U+U+O4XC6EvNQcUijsWp51LKMFzILhy70as3a5FpBC4ciOE6bmRkT+w/zNAtAUBhCRPXpXHWy6F6Dhu1aTIYXCsCbjs3zf8l13kbljaYRX43X8IAxSKKyfudX03IjIP5i/WQCawgAisseYNlMhhcKkLjNNj7Vv3UFIoVDj+cZwOp0A3HcGqzxWD1IonDty0avxhjYaCykUZvQNNz03IvIP5m8WgKYwgIjsET5kKaRQGFB7hOmxMtIzdLF3dNdJAMDt6/F6ocm97wbmZ1a/BZBCYUjDsabnRkT+wfzNAtAUBhCRPTb/uB1SKLT/Z09LxutfazikUJjy1SwAwLHdpyCFQq0Xm3k91oZZ2yCFwpf/6W3J3Iio4DF/swA0hQFEZI8jO05ACoU6L3veoy8vG2e7i7ZGv28HwFwRZ8ytdrkWlsyNiAoe8zcLQFMYQET2uHbhOqRQ+PiBmvq9PTOSbiejwv01IYVC7OnLmNE3HFIoDG3k/WPcm5d/3kEkMyPT9NyIqOAxf7MANIUBRGSPzIxM3W8v7uptS8bs9GEfSKEwf9gyDA4dDSkUZg9Y6PU4LpcLnzwYAikULp25YsnciKhgMX+zADSFAURkn+AyTSCFwqn9Zy0Zb+HIFZBCoeMHYWj3jx6QQmHT3O0+jdXwt20hhcL+DYctmRsRFSzmbxaApjCAiOzT8r0ukEJh57K9lox3Ofqq+9HtfcFQzzWGFAonIk77NFa3TwZACoWVkzdYMjciKljM3ywATWEAEdmnZ5VBkEJh2fi1lo3Z5M0Ouv2LFAoJtxJ9GmdUy0mQQmFq99mWzY2ICg7zNwtAUxhARPYZ2WIipFD4ofePlo1p7P8rhULVJ0J9Hmfet0sghcLAOiMtmxsRFRzmbxaApjCAiOxjrNS9dws3M47uPKELwJbvdfF5nC3hOyGFQtu/d7dsbkRUcJi/WQCawgAiss/KSeshhUKPygMtG9PhcKDyI3X0YhBfnYg4DSkUgss2tWxuBSkjPQPJCXf8PQ0iv2H+ZgFoCgOIyD67lu9z36l7t7Ol4zb43wreVn/u6vMY8TcS9J3E9NR0C2dnL4fDgbnfLEb1pxuiYukQLByxwt9TIvIL5u8ALgAdDgd69uyJl19+GaVLl8arr76Kr7/+Gi6Xy+MxGEBE9jHusvmyXVtemv+pE6RQ+PzZRl797/1uLpdL30mMOXnJ0vnZJSUpBd0q9s+yCEYKhfPHYvw9NaICx/wdwAXggAED8NRTT2HFihU4d+4c5s+fj0ceeQSjRo3yeAwGEJF9jN1AKtxvzW4ghvq/bqWLn4snYn0ex1hRHLEm0rK52SUlKQVt/94dUihUfrgOVk5aj0a/bwcpFLYv3uPv6REVOObvAC4AK1WqhEaNGmX5rnr16qhTp47HYzCAiOyTnpZhul3LvRwOBz5+oKYeN3zIUp/H6vmp9W1q7JCelqF3Qan2VAMc230KAHQz7G0Ldvl5hkQFj/k7gAvAAQMGoFy5cjh58iQA4ODBg3j22Wcxa9asXM9JS0tDQkKC/sTExAR8ABHZ6bPH61v6mPLKuWu6GbTZhSCjW0+BFAqTu860ZG52cDqd6F9rOKRQqPKLeji+55T+zbgDyN1MKBCxAAzgAtDpdKJr164QQuC+++6DEAIDB+a92jAsLAxBQUHZPoEcQER2Cn29DaRQOLT1qCXj7d9wGFIo1H31C10IJt1O9mms+cOWQQqFfjWHWTI3O0zrNRdSKHz8QE3sX39If+9wOFDpodrudxhPXfbjDIn8gwVgABeAc+fOxYsvvoi5c+fi8OHDmDFjBp588kn88MMPuZ7DO4BEBct4TLl1/k5LxlsxcR2kUOj2yQA0fqM9pFDY/KNv+wFvW7gbUii0fv8rS+ZmNaNXoRQKq6duzPJbzMlLkELhkwdD4HA4/DRDIv9hARjABeCLL76IMWPGZPmuX79++M1vfuPxGAwgInuFVRvsfs9u3BpLxpvUZSakUBjTZiomdZ4BKRQG1fN84dfdTh+IhhQK6rnGlszNSueOXETlh92rlMd/mf0/ajf/uN3dCucvvrfCISrKmL8LSQHYvXt33LlTsE1Jn3zySYwbNy7LdwMHDsRrr73m8RgMICJ7DW86HlIozOgbbsl4fdUQSKGwcOQKHNp6FFIoVH+6oU93wRLjkvQdtpTkVEvmZ4XkhDv60Xln2TfHP5tR/I5sMdEPMyTyP+bvQlIAvv/++yhbtiymTZtWYNcMDQ3FCy+8oNvALFq0CE8//TS6dPF8eygGEJG9pnSbre/YWcHoAbh7xT44Mh2o9mQopFA4suOET+MZi1TOHbloyfzMcrlc6FtjKKRQCHmpOeJv5Pzvpo4fhEEKhVVTNhTwDIkKB+bvQlIAAsDMmTPxy1/+Eu+88w62bdtm+/USExPRrl07vPTSS7oRdI8ePZCe7nlXfwYQkb2MhRYDao8wPZbL5UKVX9SDFAoXjrv7//UPGQEpFKZ2n+3TmM3+2FEXlIXBkjGrde/Eo7tO5nhMZkamfjwcHXWhgGdIVDgwfxeiAhAAUlJSEBYWhocffhjVq1fH2bNn/T2lPDGAiOy19ofNkEKha4V+pseKu3obUih8VKKG3r5t/cytkEKh2dsdfRrTeEdxyZjVpudn1ukD0ahYqhakUFgwfOyk6W8AACAASURBVHmuxx3ddVI/+raywTZRUcL8XcgKQENsbCzq1q2LBx98EF26dEFUVFShXKnGACKyl7Ef8Bcm9u01HNlxQj8aNSTcTET5kjUghcK1ize8HnN8h2mQQmFCx+mm52dGSlIKGvzG/d5fr8++yXOLux8HL4EUCr2rDi7AGRIVLszfhaQATEtLw8aNGzF27Fi0bdsWFSpUQLly5VCiRAmUKFECQgiULl0a77zzjr+nmgUDiMheUduPQwqFer9qZXqsdTO2QAqFTv8Ny/J92/9zt5pZPmGd12MuGrUSUij0+XyI6fmZMaThWL1vcn67pvSoPDDfu4RExR3zdyEpAP/2t7+hdOnSeP/991GvXj30798f4eHhOHjwIFJSUhAXF4dNmzZh5MiR/p5qFgwgInudP3rRvYXZk6Gmx/qh94+QQmFYk/FZvp/VfwGkUOhZZZDXY+5cthdSKLR4p7Pp+fnK6PdXvmQNHNxyJM9jHZkOVHnM/R7kqf2F+xUbIjsxfxeSAvD1119HZGTh31D9XgwgInvdvBynixuz76sNrDMSUij8OHhJlu/PHDwHKRQqPVRbvxvoqXNH3AVq1SdCTc3NV9djbqLqE6EeL2Qx3v+r9mRooXythqigMH8XkgKwqGIAEdkrLSVN99pLjvdtyzZDq790hRQK2xbuzvK9y+VCrRebQQqFiNUHvBozJTlVzy8xLsnU/LzldDrR6cM++h3JzIzMfM8x7naGVf+2AGZIVHgxf/u5AOzVqxf27Ssc7RN8wQAispfL5dIrW69duG5qLKPn39lD57P9ZjSc9qXfoHqusV8eqS4csQJSKFR+uI7H+/l2ln0hhcLi0atsnh1R4cb87ecCsGHDhnjmmWfwwgsvoEWLFli1apVXffj8jQFEZD/1bCN3z7rD2Qs3TyXcStR36lLvpGX7ffviPXqxSV4raHPS+q/d3HcWF+zyeX7eOn/0IiqWDnFvkzd+rUfnpKWk6XPOH4uxeYZEhRvzdyF4BOx0OrFt2zZ07twZr7/+Oh599FFUr14d06dPx61bt/w9vTwxgIjsV/+11pBCIeqnYz6PcWz3KUihUPOFpjn+npKUou80XjwR69XYRjPp8CFLfZ6fNzIzMtHy3c6QQqHbJwM8Llj3rTvoboPzy+ZeF7lExQ3zdyEoAO917NgxDB48GH//+99RqlQp/POf/8SQIUMQG+vdv5QLAgOIyH5GsbN75X6fx9gwaxukUOjw7165HtPlo74+tUcxtqsb1XKSz/PzhrGaudpTDXDzcpzH503qMhNSKAxuMNrG2REVDczfhaQAHDVqFC5dupTt++vXr2Pq1KmoUqUKhgzxb5+tnDCAiOxn7Fu7+cftPo8xPWwepFAY2nhcrscsGL7c3Sfwwz5ejb1qygZIofDVx+Z3K8nPyX1nUP6+YJ/+PoxCev3MrTbNjqjoYP4uJAWgEAKvvvoqLl7MuqF6RkZGoV4kwgAisl/PTwdBCoWVk9b7PMaA2iNybAFzt5iTlyCFwscP1MSdxBSPx47cFAUpFEJfb+Pz/DyRnpaBJm92gBQKXwcP8+rc+BsJ+h1Ib+4aEhVXzN+FqABs1qwZXnnllSxF4NWrV1GiRAk/zixvDCAi+xnF2/xhy3weo+V7XSCFwvbFe/I8znjf8KdFu/M87m5Xz1/XhaOdvfWmfDULUiio5xoj/oZ3/87Z/ON2SKHQ5A8dbJodUdHC/F1ICsASJUrg2rVr6NmzZ5Yi8OrVqxBC+Hl2uWMAEdnPaNEy8+v5Pp3vcrn07hfnjlzM89gxbabmuFtIXhwOBz5+oKYlrWpyc3zPKb1nsTfFqWFYE/ff4fgO06yfHFERxPxdyApAwN0b0CgCeQeQiMZ3mAYpFCZ3nenT+XFXb0MKhY9K1Mh3p4+I1Qf0amFvVsoadw4Pbs57KzZfpKemo/Eb7SGFwoDaI7w+3+Vyoc7LLU0vpCEqTpi/C0kBKITQBSAA9O7dG6+88gr27NnDApAowE3rORdSKIxuPcWn8w9vOwYpFOq83DLfY9NT01H54TqQQuHMwXMeX6NrhX6QQmH11I0+zTEvxirjGs83RsLNRK/Pjz19WT+iTkny/N1GouKM+buQFIADBw5EcnLWbZ569+6NZ599lgUgUYCbM3ARpFAY0nCsT+evnroRUih0reDZKl1j0cmcgYs8vsbIFhM93o/XG3ev+vXl0S8ALBu/Nt8WOESBhvm7kBSAuenXrx8ee+wxf08jVwwgIvsZW571D/H+8Sfwc/87T+8gLh27BlIotP9nT4+vET50mXuOtYb7NMecZKRnoNnbHSGFQr+a3q36vVtfNcTUO5RExRHzdyEvAAs7BhCR/VZMXAcpFHpXHezT+b2rDnbvf/udZ/vfGqt6y5esgYRbnj1yNbaS++LPXX2aY05m9A2HFAqfP9MQt6/H+zSGw+FAtacaQAqFoztPWDY3oqKO+ZsFoCkMICL7rZu+xatHuPdq+Nu2kEJh37qDHp9jLLrwtNly9OHz7t05ngz1aY73Onfkol5ZvHHOTz6Pc3LfGUihUOWxenBk2teihqioYf5mAWgKA4jIflvm7fD5HbbMjExUuP9/LVou3vD4vAkdp3u1bVpKcqputOzpXcPcOBwOtP5rN0ih0PPTQab27f1x8BL3OFUGmZoTUXHD/M0C0BQGEJH9jMerrf/azetzL56IhRQKlR+uA6fT6fF5xu4e6tlGHp8XXLYppFA4EXHa63nezXjnscpj9XAj9qapsYzVyQtHrjA1DlFxw/zNAtAUBhCR/fascvfma/FOZ6/P3bE0wqdzMzMyUeUX9bwq6Nr/syekUNg01/c9iy9HX9VtaFZMXOfzOIB7EUmlh2pDCoXoqAumxiIqbpi/WQCawgAist+BjYfd25i96f02ZsYjUF9WEIdV/xZSKMzoG+7R8d82HAMpFGb1W+D1tQB3w2bjjt2X/+lt6tEv8HP/Q/VcY9NjERU3zN8sAE1hABHZ79DWo5BCocFv2nh9rlGUzejjWRF3t5WTN7gfPb//lUfHz+q/wKv3Bu9lLHapWDoEMScv+TTG3Wb0CTfdQoaouGL+ZgFoCgOIyH5Hd56AFAr1ftXK63ONxRRbwnd6fe6N2Jt6CzlP2rAYi1Xa/r2719eKuxav27V404A6L1/+pzekUFg+wdyjZKLiiPmbBaApDCAi+52IOA0pFGqXa+HVeS6XC1Ueq2fqHbjmf+oEKRTWz9ya77GnD0Trvn3eGlhnJKRQaPbHjsjMyPRlqlmkp6ajYukQSKEsuZtIVNwwf7MANIUBRGS/U/vPQgqFWi828+q8G5duuRs63xeM9LQMn65t7MM7oHb+7xCmJKXoVjBJt5PzPd4QsfqAbjxtdgWx4eDmI5BCIbhsU77/5wOHw4GLJ2K9+udIRQvzNwtAUxhARPY7c/Ccu5gp08Sr8/avP+Tzu4OGqJ+O6QbPnjRSDi7TxKuVwynJqaj7SktIoTCu/TSf53mv6WHzPC5c6WcXT8RiTJupqPZkKKRQqPRQbRzfc8rf0yIbMH+zADSFAURkv7OHzuvVrN5Y/N0qU1vIAYAj06GLgajtx/M9vsO/enm1e4fRcLp2uRZISUrxeZ734vt/3jl76Lxe9X3vZ9n4tf6eHtmA+ZsFoCkMICL7GdusqWcbeXXeiOYTIYXClG6zTV2/f63hkELh+x5z8j12aKOxHq86Pn0gGuXvC4YUCrtX7DM1x7ulp2Xgkwfd7/9dOB5r2bjFUezpy+gfMiJLwdezyiCMbfe9XgDEv8PiifmbBaApDCAi+0VHXfCpADQaM2+cvc3U9Y32LM3/1CnfY+d+s9ijR6+OTAdavtfFljYtUduPs/9fPhJuJWJM26l6m0Djn8P5oxdx5dw1VH+6IaRQGNvue39PlWzC/M0C0BQGEJH9fCkAXS4Xqj7hfnR75uA5U9e/fT0eH5WoASkUbly6leexO5a4dx5p+W7eO48sHOne7q3qE6G4dSXO1PzuNWfgIkih0OfzIZaOWxxkZmRi0aiV+rG+FArdKw3A6choAO6FPM3e7uj+Z/heF6Snpvt5xmQX5m8WgKYwgIjspx8Be/EOoF4BXLKGJUm89ftfQQqFVVM25Hnc+WMxkELh00fr5nr37drFG6j8SB3b3tHr9skA7v+bg/3rD6Hh79rpwq/pW19i//pD+vfMjEx89bF7J5YazzfG9Rhz+zBT4cb8zQLQFAYQkf2MRSA1nve8ANy79iCkUGj427aWzMHYVSO/u2oZ6Rn6vb6c7ha6XC70+uwbSKHQ7h894HQ6LZmfwel04rPH60MKhZP7zlg6dlF17eIN9FVDdOGnnm2E5RPWweH4eVW3y+XCN/W/gxQKlR+uw5W/AYD5mwWgKQwgIvsZDZaDyzb1+Jz5w5ZBCoW+yprHoCf2ntF39jLS8+4pWP+11pBCIXJTVLbfti/eAykUKtxf0+fm1HkxHpdXfqSOR21rirOM9AzMHbQIlR+uo/tBjmk7NVtvP5fLhfEdpulj9qw64KcZU0Fi/mYBaAoDiMh+RvEV8svmHp9jZg/gnDidTtR4vjGkUDiw8XCex3avNCDH9iF3ElMQ8svmlqxMzs3yCesghUKnD/vYMn5RcXDzkSyPe9v/syfOHjqf47HG3V0pFNZN31LAMyV/Yf5mAWgKA4jIfsd2n4IUCnVfaenxOS3f7QwpFLYt3G3ZPAY3GA0pFCZ0nJ7nceO//CHHFaRGa5F6v2qFtJQ0y+aVZY6h7jlO6znXlvELu9vX4/XfgfHe6LrpW3J9H3PhiBX62MXfrSrg2ZI/MX+zADSFAURkP6OtSf3XWnt0vCPToffBjT192bJ5bAnf6dF7hSsnb4AUCl0r9NPfndp/FuVLulcSR6yJtGxO9zIePwfaY0yXy4XVUzei2lMNdP++US0n5bmV28pJ63XxN/Pr+QU4WyoMmL8DvACMjY1FnTp18OSTT6J06dJ48803sXfvXo/PZwAR2S9yUxSkUGj0+3YeHW+sxK38cB1LF1kkxyfrvnGXzlzJ9TijYA15yf3I2uFw4Is/d4UUCv1D7NuaLeFmoi5oEuOSbLtOYXPheCw6/LuX/rM3+2NHHN11Ms9z1s/cqlv7TOo8g/0SAxDzdwAXgHFxcShXrhwaNGiAPXv2IDo6GmvXrsWZM56vnGMAEdnPWNHb7I8dPTp+y7wdkEKh9ftfWT6Xjh+EuR8Xjs79cWHCrZ8LsZSkFCwe7d6S7rPH6+PmZWt7/t1t98r9lq58LuzS0zIwo084KpaqpQv+8KHL8l38snX+Tn039rtWk1n8BSjm7wAuALt27Yp//OMfpsZgABHZb8fSCK8KuindZkMKheFNx1s+l/AhS7M93s2Jes69YGT3qgOo8ot67kUh49ZYPp+7/dD7R0ihMDh0tK3XKQyith9Ho9//vMije6UBuHLuWr7n7Vgaoe/iDmk41vI2PFR0MH8HcAH4u9/9Du3bt4dSCs888wz++Mc/YtKkSXmek5aWhoSEBP2JiYkJ+AAispvx7l2Hf/Xy6HijEfLSsdYXXBeOx0IKhYqlaiElKSXX44xHkq3+4m4g3fqv3WwvNowmxnb8uQuL5IQ7GPXF5CyLPDb/uN2ju3gRayL13cKBdUZm6QNIgYcFYAAXgKVKlUKpUqXQrVs3HDhwABMnTkTp0qXxww8/5HpOWFgYgoKCsn0COYCI7LZuhnsv3i7lv/bo+OAyTSCFwtGdJyyfi8vlQr1ftYIUCjuWROR63MgWE3WRUv6+YL3VmF1cLpdeAHFib/FsAL1r+T7dRkcKhaGNxiLhVqJH50ZuisInD4bo3pCB3iORWAACAVwA3n///fjb3/6W5bs2bdrgr3/9a67n8A4gUcEzetv1rjo432Pjrt7Wq0BTklNtmc/o1lPyfcRsNKKWQmF8h2m2zONul6OvQgqFjx+oifS0vBtVFzW3r8djQO0R+u+z3q9a5duL8W5RPx3TzaB7VhmUbyNvCgwsAAO4AHzppZfQuHHWraXGjRuHsmXLejwGA4jIfkavtoF1RuZ7bMSaSNsXQhjXqPlC01wfPQ6qO0rf/buTmPujYqtsne9+TN7yvS62X6uguFwubJy9DdWfbqj3dZ7YaTpS73jeQ/HY7lP6HcyvPu5X7Ipj8h3zdwAXgCEhIdkWgbRv3z7bXcG8MICI7Der3wJIoTCsSf6LOuYOWuRut1JruG3zSU/LQOVH3HeUTu0/m+3388diUOGBmj+vBLbpTuTdJnedadvCF3+4EXsTPasM0n+HTd/60utH26cPRKPqE6HunVH+G+ZV4UjFH/N3ABeAERERuO+++zBgwACcPn0as2fPxkMPPYRZs2Z5PAYDiMh+RnEzrv20fI/tq4ZACoV53y6xdU69qw52bzXXN+tWcy6XS7eK+fh/ReDJffa/k9el/NeQQmHFxHW2X8tOLpcLq6ZswGeP19d/hzP6hnv92DY66oK+c9juHz3yXLBDgYn5O4ALQABYvnw53nzzTZQqVQq//e1v810FfC8GEJH9jFWf03rlv71Z3VdaerRfr1nGbh9f/Llrlu/XTXcvWKn0UG20/mu3Atlf1uVy4fNn3MXOiYjTtl7LTlfPX9eFrNH259yRi16Pc/FErN63udVfuiI54Y4Ns6Wijvk7wAtAsxhARPb7pv53Ht3Vu3snjLy2ALPCrStx+lpGc+eEW4lQzzaCFApzBy3Si0UmdZ5h61xuxN7U7xvatcewnZxOJ5aNX4tPH60LKRQ+eTAE4UOW+rRS93L0Vb1SuNkfO3q8SpgCD/M3C0BTGEBE9uv12TcePd40dgzxdM9gs1r9xb2926opGwAAI5pNgBQKTd7sgMyMTKyYuM6jptFmGTuANH6jva3XscPl6Kvo9N8wXUy3+0cPxJy85NNY12Nuou6rX+htA29fj7d4tlScMH+zADSFAURkvy//0xtSKGz+cXuex80ZaP8CkLvN6Buu29Mc3XVSFzGHth4FAP1dcJkmts5DL3yxcZ9hqzmdTiwdu0Yvpqn8cB0sGrXS52bZcVdvo+Fv2+r/ALBzyz0qHpi/WQCawgAisl+ztztCCoWINZF5HmcszAgfuqxA5nU6Mlo/smzyhy8hhcK3Dcfo31OSUnRRaOfdKKNH3pyBi2y7hpUuR1/VC2WkUOjw7164dOaKz+Ml3ErUMRLyUnNcPX/dwtlSccX8zQLQFAYQkf1CXmqe7wIHl8uF4LJNIYXC4W3HCmReLpcry84U1Z5qkK3QM3YNsXNRSpM/dHDvO7xin23XsEJOd/0Wf7fK1BZ5dxJT0Pr9r/Sd1phTly2cMRVnzN8sAE1hABHZzygYYk/nntyvx/y8EKIg+u4ZjIbPUiisnLwh2+9h1dx3JReOWGHL9R2ZDt1u5sq5a7ZcwwpXzl1Dpw/7WHbXDwDSU9P1+4PVnmqA6KgLFs2WAgHzNwtAUxhARPZKT033aGXvtoW79crPgtTu/3rofnWZmZnZfp8eNg9SKAwOHW3L9S+eiNV308zcSbOLy+XCionr9ArfSg/VNvWunyEzI1M3iv700bpFuv0N+QfzNwtAUxhARPa6u8VJbtuuAcCkzjMghcKIZhMKbG7G6lvjk1MRsmNJhLswfduewnT74j3uLeDe7WzL+GZcj7mJrz7ul3WFrwWPaJ1Op77z+smDITi45YgFs6VAw/zNAtAUBhCRvYyFFjWeb5znce3+4b4Tt/aHzQUyr9Q7abrpdOjrbXJtVH31/HVIoVDh/pq27ENrrHweVHeU5WP7yuVyYd30LXo3j4qlQzB/2DI4HN739ctp7DFtpur/KNi1vHC/90iFF/M3C0BTGEBE9tq3zt3br8kfOuR6TEZ6Bj55MARSKFw8EVsg85rSbbZedWr0+2v61pfZjnO5XKj2VINc9w02a3DoaEihMKvfAsvH9sWtK3G6b6Oxm8eF49b9MzEeqX9UogY2zt5m2bgUeJi/WQCawgAistf6mVshhUJn2TfXY47tPqUXAuT1mNgq549eRIX73Qsvti/eg4RbiSh/XzCkULh89mq2443FD0bDaCsZ281tnb/T8rG9tSV8p95/9+MHamLOwEU+7eaRmyVjVuvCcsmY1ZaNS4GJ+ZsFoCkMICJ7zft2Sb6POBcMXw4pFHpUHmj7fJxOJzr8uxekUOj12Tf6e6Ov3cKR2Vf7Tug4HVIojPpisuXzMQquMwfPWT62pxJuJqJ/yAhdnDX/UyecPXTe0mts/nE7PipRA1IoTA+bZ+nYFJiYv1kAmsIAIrLXuPbT8t1PN6z6t3r/Xbut/n6TXnV7d8PhhSNWQAqFL//TO9s5G+f8pB+HWinpdrIuulKSUiwd21O7V+5HcJkm+p28ab3mIiPd2ncd9284rFvdjPpicoHc5aXij/mbBaApDCAie/WrOSzXO2uA+x079WwjSKEQtf24rXOJv5Gg77jN+3ZJlt+unLvmLoJK1kD8jaz/Pog5dVkvhsjMyN4qxlen9p+FFArqubwXyNjhTmIKhjcdrwvQhr9rZ0srltMHonULma+Dh1mykIQIYP4GWACawgAislfb//XZy+0dN6MPXsXSIbassr3b0EZj9WKPnAq5Zn90b0e2ZtqmLN87nU5Ueaye5Y9qt87fCSkU2vytm2VjeuLQ1qN6BbQUCuM7TENaSprl17kcfVXfXez03zDb//lSYGH+ZgFoCgOIyF7GNnBHd53M8feVkzfonSXsdGjrUV3wHNlxIsdjjBWqPasMyvab8Y7g6qkbLZtT+JClkEJhQO0Rlo2Zl/TUdEzsNF2/i1fn5ZY4uNmeHnwJNxPR4DdtdA/F5Pjcm4AT+YL5mwWgKQwgIvs4Mh16de2NS7dyPMZoCDytZ/YefFbJSM9Ao9+3gxQKw5uOz/W46MPn9d3Ie9/Js6NR9XetJkMKhSndZls2Zm5OH4hGkzc76CJ4aKOxSE64Y8u10lLS9J3f2uVa4EbsTVuuQ4GN+ZsFoCkMICL7GE2UP36gZo5bh7lcLtR8oSmkUDiw8bBt85g9YKF+1y4xLinX41wuF+r/ulWOj6y3LdilV8hapeen7q3Qlk9YZ9mY93JkOjB7wELd9kY91xg7l+217XpOpxN9awyFFAqfPV4f549etO1aFNiYv1kAmsIAIrKP8di1/q9b5fh7zMlL7jtupWrZ8g4aAMSevoyKpd1NpjfMyr/x8MRO7pYv/UOyPpa9dvGGXimbeseauRrvHO5ZdcCS8e4Vc+oy2v69u77r1+fzIbh9Pd6WaxmMO6UVS9Wy7fEyEcD8DbAANIUBRGSftT9szrMJ9PIJ62x9/8/lcqFL+a8hhUKXj/p61H7k6K6TkELh00frIj01PctYwWXddyujfjpmyfw+f8a9ItnqnnsulwvLxq9F5YfrQAqFKo/Vw7rpW2xvv2L88/S02CYyg/mbBaApDCAi+0zrOTfP9+a+Dna3iJnRJ9yW62+YtQ1SKHzyYAhiT1/26Byn04laLzaDFCrbPrVh1QZDCoXwIUtNzy09LUMXS/e2nTHj5uU4dPtkgB6703/DcO3C9fxPNGnfuoP6fc8Zfe3550l0N+ZvFoCmMICI7GPsLpFTweR0OnVPPjv6/yXcStT9BWf1926f3TFtpkIKhcENRmf5fu43i/WjVLPufj/Sqjtz2xbs0vsWVywdggXDl+f47qXVzh+L0W1yBoeOZqNnKhDM3ywATWEAEdmn5XtdIIXCjiUR2X4zmiBX+UU9S5srG4Y2HgcpFBq/0d7rnS2MdxerPhGa5dzD245BCoXgMk1MFznH97j3Pw75ZXNT4wBAcnwyBoeO1nf9WrzTucAWXyTcTES9X7kXzrT/Z0/2+qMCw/zNAtAUBhCRPVwul94B4vyxmGy/zx20KNeee2Yd3HJEF0O+vK/ncDh0A+O7F2ikpaTpLc0uR181Ncedy/ZCCoWW73UxNc7BLUdQu1wLvYvJ1O6zLd/KLTcZ6Rm6P2LdV7+wfYEJ0d2Yv1kAmsIAIrLHjdibetVsTgXJl//pDSkUloxZbel101PTdQPiEc0n+jzOqJaTIIXCtw3HZPm+1V+6WrLIYfXUjZBCoVvF/j6dn56WgUmdZ+imznVf/cL2rfTuNbLFRH0XNzrqQoFem4j5mwWgKQwgInvsX38IUig0+E2bbL8lJ9zRfekunbli6XWn9XIvPAku2xRJt33ffeLg5iM5PgYe134apFAY2cL34hIA5n27BFIoDKo3yutzow+fR7O3O/7c1LnxONxJTMn/RAutmOhe8ftRiRrZFssQFQTmbxaApjCAiOyxcOQKSKHQu+rgbL/9tGi3uz/ga60tvea5Ixf1I9rc9h72lMPh0G1fdq/cr7/fttA99yZvdjA1/uSuMyGFwth233t8jtPpxPxhy1CxVC1IofD5Mw1zfL/SblHbj+u/59kDFhb49YkA5m+ABaApDCAiexiLMHLa4s34bUzbqZZdz+FwoM3fukEKhV6ffWPJStTRradACoVv6n+nv4u7Fq/vvCXcTPR57BHNJnjVAufaxRvo9GEffe0elQci7uptn6/vqxuXbun3I/vVHMYVv+Q3zN8sAE1hABHZw3hXbkt41jtxTqdTFxD71h207HqLv1ul30e7HmPN3rNR24/rMe9uCt3wd+1yXd3sqX413T0QF45cke+xG+f8hM8erw8pFCo/XAfLJ6zzS+GVkZ6h9/ht8ocO2fZLJipIzN8sAE1hABFZz+FwoNJDtSGFQszJS1l+O7H3jN5pw6rVqtcuXEflR9y7Xiwdu8aSMQF3sWqssP1p0W79vXH3bnyHaT6P3a1if0ihsGbaplyPSbqdjAG1R+i7fq3f/woxpzxraG0Hoz/iZ4/X97ixNpFdmL9ZAJrCACKy3vmjF913qx6pk60RsbE7SF9lvpky4G43YxRT7f7Rw/LGx8bewH1rDNXfbZq7HVIoNP9TJ5/HbfcP95206I32pgAAIABJREFUbQt25fh75KYohLzUXK+knh42D45Mh8/XM2vzj9t1IbpjacG/d0h0L+ZvFoCmMICIrLd+5lZIodD2/3pk+63Jmx0ghcL6mVstuda6GVv0zhcXjsdaMubdTh+I1uMnJ9wBANy6EqdXwCbc8u09wOZ/6gQpFCJWH8jyfXpaBiZ2mq7bu9R/rTWO7jpp+s9hRszJS7qn45SvZvl1LkQG5m8WgKYwgIisN6bt1BwXecScugwpFCrcXxOJcUmmrxN39bbe+syu1agul0u/87f2h836+0a/b5ft0bA3jDEPbjmiv4uOuoBmf/y5vcvwpuP9/p5dWkqabjnT8YMwv96FJLob8zcLQFMYQETWa/1X92rcjbOzNks29tLt8lFfS67Tt8ZQ/SjWju3kDDO/np9t3t+1mgwpFEZ9MdmnMeu+0hJSKBzbfQpOpxMLR65AxdIhfm3vkhOj2bN6rjFuXo7z93SINOZvFoCmMICIrJWelqH71N3b5NnYG3j5hHWmr7NtwS59N/H0gWjT4+Xl8tmrequ1G5duAQB2LImAFAqhr2dvdO2Jmi+4ewzuXRuJLuW/1nf9ulca4Jf2Ljkxeh6652ndim0iKzB/swA0hQFEZK2ju07qu1h3tyq5HP1zERV3zdyesfE3EqCebQQpFL7vMcfslD1itD8JH7IUAJAcn4zy9wVDCoWr5697PZ56rrFeUSuFQqWHamPp2DWFpq/e9ZibqPZkKKRQmNRlpr+nQ5QN8zcLQFMYQETWCh+yVDdjvpvx+LfTf8NMX6N/yAi9G0d6mjWtZPKzbPxaSKHQ9K0v9XdGUbhy8gavxrqTmIKKpWvpu2st3+1sywIWXzmdTnT6bxikUPjiz10ta9dDZCXmbxaApjCAiKzVs8qgLHfKDMZCAm+LpXsZ28iVvy8YJyJOmxrLG4lxSfrR9ulI9yPnGX3CIYVCn889b2lzZMcJ1H31C138DWs6vtAVWPOHLdNtfPzZd5AoL8zfLABNYQARWcfhcKDqE+7Hhsf3nNLfnzvi7gv48QPmVv/e/eh3SrfZVkzZK8aiE2P/3uN7Trl3CnmsXr6LUDIzMjGt11yUL+lu7/LR//7v+aMXC2LqHjt35KIudFdMNP+uJpFdmL9ZAGqDBg1CUFAQ2rVr5/E5DCAi65zaf1ZvnXZ3u5DJXWfm+FjYGy6XSxdgTf5QcI9+77Z75X79fmNGegacTic+f6YhpFA4tPVorufFnLqM1u9/pe/6Dao3Cp8/7T4v+vD5AvwT5C0zIxMt3+2sF6MUlvcRiXLC/M0CEAAQERGBl19+GW+99RYLQCI/+XHwEkih0KPyQP2dw+FArRebQQqFrfN35nF23jbO+Umv+j21/6wV0/WaI9OB4LLu1bvbFrr7/w2qO8q9UKLzjGzHu1wurJi4DpUfdm9TV/WJUGz+cTsA6HHsXsHsjVn9F0AKhWpPhrLlCxV6zN8sAJGUlITXXnsN69evx7///W8WgER+0ln2hRQKi0at1N/tW3dQFxW+3rW7EXtTP1qe0Sfcqun6xLib2b3SAAA/b5HW8HdZ/70Tdy1evw8phUKnD/vg2sUb+ve7+wAWBuePxehHv+tmbPH3dIjyxfzNAhD169dH+/btAYAFIJGfpCSn6gLi4omfV7T2rzXcVMNkl8uFrhX66RWpdjZ89oSxm0n5kjVwPeYmkuOTUeH+mpBCIfa0e8HE7hX7dJuXiqVqIXzosmx7FOudQDYfyekyBcrpdOoVzT0qD+SjXyoSmL8DvACcO3cu3nzzTaSmpgLIvwBMS0tDQkKC/sTExAR8ABFZYeeyvZBCoc7LLXUBkXAzUReFvj62XTJmNaRQ+ORBe/b69UWHf/WCFAozv54PAOj0YR9IoTBn0CK9c4bxruLZQzm/49fiHfe7dntWHcjx94JktLj59NG6We5SEhVmLAADuAC8ePEinn32WRw6dEh/l18BGBYWhqCgoGyfQA4gIiuMaDYh252+BcOXQwqFFu909mnMC8dj8cmD7u3RFn+3yqqpmrZ+5lZIoRDyUnM4HA4sGrXSXaQ+VFsXf+PaT0N6anquY3T4t7uI3BLu+3uRVrh1JU43oy5Mf8dE+WEBGMAF4OLFixEUFISSJUvqT1BQEIQQKFmyJByO7JuW8w4gkfWcTieCyzSBFAoRayIBuB/dNvhNG0ihsGz8Wq/HzEjP0HfJulboV6geS6anpqPaUw0ghcKOZXsxsfMMXfgFl22C/esP5TtGz08HWdIX0axB9dyLWFq+1yXHf2cSFVYsAAO4AExMTERUVFSWz3vvvYe6desiKirKozEYQETmHd15Qrd/MRZ67N9wWD9WvJOY4vWYk/5XVFV/uqHef7cwGdd+mntl7/+2SzM+84ct8+h8o/Ca9+0Sm2eau6ifjrl7EpaoUaBNtYmswPwdwAVgTrgIhKjgjf/yB0ihMKD2CP1d76qDfV78sX/9IV1QbV+8x8qpWsLlcmHOwIV6jpUfrYuvg4fp1b6eGNvue0ihMLmrf/bZdTgc+g7rsCbj/TIHIjOYv1kAZsECkKhgOZ1OhLzUPEuxdjn6Kj4q4d7pwtuFG7evx+vHySOaT7Rjyqbcvh6PsOrfZrnrN7LlRFw+e1WvDo67Fp/vOEbPvaGNxhbArLNb/f0mSKHw2eP1cft6/vMlKmyYv1kAmsIAIjLHeIxY5Rf19KIH4+5W1wr9vBrL6XSi2ycDIIVC4zfaI/VOmh1T9tnulftR4/nGelu7b+p9px9Tp6Wk4Ys/d4UUCkvHrsl3rJWT1mdrml1QUu+k6UbU9+7ZTFRUMH+zADSFAURkjrH6d3CD0QCAxLgkVH7EvfPF3rUHvRorfMhS3fKlMG2RlpKcmqW9S+M32uP0gWg4HA7ULtcCUiis/n4TwocugxQKbf+vR75j7l6xz9QKaTPmDFwEKRTqvtLSL1vqEVmB+ZsFoCkMICLfpaem6xYi+zccBvDzo82mb33p1crdo7tO6obKyyess2vKXju66yTqv9Y6S3uXtJSf70wa2981e7sjbsTe1I++r5y7lue4pyOjIYWCeq6x3X+ELBLjkvQ/s/UztxbotYmsxPzNAtAUBhCR7zbN3a774TmdTqTeSYN6thGkUNgwa5vH4yTcTNTvEfavNbxQtHzJzMjEtF5zUb6ku6AL+WVzXeTeLTEuSe/1G7kpSjeFntVvQZ7jJ9xM1EXl3QWl3ab1nKubVN+7OwlRUcL8zQLQFAYQke86/TcMUij80PtHAMDCESv0o0VHpmc95e5+7y/09TZITrhj55Q9cv7oRbR8t7Mu0AbWGYmk28m5Hj+q5SS9P/C66VsghUL911rnWci6XC58+mhdnxbK+CrhViKq/KIepFDYtnB3gVyTyC7M3ywATWEAEfkm5uQlver12oXrSEv5eWHByknrPR5n5tfzIYVCpYdq57ptWkFxOp1YOGIFKpZ27z5S7clQbJm3I9/zYk5d1o9+T+w9o9+BjPrpWJ7nNXu7I6RQ2L1yv1V/hDzN6BOuH1fz7h8VdczfLABNYQAR+WZM26lZVrEa277VLtcCGemeLSyIWH1AF05rpm2yc7r5unr+Ojp+EKbv+nWr2N+rBtRh1dx9D4c0HIshDcdCCoVvG47J85y+NYZCCoUFw5ebnX6+UpJT9e4lm3/cbvv1iOzG/M0C0BQGEJH3khPu6EeJEWsicScxRb/75+nWZpfPXkW1/+2iMaLZBJtnnDuXy4XV32/Sf57KD9fBsvFrvX4P8eiuk7o9zPbFe/RdzeT43B8dG+/jFUQj5qVj10AKhXq/asUt36hYYP5mAWgKA4jIe/OHududNPxdOzidTv1osf5rrT169y8lORVN3/oSUii0/ms3v7UiuXUlDj2rDNJ3/dr+Xw/Enr7s83gd/t0LUiiMbfc9Gr/RPt+egMYimrZ/7+7zNT3hdDoR+rp7X+bFo1fZei2igsL8zQLQFAYQkXcy0jMQ8svm+m7frStx+p03T96Xczqd6KuGQAqF4DJNcCP2ZgHMOrst83boR6IVS9XC3G8Wm74ztnftQX3nb/aABXq1bW53E88duaj3S7bznTxjXlUeq4eUJO/3ZSYqjJi/WQCawgAi8s7qqRt18Zaemo5hTca77+S9/5VHj02nh83Tj0qjth8vgBlnFX8jAf1rDdd3/Vq809myptMul0vvBjK23fe6PcyhrUdzPN6R6dALTszcecyPsXXd6NZTbLsGUUFj/mYBaAoDiMhzjkwH6v+6ld5C7PSBaL2Iw5Nibsu8HbrwWj11YwHMOKsdSyKgnnNv5Vb+vmBM6zXX4wUrHl9jaYT7XcJH6uCb+u6t4vp8PiTX41u//xWkUNg0156FGXHX4nWD7eioC7Zcg+j/27vvsCiuhQ3gu6KgRgG9GmvgJiYmUW/aTUjyJTfmXldARVCzNBURkaLYu7FgiRUVFY1d1KgoURELlljQCIoNVFTsBQtF6SJt9/3+IExYl7LLLm33/T3PPI8ss7NzmCPn5cycc6oD228GQI2wAhGprqj376fmbniVmY0R300pnLzZ2b/c9944dxvdGxT2dq0as6kKzvZv6S8zMK//MiF8Du40GnEX7lbKZ8nlcmEOQb9BK4WpckpbGSRg2Hqhx7Ay7F5aODejj8XESjk+UXVh+80AqBFWICLV5L7OFVbrCF60D4c2nhB6upLiy36O79n9BGGU8FTbeVU6CjUi9DwcWg0Wgti6ib8h93VupX5m5L4LwojiooEhq0YHlrjv8W2nIRFLMfSrygloRbekOfiDdA3bbwZAjbACEakm2C8UErEUTm09kfgoCX2auUEilmLnwr1lvi/9RQbcPhohPG9XVYMQ0l8o9voN6jASN87drpLPlsvlGPbN5MLA23OeMNAjIyVTad/Ex8nCLelXGdr92Tx/kCgE35TENK0em6i6sf1mANQIKxBR+dKS02FnOqDw2b2NJzC331JIxFJ4fDIG+Xn5pb7v9asc4Taxs5mXWhMra+L07nN/P+tnYI+1Eyq/1+9Nl49fhUQshVU9ByEAb/2l5PWB+787BBKxFFFhl7V6DkVL8435cbpWj0tUE7D9ZgDUCCsQUfn8PVdDIpbC6/Nx+DPknBCs4s7fKfU9BfkFwhx7vZq44kHs40o/z5SEVMxyWCz0+rl3HFVlvX4lmWA5CxKxFMO//RkSsRR9mrkhO+u10n6L3H8t8zZxRY3rMqPKVhohqmpsvxkANcIKRFS2uAt3hZG+kfsuwL5lYc/a2vFbSn2PTCbDgoEBkIil6N7AGVdPl70mrqbkcjmObg4X5vWzrOuADT9vq7YJposUHyXt9I6nMHr6TeHBkcLE2tqSnfUa1oaFo3/jbz3V2nGJagq23wyAGmEFIipdQX4BvL8oHNE6t99SYT45946jSr2lKpfLhXWCLes6ICL0fKWe4/MHiZhkPVvo9fP6fBzuXL5fqZ+pjgWuhUHY5f1hkIilkL49SKkXMDM1C5Z1HSARS/HsXoJWPvfi0RhhbWZ1l7Ujqg3YfjMAaoQViKh0QfNDIBFL0bupK4IXhQoTON++dK/E/eVyOdZP3iaEsaNbwivt3AoKCrDb/4CwCkm3+s7YPndPmc8kVofkJy+ECaGLek+D5u1R2m/sf321ers2cFrhOsPzByzXyvGIahq23wyAGmEFIirZwxvxwioVW2b9LszhV9ao36I1gctbA1dTd2MewMdiovBZoztPw+O4J5X2eZr6bdbvhc9CNnUVAnVmapbCPiHLw7S6LnDR84f7Vh3RyvGIahq23wyAGmEFIlKWl5snTGY8oetMuLYfDolYisnd55S6Zm1RyJGIpfh98b5KOa/srNdYO+E34XapnekA7F99tFLX0dWG3Ne56P/e0MKBIM0Lp89ZN/E3hX2Sn74UnhdMeJik0efJ5XJhmp5bFytnwmui6sb2mwFQI6xARMrWTvhN6LEqer7O2cwLacnK/0/kcrlwu1EilmLHgrLnBayocwcuCtOlSMRSzLRfVGXTymjD2f0X/xo97SDcsn4z6I35cTokYim2z1W+RayOl89ThJHaVT39DVFVYfvNAKgRViAiRVFhlxVClkQsRTcjJ9yMUp5ORS6XY824zcL+5U0KXRFJ8S8w4yc/4TP6mnvj7P6LWv+cqjC91wJIxFLYmrgULqHntETh+0Wrq7i2H67RwI0rp64XDjxp56PpKRPVWGy/GQA1wgpE9LfnDxKFqVTGS2YKoetw4AmlfQsKCoT5ASViKfYsO6jVc8nPy0fwon3CIA/Lug5YM25zla0kUhkSHyejZ+P+hT+zOoU/t+JT5LzKyBbKe+XU9Qp/zpFNJ4Xb90S6iu03A6BGWIGICr1+lQOvz8dBIpZi4EcjYG3kVOp8f7k5eULvoKWBPQ6uO6bVc4kJj8XgTqOFcDniuym4d+WhVj+juoQEhP21QohjiaupLB68qsTeQXVsm7MbErEUC91WaOOUiWoktt8MgBphBSIqnLh5ptRPGKFadItyxk9+SgMsMlOzhClLuhk5ITw4UmvnkfzkBeb09ReC30/N3XBow/EaP8hDHTKZDKP+M1UhBAYv+nvQzN2YB8L3kp+8qNBnrBodWO5k3US1HdtvBkCNsAIRAWvHbxHWrS26BTzy+ynIyc5R2C/hYZLQM2dr7IJLx65q5fNzc/IQNG+PcPuzax17LPVeg/SXGVo5fk3z5M4z9GjYVwi6Nm/1w7P7f08APbrzNI0CXNHScqWtPUykC9h+MwBqhBWI9N3upQeEIFI0dYjnp2OV5qm7ce62MJGxYxsP3InWfLUNuVyOMyFRGPC+j8Lt3tImmtYle1ccEsJu0fN6RQM/ikYM2xq7ICMlU+1jz3NZptSzSKRr2H4zAGqEFYj0WdFgAYlYil5NCicpdvtoBFISUhX2O7b1tDAptOenY5H4OFnjz74b8wDjuswQPt+htQeObgnXm2XL5HI5Jnf7RSEEHlhzFEDhbWKPT8ZAIpZi0/Qdah97Xv9llTofI1FNwPabAVAjrECkr45vOw1Lg8LgUTQy1bX9cIW59QryC7BqzCYhpE2zm6/xKNwXz1KwePAq4bO71XfG+snb8Cqj9o7uraiUhFRIW7j/fSu4UT88vfscAHB611mhFzD9hXq3whcNWgmJWIptc3ZXxmkT1QhsvxkANcIKRPro6JZwIYAVLfE2qMNIvHiWIuyTkpAqDPaQiKXY8PM2jQZjZGdmY8uMYOE5P4lYitmOi/H8QaI2ilRrXTwaI/w8JGIphn87GQX5BZDJZMKo7F9HBap1zJUjN5a42giRLmH7zQCoEVYg0jf7fj0s3HK0MiwchTrk3+ORmpQm7BNzMhYOrT2E3sHTu85W+PPy8/Kxb9UROLQaLIScYd9MxrUzN7VRHJ0QODVIIQRu+HkbAODCkcJwaG3oiPjbz1Q+3tZfdnEaGNJ5bL8ZADXCCkT6Qi6XY8uMYCFkFIXAcV1mICv9FYDCW76bfXcKvYPuHUfh0c0nFfo8mUyGkzvOCOsIF61MEb4zQm+e81NVQUEBJljOUrg25w9dBgDhOcGfe8xR+ed2dEt44bX9n28lnjVR9WL7zQCoEVYg0gd5uXlYMDBAoZdJIpZi/oDlyMvNAwA8u5+Akd9PEb630G0FsrNeq/1Zcrkc5w5cFG5fSsRSSN8ehJDlYcJnkbL0FxkKax33/sdAPH+QiMdxT2D9V0+tqj2x18/eEkZrE+kqtt8MgBphBSJdl5KYhtE/TFMKf1tn74JcLodcLkfY+mPCQBBbYxcc23pa7c+Ry+W49McVDP92svAZtsYu2DIzWC8HeFTE/asPFZ6R9Pp8HF6/ysHGKdsLR0q3GqzStDBZ6a+EYxS/tU+kS9h+MwBqhBWIdNnNqNtwNvNSWHvW1tgFZ0KiAACJj5KEW4wSsRSjf5imMCGxKoqCX9HqFhKxFD0a9sXa8VuQlsz/V+qK3HdBIajPcliM169eY+CHhbfS57ksU+k4bh+PhEQsRUTo+Uo+Y6LqwfabAVAjrECki+RyOfYsOwireg4KYWJwp9F4dPMJCgoKEBIQJvT6davvjGC/UBQUFKj1GVFhlzHi/34Wjt+tvjNWjNiAl89Tyj8AlSpkeZjCdVs/eRuuR8YJz2aqsvyev9caSMRSrBi+oQrOmKjqsf1mANQIKxDpmtSkNEy1nad0y3fRoJXIznqN25fuwcdiosLKG+oM9CgoKEB4cCS8vxgvHKN7g8LgV3wOQdJM0fJ8Rdv+1UeFW8F2pgPK7ak9ExIFiViK/u8O4aAb0klsv/U8AM6dOxdffvklGjVqhObNm8POzg5xcXEqv58ViHRJROh5/PT2IIXg0KuJK8J3RiD9RQaWDVkrjP61NXFB6MrDKs/tl/s6FwfX/qEwqtemUT+sGrNJYf5A0g65XI6Fbiv+HhlsYI8TQX8KPa5D/j0eua9zS31/dtZr2LxV+DzhzajbVXjmRFWD7beeB0ArKysEBgYiNjYWMTEx6N69O8zMzJCVlVX+m8EKRLohNSkNc/stVer1m2Q9G8/uJWD30gPo3dRVeH1OX3+VQ1tacjp+m/W7wooVvZu6InBaEJ/xq2QF+QWY8dNC4eduVc8BRzefFNZsXuAaUGbvXlGdWOKxqgrPmqhqsP3W8wD4pqSkJIhEIpw6dUql/VmBqDaTyWQ4tOE4ejcdqNjr19QVYRuOIzw4UqHHzuOTMYg5GavSsR/EPoa/52phpRCJWApnMy/s9j+g8XJwpLq83DyFW/rWRk7YuXAvLOsWPt8ZND+k1PfGnIwt7Kl9qx/SX6q3nBxRTcf2mwFQwZ07dyASiXDt2jWV9mcFotoq7sJdDP9mslKv35y+/ji544zCc37SFu44sOZouYM8CvILcCYkCuMlMxWOOeTf43F822nk5+VXUemoOKUQaOiIZUPXCl+fCDpT4vvkcjk8PxsLiViKzb47q/isiSoX228GQIFMJkOPHj3w3XfflbpPTk4O0tPThS0+Pl7vKxDVLomPkzF/wHKl4Deow0js9AtVmMzZplE/bJq+o9x5+F48S8HW2bv+njJGLIWlgT1m/OSHK6eucxBBDZCfl4+ZUj+F28FTbOYJgfD84egS3xceHClM/8M5AUmXMAAyAAq8vb1hbm6O+Pj4Uvfx9fWFSCRS2vS5AlHtkJacjtVjNwnr9xa/3evvtQbDvp6kMB3Lr6MCkZJYeoNfUFCA84ejMVPqB6t6fx+zTzM3rJv4GxIeJlVh6UgVBQUFWOz+q8L1H/rVRGHuxZJu78tkMgz593g+C0g6hwGQARAA4OPjg7Zt2+L+/ftl7sceQKpt0pLTsX7yVoVn8SRiKbo1cMYUm7lw+3iEWtOxPLufgE3Td6CvubfC8Ub83884uiW8zJGlVP3kcjk2Tt2ucO0GfOAjPOsXfUL58Zdrf94oHElcxx7X/rxRDWdNpH0MgHoeAOVyOXx8fNC6dWvcvq3+VAesQFRTJcW/wMoRG9DNyEmhsbcydMSwbybjp+Zuwmu2Ji5YN/E3pCSklnisrLQsHNpwHGN+nK5wrN5NXbFi+Abcv/qwiktHmgpbf0yY0qfoOc+iPwLOHbiotP+iQSsLw+L7Plyaj3QC2289D4BDhgyBiYkJwsPD8fz5c2HLzlbtFxwrENU0ty7exSyHRehqYK8Q1qwNHTHwwxEKq3s4m3kh2C8UWWnK0x7l5uThTEgUZjksVug97FrHHhMsZ+H49j/Z21fLxZyMRY+3/l472KZx4b8t6zrgcOAJhX2z0rKEXt9fnP35XCfVemy/9TwAlvQ8n0gkQmBgoErvZwWimiA3Jw/Htp7C4E/GKA3u6N7AWZj3rWgb+f0UnNxxRmlUbl5uHqLCLmOh2wrYmQ5QGiSyfe4eJD5OrqZSUmV4dj8BLu2G/j14p9gfCIHTghQm+o6NiBOmj9m5cG81njWR5th+63kA1BQrEFWnhzfisWzoWtg06qcU/Gwa9VPoBezZuD/8vdbgbswDhWPkZOcgIvQ8FgwMQK8mrgrHcGzjgVVjNuH2pXvs8dFhr1/lYHrvBUp1SCKWYqbUT2HexqJ1hrvWsVdpTWGimortNwOgRliBqKqlJadj99IDGPDBMKXGumsde4URuUWDMw6uO6bw3FZacjqObg7HjJ/8lMKjfUt3LBu6DldOXVd5mTeq/eRyOUJXHhJ6+Ipv7h1HCes9y+VyLPdZJzxWEBV2uZrPnKhi2H4zAGqEFYiqQlb6KxwOPAEfi4kKD+4Lwe+N5/36/XMINk7Zjsdxfzfad2MeYPvcPRj5/RRYvrG/s5kXVozYgCunrpc72TPptofXHyuN8C7qUT66ORxA4XQysx0XF44mN3JC5L4L1XzWROpj+80AqBFWIKosqUlpCP31CIZ8OUEp4JW02bd0x3Kfdbj25w3IZDKkJafjRNAZLHRbAYfWHkr7e346FoHTgnDr4l3e3iUFuTl58PdaU2I9m9PXHxkpmcjPy8eMn/xKHTRCVNOx/WYA1AgrEGmLXC7H/asPsWbCFvQv9lB+WZtTW08s91mHmJOxyEzLwvlDl7F2/BZh4l6FHpy3+mFqz3nYt+oIEh9xkmYq37UzN/HT24OU6pJjGw+c3X8R+Xn5CqvKbJyynY8NUK3B9psBUCOsQKSJ9BcZOBJ4AhO6zoRNo/4qhT7PT8di45TtiD5xDecOXMT6SVsx/NvJSs/+ScRSeHwyBqvHbsbFozGcsoUqJDcnD8t91qNrHeW6+IuzP5KfvsD6yduE16bYzEX6y4zqPm2icrH9ZgDUCCsQqSMzNQsnd5yBb5+FkLZ0Vynw2Zq4YHrvBQiatwchAWEIGLYeXp+PU3qOTyKWov+7Q+DnthLHt53Gy+cp1V1c0iGPbsZjUMdRSnWup7ELQpaH4XDgCWG+SGczL1w5db26T5moTGy/GQA1wgpEpZHL5Uh4mISQgDBMspqNPs3dVAp31wJMAAAYm0lEQVR81oaOGP7tZMwfEAB/7zWYbregxGf4JGIpXNr5YKHbChwOPIFn9xOqu8ik4+RyOY5sOglbExelujiow0jsW3VYGJ3etY491ozbjJzsnOo+baISsf1mANQIKxAVyUrLwpnQ81g8eBXcO42GdX0nlQOfxydjMKHrLIzrMgOu7YeXONLXqp4jhn41EStGbEB4cGSZ6/USVabcnDysHrsZlnWV6+noH6Zimu184esBHwzDpWNXq/uUiZSw/WYA1AgrkH5KSUjF8aA/4TfoV3h8OqbEiZjLuqXr9vEIuHcaXWrPnkRcOJXLTPtFCPYLxdXTN/D6FXtSqGbJSMnEbMclkJTwfOBQi4mQFhtAMttxMQcfUY3C9psBUCOsQLrtVUY2Lh+/ho1TtmOi5Sw4m3mVONiitM2qniOkLdxh39Id3croEez3zyHw7b0Av836HVFhl5GSmFbdRSdS2YvnKZhmO6/Euu38jpcwjVG3+s5YN/E3ZKYqrz1NVNXYfjMAaoQVqPaTyWR4/jARx7b/iYDhGzC68zQ4tvGAlaHqQU8ilsLK0BE2jfuXGRC71XeG9xfjsWBgAHYt2Y/Lx69yxCTpjJcJKZjRx6/EeSuL95L3auKKrb/sQlb6q+o+ZdJjbL8ZADXCClQ75Obk4f7Vhzi4/hiW+6zD2P/6wtncG90b9lUr5BU+3C4tcbkshaBn5ITB/xqNWQ6LsWVmME7vOotHN5+gIJ+rbJDuy0p/hSWeq2FtpNzrXXz0eq8mrgicGoTUJPZ4U9Vj+80AqBFWoOonl8uR9iIdMeGx2LP8IJYOWYOx//NF/3ZDYWvsUuKD6traHFoNxujO07B48CoE+4Uict8FxN9+xqBHBKAgvwDBi0LxUzkj4Ls3cIa/52o8iH1c3adMeoTtNwOgRliBKo9cLkf6ywzcjLqNI5tPYuOU7fjFyR/DvpmEvv/0hq2JC6zqld0Tp+lmWdcB/d8binFdZmCJxyoEzQ/Bqd8jcSf6Pl5lZFf3j4io1rh6+jp8vp5U4oCR4tu4//kifGcE8nLzqvuUScex/WYA1AgrkOpkMhlSk9IQd/4OwoMjsNMvFAHD1mOa7TwM/XIC+r07BL3/MRDdGjiXOMlxZWzdGzjDtf1wjOsyA35uK7FlRjAOB55A9IlreP4gkT15RFqWnfUaaydsQa8mrmX+3+zTzA2rRgfi3pWH1X3KpKPYfjMAakSfKpBMJkNW+is8vfMMV07F4uSOM9iz7CDWT9qK+QOWY3K3XzD0q4lw/WA4HFoNhp2pC7o3cC73ebnK2vo0c4PHJ2MwyXo2/NxWInBqEPatOoLIfRdw5/J9pCWnQy6XV/ePlUhv3bvyAJO7zYF1OQOu3DuOQtD8ECQ85DQypD361H6XhgFQAzWlAsnlcuTm5CEzNROJj5Jw/+ojXDtzE+cOXsSJoDPYv/oIgubvwZrxW7DEcxVmOyzBJOvZGPn9VHh9Ng6u7YfD+R0vSN8eBDvTAejxVl9YGzlVW3graetqYI8+zd3g3nEUxv7XF7MdFyNg2Hpsnb0LB9f+gch9FxB3/g4SHyfz9hFRLSKXy3Hu4CX4WEwqt/ff87OxCPYLxdO7z6v7tKmWqyntd3ViANRAUQXq194bbh+PgNtHIzDwwxFwbT8cAz4YhgHv+8ClnQ/6vzsU/f7pDWczLzi19YRjGw/YtxoMaQt39Gnuht7NBqJXE1fYmrigp3F/2DTqh+4N+8K6vhOsDB1hWc+hcGqFcp6fqS1bj4Z94dB6MNw7jsLoztPg22chFrn/irUTfsOOBXsRtv4YzoRE4dqfN/Do5hOkJadDJpNV9+Umokoml8sRERqFoRYTYVnOM77OZl5YN/E3XI+MQ0EBH9cg9TAAMgBqpKgC/Siyq/ZQVRWbtZET7EwHwLGtJ9w+GgEfi0mYYDkLsx0XY/HgVVg1ZhO2zAzGbv8DOLTxBE7vPodLx64i7sJdPLnzDGnJ6cjPy6/uy0ZEtcT1yDhMsv4FPd4qe8omayMnTLCcicOBJ7hMIqmEAZABUCPVFQC7GtjDqp4jujVwhk2jfrBrMgDStwfBqa0nBrzvA/dOozH0ywkY9f1UTLSchWl28zGn71Is8VyFX0cHYsPP27B19i4EL9qH0JWHcWjjCZzccQaR+y7g0rGruH72Fu5ffYhn9xKQkpCK7Mxs9sARUbVKTUrD6vFb4PyOV7m/I3s27o9pdgsQ/nsk0pL1t4Gn0jEAMgBqpKgCndh1GucPR+P84WhcOBKDi0djcOmPK7h07CqiT1xDzMlYXDl1Hdf+vIHYiDjcOHcbcefv4Pale7gb8wD3rz3CwxvxiL/9DM/uJSDxURKSn75ESmIaMlIykZ2ZjdycPIYwIiIU3iq+cvo6pvacB7smA8oNhN0b9sXwbydj/9qjeHY/gQPAiAEQDIAaYQUiIqp+MpkMkfvOY6LVbNiZlB8IuxrYQ9rSHb84LcH5I9Fclk4Psf1mANQIKxARUc0jl8txPTIOc5yXwqHV4BLXJ35zs6zrAPuW7phuNx9nQs8jIyWzuotBlYjtNwOgRliBiIhqh6z0LPy+ZD+GfT0JNo37qfbMdR0pbBr1g3un0Vg1JhB3ou9xIJuOYPvNAKgRViAiotrrZUIqtv2yC0O/moCejfujax3VViHqamCPno37w+3jkfBzX4mYk9eQ+zq3uotDamD7zQCoEVYgIiLdkvM6F8e2ncbUnvPg0GowrMpZqeTNzcrQEX2auWHoVxOwctRG3Iy6xV7DGojtNwOgRliBiIj0Q0ZKBkKWh2GCZAbsW7qXu4Rdac8Z2hq7YMD7PpjScx52+e9H4uMkjkquBmy/GQA1wgpERKTfCgoKcP7QZfgNWgH3DqNga+JS4WU0Les6wKZRPzi19cSI76Zgmc9aRO6/iNevXld3MXUO228GQI2wAhERUWny8/Nx4WgM/L3XwOuLcejTzA3WRo4aLetpWdcBPRr2hbSFOzz+NQbTey3A1jm7cOviXS6Jpwa23wyAGmEFIiKiisrKyMLJnWewwDUAXp+Pg/TtQejWwFmlaWtUGajSrb4TejVxRb93h2DYN5Pwi7M/di4KRdyFO8jP1++wyPabAVAjrEBERFSZnj9IxJ7lBzHLcTE8PxsL+5bu6PFWX1jW1TwkFp/uxrKuA7o3dEavpq7oa+4N7y8nYJrtPKweuxl//BaOhIeJOvWsIttvBkCNsAIREVF1k8lkuBN9H0Hz92CmwyJ4fzEeTm090dO4P6yNHLXSo1haL6O1kSNsGvVDn2Zu6PfPIfD6fBwmWc3GYo9V2OkXggtHopGeklHdPyIlbL8ZADXCCkRERLWJTCbDg+uPsXdlGBYP/hVjfvTFwI9GQPr2INg06gdrw8oLjArhsY49LOs6wNrICTaN+qH3PwbCqa0n3DqMxIjvfsb03gux3Gcddi7cizMhUXhy77lWn3Fk+80AqBFWICIi0nU5OTm4FnEDwYtDsWjwrxgvmYnB/xoDp7ae6NXEFd0bOsOqXtUEx5JuX3c1sIdVPQd0q+8Mm8b90KupKxxae8DlfR94fTYWoztPw4yf/LDUew22zNqJwxuPI/JwlN633wyAGmAAJCIiKl3qizREhV3CDr8Q+Hutxs895mCoxUS4vO8D+5busDVxKQyQRT2PGoyQVmf7UWSn9+03A6AGGACJiIgq16tXr3Hj3C0cCjyOjdOCsNBtBSZ3n4NhX0+C20cj4WzmhT7N3dDT2AXdGxSGScu6DmUu7ccAyACoEQZAIiKi2kUul+PBnUd6334zAGqAAZCIiKj2YfvNAKgRViAiIqLah+03AyBWrFgBc3NzGBkZwcLCAlFRUSq/lxWIiIio9mH7recBcMeOHTA0NMTGjRtx/fp1eHh4wNTUFImJiSq9nxWIiIio9mH7recB0MLCAj4+PsLXMpkMrVu3xrx581R6PysQERFR7cP2W48DYG5uLgwMDBASEqLw+oABA2Bra1vie3JycpCeni5sjx8/hkgkQnx8vMLr3Lhx48aNG7eau8XHx0MkEiEtLa0qIkeNpLcB8OnTpxCJRIiMjFR4ffz48bCwsCjxPb6+vhCJRNy4cePGjRs3Hdju3btXFZGjRmIAVCMAvtkD+OhR4TxCjx8/rva/ZqrjLyd96/lkuVlufdhYbpZbH7aiO3ipqalVETlqJL0NgBW5Bfym9HT9fIaA5Wa59QHLzXLrA5Zbv8pdnN4GQKBwEMiwYcOEr2UyGdq0acNBIOVguVlufcBys9z6gOXWr3IXp9cBcMeOHTAyMsKmTZtw48YNeHp6wtTUFAkJCSq9X18rEMvNcusDlpvl1gcst36Vuzi9DoAAEBAQADMzMxgaGsLCwgLnzp1T+b05OTnw9fVFTk5OJZ5hzcNys9z6gOVmufUBy61f5S5O7wMgERERkb5hACQiIiLSMwyARERERHqGAZCIiIhIzzAAEhEREekZBsA3rFixAubm5jAyMoKFhQWioqLK3D84OBgffvghjIyM0KlTJxw8eFDh+3K5HNOmTUPLli1Rv359dOnSBbdv367MIlSIOuVeu3Ytvv/+e5iamsLU1BRdunRR2t/V1VVpyR0rK6vKLoba1Cl3YGCgUpmMjIwU9tHF6925c+cSl1Dq3r27sE9Nv96nTp2CjY0NWrVqBZFIpDQBfElOnjyJzz//HIaGhmjXrh0CAwOV9lH390VVU7fcu3fvhkQiQbNmzdC4cWN88803OHz4sMI+JS2J+eGHH1ZmMdSmbrlPnjxZYh1//vy5wn66dr1L+n8rEonQoUMHYZ/acL3nzp2LL7/8Eo0aNULz5s1hZ2eHuLi4ct+nK+13RTEAFrNjxw4YGhpi48aNuH79Ojw8PGBqaorExMQS94+IiICBgQEWLlyIGzduYOrUqahXrx6uXbsm7DN//nyYmJhg7969uHLlCmxtbfHuu+/i9evXVVWscqlb7r59+2LlypWIjo7GzZs3MXDgQJiYmODJkyfCPq6urrC2tsbz58+FLSUlpaqKpBJ1yx0YGAhjY2OFMr05Z6QuXu+XL18qlDk2NhYGBgYKgaimX++wsDBMmTIFe/bsUalhvH//Pho2bIgxY8bgxo0bCAgIgIGBgUIYUvfnWB3ULffIkSOxYMECnD9/Hrdv38bkyZNRr149XL58WdjH19cXHTt2VLjWycnJlV0Utahb7qIAeOvWLYVyyWQyYR9dvN5paWkK5Y2Pj0fTpk3h6+sr7FMbrreVlRUCAwMRGxuLmJgYdO/eHWZmZsjKyir1PbrSfmuCAbAYCwsL+Pj4CF/LZDK0bt261JVBHBwc0KNHD4XXvv76a3h5eQEo/OuhZcuW8PPzE76flpYGIyMjBAUFVUIJKkbdcr+poKAAjRs3xubNm4XXXF1dYWdnp/Vz1SZ1yx0YGAgTE5NSj6cv19vf3x+NGzdW+OVaG653EVUaxgkTJqBjx44Krzk6Oir0amr6c6xqqvZ8vqlDhw6YOXOm8LWvry8+/fRTbZ5apVInAJa1Lqw+XO+QkBCIxWI8fPhQeK22XW8ASEpKgkgkwqlTp0rdR1fab00wAP6lImsDv/POO/D391d4bfr06fjkk08AAPfu3YNIJEJ0dLTCPj/88ANGjBihxbOvOG2siZyRkYH69etj//79wmuurq4wMTFB8+bN0b59e3h7e+PFixdaPXdNVKTcgYGBMDAwgJmZGdq2bQtbW1vExsYK39eX692pUyd4eHgovFbTr3dxqjSM//nPfzBy5EiF1zZu3AhjY2MA2vk5VrWKBAKZTIZ33nkHAQEBwmu+vr5o2LAhWrVqhXfffRd9+/bFo0ePtH26WqNOADQ3N0fLli0hkUhw5swZ4fv6cr1tbGzQtWtXhddq2/UGgDt37kAkEin05r1JF9pvTTEA/uXp06cQiUSIjIxUeH38+PGwsLAo8T316tXD9u3bFV5buXIl3n77bQCFXcwikQjPnj1T2Mfe3h4ODg5aPPuKq0i53zRkyBC89957Ct3iQUFBCA0NxdWrVxESEoKPP/4YX331FQoKCrR6/hVVkXJHRkZi8+bNiI6ORnh4OGxsbGBsbIz4+HgA+nG9o6KiIBKJlJ59qunXuzhVGsYPPvgAc+fOVXjt4MGDEIlEyM7O1sr/m6pWkUCwYMECNGnSROE2Z1hYGIKDg3HlyhUcPnwY3377LczMzJCRkaHtU9YKVcodFxeH1atX4+LFi4iIiICbmxvq1q2LS5cuAdDO78mqpu71fvr0KQwMDLBz506F12vb9ZbJZOjRowe+++67MvfThfZbUwyAf2EArNgvtnnz5qFJkya4cuVKmfsV/TV17Ngxjc5XW7TxCz0vLw/t2rXD1KlTAejH9fb09MS//vWvcverade7OAZA1Wzbtg0NGzbEH3/8UeZ+qampMDY2xvr16zU9xUpR0VvfP/zwA/r37w9APwLg3Llz8Y9//AO5ubll7lfTr7e3tzfMzc2FP8xLowvtt6YYAP/CW8Dq39rw8/ODiYkJLly4oNJnNWvWDKtXr67wuWqTtm7pSKVSODk5AdD9652VlQVjY2MsXbpUpc+qSde7ON4CLl9QUBAaNGiAAwcOqLT/l19+iUmTJmlyepWmogFw3Lhx+OabbwDo/vWWy+V4//33MWrUKJX2r6nX28fHB23btsX9+/fL3VcX2m9NMQAWY2FhgWHDhglfy2QytGnTpsxBIDY2Ngqvffvtt0oPkS5atEj4fnp6eo17iFTdcgOFt4aMjY1x9uxZlT4jPj4eYrEYoaGhGp+vtlSk3MUVFBTgww8/xOjRowHo9vUGCp+BNDIyUunZvpp4vYuoOgikU6dOCq85OzsrDQLRpP5UNVUDwfbt21G/fn3s3btXpeNmZmaiSZMmWLZsmaanWCkqGgAlEgl69+4tfK2r1xv4+xnIsp6ZK1ITr7dcLoePjw9at26t8jQtutJ+a4IBsJgdO3bAyMgImzZtwo0bN+Dp6QlTU1Nhqg8XFxeFv3oiIiJQt25dLFq0CDdv3oSvr2+Jw8hNTU2F56Ps7Oxq3DBydcs9f/58GBoaYteuXQpTA2RmZgIo/AUxbtw4nD17Fg8ePMCxY8fwxRdf4IMPPkBOTk61lLEk6pZ75syZOHLkCO7du4dLly7ByckJ9evXx/Xr14V9dPF6F/n+++/h6Oio9HptuN6ZmZmIjo5GdHQ0RCIRlixZgujoaOFh9kmTJsHFxUXYv2gamPHjx+PmzZtYuXJlidPAlPVzrAnULfe2bdtQt25drFy5UuH/dlpamrDP2LFjER4ejgcPHiAiIkKYNzApKanKy1cadcvt7++PvXv34s6dO7h27RpGjhyJOnXqKDzCoIvXu0j//v3x9ddfl3jM2nC9hwwZAhMTE4SHhyvU2+zsbGEfXW2/NcEA+IaAgACYmZnB0NAQFhYWOHfunPC9zp07w9XVVWH/4OBgtG/fHoaGhujYsWOpE0m2aNECRkZG6NKlC27dulUVRVGLOuU2NzcvcfLQormjsrOzYWlpiebNm6NevXowNzeHh4dHjfpFWUSdco8aNUrYt0WLFujevbvC/GiAbl5voPAheZFIhKNHjyodqzZc79Im+i0qp6urKzp37qz0ns8++wyGhoZ47733SpwIuqyfY02gbrlLm/S7eH1wdHREq1atYGhoiDZt2sDR0RF3796t2oKVQ91yL1iwAO3atUP9+vXRtGlT/Pjjjzhx4oTScXXtegOFU5s0aNAAa9euLfGYteF6l1RmkUik8H9Wl9vvimIAJCIiItIzDIBEREREeoYBkIiIiEjPMAASERER6RkGQCIiIiI9wwBIREREpGcYAImIiIj0DAMgERERkZ5hACQiIiLSMwyARERERHqGAZCIiIhIzzAAEhEV4+3tje+++67E77Vp0wbz5s2r4jMiItI+BkAior/ExsaiTp06iIiIKPH7EokEjo6OVXxWRETaxwBIRPQXV1dXfP3116V+38HBAZ07d666EyIiqiQMgEREAPLz89G4cWMsXLhQeM3T0xPr168Xvu7WrRusra2r4/SIiLSKAZCICEBcXBxEIhEOHToEAJDJZGjSpAl27twp7NOmTRuMGTOmuk6RiEhrGACJiACcO3cOIpEIf/75JwAgLCwMIpEIoaGhAICzZ88qfJ+IqDZjACQiAvD8+XOIxWIMHToUly9fRocOHdCjRw8MGjQIly9fxqeffgqJRFLdp0lEpBUMgEREf5k7dy6MjY3RokULbNiwATExMTA3N8dbb70FJycnpKSkVPcpEhFpBQMgERERkZ5hACQiIiLSMwyARERERHqGAZCIiIhIzzAAEhEREekZBkAiIiIiPcMASERERKRnGACJiIiI9AwDIBEREZGeYQAkIiIi0jMMgERERER6hgGQiIiISM8wABIRERHpmf8Hiu27JMMc3UoAAAAASUVORK5CYII=\" width=\"640\">"
 | |
|       ],
 | |
|       "text/plain": [
 | |
|        "<IPython.core.display.HTML object>"
 | |
|       ]
 | |
|      },
 | |
|      "metadata": {},
 | |
|      "output_type": "display_data"
 | |
|     }
 | |
|    ],
 | |
|    "source": [
 | |
|     "gamma = 1\n",
 | |
|     "alpha = 1\n",
 | |
|     "beta_mul = 0.01\n",
 | |
|     "delta = 0.1\n",
 | |
|     "\n",
 | |
|     "z, omega = np.meshgrid(\n",
 | |
|     "    np.linspace(0, 15, 500),\n",
 | |
|     "    np.linspace(0, 2, 500)\n",
 | |
|     ")\n",
 | |
|     "\n",
 | |
|     "plt.figure()\n",
 | |
|     "for beta in (-0.3, 0.0, 1, 4):\n",
 | |
|     "    F = left(gamma, z)\n",
 | |
|     "    G = right(alpha, beta*beta_mul, delta, z, omega)\n",
 | |
|     "    plt.contour(omega, z, (F-G), [0])\n",
 | |
|     "    plt.xlabel(\"$\\omega$\")\n",
 | |
|     "    plt.ylabel(\"$z/\\gamma$\")"
 | |
|    ]
 | |
|   },
 | |
|   {
 | |
|    "cell_type": "code",
 | |
|    "execution_count": 145,
 | |
|    "metadata": {},
 | |
|    "outputs": [
 | |
|     {
 | |
|      "data": {
 | |
|       "application/javascript": [
 | |
|        "/* Put everything inside the global mpl namespace */\n",
 | |
|        "window.mpl = {};\n",
 | |
|        "\n",
 | |
|        "\n",
 | |
|        "mpl.get_websocket_type = function() {\n",
 | |
|        "    if (typeof(WebSocket) !== 'undefined') {\n",
 | |
|        "        return WebSocket;\n",
 | |
|        "    } else if (typeof(MozWebSocket) !== 'undefined') {\n",
 | |
|        "        return MozWebSocket;\n",
 | |
|        "    } else {\n",
 | |
|        "        alert('Your browser does not have WebSocket support.' +\n",
 | |
|        "              'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
 | |
|        "              'Firefox 4 and 5 are also supported but you ' +\n",
 | |
|        "              'have to enable WebSockets in about:config.');\n",
 | |
|        "    };\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n",
 | |
|        "    this.id = figure_id;\n",
 | |
|        "\n",
 | |
|        "    this.ws = websocket;\n",
 | |
|        "\n",
 | |
|        "    this.supports_binary = (this.ws.binaryType != undefined);\n",
 | |
|        "\n",
 | |
|        "    if (!this.supports_binary) {\n",
 | |
|        "        var warnings = document.getElementById(\"mpl-warnings\");\n",
 | |
|        "        if (warnings) {\n",
 | |
|        "            warnings.style.display = 'block';\n",
 | |
|        "            warnings.textContent = (\n",
 | |
|        "                \"This browser does not support binary websocket messages. \" +\n",
 | |
|        "                    \"Performance may be slow.\");\n",
 | |
|        "        }\n",
 | |
|        "    }\n",
 | |
|        "\n",
 | |
|        "    this.imageObj = new Image();\n",
 | |
|        "\n",
 | |
|        "    this.context = undefined;\n",
 | |
|        "    this.message = undefined;\n",
 | |
|        "    this.canvas = undefined;\n",
 | |
|        "    this.rubberband_canvas = undefined;\n",
 | |
|        "    this.rubberband_context = undefined;\n",
 | |
|        "    this.format_dropdown = undefined;\n",
 | |
|        "\n",
 | |
|        "    this.image_mode = 'full';\n",
 | |
|        "\n",
 | |
|        "    this.root = $('<div/>');\n",
 | |
|        "    this._root_extra_style(this.root)\n",
 | |
|        "    this.root.attr('style', 'display: inline-block');\n",
 | |
|        "\n",
 | |
|        "    $(parent_element).append(this.root);\n",
 | |
|        "\n",
 | |
|        "    this._init_header(this);\n",
 | |
|        "    this._init_canvas(this);\n",
 | |
|        "    this._init_toolbar(this);\n",
 | |
|        "\n",
 | |
|        "    var fig = this;\n",
 | |
|        "\n",
 | |
|        "    this.waiting = false;\n",
 | |
|        "\n",
 | |
|        "    this.ws.onopen =  function () {\n",
 | |
|        "            fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n",
 | |
|        "            fig.send_message(\"send_image_mode\", {});\n",
 | |
|        "            if (mpl.ratio != 1) {\n",
 | |
|        "                fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n",
 | |
|        "            }\n",
 | |
|        "            fig.send_message(\"refresh\", {});\n",
 | |
|        "        }\n",
 | |
|        "\n",
 | |
|        "    this.imageObj.onload = function() {\n",
 | |
|        "            if (fig.image_mode == 'full') {\n",
 | |
|        "                // Full images could contain transparency (where diff images\n",
 | |
|        "                // almost always do), so we need to clear the canvas so that\n",
 | |
|        "                // there is no ghosting.\n",
 | |
|        "                fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
 | |
|        "            }\n",
 | |
|        "            fig.context.drawImage(fig.imageObj, 0, 0);\n",
 | |
|        "        };\n",
 | |
|        "\n",
 | |
|        "    this.imageObj.onunload = function() {\n",
 | |
|        "        fig.ws.close();\n",
 | |
|        "    }\n",
 | |
|        "\n",
 | |
|        "    this.ws.onmessage = this._make_on_message_function(this);\n",
 | |
|        "\n",
 | |
|        "    this.ondownload = ondownload;\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype._init_header = function() {\n",
 | |
|        "    var titlebar = $(\n",
 | |
|        "        '<div class=\"ui-dialog-titlebar ui-widget-header ui-corner-all ' +\n",
 | |
|        "        'ui-helper-clearfix\"/>');\n",
 | |
|        "    var titletext = $(\n",
 | |
|        "        '<div class=\"ui-dialog-title\" style=\"width: 100%; ' +\n",
 | |
|        "        'text-align: center; padding: 3px;\"/>');\n",
 | |
|        "    titlebar.append(titletext)\n",
 | |
|        "    this.root.append(titlebar);\n",
 | |
|        "    this.header = titletext[0];\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n",
 | |
|        "\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n",
 | |
|        "\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype._init_canvas = function() {\n",
 | |
|        "    var fig = this;\n",
 | |
|        "\n",
 | |
|        "    var canvas_div = $('<div/>');\n",
 | |
|        "\n",
 | |
|        "    canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n",
 | |
|        "\n",
 | |
|        "    function canvas_keyboard_event(event) {\n",
 | |
|        "        return fig.key_event(event, event['data']);\n",
 | |
|        "    }\n",
 | |
|        "\n",
 | |
|        "    canvas_div.keydown('key_press', canvas_keyboard_event);\n",
 | |
|        "    canvas_div.keyup('key_release', canvas_keyboard_event);\n",
 | |
|        "    this.canvas_div = canvas_div\n",
 | |
|        "    this._canvas_extra_style(canvas_div)\n",
 | |
|        "    this.root.append(canvas_div);\n",
 | |
|        "\n",
 | |
|        "    var canvas = $('<canvas/>');\n",
 | |
|        "    canvas.addClass('mpl-canvas');\n",
 | |
|        "    canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n",
 | |
|        "\n",
 | |
|        "    this.canvas = canvas[0];\n",
 | |
|        "    this.context = canvas[0].getContext(\"2d\");\n",
 | |
|        "\n",
 | |
|        "    var backingStore = this.context.backingStorePixelRatio ||\n",
 | |
|        "\tthis.context.webkitBackingStorePixelRatio ||\n",
 | |
|        "\tthis.context.mozBackingStorePixelRatio ||\n",
 | |
|        "\tthis.context.msBackingStorePixelRatio ||\n",
 | |
|        "\tthis.context.oBackingStorePixelRatio ||\n",
 | |
|        "\tthis.context.backingStorePixelRatio || 1;\n",
 | |
|        "\n",
 | |
|        "    mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n",
 | |
|        "\n",
 | |
|        "    var rubberband = $('<canvas/>');\n",
 | |
|        "    rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n",
 | |
|        "\n",
 | |
|        "    var pass_mouse_events = true;\n",
 | |
|        "\n",
 | |
|        "    canvas_div.resizable({\n",
 | |
|        "        start: function(event, ui) {\n",
 | |
|        "            pass_mouse_events = false;\n",
 | |
|        "        },\n",
 | |
|        "        resize: function(event, ui) {\n",
 | |
|        "            fig.request_resize(ui.size.width, ui.size.height);\n",
 | |
|        "        },\n",
 | |
|        "        stop: function(event, ui) {\n",
 | |
|        "            pass_mouse_events = true;\n",
 | |
|        "            fig.request_resize(ui.size.width, ui.size.height);\n",
 | |
|        "        },\n",
 | |
|        "    });\n",
 | |
|        "\n",
 | |
|        "    function mouse_event_fn(event) {\n",
 | |
|        "        if (pass_mouse_events)\n",
 | |
|        "            return fig.mouse_event(event, event['data']);\n",
 | |
|        "    }\n",
 | |
|        "\n",
 | |
|        "    rubberband.mousedown('button_press', mouse_event_fn);\n",
 | |
|        "    rubberband.mouseup('button_release', mouse_event_fn);\n",
 | |
|        "    // Throttle sequential mouse events to 1 every 20ms.\n",
 | |
|        "    rubberband.mousemove('motion_notify', mouse_event_fn);\n",
 | |
|        "\n",
 | |
|        "    rubberband.mouseenter('figure_enter', mouse_event_fn);\n",
 | |
|        "    rubberband.mouseleave('figure_leave', mouse_event_fn);\n",
 | |
|        "\n",
 | |
|        "    canvas_div.on(\"wheel\", function (event) {\n",
 | |
|        "        event = event.originalEvent;\n",
 | |
|        "        event['data'] = 'scroll'\n",
 | |
|        "        if (event.deltaY < 0) {\n",
 | |
|        "            event.step = 1;\n",
 | |
|        "        } else {\n",
 | |
|        "            event.step = -1;\n",
 | |
|        "        }\n",
 | |
|        "        mouse_event_fn(event);\n",
 | |
|        "    });\n",
 | |
|        "\n",
 | |
|        "    canvas_div.append(canvas);\n",
 | |
|        "    canvas_div.append(rubberband);\n",
 | |
|        "\n",
 | |
|        "    this.rubberband = rubberband;\n",
 | |
|        "    this.rubberband_canvas = rubberband[0];\n",
 | |
|        "    this.rubberband_context = rubberband[0].getContext(\"2d\");\n",
 | |
|        "    this.rubberband_context.strokeStyle = \"#000000\";\n",
 | |
|        "\n",
 | |
|        "    this._resize_canvas = function(width, height) {\n",
 | |
|        "        // Keep the size of the canvas, canvas container, and rubber band\n",
 | |
|        "        // canvas in synch.\n",
 | |
|        "        canvas_div.css('width', width)\n",
 | |
|        "        canvas_div.css('height', height)\n",
 | |
|        "\n",
 | |
|        "        canvas.attr('width', width * mpl.ratio);\n",
 | |
|        "        canvas.attr('height', height * mpl.ratio);\n",
 | |
|        "        canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n",
 | |
|        "\n",
 | |
|        "        rubberband.attr('width', width);\n",
 | |
|        "        rubberband.attr('height', height);\n",
 | |
|        "    }\n",
 | |
|        "\n",
 | |
|        "    // Set the figure to an initial 600x600px, this will subsequently be updated\n",
 | |
|        "    // upon first draw.\n",
 | |
|        "    this._resize_canvas(600, 600);\n",
 | |
|        "\n",
 | |
|        "    // Disable right mouse context menu.\n",
 | |
|        "    $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n",
 | |
|        "        return false;\n",
 | |
|        "    });\n",
 | |
|        "\n",
 | |
|        "    function set_focus () {\n",
 | |
|        "        canvas.focus();\n",
 | |
|        "        canvas_div.focus();\n",
 | |
|        "    }\n",
 | |
|        "\n",
 | |
|        "    window.setTimeout(set_focus, 100);\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype._init_toolbar = function() {\n",
 | |
|        "    var fig = this;\n",
 | |
|        "\n",
 | |
|        "    var nav_element = $('<div/>')\n",
 | |
|        "    nav_element.attr('style', 'width: 100%');\n",
 | |
|        "    this.root.append(nav_element);\n",
 | |
|        "\n",
 | |
|        "    // Define a callback function for later on.\n",
 | |
|        "    function toolbar_event(event) {\n",
 | |
|        "        return fig.toolbar_button_onclick(event['data']);\n",
 | |
|        "    }\n",
 | |
|        "    function toolbar_mouse_event(event) {\n",
 | |
|        "        return fig.toolbar_button_onmouseover(event['data']);\n",
 | |
|        "    }\n",
 | |
|        "\n",
 | |
|        "    for(var toolbar_ind in mpl.toolbar_items) {\n",
 | |
|        "        var name = mpl.toolbar_items[toolbar_ind][0];\n",
 | |
|        "        var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
 | |
|        "        var image = mpl.toolbar_items[toolbar_ind][2];\n",
 | |
|        "        var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
 | |
|        "\n",
 | |
|        "        if (!name) {\n",
 | |
|        "            // put a spacer in here.\n",
 | |
|        "            continue;\n",
 | |
|        "        }\n",
 | |
|        "        var button = $('<button/>');\n",
 | |
|        "        button.addClass('ui-button ui-widget ui-state-default ui-corner-all ' +\n",
 | |
|        "                        'ui-button-icon-only');\n",
 | |
|        "        button.attr('role', 'button');\n",
 | |
|        "        button.attr('aria-disabled', 'false');\n",
 | |
|        "        button.click(method_name, toolbar_event);\n",
 | |
|        "        button.mouseover(tooltip, toolbar_mouse_event);\n",
 | |
|        "\n",
 | |
|        "        var icon_img = $('<span/>');\n",
 | |
|        "        icon_img.addClass('ui-button-icon-primary ui-icon');\n",
 | |
|        "        icon_img.addClass(image);\n",
 | |
|        "        icon_img.addClass('ui-corner-all');\n",
 | |
|        "\n",
 | |
|        "        var tooltip_span = $('<span/>');\n",
 | |
|        "        tooltip_span.addClass('ui-button-text');\n",
 | |
|        "        tooltip_span.html(tooltip);\n",
 | |
|        "\n",
 | |
|        "        button.append(icon_img);\n",
 | |
|        "        button.append(tooltip_span);\n",
 | |
|        "\n",
 | |
|        "        nav_element.append(button);\n",
 | |
|        "    }\n",
 | |
|        "\n",
 | |
|        "    var fmt_picker_span = $('<span/>');\n",
 | |
|        "\n",
 | |
|        "    var fmt_picker = $('<select/>');\n",
 | |
|        "    fmt_picker.addClass('mpl-toolbar-option ui-widget ui-widget-content');\n",
 | |
|        "    fmt_picker_span.append(fmt_picker);\n",
 | |
|        "    nav_element.append(fmt_picker_span);\n",
 | |
|        "    this.format_dropdown = fmt_picker[0];\n",
 | |
|        "\n",
 | |
|        "    for (var ind in mpl.extensions) {\n",
 | |
|        "        var fmt = mpl.extensions[ind];\n",
 | |
|        "        var option = $(\n",
 | |
|        "            '<option/>', {selected: fmt === mpl.default_extension}).html(fmt);\n",
 | |
|        "        fmt_picker.append(option)\n",
 | |
|        "    }\n",
 | |
|        "\n",
 | |
|        "    // Add hover states to the ui-buttons\n",
 | |
|        "    $( \".ui-button\" ).hover(\n",
 | |
|        "        function() { $(this).addClass(\"ui-state-hover\");},\n",
 | |
|        "        function() { $(this).removeClass(\"ui-state-hover\");}\n",
 | |
|        "    );\n",
 | |
|        "\n",
 | |
|        "    var status_bar = $('<span class=\"mpl-message\"/>');\n",
 | |
|        "    nav_element.append(status_bar);\n",
 | |
|        "    this.message = status_bar[0];\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n",
 | |
|        "    // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n",
 | |
|        "    // which will in turn request a refresh of the image.\n",
 | |
|        "    this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype.send_message = function(type, properties) {\n",
 | |
|        "    properties['type'] = type;\n",
 | |
|        "    properties['figure_id'] = this.id;\n",
 | |
|        "    this.ws.send(JSON.stringify(properties));\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype.send_draw_message = function() {\n",
 | |
|        "    if (!this.waiting) {\n",
 | |
|        "        this.waiting = true;\n",
 | |
|        "        this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n",
 | |
|        "    }\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype.handle_save = function(fig, msg) {\n",
 | |
|        "    var format_dropdown = fig.format_dropdown;\n",
 | |
|        "    var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n",
 | |
|        "    fig.ondownload(fig, format);\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype.handle_resize = function(fig, msg) {\n",
 | |
|        "    var size = msg['size'];\n",
 | |
|        "    if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n",
 | |
|        "        fig._resize_canvas(size[0], size[1]);\n",
 | |
|        "        fig.send_message(\"refresh\", {});\n",
 | |
|        "    };\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n",
 | |
|        "    var x0 = msg['x0'] / mpl.ratio;\n",
 | |
|        "    var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n",
 | |
|        "    var x1 = msg['x1'] / mpl.ratio;\n",
 | |
|        "    var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n",
 | |
|        "    x0 = Math.floor(x0) + 0.5;\n",
 | |
|        "    y0 = Math.floor(y0) + 0.5;\n",
 | |
|        "    x1 = Math.floor(x1) + 0.5;\n",
 | |
|        "    y1 = Math.floor(y1) + 0.5;\n",
 | |
|        "    var min_x = Math.min(x0, x1);\n",
 | |
|        "    var min_y = Math.min(y0, y1);\n",
 | |
|        "    var width = Math.abs(x1 - x0);\n",
 | |
|        "    var height = Math.abs(y1 - y0);\n",
 | |
|        "\n",
 | |
|        "    fig.rubberband_context.clearRect(\n",
 | |
|        "        0, 0, fig.canvas.width, fig.canvas.height);\n",
 | |
|        "\n",
 | |
|        "    fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n",
 | |
|        "    // Updates the figure title.\n",
 | |
|        "    fig.header.textContent = msg['label'];\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype.handle_cursor = function(fig, msg) {\n",
 | |
|        "    var cursor = msg['cursor'];\n",
 | |
|        "    switch(cursor)\n",
 | |
|        "    {\n",
 | |
|        "    case 0:\n",
 | |
|        "        cursor = 'pointer';\n",
 | |
|        "        break;\n",
 | |
|        "    case 1:\n",
 | |
|        "        cursor = 'default';\n",
 | |
|        "        break;\n",
 | |
|        "    case 2:\n",
 | |
|        "        cursor = 'crosshair';\n",
 | |
|        "        break;\n",
 | |
|        "    case 3:\n",
 | |
|        "        cursor = 'move';\n",
 | |
|        "        break;\n",
 | |
|        "    }\n",
 | |
|        "    fig.rubberband_canvas.style.cursor = cursor;\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype.handle_message = function(fig, msg) {\n",
 | |
|        "    fig.message.textContent = msg['message'];\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype.handle_draw = function(fig, msg) {\n",
 | |
|        "    // Request the server to send over a new figure.\n",
 | |
|        "    fig.send_draw_message();\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n",
 | |
|        "    fig.image_mode = msg['mode'];\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype.updated_canvas_event = function() {\n",
 | |
|        "    // Called whenever the canvas gets updated.\n",
 | |
|        "    this.send_message(\"ack\", {});\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "// A function to construct a web socket function for onmessage handling.\n",
 | |
|        "// Called in the figure constructor.\n",
 | |
|        "mpl.figure.prototype._make_on_message_function = function(fig) {\n",
 | |
|        "    return function socket_on_message(evt) {\n",
 | |
|        "        if (evt.data instanceof Blob) {\n",
 | |
|        "            /* FIXME: We get \"Resource interpreted as Image but\n",
 | |
|        "             * transferred with MIME type text/plain:\" errors on\n",
 | |
|        "             * Chrome.  But how to set the MIME type?  It doesn't seem\n",
 | |
|        "             * to be part of the websocket stream */\n",
 | |
|        "            evt.data.type = \"image/png\";\n",
 | |
|        "\n",
 | |
|        "            /* Free the memory for the previous frames */\n",
 | |
|        "            if (fig.imageObj.src) {\n",
 | |
|        "                (window.URL || window.webkitURL).revokeObjectURL(\n",
 | |
|        "                    fig.imageObj.src);\n",
 | |
|        "            }\n",
 | |
|        "\n",
 | |
|        "            fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
 | |
|        "                evt.data);\n",
 | |
|        "            fig.updated_canvas_event();\n",
 | |
|        "            fig.waiting = false;\n",
 | |
|        "            return;\n",
 | |
|        "        }\n",
 | |
|        "        else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n",
 | |
|        "            fig.imageObj.src = evt.data;\n",
 | |
|        "            fig.updated_canvas_event();\n",
 | |
|        "            fig.waiting = false;\n",
 | |
|        "            return;\n",
 | |
|        "        }\n",
 | |
|        "\n",
 | |
|        "        var msg = JSON.parse(evt.data);\n",
 | |
|        "        var msg_type = msg['type'];\n",
 | |
|        "\n",
 | |
|        "        // Call the  \"handle_{type}\" callback, which takes\n",
 | |
|        "        // the figure and JSON message as its only arguments.\n",
 | |
|        "        try {\n",
 | |
|        "            var callback = fig[\"handle_\" + msg_type];\n",
 | |
|        "        } catch (e) {\n",
 | |
|        "            console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n",
 | |
|        "            return;\n",
 | |
|        "        }\n",
 | |
|        "\n",
 | |
|        "        if (callback) {\n",
 | |
|        "            try {\n",
 | |
|        "                // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n",
 | |
|        "                callback(fig, msg);\n",
 | |
|        "            } catch (e) {\n",
 | |
|        "                console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n",
 | |
|        "            }\n",
 | |
|        "        }\n",
 | |
|        "    };\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n",
 | |
|        "mpl.findpos = function(e) {\n",
 | |
|        "    //this section is from http://www.quirksmode.org/js/events_properties.html\n",
 | |
|        "    var targ;\n",
 | |
|        "    if (!e)\n",
 | |
|        "        e = window.event;\n",
 | |
|        "    if (e.target)\n",
 | |
|        "        targ = e.target;\n",
 | |
|        "    else if (e.srcElement)\n",
 | |
|        "        targ = e.srcElement;\n",
 | |
|        "    if (targ.nodeType == 3) // defeat Safari bug\n",
 | |
|        "        targ = targ.parentNode;\n",
 | |
|        "\n",
 | |
|        "    // jQuery normalizes the pageX and pageY\n",
 | |
|        "    // pageX,Y are the mouse positions relative to the document\n",
 | |
|        "    // offset() returns the position of the element relative to the document\n",
 | |
|        "    var x = e.pageX - $(targ).offset().left;\n",
 | |
|        "    var y = e.pageY - $(targ).offset().top;\n",
 | |
|        "\n",
 | |
|        "    return {\"x\": x, \"y\": y};\n",
 | |
|        "};\n",
 | |
|        "\n",
 | |
|        "/*\n",
 | |
|        " * return a copy of an object with only non-object keys\n",
 | |
|        " * we need this to avoid circular references\n",
 | |
|        " * http://stackoverflow.com/a/24161582/3208463\n",
 | |
|        " */\n",
 | |
|        "function simpleKeys (original) {\n",
 | |
|        "  return Object.keys(original).reduce(function (obj, key) {\n",
 | |
|        "    if (typeof original[key] !== 'object')\n",
 | |
|        "        obj[key] = original[key]\n",
 | |
|        "    return obj;\n",
 | |
|        "  }, {});\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype.mouse_event = function(event, name) {\n",
 | |
|        "    var canvas_pos = mpl.findpos(event)\n",
 | |
|        "\n",
 | |
|        "    if (name === 'button_press')\n",
 | |
|        "    {\n",
 | |
|        "        this.canvas.focus();\n",
 | |
|        "        this.canvas_div.focus();\n",
 | |
|        "    }\n",
 | |
|        "\n",
 | |
|        "    var x = canvas_pos.x * mpl.ratio;\n",
 | |
|        "    var y = canvas_pos.y * mpl.ratio;\n",
 | |
|        "\n",
 | |
|        "    this.send_message(name, {x: x, y: y, button: event.button,\n",
 | |
|        "                             step: event.step,\n",
 | |
|        "                             guiEvent: simpleKeys(event)});\n",
 | |
|        "\n",
 | |
|        "    /* This prevents the web browser from automatically changing to\n",
 | |
|        "     * the text insertion cursor when the button is pressed.  We want\n",
 | |
|        "     * to control all of the cursor setting manually through the\n",
 | |
|        "     * 'cursor' event from matplotlib */\n",
 | |
|        "    event.preventDefault();\n",
 | |
|        "    return false;\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype._key_event_extra = function(event, name) {\n",
 | |
|        "    // Handle any extra behaviour associated with a key event\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype.key_event = function(event, name) {\n",
 | |
|        "\n",
 | |
|        "    // Prevent repeat events\n",
 | |
|        "    if (name == 'key_press')\n",
 | |
|        "    {\n",
 | |
|        "        if (event.which === this._key)\n",
 | |
|        "            return;\n",
 | |
|        "        else\n",
 | |
|        "            this._key = event.which;\n",
 | |
|        "    }\n",
 | |
|        "    if (name == 'key_release')\n",
 | |
|        "        this._key = null;\n",
 | |
|        "\n",
 | |
|        "    var value = '';\n",
 | |
|        "    if (event.ctrlKey && event.which != 17)\n",
 | |
|        "        value += \"ctrl+\";\n",
 | |
|        "    if (event.altKey && event.which != 18)\n",
 | |
|        "        value += \"alt+\";\n",
 | |
|        "    if (event.shiftKey && event.which != 16)\n",
 | |
|        "        value += \"shift+\";\n",
 | |
|        "\n",
 | |
|        "    value += 'k';\n",
 | |
|        "    value += event.which.toString();\n",
 | |
|        "\n",
 | |
|        "    this._key_event_extra(event, name);\n",
 | |
|        "\n",
 | |
|        "    this.send_message(name, {key: value,\n",
 | |
|        "                             guiEvent: simpleKeys(event)});\n",
 | |
|        "    return false;\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype.toolbar_button_onclick = function(name) {\n",
 | |
|        "    if (name == 'download') {\n",
 | |
|        "        this.handle_save(this, null);\n",
 | |
|        "    } else {\n",
 | |
|        "        this.send_message(\"toolbar_button\", {name: name});\n",
 | |
|        "    }\n",
 | |
|        "};\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n",
 | |
|        "    this.message.textContent = tooltip;\n",
 | |
|        "};\n",
 | |
|        "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n",
 | |
|        "\n",
 | |
|        "mpl.extensions = [\"eps\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
 | |
|        "\n",
 | |
|        "mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n",
 | |
|        "    // Create a \"websocket\"-like object which calls the given IPython comm\n",
 | |
|        "    // object with the appropriate methods. Currently this is a non binary\n",
 | |
|        "    // socket, so there is still some room for performance tuning.\n",
 | |
|        "    var ws = {};\n",
 | |
|        "\n",
 | |
|        "    ws.close = function() {\n",
 | |
|        "        comm.close()\n",
 | |
|        "    };\n",
 | |
|        "    ws.send = function(m) {\n",
 | |
|        "        //console.log('sending', m);\n",
 | |
|        "        comm.send(m);\n",
 | |
|        "    };\n",
 | |
|        "    // Register the callback with on_msg.\n",
 | |
|        "    comm.on_msg(function(msg) {\n",
 | |
|        "        //console.log('receiving', msg['content']['data'], msg);\n",
 | |
|        "        // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
 | |
|        "        ws.onmessage(msg['content']['data'])\n",
 | |
|        "    });\n",
 | |
|        "    return ws;\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.mpl_figure_comm = function(comm, msg) {\n",
 | |
|        "    // This is the function which gets called when the mpl process\n",
 | |
|        "    // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
 | |
|        "\n",
 | |
|        "    var id = msg.content.data.id;\n",
 | |
|        "    // Get hold of the div created by the display call when the Comm\n",
 | |
|        "    // socket was opened in Python.\n",
 | |
|        "    var element = $(\"#\" + id);\n",
 | |
|        "    var ws_proxy = comm_websocket_adapter(comm)\n",
 | |
|        "\n",
 | |
|        "    function ondownload(figure, format) {\n",
 | |
|        "        window.open(figure.imageObj.src);\n",
 | |
|        "    }\n",
 | |
|        "\n",
 | |
|        "    var fig = new mpl.figure(id, ws_proxy,\n",
 | |
|        "                           ondownload,\n",
 | |
|        "                           element.get(0));\n",
 | |
|        "\n",
 | |
|        "    // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n",
 | |
|        "    // web socket which is closed, not our websocket->open comm proxy.\n",
 | |
|        "    ws_proxy.onopen();\n",
 | |
|        "\n",
 | |
|        "    fig.parent_element = element.get(0);\n",
 | |
|        "    fig.cell_info = mpl.find_output_cell(\"<div id='\" + id + \"'></div>\");\n",
 | |
|        "    if (!fig.cell_info) {\n",
 | |
|        "        console.error(\"Failed to find cell for figure\", id, fig);\n",
 | |
|        "        return;\n",
 | |
|        "    }\n",
 | |
|        "\n",
 | |
|        "    var output_index = fig.cell_info[2]\n",
 | |
|        "    var cell = fig.cell_info[0];\n",
 | |
|        "\n",
 | |
|        "};\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype.handle_close = function(fig, msg) {\n",
 | |
|        "    var width = fig.canvas.width/mpl.ratio\n",
 | |
|        "    fig.root.unbind('remove')\n",
 | |
|        "\n",
 | |
|        "    // Update the output cell to use the data from the current canvas.\n",
 | |
|        "    fig.push_to_output();\n",
 | |
|        "    var dataURL = fig.canvas.toDataURL();\n",
 | |
|        "    // Re-enable the keyboard manager in IPython - without this line, in FF,\n",
 | |
|        "    // the notebook keyboard shortcuts fail.\n",
 | |
|        "    IPython.keyboard_manager.enable()\n",
 | |
|        "    $(fig.parent_element).html('<img src=\"' + dataURL + '\" width=\"' + width + '\">');\n",
 | |
|        "    fig.close_ws(fig, msg);\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype.close_ws = function(fig, msg){\n",
 | |
|        "    fig.send_message('closing', msg);\n",
 | |
|        "    // fig.ws.close()\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype.push_to_output = function(remove_interactive) {\n",
 | |
|        "    // Turn the data on the canvas into data in the output cell.\n",
 | |
|        "    var width = this.canvas.width/mpl.ratio\n",
 | |
|        "    var dataURL = this.canvas.toDataURL();\n",
 | |
|        "    this.cell_info[1]['text/html'] = '<img src=\"' + dataURL + '\" width=\"' + width + '\">';\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype.updated_canvas_event = function() {\n",
 | |
|        "    // Tell IPython that the notebook contents must change.\n",
 | |
|        "    IPython.notebook.set_dirty(true);\n",
 | |
|        "    this.send_message(\"ack\", {});\n",
 | |
|        "    var fig = this;\n",
 | |
|        "    // Wait a second, then push the new image to the DOM so\n",
 | |
|        "    // that it is saved nicely (might be nice to debounce this).\n",
 | |
|        "    setTimeout(function () { fig.push_to_output() }, 1000);\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype._init_toolbar = function() {\n",
 | |
|        "    var fig = this;\n",
 | |
|        "\n",
 | |
|        "    var nav_element = $('<div/>')\n",
 | |
|        "    nav_element.attr('style', 'width: 100%');\n",
 | |
|        "    this.root.append(nav_element);\n",
 | |
|        "\n",
 | |
|        "    // Define a callback function for later on.\n",
 | |
|        "    function toolbar_event(event) {\n",
 | |
|        "        return fig.toolbar_button_onclick(event['data']);\n",
 | |
|        "    }\n",
 | |
|        "    function toolbar_mouse_event(event) {\n",
 | |
|        "        return fig.toolbar_button_onmouseover(event['data']);\n",
 | |
|        "    }\n",
 | |
|        "\n",
 | |
|        "    for(var toolbar_ind in mpl.toolbar_items){\n",
 | |
|        "        var name = mpl.toolbar_items[toolbar_ind][0];\n",
 | |
|        "        var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
 | |
|        "        var image = mpl.toolbar_items[toolbar_ind][2];\n",
 | |
|        "        var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
 | |
|        "\n",
 | |
|        "        if (!name) { continue; };\n",
 | |
|        "\n",
 | |
|        "        var button = $('<button class=\"btn btn-default\" href=\"#\" title=\"' + name + '\"><i class=\"fa ' + image + ' fa-lg\"></i></button>');\n",
 | |
|        "        button.click(method_name, toolbar_event);\n",
 | |
|        "        button.mouseover(tooltip, toolbar_mouse_event);\n",
 | |
|        "        nav_element.append(button);\n",
 | |
|        "    }\n",
 | |
|        "\n",
 | |
|        "    // Add the status bar.\n",
 | |
|        "    var status_bar = $('<span class=\"mpl-message\" style=\"text-align:right; float: right;\"/>');\n",
 | |
|        "    nav_element.append(status_bar);\n",
 | |
|        "    this.message = status_bar[0];\n",
 | |
|        "\n",
 | |
|        "    // Add the close button to the window.\n",
 | |
|        "    var buttongrp = $('<div class=\"btn-group inline pull-right\"></div>');\n",
 | |
|        "    var button = $('<button class=\"btn btn-mini btn-primary\" href=\"#\" title=\"Stop Interaction\"><i class=\"fa fa-power-off icon-remove icon-large\"></i></button>');\n",
 | |
|        "    button.click(function (evt) { fig.handle_close(fig, {}); } );\n",
 | |
|        "    button.mouseover('Stop Interaction', toolbar_mouse_event);\n",
 | |
|        "    buttongrp.append(button);\n",
 | |
|        "    var titlebar = this.root.find($('.ui-dialog-titlebar'));\n",
 | |
|        "    titlebar.prepend(buttongrp);\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype._root_extra_style = function(el){\n",
 | |
|        "    var fig = this\n",
 | |
|        "    el.on(\"remove\", function(){\n",
 | |
|        "\tfig.close_ws(fig, {});\n",
 | |
|        "    });\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype._canvas_extra_style = function(el){\n",
 | |
|        "    // this is important to make the div 'focusable\n",
 | |
|        "    el.attr('tabindex', 0)\n",
 | |
|        "    // reach out to IPython and tell the keyboard manager to turn it's self\n",
 | |
|        "    // off when our div gets focus\n",
 | |
|        "\n",
 | |
|        "    // location in version 3\n",
 | |
|        "    if (IPython.notebook.keyboard_manager) {\n",
 | |
|        "        IPython.notebook.keyboard_manager.register_events(el);\n",
 | |
|        "    }\n",
 | |
|        "    else {\n",
 | |
|        "        // location in version 2\n",
 | |
|        "        IPython.keyboard_manager.register_events(el);\n",
 | |
|        "    }\n",
 | |
|        "\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype._key_event_extra = function(event, name) {\n",
 | |
|        "    var manager = IPython.notebook.keyboard_manager;\n",
 | |
|        "    if (!manager)\n",
 | |
|        "        manager = IPython.keyboard_manager;\n",
 | |
|        "\n",
 | |
|        "    // Check for shift+enter\n",
 | |
|        "    if (event.shiftKey && event.which == 13) {\n",
 | |
|        "        this.canvas_div.blur();\n",
 | |
|        "        event.shiftKey = false;\n",
 | |
|        "        // Send a \"J\" for go to next cell\n",
 | |
|        "        event.which = 74;\n",
 | |
|        "        event.keyCode = 74;\n",
 | |
|        "        manager.command_mode();\n",
 | |
|        "        manager.handle_keydown(event);\n",
 | |
|        "    }\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "mpl.figure.prototype.handle_save = function(fig, msg) {\n",
 | |
|        "    fig.ondownload(fig, null);\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "\n",
 | |
|        "mpl.find_output_cell = function(html_output) {\n",
 | |
|        "    // Return the cell and output element which can be found *uniquely* in the notebook.\n",
 | |
|        "    // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n",
 | |
|        "    // IPython event is triggered only after the cells have been serialised, which for\n",
 | |
|        "    // our purposes (turning an active figure into a static one), is too late.\n",
 | |
|        "    var cells = IPython.notebook.get_cells();\n",
 | |
|        "    var ncells = cells.length;\n",
 | |
|        "    for (var i=0; i<ncells; i++) {\n",
 | |
|        "        var cell = cells[i];\n",
 | |
|        "        if (cell.cell_type === 'code'){\n",
 | |
|        "            for (var j=0; j<cell.output_area.outputs.length; j++) {\n",
 | |
|        "                var data = cell.output_area.outputs[j];\n",
 | |
|        "                if (data.data) {\n",
 | |
|        "                    // IPython >= 3 moved mimebundle to data attribute of output\n",
 | |
|        "                    data = data.data;\n",
 | |
|        "                }\n",
 | |
|        "                if (data['text/html'] == html_output) {\n",
 | |
|        "                    return [cell, data, j];\n",
 | |
|        "                }\n",
 | |
|        "            }\n",
 | |
|        "        }\n",
 | |
|        "    }\n",
 | |
|        "}\n",
 | |
|        "\n",
 | |
|        "// Register the function which deals with the matplotlib target/channel.\n",
 | |
|        "// The kernel may be null if the page has been refreshed.\n",
 | |
|        "if (IPython.notebook.kernel != null) {\n",
 | |
|        "    IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n",
 | |
|        "}\n"
 | |
|       ],
 | |
|       "text/plain": [
 | |
|        "<IPython.core.display.Javascript object>"
 | |
|       ]
 | |
|      },
 | |
|      "metadata": {},
 | |
|      "output_type": "display_data"
 | |
|     },
 | |
|     {
 | |
|      "data": {
 | |
|       "text/html": [
 | |
|        "<img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAoAAAAHgCAYAAAA10dzkAAAgAElEQVR4nOzdZ3gU19UHcF2wARdsnLhhYmPjlri8SRxHTpzYJM41GBuDjS8dSYjeQYBER3QsqkXvvTcBBtF7MV2YInoVTXRRhMru/t8P4x2xbNFKs9JqpP/vefYDU6/ynjfnZGbuuQEgIiIiogIlwN8DICIiIqLcxQKQiIiIqIBhAUhERERUwLAAJCIiIipgWAASERERFTAsAImIiIgKGBaARERERAUMC0AiIiKiAoYFIBEREVEBwwKQiIiIqIBhAUhERERUwLAAJCIiIipgWAASERERFTAsAImIiIgKGBaARERERAUMC0AiIiKiAoYFIBEREVEBwwKQiIiIqIBhAUhERERUwLAAJCIiIipgWAASERERFTAsAImIiIgKGBaARERERAUMC0AiIiKiAoYFIBEREVEBwwKQiIiIqIBhAUhERERUwLAAJCIiIipgWAASERERFTAsAImIiIgKGBaARERERAUMC0AiIiKiAoYFIBEREVEBwwKQiIiIqIBhAUhERERUwLAAJCIiIipgWAASERERFTAsAImIiIgKGBaARERERAUMC0AiIiKiAoYFIBEREVEBwwKQiIiIqIBhAUhERERUwLAAJCIiIipgWAASERERFTAsAImIiIgKGBaARERERAUMC0AiIiKiAoYFIBEREVEBwwKQiIiIqIBhAUhERERUwLAAJCIiIipg8k0BuGnTJlSsWBElS5ZEQEAAYmJiPB6/cOFCSCnx/PPPo3jx4vjHP/6BlStX5tJoiYiIiPwn3xSAsbGx6NKlCxYtWuRVAdi6dWtERUVh165dOH78ODp16oTHH38c+/bty6URExEREflHvikAH+ZNAejKe++9h549e+bAiIiIiIjyDhaAv7FarXj11VcxfPjwHBoVERERUd7AAvA3UVFReO6555CYmOj2mJSUFCQlJem/W7du4dSpU7h9+7bDdv74448//vjjL+/+bt++jYSEBFitVqMlh2mxAAQwc+ZMPPnkk1izZo3H4yIjIxEQEMAff/zxxx9//OWDX0JCgtGSw7QKfAE4e/ZsPPHEE1i2bFmmxz76BPD8+fN6APn7f83wxx9//PHHH3/e/RISEhAQEIDbt28bLTlMq0AXgLNmzUKxYsWwePHibN0nKSkJAQEBSEpKytb5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\" width=\"640\">"
 | |
|       ],
 | |
|       "text/plain": [
 | |
|        "<IPython.core.display.HTML object>"
 | |
|       ]
 | |
|      },
 | |
|      "metadata": {},
 | |
|      "output_type": "display_data"
 | |
|     }
 | |
|    ],
 | |
|    "source": [
 | |
|     "def left(gamma, z):\n",
 | |
|     "    return z / gamma\n",
 | |
|     "\n",
 | |
|     "def right(alpha, beta, delta, z, f):\n",
 | |
|     "    omega = 2*np.pi*f\n",
 | |
|     "    denom = (omega**2 - alpha - (3/4)*beta*z**2)**2 + (delta*omega)**2\n",
 | |
|     "    return 1/np.sqrt(denom)\n",
 | |
|     "\n",
 | |
|     "f_resonance = 8e3\n",
 | |
|     "omega_resonance = 2*np.pi*f_resonance\n",
 | |
|     "\n",
 | |
|     "gamma = 1e7\n",
 | |
|     "alpha = omega_resonance**2\n",
 | |
|     "beta_mul = 1e8\n",
 | |
|     "delta = 200\n",
 | |
|     "\n",
 | |
|     "z, fs = np.meshgrid(\n",
 | |
|     "    np.linspace(0, 1.2, 500),\n",
 | |
|     "    np.linspace(6.5e3, 8.5e3, 500)\n",
 | |
|     ")\n",
 | |
|     "\n",
 | |
|     "plt.figure()\n",
 | |
|     "for beta in (0.0, 1, 4):\n",
 | |
|     "    F = left(gamma, z)\n",
 | |
|     "    G = right(alpha, beta*beta_mul, delta, z, fs)\n",
 | |
|     "    plt.contour(fs, z, (F-G), [0])\n",
 | |
|     "    plt.xlabel(\"$\\omega$\")\n",
 | |
|     "    plt.ylabel(\"$z/\\gamma$\")"
 | |
|    ]
 | |
|   },
 | |
|   {
 | |
|    "cell_type": "markdown",
 | |
|    "metadata": {},
 | |
|    "source": [
 | |
|     "## Rough method\n",
 | |
|     "\n",
 | |
|     "#### Simulating frequency response -- no coupling\n",
 | |
|     "\n",
 | |
|     " 1. Calculate linear stiffness $\\alpha$ from resonance frequencies.\n",
 | |
|     " 2. Derive slope and half-width maximum by search on $\\beta$ and $\\delta$. Scale signals and apply MSE loss function.\n",
 | |
|     " 3. Finally, scale amplitude by the inverse of scaling factor in 2).\n",
 | |
|     " \n",
 | |
|     "Step 3) outputs ballpark parameters for frequency scan simulations. See other notebook for coupling and further optimization."
 | |
|    ]
 | |
|   },
 | |
|   {
 | |
|    "cell_type": "code",
 | |
|    "execution_count": null,
 | |
|    "metadata": {},
 | |
|    "outputs": [],
 | |
|    "source": []
 | |
|   }
 | |
|  ],
 | |
|  "metadata": {
 | |
|   "anaconda-cloud": {},
 | |
|   "kernelspec": {
 | |
|    "display_name": "Python 3",
 | |
|    "language": "python",
 | |
|    "name": "python3"
 | |
|   },
 | |
|   "language_info": {
 | |
|    "codemirror_mode": {
 | |
|     "name": "ipython",
 | |
|     "version": 3
 | |
|    },
 | |
|    "file_extension": ".py",
 | |
|    "mimetype": "text/x-python",
 | |
|    "name": "python",
 | |
|    "nbconvert_exporter": "python",
 | |
|    "pygments_lexer": "ipython3",
 | |
|    "version": "3.5.2"
 | |
|   }
 | |
|  },
 | |
|  "nbformat": 4,
 | |
|  "nbformat_minor": 1
 | |
| }
 |