{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Deep Learning Models -- A collection of various deep learning architectures, models, and tips for TensorFlow and PyTorch in Jupyter Notebooks.\n",
    "- Author: Sebastian Raschka\n",
    "- GitHub Repository: https://github.com/rasbt/deeplearning-models"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Sebastian Raschka \n",
      "\n",
      "CPython 3.6.7\n",
      "IPython 7.1.1\n",
      "\n",
      "torch 0.4.1\n"
     ]
    }
   ],
   "source": [
    "%load_ext watermark\n",
    "%watermark -a 'Sebastian Raschka' -v -p torch"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- Runs on CPU or GPU (if available)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Model Zoo -- Plotting Live Training Performance in Jupyter Notebooks via Matplotlib"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "There are more sophisticated ways to plot the performance of a model during training than using matplotlib. However, sometimes, we just want to keep it simple, and this notebook shows how we can create a simple plotting function with matplotlib that updates every epoch. \n",
    "\n",
    "\n",
    "A simple example of this is shown below (of course, we could extend it to show e.g., a grid of multiple plots):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "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,iVBORw0KGgoAAAANSUhEUgAAAoAAAAHgCAYAAAA10dzkAAAAAXNSR0IArs4c6QAAQABJREFUeAHs3QlclVX6B/Cf7AICLqioqKC4gJC5VJq7lrum2UxN/bNlaprMSiuX1Fxza7dss6lscsaZ3HPLfUnT3FIQFRRXXHAFBNku/p/z3oHQAFG4733vfX/n8yHv8t6zfM9NHs97lnLXJYGJAhSgAAUoQAEKUMA0Ai6maSkbSgEKUIACFKAABSigCTAA5BeBAhSgAAUoQAEKmEyAAaDJOpzNpQAFKEABClCAAgwA+R2gAAUoQAEKUIACJhNgAGiyDmdzKUABClCAAhSgAANAfgcoQAEKUIACFKCAyQQYAJqsw9lcClCAAhSgAAUowACQ3wEKUIACFKAABShgMgEGgCbrcDaXAhSgAAUoQAEKMADkd4ACFKAABShAAQqYTIABoMk6nM2lAAUoQAEKUIACDAD5HaAABShAAQpQgAImE2AAaLIOZ3MpQAEKUIACFKAAA0B+ByhAAQpQgAIUoIDJBBgAmqzD2VwKUIACFKAABSjAAJDfAQpQgAIUoAAFKGAyAQaAJutwNpcCFKAABShAAQowAOR3gAIUoAAFKEABCphMgAGgyTqczaUABShAAQpQgAIMAPkdoAAFKEABClCAAiYTYABosg5ncylAAQpQgAIUoAADQH4HKEABClCAAhSggMkEGACarMPZXApQgAIUoAAFKMAAkN8BClCAAhSgAAUoYDIBBoAm63A2lwIUoAAFKEABCjAA5HeAAhSgAAUoQAEKmEyAAaDJOpzNpQAFKEABClCAAgwA+R2gAAUoQAEKUIACJhNgAGiyDmdzKUABClCAAhSgAANAfgcoQAEKUIACFKCAyQQYAJqsw9lcClCAAhSgAAUowACQ3wEKUIACFKAABShgMgEGgCbrcDaXAhSgAAUoQAEKMADkd4ACFKAABShAAQqYTIABoMk6nM2lAAUoQAEKUIACDAD5HaAABShAAQpQgAImE2AAaLIOZ3MpQAEKUIACFKAAA0B+ByhAAQpQgAIUoIDJBBgAmqzD2VwKUIACFKAABSjAAJDfAQpQgAIUoAAFKGAyAQaAJutwNpcCFKAABShAAQowAOR3gAIUoAAFKEABCphMgAGgyTqczaUABShAAQpQgAIMAPkdoAAFKEABClCAAiYTYABosg5ncylAAQpQgAIUoAADQH4HKEABClCAAhSggMkEGACarMPZXApQgAIUoAAFKMAAkN8BClCAAhSgAAUoYDIBBoAm63A2lwIUoAAFKEABCjAA5HeAAhSgAAUoQAEKmEyAAaDJOpzNpQAFKEABClCAAgwA+R2gAAUoQAEKUIACJhNgAGiyDmdzKUABClCAAhSgAANAfgcoQAEKUIACFKCAyQQYAJqsw9lcClCAAhSgAAUowACQ3wEKUIACFKAABShgMgE3k7W3TJubm5uL06dPo0KFCihXrlyZ5s3MKEABClCAAhSwjcD169eRmpqKGjVqwMXFnGNhDABL8d1SwV9wcHApcuBHKUABClCAAhSwl8DJkydRq1YtexVv13IZAJaCX438qaS+QH5+fqXIiR+lAAUoQAEKUEAvgZSUFG0AJ+/3uF7lGqkcBoCl6I28274q+GMAWApIfpQCFKAABShgB4G83+N2KNruRZrzxrfd2VkBClCAAhSgAAUoYD8BBoD2s2fJFKAABShAAQpQwC4CDADtws5CKUABClCAAhSggP0EOAfQxvZqqXlOTg4sFouNS2L2thJwdXWFm5sbt/qxFTDzpQAFKEAB3QUYANqQPCsrC2fOnEF6eroNS2HWegh4e3sjKCgIHh4eehTHMihAAQpQgAI2FWAAaCNetUn00aNHoUaP1EaTKnAw82ojGzHbPFs1gqsC+fPnz2v9GRYWZtpNQ22OzQIoQAEKUEA3AQaANqJWQYMKAtVG0Wr0iMlxBcqXLw93d3ccP35cCwa9vLwctzGsOQUoQAEKUEAEuAjExl8Dsx4xY2NW3bNnP+pOzgIpQAEKUMCGAk4bAG7atAm9e/fWbr+qW6+LFi26gVHd2nvrrbe0eV1qhKdLly6Ij4+/4Ro+oQAFKEABClCAAs4o4LQBYFpaGu666y7MnDmz0H6bPn06ZsyYgc8//xzbt2+Hj48PunbtioyMjEKv54t3JlC3bl18+OGHd/ZhfooCFKAABShAAZsIOO0cwO7du0P9FJbU6J8KSkaPHo2+fftql3z33XeoVq2aNlL46KOPFvYxU7zWoUMHNG3atMyCth07dmjBtSnw2EgKUIACFKCAgwg47Qhgcf5qde7Zs2e127551/n7++Pee+/FL7/8kvcS/yxCIG9vwyLevuHlwMBALoK5QYRPKEABCjiuwNXMHMxcfxhZObmO2wjWXBMwZQCogj+V1IhfwaSe571X8PW8x5mZmUhJSbnhJ+89Z/jzqaeewsaNG/HRRx9pW9aouZPHjh3Dhg0btOcrVqxA8+bN4enpiZ9//hlHjhzRRlCVm6+vL1q2bIk1a9bcQHHzLWCV51dffYV+/fppgaHaVmXJkiU3fObmJ//85z/RokULVKhQAdWrV8df/vIXJCUl3XDZ/v370atXL/j5+WnXtW3bVqtf3kVff/01IiIitLqr/fxeeumlvLf4JwUoQAEKlEBgU9x5dP1gE9756RC+2HikBJ/gJUYWMGUAeKcdMmXKFKiRwrwftcXL7SQ1cpaelaP7jyq3JEkFfq1atcJzzz2nbWCtNrEu2MYRI0Zg6tSpOHDgAKKionD16lX06NEDa9euxZ49e9CtWzdt4c2JEyeKLW78+PH405/+hH379mmff/zxx3Hp0qUiP5OdnY2JEydi79692i16FZSqYDUvJSYmol27dlpwt27dOuzatQvPPPOMdgKLuuazzz7DoEGD8PzzzyM6OloLOOvXr5/3cf5JAQpQgALFCFxJz8LrP+zFk1//isQr11CrYnncXbtiMZ/gW44g4LRzAIvDV6NIKp07d05bBZx3rXqu5r8VlUaOHImhQ4fmv61GAwsGSPlvFPHgWrYF4W/9VMS7tns5dkJXeHvcuqtVYKs2rFb7FuYZFazVhAkT8MADD+S/VKlSJW2hTd4LKkhbuHChFmAVN8KmgrfHHntM+9jkyZO1xTi//vqrFkDm5VXwTxXM5aXQ0FDtejXaqAJQNfKoFvqous+dO1fbr09d26BBg7yPYNKkSXjttdfwyiuv5L+mPs9EAQpQgALFC6yMOYPRi/bjwtVMuRMEPNW6Ll5/sCF8PG/9O6X4nPmuvQVMOQIYEhKiBThq5CovqWBOrQZWI2BFJXXrU91iLPhT1LXO+Lq6DVswqQDs9ddfR+PGjREQEKAFY2p08FYjgGr0MC+p1dfK8+Zbunnvqz/ViJ7a0qd27dra7d327dtrb+eV89tvv0Hd8lWbNd+cVL6nT59G586db36LzylAAQpQoAiBpNQM/P37XXjh+91a8Fcv0AfzXmiFsb0jGPwVYeZoLzttCK+Ck8OHD+f3h1r4oQIFNWqlAolXX31VGxlSc9BUQDhmzBhtz8CHHnoo/zNl/aC8uyvUaJzeSZVbFkkFawWTCv5Wr16Nd999F+qWqtpPccCAAdppGQWvu/nxzYGamheoTk0pLKntfNT2POpnzpw5UItKVOCnnqvTVlRS5RaVinuvqM/wdQpQgAJmFVBThhbsTsSEpbFIvpYNV5dy+Hv7enipU314ldHvErPaGq3dThsA7ty5Ex07dsz3zrt1O3DgQHz77bcYNmwYVHCh5oVduXIFbdq0wcqVK2HLY75UoFOSW7H5lbbDA3UL2GKxlKjkLVu2aHPx1IIOlVTQrebnlWU6ePAgLl68qM09zLvdrvq2YFIjirNnz4aaK3hzcKkWjtSVvQjVaG/B70PBz/MxBShAAQpAm9/35oJobJTFHipF1PDD9AFR8qc/eZxQwGlvAav97NS/ZG7+UcGfSioYU3Pa1KpftfmzWr1acN6YdpEJ/6OCJXUrXAVyFy5cKHJkTtGo0dMFCxZoI6tqgYZanVvUSN6dUqrRWhWUfvzxx0hISNDmF6q5hgWTmm+obuGr/RtVcKhOdFErhw8dOqRdNm7cOLz33nva3EH13u7du7X88vJ48sknoeZ3MlGAAhQwo0Bu7nX885djePD9jVrw5+HmgmHdGmLRoPsZ/DnxF8JpA0An7jObNk3d1nV1dUV4eHj+7daiCnz//fdRsWJFtG7dWpujp27LNmvWrKjL7+h1dctXBe0//PCDVie1Clndci6YKleuDLX6V41AqvmBaquaWbNm5Y8GqlFftfH3p59+qm0Fo7aLKXjsn7qlrFY8M1GAAhQwm0DC+at49MttGLN4P9KyLGhRpyJWvNIWL3aoD3dXhgjO/H0oJyNkJdsjxJkV7rBtatRJrT5NTk7WFjIUzEaNKqp5h2p+oS1vKxcsk49tJ8D+tJ0tc6YABfQXyLHkYtbmo/hgTZy2qbO3hyuGd2uE/7uvDlxk3p+zp+J+fzt72/Pa57RzAPMayD8pQAEKUIACFPhdIPZ0CobP34foxGTtxbZhVTC5XySCK3n/fhEfOb0AA0Cn72I2kAIUoAAFKABk5ljwybrD+GzDEeTIvD8/LzeM6RWOAc1rafPiaWQuAQaA5upvtpYCFKAABUwosPvEZQyftw/xSVe11neLqI4JD0WgagUvE2qwyUqAASC/BxSgAAUoQAEnFVDHj777Uxy+2XpUdsUAqvh6YmLfCHSPDHLSFrNZJRVgAFhSKV5HAQpQgAIUcCCBrYcvYITs63fiUrpW6/7NauItueUb4O3hQK1gVW0lwADQVrLMlwIUoAAFKGAHAXWCx5TlBzB3x0mt9JoB5fF2vybo0LCqHWrDIo0qwADQqD3DelGAAhSgAAVuU2B17DmMXhSNcymZ2iefbFVHNnVuBF9P/rq/TUqnv5zfCKfvYjaQAhSgAAWcXeDi1UyM+zEWP+49rTU1pIoPpj0chXtCKjl709m+OxRgAHiHcPwYBShAAQpQwN4C6iyHJRL0jVuyH5fTs+Eqmzg/1zYUr3YJg5e7q72rx/INLMBzXgzcOY5aNXWesDp6LS+pc5cXLVqU9/QPf6pzh9U1v/322x/e4wsUoAAFKFC4wJnka/jr7J14Ze5vWvDXqHoFLHrxfozo3ojBX+FkfLWAAEcAC2DwoW0E1Dm76sxgJgpQgAIUKL1ArmzirBZ4qIUeqZk58JAzewd3qo+/ta8HDzeO65Re2Bw5MAA0Rz/btZXVq1e3a/ksnAIUoICzCBy/mKYd47Yt4ZLWpLtrB2C6zPULq1bBWZrIdugkwH8q6ATtCMV8+eWXqFGjBnJzc2+obt++ffHMM89orx05cgTqebVq1eDr64uWLVtizZo1N1x/85ObbwH/+uuvuPvuu+Hl5YUWLVpgz549N3/kD8//+c9/atdWqFABKqD8y1/+gqSkpBuu279/P3r16gU/Pz+o69q2bQtV37z09ddfIyIiAp6enggKCsJLL72U9xb/pAAFKGBoAYuM+n21OQFdP9wEFfyVl/l96hi3eS+0ZvBn6J4zbuUYAOrZN2ob9qw0/X9UuSVIjzzyCC5evIj169fnX33p0iWsXLkSjz/+uPba1atX0aNHD6xdu1YL3Lp164bevXvjxIkT+Z8p7oH6vArSwsPDsWvXLowbNw6vv/56cR/R3svOzsbEiROxd+9ebT6hmjf41FNP5X8uMTER7dq104K7devWaXmroDUnJ0e75rPPPsOgQYPw/PPPIzo6GkuWLEH9+vXzP88HFKAABYwqcOhsKvp/thWTlh1ARnYuWterjJ9ebYdn24Roiz6MWm/Wy9gCvAWsZ/9ky27sk2voWaK1rDdlWwAPn1uWq+bpde/eHf/617/QuXNn7fp58+ahSpUq6Nixo/b8rrvugvrJSyooW7hwoRZQlWRETeWtRhj/8Y9/aCOAakTu1KlT+Pvf/56XZaF/5o1AqjdDQ0MxY8YMbfRRBZRqJHLmzJnw9/fH3Llz4e7uruXRoEGD/LwmTZqE1157Da+88kr+a2r0kokCFKCAUQWycnLx6YbDmLn+MLIt11FB9vIb1bMx/twyWFs4Z9R6s16OIcARQMfoJ91qqUb65s+fj8xM6yaic+bMwaOPPgoXF+tXRQVcasSucePGCAgI0IKvAwcOlHgEUF0bFRWlBX95jWrVqlXewyL/VKOFaqSxdu3a2u3d9u3ba9fmjTyqFcTqlm9e8FcwI3Wr+PTp0/lBbcH3+JgCFKCAEQX2nryCPp/8jA/XxGvBX5fG1bB6aHs8ek9tBn9G7DAHrBNHAPXsNHdvQI3G6Z1UuSVMKshS+0otW7ZMG2HbvHkzPvjgg/xPq+Bv9erVePfdd7VbqOXLl8eAAQOQlZWVf01ZP0hLS0PXrl21HxWQBgYGagGnei2vXFWPolJx7xX1Gb5OAQpQwB4C17IsEvTFYZbM95Npf6jk44FxfSLQOyqIgZ89OsSJy2QAqGfnyl53JbkVq2eVbi5LLczo378/VKB1+PBhNGzYEM2aNcu/bMuWLdrcu379+mmvqRFBNR+vpEmNHKoFHRkZGfmjgNu2bSv24wcPHtTmJk6dOhXBwcHatTt37rzhM2pUcfbs2VBzBW8eBVQLQurK3oRq3mLerewbPswnFKAABQwgsC3hIkbM34djF2W6kKS+TWtgbO8ILQg0QPVYBScT4C1gJ+vQsmiOug2sRgDVqtm8xR95+YaFhWHBggXaps1qQYZajXvzquG8awv7U12vVgU/99xziI2NxfLly7XRxMKuzXtN3fb18PDAxx9/jISEBG2+oZp7WDCp+YcpKSna7WoVHMbHx2uB5qFDh7TL1GKT9957T5s7qN7bvXu3ll9eHk8++SRGjhyZ95R/UoACFNBNIDUjG6MWRuPRL7dpwV91Py/8Y2ALfPTo3Qz+dOsF8xXEANB8fX7LFnfq1AmVKlWCCp5UwFYwvf/++9qmzq1bt9bm5KnbsAVHCAteW9hjtWDjxx9/1Fbiqq1gRo0ahWnTphV2af5r6pbvt99+ix9++EFbPaxGAtUt6IKpcuXKUKt/1Yikmh/YvHlzzJo1K380cODAgdrpJJ9++qm2FYxaiawCwbyk5hKqDauZKEABCugpsP5gErp+sAlztp/Qin1M5vitGtoOnWXOHxMFbClQTuZ7lWyPEFvWwkHzViNOauVpcnKytvdcwWaoW5xHjx5FSEhI/q3Ogu/zsWMJsD8dq79YWwoYXeByWhYmLI3Fwj2JWlXrVPbGlP6RssVLFaNX3SnqV9zvb6doYAkawTmAJUDiJRSgAAUoQIGyENAW2UWfwdjF+3FRgkAXmRr+zP0heO3Bhijv4VoWRTAPCpRIgAFgiZh4EQUoQAEKUKB0AkkpGRi9KAarYs9pGTWo5otpcozb3bV5VnrpZPnpOxFgAHgnavwMBShAAQpQoIQCatTvh52nMHFZLFIzcuAmw36DOtbHix3rwdONo34lZORlZSzAALCMQZkdBShAAQpQIE/g5KV0vCkrfDfHX9Beiqrlj+kDotCoul/eJfyTAnYRYABoF3YWSgEKUIACzixgkV2cv/vlGN756RDSZXNnTzcXmefXQJvv5+bKDTicue8dpW0MAG3cU1xkbWNgnbJnP+oEzWIo4AQCh5NSMXx+NHYdv6y15p6QStpcv5Aqtz6T3QmazyY4iAADQBt1VN5pFOnp6eBRZDZC1jFb1Y8q5fWrjkWzKApQwEEEsi25+HJTAj6S83uz5LGvpxtGdG+Ev8jefi5quS8TBQwkwADQRp3h6uqKgIAAJCUlaSV4e3vzHEcbWdsyWzXyp4I/1Y+qP1W/MlGAAhS4WSAmMRnD5u1D7JkU7a0ODQMxuV8kagQUfU75zXnwOQX0FGAAaEPt6tWra7nnBYE2LIpZ21hABX95/Wnjopg9BSjgQAIZ2RbMWBuPL2TkT837C/B2l/N7w/FQ05r8R78D9aMZq8oA0Ia9rs68DQoKQtWqVZGdnW3Dkpi1LQXUbV+O/NlSmHlTwDEFdh67hGHz9yHhfJrWgJ5RQRjfJwJVfD0ds0GstakEGADq0N0qeGAAoQM0i6AABSigg0BaZg6mrzyI77YdhzpMNbCCJyY91ARdI6x3fXSoAougQKkFGACWmpAZUIACFKCAWQQ2xZ3HyAXRSLxyTWvyn1rUwqge4fCXW79MFHAkAQaAjtRbrCsFKEABCthFIDk9WzvJY96uU1r5NWVxx9SHI9E2LNAu9WGhFCitAAPA0gry8xSgAAUo4NQCK2POYMzi/TifmikLO4CBrerija4N4SPbvDBRwFEF+O111J5jvSlAAQpQwKYCKuAbuyQGy6PPauXUC/TRjnFrXqeSTctl5hTQQ4ABoB7KLIMCFKAABRxGQO3/uWB3IiYsjUXytWy4yibOL7QPxeBOYfBy516gDtORrGixAgwAi+XhmxSgAAUoYCYBtbjjTVnksVEWe6gUUcNPG/WLqOFvJga21QQCDABN0MlsIgUoQAEKFC+QK5s4z9l+HFNXHERalgUebi54tUsYnmsbCndXl+I/zHcp4IACDAAdsNNYZQpQgAIUKDuBhPNXMWJ+NH6VjZ1ValGnoqzwjUL9qr5lVwhzooDBBBgAGqxDWB0KUIACFNBHIMeSi69+PooPVschMycX3h6uGN6tEf7vvjpwkXl/TBRwZgEGgM7cu2wbBShAAQoUKnDgTAqGzduH6MRk7f22YVUwuV8kgit5F3o9X6SAswkwAHS2HmV7KEABClCgSIHMHAtmrjuMTzccQY7M+/PzcsOYXuEY0LyW7PHHUb8i4fiG0wkwAHS6LmWDKEABClCgMIHdJy5juIz6xSdd1d7uGlENE/s2QVU/r8Iu52sUcGoBBoBO3b1sHAUoQAEKpGfl4L1Vcfh6y1HIFn+o4uuBCRL49YgMIg4FTCvAANC0Xc+GU4ACFHB+ga2HL2CE7Ot34lK61tj+zWpiTM9wVPTxcP7Gs4UUKEaAAWAxOHyLAhSgAAUcUyAlIxuTlx3A3B0ntQbU8PfC2/0j0bFhVcdsEGtNgTIWYABYxqDMjgIUoAAF7CuwJvYcRi2KxrmUTK0ialuX4d0bwdeTv/Ls2zMs3UgC/L/BSL3BulCAAhSgwB0LXLyaiXE/xuLHvae1PEKq+GCqjPrdG1r5jvPkByngrAIMAJ21Z9kuClCAAiYRuC4rO5ZI0Ddegr9LaVlQezg/1y4UQ7o0gJe7q0kU2EwK3J4AA8Db8+LVFKAABShgIIEzydcwemEM1h5M0mrVqHoFTB8QhahaAQaqJatCAeMJMAA0Xp+wRhSgAAUocAsBNer3719PYsryA0jNzIG7azkM7hSGF9rXg4ebyy0+zbcpQAHT/l9isVgwZswYhISEoHz58qhXrx4mTpwoe0TJJlFMFKAABShgWIHjF9Pwl1nb8ebCaC34axocgGUvt8XLncMY/Bm211gxowmYdgRw2rRp+OyzzzB79mxERERg586dePrpp+Hv74+XX37ZaP3E+lCAAhQwvYBFjm77RjZzfnfVIWRk58r8Phe8/mBDPH1/CFzVxD8mClCgxAKmDQC3bt2Kvn37omfPnhpW3bp18e9//xu//vprifF4IQUoQAEK6CMQdy4Vb8gxbntPXtEKbF2vsqzwjULtyt76VICl/C6QkwW4cSPt30Ec85FpbwG3bt0aa9euRVxcnNZze/fuxc8//4zu3bsX2ZOZmZlISUm54afIi/kGBShAAQqUWiArJxcfrYlHzxmbteCvguzlp7Z2mfPXexn8lVr3NjNQU6T2zgU+igIuxN/mh3m50QRMOwI4YsQILZBr1KgRXF1doeYEvv3223j88ceL7KMpU6Zg/PjxRb7PNyhAAQpQoOwE1Gjf8Pn7cPBsqpZpl8ZVMemhSFSXUz2YdBa4IieqLB0CHF5tLXjrx0CfGTpXgsWVpYBpA8D//ve/mDNnDv71r39pcwB/++03vPrqq6hRowYGDhxYqPHIkSMxdOjQ/PfUaGBwcHD+cz6gAAUoQIHSC2RkW/DB6jjM2pwAmfaHSnJu79je4ehzVw2UK8e5fqUXvo0ccnOBXV8Dq8cCWVcBV7n12344cP8rt5EJLzWiQDlZ9Sr/e5kvqcBNjQIOGjQov/GTJk3C999/j4MHD+a/VtwDFQCqRSPJycnw8/Mr7lK+RwEKUIACJRDYnnBRG/U7djFdu7pv0xp4q1c4Kvt6luDTvKRMBS4eAZYMBo5vsWYbfK+M+n0CBDYo02LskRl/f8s0TnvAG6HM9PR0uLjcOAVS3QrOVf/aYaIABShAAV0FUjOyMW3lQXy/7YRWbnU/L7nd2wRdwqvpWg8WJgKWHGDbTGD9ZCAnA3D3AbrICGDLvwIuPFnFWb4jpg0Ae/furc35q127tnYLeM+ePXj//ffxzDPPOEvfsh0UoAAFHEJg/aEkjFoQjdPJEmxIeuyeYIzs0Rh+Xu4OUX+nquTZGBn1ewk4vcfarNAOQG+Z61exjlM1k40BTHsLODU1VdsIeuHChUhKStLm/j322GN466234OFRsuXtHELm/0IUoAAF7lzgspzbO3FpLBbsSdQyqV3JW1vh27p+lTvPlJ+8M4GcTGDze9afXBkB9PIHusoIYFNZGOmE8y75+9vEAeCd/R9y46f4BbrRg88oQAEKlERATT1fFn0GYxfvx0UJAtUezs/IZs6vyabO5T14i7EkhmV6zamdwGIZ9Tt/wJpto15ATwkGK1Qv02KMlBl/f5t4DqCRvoisCwUoQAGzCCSlZGD0ohisij2nNTmsqi+mD4jC3bUrmoXAOO3MkoU26ybJfL9PpU6yHtQnEOjxDhD+kFOO+hkH3hg1Me0cQGPwsxYUoAAFzCGgRv1+2HUKk+SWb0pGDtxk2O/FjvUxqGM9eLpx1E/3b8HRTdYVvpePWYuOehToNgXwrqR7VVigfQQYANrHnaVSgAIUMI3AyUvpeHNhNDbHX9DaHFnTXxv1axzE7bN0/xJkJMuefm/J3n7fWov2qwn0+hBo8KDuVWGB9hVgAGhff5ZOAQpQwGkFcmUX59m/HMM7Px1CepZFRvpcMPSBBni2TQjcXG/chstpEYzUsEMrrad5pJ621qrFs7K9yzhZ8MFA3EjdpFddGADqJc1yKEABCphI4HBSqmzoHI1dxy9rrb4npJK2wjc00NdECgZpapqMvK6Q0zti5lkrVClUNnSWo9zqtjFIBVkNewgwALSHOsukAAUo4KQC2ZZcfLkpAR+tiUeWPPaRVb0jZE+/x++pLZvv8xg3XbtdHfQVM1+Cv2FA+kVZ2CGjrq1eAjq+KZs7l9e1KizMeAIMAI3XJ6wRBShAAYcUiElMxrB5+xB7JkWrf4eGgXi7XyRqBjDY0L1DU+Q271I5uz5uhbXoqhFAXxn1q9lc96qwQGMKMAA0Zr+wVhSgAAUcRiAj24IZa+PxhYz8WWTeX4C3O8b2DsdDTWvKHsIc9dO1I9Wo3+7ZwKoxQKYE4i5ymkq7N4A2Q2TjNw9dq8LCjC3AANDY/cPaUYACFDC0wM5jlzBs/j4knE/T6tkzMgjj+kQgsIKnoevtlJW7lCBbu7wMHNtsbZ4a7esrZ/pWbeyUzWWjSifAALB0fvw0BShAAVMKpGXmaKt71SpfNeikAr6JfZugWxPnPT3CsB2dawG2fw6snQjkXJORPrnl3mk0cN/fZQSQeywatt/sXDEGgHbuABZPAQpQwNEENsWdx8gF0Ui8IsGGpEea18LonuHwl1u/TDoLJB2wHuOWuNNacN22ssJ3BqBW+jJRoBgBBoDF4PAtClCAAhT4XSA5PRsTl8VinpzooZJa3DH14Ui0DZMjxJj0FcjJArbIBs4bpwO52YCn7OX3oIwANhvIY9z07QmHLY0BoMN2HStOAQpQQD+BlTFnMWZxDM6nZsrCDmBgq7p4o2tD+Hjy14h+vfC/khJ3W49xOxdjfaFBN6Dn+4C/nOrBRIESCvD/3BJC8TIKUIACZhRQAd+4JfuxLPqM1vzQQB9MfzgKLepWMiOHfducLbfcN0wBtsp2Ltdz5dzeykB3GQFs8jBH/ezbMw5ZOgNAh+w2VpoCFKCAbQWuy8qOhXsSMWFpLK7IrV9X2cT5hfahGNwpDF7uXFhgW/1Ccj+2xTrqd+mI9U0V9Kngz6dKIRfzJQrcWoAB4K2NeAUFKEABUwmoxR2jFkZjw6HzWrvDg/wwfUAUmtT0N5WDIRqbmQqsGQfs+MpanQpB1tu9jXoYonqshOMKMAB03L5jzSlAAQqUqUCubOI8Z/txTF1xEGlZFni4ueCVzmF4vl0o3F3lGDEmfQXiVwM/vgqknLKWqxZ4PDABKB+gbz1YmlMKMAB0ym5loyhAAQrcnsDRC2kYLhs6/3r0kvbB5nUqYprM9atf1ff2MuLVpRdIlz5YORLYN9eaV0Ad2drlYyC0fenzZg4U+J8AA0B+FShAAQqYWCDHkouvfj6KD1bHITMnF94erhgmq3uflFW+LjLvj0lHAbWjduxiYPnrQJq6/S7+970omzqPAjx8dKwIizKDAANAM/Qy20gBClCgEIEDZ1IwbN4+RCcma++2DauCyf0iEVzJu5Cr+ZJNBVLPAsteAw4utRYT2EhG/T4BglvatFhmbl4BBoDm7Xu2nAIUMKlAZo4FM9cdxqcbjiBH5v35eblhdK9w7USPcmqTPyb9BNSo329zgJ/eBDIkEHeRX8tthgLtZBTQjecp69cR5iuJAaD5+pwtpgAFTCyw+8RlDJdRv/ikq5pC14hq2hm+Vf28TKxip6ZfPi6LPF4BEtZbKxDUFOgro37VI+1UIRZrJgEGgGbqbbaVAhQwrUB6Vg7eWxWHr7cchRp0quLrgfF9mqBHZHU52YOjfrp+MXJlE+cds2R7l/FAdpqM9Enw3UEWfbR6CXDlr2Vd+8LEhfGbZuLOZ9MpQAFzCGw9fAEjFkTjxKV0rcH9m9XEmJ7hqOjjYQ4AI7XyQjywWAK9k9ustard2rrCt0p9I9WSdTGBAANAE3Qym0gBCphTICUjG1OWH8C/fz2pAdTw98Lb/SPRsWFVc4LYs9WWbDnCbYYc5TYNsGTKql7ZXucBGQFs/ozM++Mei/bsGrOWzQDQrD3PdlOAAk4tsCb2HEYtisa5FAk2JD1xX20M79YIFbzcnbrdhmzcmb3WUb+z+6zVq98F6PUhEBBsyOqyUuYQYABojn5mKylAAZMIXLyaifE/xmLJ3tNai0Oq+GCKjPrdF1rZJAIGamZ2BrBJzuv9WYK96xY5waMi0HUKcNejssUf510aqKdMWRUGgKbsdjaaAhRwNoHrsrJDBX0q+LuUlgW1h/NzcoTbkC4N4OXu6mzNNX57TmwHlshcvwtx1rqG9wV6vAv48va78TvPHDVkAGiOfmYrKUABJxY4m5yBUQujsfZgktbKRtUrYPqAKETV4pmxund7pmyvs24isP0LKVqWW/tWswZ+4X10rwoLpEBxAgwAi9PhexSgAAUMLKBG/ebuOInJyw4gNTMH7q7lMLhTGF5oXw8eblxYoHvXHVln3dfvyglr0U2fkFu+k6y3fnWvDAukQPECDACL9+G7FKAABQwpcPxiGkbMj8YvCRe1+jUNDtBG/RpUq2DI+jp1pa5dlpM8RsuJHt9bm+lfG+gt8/7qd3bqZrNxji3AANCx+4+1pwAFTCZgkaPbvpHNnN9ddQgZ2bkyv88Frz/YEE/fHwJXNfGPSV+BA0vlDF85uu3qOSlX/O95Huj8FuAp27wwUcDAAgwADdw5rBoFKECBggJx51IxTI5x++3kFe3l1vUqY2r/KNSu7F3wMj7WQ+CqzLdc/gYQu8haWuUw64bOdVrpUTrLoECpBRgAlpqQGVCAAhSwrUBWTi4+23AEn6yPR7blOip4uuHNno3xaMtgHuNmW/o/5q7O0dv3H2DlCEDd+i0nK6zvl/N82w8H3Hme8h/B+IpRBRgAGrVnWC8KUIACIrDv1BVt1O/g2VTNo0vjqpj0UCSqy6keTDoLJJ+SRR6vAodXWwuuHimjfp8ANZrqXBEWR4HSCzAALL0hc6AABShQ5gIZ2RZ8sDoOszYnQKb9oZKc2zuuTwR6RwVx1K/MtW+RYW4usOtrYPU4IEsCcVc5Q1mN+KmRP1eerHILPb5tUAEGgAbtGFaLAhQwr8B2Wdk7fP4+HLuYriH0bVoDb/UKR2VfT/Oi2KvlF4/Ihs6DgeNbrDUIvtc66hfYwF41YrkUKBMBBoBlwshMKEABCpReIDUjG9NWHsT326z7yFX385LbvU3QJVw2E2bSV8CSA2ybCayfDOTIkW7uPkCXsUDLvwIuPFlF385gabYQYABoC1XmSQEKUOA2BdYfSsKoBdE4Lad6qPTYPcEY2aMx/Lx4i/E2KUt/+dkY6zFup/dY8wrtIPv6zQAq1il93syBAgYRYABokI5gNShAAXMKXJZzeycujcWCPYkaQO1K3rK1SyRa169iThB7tjonE9j8nvUnV0YAPf3lJI+3gbvlRI9y3GPRnl3DsstegAFg2ZsyRwpQgAK3FFDHuC2PPouxS2Jw4WoW1B7Oz8hmzq/Jps7lPXiL8ZaAZX3BqZ3A4peA8wesOTfqZT3D1y+orEtifhQwhAADQEN0AytBAQqYSSApJQOjF8VgVaw6PQIIq+qrHeN2d+2KZmIwRluzZKHNukky3+9TqY8st/YJlMDvHSD8IY76GaOHWAsbCTAAtBEss6UABShws4Aa9fth1ylMklu+KRk5cJNhvxc71segjvXg6cZRv5u9bP786CbrCt/Lx6xFRT0KdJsCeFeyedEsgAL2FmAAaO8eYPkUoIApBE5eSsebC6OxOf6C1t7Imv7aqF/jID9TtN9QjcxIlj395LzeXd9aq+VXE+j1IdDgQUNVk5WhgC0FGADaUpd5U4ACphfIlV2cZ/9yDO/8dAjpWRYZ6XPB0Aca4Nk2IXBzdTG9j+4Ah1YCS4cAqaetRbd4VrZ3GQd4MRDXvS9YoF0FGADalZ+FU4ACzixwOClVNnSOxq7jl7Vm3hNSCdMejkJIFdlTjklfgTQZeV0hp3fEzLOWWylUNnT+GKjbRt96sDQKGESAAaBBOoLVoAAFnEcg25KLLzcl4KM18ciSx76ebhjRvRH+ck9tuKjlvkz6Cci8S8TMl+BvGJB+URZ2yKhrq5eAjm/K5s7l9asHS6KAwQQYABqsQ1gdClDAsQViEpMxbN4+xJ5J0RrSoWEgJveLRI0ABhu692yK3OZdOhSIW2EtumoE0FdG/Wo2170qLJACRhNgAGi0HmF9KEABhxTIyLZgxtp4fCEjfxaZ9xfg7Y6xvcPxUNOasocwR/107VQ16rd7NrBqDJApgbiLnKbS7g2gjcz9c/PQtSosjAJGFWAAaNSeYb0oQAGHEdh57BKGzd+HhPNpWp17RgVhfJ8IVPH1dJg2OE1FLyXI1i4vA8c2W5ukRvv6ypm+VRs7TRPZEAqUhQADwLJQZB4UoIApBdIyc7TVvWqVrxp0CqzgiUkPNUHXiOqm9LBro3MtwPbPgbUTgZxrMtInt9w7ywjgvS/ICCD3WLRr37BwQwowADRkt7BSFKCA0QU2xZ3HyAXRSLwiwYakP7WohVE9wuEvt36ZdBZIOmA9xi1xp7Xgum1lhe8MQK30ZaIABQoVYABYKAtfpAAFKFC4QHJ6NiYui8U8OdFDpVoVy2NK/0i0DZMjxJj0FcjJArbIBs4bpwO52YCn7OX3oIwANhvIY9z07QmW5oACsh7evCkxMRFPPPEEKleujPLlyyMyMhI7d/7vX5DmZWHLKUCBIgRWxpxFlw82asGfWtfxVOu6+OnVdgz+ivCy6cuJu4FZHYH1b1uDvwbdgBe3Ac2fYvBnU3hm7iwCph0BvHz5Mu6//3507NgRK1asQGBgIOLj41GxIg9jd5YvN9tBgbISOJ+aibFLYrA8+qyWZb1AH+0Yt+Z1KpVVEcynpALZcst9/WTgl0+A67lybm9loLuMADZ5mIFfSQ15HQVEwLQB4LRp0xAcHIxvvvkm/4sQEhKS/5gPKEABClyXlR0L9yRiwtJYXJFbv66yifML7UMxuFMYvNy5sED3b8ixLbLCdzBw6Yi1aBX0qeDPp4ruVWGBFHB0AcPeAs7KysKhQ4eQk5NjE+MlS5agRYsWeOSRR1C1alXcfffdmDVrlk3KYqYUoIDjCajFHU9/uwND/7tXC/4iavhhyUv3442ujRj86d2dmanAsteAb3tYg78KQcCj/wYGfM3gT+++YHlOI2C4ADA9PR3PPvssvL29ERERgRMnTmjYgwcPxtSpU8sMPiEhAZ999hnCwsLw008/4e9//ztefvllzJ4tm4cWkTIzM5GSknLDTxGX8mUKUMBBBXJlE+d//nIMD76/ERsOnYeHmwuGdWuIRYPuR0QNfwdtlQNXO341MPM+YMdX1kaoBR5qrl8jCQaZKECBOxYwXAA4cuRI7N27Fxs2bICXl1d+w7p06YL//Oc/+c9L+yA3NxfNmjXD5MmTtdG/559/Hs899xw+/1z2kSoiTZkyBf7+/vk/6hYyEwUo4DwCRy+k4dFZ2zBm8X6kZVnQok5FLH+5LV7sUB/urob769J54AtrSfolYMHfgDkDgBRZcR1QB3hyiXV7l/IBhX2Cr1GAArchYLg5gIsWLdICvfvuu++G45PUaOCRI/+b93EbDSzq0qCgIISHh9/wduPGjTF/vhwaXkRSwenQoUPz31WjgQwC8zn4gAIOK5BjycVXPx/FB6vjkJmTC28PVwzv1gj/d18duMi8PyYdBdSO2rGLgeWvA2nnpWDxv+9FoNMowMNHx4qwKAo4t4DhAsDz589rc/JuZk9LS7shILz5/dt9rlYAqzmGBVNcXBzq1JF/ZRaRPD09oX6YKEAB5xE4cCYFw+btQ3RistaotmFVMLlfJIIreTtPIx2lJamyylrN9Tu41FrjwEYy4vcJENzSUVrAelLAYQQMFwCqhRnLli2DmvOnUt4h6l999RVatWpVZrBDhgxB69attVvAf/rTn/Drr7/iyy+/1H7KrBBmRAEKGFYgM8eCmesO49MNR5Aj8/78vNwwplc4BjSvlf/3jmEr72wVU6N+v80BfnoTyJBA3EV+NbWRuy3tZBTQjf/odrbuZnuMIWC4AFDNyevevTtiY2O1FcAfffSR9njr1q3YuHFjmam1bNkSCxcuhLqtO2HCBKgtYD788EM8/vjjZVYGM6IABYwpsPvEZQyXUb/4pKtaBbtGVMPEvk1Q1e/3ecfGrLkT1uryceDHV4CE9dbGBTUF+s4EqjdxwsaySRQwjkA52edK/ullrKTm+qkVv2oxyNWrV7XFGsOHD9dO6jBSTdUcQLUoJDk5GX5+cgQREwUoYGiB9KwcvLcqDl9vOQr1N18VXw9MkMCvR6RsK8Kkr4AsxMMO2XprzXggO01G+iT47jASaPUS4Gq4sQl9bViazQX4+1vusBoxALR5z5dRAfwClREks6GADgJbD1/AiAXROHEpXSutf7OaGNMzHBV9PHQonUXcIHAhHlgsgd7JbdaXa7eWuX4fS0Re/4bL+IQCthLg728DngSyfPlyuLq6omvXrjf0u9qrT23dom4PM1GAAhQoqUBKRjamLD+Af/96UvtIDX8vvN0/Eh0bVi1pFryurAQs2cDWGcCGaYAlU1b1+gIPyAhg82dk3h+32SkrZuZDgZIIGO7/uBEjRsBisfyh7upOtXqPiQIUoEBJBdbEnsMDsqFzXvCntnVZNbQ9g7+SApbldWf2ArM6AWsnWIO/+l2sGzq3/CuDv7J0Zl4UKKGA4SZaxMfH/2F/PtWWRo0a4fDhwyVsFi+jAAXMLHDxaibG/xiLJXtPawwhVXwwVUb97g2tbGYW+7Q9OwPYNB34+UPguvzjvnxFoNtUIOrPapsH+9SJpVKAAjBcAKgWVahj2urWrXtD96jgz8eHm4DegMInFKDADQLqToEK+lTwdyktC2oP5+fahWJIlwY8v/cGKZ2enNgOOUAZuBBnLTC8L9DjXcCXt9916gEWQ4EiBQwXAPbt2xevvvqqtkVLvXr1tIqr4O+1115Dnz59imwI36AABcwtcDY5A6MWRmPtwSQNolH1Cpg+IApRtXhsmO7fjEzZXmfdRGD7F1K0LLf2rWYN/ML5d7jufcECKVCEgOECwOnTp6Nbt27aLd9atWpp1T516hTatm2Ld9+VfzkyUYACFCggoEb95u44icnLDiA1M0fO7C2HwZ3C8EL7evBwM9w05wI1d9KHR9ZZ9/W7csLawKZPAF0nWW/9OmmT2SwKOKKA4QJAdQtYbfq8evVqbR/A8uXLIyoqCu3atXNEX9aZAhSwocDxi2kYMT8avyRc1EppGhygjfo1qFbBhqUy60IFrl2WkzxGy4ke31vf9q8N9JZ5f/U7F3o5X6QABewrwH0AS+HPfYRKgcePUqAUAhY5uu0b2cz53VWHkJGdK/P7XPD6gw3x9P0hcFUT/5j0FTiwVM7wlaPbrp6TcsX/nueBzm8BnrLNCxMFDCjA398G3AdQfU/Wrl2r/SQlJWl7/xX87nz99dcFn/IxBShgMoG4c6kYJse4/Xbyitby1vUqywrfKNSu7G0yCQM096rMt1z+BhC7yFqZymHWDZ3rtDJA5VgFClCgOAHD3QIeP368djZvixYtEBQUxEPZi+s9vkcBEwlk5eTisw1H8Mn6eGRbrqOCpxtG9WyMP7cM5t8Ten8PZN4l9v0HWCl7s6pbv+VcgfvlPN/2wwF3nqesd3ewPArciYDhAsDPP/8c3377Lf7v//7vTtrDz1CAAk4osO/UFW3U7+DZVK11XRpXxaSHIlFdTvVg0lkg+ZQs8ngVOLzaWnD1SBn1+wSo0VTnirA4ClCgNAKGCwCzsrLQurWcC8lEAQqYXiAj24IPVsdh1uYEyLQ/VJJze8f1iUDvKN4d0P3LIUdxYpdMwVk9DsiSQNxVzlBWI35q5M/VXffqsEAKUKB0AoYLAP/617/iX//6F8aMGVO6lvHTFKCAQwtsl5W9w+fvw7GL6Vo7+jatgbd6haOyr6dDt8shK3/xiGzoPBg4vsVa/eB7raN+gQ0csjmsNAUoYMBFIBkZGfjyyy+xZs0abfsXd/cb/2X5/vvvs98oQAEnFkjNyMa0lQfx/TbrPnLV/bzkdm8TdAmXzYSZ9BWw5ADbZgLrJwM5cqSbu5zG1GUsoJ3fK/P+mChAAYcVMNwI4L59+9C0qXUuSUxMzA2w5Xhu5A0efEIBZxNYfygJoxZE47Sc6qHSY/cEY2SPxvDzuvEfgs7WbkO256z8/auOcTu9x1q90A6yr98MoGIdQ1aXlaIABW5PwHAB4Pr162+vBbyaAhRweIHLcm7vxKWxWLAnUWtL7UresrVLJFrXr+LwbXO4BuRkApvfs/7kygigp7+c5PE2cLec6MF/hDtcd7LCFChKwHABYFEV5esUoIDzCahj3JZHn8XYJTG4cDULag/nZ2Qz59dkU+fyHrzFqHuPn9oJLJZRv/MHrEU36mU9w9cvSPeqsEAKUMC2AoYMAHfu3In//ve/OHHiBNSq4IJpwYIFBZ/yMQUo4KACSSkZGL0oBqti1ekRQFhVX+0Yt7trV3TQFjlwtbNkoc26STLf71NpxHXAJ1ACv3eA8Ic46ufA3cqqU6A4AcOdlD537lxtG5gDBw5g4cKFyM7Oxv79+7Fu3Tqoc4KZKEABxxZQo37/3XkSXd7fqAV/bjLs93LnMCx9uQ0Y/Nmhb49uAj6TkzvUYg8V/EX9GRj0KxDRj8GfHbqDRVJALwHDjQBOnjwZH3zwAQYNGoQKFSrgo48+QkhICP72t79pJ4PoBcNyKECBshc4eSkdby6Mxub4C1rmkTX9tVG/xkF+ZV8YcyxeICNZ9vST83p3fWu9zq8m0OtDoMGDxX+O71KAAk4hYLgA8MiRI+jZs6eG6+HhgbS0NO2YpyFDhqBTp05QR8UxUYACjiWQK7s4z/7lGN756RDSsyzwdHPB0Aca4Nk2IXBzNdyNCMfCvZPaHloJLB0CpJ62frrFs7K9yzjAi4H4nXDyMxRwRAHDBYAVK1ZEaqr1uKeaNWtCbQUTGRmJK1euID3duiGsI0KzzhQwq8DhpKvahs67jl/WCO4JqaSt8A0N9DUrif3anSYjryuGAzHzrHWoFCobOn8M1G1jvzqxZApQwC4ChgsA27Vrh9WrV2tB3yOPPIJXXnlFm/+nXuvcubNdkFgoBShw+wLZllx8uSkBH62JR5Y89pFVvSNkT7/H76kNF7Xcl0k/AZl3iZj5EvwNA9Ivytw+GXVt9RLQYSTg4a1fPVgSBShgGAHDBYCffPIJ1GkgKo0aNQrqJJCtW7fi4YcfxujRow0Dx4pQgAJFC8QkJmPYvH2IPZOiXdS+QSAmy75+NQPKF/0hvmMbgRS5zbt0KBC3wpp/1Qigr4z61Wxum/KYKwUo4BAC5WRFnvzTkOlOBFJSUrSVycnJyfDz49yZOzHkZ5xLICPbghlr4/GFjPxZZN5fgLe7dn5vv7tranN5nau1Bm+N+qt993fAKjlXPVMWfLjIaSrt3gDayNw/Nw+DV57Vo4BtBfj724BnAed1eVJSEtRPbm5u3kvan1FRUTc85xMKUMAYAjuPXcKw+fuQcD5Nq1DPyCCM6xOBwAqexqigmWpx6Sjw48uA2uJFJTXa11e2eana2Pqc/6UABUwvYLhbwLt27cLAgQOh9gG8eXBSnQVssVhM32kEoICRBNIyc7TVvWqVrxp0UgHfxL5N0K1JdSNV0xx1yZW/H7d/DqydCORck3/iyy33TjJ15r6/ywggT1Yxx5eAraRAyQQMFwA+88wzaNCgAf7xj3+gWrVqvG1Usn7kVRSwi8CmuPMYuSAaiVck2JD0SPNaGN0zHP5y65dJZ4Gkg8ASWdhxaoe14LptZYXvDECt9GWiAAUocJOA4QLAhIQEzJ8/H/Xr17+pqnxKAQoYRSA5PRsTl8Vi3q5TWpXU4o6pD0eibVigUaponnrkyHGZW2QD501ydJtFHnvKfOQHZQSw2UCe5GGebwFbSoHbFjBcAKi2etm7dy8DwNvuSn6AAvoIrIw5izGLY3A+NVNG6IGBrerija4N4eNpuL9O9AGxZymJu2XUbzBwLsZaiwbdgJ7vA/5yqgcTBShAgWIEDPc39ldffaXNAVQbQDdp0kTbBqZg/fv06VPwKR9TgAI6CaiAb9yS/VgWfUYrMTTQB9MfjkKLupV0qgGLyRfIllvuG6YAW2U7l+uyUM67MtB9OtDkYY765SPxAQUoUJyA4QLAX375BVu2bMGKFf/bs6pA7bkIpAAGH1JAJwG1GGvhnkRMWBqLK3Lr11U2cX6hfSgGdwqDlzsXFujUDb8Xc2yLddTv0hHrayroU8GfT5Xfr+EjClCAArcQMFwAOHjwYDzxxBMYM2aMtgjkFvXn2xSggA0F1OKOUQujseHQea2U8CA/TB8QhSY1/W1YKrMuVCAzFVgzDtjxlfXtCkHW272NehR6OV+kAAUoUJyA4QLAixcvYsiQIQz+ius1vkcBGwvkyibOc7Yfx9QVB5GWZYGHmwte6RyG59uFwt1VjhFj0lcgfrXs6/cqkHLKWq5a4PHABKB8gL71YGkUoIDTCBguAOzfvz/Wr1+PevXqOQ0yG0IBRxI4eiENw2VD51+PXtKq3bxORUyTuX71q/o6UjOco67p0gcr5bzefXOt7alYF+gtW7uEtneO9rEVFKCA3QQMFwCqPQBHjhyJn3/+GZGRkX9YBPLyyy/bDYsFU8CZBXIsufjq56P4YHUcMnNy4e3himGyuvdJWeXrIvP+mHQW2L8IWP46kKZuv4v/fS/Kps6jAA8fnSvC4ihAAWcUMNxZwCEhIUU6q+RKohMAAD5iSURBVEUgap9AoySeJWiUnmA9Sitw4EwKhs3bh+hEOTNWUtuwKpjcLxLBlbxLmzU/f7sCqWetgd+BH62fDGwkGzp/AgS3vN2ceD0FKFCEAH9/G/As4KNHjxbRXXyZAhQoa4HMHAtmrjuMTzccQY7M+/PzcsOYXuEYICd6qH9wMekooM7R+20O8NObQIYE4i5yg6bNUKCdjAK68TxlHXuCRVHAFAKGugWcnZ2NRo0aYenSpWjcmIeWm+IbyEbaTWD3icsYLqN+8UlXtTp0jaimneFb1c/LbnUybcGXj8sij1eAhPVWgqCmQN+ZQPUmpiVhwylAAdsKGCoAdHd3R0ZGhm1bzNwpYHKB9KwcvLcqDl9vOQo16FTF1wMT+jZB9ybVOeqn93cjVzZx3jFLtncZD2SnyUifBN8dZQTwvkGAq6H+etZbhuVRgAI2FjDc3zCDBg3CtGnToE4EcXMzXPVs3B3MngK2Fdh6+AJGLIjGiUvpWkH9m9XEmJ7hqOjjYduCmfsfBS7EA4tfAk5us75Xu7XM9ftYIvL6f7yWr1CAAhQoYwHDRVg7duzA2rVrsWrVKm0VsI/PjSveFixYUMYEzI4Czi+QkpGNycsOYO6Ok1pja/h74e3+kejYsKrzN95oLbRkyxFuspXLhmmAJVNW9cr2Og/ICGDzZ2TeH/dYNFp3sT4UcFYBwwWAAQEBePhhOdqIiQIUKBOBNbHnMGpRNM6lSLAh6f/uq4Nh3Rqigpd7meTPTG5D4Mxe66jf2X3WD9XvAvT6EAgIvo1MeCkFKECB0gsYLgD85ptvSt8q5kABCuDi1UyM+zEWP+49rWmEVPHBVBn1uze0MnX0FsiWuc2b5LzenyXYu26REzwqAt2mAlF/li3+uNpa7+5geRSggAG3gcnrlPPnz+PQoUPa04YNGyIwMDDvLf5JAQoUI3BdVnYskaBvvAR/l9KyoPZwfk6OcBvSpQG83F2L+STfsonAie3AEpnrdyHOmn34Q0CPdwBf3n63iTczpQAFSiRguBHAtLQ0DB48GN999x1y1Qo5Sa6urnjyySfx8ccfw9ubG9OWqGd5kSkFziRfw+iFMVh7MElrf6PqFTB9QBSiagWY0sOujc6U7XXWTQS2fyHVkOXWvtWAnu8BjXvbtVosnAIUoIASMNyM46FDh2Ljxo348ccfceXKFe1n8eLF2muvvfYae40CFChEQI36/Wv7CTz4/iYt+HN3LYehDzSQgac2DP4K8bL5S0fWAZ+1kuDvcylKgr+mTwCDZCSQwZ/N6VkABShQMgHDHQVXpUoVzJs3Dx06dLihBevXr8ef/vQnqFvDRkk8SsYoPWHuehy/mIYR86PxS8JFDaJpcIA26tegWgVzw9ij9dcuy0keo+VEj++tpfvXBnrLvL/6ne1RG5ZJAQoUIcDf3wacA5ieno5q1eRWyU2patWqUO8xUYACVgGLHN32jWzm/O6qQ8jIzpX5fS54/cGGePr+ELiqiX9M+gocWAosk6Pbrp6TcsX/nueBzm8BnrLNCxMFKEABgwkYbg5gq1atMHbsWG0OoJeX9Uiqa9euYfz48VDvMVGAAkDcuVS8Ice47T15ReNoXa+yrPCNQu3KnCOr+/fjqsy3XP4GELvIWnTlMDnG7ROg9n26V4UFUoACFCipgOECwA8//BDdunVDrVq1cNddd2nt2Lt3L1Qw+NNPP5W0XbyOAk4pkJWTi882HMEn6+ORbbmOCp5uGNWzMf7cMpjHuOnd4+ocvX3/AVaOANSt33KywrrNq0C7YYC79R+veleJ5VGAAhQoqYDh5gCqiqtbvXPmzMHBgwe1djRu3BiPP/44ypcvX9J26XId5xDowsxC/iegRvuGz9+Hg2dTtVe6NK6KSQ9Forqc6sGks0DyKeBHCfYOr7YWXD1SRv1mAkHWf7TqXBsWRwEK3KYAf38bZA5gs2bNtOPfKlasiAkTJuD111/Hc889d5vdycsp4JwC17Is+HBNHGZtToBM+0MlObd3XJ8I9I4K4qif3l2utqba9TWwehyQJYG4qyfQYTjQ+mV5zJNV9O4OlkcBCty5gCG2gTlw4ADU/n8qqbl+V6/K/lk6p6lTp2q/TF99Vf5Vz0QBgwhsk5W93T/ahC82WYO/vk1rYPWQduhzVw0Gf3r30cUjwOxestBDtqNSwV/wvcALPwNt5TmDP717g+VRgAKlFDDEHMCmTZvi6aefRps2baD2M3v33Xfh61v4yrm33pJVdWWcduzYgS+++AJRUVFlnDOzo8CdCaRmZGPqioOYI3v7qVTdz0tu9zZBl/A/rpC/sxL4qRILWHKAbXJ7d/1kICdD5vf5AF3GAi3lLoWLIf4NXeKm8EIKUIACeQKGCAC//fZbbeXv0qVLtVGNFStWwM3tj1UrJ2dmlnUAqEYb1fzCWbNmYdKkSXku/JMCdhNYL6d4jFoYjdPJEmxIeuye2hjZoxH8vHiLUfdOORtjPcbt9B5r0aEdZV+/j4CKdXSvCgukAAUoUJYCf4yyyjL3EualzvqdO3eudrWL/It67dq1UPv+6ZEGDRqEnj17okuXLrcMADMzM6F+8pKaRMpEgbISuCzn9k5YGouFexK1LGtX8sbUhyPRul6VsiqC+ZRUIEf+P9/8nvUnV0YAvfyBrjIC2PRxWe3LPRZLysjrKEAB4woYIgDM48nOzsbAgQPz5wPmvW6rP1XQuXv3bqhbwCVJU6ZM0eYoluRaXkOBkgqoaQ/Los9g7OL9uChBoNrD+RnZzPk12dS5vIdsLcKkr8CpncDil4DzB6zlNpJ5f+oM3wrV9a0HS6MABShgQwHDbQMTEBCAPXv2ICQkxIbNBk6ePIkWLVpg9erV+XP/1PFzaj6i2ouwsFTYCGBwcDCSk5Ph5+dX2Ef4GgWKFTiXkoExi2KwKladHgGEVfXVjnG7u3bFYj/HN20gkCUnDa2TaSDbPpXMZbm1TyDQ4x0g/CGO+tmAm1lSwJ4C3AZG/lqT0Qf5m844SY0AqiBsyJAhNq3UokWL0K9fP7i6/j7CYrFYtDmI6ja0CvYKvldYZfgFKkyFr5VEQP1v98POU5i4LBapGTlwk2G/FzvWx6CO9eDp9vt3siR58ZoyEDi6Seb6DQYuH7NmFvUo0G0K4F2pDDJnFhSggNEE+PvbIPsAFvxihIWFaXsBbtmyBc2bN4ePj6y4K5Befln22yqD1LlzZ0RHR9+Qk1qJ3KhRIwwfPvyWwd8NH+QTCtyGwMlL6Ri5IBo/H76gfSqqlj+mPRyFxkEcRb4NxrK5NCNZ9vSTnQV2fWvNz6+WLPKQOwBhD5RN/syFAhSggEEFDDcCWNytX7UKOCEhwWaUt7oFfHPB/BfEzSJ8XpyARXZx/u6XY5i+8hCuZVtkpM9F5vk10Ob7ublyO5Hi7Gzy3qGVwFK505B62pp9i2dle5dxsuCDgbhNvJkpBQwkwN/fBhwBPHr0qIG+IqwKBcpG4HBSqhzjFo1dx+XMWEn3hFTSRv1Cqtw4wl02pTGXYgXSZOR1hZzeETPPelmlUKDPJ0Dd+4v9GN+kAAUo4EwChloFXBA2KysLKhisV69eoXsCFry2rB5v2LChrLJiPhTQBLItufhSTvH4aE08suSxr6cbRnRvhL/I3n4uarkvk34CarpzzHwJ/obJgeMXZQa0jLq2lnl/HUbK5s7GOmdcPxSWRAEKmFXAcAFgeno6Bg8ejNmzZ2t9EhcXh9DQUO21mjVrYsSIEWbtK7bbwQRiEpMxbN4+xJ6x7hfZoWEgJveLRI0ABhu6d2WK3OZdOhSIW2EtumoE0FdG/Wo2070qLJACFKCAEQQMN/Fo5MiR2Lt3L9RonJeXV76R2qj5P//5T/5zPqCAUQUyZH7f9JUH0XfmFi34C/B2xwd/vgvfPNWSwZ/enaZG/dQCj5n3WoM/FzlNpcObwPMbGPzp3RcsjwIUMJSA4UYA1fYsKtC77777bjjsPiIiAkeOyGHsTBQwsMDOY5cwbP4+JJxP02rZMyoI43pHILCCp4Fr7aRVuyTziX+UXQPUFi8q1WxhHfWr2tj6nP+lAAUoYGIBwwWA58+fL/QYuLS0tBsCQhP3GZtuQIG0zBxt1O+7bcehBp1UwDfpoSboGsHTI3TvrlwLsP1zYO1EIOeaLHWTW+6dxwD3vgC4cI9F3fuDBVKAAoYUMFwAqE7nWLZsmTbnT4mprV9U+uqrr9CqVSvtMf9DASMJbIo7r+3rl3hFgg1JjzSvhdE9w+Evt36ZdBZIOmA9xi1xp7Xgum1lhe8MQK30ZaIABShAgXwBwwWAkydPRvfu3REbG4ucnBx89NFH2uOtW7di48aN+RXnAwrYWyA5PVs7yWPerlNaVWpVLI8p/SPRNkyOEGPSVyAnC9giGzhvnA7kZgOespffgzIC2Gyg+lekvnVhaRSgAAUcQMBwAWCbNm20RSBTpkxBZGQkVq1ahWbNmuGXX37RnjuAKatoAoGVMWcxZnEMzqdmavHFwFZ18UbXhvCRbV6YdBZI3G09xu1cjLXgBt2Anu8D/jV1rgiLowAFKOA4Aob5bZWbm4t33nkHS5YsgdoDsFOnTtqIX/ny3DLDcb5Ozl9TFfCNXRKD5dFntcaGBvpguhzj1qJuJedvvNFamC233DfIeb1bPwau58q5vZWB7jIC2ORhjvoZra9YHwpQwHAChgkA3377bYwbNw5quxcV9M2YMQNqQcjXX39tODRWyHwC12Vlx8I9iZiwNBZX5Navq2zi/EJ72Z+yUxi83LmwQPdvxLEt1lG/S//bGaDJAAn+pgE+VXSvCgukAAUo4IgChjkLOCwsDK+//jr+9re/aY5r1qxBz549ce3aNTkxwXDbFWp15FmCjviVv/06q8UdoxZGY8Oh89qHw4P8MH1AFJrU9L/9zPiJ0glkpgJrxgE7vrLmUyEI6PUB0LB76fLlpylAAVMJ8Pe3gc4CPnHiBHr06JH/BVQjgWoF8OnTp1GrVq381/mAAnoJ5OZex5ztxzF1xUGkZVng4eaCVzqH4fl2oXB3NeY/SvSysUs58atlX79XgZRT1uLVAo8HJgDlA+xSHRZKAQpQwJEFDHMLWK34LXjyh0J1d3dHdras6GOigM4CRy+kYbhs6Pzr0Utayc3rVMQ0metXv6qvzjVhcUiXPlgp5/Xum2vFqFgX6C1bu4S2Jw4FKEABCtyhgGECQDXH6qmnnoKn5+8nJmRkZOCFF16Aj49PfvMWLFiQ/5gPKFDWAjmWXHz181F8sDoOmTm58PZwxTBZ3fukrPJ1kXl/TDoL7F8ELH8dSFO338X/vheBTqMAj9//TtC5RiyOAhSggFMIGCYAHDhQbufclJ544ombXuFTCthO4MCZFAybtw/RiclaIW3DqmByv0gEV/K2XaHMuXCBVFllrQK/Az9a3w9sJBs6fwIEtyz8er5KAQpQgAK3JWCYAPCbb765rYrzYgqUlUBmjgUz1x3GpxuOIEfm/fl5uWFMr3AMkBM98k6iKauymM8tBNQ5er/NAX56E8iQQNxF/opqMxRoJ8Gg2+93B26RC9+mAAUoQIFbCBgmALxFPfk2BWwisPvEZQyXUb/4pKta/l0jqmFi3yao6udlk/KYaTECl48DS2WRx5F11ouCmgJ9ZwLVmxTzIb5FAQpQgAJ3IsAA8E7U+BmHF0jPysF7q+Lw9ZajUINOVXw9ML5PE/SIrM5RP717VzaBx45Zsr3LeCA7TUb6JPjuIIs+Wr0EuPKvKL27g+VRgALmEODfruboZ7aygMDWwxcwYkE0TlxK117t36wmxvQMR0UfjwJX8aEuAhfigcUS6J3cZi2udmuZ6/exROT1dSmehVCAAhQwqwADQLP2vAnbnZKRjSnLD+Dfv57UWl/D3wtv949Ex4ZVTahh5yZbZHunrbKVywY5vcOSKat6ZXudB2QEsPkzMu+PeyzauXdYPAUoYAIBBoAm6GQ2Ue4uxp7DqEXROJciwYakJ+6rjeHdGqGClzt59BY4s9c66nd2n7Xk+l3kNI8PgYBgvWvC8ihAAQqYVoABoGm73hwNv3g1E+N/jMWSvae1BodU8cFUGfW7N7SyOQCM1MrsDGDTdOBnCfauW+QEj4pAt6lA1J9liz/Z44+JAhSgAAV0E2AAqBs1C9JTQG0sroI+FfxdSsuC2sP5OTnCbUiXBvByd9WzKixLCZzYDiyRuX4X4qwe4X2BHu8Cvrz9zi8IBShAAXsIMAC0hzrLtKnA2eQMjFoYjbUHk7RyGlWvgOkDohBVK8Cm5TLzQgQyZXuddROB7V/Im7Lc2reaNfAL71PIxXyJAhSgAAX0EmAAqJc0y7G5gBr1m7vjJCYvO4DUzBy4u5bD4E5heKF9PXi4cWGBzTvg5gLUfn4/vgJcOWF9p6mc7NN1kvXW783X8jkFKEABCugqwABQV24WZiuB4xfTMGJ+NH5JuKgV0TQ4QBv1a1Ctgq2KZL5FCVy7DKwaDez53nqFf22gt8z7q9+5qE/wdQpQgAIU0FmAAaDO4CyubAUscnTbN7KZ87urDiEjO1fm97ng9Qcb4un7Q+CqJv4x6StwYCmwTI5uu3pOyhX/e54HOr8FeMo2L0wUoAAFKGAYAQaAhukKVuR2BeLOpWKYHOP228kr2kdbycreqQ9Hok5ln9vNiteXVuCqzLdc/gYQu8iaU+Uw64bOdVqVNmd+ngIUoAAFbCDAANAGqMzStgJZObn4fOMRfLwuHtmW66jg6YY3ezbGoy2DeYybben/mLs6R2/ff4GVwwF167ecrLC+X+b9tZfn7jxP+Y9gfIUCFKCAMQQYABqjH1iLEgrsO3VFG/U7eDZV+0TnRlUxqV8TBPmXL2EOvKzMBJJPySKPV4HDq61ZVo+UUb9PgBpNy6wIZkQBClCAArYRYABoG1fmWsYCGdkWfLA6DrM2J0Cm/aGSnNs7tnc4+txVg6N+ZWx9y+xyc4FdXwOrxwFZEoi7yhnKasRPjfy58mSVW/rxAgpQgAIGEGAAaIBOYBWKF9guK3uHz9+HYxfTtQtV0KeCv8q+nsV/kO+WvcDFI7Kh82Dg+BZr3sH3Wkf9AhuUfVnMkQIUoAAFbCbAANBmtMy4tAKpGdmYtvIgvt9m3Ueuup8XJj3UBF3Cq5U2a37+dgUsOcC2mcD6yUCOHOnmLgttuowFWv4VcOHJKrfLyespQAEK2FuAAaC9e4DlFyqw/lASRi2Ixmk51UOlx+4JxsgejeHnxVuMhYLZ8sWzMdZj3E7vsZYS2kH29ZsBVKxjy1KZNwUoQAEK2FCAAaANcZn17QtclnN7Jy6NxYI9idqHa1fyxtT+kWhdv8rtZ8ZPlE4gJxPY/J71J1dGAD395SSPt4G75USPctxjsXS4/DQFKEAB+wowALSvP0v/n4A6xm159FmMXRKDC1ezoPZwfkY2cx76YAN4e/BrqvsX5dROYPFLwPkD1qIb9bKe4esXpHtVWCAFKEABCpS9AH+zlr0pc7xNgaSUDIxeFINVser0CCCsqq92jNvdtSveZk68vNQCWbLQZt0kme/3qWQly619AiXwewcIf4ijfqXGZQYUoAAFjCPAANA4fWG6mqhRvx92ncIkueWbkpEDNxn2e7FjfQzqWA+eblxYoPsX4ugm6wrfy8esRUc9CnSbAnhX0r0qLJACFKAABWwrwADQtr7MvQiBk5fS8ebCaGyOv6BdEVnTXxv1axzkV8Qn+LLNBDKSZU8/Oa9317fWIvxqAr0+BBo8aLMimTEFKEABCthXgAGgff1NV3qu7OI8+5djeOenQ0jPsshInwuGPtAAz7YJgZuri+k87N7gQyuBpUOA1NPWqrR4VrZ3GQd4MRC3e9+wAhSgAAVsKMAA0Ia4zPpGgcNJqbKhczR2Hb+svXFPSCVthW9ooO+NF/KZ7QXSZOR1hZzeETPPWlalUNnQ+WOgbhvbl80SKEABClDA7gIMAO3eBc5fgWxLLr7clICP1sQjSx77eLhihOzp9/g9teGilvsy6Scg8y4RM1+Cv2FA+kVZ2CGjrq1eAjq+KZs78zxl/TqCJVGAAhSwrwADQPv6O33pMYnJGDZvH2LPpGht7dAwEG/3i0TNAAYbund+itzmXToUiFthLbpqBND3E6BmM92rwgIpQAEKUMC+AgwA7evvtKVnZFswY208vpCRP4vM+wvwdtfO732oaU3ZQ5ijfrp2vBr12z0bWDUGyJRA3EVOU2n3BtBG5v65eehaFRZGAQpQgALGEGAAaIx+cKpa7Dx2CcPm70PC+TStXT0jgzCuTwQCK3g6VTsdojGXEmRrl5eBY5ut1a3ZXEb95Ezfqo0dovqsJAUoQAEK2EaAAaBtXE2Za1pmjra6V63yVYNOKuCb2LcJujWpbkoPuzY61wJs/xxYOxHIuSYjfXLLvbOMAN77gowAco9Fu/YNC6cABShgAAEGgAboBGeowqa48xi5IBqJVyTYkPRI81oY3TMc/nLrl0lngaQD1mPcEndaC67bVlb4zgDUSl8mClCAAhSggAgwAOTXoFQCyenZmLgsFvPkRA+ValUsjyn9I9E2TI4QY9JXICcL2CIbOG+cDuRmA56yl9+DMgLYbCCPcdO3J1gaBShAAcMLMAA0fBcZt4IrY85gzOL9OJ+aKQs7gIGt6uKNrg3h48mvle69lrjbOuqXtN9adINuQM/3AX851YOJAhSgAAUocJMAf1PfBMKntxZQAd/YJTFYHn1Wuzg00AfTH45Ci7qVbv1hXlG2Atlyy339ZOAX2c7leq6c21sZ6C4jgE0e5qhf2UozNwpQgAJOJcAA0Km607aNuS4rOxbsTsSEpbFIvpYNV9nE+YX2oRjcKQxe7lxYYFv9QnI/tkVW+A4GLh2xvtlkgAR//9/encDpWO//H3+bwWAwWWJUhCg7ZUs6WjhkK5061f9XPVTn9+tXIW1O0oI20q9yirT8W87vkU6d6o82OkKUY0tlyRoVLRiRYTRjzMz/872uTIYJM3Pf1729rsdjci/X9V2e33u6P/O9vssjUmrtYk7mJQQQQAABBH4TIAD8zYJHRxBwkztG2CSPuTbZwx0t6lXXuEvbqNWJaUe4irfCIpBta/l9OEr69AU/+Wr1pH5PSKf1Dkt2JIoAAgggEH8CBIDx16YhrVG+LeI8edG3Gjt9jbL25ali+SQN7d5U13drrArJto0YR7AC62dK79wiZX7n5+smeLiJHpUIxINtCHJDAAEEYluAADC22y+spd+YsUfD31qhxbawszs6nFxDY22sX5M6VcOaL4kXI7DX2mDGXdLy1/w3azSU+tvSLo3PKeZkXkIAAQQQQODIAgndhTNmzBh17NhR1apVU506dTRgwACtXbv2yGIJ8O7+vHw9M3eDev/tYy/4q1IxWaP6t9A//7sLwV/Q7e9W1P5yijSx06/Bn023PnOQdOO/Cf6CbgvyQwABBOJIIKF7AOfOnatBgwZ5QeD+/fs1YsQI9ezZU6tWrVJqamocNfOxV2XVD5m607ZxW/H9Lu+iPzStrYcvbq36NasceyKcGRqB3TbL+r3bpTXv+ukd38wWdLbZvvU7hiZ9UkEAAQQQSFiBcjaz07oYOJxARkaG1xPoAsNu3bodFSUzM1NpaWnatWuXqlevftTzo/mEnP15mjD7K036aIP227i/6pXK695+LXSp7ehRzi3yxxGcgPuV/GKy9MEIKdsC8ST7O+3s26Rud9jS7eynHFxDkBMCCMSrQDx9f5e2jRK6B/BQNBfIuaNmzcRaz+6zTTt155vLtX7bHq/+vVrW9fbwrVO9kvec/wQosPNbm+QxVNo4x8+0XjvpoolSeqsAC0FWCCCAAALxLkAA+GsL5+fn65ZbblHXrl3VqlXxX7Y5OTlyPwcO9xdELB979+3XY/9apxfnfy3X6VS7akXdf1Er9Wlty4pwBCtgnz8ted6Wdxkt5WZZT58F3+dZD6Ab75fMr2mwjUFuCCCAQPwL8M3yaxu7sYArV67UJ5988rut7iaNjB5tX9BxcPz7q+0abuv6bdqx16vNn04/0bvlWyO1YhzULsaqkLHOFnQeLG1e5Be8wVk21u8pi8ibxFhFKC4CCCCAQKwIMAbQWmrw4MGaNm2a5s2bp0aNGv1u2xXXA1i/fv2YGgPodvAY8/5qvbZks1fPE9Iq6aE/tdZ5p9X53XrzRpgE8nKl+X+T5truHXn7pIq2vM4f7Q+M9tfZuL+EnqAfJnCSRQABBHwBxgDajaZE/jC4+S9DhgzRlClT9NFHHx0x+HNOKSkp3k+sms1ctVX3TF2hrZn+beyrzzxZd/ZupqopCf0xiExz/rhMmma3d7es8PNv0sN28xgvHVc/MuUhVwQQQACBhBJI6G9+d9v31Vdf9Xr/3FqAW7bYsht2uJm9lStXjpsPwk97cjTqnVV6Z9kPXp0a1U7VWOv169y4VtzUMWYqkpvt9/i5nr+CPKlyDemCsVKby2XTrWOmGhQUAQQQQCC2BRL6FvDvLW/y0ksv6Zprrjlqy0Z7F7Lr4Xzbgr5Rb3+pnXtzlWTxxX/ZFm639jhVlSokH7V+nBBigU02xs+N9dtuY/7c0WKA1OdRqSq3330Q/osAAggEIxDt399BKCR0D2A8L4H4465fdM+UlZq1Zpv3OWqWXk3jLm2jNicdF8TnijwOFsix5XVm3S8tfs5etenWVetKfR+Tmvc/+CweI4AAAgggEJhAQgeAgSkHmJELav+xeLM30WN3zn5VTE7SkPOb6L/POUUVyzOxIMCm8LPaMNt6/Wxdv12b/OftrpJ6Pejf+g28MGSIAAIIIICAL0AAGEefhG9/ytLwt1ZowcafvFq1q3+cHrVev6Z1q8VRLWOkKr/stJ087rEdPV7xC5zWQOpvkzyadI+RClBMBBBAAIF4FiAAjIPWzbOt216yxZz/519rlZ2bb+P7knRHz9N0bddGSnYD/ziCFVj9jr+H756tlq/5d7pe6n6fTSO3ZV44EEAAAQQQiAIBAsAoaISyFGHd1t0aZtu4Ldv8s5fMWafUshm+bdSgVpWyJMu1pRHYY+Mt3x8mrZrqX12rqW3jNkFqcGZpUuMaBBBAAAEEwiZAABg22vAmvG9/viZ9tEET5qxXbl6Bqtlafnf3ba7LO9a31UTo9Quv/iGp27hLLX9dmjFccrd+y9kM66427u+cO6UK7Kd8iBZPEUAAAQSiQIAAMAoaoaRFcL19d761XGu27PYu7dG8jh4c0FrptqsHR8ACP2+W3r1V+mqmn3F6a+v1myjVaxtwQcgOAQQQQACBYxcgADx2q4if+cu+PI3/cJ2e/3ijbNifatq+vaMubKn+berR6xd06+TnS0tflGaOlPbZMi/Jtoey6/FzPX/JFYIuDfkhgAACCCBQIgECwBJxRe7khTazd7j1+n3z016vEBe1O0H39WuhWlVTIleoRM35pw22tMsQ6dv5vkD9ztKFNtbv+FMTVYR6I4AAAgjEmAABYJQ32O7sXI2dvkaTF/nryKVXr2S3e1upRwtbTJgjWIG8/dJCu70752Fpv23pViFV6mE9gB3/U0piZ5VgG4PcEEAAAQTKIkAAWBa9MF87x3bxuHvKCv2wy4INO/5Ppwa6q08zVa/ELcYw0x+e/JaV/jZuP3zuv9f4XFvX70mpxsmHn8srCCCAAAIIRLkAAWAUNtDOrH26/91VmvL5917pGtSsorGXtNZZp9SOwtLGeZH250gfP+b/5FsPYKU028nDegDbXWmzfZltHeetT/UQQACBuBUgAIyipnXbuL234keNnPalfrIg0K3hfJ0t5ny7LepcuSK3GANvqu8+laYNljJW+1k36+fv4VstPfCikCECCCCAAAKhFCAADKVmGdLalpmte6au1L9Wud0jpFPrVtUjl7TR6Q1qlCFVLi2VwD6baDP7QRvv97RdbtOtU4+X+jwqtRhAr1+pQLkIAQQQQCDaBAgAI9wirtfvjU+/0wPvrdLu7P0qb91+g85ropvOO0Up5en1C7x5vp7nz/Dd+Y2fdZsrpAvGSFVqBl4UMkQAAQQQQCBcAgSA4ZI9hnQ379irETbJ4+P1272z25yUpnGXtlGz9OrHcDWnhFQge5et6Wf79S592U+2+olSv/HWFdszpNmQGAIIIIAAAtEgQAAYgVbIs1Wc/3fBN3r0g7Xaa4s7p5RPsnF+p3rj/conJ0WgRAme5doZ/m4eu3/wITr8xZZ3GWUTPgjEE/yTQfURQACBuBUgAAy4ab/attu2cVuhpd/u9HLu1KimN9avUW1bU44jWIEs63mdbrt3rHzTz7dmY1vQ+Smp4dnBloPcEEAAAQQQCFiAADAg8Ny8fD03b6P+9uF67bPHVVPKa3jvZvoPW9svyU335QhOwMZdauVbFvz9Vdr7k03ssF7XLoOl80bY4s6VgysHOSGAAAIIIBAhAQLAAOBXfr9Lf31zuVb9mOnldu5px+vhi1vrhOMINgLgL5pFpt3mffc2ad10//U6LaWLrNfvxPZFz+MZAggggAACcSxAABjGxs3OzdOTs9brWev5c+P+jqtSQSP7t9CAdifaGsL0+oWR/vCkXa/fZ3+X/nWvlGOBeJLtptJtmHT2rVL5ioefzysIIIAAAgjEsQABYJga99Nvduivby3XxowsL4e+bepp9IUtVbtqSphyJNnfFdjxtfTOzZJb4sUdrrfvItvTt05z/zn/RQABBBBAIMEECABD3OBZOfu92b1/X/CNXKfT8dVS9OCAVurVkt0jQkx99OTy86RFz0izHpD2/2I9fXbL/fx7pDNvtB5A1lg8OiBnIIAAAgjEqwABYAhbdt66DN31/1bo+58t2LDjsg4n6e4+LZRmt345AhbYtsYWdLaJHd8t8TNu+Aeb4fuk5Gb6ciCAAAIIIJDgAgSAIfgA7Nqbq/s/WKY3l37npXZSjcoa86fW+kNT20KMI1iB/fuk+baA8zzbui3PHqfYWn49rQfwjIFs4xZsS5AbAggggEAUCxAAhqBxLpr4iXbklreJHdLALg01rNdpSrVlXjgCFvj+M38bt60r/YxPvUDq+7iUZrt6cCCAAAIIIIBAoQBRSiFF6R9s37NPTX/dxq39yTVLnxBXlk4g1265f2T79f7blnMpyJcqWxv0Hie1vpRev9KJchUCCCCAQJwLEACGoIH/6w+NNKz/6apUgYkFIeAsWRLfzPd7/XZs8K9rdYkf/KXWLlk6nI0AAggggEACCRAAhqCxh/Y4leAvBI4lSiJnt/ThKGnJ//Uvq1bPv93brE+JkuFkBBBAAAEEElGAADARWz3W67x+pq3rd4uU+Z1fEzfB44/3263f42K9ZpQfAQQQQACBQAQIAANhJpOQCOzdIc24S1r+mp/ccSfb0i427q/xOSFJnkQQQAABBBBIFAECwERp6Viv55dTpffvkLIyrCY23dot5uwWda6YGus1o/wIIIAAAggELkAAGDg5GZZIYPcWP/Bb/Y5/2fHNrNdvglS/Y4mS4WQEEEAAAQQQ+E2AAPA3Cx5Fk4DbR++LydIHI6TsXbZ1m31Uz75N6ma9gOXZTzmamoqyIIAAAgjEngABYOy1WfyXeOe3NsljqLRxjl/Xeu2ki6zXL711/NedGiKAAAIIIBCAAAFgAMhkcYwC+baI85LnbXmX0VJulvX0VZLOtUkfXWxP32Q+qseoyGkIIIAAAggcVYBv1aMScUIgAtvXS9Ms0Nu80M+uwVn+DN/aTQLJnkwQQAABBBBIJAECwERq7Wisa16ubeH2pG3l9oiUl2OzeqtKPUZJHf5i4/6SorHElAkBBBBAAIGYFyAAjPkmjOEK/LjM7/XbstyvRJMeUr/x0nH1Y7hSFB0BBBBAAIHoFyAAjP42ir8S5mZL88ZJn1iwV5BnO3jUkC4YK7W53Jb4szX+OBBAAAEEEEAgrAIEgGHlJfHDBDYtkt62sX7b1/lvtbhI6vM/UtU6h53KCwgggAACCCAQHgECwPC4kuqhAjl7pNkPSIuetXdsjb+qdf3Ar8WFh57JcwQQQAABBBAIswABYJiBSd4ENsz21/X7eZPP0e4qqdeD/q1fgBBAAAEEEEAgcAECwMDJEyjDX3baTh62X+8Xr/iVTmsg9bdxf026JxACVUUAAQQQQCD6BAgAo69N4qNEbu/e926X9my1+tjEjk7XS93vk1JsmRcOBBBAAAEEEIioAAFgRPnjMPM926T3h0mrpvqVq9XU38atwZlxWFmqhAACCCCAQGwKEADGZrtFX6kLbGLH8telGcMld+u3XLLU1fbzPedOqYJt6caBAAIIIIAAAlEjQAAYNU0RwwX5ebP07q3SVzP9SqS3tm3cJkgntIvhSlF0BBBAAAEE4leAADB+2zb8NcvPl5a+KM0cKe2zZV6SK/o9fq7nL7lC+PMnBwQQQAABBBAolQABYKnYuEg/bbAFnYdI3873Mep39nv9jj8VHAQQQAABBBCIcgECwChvoKgrXt5+aeFEac7D0n7b0q1CqtTDegA7/qeUZOP+OBBAAAEEEEAg6gUIAKO+iaKogFtW+tu4/fC5X6jG59q6fk9KNU6OokJSFAQQQAABBBA4mgAB4NGEeN96+nKkjx/zf/KtB7BSmu3kYT2A7a602b62xh8HAggggAACCMSUAAFgTDVXBAr73afStEFSxho/82b9pL4WDFZLj0BhyBIBBBBAAAEEQiFAABgKxXhMY1+WNPshG+/3tNXO1vhLPV7q86jUYgC9fvHY3tQJAQQQQCChBJISqrbFVHbixIlq2LChKlWqpM6dO2vx4sXFnJVgL22cK006y5/s4YK/NldIg8yl5cUEfwn2UaC6CCCAAALxKZDQAeDrr7+u2267TSNHjtRnn32mtm3bqlevXtq2zbYzS8Qje5dN8rhZ+t8LpZ3fSNVPlP7jDelPz0pVaiaiCHVGAAEEEEAgLgXKFdgRlzU7hkq5Hr+OHTtqwgTbtcKOfFvYuH79+hoyZIiGDx9+1BQyMzOVlpamXbt2qXr16kc9P6pPWDvd381j949+MTv8xZZ3GWUTPmK8XlGNTuEQQAABBCIhEFff36UETNgxgPv27dPSpUt11113FdIlJSWpR48eWrBgQeFrcf8ga7s03fbrXfmmX9Wajf0FnRt2jfuqU0EEEEAAAQQSVSBhA8Dt27crLy9PdevWLdL27vmaNb/OeC3yjpSTk+P9HHjZ/QURs4fr+F35lgV/f5X2/mRj+2w0wFlDpHMtIK5QOWarRcERQAABBBBA4OgCCRsAHp3m8DPGjBmj0aNHH/5GrL2S+YN/u3fdDL/kdVpKFz0lndg+1mpCeRFAAAEEEECgFAIJOwmkdu3aSk5O1tatW4uwuefp6elFXjvwxN0uduP9Dvxs3rz5wFux8a/r9Vv6sjTR9u11wV9SBevxGyFd/xHBX2y0IKVEAAEEEEAgJAIJGwBWrFhR7du316xZswoh3SQQ97xLly6Frx38ICUlxZvs4SZ8HPg5+P2ofrxjo/T3/tI7Q+1ett26PrGDdMPHFgDa+L/yFaO66BQOAQQQQAABBEIrkNC3gN0SMAMHDlSHDh3UqVMnjR8/XllZWbr22mtDqxzJ1PLzbD2/Sbao84O2pdsvFuzZ+L7u90qdb7AewORIloy8EUAAAQQQQCBCAgkdAF5++eXKyMjQfffdpy1btqhdu3aaMWPGYRNDItQ2Zc9222rbxm2w9P2nfloN/2AzfJ+U3ExfDgQQQAABBBBIWIGEXgewrK0etesI7d8nzR8vzR1nixvmSim2ll/PB6QzBrKTR1kbnesRQAABBGJeIGq/vwOUTegewACdg8vq+8/8Xr9tX/p5nnqB1PdxKc129eBAAAEEEEAAAQRMgAAwXj4GuTa+b87D0gLb1aQg37ZuqyX1th7AVpfQ6xcvbUw9EEAAAQQQCJEAAWCIICOazDfzbQ9fW8R5xwa/GK0uteDvESm1dkSLReYIIIAAAgggEJ0CBIDR2S7HVqpsW87lw1HSpy/451erJ/V7Qjqt97Fdz1kIIIAAAgggkJACBICx2uzrZ9qafrdImd/5NXATPNxEj0ppsVojyo0AAggggAACAQkQAAYEHbJs9u6QZth+vctf85Os0VDqb0u7ND4nZFmQEAIIIIAAAgjEtwABYKy0r9vGbdVU6f1hUlaGlbqcdOZN0vl3SxVTY6UWlBMBBBBAAAEEokCAADAKGuGoRdi9RXrvdmnNu/6pxzezBZ1ttm/9jke9lBMQQAABBBBAAIFDBQgADxWJpueu1++LydIHI6TsXbZ1mzXX2bdJ3e6wBXxSoqmklAUBBBBAAAEEYkiAADBaG2vntzbJY6i0cY5fwnrtpIsmSumtorXElAsBBBBAAAEEYkSAADDaGirfFnFe8rwt7zJays2ynr5K0nnWA3jmICmZ5oq25qI8CCCAAAIIxKIAEUU0tVrGOn9B580L/VI1OMvG+j0l1W4STaWkLAgggAACCCAQ4wIEgNHQgHm50r9tKZePbPeOvByb1VtV+qP1ALa/zsb9JUVDCSkDAggggAACCMSRAAFgpBvzx2XStMHSluV+SZr0sN08xkvH1Y90ycgfAQQQQAABBOJUgAAwUg2bmy3NGyd9YsFeQZ5UuYZ0wVipzeW2xJ+t8ceBAAIIIIAAAgiESYAAMEywR0x20yIb62e9ftttzJ87WgyQ+jwqVa3jP+e/CCCAAAIIIIBAGAUIAMOIe1jSOXuk2bZf76Jn7S1b469qXanvY1Lz/oedygsIIIAAAggggEC4BAgAwyV7aLobZvvr+v28yX+n3VVSrwf9W7+HnstzBBBAAAEEEEAgjAIEgGHE9ZL+Zaft5HGP7ejxip9TWgOpv437a9I93DmTPgIIIIAAAgggUKwAAWCxLCF6cbXt3fuebd22Z6slaBM7Ol0vdb9PSrFlXjgQQAABBBBAAIEICRAAhgN+zzbp/WHSqql+6rWa2jZuE6QGZ4YjN9JEAAEEEEAAAQRKJEAAWCKuo5xcYBM7lr8uzRguuVu/5ZKlrraf7zl3ShVsSzcOBBBAAAEEEEAgCgQIAEPVCLu+s0ket0hfzfRTTG9tvX4TpXptQ5UD6SCAAAIIIIAAAiERIAAsA2OB6/GzI3OeLeuy+Akp15Z5SaognX2rdOaNUrI9zswsQw5cigACCCCAAAKhFsj89bv5wPd4qNOPhfTKWeX9KCYWShtlZdy4caNOOeWUKCsVxUEAAQQQQACBYxHYsGGDGjdufCynxt059ACWoUlr1qzpXb1p0yalpaWVISUuLauA+2uufv362rx5s6pXr17W5Li+DAK0RRnwwnAp7REG1FImSVuUEi4Ml+3atUsNGjTQge/xMGQR9UkSAJahiZKSkryrXfBH0FEGyBBe6tqBtgghaBmSoi3KgBeGS2mPMKCWMknaopRwYbjswPd4GJKO+iT9CCbqi0kBEUAAAQQQQAABBEIlQAAYKknSQQABBBBAAAEEYkQgeZQdMVLWqCxmcnKyzj33XJUvz930SDcQbRHpFvgtf9riN4toeER7REMr+GWgLWiLaBFgFnC0tATlQAABBBBAAAEEAhLgFnBA0GSDAAIIIIAAAghEiwABYLS0BOVAAAEEEEAAAQQCEiAADAiabBBAAAEEEEAAgWgRIACMlpagHAgggAACCCCAQEACBIClhJ44caIaNmyoSpUqqXPnzlq8eHEpU+KysgiMGTNGHTt2VLVq1VSnTh0NGDBAa9euLUuSXBsigbFjx6pcuXK65ZZbQpQiyZRE4Pvvv9dVV12lWrVqqXLlymrdurU+/fTTkiTBuSEQyMvL07333qtGjRp57eC2D33ggQfELqwhwD2GJObNm6f+/fvrhBNO8P5/NHXq1CJXuXa47777VK9ePa99evToofXr1xc5J16fEACWomVff/113XbbbRo5cqQ+++wztW3bVr169dK2bdtKkRqXlEVg7ty5GjRokBYuXKiZM2cqNzdXPXv2VFZWVlmS5doyCixZskTPPvus2rRpU8aUuLw0Ajt37lTXrl1VoUIFTZ8+XatWrdJjjz2mGjVqlCY5rimDwCOPPKJJkyZpwoQJWr16tdzzcePG6amnnipDqlx6rALuu8B9R7tOm+IO1xZPPvmknnnmGS1atEipqane93l2dnZxp8fVaywDU4rmdD1+rtfJ/UK7Iz8/39uHdsiQIRo+fHgpUuSSUAlkZGR4PYEuMOzWrVuokiWdEgjs2bNHZ5xxhp5++mk9+OCDateuncaPH1+CFDi1rALu/0Pz58/Xxx9/XNakuL6MAv369VPdunX1wgsvFKZ0ySWXeL1Nr7zySuFrPAi/gLsjMWXKFO9OkcvN9f65nsHbb79dd9xxh1cAt0ewa6+XX35ZV1xxRfgLFcEc6AEsIf6+ffu0dOlSuW7iA4fbS9A9X7BgwYGX+DdCAu6X1x2JvMF3hOgLs3U9sn379i3yO1L4Jg8CEXj77bfVoUMH/fnPf/b+IDr99NP1/PPPB5I3mRQVOOusszRr1iytW7fOe2PZsmX65JNP1Lt376In8ixwga+//lpbtmwp8v+qtLQ0b1hXInyfs31FCT9y27dvlxvT4f5COPhwz9esWXPwSzwOWMD1xLrxZu7WV6tWrQLOneycwGuvveYNi3C3gDkiJ7Bx40bvtqMbqjJixAi59rj55ptVsWJFDRw4MHIFS8CcXW9sZmammjVrJrcLiPv+eOihh3TllVcmoEZ0VdkFf+4o7vv8wHvRVeLQloYAMLSepBZBAdfztHLlSu+v6wgWI2Gz3rx5s4YOHeqNxXSTozgiJ+D+GHI9gA8//LBXCNcD6H433DgnAsBg2+Wf//ynJk+erFdffVUtW7bUF1984f2h6m490hbBtgW5FRXgFnBRj6M+q127tvdX3NatW4uc656np6cXeY0nwQkMHjxY7777rubMmaOTTjopuIzJqVDADY1wE6Hc+D+3N7b7cWMx3QBr99j1fHAEI+BmNLZo0aJIZs2bN9emTZuKvMaT8AsMGzbMGxvuxpO5mdhXX321br31VrkVDDgiK3DgOztRv88JAEv4+XO3UNq3b++N6Thwqftr243x6NKly4GX+DcgATeI1wV/bmDv7NmzvaUWAsqabA4R6N69u1asWOH1cLheDvfjeqHcrS732N3+4ghGwA2DOHQ5JDcG7eSTTw6mAORSKLB37165ceIHH+53wX1vcERWwC3N44JA9/194HC3691s4ET4PucW8IFWL8G/blyN67p3X26dOnXyZji6qebXXnttCVLh1FAIuNu+7tbKtGnTvLUAD4zbcAN53dpnHMEJuLUYDx176ZZUcOvQHfp6cKVKzJxcD5ObfOBuAV922WXeOqXPPfec3A9HsAJuDTo35q9BgwbeLeDPP/9cjz/+uK677rpgC5KgublVCb766qvC2ruJH+4PUjdR0LWJGzfuVito2rSp14Hg1mx0t+fdmrJxf1gPCkcpBGwNpwL78BRYj2CBBYEFtg5dKVLhkrIK2C9oQXE/L730UlmT5voQCJxzzjkFNi4wBCmRREkF3nnnnQILvAtSUlIKbAJCgQV/JU2C80MgYD1K3u+A+76wsbEFjRs3Lrj77rsLcnJyQpA6SRxNwIYFFfsdYZ043qXWE1tgQV+BTQTxflfsTkaB9Z4fLdm4eJ91AOM+xKeCCCCAAAIIIIBAUYGiAxOKvsczBBBAAAEEEEAAgTgUIACMw0alSggggAACCCCAwJEECACPpMN7CCCAAAIIIIBAHAoQAMZho1IlBBBAAAEEEEDgSAIEgEfS4T0EEEAAAQQQQCAOBQgA47BRqRICCCCAAAIIIHAkAQLAI+nwHgIIIIAAAgggEIcCBIBx2KhUCQEEIidQrlw5TZ06NXIFIGcEEEDgGAQIAI8BiVMQQCA2BK655hq5AOzQnwsuuCA2KkApEUAAgYAE2As4IGiyQQCBYARcsGdbARbJzLZDK/KcJwgggECiC9ADmOifAOqPQJwJuGAvPT29yE+NGjW8WrqewUmTJql3796qXLmybF9Wvfnmm0UEVqxYofPPP997v1atWrr++uvlNpQ/+HjxxRfVsmVLubzq1aunwYMHH/y2tm/frosvvlhVqlTxNpl/++23i7zPEwQQQCDSAgSAkW4B8kcAgUAFbON3XXLJJVq2bJmuvPJKXXHFFVq9erVXhqysLPXq1UsuYFyyZIneeOMNffjhh0UCPBdADho0yAsMXbDogrsmTZoUqcPo0aN12WWXafny5erTp4+Xz44dO4qcwxMEEEAgogIFHAgggECcCAwcOLAgOTm5IDU1tcjPQw895NXQ/mdbcMMNNxSpbefOnQtuvPFG77XnnnuuwIK/AuvxKzznvffeK0hKSirYsmWL99oJJ5xQcPfddxe+f+gDl8c999xT+LJLy702ffr0wtd4gAACCERagDGAEQ2/yRwBBEItcN5553m3eQ9Ot2bNmoVPu3TpUvjYPXDPv/jiC+811xPYtm1bWQBZeE7Xrl2Vn5+vtWvXepNLfvjhB3Xv3r3w/eIetGnTpvBll1b16tW1bdu2wtd4gAACCERagAAw0i1A/gggEFIBF3Adeks2VBm4cYPHclSoUKHIaW7soQsiORBAAIFoEWAMYLS0BOVAAIFABBYuXFgkH/e8efPm3mvuXzc20I0FPHDMnz9fdgtYp512mqpVq6aGDRtq1qxZB97mXwQQQCAmBegBjMlmo9AIIPB7Ajk5ObLxekXeLl++vGrXru295iZ2dOjQQWeffbYmT56sxYsX64UXXvDec5NCRo4cKRtLqFGjRikjI0NDhgzR1Vdfrbp163rnuNdtHKHq1KnjzSbevXu3XJDozuNAAAEEYkWAADBWWopyIoDAMQnMmDHDW5rl4JNd792aNWu8l9wM3ddee0033XSTd94//vEPtWjRwnvPLdvywQcfaOjQoerYsaO3jIubMfz4448XJueCw+zsbD3xxBO64447vMDy0ksvLXyfBwgggEAsCJRzs1BioaCUEQEEECirgBuLN2XKFA0YMKCsSXE9AgggENMCjAGM6eaj8AgggAACCCCAQMkFCABLbsYVCCCAAAIIIIBATAswBjCmm4/CI4BASQQY8VISLc5FAIF4FqAHMJ5bl7ohgAACCCCAAALFCBAAFoPCSwgggAACCCCAQDwLEADGc+tSNwQQQAABBBBAoBgBAsBiUHgJAQQQQAABBBCIZwECwHhuXeqGAAIIIIAAAggUI0AAWAwKLyGAAAIIIIAAAvEsQAAYz61L3RBAAAEEEEAAgWIECACLQeElBBBAAAEEEEAgngUIAOO5dakbAggggAACCCBQjMD/BwZY2VLmfFNbAAAAAElFTkSuQmCC\" width=\"640\">"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import numpy as np\n",
    "from matplotlib import pyplot as plt\n",
    "\n",
    "class LivePerformanceplot(object):\n",
    "\n",
    "    def __init__(self, labels, xlim='auto', ylim='auto', xlabel='Epoch', ylabel='Performance'):\n",
    "\n",
    "        \n",
    "        self.xlim = xlim\n",
    "        self.ylim = ylim\n",
    "        fig, ax = plt.subplots(1, 1)\n",
    "        self.ax = ax\n",
    "        self.fig = fig\n",
    "        \n",
    "        self.labels = labels\n",
    "        for label in self.labels:\n",
    "            self.ax.plot([0], label=label)\n",
    "\n",
    "        if not xlim == 'auto':\n",
    "            self.ax.set_xlim(self.xlim)\n",
    "\n",
    "        if not ylim == 'auto':\n",
    "            self.ax.set_ylim(self.ylim)\n",
    "\n",
    "        self.ax.set_xlabel(xlabel)\n",
    "        self.ax.set_ylabel(ylabel)\n",
    "        self.ax.legend()\n",
    "        \n",
    "        self.max = -np.inf\n",
    "        self.min = np.inf\n",
    "        self.num_iter = 0\n",
    "\n",
    "    def update(self, data_dict):             \n",
    "        self.num_iter += 1\n",
    "        \n",
    "        if self.xlim == 'auto':\n",
    "            self.ax.set_xlim(0, self.num_iter)\n",
    "        \n",
    "        changed = False\n",
    "        for i, label in enumerate(self.labels):\n",
    "            \n",
    "            line = self.ax.lines[i]\n",
    "            line.set_xdata(data_dict[label][0])\n",
    "            line.set_ydata(data_dict[label][1])\n",
    "            \n",
    "            recent_y_value = data_dict[label][1][-1]\n",
    "\n",
    "            if self.ylim == 'auto':\n",
    "                changed = False\n",
    "                if recent_y_value > self.max:\n",
    "                    self.max = recent_y_value\n",
    "                    changed = True\n",
    "                if recent_y_value < self.min:\n",
    "                    self.min = recent_y_value\n",
    "                    changed = True\n",
    "                    \n",
    "            if changed:  \n",
    "                self.ax.set_ylim(self.min - self.min*0.05, self.max + self.max*0.05)\n",
    "\n",
    "            self.fig.canvas.draw()\n",
    "\n",
    "\n",
    "            \n",
    "########## Testing\n",
    "            \n",
    "import time\n",
    "\n",
    "%matplotlib notebook\n",
    "plot = LivePerformanceplot(labels=['train acc.', 'valid acc.'])\n",
    "\n",
    "x1 = []\n",
    "y1 = []\n",
    "\n",
    "x2 = []\n",
    "y2 = []\n",
    "\n",
    "for i in range(10):\n",
    "    time.sleep(2)\n",
    "    x1.append(i)\n",
    "    y1.append(i+1)\n",
    "    \n",
    "    x2.append(i)\n",
    "    y2.append(i-1)\n",
    "    \n",
    "    data_dict = {'train acc.': [x1, y1], 'valid acc.': [x2, y2]}\n",
    "    plot.update(data_dict=data_dict)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Imports"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import torch\n",
    "import torch.nn.functional as F\n",
    "from torchvision import datasets\n",
    "from torchvision import transforms\n",
    "from torch.utils.data import DataLoader"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Settings and Dataset"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Image batch dimensions: torch.Size([128, 1, 28, 28])\n",
      "Image label dimensions: torch.Size([128])\n"
     ]
    }
   ],
   "source": [
    "##########################\n",
    "### SETTINGS\n",
    "##########################\n",
    "\n",
    "# Device\n",
    "device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\n",
    "\n",
    "# Hyperparameters\n",
    "random_seed = 1\n",
    "learning_rate = 0.05\n",
    "num_epochs = 10\n",
    "batch_size = 128\n",
    "\n",
    "# Architecture\n",
    "num_classes = 10\n",
    "\n",
    "\n",
    "##########################\n",
    "### MNIST DATASET\n",
    "##########################\n",
    "\n",
    "# Note transforms.ToTensor() scales input images\n",
    "# to 0-1 range\n",
    "train_dataset = datasets.MNIST(root='data', \n",
    "                               train=True, \n",
    "                               transform=transforms.ToTensor(),\n",
    "                               download=True)\n",
    "\n",
    "test_dataset = datasets.MNIST(root='data', \n",
    "                              train=False, \n",
    "                              transform=transforms.ToTensor())\n",
    "\n",
    "\n",
    "train_loader = DataLoader(dataset=train_dataset, \n",
    "                          batch_size=batch_size, \n",
    "                          shuffle=True)\n",
    "\n",
    "test_loader = DataLoader(dataset=test_dataset, \n",
    "                         batch_size=batch_size, \n",
    "                         shuffle=False)\n",
    "\n",
    "# Checking the dataset\n",
    "for images, labels in train_loader:  \n",
    "    print('Image batch dimensions:', images.shape)\n",
    "    print('Image label dimensions:', labels.shape)\n",
    "    break"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "##########################\n",
    "### MODEL\n",
    "##########################\n",
    "\n",
    "\n",
    "class ConvNet(torch.nn.Module):\n",
    "\n",
    "    def __init__(self, num_classes):\n",
    "        super(ConvNet, self).__init__()\n",
    "        \n",
    "        # calculate same padding:\n",
    "        # (w - k + 2*p)/s + 1 = o\n",
    "        # => p = (s(o-1) - w + k)/2\n",
    "        \n",
    "        # 28x28x1 => 28x28x4\n",
    "        self.conv_1 = torch.nn.Conv2d(in_channels=1,\n",
    "                                      out_channels=4,\n",
    "                                      kernel_size=(3, 3),\n",
    "                                      stride=(1, 1),\n",
    "                                      padding=1) # (1(28-1) - 28 + 3) / 2 = 1\n",
    "        # 28x28x4 => 14x14x4\n",
    "        self.pool_1 = torch.nn.MaxPool2d(kernel_size=(2, 2),\n",
    "                                         stride=(2, 2),\n",
    "                                         padding=0) # (2(14-1) - 28 + 2) = 0                                       \n",
    "        # 14x14x4 => 14x14x8\n",
    "        self.conv_2 = torch.nn.Conv2d(in_channels=4,\n",
    "                                      out_channels=8,\n",
    "                                      kernel_size=(3, 3),\n",
    "                                      stride=(1, 1),\n",
    "                                      padding=1) # (1(14-1) - 14 + 3) / 2 = 1                 \n",
    "        # 14x14x8 => 7x7x8                             \n",
    "        self.pool_2 = torch.nn.MaxPool2d(kernel_size=(2, 2),\n",
    "                                         stride=(2, 2),\n",
    "                                         padding=0) # (2(7-1) - 14 + 2) = 0\n",
    "        \n",
    "        self.linear_1 = torch.nn.Linear(7*7*8, num_classes)\n",
    "\n",
    "        \n",
    "    def forward(self, x):\n",
    "        out = self.conv_1(x)\n",
    "        out = F.relu(out)\n",
    "        out = self.pool_1(out)\n",
    "\n",
    "        out = self.conv_2(out)\n",
    "        out = F.relu(out)\n",
    "        out = self.pool_2(out)\n",
    "        \n",
    "        logits = self.linear_1(out.view(-1, 7*7*8))\n",
    "        probas = F.softmax(logits, dim=1)\n",
    "        return logits, probas\n",
    "\n",
    "    \n",
    "torch.manual_seed(random_seed)\n",
    "model = ConvNet(num_classes=num_classes)\n",
    "\n",
    "model = model.to(device)\n",
    "    \n",
    "\n",
    "##########################\n",
    "### COST AND OPTIMIZER\n",
    "##########################\n",
    "\n",
    "cost_fn = torch.nn.CrossEntropyLoss()  \n",
    "optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Training"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/javascript": [
       "/* Put everything inside the global mpl namespace */\n",
       "window.mpl = {};\n",
       "\n",
       "\n",
       "mpl.get_websocket_type = function() {\n",
       "    if (typeof(WebSocket) !== 'undefined') {\n",
       "        return WebSocket;\n",
       "    } else if (typeof(MozWebSocket) !== 'undefined') {\n",
       "        return MozWebSocket;\n",
       "    } else {\n",
       "        alert('Your browser does not have WebSocket support.' +\n",
       "              'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
       "              'Firefox 4 and 5 are also supported but you ' +\n",
       "              'have to enable WebSockets in about:config.');\n",
       "    };\n",
       "}\n",
       "\n",
       "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n",
       "    this.id = figure_id;\n",
       "\n",
       "    this.ws = websocket;\n",
       "\n",
       "    this.supports_binary = (this.ws.binaryType != undefined);\n",
       "\n",
       "    if (!this.supports_binary) {\n",
       "        var warnings = document.getElementById(\"mpl-warnings\");\n",
       "        if (warnings) {\n",
       "            warnings.style.display = 'block';\n",
       "            warnings.textContent = (\n",
       "                \"This browser does not support binary websocket messages. \" +\n",
       "                    \"Performance may be slow.\");\n",
       "        }\n",
       "    }\n",
       "\n",
       "    this.imageObj = new Image();\n",
       "\n",
       "    this.context = undefined;\n",
       "    this.message = undefined;\n",
       "    this.canvas = undefined;\n",
       "    this.rubberband_canvas = undefined;\n",
       "    this.rubberband_context = undefined;\n",
       "    this.format_dropdown = undefined;\n",
       "\n",
       "    this.image_mode = 'full';\n",
       "\n",
       "    this.root = $('<div/>');\n",
       "    this._root_extra_style(this.root)\n",
       "    this.root.attr('style', 'display: inline-block');\n",
       "\n",
       "    $(parent_element).append(this.root);\n",
       "\n",
       "    this._init_header(this);\n",
       "    this._init_canvas(this);\n",
       "    this._init_toolbar(this);\n",
       "\n",
       "    var fig = this;\n",
       "\n",
       "    this.waiting = false;\n",
       "\n",
       "    this.ws.onopen =  function () {\n",
       "            fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n",
       "            fig.send_message(\"send_image_mode\", {});\n",
       "            if (mpl.ratio != 1) {\n",
       "                fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n",
       "            }\n",
       "            fig.send_message(\"refresh\", {});\n",
       "        }\n",
       "\n",
       "    this.imageObj.onload = function() {\n",
       "            if (fig.image_mode == 'full') {\n",
       "                // Full images could contain transparency (where diff images\n",
       "                // almost always do), so we need to clear the canvas so that\n",
       "                // there is no ghosting.\n",
       "                fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
       "            }\n",
       "            fig.context.drawImage(fig.imageObj, 0, 0);\n",
       "        };\n",
       "\n",
       "    this.imageObj.onunload = function() {\n",
       "        fig.ws.close();\n",
       "    }\n",
       "\n",
       "    this.ws.onmessage = this._make_on_message_function(this);\n",
       "\n",
       "    this.ondownload = ondownload;\n",
       "}\n",
       "\n",
       "mpl.figure.prototype._init_header = function() {\n",
       "    var titlebar = $(\n",
       "        '<div class=\"ui-dialog-titlebar ui-widget-header ui-corner-all ' +\n",
       "        'ui-helper-clearfix\"/>');\n",
       "    var titletext = $(\n",
       "        '<div class=\"ui-dialog-title\" style=\"width: 100%; ' +\n",
       "        'text-align: center; padding: 3px;\"/>');\n",
       "    titlebar.append(titletext)\n",
       "    this.root.append(titlebar);\n",
       "    this.header = titletext[0];\n",
       "}\n",
       "\n",
       "\n",
       "\n",
       "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n",
       "\n",
       "}\n",
       "\n",
       "\n",
       "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n",
       "\n",
       "}\n",
       "\n",
       "mpl.figure.prototype._init_canvas = function() {\n",
       "    var fig = this;\n",
       "\n",
       "    var canvas_div = $('<div/>');\n",
       "\n",
       "    canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n",
       "\n",
       "    function canvas_keyboard_event(event) {\n",
       "        return fig.key_event(event, event['data']);\n",
       "    }\n",
       "\n",
       "    canvas_div.keydown('key_press', canvas_keyboard_event);\n",
       "    canvas_div.keyup('key_release', canvas_keyboard_event);\n",
       "    this.canvas_div = canvas_div\n",
       "    this._canvas_extra_style(canvas_div)\n",
       "    this.root.append(canvas_div);\n",
       "\n",
       "    var canvas = $('<canvas/>');\n",
       "    canvas.addClass('mpl-canvas');\n",
       "    canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n",
       "\n",
       "    this.canvas = canvas[0];\n",
       "    this.context = canvas[0].getContext(\"2d\");\n",
       "\n",
       "    var backingStore = this.context.backingStorePixelRatio ||\n",
       "\tthis.context.webkitBackingStorePixelRatio ||\n",
       "\tthis.context.mozBackingStorePixelRatio ||\n",
       "\tthis.context.msBackingStorePixelRatio ||\n",
       "\tthis.context.oBackingStorePixelRatio ||\n",
       "\tthis.context.backingStorePixelRatio || 1;\n",
       "\n",
       "    mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n",
       "\n",
       "    var rubberband = $('<canvas/>');\n",
       "    rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n",
       "\n",
       "    var pass_mouse_events = true;\n",
       "\n",
       "    canvas_div.resizable({\n",
       "        start: function(event, ui) {\n",
       "            pass_mouse_events = false;\n",
       "        },\n",
       "        resize: function(event, ui) {\n",
       "            fig.request_resize(ui.size.width, ui.size.height);\n",
       "        },\n",
       "        stop: function(event, ui) {\n",
       "            pass_mouse_events = true;\n",
       "            fig.request_resize(ui.size.width, ui.size.height);\n",
       "        },\n",
       "    });\n",
       "\n",
       "    function mouse_event_fn(event) {\n",
       "        if (pass_mouse_events)\n",
       "            return fig.mouse_event(event, event['data']);\n",
       "    }\n",
       "\n",
       "    rubberband.mousedown('button_press', mouse_event_fn);\n",
       "    rubberband.mouseup('button_release', mouse_event_fn);\n",
       "    // Throttle sequential mouse events to 1 every 20ms.\n",
       "    rubberband.mousemove('motion_notify', mouse_event_fn);\n",
       "\n",
       "    rubberband.mouseenter('figure_enter', mouse_event_fn);\n",
       "    rubberband.mouseleave('figure_leave', mouse_event_fn);\n",
       "\n",
       "    canvas_div.on(\"wheel\", function (event) {\n",
       "        event = event.originalEvent;\n",
       "        event['data'] = 'scroll'\n",
       "        if (event.deltaY < 0) {\n",
       "            event.step = 1;\n",
       "        } else {\n",
       "            event.step = -1;\n",
       "        }\n",
       "        mouse_event_fn(event);\n",
       "    });\n",
       "\n",
       "    canvas_div.append(canvas);\n",
       "    canvas_div.append(rubberband);\n",
       "\n",
       "    this.rubberband = rubberband;\n",
       "    this.rubberband_canvas = rubberband[0];\n",
       "    this.rubberband_context = rubberband[0].getContext(\"2d\");\n",
       "    this.rubberband_context.strokeStyle = \"#000000\";\n",
       "\n",
       "    this._resize_canvas = function(width, height) {\n",
       "        // Keep the size of the canvas, canvas container, and rubber band\n",
       "        // canvas in synch.\n",
       "        canvas_div.css('width', width)\n",
       "        canvas_div.css('height', height)\n",
       "\n",
       "        canvas.attr('width', width * mpl.ratio);\n",
       "        canvas.attr('height', height * mpl.ratio);\n",
       "        canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n",
       "\n",
       "        rubberband.attr('width', width);\n",
       "        rubberband.attr('height', height);\n",
       "    }\n",
       "\n",
       "    // Set the figure to an initial 600x600px, this will subsequently be updated\n",
       "    // upon first draw.\n",
       "    this._resize_canvas(600, 600);\n",
       "\n",
       "    // Disable right mouse context menu.\n",
       "    $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n",
       "        return false;\n",
       "    });\n",
       "\n",
       "    function set_focus () {\n",
       "        canvas.focus();\n",
       "        canvas_div.focus();\n",
       "    }\n",
       "\n",
       "    window.setTimeout(set_focus, 100);\n",
       "}\n",
       "\n",
       "mpl.figure.prototype._init_toolbar = function() {\n",
       "    var fig = this;\n",
       "\n",
       "    var nav_element = $('<div/>')\n",
       "    nav_element.attr('style', 'width: 100%');\n",
       "    this.root.append(nav_element);\n",
       "\n",
       "    // Define a callback function for later on.\n",
       "    function toolbar_event(event) {\n",
       "        return fig.toolbar_button_onclick(event['data']);\n",
       "    }\n",
       "    function toolbar_mouse_event(event) {\n",
       "        return fig.toolbar_button_onmouseover(event['data']);\n",
       "    }\n",
       "\n",
       "    for(var toolbar_ind in mpl.toolbar_items) {\n",
       "        var name = mpl.toolbar_items[toolbar_ind][0];\n",
       "        var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
       "        var image = mpl.toolbar_items[toolbar_ind][2];\n",
       "        var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
       "\n",
       "        if (!name) {\n",
       "            // put a spacer in here.\n",
       "            continue;\n",
       "        }\n",
       "        var button = $('<button/>');\n",
       "        button.addClass('ui-button ui-widget ui-state-default ui-corner-all ' +\n",
       "                        'ui-button-icon-only');\n",
       "        button.attr('role', 'button');\n",
       "        button.attr('aria-disabled', 'false');\n",
       "        button.click(method_name, toolbar_event);\n",
       "        button.mouseover(tooltip, toolbar_mouse_event);\n",
       "\n",
       "        var icon_img = $('<span/>');\n",
       "        icon_img.addClass('ui-button-icon-primary ui-icon');\n",
       "        icon_img.addClass(image);\n",
       "        icon_img.addClass('ui-corner-all');\n",
       "\n",
       "        var tooltip_span = $('<span/>');\n",
       "        tooltip_span.addClass('ui-button-text');\n",
       "        tooltip_span.html(tooltip);\n",
       "\n",
       "        button.append(icon_img);\n",
       "        button.append(tooltip_span);\n",
       "\n",
       "        nav_element.append(button);\n",
       "    }\n",
       "\n",
       "    var fmt_picker_span = $('<span/>');\n",
       "\n",
       "    var fmt_picker = $('<select/>');\n",
       "    fmt_picker.addClass('mpl-toolbar-option ui-widget ui-widget-content');\n",
       "    fmt_picker_span.append(fmt_picker);\n",
       "    nav_element.append(fmt_picker_span);\n",
       "    this.format_dropdown = fmt_picker[0];\n",
       "\n",
       "    for (var ind in mpl.extensions) {\n",
       "        var fmt = mpl.extensions[ind];\n",
       "        var option = $(\n",
       "            '<option/>', {selected: fmt === mpl.default_extension}).html(fmt);\n",
       "        fmt_picker.append(option)\n",
       "    }\n",
       "\n",
       "    // Add hover states to the ui-buttons\n",
       "    $( \".ui-button\" ).hover(\n",
       "        function() { $(this).addClass(\"ui-state-hover\");},\n",
       "        function() { $(this).removeClass(\"ui-state-hover\");}\n",
       "    );\n",
       "\n",
       "    var status_bar = $('<span class=\"mpl-message\"/>');\n",
       "    nav_element.append(status_bar);\n",
       "    this.message = status_bar[0];\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n",
       "    // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n",
       "    // which will in turn request a refresh of the image.\n",
       "    this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.send_message = function(type, properties) {\n",
       "    properties['type'] = type;\n",
       "    properties['figure_id'] = this.id;\n",
       "    this.ws.send(JSON.stringify(properties));\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.send_draw_message = function() {\n",
       "    if (!this.waiting) {\n",
       "        this.waiting = true;\n",
       "        this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n",
       "    }\n",
       "}\n",
       "\n",
       "\n",
       "mpl.figure.prototype.handle_save = function(fig, msg) {\n",
       "    var format_dropdown = fig.format_dropdown;\n",
       "    var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n",
       "    fig.ondownload(fig, format);\n",
       "}\n",
       "\n",
       "\n",
       "mpl.figure.prototype.handle_resize = function(fig, msg) {\n",
       "    var size = msg['size'];\n",
       "    if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n",
       "        fig._resize_canvas(size[0], size[1]);\n",
       "        fig.send_message(\"refresh\", {});\n",
       "    };\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n",
       "    var x0 = msg['x0'] / mpl.ratio;\n",
       "    var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n",
       "    var x1 = msg['x1'] / mpl.ratio;\n",
       "    var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n",
       "    x0 = Math.floor(x0) + 0.5;\n",
       "    y0 = Math.floor(y0) + 0.5;\n",
       "    x1 = Math.floor(x1) + 0.5;\n",
       "    y1 = Math.floor(y1) + 0.5;\n",
       "    var min_x = Math.min(x0, x1);\n",
       "    var min_y = Math.min(y0, y1);\n",
       "    var width = Math.abs(x1 - x0);\n",
       "    var height = Math.abs(y1 - y0);\n",
       "\n",
       "    fig.rubberband_context.clearRect(\n",
       "        0, 0, fig.canvas.width, fig.canvas.height);\n",
       "\n",
       "    fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n",
       "    // Updates the figure title.\n",
       "    fig.header.textContent = msg['label'];\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.handle_cursor = function(fig, msg) {\n",
       "    var cursor = msg['cursor'];\n",
       "    switch(cursor)\n",
       "    {\n",
       "    case 0:\n",
       "        cursor = 'pointer';\n",
       "        break;\n",
       "    case 1:\n",
       "        cursor = 'default';\n",
       "        break;\n",
       "    case 2:\n",
       "        cursor = 'crosshair';\n",
       "        break;\n",
       "    case 3:\n",
       "        cursor = 'move';\n",
       "        break;\n",
       "    }\n",
       "    fig.rubberband_canvas.style.cursor = cursor;\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.handle_message = function(fig, msg) {\n",
       "    fig.message.textContent = msg['message'];\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.handle_draw = function(fig, msg) {\n",
       "    // Request the server to send over a new figure.\n",
       "    fig.send_draw_message();\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n",
       "    fig.image_mode = msg['mode'];\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.updated_canvas_event = function() {\n",
       "    // Called whenever the canvas gets updated.\n",
       "    this.send_message(\"ack\", {});\n",
       "}\n",
       "\n",
       "// A function to construct a web socket function for onmessage handling.\n",
       "// Called in the figure constructor.\n",
       "mpl.figure.prototype._make_on_message_function = function(fig) {\n",
       "    return function socket_on_message(evt) {\n",
       "        if (evt.data instanceof Blob) {\n",
       "            /* FIXME: We get \"Resource interpreted as Image but\n",
       "             * transferred with MIME type text/plain:\" errors on\n",
       "             * Chrome.  But how to set the MIME type?  It doesn't seem\n",
       "             * to be part of the websocket stream */\n",
       "            evt.data.type = \"image/png\";\n",
       "\n",
       "            /* Free the memory for the previous frames */\n",
       "            if (fig.imageObj.src) {\n",
       "                (window.URL || window.webkitURL).revokeObjectURL(\n",
       "                    fig.imageObj.src);\n",
       "            }\n",
       "\n",
       "            fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
       "                evt.data);\n",
       "            fig.updated_canvas_event();\n",
       "            fig.waiting = false;\n",
       "            return;\n",
       "        }\n",
       "        else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n",
       "            fig.imageObj.src = evt.data;\n",
       "            fig.updated_canvas_event();\n",
       "            fig.waiting = false;\n",
       "            return;\n",
       "        }\n",
       "\n",
       "        var msg = JSON.parse(evt.data);\n",
       "        var msg_type = msg['type'];\n",
       "\n",
       "        // Call the  \"handle_{type}\" callback, which takes\n",
       "        // the figure and JSON message as its only arguments.\n",
       "        try {\n",
       "            var callback = fig[\"handle_\" + msg_type];\n",
       "        } catch (e) {\n",
       "            console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n",
       "            return;\n",
       "        }\n",
       "\n",
       "        if (callback) {\n",
       "            try {\n",
       "                // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n",
       "                callback(fig, msg);\n",
       "            } catch (e) {\n",
       "                console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n",
       "            }\n",
       "        }\n",
       "    };\n",
       "}\n",
       "\n",
       "// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n",
       "mpl.findpos = function(e) {\n",
       "    //this section is from http://www.quirksmode.org/js/events_properties.html\n",
       "    var targ;\n",
       "    if (!e)\n",
       "        e = window.event;\n",
       "    if (e.target)\n",
       "        targ = e.target;\n",
       "    else if (e.srcElement)\n",
       "        targ = e.srcElement;\n",
       "    if (targ.nodeType == 3) // defeat Safari bug\n",
       "        targ = targ.parentNode;\n",
       "\n",
       "    // jQuery normalizes the pageX and pageY\n",
       "    // pageX,Y are the mouse positions relative to the document\n",
       "    // offset() returns the position of the element relative to the document\n",
       "    var x = e.pageX - $(targ).offset().left;\n",
       "    var y = e.pageY - $(targ).offset().top;\n",
       "\n",
       "    return {\"x\": x, \"y\": y};\n",
       "};\n",
       "\n",
       "/*\n",
       " * return a copy of an object with only non-object keys\n",
       " * we need this to avoid circular references\n",
       " * http://stackoverflow.com/a/24161582/3208463\n",
       " */\n",
       "function simpleKeys (original) {\n",
       "  return Object.keys(original).reduce(function (obj, key) {\n",
       "    if (typeof original[key] !== 'object')\n",
       "        obj[key] = original[key]\n",
       "    return obj;\n",
       "  }, {});\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.mouse_event = function(event, name) {\n",
       "    var canvas_pos = mpl.findpos(event)\n",
       "\n",
       "    if (name === 'button_press')\n",
       "    {\n",
       "        this.canvas.focus();\n",
       "        this.canvas_div.focus();\n",
       "    }\n",
       "\n",
       "    var x = canvas_pos.x * mpl.ratio;\n",
       "    var y = canvas_pos.y * mpl.ratio;\n",
       "\n",
       "    this.send_message(name, {x: x, y: y, button: event.button,\n",
       "                             step: event.step,\n",
       "                             guiEvent: simpleKeys(event)});\n",
       "\n",
       "    /* This prevents the web browser from automatically changing to\n",
       "     * the text insertion cursor when the button is pressed.  We want\n",
       "     * to control all of the cursor setting manually through the\n",
       "     * 'cursor' event from matplotlib */\n",
       "    event.preventDefault();\n",
       "    return false;\n",
       "}\n",
       "\n",
       "mpl.figure.prototype._key_event_extra = function(event, name) {\n",
       "    // Handle any extra behaviour associated with a key event\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.key_event = function(event, name) {\n",
       "\n",
       "    // Prevent repeat events\n",
       "    if (name == 'key_press')\n",
       "    {\n",
       "        if (event.which === this._key)\n",
       "            return;\n",
       "        else\n",
       "            this._key = event.which;\n",
       "    }\n",
       "    if (name == 'key_release')\n",
       "        this._key = null;\n",
       "\n",
       "    var value = '';\n",
       "    if (event.ctrlKey && event.which != 17)\n",
       "        value += \"ctrl+\";\n",
       "    if (event.altKey && event.which != 18)\n",
       "        value += \"alt+\";\n",
       "    if (event.shiftKey && event.which != 16)\n",
       "        value += \"shift+\";\n",
       "\n",
       "    value += 'k';\n",
       "    value += event.which.toString();\n",
       "\n",
       "    this._key_event_extra(event, name);\n",
       "\n",
       "    this.send_message(name, {key: value,\n",
       "                             guiEvent: simpleKeys(event)});\n",
       "    return false;\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.toolbar_button_onclick = function(name) {\n",
       "    if (name == 'download') {\n",
       "        this.handle_save(this, null);\n",
       "    } else {\n",
       "        this.send_message(\"toolbar_button\", {name: name});\n",
       "    }\n",
       "};\n",
       "\n",
       "mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n",
       "    this.message.textContent = tooltip;\n",
       "};\n",
       "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n",
       "\n",
       "mpl.extensions = [\"eps\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
       "\n",
       "mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n",
       "    // Create a \"websocket\"-like object which calls the given IPython comm\n",
       "    // object with the appropriate methods. Currently this is a non binary\n",
       "    // socket, so there is still some room for performance tuning.\n",
       "    var ws = {};\n",
       "\n",
       "    ws.close = function() {\n",
       "        comm.close()\n",
       "    };\n",
       "    ws.send = function(m) {\n",
       "        //console.log('sending', m);\n",
       "        comm.send(m);\n",
       "    };\n",
       "    // Register the callback with on_msg.\n",
       "    comm.on_msg(function(msg) {\n",
       "        //console.log('receiving', msg['content']['data'], msg);\n",
       "        // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
       "        ws.onmessage(msg['content']['data'])\n",
       "    });\n",
       "    return ws;\n",
       "}\n",
       "\n",
       "mpl.mpl_figure_comm = function(comm, msg) {\n",
       "    // This is the function which gets called when the mpl process\n",
       "    // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
       "\n",
       "    var id = msg.content.data.id;\n",
       "    // Get hold of the div created by the display call when the Comm\n",
       "    // socket was opened in Python.\n",
       "    var element = $(\"#\" + id);\n",
       "    var ws_proxy = comm_websocket_adapter(comm)\n",
       "\n",
       "    function ondownload(figure, format) {\n",
       "        window.open(figure.imageObj.src);\n",
       "    }\n",
       "\n",
       "    var fig = new mpl.figure(id, ws_proxy,\n",
       "                           ondownload,\n",
       "                           element.get(0));\n",
       "\n",
       "    // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n",
       "    // web socket which is closed, not our websocket->open comm proxy.\n",
       "    ws_proxy.onopen();\n",
       "\n",
       "    fig.parent_element = element.get(0);\n",
       "    fig.cell_info = mpl.find_output_cell(\"<div id='\" + id + \"'></div>\");\n",
       "    if (!fig.cell_info) {\n",
       "        console.error(\"Failed to find cell for figure\", id, fig);\n",
       "        return;\n",
       "    }\n",
       "\n",
       "    var output_index = fig.cell_info[2]\n",
       "    var cell = fig.cell_info[0];\n",
       "\n",
       "};\n",
       "\n",
       "mpl.figure.prototype.handle_close = function(fig, msg) {\n",
       "    var width = fig.canvas.width/mpl.ratio\n",
       "    fig.root.unbind('remove')\n",
       "\n",
       "    // Update the output cell to use the data from the current canvas.\n",
       "    fig.push_to_output();\n",
       "    var dataURL = fig.canvas.toDataURL();\n",
       "    // Re-enable the keyboard manager in IPython - without this line, in FF,\n",
       "    // the notebook keyboard shortcuts fail.\n",
       "    IPython.keyboard_manager.enable()\n",
       "    $(fig.parent_element).html('<img src=\"' + dataURL + '\" width=\"' + width + '\">');\n",
       "    fig.close_ws(fig, msg);\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.close_ws = function(fig, msg){\n",
       "    fig.send_message('closing', msg);\n",
       "    // fig.ws.close()\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.push_to_output = function(remove_interactive) {\n",
       "    // Turn the data on the canvas into data in the output cell.\n",
       "    var width = this.canvas.width/mpl.ratio\n",
       "    var dataURL = this.canvas.toDataURL();\n",
       "    this.cell_info[1]['text/html'] = '<img src=\"' + dataURL + '\" width=\"' + width + '\">';\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.updated_canvas_event = function() {\n",
       "    // Tell IPython that the notebook contents must change.\n",
       "    IPython.notebook.set_dirty(true);\n",
       "    this.send_message(\"ack\", {});\n",
       "    var fig = this;\n",
       "    // Wait a second, then push the new image to the DOM so\n",
       "    // that it is saved nicely (might be nice to debounce this).\n",
       "    setTimeout(function () { fig.push_to_output() }, 1000);\n",
       "}\n",
       "\n",
       "mpl.figure.prototype._init_toolbar = function() {\n",
       "    var fig = this;\n",
       "\n",
       "    var nav_element = $('<div/>')\n",
       "    nav_element.attr('style', 'width: 100%');\n",
       "    this.root.append(nav_element);\n",
       "\n",
       "    // Define a callback function for later on.\n",
       "    function toolbar_event(event) {\n",
       "        return fig.toolbar_button_onclick(event['data']);\n",
       "    }\n",
       "    function toolbar_mouse_event(event) {\n",
       "        return fig.toolbar_button_onmouseover(event['data']);\n",
       "    }\n",
       "\n",
       "    for(var toolbar_ind in mpl.toolbar_items){\n",
       "        var name = mpl.toolbar_items[toolbar_ind][0];\n",
       "        var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
       "        var image = mpl.toolbar_items[toolbar_ind][2];\n",
       "        var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
       "\n",
       "        if (!name) { continue; };\n",
       "\n",
       "        var button = $('<button class=\"btn btn-default\" href=\"#\" title=\"' + name + '\"><i class=\"fa ' + image + ' fa-lg\"></i></button>');\n",
       "        button.click(method_name, toolbar_event);\n",
       "        button.mouseover(tooltip, toolbar_mouse_event);\n",
       "        nav_element.append(button);\n",
       "    }\n",
       "\n",
       "    // Add the status bar.\n",
       "    var status_bar = $('<span class=\"mpl-message\" style=\"text-align:right; float: right;\"/>');\n",
       "    nav_element.append(status_bar);\n",
       "    this.message = status_bar[0];\n",
       "\n",
       "    // Add the close button to the window.\n",
       "    var buttongrp = $('<div class=\"btn-group inline pull-right\"></div>');\n",
       "    var button = $('<button class=\"btn btn-mini btn-primary\" href=\"#\" title=\"Stop Interaction\"><i class=\"fa fa-power-off icon-remove icon-large\"></i></button>');\n",
       "    button.click(function (evt) { fig.handle_close(fig, {}); } );\n",
       "    button.mouseover('Stop Interaction', toolbar_mouse_event);\n",
       "    buttongrp.append(button);\n",
       "    var titlebar = this.root.find($('.ui-dialog-titlebar'));\n",
       "    titlebar.prepend(buttongrp);\n",
       "}\n",
       "\n",
       "mpl.figure.prototype._root_extra_style = function(el){\n",
       "    var fig = this\n",
       "    el.on(\"remove\", function(){\n",
       "\tfig.close_ws(fig, {});\n",
       "    });\n",
       "}\n",
       "\n",
       "mpl.figure.prototype._canvas_extra_style = function(el){\n",
       "    // this is important to make the div 'focusable\n",
       "    el.attr('tabindex', 0)\n",
       "    // reach out to IPython and tell the keyboard manager to turn it's self\n",
       "    // off when our div gets focus\n",
       "\n",
       "    // location in version 3\n",
       "    if (IPython.notebook.keyboard_manager) {\n",
       "        IPython.notebook.keyboard_manager.register_events(el);\n",
       "    }\n",
       "    else {\n",
       "        // location in version 2\n",
       "        IPython.keyboard_manager.register_events(el);\n",
       "    }\n",
       "\n",
       "}\n",
       "\n",
       "mpl.figure.prototype._key_event_extra = function(event, name) {\n",
       "    var manager = IPython.notebook.keyboard_manager;\n",
       "    if (!manager)\n",
       "        manager = IPython.keyboard_manager;\n",
       "\n",
       "    // Check for shift+enter\n",
       "    if (event.shiftKey && event.which == 13) {\n",
       "        this.canvas_div.blur();\n",
       "        event.shiftKey = false;\n",
       "        // Send a \"J\" for go to next cell\n",
       "        event.which = 74;\n",
       "        event.keyCode = 74;\n",
       "        manager.command_mode();\n",
       "        manager.handle_keydown(event);\n",
       "    }\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.handle_save = function(fig, msg) {\n",
       "    fig.ondownload(fig, null);\n",
       "}\n",
       "\n",
       "\n",
       "mpl.find_output_cell = function(html_output) {\n",
       "    // Return the cell and output element which can be found *uniquely* in the notebook.\n",
       "    // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n",
       "    // IPython event is triggered only after the cells have been serialised, which for\n",
       "    // our purposes (turning an active figure into a static one), is too late.\n",
       "    var cells = IPython.notebook.get_cells();\n",
       "    var ncells = cells.length;\n",
       "    for (var i=0; i<ncells; i++) {\n",
       "        var cell = cells[i];\n",
       "        if (cell.cell_type === 'code'){\n",
       "            for (var j=0; j<cell.output_area.outputs.length; j++) {\n",
       "                var data = cell.output_area.outputs[j];\n",
       "                if (data.data) {\n",
       "                    // IPython >= 3 moved mimebundle to data attribute of output\n",
       "                    data = data.data;\n",
       "                }\n",
       "                if (data['text/html'] == html_output) {\n",
       "                    return [cell, data, j];\n",
       "                }\n",
       "            }\n",
       "        }\n",
       "    }\n",
       "}\n",
       "\n",
       "// Register the function which deals with the matplotlib target/channel.\n",
       "// The kernel may be null if the page has been refreshed.\n",
       "if (IPython.notebook.kernel != null) {\n",
       "    IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n",
       "}\n"
      ],
      "text/plain": [
       "<IPython.core.display.Javascript object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<img src=\"data:image/png;base64,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qFu3rtSoUSNsXbw3Olpb564sXz47J8bR4LNnz57y6KOPyl//+lcZP368TJo0STQ4/+9//ys//fRTvMtnm08CBKA+wZMtAggggAACXgWOOOII0SBUazdt0mUNPg8//HC7ynmNrHls3ry59O7dW6688konMNVjXnnlldAxsWr3xo0bJ+3atZPKlSvLMcccIzNnzgwds3btWrnwwgulSZMmTo1j27Zt5YMPPght1xrZ0aNHy7PPPuvU0GoNruajSQPCM888U2rWrOmU57jjjpP58+c72+z/nnjiCdG5NHW6LA0k440qf+aZZ2TMmDEyfPhwZ98OHTrIAQccIH/5y1/ku+++k4MOOsg57Y4dO+Tmm292pkjSa+ratat8//33NktZt26dXHTRRVK/fn3RKZX0OK1B1dSiRQvnVa31WtSYVDwBAtDi+UU9etN2Hu8WFYaVCCCAQIAEnMnDd+6WrT78aN7JJg0gbUCkx77++utyxRVXeDrNk08+KR07dpQff/xRbrjhBrn++utl7ty5cY+94447RI/TIE2DsrPOOisUCGrt65FHHimDBg1yAlOtebzkkkucmkc9qQaenTt3lmuuucZp3tcmfg2gf/31V+nWrZtUqlRJRowYIVOmTHEC4927d4fKMnLkSCcg1de33npL3nzzTecntEPEwnvvvSc9evQoEojrbvp4zGrVqjlH3HnnndK/f3/nnD/88IMceOCBTs3p77//7my/9957ZdasWTJkyBCZPXu2vPjii6JN+Zq0RlXTsGHDnOtxfxFwNvC/pAWys7496cvM7AGd+4yQ205vL7f2OMj5ppTZ3MkNAQQQQMCLwLZde+TQ+4Z62TXt+8x6qKdUrZjcn+CLL75YevXqJYsXL3bKozWU2iyvg4YSpdNPP90JPHW/f/7zn/L000+LBnitWrWKeej9998vJ598srNdA8GmTZvKp59+Kueff75T8/mPf/wjdOxNN90kQ4cOlY8++kg6deoktWrVkooVKzq1o9q8b9MLL7zgbNNya3Co6eCDD7abndc6derI888/70zk3rp1aznjjDOc2k0NZqOlefPmJayR3LJlixNQvmmC2dNOO805zauvvirffPON9O3bVzTYXrJkiRPEaqCuSWuObdIAXJPWyLqvx27nNXmB5D79yZ+/1B7x7PB5oj8/PdhTqlWCudR+ELhwBBBAIE0C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7LHWu3dv+/7775Py7NixwwYPHhyC0Z944ok2bNgw27NnT1Keb775xi699NKga63rO3HixKT7nKROYPz48dalSxerV6+enXrqqTZgwAD77rvvkgT99ddfNmrUKDvppJOsbt26dt1119mWLVuS8mgVsquuusrq1KkT5Nx99932zz//JOUpLS21jh072tFHH20tWrSwF154Iek+J6kRePrpp+28884L74yCknft2tU+/PDDWAh6i1Hk9cGECRPCWvZjxoyJ24nuYhQcVAUB/6VMypDAa6+95o466ig3Y8YMt2bNGjd8+HDnjRfnvxwzlEzxVAh88MEH7oEHHnDvvPOO8++Ke/fdd5OK+w9Y51ehcN4wdStXrnTXXHONO+uss9yff/4Z57v88std+/bt3Zdffuk+++wz5w0UN2jQoPj+rl27XMOGDZ03Ut3q1avdq6++6rwx65599tk4DwepE+jbt697/vnnA9Ovv/7aXXnlle6MM85w3viPhY0YMcJ5g9/NmzfPLVu2zF100UWuW7du8X1vaLq2bds6/8PCffXVV07/DyeffLK777774jwbNmxw3jh1d9xxh1u7dq2bOnWq86Fk3Jw5c+I8HKRG4L333nPvv/++W79+vfM/Gtz999/vateuHXQpSegtNZ7Vkds7TJx3oDj/Q8LdfvvtcRPQXYyCgyogYFUg84gTecEFFzjvmYmf+8CBA86v9eq8Vye+xkFuCZQ1QA8ePOgaNWrkHn/88bghO3fudN4LFoxIXZRBonJLly6N83hPjvPeVPfLL7+Ea9OnT3f169d3f//9d5znnnvuceecc058zkHmBLZu3Rp0sXDhwiBMupJR8+abb8bC161bF/J88cUX4ZoMTr8crvv111/jPN4757xXLtbX2LFjXZs2beL7Ohg4cKCTAUzKHgG9I88995xDb9ljWlWS/NrkrmXLlm7u3LmuR48esQGK7qqKOHIjAnTBZ+hW3rdvny1fvjx050aitCa8unf9F2N0iX01E9i4caN5wyRJT1qTV8MlIj1pr273zp07x62VHqXPxYsXh2vK0717d/Me7ziPN15Cd/Fvv/0WX+MgMwLe0xwENGjQIOz1ju3fvz9Jf61atTLvJU3SX7t27cx7qOPKpZvff//dfM9EuCb9SaeJSXmi/4HE6xynTsD/+DbfI2R//PFH6IpHb6kzzHUJDWvR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\" width=\"672\">"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch: 001/010 | Batch 000/469 | Cost: 2.3016\n",
      "Epoch: 001/010 | Batch 050/469 | Cost: 2.2714\n",
      "Epoch: 001/010 | Batch 100/469 | Cost: 1.6118\n",
      "Epoch: 001/010 | Batch 150/469 | Cost: 0.8000\n",
      "Epoch: 001/010 | Batch 200/469 | Cost: 0.5079\n",
      "Epoch: 001/010 | Batch 250/469 | Cost: 0.3221\n",
      "Epoch: 001/010 | Batch 300/469 | Cost: 0.2851\n",
      "Epoch: 001/010 | Batch 350/469 | Cost: 0.3117\n",
      "Epoch: 001/010 | Batch 400/469 | Cost: 0.2836\n",
      "Epoch: 001/010 | Batch 450/469 | Cost: 0.3169\n",
      "Epoch: 001/010 training accuracy: 92.72%\n",
      "Epoch: 002/010 | Batch 000/469 | Cost: 0.2469\n",
      "Epoch: 002/010 | Batch 050/469 | Cost: 0.2342\n",
      "Epoch: 002/010 | Batch 100/469 | Cost: 0.2883\n",
      "Epoch: 002/010 | Batch 150/469 | Cost: 0.2920\n",
      "Epoch: 002/010 | Batch 200/469 | Cost: 0.1797\n",
      "Epoch: 002/010 | Batch 250/469 | Cost: 0.2277\n",
      "Epoch: 002/010 | Batch 300/469 | Cost: 0.1746\n",
      "Epoch: 002/010 | Batch 350/469 | Cost: 0.2430\n",
      "Epoch: 002/010 | Batch 400/469 | Cost: 0.1579\n",
      "Epoch: 002/010 | Batch 450/469 | Cost: 0.1279\n",
      "Epoch: 002/010 training accuracy: 95.07%\n",
      "Epoch: 003/010 | Batch 000/469 | Cost: 0.1224\n",
      "Epoch: 003/010 | Batch 050/469 | Cost: 0.1998\n",
      "Epoch: 003/010 | Batch 100/469 | Cost: 0.2211\n",
      "Epoch: 003/010 | Batch 150/469 | Cost: 0.0906\n",
      "Epoch: 003/010 | Batch 200/469 | Cost: 0.1502\n",
      "Epoch: 003/010 | Batch 250/469 | Cost: 0.2392\n",
      "Epoch: 003/010 | Batch 300/469 | Cost: 0.1108\n",
      "Epoch: 003/010 | Batch 350/469 | Cost: 0.1736\n",
      "Epoch: 003/010 | Batch 400/469 | Cost: 0.1428\n",
      "Epoch: 003/010 | Batch 450/469 | Cost: 0.1253\n",
      "Epoch: 003/010 training accuracy: 96.22%\n",
      "Epoch: 004/010 | Batch 000/469 | Cost: 0.1369\n",
      "Epoch: 004/010 | Batch 050/469 | Cost: 0.1984\n",
      "Epoch: 004/010 | Batch 100/469 | Cost: 0.1297\n",
      "Epoch: 004/010 | Batch 150/469 | Cost: 0.1437\n",
      "Epoch: 004/010 | Batch 200/469 | Cost: 0.1140\n",
      "Epoch: 004/010 | Batch 250/469 | Cost: 0.0566\n",
      "Epoch: 004/010 | Batch 300/469 | Cost: 0.1120\n",
      "Epoch: 004/010 | Batch 350/469 | Cost: 0.1777\n",
      "Epoch: 004/010 | Batch 400/469 | Cost: 0.2209\n",
      "Epoch: 004/010 | Batch 450/469 | Cost: 0.1390\n",
      "Epoch: 004/010 training accuracy: 96.77%\n",
      "Epoch: 005/010 | Batch 000/469 | Cost: 0.1306\n",
      "Epoch: 005/010 | Batch 050/469 | Cost: 0.0445\n",
      "Epoch: 005/010 | Batch 100/469 | Cost: 0.1327\n",
      "Epoch: 005/010 | Batch 150/469 | Cost: 0.0846\n",
      "Epoch: 005/010 | Batch 200/469 | Cost: 0.0759\n",
      "Epoch: 005/010 | Batch 250/469 | Cost: 0.0796\n",
      "Epoch: 005/010 | Batch 300/469 | Cost: 0.1364\n",
      "Epoch: 005/010 | Batch 350/469 | Cost: 0.1421\n",
      "Epoch: 005/010 | Batch 400/469 | Cost: 0.0904\n",
      "Epoch: 005/010 | Batch 450/469 | Cost: 0.0598\n",
      "Epoch: 005/010 training accuracy: 97.15%\n",
      "Epoch: 006/010 | Batch 000/469 | Cost: 0.0723\n",
      "Epoch: 006/010 | Batch 050/469 | Cost: 0.0481\n",
      "Epoch: 006/010 | Batch 100/469 | Cost: 0.0386\n",
      "Epoch: 006/010 | Batch 150/469 | Cost: 0.0420\n",
      "Epoch: 006/010 | Batch 200/469 | Cost: 0.1176\n",
      "Epoch: 006/010 | Batch 250/469 | Cost: 0.0718\n",
      "Epoch: 006/010 | Batch 300/469 | Cost: 0.0537\n",
      "Epoch: 006/010 | Batch 350/469 | Cost: 0.0231\n",
      "Epoch: 006/010 | Batch 400/469 | Cost: 0.0939\n",
      "Epoch: 006/010 | Batch 450/469 | Cost: 0.0848\n",
      "Epoch: 006/010 training accuracy: 97.43%\n",
      "Epoch: 007/010 | Batch 000/469 | Cost: 0.1984\n",
      "Epoch: 007/010 | Batch 050/469 | Cost: 0.0445\n",
      "Epoch: 007/010 | Batch 100/469 | Cost: 0.0525\n",
      "Epoch: 007/010 | Batch 150/469 | Cost: 0.0640\n",
      "Epoch: 007/010 | Batch 200/469 | Cost: 0.0669\n",
      "Epoch: 007/010 | Batch 250/469 | Cost: 0.0952\n",
      "Epoch: 007/010 | Batch 300/469 | Cost: 0.0293\n",
      "Epoch: 007/010 | Batch 350/469 | Cost: 0.0972\n",
      "Epoch: 007/010 | Batch 400/469 | Cost: 0.1133\n",
      "Epoch: 007/010 | Batch 450/469 | Cost: 0.0554\n",
      "Epoch: 007/010 training accuracy: 97.77%\n",
      "Epoch: 008/010 | Batch 000/469 | Cost: 0.1194\n",
      "Epoch: 008/010 | Batch 050/469 | Cost: 0.1556\n",
      "Epoch: 008/010 | Batch 100/469 | Cost: 0.0913\n",
      "Epoch: 008/010 | Batch 150/469 | Cost: 0.0400\n",
      "Epoch: 008/010 | Batch 200/469 | Cost: 0.0833\n",
      "Epoch: 008/010 | Batch 250/469 | Cost: 0.0418\n",
      "Epoch: 008/010 | Batch 300/469 | Cost: 0.0885\n",
      "Epoch: 008/010 | Batch 350/469 | Cost: 0.0844\n",
      "Epoch: 008/010 | Batch 400/469 | Cost: 0.0675\n",
      "Epoch: 008/010 | Batch 450/469 | Cost: 0.1387\n",
      "Epoch: 008/010 training accuracy: 97.56%\n",
      "Epoch: 009/010 | Batch 000/469 | Cost: 0.0827\n",
      "Epoch: 009/010 | Batch 050/469 | Cost: 0.1027\n",
      "Epoch: 009/010 | Batch 100/469 | Cost: 0.1812\n",
      "Epoch: 009/010 | Batch 150/469 | Cost: 0.0660\n",
      "Epoch: 009/010 | Batch 200/469 | Cost: 0.0881\n",
      "Epoch: 009/010 | Batch 250/469 | Cost: 0.1576\n",
      "Epoch: 009/010 | Batch 300/469 | Cost: 0.0478\n",
      "Epoch: 009/010 | Batch 350/469 | Cost: 0.0779\n",
      "Epoch: 009/010 | Batch 400/469 | Cost: 0.0407\n",
      "Epoch: 009/010 | Batch 450/469 | Cost: 0.0236\n",
      "Epoch: 009/010 training accuracy: 97.83%\n",
      "Epoch: 010/010 | Batch 000/469 | Cost: 0.0182\n",
      "Epoch: 010/010 | Batch 050/469 | Cost: 0.0742\n",
      "Epoch: 010/010 | Batch 100/469 | Cost: 0.0425\n",
      "Epoch: 010/010 | Batch 150/469 | Cost: 0.0332\n",
      "Epoch: 010/010 | Batch 200/469 | Cost: 0.0795\n",
      "Epoch: 010/010 | Batch 250/469 | Cost: 0.0571\n",
      "Epoch: 010/010 | Batch 300/469 | Cost: 0.1068\n",
      "Epoch: 010/010 | Batch 350/469 | Cost: 0.1661\n",
      "Epoch: 010/010 | Batch 400/469 | Cost: 0.0202\n",
      "Epoch: 010/010 | Batch 450/469 | Cost: 0.0613\n",
      "Epoch: 010/010 training accuracy: 97.77%\n"
     ]
    }
   ],
   "source": [
    "def compute_accuracy(model, data_loader):\n",
    "    correct_pred, num_examples = 0, 0\n",
    "    for features, targets in data_loader:\n",
    "        features = features.to(device)\n",
    "        targets = targets.to(device)\n",
    "        logits, probas = model(features)\n",
    "        _, predicted_labels = torch.max(probas, 1)\n",
    "        num_examples += targets.size(0)\n",
    "        correct_pred += (predicted_labels == targets).sum()\n",
    "    return correct_pred.float()/num_examples * 100\n",
    "    \n",
    "\n",
    "    \n",
    "minibatch_costs = []\n",
    "\n",
    "%matplotlib notebook\n",
    "plot = LivePerformanceplot(labels=['Minibatch Cost'],\n",
    "                           xlabel='Iteration')\n",
    "\n",
    "\n",
    "for epoch in range(num_epochs):\n",
    "\n",
    "    model = model.train()\n",
    "    for batch_idx, (features, targets) in enumerate(train_loader):\n",
    "        \n",
    "        features = features.to(device)\n",
    "        targets = targets.to(device)\n",
    "\n",
    "        ### FORWARD AND BACK PROP\n",
    "        logits, probas = model(features)\n",
    "        cost = cost_fn(logits, targets)\n",
    "        minibatch_costs.append(cost.detach().cpu().numpy())\n",
    "        optimizer.zero_grad()\n",
    "        \n",
    "        cost.backward()\n",
    "        \n",
    "        ### UPDATE MODEL PARAMETERS\n",
    "        optimizer.step()\n",
    "        \n",
    "        ### UPDATE PLOT\n",
    "        \n",
    "        data_dict = {'Minibatch Cost': (range(len(minibatch_costs)), minibatch_costs)}\n",
    "        plot.update(data_dict=data_dict)\n",
    "        \n",
    "        ### LOGGING\n",
    "        if not batch_idx % 50:\n",
    "            print ('Epoch: %03d/%03d | Batch %03d/%03d | Cost: %.4f' \n",
    "                   %(epoch+1, num_epochs, batch_idx, \n",
    "                     len(train_loader), cost))\n",
    "    \n",
    "    model = model.eval()\n",
    "    print('Epoch: %03d/%03d training accuracy: %.2f%%' % (\n",
    "          epoch+1, num_epochs, \n",
    "          compute_accuracy(model, train_loader)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Evaluation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Test accuracy: 97.76%\n"
     ]
    }
   ],
   "source": [
    "print('Test accuracy: %.2f%%' % (compute_accuracy(model, test_loader)))"
   ]
  }
 ],
 "metadata": {
  "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.7.1"
  },
  "toc": {
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}