Repository: aidotse/PASEOS (language: python)

Issue:
Visual implementation follow up
# Description

Summary of changes

* Changed API to simplify user interaction
* Fixed problems on win / linux
* Some minor restyling
* Refactoring

## Resolved Issues

N/A

## How Has This Been Tested?

- example jupyter notebook
- ran tests

## Related Pull Requests

- #27 



Discussion / hints:

Fix patch:
diff --git a/README.md b/README.md
index f66e778b..f7f13a9e 100644
--- a/README.md
+++ b/README.md
@@ -21,4 +21,22 @@ This project is currently under development. Use at your own risk. :)
   <p align="center">
     Description of PASEOS workflow on an individual device
   </p>
+</p>
+
+## Visualising PASEOS
+Navigate to paseos/visualization to find a jupyter notebook containing examples of how to visualize PASEOS.
+Visualization can be done in interactive mode or as an animation that is saved to disc.
+In the figure below, Earth is visualized in the center as a blue sphere with different spacecraft in orbit.
+Each spacecraft has a name and if provided, a battery level and a communications device.
+The local device is illustrated with white text.
+In the upper-right corner, the status of the communication link between each spacecraft is shown.
+Finally, the time in the lower left and lower right corners correspond to the epoch and the PASEOS local simulation time.
+
+<p align="center">
+  <a href="https://github.com/aidotse/PASEOS/">
+    <img src="resources/images/animation.png" alt="Scheme"  width="900" height="500">
+  </a>
+  <p align="center">
+    Snapshot of PASEOS visualization
+  </p>
 </p>
\ No newline at end of file
diff --git a/environment.yml b/environment.yml
index 971c8f68..b6704efa 100644
--- a/environment.yml
+++ b/environment.yml
@@ -2,14 +2,15 @@ name: paseos
 channels:
   - conda-forge
 dependencies:
-  - dotmap
-  - loguru
-  - myst-parser
-  - pykep
-  - pytest
-  - python
-  - scikit-spatial
-  - sphinx
-  - sphinx_rtd_theme
-  - toml
-  - tqdm
+- dotmap
+- loguru
+- matplotlib
+- myst-parser
+- pykep
+- pytest
+- python 
+- scikit-spatial
+- sphinx
+- sphinx_rtd_theme
+- toml
+- tqdm
\ No newline at end of file
diff --git a/examples/visualization/example_jupyter.ipynb b/examples/visualization/example_jupyter.ipynb
new file mode 100644
index 00000000..36d98b24
--- /dev/null
+++ b/examples/visualization/example_jupyter.ipynb
@@ -0,0 +1,1161 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "# Visualization of PASEOS\n",
+    "\n",
+    "First load the necessary packages"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 1,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "\u001b[32m13:26:10\u001b[0m|PASEOS-\u001b[34mDEBUG\u001b[0m| \u001b[34m\u001b[1mSetting LogLevel to DEBUG\u001b[0m\n",
+      "\u001b[32m13:26:10\u001b[0m|PASEOS-\u001b[34mDEBUG\u001b[0m| \u001b[34m\u001b[1mLoaded module.\u001b[0m\n"
+     ]
+    }
+   ],
+   "source": [
+    "%load_ext autoreload\n",
+    "%autoreload 2\n",
+    "\n",
+    "# If you haven't installed PASEOS\n",
+    "import sys\n",
+    "sys.path.append(\"../..\")\n",
+    "\n",
+    "# We use pykep for orbit determination\n",
+    "import pykep as pk\n",
+    "\n",
+    "import paseos\n",
+    "from paseos.actors.spacecraft_actor import SpacecraftActor\n",
+    "from paseos.actors.actor_builder import ActorBuilder\n",
+    "paseos.set_log_level(\"INFO\")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "For animations in notebooks you currently need to use `%matplotlib notebook`. This is supported by Jupyter Notebook, but, e.g., VSCode currently does not support this."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 2,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "%matplotlib notebook"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Create a PASEOS object. Add some actors"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 3,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    " # Define central body\n",
+    "earth = pk.planet.jpl_lp(\"earth\")\n",
+    "sat1 = ActorBuilder.get_actor_scaffold(\n",
+    "        \"sat1\", SpacecraftActor, [0, 0, 0], pk.epoch(0)\n",
+    "    )\n",
+    "sat2 = ActorBuilder.get_actor_scaffold(\n",
+    "    \"sat2\", SpacecraftActor, [0, 0, 0], pk.epoch(0)\n",
+    ")\n",
+    "\n",
+    "# Define local actor\n",
+    "sat3 = ActorBuilder.get_actor_scaffold(\n",
+    "    \"sat3\", SpacecraftActor, [10000000, 0, 0], pk.epoch(0)\n",
+    ")\n",
+    "ActorBuilder.set_orbit(sat3, [-10000000, 0.1, 0.1], [0, 8000.0, 0], pk.epoch(0), earth)\n",
+    "ActorBuilder.set_power_devices(sat3, 500, 10000, 1)\n",
+    "\n",
+    "sat4 = ActorBuilder.get_actor_scaffold(\n",
+    "    \"sat4\", SpacecraftActor, [10000000, 0, 0], pk.epoch(0)\n",
+    ")\n",
+    "ActorBuilder.set_orbit(sat4, [0, 10000000, 0], [0, 0, 8000.0], pk.epoch(0), earth)\n",
+    "\n",
+    "\n",
+    "ActorBuilder.set_orbit(\n",
+    "    sat1,\n",
+    "    position=[10000000, 1e-3, 1e-3],\n",
+    "    velocity=[1e-3, 8000, 1e-3],\n",
+    "    epoch=pk.epoch(0),\n",
+    "    central_body=earth,\n",
+    ")\n",
+    "ActorBuilder.set_orbit(\n",
+    "    sat2,\n",
+    "    position=[10000000, 1e-3, 1e-3],\n",
+    "    velocity=[1e-3, -8000, 1e-3],\n",
+    "    epoch=pk.epoch(0),\n",
+    "    central_body=earth,\n",
+    ")\n",
+    "\n",
+    "# Add communication link\n",
+    "ActorBuilder.add_comm_device(sat1, device_name=\"link1\", bandwidth_in_kbps=1)\n",
+    "ActorBuilder.add_comm_device(sat2, device_name=\"link1\", bandwidth_in_kbps=2)\n",
+    "ActorBuilder.set_power_devices(sat1, 500, 10000, 1)\n",
+    "ActorBuilder.set_power_devices(sat2, 500, 10000, 1)\n",
+    "sim = paseos.init_sim(sat1)\n",
+    "sim.add_known_actor(sat2)\n",
+    "sim.add_known_actor(sat3)\n",
+    "sim.add_known_actor(sat4)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 4,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "application/javascript": [
+       "/* Put everything inside the global mpl namespace */\n",
+       "/* global mpl */\n",
+       "window.mpl = {};\n",
+       "\n",
+       "mpl.get_websocket_type = function () {\n",
+       "    if (typeof WebSocket !== 'undefined') {\n",
+       "        return WebSocket;\n",
+       "    } else if (typeof MozWebSocket !== 'undefined') {\n",
+       "        return MozWebSocket;\n",
+       "    } else {\n",
+       "        alert(\n",
+       "            '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",
+       "\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 = document.createElement('div');\n",
+       "    this.root.setAttribute('style', 'display: inline-block');\n",
+       "    this._root_extra_style(this.root);\n",
+       "\n",
+       "    parent_element.appendChild(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 (fig.ratio !== 1) {\n",
+       "            fig.send_message('set_device_pixel_ratio', {\n",
+       "                device_pixel_ratio: fig.ratio,\n",
+       "            });\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 = document.createElement('div');\n",
+       "    titlebar.classList =\n",
+       "        'ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix';\n",
+       "    var titletext = document.createElement('div');\n",
+       "    titletext.classList = 'ui-dialog-title';\n",
+       "    titletext.setAttribute(\n",
+       "        'style',\n",
+       "        'width: 100%; text-align: center; padding: 3px;'\n",
+       "    );\n",
+       "    titlebar.appendChild(titletext);\n",
+       "    this.root.appendChild(titlebar);\n",
+       "    this.header = titletext;\n",
+       "};\n",
+       "\n",
+       "mpl.figure.prototype._canvas_extra_style = function (_canvas_div) {};\n",
+       "\n",
+       "mpl.figure.prototype._root_extra_style = function (_canvas_div) {};\n",
+       "\n",
+       "mpl.figure.prototype._init_canvas = function () {\n",
+       "    var fig = this;\n",
+       "\n",
+       "    var canvas_div = (this.canvas_div = document.createElement('div'));\n",
+       "    canvas_div.setAttribute(\n",
+       "        'style',\n",
+       "        'border: 1px solid #ddd;' +\n",
+       "            'box-sizing: content-box;' +\n",
+       "            'clear: both;' +\n",
+       "            'min-height: 1px;' +\n",
+       "            'min-width: 1px;' +\n",
+       "            'outline: 0;' +\n",
+       "            'overflow: hidden;' +\n",
+       "            'position: relative;' +\n",
+       "            'resize: both;'\n",
+       "    );\n",
+       "\n",
+       "    function on_keyboard_event_closure(name) {\n",
+       "        return function (event) {\n",
+       "            return fig.key_event(event, name);\n",
+       "        };\n",
+       "    }\n",
+       "\n",
+       "    canvas_div.addEventListener(\n",
+       "        'keydown',\n",
+       "        on_keyboard_event_closure('key_press')\n",
+       "    );\n",
+       "    canvas_div.addEventListener(\n",
+       "        'keyup',\n",
+       "        on_keyboard_event_closure('key_release')\n",
+       "    );\n",
+       "\n",
+       "    this._canvas_extra_style(canvas_div);\n",
+       "    this.root.appendChild(canvas_div);\n",
+       "\n",
+       "    var canvas = (this.canvas = document.createElement('canvas'));\n",
+       "    canvas.classList.add('mpl-canvas');\n",
+       "    canvas.setAttribute('style', 'box-sizing: content-box;');\n",
+       "\n",
+       "    this.context = canvas.getContext('2d');\n",
+       "\n",
+       "    var backingStore =\n",
+       "        this.context.backingStorePixelRatio ||\n",
+       "        this.context.webkitBackingStorePixelRatio ||\n",
+       "        this.context.mozBackingStorePixelRatio ||\n",
+       "        this.context.msBackingStorePixelRatio ||\n",
+       "        this.context.oBackingStorePixelRatio ||\n",
+       "        this.context.backingStorePixelRatio ||\n",
+       "        1;\n",
+       "\n",
+       "    this.ratio = (window.devicePixelRatio || 1) / backingStore;\n",
+       "\n",
+       "    var rubberband_canvas = (this.rubberband_canvas = document.createElement(\n",
+       "        'canvas'\n",
+       "    ));\n",
+       "    rubberband_canvas.setAttribute(\n",
+       "        'style',\n",
+       "        'box-sizing: content-box; position: absolute; left: 0; top: 0; z-index: 1;'\n",
+       "    );\n",
+       "\n",
+       "    // Apply a ponyfill if ResizeObserver is not implemented by browser.\n",
+       "    if (this.ResizeObserver === undefined) {\n",
+       "        if (window.ResizeObserver !== undefined) {\n",
+       "            this.ResizeObserver = window.ResizeObserver;\n",
+       "        } else {\n",
+       "            var obs = _JSXTOOLS_RESIZE_OBSERVER({});\n",
+       "            this.ResizeObserver = obs.ResizeObserver;\n",
+       "        }\n",
+       "    }\n",
+       "\n",
+       "    this.resizeObserverInstance = new this.ResizeObserver(function (entries) {\n",
+       "        var nentries = entries.length;\n",
+       "        for (var i = 0; i < nentries; i++) {\n",
+       "            var entry = entries[i];\n",
+       "            var width, height;\n",
+       "            if (entry.contentBoxSize) {\n",
+       "                if (entry.contentBoxSize instanceof Array) {\n",
+       "                    // Chrome 84 implements new version of spec.\n",
+       "                    width = entry.contentBoxSize[0].inlineSize;\n",
+       "                    height = entry.contentBoxSize[0].blockSize;\n",
+       "                } else {\n",
+       "                    // Firefox implements old version of spec.\n",
+       "                    width = entry.contentBoxSize.inlineSize;\n",
+       "                    height = entry.contentBoxSize.blockSize;\n",
+       "                }\n",
+       "            } else {\n",
+       "                // Chrome <84 implements even older version of spec.\n",
+       "                width = entry.contentRect.width;\n",
+       "                height = entry.contentRect.height;\n",
+       "            }\n",
+       "\n",
+       "            // Keep the size of the canvas and rubber band canvas in sync with\n",
+       "            // the canvas container.\n",
+       "            if (entry.devicePixelContentBoxSize) {\n",
+       "                // Chrome 84 implements new version of spec.\n",
+       "                canvas.setAttribute(\n",
+       "                    'width',\n",
+       "                    entry.devicePixelContentBoxSize[0].inlineSize\n",
+       "                );\n",
+       "                canvas.setAttribute(\n",
+       "                    'height',\n",
+       "                    entry.devicePixelContentBoxSize[0].blockSize\n",
+       "                );\n",
+       "            } else {\n",
+       "                canvas.setAttribute('width', width * fig.ratio);\n",
+       "                canvas.setAttribute('height', height * fig.ratio);\n",
+       "            }\n",
+       "            canvas.setAttribute(\n",
+       "                'style',\n",
+       "                'width: ' + width + 'px; height: ' + height + 'px;'\n",
+       "            );\n",
+       "\n",
+       "            rubberband_canvas.setAttribute('width', width);\n",
+       "            rubberband_canvas.setAttribute('height', height);\n",
+       "\n",
+       "            // And update the size in Python. We ignore the initial 0/0 size\n",
+       "            // that occurs as the element is placed into the DOM, which should\n",
+       "            // otherwise not happen due to the minimum size styling.\n",
+       "            if (fig.ws.readyState == 1 && width != 0 && height != 0) {\n",
+       "                fig.request_resize(width, height);\n",
+       "            }\n",
+       "        }\n",
+       "    });\n",
+       "    this.resizeObserverInstance.observe(canvas_div);\n",
+       "\n",
+       "    function on_mouse_event_closure(name) {\n",
+       "        return function (event) {\n",
+       "            return fig.mouse_event(event, name);\n",
+       "        };\n",
+       "    }\n",
+       "\n",
+       "    rubberband_canvas.addEventListener(\n",
+       "        'mousedown',\n",
+       "        on_mouse_event_closure('button_press')\n",
+       "    );\n",
+       "    rubberband_canvas.addEventListener(\n",
+       "        'mouseup',\n",
+       "        on_mouse_event_closure('button_release')\n",
+       "    );\n",
+       "    rubberband_canvas.addEventListener(\n",
+       "        'dblclick',\n",
+       "        on_mouse_event_closure('dblclick')\n",
+       "    );\n",
+       "    // Throttle sequential mouse events to 1 every 20ms.\n",
+       "    rubberband_canvas.addEventListener(\n",
+       "        'mousemove',\n",
+       "        on_mouse_event_closure('motion_notify')\n",
+       "    );\n",
+       "\n",
+       "    rubberband_canvas.addEventListener(\n",
+       "        'mouseenter',\n",
+       "        on_mouse_event_closure('figure_enter')\n",
+       "    );\n",
+       "    rubberband_canvas.addEventListener(\n",
+       "        'mouseleave',\n",
+       "        on_mouse_event_closure('figure_leave')\n",
+       "    );\n",
+       "\n",
+       "    canvas_div.addEventListener('wheel', function (event) {\n",
+       "        if (event.deltaY < 0) {\n",
+       "            event.step = 1;\n",
+       "        } else {\n",
+       "            event.step = -1;\n",
+       "        }\n",
+       "        on_mouse_event_closure('scroll')(event);\n",
+       "    });\n",
+       "\n",
+       "    canvas_div.appendChild(canvas);\n",
+       "    canvas_div.appendChild(rubberband_canvas);\n",
+       "\n",
+       "    this.rubberband_context = rubberband_canvas.getContext('2d');\n",
+       "    this.rubberband_context.strokeStyle = '#000000';\n",
+       "\n",
+       "    this._resize_canvas = function (width, height, forward) {\n",
+       "        if (forward) {\n",
+       "            canvas_div.style.width = width + 'px';\n",
+       "            canvas_div.style.height = height + 'px';\n",
+       "        }\n",
+       "    };\n",
+       "\n",
+       "    // Disable right mouse context menu.\n",
+       "    this.rubberband_canvas.addEventListener('contextmenu', function (_e) {\n",
+       "        event.preventDefault();\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 toolbar = document.createElement('div');\n",
+       "    toolbar.classList = 'mpl-toolbar';\n",
+       "    this.root.appendChild(toolbar);\n",
+       "\n",
+       "    function on_click_closure(name) {\n",
+       "        return function (_event) {\n",
+       "            return fig.toolbar_button_onclick(name);\n",
+       "        };\n",
+       "    }\n",
+       "\n",
+       "    function on_mouseover_closure(tooltip) {\n",
+       "        return function (event) {\n",
+       "            if (!event.currentTarget.disabled) {\n",
+       "                return fig.toolbar_button_onmouseover(tooltip);\n",
+       "            }\n",
+       "        };\n",
+       "    }\n",
+       "\n",
+       "    fig.buttons = {};\n",
+       "    var buttonGroup = document.createElement('div');\n",
+       "    buttonGroup.classList = 'mpl-button-group';\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",
+       "            /* Instead of a spacer, we start a new button group. */\n",
+       "            if (buttonGroup.hasChildNodes()) {\n",
+       "                toolbar.appendChild(buttonGroup);\n",
+       "            }\n",
+       "            buttonGroup = document.createElement('div');\n",
+       "            buttonGroup.classList = 'mpl-button-group';\n",
+       "            continue;\n",
+       "        }\n",
+       "\n",
+       "        var button = (fig.buttons[name] = document.createElement('button'));\n",
+       "        button.classList = 'mpl-widget';\n",
+       "        button.setAttribute('role', 'button');\n",
+       "        button.setAttribute('aria-disabled', 'false');\n",
+       "        button.addEventListener('click', on_click_closure(method_name));\n",
+       "        button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n",
+       "\n",
+       "        var icon_img = document.createElement('img');\n",
+       "        icon_img.src = '_images/' + image + '.png';\n",
+       "        icon_img.srcset = '_images/' + image + '_large.png 2x';\n",
+       "        icon_img.alt = tooltip;\n",
+       "        button.appendChild(icon_img);\n",
+       "\n",
+       "        buttonGroup.appendChild(button);\n",
+       "    }\n",
+       "\n",
+       "    if (buttonGroup.hasChildNodes()) {\n",
+       "        toolbar.appendChild(buttonGroup);\n",
+       "    }\n",
+       "\n",
+       "    var fmt_picker = document.createElement('select');\n",
+       "    fmt_picker.classList = 'mpl-widget';\n",
+       "    toolbar.appendChild(fmt_picker);\n",
+       "    this.format_dropdown = fmt_picker;\n",
+       "\n",
+       "    for (var ind in mpl.extensions) {\n",
+       "        var fmt = mpl.extensions[ind];\n",
+       "        var option = document.createElement('option');\n",
+       "        option.selected = fmt === mpl.default_extension;\n",
+       "        option.innerHTML = fmt;\n",
+       "        fmt_picker.appendChild(option);\n",
+       "    }\n",
+       "\n",
+       "    var status_bar = document.createElement('span');\n",
+       "    status_bar.classList = 'mpl-message';\n",
+       "    toolbar.appendChild(status_bar);\n",
+       "    this.message = status_bar;\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",
+       "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",
+       "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], msg['forward']);\n",
+       "        fig.send_message('refresh', {});\n",
+       "    }\n",
+       "};\n",
+       "\n",
+       "mpl.figure.prototype.handle_rubberband = function (fig, msg) {\n",
+       "    var x0 = msg['x0'] / fig.ratio;\n",
+       "    var y0 = (fig.canvas.height - msg['y0']) / fig.ratio;\n",
+       "    var x1 = msg['x1'] / fig.ratio;\n",
+       "    var y1 = (fig.canvas.height - msg['y1']) / fig.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,\n",
+       "        0,\n",
+       "        fig.canvas.width / fig.ratio,\n",
+       "        fig.canvas.height / fig.ratio\n",
+       "    );\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",
+       "    fig.rubberband_canvas.style.cursor = msg['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.handle_history_buttons = function (fig, msg) {\n",
+       "    for (var key in msg) {\n",
+       "        if (!(key in fig.buttons)) {\n",
+       "            continue;\n",
+       "        }\n",
+       "        fig.buttons[key].disabled = !msg[key];\n",
+       "        fig.buttons[key].setAttribute('aria-disabled', !msg[key]);\n",
+       "    }\n",
+       "};\n",
+       "\n",
+       "mpl.figure.prototype.handle_navigate_mode = function (fig, msg) {\n",
+       "    if (msg['mode'] === 'PAN') {\n",
+       "        fig.buttons['Pan'].classList.add('active');\n",
+       "        fig.buttons['Zoom'].classList.remove('active');\n",
+       "    } else if (msg['mode'] === 'ZOOM') {\n",
+       "        fig.buttons['Pan'].classList.remove('active');\n",
+       "        fig.buttons['Zoom'].classList.add('active');\n",
+       "    } else {\n",
+       "        fig.buttons['Pan'].classList.remove('active');\n",
+       "        fig.buttons['Zoom'].classList.remove('active');\n",
+       "    }\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",
+       "            var img = evt.data;\n",
+       "            if (img.type !== 'image/png') {\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",
+       "                img.type = 'image/png';\n",
+       "            }\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",
+       "\n",
+       "            fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
+       "                img\n",
+       "            );\n",
+       "            fig.updated_canvas_event();\n",
+       "            fig.waiting = false;\n",
+       "            return;\n",
+       "        } else if (\n",
+       "            typeof evt.data === 'string' &&\n",
+       "            evt.data.slice(0, 21) === 'data:image/png;base64'\n",
+       "        ) {\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(\n",
+       "                \"No handler for the '\" + msg_type + \"' message type: \",\n",
+       "                msg\n",
+       "            );\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(\n",
+       "                    \"Exception inside the 'handler_\" + msg_type + \"' callback:\",\n",
+       "                    e,\n",
+       "                    e.stack,\n",
+       "                    msg\n",
+       "                );\n",
+       "            }\n",
+       "        }\n",
+       "    };\n",
+       "};\n",
+       "\n",
+       "// from https://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",
+       "    }\n",
+       "    if (e.target) {\n",
+       "        targ = e.target;\n",
+       "    } else if (e.srcElement) {\n",
+       "        targ = e.srcElement;\n",
+       "    }\n",
+       "    if (targ.nodeType === 3) {\n",
+       "        // defeat Safari bug\n",
+       "        targ = targ.parentNode;\n",
+       "    }\n",
+       "\n",
+       "    // pageX,Y are the mouse positions relative to the document\n",
+       "    var boundingRect = targ.getBoundingClientRect();\n",
+       "    var x = e.pageX - (boundingRect.left + document.body.scrollLeft);\n",
+       "    var y = e.pageY - (boundingRect.top + document.body.scrollTop);\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",
+       " * https://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",
+       "        }\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",
+       "        this.canvas.focus();\n",
+       "        this.canvas_div.focus();\n",
+       "    }\n",
+       "\n",
+       "    var x = canvas_pos.x * this.ratio;\n",
+       "    var y = canvas_pos.y * this.ratio;\n",
+       "\n",
+       "    this.send_message(name, {\n",
+       "        x: x,\n",
+       "        y: y,\n",
+       "        button: event.button,\n",
+       "        step: event.step,\n",
+       "        guiEvent: simpleKeys(event),\n",
+       "    });\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",
+       "    // Prevent repeat events\n",
+       "    if (name === 'key_press') {\n",
+       "        if (event.key === this._key) {\n",
+       "            return;\n",
+       "        } else {\n",
+       "            this._key = event.key;\n",
+       "        }\n",
+       "    }\n",
+       "    if (name === 'key_release') {\n",
+       "        this._key = null;\n",
+       "    }\n",
+       "\n",
+       "    var value = '';\n",
+       "    if (event.ctrlKey && event.key !== 'Control') {\n",
+       "        value += 'ctrl+';\n",
+       "    }\n",
+       "    else if (event.altKey && event.key !== 'Alt') {\n",
+       "        value += 'alt+';\n",
+       "    }\n",
+       "    else if (event.shiftKey && event.key !== 'Shift') {\n",
+       "        value += 'shift+';\n",
+       "    }\n",
+       "\n",
+       "    value += 'k' + event.key;\n",
+       "\n",
+       "    this._key_event_extra(event, name);\n",
+       "\n",
+       "    this.send_message(name, { key: value, 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",
+       "\n",
+       "///////////////// REMAINING CONTENT GENERATED BY embed_js.py /////////////////\n",
+       "// prettier-ignore\n",
+       "var _JSXTOOLS_RESIZE_OBSERVER=function(A){var t,i=new WeakMap,n=new WeakMap,a=new WeakMap,r=new WeakMap,o=new Set;function s(e){if(!(this instanceof s))throw new TypeError(\"Constructor requires 'new' operator\");i.set(this,e)}function h(){throw new TypeError(\"Function is not a constructor\")}function c(e,t,i,n){e=0 in arguments?Number(arguments[0]):0,t=1 in arguments?Number(arguments[1]):0,i=2 in arguments?Number(arguments[2]):0,n=3 in arguments?Number(arguments[3]):0,this.right=(this.x=this.left=e)+(this.width=i),this.bottom=(this.y=this.top=t)+(this.height=n),Object.freeze(this)}function d(){t=requestAnimationFrame(d);var s=new WeakMap,p=new Set;o.forEach((function(t){r.get(t).forEach((function(i){var r=t instanceof window.SVGElement,o=a.get(t),d=r?0:parseFloat(o.paddingTop),f=r?0:parseFloat(o.paddingRight),l=r?0:parseFloat(o.paddingBottom),u=r?0:parseFloat(o.paddingLeft),g=r?0:parseFloat(o.borderTopWidth),m=r?0:parseFloat(o.borderRightWidth),w=r?0:parseFloat(o.borderBottomWidth),b=u+f,F=d+l,v=(r?0:parseFloat(o.borderLeftWidth))+m,W=g+w,y=r?0:t.offsetHeight-W-t.clientHeight,E=r?0:t.offsetWidth-v-t.clientWidth,R=b+v,z=F+W,M=r?t.width:parseFloat(o.width)-R-E,O=r?t.height:parseFloat(o.height)-z-y;if(n.has(t)){var k=n.get(t);if(k[0]===M&&k[1]===O)return}n.set(t,[M,O]);var S=Object.create(h.prototype);S.target=t,S.contentRect=new c(u,d,M,O),s.has(i)||(s.set(i,[]),p.add(i)),s.get(i).push(S)}))})),p.forEach((function(e){i.get(e).call(e,s.get(e),e)}))}return s.prototype.observe=function(i){if(i instanceof window.Element){r.has(i)||(r.set(i,new Set),o.add(i),a.set(i,window.getComputedStyle(i)));var n=r.get(i);n.has(this)||n.add(this),cancelAnimationFrame(t),t=requestAnimationFrame(d)}},s.prototype.unobserve=function(i){if(i instanceof window.Element&&r.has(i)){var n=r.get(i);n.has(this)&&(n.delete(this),n.size||(r.delete(i),o.delete(i))),n.size||r.delete(i),o.size||cancelAnimationFrame(t)}},A.DOMRectReadOnly=c,A.ResizeObserver=s,A.ResizeObserverEntry=h,A}; // eslint-disable-line\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\", \"Left button pans, Right button zooms\\nx/y fixes axis, CTRL fixes aspect\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\\nx/y fixes axis\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n",
+       "\n",
+       "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
+       "\n",
+       "mpl.default_extension = \"png\";/* global mpl */\n",
+       "\n",
+       "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.binaryType = comm.kernel.ws.binaryType;\n",
+       "    ws.readyState = comm.kernel.ws.readyState;\n",
+       "    function updateReadyState(_event) {\n",
+       "        if (comm.kernel.ws) {\n",
+       "            ws.readyState = comm.kernel.ws.readyState;\n",
+       "        } else {\n",
+       "            ws.readyState = 3; // Closed state.\n",
+       "        }\n",
+       "    }\n",
+       "    comm.kernel.ws.addEventListener('open', updateReadyState);\n",
+       "    comm.kernel.ws.addEventListener('close', updateReadyState);\n",
+       "    comm.kernel.ws.addEventListener('error', updateReadyState);\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",
+       "        var data = msg['content']['data'];\n",
+       "        if (data['blob'] !== undefined) {\n",
+       "            data = {\n",
+       "                data: new Blob(msg['buffers'], { type: data['blob'] }),\n",
+       "            };\n",
+       "        }\n",
+       "        // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
+       "        ws.onmessage(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 = document.getElementById(id);\n",
+       "    var ws_proxy = comm_websocket_adapter(comm);\n",
+       "\n",
+       "    function ondownload(figure, _format) {\n",
+       "        window.open(figure.canvas.toDataURL());\n",
+       "    }\n",
+       "\n",
+       "    var fig = new mpl.figure(id, ws_proxy, ondownload, element);\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;\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",
+       "    fig.cell_info[0].output_area.element.on(\n",
+       "        'cleared',\n",
+       "        { fig: fig },\n",
+       "        fig._remove_fig_handler\n",
+       "    );\n",
+       "};\n",
+       "\n",
+       "mpl.figure.prototype.handle_close = function (fig, msg) {\n",
+       "    var width = fig.canvas.width / fig.ratio;\n",
+       "    fig.cell_info[0].output_area.element.off(\n",
+       "        'cleared',\n",
+       "        fig._remove_fig_handler\n",
+       "    );\n",
+       "    fig.resizeObserverInstance.unobserve(fig.canvas_div);\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.innerHTML =\n",
+       "        '<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 / this.ratio;\n",
+       "    var dataURL = this.canvas.toDataURL();\n",
+       "    this.cell_info[1]['text/html'] =\n",
+       "        '<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 () {\n",
+       "        fig.push_to_output();\n",
+       "    }, 1000);\n",
+       "};\n",
+       "\n",
+       "mpl.figure.prototype._init_toolbar = function () {\n",
+       "    var fig = this;\n",
+       "\n",
+       "    var toolbar = document.createElement('div');\n",
+       "    toolbar.classList = 'btn-toolbar';\n",
+       "    this.root.appendChild(toolbar);\n",
+       "\n",
+       "    function on_click_closure(name) {\n",
+       "        return function (_event) {\n",
+       "            return fig.toolbar_button_onclick(name);\n",
+       "        };\n",
+       "    }\n",
+       "\n",
+       "    function on_mouseover_closure(tooltip) {\n",
+       "        return function (event) {\n",
+       "            if (!event.currentTarget.disabled) {\n",
+       "                return fig.toolbar_button_onmouseover(tooltip);\n",
+       "            }\n",
+       "        };\n",
+       "    }\n",
+       "\n",
+       "    fig.buttons = {};\n",
+       "    var buttonGroup = document.createElement('div');\n",
+       "    buttonGroup.classList = 'btn-group';\n",
+       "    var button;\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",
+       "            /* Instead of a spacer, we start a new button group. */\n",
+       "            if (buttonGroup.hasChildNodes()) {\n",
+       "                toolbar.appendChild(buttonGroup);\n",
+       "            }\n",
+       "            buttonGroup = document.createElement('div');\n",
+       "            buttonGroup.classList = 'btn-group';\n",
+       "            continue;\n",
+       "        }\n",
+       "\n",
+       "        button = fig.buttons[name] = document.createElement('button');\n",
+       "        button.classList = 'btn btn-default';\n",
+       "        button.href = '#';\n",
+       "        button.title = name;\n",
+       "        button.innerHTML = '<i class=\"fa ' + image + ' fa-lg\"></i>';\n",
+       "        button.addEventListener('click', on_click_closure(method_name));\n",
+       "        button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n",
+       "        buttonGroup.appendChild(button);\n",
+       "    }\n",
+       "\n",
+       "    if (buttonGroup.hasChildNodes()) {\n",
+       "        toolbar.appendChild(buttonGroup);\n",
+       "    }\n",
+       "\n",
+       "    // Add the status bar.\n",
+       "    var status_bar = document.createElement('span');\n",
+       "    status_bar.classList = 'mpl-message pull-right';\n",
+       "    toolbar.appendChild(status_bar);\n",
+       "    this.message = status_bar;\n",
+       "\n",
+       "    // Add the close button to the window.\n",
+       "    var buttongrp = document.createElement('div');\n",
+       "    buttongrp.classList = 'btn-group inline pull-right';\n",
+       "    button = document.createElement('button');\n",
+       "    button.classList = 'btn btn-mini btn-primary';\n",
+       "    button.href = '#';\n",
+       "    button.title = 'Stop Interaction';\n",
+       "    button.innerHTML = '<i class=\"fa fa-power-off icon-remove icon-large\"></i>';\n",
+       "    button.addEventListener('click', function (_evt) {\n",
+       "        fig.handle_close(fig, {});\n",
+       "    });\n",
+       "    button.addEventListener(\n",
+       "        'mouseover',\n",
+       "        on_mouseover_closure('Stop Interaction')\n",
+       "    );\n",
+       "    buttongrp.appendChild(button);\n",
+       "    var titlebar = this.root.querySelector('.ui-dialog-titlebar');\n",
+       "    titlebar.insertBefore(buttongrp, titlebar.firstChild);\n",
+       "};\n",
+       "\n",
+       "mpl.figure.prototype._remove_fig_handler = function (event) {\n",
+       "    var fig = event.data.fig;\n",
+       "    if (event.target !== this) {\n",
+       "        // Ignore bubbled events from children.\n",
+       "        return;\n",
+       "    }\n",
+       "    fig.close_ws(fig, {});\n",
+       "};\n",
+       "\n",
+       "mpl.figure.prototype._root_extra_style = function (el) {\n",
+       "    el.style.boxSizing = 'content-box'; // override notebook setting of border-box.\n",
+       "};\n",
+       "\n",
+       "mpl.figure.prototype._canvas_extra_style = function (el) {\n",
+       "    // this is important to make the div 'focusable\n",
+       "    el.setAttribute('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",
+       "    } else {\n",
+       "        // location in version 2\n",
+       "        IPython.keyboard_manager.register_events(el);\n",
+       "    }\n",
+       "};\n",
+       "\n",
+       "mpl.figure.prototype._key_event_extra = function (event, _name) {\n",
+       "    // Check for shift+enter\n",
+       "    if (event.shiftKey && event.which === 13) {\n",
+       "        this.canvas_div.blur();\n",
+       "        // select the cell after this one\n",
+       "        var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n",
+       "        IPython.notebook.select(index + 1);\n",
+       "    }\n",
+       "};\n",
+       "\n",
+       "mpl.figure.prototype.handle_save = function (fig, _msg) {\n",
+       "    fig.ondownload(fig, null);\n",
+       "};\n",
+       "\n",
+       "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(\n",
+       "        'matplotlib',\n",
+       "        mpl.mpl_figure_comm\n",
+       "    );\n",
+       "}\n"
+      ],
+      "text/plain": [
+       "<IPython.core.display.Javascript object>"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "text/html": [
+       "<img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA38AAAHACAYAAAAStNEGAAAgAElEQVR4XuydCbyVc/7Hvy2otCihiBokzIw1RnaiVaRsGWRokYwYJjOYkmikkSWyhSSZmsaShGhqTJIlhiH/KaUoJSo0ab31/31+3U9+PT1nucu595xzP4/X87rnnOf3/Jb377nX+fTdKpnZZnfqEAEREAEREAEREAEREAEREAERyGMClST+8nh3tTQREAEREAEREAEREAEREAERKCQg8adHQQREQAREQAREQAREQAREQAQqAAGJvwqwyVqiCIiACIiACIiACIiACIiACEj86RkQAREQAREQAREQAREQAREQgQpAQOKvAmyyligCIiACIiACIiACIiACIiACEn96BkRABERABERABERABERABESgAhCQ+KsAm6wlioAIiIAIiIAIiIAIiIAIiIDEn54BERABERABERABERABERABEagABCT+KsAma4kiIAIiIAIiIAIiIAIiIAIiIPGnZ0AEREAEREAEREAEREAEREAEKgABib8KsMlaogiIgAiIgAiIgAiIgAiIgAhI/OkZEAEREAEREAEREAEREAEREIEKQEDirwJsspYoAiIgAiIgAiIgAiIgAiIgAhJ/egZEQAREQAREQAREQAREQAREoAIQkPirAJusJYqACIiACIiACIiACIiACIiAxJ+eAREQAREQAREQAREQAREQARGoAAQk/irAJmuJIiACIiACIiACIiACIiACIiDxp2dABERABERABERABERABERABCoAAYm/CrDJWqIIiIAIiIAIiIAIiIAIiIAISPzpGRABERABERABERABERABERCBCkBA4q8CbLKWKAIiIAIiIAIiIAIiIAIiIAISf3oGREAEREAEREAEREAEREAERKACEJD4qwCbrCWKgAiIgAiIgAiIgAiIgAiIgMSfngEREAEREAEREAEREAEREAERqAAEJP4qwCZriSIgAiIgAiIgAiIgApkj0LVrV5s8ebItWbLED9K7d2+75pprbP/997f69evb8uXLizV4tN/Ro0db8+bNbcOGDfbOO+9Yz549bePGjaXS94gRI3zflSpVsjlz5till15qq1evLnLf0Tmzg3vvvdcuu+wyq1WrVpH71A2lR0Dir/RYqicREAEREAEREAEREIEKSGDq1Kl2/fXX26xZs/zqDzvsMFu5cqVNmzbNC6riir9ov23btrWXX37ZjzFmzBh744037KGHHioW8WjfEGWrVq3yfd111122bNkyGzx4cJH7jvaLDo488kjr06ePnX322RJ/RSZaujdI/JUuT/UmAiIgAiIgAiIgAiKQBwRq1Khh48aNs0aNGlmVKlVs4MCB1qxZM+vQoYNVr17dZsyY4S1vnTt3tpEjR9rixYttzZo11qJFC1u7dq0n8Pnnn28n/kqjX/QNyyKsijfffPNW2qXV9/Dhw23BggV25513+r5L0u/69evt9ddftwsvvNDmzp0r8VfOvxsSf+W8ARpeBERABERABERABEQg+wh06tTJ2rRpYz169PCTq127theBsOjhGDVqlBeHEydOtDhrVyLxVxr9Vq1a1d5++21vTZs+ffpWeCXt+/HHH7d27drZ7NmzrX379l7M4ihJv1dffbVVrlzZ7rnnHm9ZlNtn+T7rEn/ly1+ji4AIiIAIiIAIiIAIZCGBpk2b+ji+sWPHeoEHkQUR1LdvX28Jq1evng0bNsy7RhZF/JVGv4888oiPx7v22mu3IVcafUOoYV3vvvuut2jiKG6/DRs29AL55JNPtoKCAom/LHjOJf6yYBM0BREQAREQAREQAREQgewjULduXW8J6969u02ZMsUnckEM36JFi6x///5+wgMGDCiS+MM9Jem3X79+dvjhh3shunnz5u2glaRvdnbCCSd4kQsXVx7F6RfsHnvssa1usPvss4/Nnz/fi0kd5UNA4q98uGtUERABERABERABERCBLCYAq9WKFSts3bp13gWyW7duPp6vSZMm3v1z5syZNn78eC/+JkyYYEOHDvUJXsIjLuavJP1efvnlPmNmy5YttwqqcLyS9L3ffvvZvHnzfHdDhgzxP3//+9/7nyXpN5yf3D7L/4GX+Cv/PdAMREAEREAEREAEREAEsoxAq1atvAjatGmTL63Qq1cv69ixo3Xp0sWWLl3qyyEsXLjQiz9Y4QYNGrQ14QsshbCcNWjQwGfNnDRpkrce4ihJvxBPGJNZOZ999lmfiIZHcfs+7rjjvIsr4hpR6uHDDz/06+U4xe03TH6DOUr8lf9DLvFX/nugGYiACIiACIiACIiACIiACIhAxglI/GUcsQYQAREQAREQAREQAREQAREQgfInIPFX/nugGYiACIiACIiACIiACIiACIhAxglI/GUcsQYQAREQAREQAREQAREQAREQgfInIPFX/nugGYiACIiACIiACIiACIiACIhAxglI/GUcsQYQAREQAREQAREQAREQAREQgfInIPFX/nugGYiACIiACIiACIiACIiACJQygQsvvNB69uxpJ510Uin3vH13TzzxhH377bdbayNmfMBiDiDxV0xwuk0EREAEREAEREAEREAE+vXrZ7feemtGQGSq71zrNyNwS7lTib9SBqruREAEREAEREAEREAERCDbCBQUFFiVKlUyMq1M9Z1r/WYEbil3KvFXykDVnQiIgAiIgAiIgAiIgAhkG4FMCSmsM1N951q/6ez5ddddZ3369LFddtnFvvnmG7vxxhutWrVqdtVVV9lRRx3lu/jlL39pI0aMsIMOOsjefPNNmzt3rjVs2NDOPfdca9y4sS1YsMAuueQSu+WWW6xevXr2zDPP2JVXXunvrVWrlo0ePdqOOeYY23HHHW3WrFn+2pw5c/x1ib90dkltREAEREAEREAEREAERCCHCWRKSEn8pf9QHHDAAfbBBx/Y4Ycf7sVYgwYNrG7dunb00UdvFX9Vq1b11yD+7rzzTi/iJk6caK+99to24u/pp5/2cYK77rqrvffee3b55Zfbiy++aHXq1LHTTz/dJk2aZJs3b7Z7773XDjvsMD+GxF/6e6WWIiACIiACIiACIiACIpBVBDZt2uS/4Jf6UbnUe8zZDitZJatcaVsg8zfPt8buPx7fr/zeiy4eAwYMiI2v3Hfffe3jjz82JHh55ZVXbO3atf6Wrl27bhV/J5xwgj333HO2++67G/YXx1NPPeWtg6Hlb//997d58+b562PHjrXZs2cbxo0ee+21ly1atMh23nln+/HHH2X5y9knURMXAREQAREQAREQARGo0AQyZs3LgJ7M1Y0qMBcrWWnbWMmCze4z9x+Pgk3px1Oed9553g0T1r9//etfBjdQWPfo9nn++efbTTfdZIcccsjW/gcNGmRNmzbdRvzVrFnTVq9e7duErpzVq1e3u+++21q3bu1dQiEg4WIKd9EvvvhC4i9XH0TNWwREQAREQAREQAREoGITkPjL/P6XtvjjjGvUqOHdOiHyHnvssW0sf88++6ztscceSS1/icTfzTffbG3btvVC8auvvjJa/po0aWILFy6U+Mv8I6MRREAEREAEREAEREAERKD0CUj8lT7TaI+lKf4Q87f33nvb9OnTbePGjQaLHmLxRo4cuU3M32effWYPPvig3XXXXf464veiMX+JxN/gwYPtyCOPtA4dOhjiB++77z679NJLTeIv88+KRhABERABERABERABERCBjBGQ+MsY2q0dl6b4QxbPRx991A4++GCfIfX999/3LqCh2ycGPvTQQ33ClwMPPNBn+0R2T4i9iy66aGu2z0TiDxZDZP9E5tCvv/7aBg4c6MWlxF/mnxWNIAIiIAIiIAIiIAIiIAIZIyDxlzG0GRF/xZ3tX//6V/v888/tj3/8Y3G7yLn7KrkZK/Q057ZNExYBERABERABERABEcgUAYm/TJH9qd/StPylO1tk/Jw/f74tWbLEJ25B9k989u6776bbRc63k/jL+S3UAkRABERABERABERABJDWf/Lkyf6LPY7evXvbNddcY0jdX79+fVu+fHnakCT+0kZV7IblIf5+85vf2G233ebLR3z55Zc+MQwyelakQ+KvIu221ioCIiACIiACIiACeUpg6tSpdv3119usWbP8ClGAe+XKlTZt2jRr3ry5xF+W7Xt5iL8sQ1Au05H4KxfsGlQEREAEREAEREAERCAVAaTtHzdunDVq1MiqVKnik2w0a9bMZ1xE3bUZM2ZYz549rXPnzj75xuLFi23NmjXWokWLrYW+EdMl8ZeKdNlfl/gre+YYUeKvfLhrVBEQAREQAREQAREQgRQEOnXqZG3atLEePXr4lrVr1/YiEBY9HKNGjfLicOLEiRa1/LFrib/sfMwk/spnXyT+yoe7RhUBERABERABERABEUhBoGnTpj6Ob+zYsV7goY4bBGHfvn0NVsF69erZsGHDDDXYSiL++vXrZ/37999mNhCZpX4ozeJWpBJ/pf50pdWhxF9amNRIBERABERABERABESgPAjUrVvX2rVrZ927d7cpU6b4RC5w41y0aNFWwTZgwIASib/oupTwJfM7LfGXecZxI0j8lQ93jSoCIiACIiACIiACIpCCQMOGDW3FihW2bt06a9++vXXr1s3H86GwNixzM2fOtPHjxxvE34QJE2zo0KE+wUt4yO0zOx8zib/y2ReJv/LhrlFFQAREQAREQAREQARSEGjVqpUNGTLENm3aZBs2bLBevXpZx44drUuXLrZ06VKbM2eOLVy40Is/uIMOGjRoa8IXWArhHtqgQQNb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QKtWrWzIkCG2adMm27Bhg/Xq1cs6duxoXbp0saVLl9qcOXNs4cKFXvzBHXTQoEFbE77Q6geQEn8leJwk/koAL/tulfjLvj3RjERABERABERABERABMqRgNw+A/gSf+X4JJb+0BJ/pc9UPYqACIiACIiACIiACOQwAYk/ib8cfnyTTl3iLzFqtzkAACAASURBVF93VusSAREQAREQAREQAREoFgGJP4m/Yj04OXCTxF8ObJKmKAIiIAIiIAIiIAIiUHYEJP4k/qJP2957722zZ8+2PfbYw3788ceMPoxdu3a1q666yo466qhSH0fir9SRqkMREAEREAEREAEREIFcJiDxJ/FXns+vxF950tfYIiACIiACIiACIiACFYqAxJ/EX3k+8BJ/5UlfY4uACIiACIiACIiACFQoAhJ/uSX+Pv/8c3vggQfsvPPOswMPPNDXf/z1r39t33zzjV8I3CfvvfdeO/jgg+3LL7+0m266ydeFjDtat27ty4ugluTq1avtqaeesr59+1rjxo1twYIFVrNmTf953bp1bcSIEdayZUvf58iRI+0Pf/iD7bbbbr7bVHP6y1/+Yueee67vB/3i3kmTJvl7Jf4q1J8bLVYERKA8CBzR4WKb+9brturbJX74Tv0etkYHH2lWqZJ9u3Cuje9/ua1fs7o8pqYxRUAEREAEypiAxF/uib/vv//ezjzzTC/4IKLef/99u+6662yXXXaxefPmecEHsXbKKafY888/b0cffbR98skn2z1ZX331lRd7o0ePtp133tl+/vOf2zvvvLOd+MP1WrVqeZEJATdx4kTbc889txF/ieaEQXHfq6++aitWrPBi77777rN9993Xz1/ir4x/4TWcCIhAxSPQ/ZHXbNLdN9jiT9/3i99p51q2bvUq/7r97+60/634xv45ckjFA6MVi4AIiEAFJICi8ps3b66AKy+7JVdy/7hauXLlbQacP3++F1k8IJ7q1Kmz9f2AAQPs1ltv3W6SsLLddttt9thjj/lrvXr18lZACD2IrBtuuMEOOeSQrfc988wz3jJ34403btcXrHCPP/64tyQuX7586/XQ8rdmzRrDCQH54Ycf+jaXX3653XHHHduIv0RziqM8d+5c69OnjxeuEn9l9xxqJBEQgTwisEO1Gnbh4DFWZ49GVqlyFfvHiEG2W+MD7KAT21vVnarbFx+9Zc/ddqX9omUnO2fACPth2Ve2Yd0ae/DSE2zjurVbSZz1x2G28quF9saTf8kjOlqKCIiACIhAaRAoKCiwKlWqlEZX2/WRqb5zrd9UcCHkkB3zpZde8k1D8QQr3vHHH++tgjz+/Oc/eysd2kWPww8/3G6++WYvHD/77DOD4ES/ofiD6+fSpUtt11139ZY7HK1atbKnn356G/GXaE5o/7vf/c4Lxr322sv/QwP6xPtRo0ZJ/KXacF0XAREQgTgCPz/1bDvg2FZO4PXyl3eqWdv9K2MVW/PDSv/+vIFP2Eevjbf/e+Mli1r+cL3zLY9as+Pa2LL5n9qTfc6yDWvXCLQIiIAIiIAIbEMgU0IKg2Sq71zrN9Ujl0z8FdXyx7Fglbzwwgvt0Ucf9SIPsXyM+UvX8pdI/EGMIubw1FNP9ZZDiD9Y/mApfPLJJyX+Um24rouACIhAHIH6+zS1y4a/ZB9NdgLvXy/Zgg/eNAjCk7peZ7AKVq9T197663Dvzhkn/tBnJffH/8y+99ii2e/ZrAmjBFoEREAEREAEJP4SPAOZEpWpHrlk4g/xeIj5g+sn3DlPPvlkL7x+9atf2ccff7xN1zvssIOdf/75Pn7vu+++sw4dOtjYsWN9TF+DBg22SfgyZswYq169ul188cXeNRX3NGrUKC3LX9u2bb3Ig5URFsQrrrjC7rnnHuvWrZvEX6rN1nUREAERSEageu261uz4tnbU2ZfZvHem2jHnXWEPXNTCvv96kbXs+Sd/65SHByYUf7je5IjjvWB8ss/Zgi0CIiACIiAC2xDo169fbBxaaWDKVN+51m8qlsnEH+6F0IO4Ouigg2zRokX2pz/9yZ577rntuoX4e+GFF3x7vIalD3GBEHbRbJ/16tXzMYZwD0W2T7h8wtIHAYgj2ZwQ7/jwww/7uERYEZGIpk2bNnb//fdL/KXabF0XAREQgUQEatVv6Fw8V9jG9evswBPaWfOOl9k+h/zK7jyjqXf/7PXkdPt4yrNe/F1yz3M2ffQ9Nv+9f/rudt17P1v+5Tz/uu01d/ifL9/zB8EWAREQAREQAREQge0IwHqHGMIWLVpkNZ1KbnZKZZTVW6TJiYAIFJdA0xane+G22WVt27Rxgz0/6Co7+JSz7NDW59mq5V/bt1/Mte+WfOHFH9xBW1810Cd8eeg3Jzl30UlWbefavtTD0jkf2fN/vmpr9s/izkf3iYAIiIAIiIAI5AeBAw44wJeC+OCDD3xtwRdffNEeeeQRXyMwmw+Jv2zeHc1NBERABERABERABERABEQg6wggXg8lI/bee2+f8ROxgXARXb9+fdbNNZyQxF9Wb48mJwIiIAIiIAIiIAIiIAIiIAKlQ0Dir3Q4qhcREAEREAEREAEREAEREAERyGoCEn9ZvT2anAiIgAiIgAiIgAiIgAiIgAiUDgGJv9LhqF5EQASylMDt766xpZ997PK2VLJNBQU2YXAf++KjmQlnW61mHTus7QU2828P+za7NGxsjQ9tYR++8teMrvCIDhf75DQ/LPvKj/PW2OH23vNPWP3GB9gFg0ZZ5ao72PO3X+nm/rZVrlLFfnP/RBt1bScVns/orqhzERABERABEcgvAhJ/+bWfWo0IiECEwC3TV9gtx9fznyL758mX3WCPdj8tISeIva73Pm/3nne4b/OzI0+0Ey+5trDGXzX3SZ3C02UCNZw1g3OTe13VibPNTmhudK/xnmeBe43P1rnze3eudOcKd37jzrUG8dfo4COdOL1mm7m1/92d9vE/nreVXy20Dr8fak///nxrcf6Vtu7HVfb+i09pv0VABERABERABEQgbQISf2mjUkMREIFcJBCKv1+c1tlZ9brY6OvOsR2r72wX3/13q16rrlVxVrXJw/vbp/980S7482g7+KQO9s3CBfbZ259YE5fNa/cme9mKr5zYmvipzXjmfWtz9fG275GNrMqOVWzmuFn2zt//7UTinnb6lSe7uoJrXPv69uGrH/vXb455x2Nr1ftk+9+K1e5+vEeFnSrurFz4c50Tf82c+NvNib+H3GffuhM1Bpe6sQa54vT/8OLvtF79nfWvt104eIw9cdUZtnmzKvXk4jOpOYuACIiACIhAeRGQ+Csv8hpXBESgTAjQ7bPqjtWsdv0G9ugVreyrTz/wrpM7VKvha/fV2KWZXfnkq/aXs/o7N8+DneXvYmf5e8aLNIi6Ey85wln+nvXzParTYVaz7s429bG3rcoOO9gVT5xrY/q+7O6rZpfe18nuOfcxJ9R+dO9r20V/6WD3//pp53JaYNc9392GXzLaibkT7e3xH9riTxe63mANhGVwoxN/h7s6g61t9Xer7duFy+2lu16x779eZnUarLfzbr3Uqu64yZ67vZsdccZF9ukbL9nns94oE34aRAREQAREQAREIH8ISPzlz15qJSIgAjEEQsvfPof8yjr96WEn0A5zMXSN7IzrhluTIw53ReCr2G6Nd7E7O4xxImtHJ/5aOfE30vVWxYm/Rk78He7E3yT3vrJdeGdra9h0V1u/Fi6cm61azR2dNW6abdywzlr2aGEjeo717XBcNryzvXzvG1Zr1x2tecfDnUicUDhDWOzWuHMHd+LPsFmNOtWcK+c6K9iw1o7ufJgd0uoXrq/HC9tv8CJx1713cRbE0+3FO4dYu2vPd+LT7LXht/hi9TpEQAREQAREQAREIBUBib9UhHRdBEQgpwmE4s+sod342odO2D1qzY5vbs2O28fG3vwP27Rxk/WdeKE90v05v9au97Z3bf7mX2+x/B1aKP7W26+HtLd3nv3U5r71ZSEXWO82uHb7uHZHunYv+PcQjr9sdYA1PqSB1apf08XnfWL/ffNz9/kW0YjYwC3xf/iJ91sEHu6rVLmq9Zt6rQ04aXDh5xCTBdbljgts8gOv25FnHu7Gn2Mrl8yz1r1buTVc4q4jdlCHCIiACIiACIiACCQmIPGnp0MERCCvCdwyfaVL+HK5W+OhtluTJtbzsbPt9tOfcUlTDnaWtNrOiva27dt8V+v+SAcb3H6srf9xtV015hy7s/1IL8b2PGgPa/+7E12SGLh9bnZunz93orGxjbnhOScazervs4t9v+x7a/TzPZz4O9aJPwjI9e7c0cUSVrI+4y51PyvbXzoOdxZGiD0IOQg+HGv9GHhfq34dW/Xtj+51JTv4lAPtpEtb2INdn3TvIS4L7GdH7OU+b+bcQV+y9td1sE/+8bFzL/3eJYHpYKOvR+KX5e6EuPzInUgmo0MEREAEREAEREAEtiUg8acnQgREIA8JNHBrOtGdP7fb373BlXr4zr3e7Ms9vHr/+/bf6YtcnN9O1vWeU13il6q26NNvbZ9f7u6SqLxk3y353s6/vZU1cK6dc2Z86dq/Y5c90Na5Ze5ks16cbTPGvG+n9z7WDjphP++xuXrlGnvqugm2Z7PdCi1/LxaKup28aOt4Yytbs2qdvTrsdfd+J+d2erqL+XvPxfwtde9h7dvyZ7j1VafYQSc1c1lCN9mP3/9oL/z5RftmAQTdFrfQy4ZfYs/84W8uicxy2+1ne9r5t53vXFcr2wuDJtjCDxE/COshhCQE5RJ3fubOT90JS6MOERABERABERABEeC3DpEQAREQgZwnUN+t4FR3HuZOvIbFDBY2WOHwmv/WBYGEA6IIpRvCz9E2+m9ieI8TfUBg7Vh4L+5nzN4q97q6OyHm8BksfDs6sbnWWREvd7F+z9ryL2HVw3UcaMPSDxhzi7snhV5ho8gPjM1zdeH9tCJG70XfaIPxIAw/cScEoQ4REAEREAEREIGKTECWv4q8+1q7COQFAQi9s93ZvHA1FFIQRBBoFH4sq4D3EFwQYNGDMXjRzyHcICS3ZObccrBUQygu8ScV16vY7j/bzcUOnmWfTP2vTbobmTkpFikAISIh5iAc0Rfj/rYki/lJCFJ8brEAbjmwBhxb3ETpGvpTLCH6Rp9IKoO26BM1BZEY5j/uhHVQhwiIgAiIgAiIQEUjIPFX0XZc6xWBvCFQ163kHHf+wp2wulEk0TpGEcUFQ3wxqQo+C8UU3kPYsW4e+8LnEEroK6yph/f88wlxBdEIscV+QmtieF/4JxftISjRPz+HkMQ82T/nEV0LxkFb3A8ByLG5VoxJyyKFIvpCe7yf7c433Ukhyvv0UwREQAREQAREIJ8JSPzl8+5qbSKQlwRqu1V1cucR7oTog+vmD4UCCBavLZkxt7g9QhRRZOFzlleIAxMKONbfgzii5RD3hIKRFjeINdyLg8ITQpLiDONSvPEnrYZ4TzdUzilOzLFvClSKO7zHPOiuyn6j68MaIDKxHghAnGDxljsRF6hDBERABERABESgIhCQ+KsIu6w1ikBeEKjhVtHZnccXihcKoi1lFbYIL8bAQexErWEQgxCHOCCaKPBwH/4Ush8KNHxOIYb2FF4UgKGlEUKKc2DbUNSFrpvha44VWiTxGme4HrqsRjeSApOurLjOdfEejoG26BNClX/6cQ0lIuCW+m1ePCVahAiIgAiIgAiIQGICEn96OkRABHKAwDFujpe6k0lVYLliPB8+Cw8Ku1BY/VRD76fEKhRJuJcCEK/DOEG8xlgUfKFopIhjhs3QNTNMzsLXodUQn9EqidewytE9lIllWA6C86MbJ0UlXUMhaNE3hGrUPTRqIaQopqWQghbrnOfOme7ENR0iIAIiIAIiIAL5SEDiLx93VWsSgbwhUNOtpJs7kcETB0QcBA4zbkate2gDKxwFF5K6oA3cQimmQisaE7hAOKFPtA8tfxBlEEN03WTSF8bKUYTyfRirx9ILoRilyGQmUrTHvZgz3TExZnQcCsW4jUX70E0VJSbiuOBeWv6YXIbCliIRHN5z53/z5gnSQkRABERABERABH4iIPGnp0EERCBLCRzr5nWu7bHHIbZhwwZbseIL9x5iEAcE1QarW7eB7bDDjrZsGa4xoQtFHv68UejB5RPCjlY99MFYQLSj4MLnLL1AMYZ7cTBrJj4PxRMtdxwXYo7upYwjpFsp5sDafmhPiyTWw2vMxInroSWPlj/MJbxGQYzPeS8zkKJPWgYLl+EZcM10UQ37w73giYQwEIM6REAEREAEREAE8oWAxF++7KTWIQJ5QwACr7s7m7mzmtWr18h+1mRfm//5PFu5EvFpOH50nzdwn+9nCxbOs+XLlxUKGlrUCAPCDGJmS929xBax/7lraAuxFLpbMk5uS/kGis4tfUGYQWzhNRO+hAlc0J4lJTh+aDGkMGTyFQo2WO5wcO74Mx1XloJCFgKOFjxYEKOunxiT86fgZXwj22MsurjifswNTD50p6yAfJr0UwREQAREQARynYDEX67voOYvAnlFANa+89y5izuRxXOLEIGFb+9GP7Nvv/3Kln4933bZZfdA+C0vJECLFt4ySycFH4QMrXEEFmbyDN0kKbrQjvfgM1gAKcRohYNQY6kHCDSIQXxGIUV3SvTPa7yXdf4gtNA3y1WEmTs5V96TyP2TwhFiLmrpCx+QMJ6RnKJrJ0dyWOoaygqYV79mWowIiIAIiECFJSDxV2G3XgsXgWwiAKF3pTsR2wcxssXSValSgdWqtYsTe7vYbvXrWeVKO1hBwSrbWLCTfbloQWAJRGvG+uHPWlQAsVYfhA2tYLSmMaaP8XAQnKGljddpEURRdhxsw8LwofUM91A4UvQxvhD3oS3miwP9hm6a+IzCK5rlk+6mtFIyiQzrA+I9y0wkixMMeXH+YWIbXA+zjoLZB+78v8I564cIiIAIiIAIiEAuEpD4y8Vd05xFIK8I7OlW08ede7uzwAm+6la79i5Wd5e6zrWzplXfqYqtXV/Z1q/fZJs2bbJq1Tbb99+vts/mfVJIgRY8lnmIwqHQgvWMLpVhG4gwZsEMXT4ponAPRRZi4NgG1ykEt8Qgbumf7p6h+MNnGIM1A5mIBmPTekhhF86RIjCufh/HpJsn5haK1qhQjHtoIOowB9YLDOMk0Z7j000UVsDp7mQcZF49iFqMCIiACIiACOQ9AYm/vN9iLVAEspnAUW5ylzrB18Dq1KlpdWrv5oVf9WqVrGrVAvth1Wb74YfvnNhb6d7vYHvuuY+tXfudVa++s321ZK5zA0UMIEQWLF/RDJe05NGSCAscyzOACcUdhA2tcSyjQGsY7qUgogWPQpDCjUlTGP+HviHEKBp5nSKN91FcMfYvHBvXoqUjKC6jMX0cL7Q2Rvec7p5x1j2OT6FHcYv3fM1C9lg7BOwMdy7I5gdLcxMBERABERABEYghIPGnx0IERKBcCFSq9Gsn+C5wbp17OytfHavidNYOToNt3rTRln3zncvuudxW/e97N7fNLuZvNxfz18QWLf4/9/kSnwSm0V77OtfPzwtdPynWooIqaglDf0xoAnHGDKBhHT/0BTfU8KBgYzuIIRzoC2IozLiJz0OBh/ehMKT7ZyiyWHidY4ZxgeE88Dkzk4ZzYW3AsMRF3LaG1kIWpYcVLxTOnB+FL0Upk9XQSoo4QNQG1CECIiACIiACIpArBCT+cmWnNE8RyBMCBx14tNXcub+L2zvIxe/t4Kx+zna341on4r51yVz+Z//7H2ryse6deeG3z96NnfD7zGX1XOGubREjWwThz9zn850ghDsijjCDJmvfsbYek67gc7pk0iqHeymqohZEzCUUg7Qosg/0R0sfNykq/pKJQdyDeSApTdQtFXMKaw+yf8Yusk4gXU2jMX9xbq7oI3QJZY3D6ANGoYjx0S8si8xeyqQw77rPlA00T341tQwREAEREIEKQEDirwJsspYoAuVNYI899rLWp3e0Iw7rZC+90tSJNcTwFdjq1Svsu+++tBUrYVWCIMHBOnhbRErDBnvYOhfvB0vgluOn2DYIwJ12qmRLl35WeI316liUnStnPT0KNvQRxuHRpTJKKir8cD0q5CCEIIrCeEH0HwrG6HX0E1oD+R59Rcs6hOUhwvlRjOEz1gykNXALuy1jMF6QTMI2aLfFuhpfTgLXQ0sg6/6x1iGE77/dOTsKTu9FQAREQAREQASykIDEXxZuiqYkAvlAYMcdd7ITT2htbVt3tiMOP8bmz69sjzxW3Vn4VjkL3te28rvFLoELC5uHFipa4FjyIFqigRYyiCIWNUeZhLiDAihM2sJ2sBJC+ECkJYoXjFrO6N4ZCqgwCQz7jgpEZgINx4n2xVqBLBMRrodWOLDAa/RPixxjFyHuKKCj99JiR8sgruM15sOELxg3ml007IcupxiP9QwxB/SN5Dsf5cNjqzWIgAiIgAiIQF4TkPjL6+3V4kSg7Anst9+B1qHd+dby1DOsZs3afgLvvbfM7ntgs3Pr/M42bIB4wwHRhT9BocskM3dCaETj7uiqiPYUKRBDoaUwXC8LtEfFI9qEpRZYyoHCjG6dUeEXjdXjWHBTTRQjGM4naunDtVAk0mWVWUGjghTtwS5RVlP0jznG3Yd74+IIeQ/j+NCO4jNqIeRaviscg0Xv+b8RWP9QDkKHCIiACIiACIhAthKQ+MvWndG8RCCHCFSrVt1OPbm9ndH+fDvowEP8zNetW2v/mv6aPTfhDZs9+0z3Sa1CcYKrUZdICglY4mq6kxktKfhwD1wNKWD4Pk74QQBBSMVZ+3AfrYGYA90i+RmuhzGB4SZErXns66f4xJ9ax7WN+yzMBErxh14gwCjkuB6KPrSLurVyZAjjMEtn3ENEF1tY7ej+ijFwH5O70IIYurKyLxa7Z5ZUMsP/TlAHcFbcoPpMBERABERABEQgCwhI/GXBJmgKIpDrBP5041A79ZT2fhnz5v/XXpo0zl6bMsElb9nZfXKrOyHoYGGDe2YY00bXR7pvsuQCxA9FDC1QtJxBKDI7ZrTEAz+Pxs2RMEseRGvw4ToFIH5G6/7FWe1wT7R8BMeJa89aedHdpigMxR8tk5gv5hot78C2UeschSGznyay3mEOrG9IgRdmLCUDCuFwfPTNtZA/XU7x+afulAtorv9Oa/4iIAIiIAL5SUDiLz/3VasSgTIlcOQRx9rpLc+0F18aa5/Mpuvfrm4Of3YnBCDEQZyIgRWJ15hMhLFsXAJj2qJxfbgX15h8hMlZEgme0OLFvimW8D6apAWfMakKE6JERRhFK8fkT/QbFaBxcX8Yg/X1cE+YmZQlKeKsb5wbaxByPXRhTXSd7VieAu/p5hlXK5H9oD34YzzME+9x4D3LXtDdFPsyx50fczD9FAEREAEREAERyBICEn9ZshGahgjkF4G6bjmD3AmLH9wr47JJUuxQ8MSJNgqSOAGE+xB/hvtwJrL2gSwtZdF4OCaVibpk0g0SYyDOjm6qjEmkeyTr/LF4Ov+kRusOcncZr8j7mTwFYipcP9fEEguJ1ob54+C6QvGHzymcw/vpRhqtM4i1JooXJEP8RLuwxAQ/oxsorq9yJ0pAwA1UhwiIgAiIgAiIQLYQkPjLlp3QPEQgbwggtu92d+7uTsTdUdyFC2SsHS13ocsjxQSLrSey5FH8QYgkE37RAu20wDGBS2gxDEUX5sGYwrg54D5YMykg0Z4xfBRhYX94zXviNhuJY+Lq8jG7Z1QA0+pHKxw40AoX7T90E/2pVMa2rWjFjFo3w1aYC9qBIUVg2J5iHeOhLdw/WYYjbx7wvFtI165dbfLkybZkyRK/tt69e9s111xj+++/v9WvX99l52WZlbxbuhYkAiIgAhWOgMRfhdtyLVgEMkkAFjJY/BoXfvmHmAmtYBAEcAus4U6KGYiJsLwB69rFZenk3CE8IJbQD8VRXHuWYQjFCqxb+NOH+5jwJJHgiRZvD9nxWug6yuth/Fx4T1TkhtcSiT+0YQxkIiFMscUSDHEJYTCnZOIT4zD7ZyJXU7ZhzB+LvYfim3PFWGD9vjs/z+RDp75LSGDq1Kl2/fXX26xZW5L1HHbYYa4ky0qbNm2aNW/eXOKvhHx1uwiIgAhkEwGJv2zaDc1FBHKewBC3gn3dCTHAzJwUEhADEGGIAQwPxvpBsEB8QDAmsz4xXi2a1ZJlEJisBAIFYyUTTHE19Tg3zCWRRZHWQ8blRedLURTdUAjOqIsn20DApZpPMlHGDKHM1EnBi/4xJl1MwSVZHGEYa5jI4kkrI+fLvuk2GrUQQlQszPmnO5cWUKNGDRs3bpw1atTIqlSpYgMHDrRmzZpZhw4drHr16jZjxgzr2bOnde7c2UaOHGmLFy+2NWvWWIsWLWzt2i1W4M8//1ziL5c2XXMVAREQgTQISPylAUlNREAE0iFwuWvUrlBYUAxQkED4hSUcwv5g8YJoQNtovbzouNEyBbhO90P0QddF9BXnQsn+aIFMZF1k5s9E10NrZtTyh3sZ0xfHjUXs49aWKKso27K4e6L9YCH2MJ6PLra0dmJu4BhXCiO0WNKdNRS2zJbK8fk+FH2Mf0QbxGRiHMzrHXcuSudBUptSINCpUydr06aN9ejRw/dWu3ZtLwJh0cMxatQoLw4nTpxoUcsfh5f4K4WNUBciIAIikGUEJP6ybEM0HRHITQKHumnf7E5YynCyjABWA7HBgu5xq/vWfQj3zWTJRnAfXRvxZ4tiMXoPRAazUUK4xVmuWEYBoiaRVTCVe2ToDhoVf4zBS7STuDdOVNLdNVFJCLKEKEvllsnYw0SWRIpb8qObaFS00spKCyi4RK2cmA9jNzFHWh4xR7RnzUX09ZY7t8SV6cgsgaZNm/o4vrFjx3qBN336dIMg7Nu3r8EqWK9ePRs2bJgNHjxY4i+zW6HeRUAERCCrCEj8ZdV2aDIikIsEINyGurOBOykSVrjXKA0AIRMt0RCukYIOAiKR1Q8CBi6dYZwg+ojGzzGLJS1+uA9toiKQwi2uQDz6ZemFZAIrmeUvkcsn153Iesf5pBKetH4mco1FTGVYJzHZMxW6ttJiCY6MiyQPso6Lb+R6sYfRrKK0HkL4gSfelxxXRwAAIABJREFUv1K4L7n4rOfWnOvWrWvt2rWz7t2725QpU3wiF8TwLVq0yPr37+8XM2DAAIm/3NpWzVYEREAESkRA4q9E+HSzCIiA2Q0OwjGFIovCia6GyVwvGd8HYYD7wtp4oTthoqyfoXijNS9OQIYiMHSrjJZF4F4mS/KCNnGF5UMhlijZC/tPNC4zdTILaTJLaJyAZOkMFqhPJRI5n2hsI7kyS2tYv48utuFzH8YWRq2SmCeOsC+4fsICqCOTBBo2bGgrVqywdevWWfv27a1bt24+nq9Jkybe/XPmzJk2fvx4L/4mTJhgQ4cO9QlewkNun5ncIfUtAiIgAuVDQOKvfLhrVBHIEwKt3Dq6uROJVZhUhEIMlrpEBwQHhFoopGCxYhIXCA72E2c5ZFIX9h9XoD06NtpAYLE0RJwIo8UsWcKZqDiMWsMSFUvnfJgsJupyGpZpSCVA0RczmXL8uFp/ybKLhnxCARidPy2qzCQaJwDJFX1SPDKBD+9DPyx9AfH3VZ78DmTnMlq1amVDhgyxTZs22YYNG6xXr17WsWNH69Kliy1dutTmzJljCxcu9OIP7qCDBg3amvAFlkK4hzZo0MCWLVtmkyZN8tZDHSIgAiIgArlPQOIv9/dQKxCBciKwhxv3Dneinl9o7aL1L1GmTAo//PmBgEF7CBecEIBMEJLMFZTWQoqgVIliosXOMV8UIsccwwQlGD9VX1G3zKj4C11CE21NXNKXcE1hds5oHxBaTKSDdlHOUVGbKkkM+6dQjMYcsrA9E8ZgbOxVNBFM9D36DefCmEbu82vueqr4yHJ6tDWsCIiACIiACOQpAYm/PN1YLUsEMk/gL26IAwu/4DOBCeO/6NIZnQU+hyUvFC9hbB2EIEs2JKvzR+tSOhY/zCFO1NE1NUwSAyGVqsg5LVhcG/rhPfiTmqxEBO+JS/oSij+0o/WPwpUZVEOxGheDF2fRLIoAZMwf5oA5xVkyMS4OziUuuynrL9IiyRIX+Ale89z5YeYfU40gAiIgAiIgAiKwlYDEnx4GERCBYhA4z93TxZ0Qa7DU0doHYQehEWe1oyiitQp/fqJuiRQb+JksXhD9xyVziVsKrWxRN0uKP95DgQhhif5plYJQoYAJYwaZLTSZpY2ZLzFG+DrO8scSDIzVo1hKVfcQvEMBHZfIhjGVyZLYkAPEN9slcxtlMhfG8+H+KOPQsovrXBPF/3T32ZbSAzpEQAREQAREQAQyT0DiL/OMNYII5BkBuHkOdmddd9LlECIBwg9CAOKDwiwUFLDkRa15oVChhYttksW9oTYg2iWz0mHsqLsnP6PIpFih22qi8g8UZrTyUfCEApblEkKByAyaFH5MjsLYQn4eWg7DxwUMwJiWtVBAYmzcR4thuJa4EhZoR5fNZI8k2lBcJ3Ld5f0UgBiPDCmU+Q8CnDvaRGMDv3ef/TPPfj+0HBEQAREQARHIXgISf9m7N5qZCGQpgYFuXge4E0XbcUDsMLkLrWC0muEnYuvquDMqSFiLDn0kytYJqxbjAUPBgXGSuYWyLeP66KpJgYbroVUL1q5UsX5ca9R6RgHEMdFXohqD4ZZG74u6faJt1KqX6JGA1ZLzIvu4bKGMu0tU35BrpFBMVgsx3A/0R3dOuo1yLLSjO3AoXjnWZ+7FfxMtTJ+XgMDGjRvtP//5j1WqVMkKCgrsqquusrfeSpxptU6dOnbhhRfagw8+6Edt3LixHXvssfbMM8+UYBapbz3hhBPsnnvusUMOOcQuuOAC+/vf/771Jq4BH3zxxRd21lln+WujR4+2X/7yl76G4U033eQ/w8+PP/7YXnjhhdSDqoUIiIAIVFACEn8VdOO1bBEoHoET3W3XupOCLFqGgbFl+JIP4QXxkKjOX2j1g3hJ1A4iiVlA6S4YV7wcoiMUULgvmesoxR/uoXBJRiVRXcCoiMNa0hGmUWEXJ/5ocUxl4QzdOqPW1GjJhkSunGgXWjbBIt1YQbrJhla/qOWWiWRC6x/WDF5vuhPtdZQmgVWrVlmtWrV8l8j+eeONN9rJJ5+ccAiIPYgpiCocJ510kl1//fXWoUOHtKeFMhIQmkU5MG7t2rX9WCg7EYq/cA3sE/O7+uqrfQZSFLI/55xzfOH6Rx55xM4888yiDK22IiACIlDhCEj8Vbgt14JFoLgEYBl7yJ0o6wBLH77MhwlS6OZHYYYv9Wib6KAISSdpC75MQoiwTENYPw79hxY9vKdoSlWoPcwwmopLXJIW3BNNugLLXzLRyXHo0sn3ceIP16LtUvFMJFLJhSIPcwxdRTF+mJyF46QrALk/tAKG6wnLUHC/wn1a5t68k2oDdL2IBELhBIH061//2s4++2zbeeedvXUMReB32GEHu/nmm73ogoUPlrX//ve/9tprrxkscgcddJCh3t+TTz5p9913n91xxx1eQO600072wAMPeMEFkThw4EBbuXKlHXjggfbXv/7V1xi89957/Yxvu+02XzIC9yc7nnjiCS8+U4k/jIE5X3zxxfaPf/zDzjjjDLv77ru9xfKDDz4oIiU1FwEREIGKRUDir2Ltt1YrAiUg8Ft3b9tAjEBwheKKLpr4s8JyCBAAiQQYrEzJyjlEpwpRxbgyjJGsCHo6JRsg2hirlqwvzoNlKKLzioq/0rT8Yay4jJ6JtpGiOJlbJ++FqMS6aYHEa95HN020pahPxQh7TeEZnTNdQeOS/OAZwHjvu/PrEjyfujVKgC6T1apVMxR9P/XUU+3999/3Rd5hKYM43HXXXX3B96ZNm3o3z2SWP1jadt99d7v99tttxx13tDfffNPOPfdcf99LL71kv/jFL2zBggX+/bPPPmtHHnmkdzmdO3euHX300TZ48GB76KGHbNasWbGbFSf+UKPw3//+t2EtEJ506YTYgwh96qmnbMqUKfbb3/7WF7LXIQIiIAIikJyAxJ+eEBEQgTQINHVt7ioUAviCD7dGJgOhyyFdM1nHD91CWCSygiHLIyyIyYQKE8hAqGxxX9siRnAvxo9LSJJOqQX0A4GSqCRFHJK4DJ1oV1y3z6hASmT5I8d0MnUyWUsqN1GuP7o/EGlMUhOKPXweumvG8WEyG6wrUaF7lqvA9TCjKJ4B7Cmyf+ooLQKh5e+YY46xESNGeIFWtWpVbyk78cQTfRH4Zs2a2c9+9jODSEwm/v72t7/5uLwff9zioosYwZ49e9r69eutf//+XlzygDsmCsXvscceXpRBJKY64sTfnnvuaV999ZWfH6x8LVu2tPnz52/TFayWmMdvfvMbO/TQQ73VEmvVIQIiIAIisD0BiT89FSIgAmkQGObaIMkLBBBECuPzKAogwiAkmIEyFB9xAhBf/hMlbYGIgNDAAYHAJDJhnyzTwDEpAhm/l8pKhb4pUlJltERbzicOVXHFH+Ya1sdLJv7Sdf3E/JgJNW6uzH5KtiwrERXgTNaCvaBFkBlKk4l1rIHPSCIBGgpJtKEIRv8fu/OLNJ5HNUmHQDRebunSpT6er127dta2bVu76KKLvEUNbp2MBUwm/saPH+/dPCHswiMuNvC8887zyWIaNGjgXUZffvnllFOOE3/hTXHXEeN3+OGH25gxY+wPf/iDXX755fbKK69499Y1a2gJTzm0GoiACIhAhSEg8VdhtloLFYHiEsC/2F9eKFQoumD5o4sfhRbcHRmTF45FQUZLD0VEtOwAhUhYxJwuh1GBFtboCxOVpEryEs7rO/cmnQyfuCdZ3Ftcts90Yv7Qb2j9Syb+mOgmHXdOCuvQUsjSFtirqCiL1jvEvOheS15hfb5kGUDDGoGJLKXoM4zJDOskovTDG+6MZgUt7rNbse8LxR+se9OnT/eWOGT93H///X3SFIi+qVOnWpMmTbwbKNxC8RrHEUccYUOHDt0qDOH2CeEIKx5EI1xFFy9ebEcdddR2iWEQS4hMo/iJdrAwpjqi4m6XXXbxVkZYFuGeikyliEn89NNPfVewYEKItm/f3o+B9cDKCMsfYhy//x7Pkw4REAEREIGQgMSfngcREIEkBOq7a4+4E4lbWA6BYgeCLBQjEFMs/xDtkq6YoaWQGSLpLhonbBJlAY0TLPiMIimdGoBwM0yUYTQ6/0TxfmhXXMsf7g0zfiYTf2ibrvWPReoh9Mg4FNTRtVFgh6IwKv54D9oy8U1URGIsZvREe7rsJrMAQvziYBvs3xx3ovyDjpISCMskIPYO2T4nTZrkhdSLL75oNWvWtPfee8/gEgpL4MKFC+3pp5/2rp2w1KH9q6++6tuPHDnSJ3BB8hZk/0R/33zzjXXs2NFb3uKygiIBy3fffWd//OMf/VIeffTR2Ji/5s2b23PPPecT0Kxdu9ZgoYR7aosWLezhhx/2wrFy5cq+HMTjjz++FUufPn18/7As4oD1D/dhjbAC6hABERABEdiegMSfngoREIEkBPCl7eTC63AnRNwdRBPq9oUHRUwyyxQEFK5DNEIo4EgWm0bBGNdnnPgLSwswDhFiE8In6gYaFSqpHoJklr/iJnzBmKGgSyX+4tYcN2/0yeQr6ZScQB9hTT6+T7Q3oaWViXdwP0tthPclcxVleQ2UBKGllH1PdZ8lc7VNtV+6Xt4EIA5hRYSV8LPPJObLez80vgiIgAiQgMSfngUREIEEBOASOcadsPoxeya/zIdumBA/EFipXPVgOURbCEhm2UwkFqOuotEpRoUQs4vGLYWWLWYehRBkTbl0EqOkEiElEX9FsfzRkhZlxoLsjM9jQXsK7HQf8HAuiSx/7AtjcN+ZZAbPRFy9xNCtM5wLXUnRD/qgUMXnC9z5SboTV7ssI4DyEIgdhDUPFkEdIiACIiAC2UNA4i979kIzEYEsI4BiyVcWzglWP2TmhHBiNkgIJwojFhJPtATE3kBE4h4KyWT16JJlCcUY0Zg/CIh0ErfgXowPgcF7UrlEon0obqNrDcsioH/W+UslhtGW5SbwpxiCinFRjKuLCj2WZ8CYrMsXlmhAnyFXtE8nSyjuC90/U4k/tKd1MXT1JIu4uMLoPChawzmjDTn8o3CfEz1T+lwEREAEREAERKCoBCT+ikpM7UWgwhC42630YHdSQIRf3iG+YKlhghUWbI/CYTwc4/p4nRkh44RJOkXfQ/GXTk2/cF5oD6GIPnAw+QjLHEBM4TrnlizeD/dHLX/pxubh3jDjZ9Ttk5Y+xjFSdGNeLGofZzkNxR/FZboPLfcrHfGHeYWF3bkeMg1FaVz8H5PQUCjSQkgBuNB19J90J652MQSQ3AVxckjIgti4r7/+2q655hpfd68sDmQRRRIZHKgtiNp/iBlct46xnunPAnUKUSQ+nZIR6feqliIgAiJQ8QhI/FW8PdeKRSANAnu7NijvAIGHL/lRqxq+9OMLPROmRGPi+EWeLpZxiVUgqtBH2HdcWYe46VL8hVkjEy0LY4QiC188EWOWSLCiH5abYOkCChSKLYov/IxaMEP3yWSoKeZYrgJrp1UR3KIWPfaF9oxhpGANrYyspce5hu3T2Hov6NBfqnhMlvWIuq5yXPRBV1SMG43/w/vQagrWZI8+sMew/qVjQU1nXRWvzYwZM3wyFCRNwYFELrVr1/ZZP8vigPhDMpfly5fbzjvv7MtEoGj7pZdeWhbDawwREAEREIEYAhJ/eixEQARiCMDds507w+LqYTMIN7iB8mBa/1D04VqyIuos7cA2TNKSTpISir+o1S8q9KIWstBimCgWLVwns5Mme0jQJ4UO2odj4E8sT/QR585JS2Sq2ELOIZUrJ8UohWGyxDlx68J9icagtS602FKAY22M44sypFAMmWNeUcslXUjp+om6f4v0G1oMAqeccordcssthhp8ccedd97pM3xu3rzZW+PGjRvn2w4YMMBbCVEPEJ+hXAOyalavXt1n9kSBdZRkQA09ZPncfffd7bLLLrNLLrnEZ+d8++23fbF1HKH4w/tatWrZl19+6Qu2r1y50scDoh7gTjvt5OMDMd8///nPvs3w4cN9Hyge/7///c9QY5A1CJH5c/DgwdamTRufCRRZRO+///6tpSmQxfTbb7/1IhOZQ3WIgAiIgAj8REDiT0+DCIhADIGn3Wew1iFOD1/Ywy/7FFgQK8zSCLGAPydRUcAkK3GQQyEAAYQv/OnW3aPgCrNUMvNksoyjjMfDfJLFHHK+GCdVUpioiCyqpa2o4i+VK2d0PtgvumfSspisVh/WHtbrC1lQxEX3k66vceIPbUOXVVpc8TMaP8lni8XfEWv6tn5Di0Hgt7/9rRdZv/vd77a7u1OnTnbFFVd48VS/fn1799137Ve/+pWhFuDzzz9vSNiyYsUKL/RGjBjhRRlq6KG/a6+91ou/atWqWZcuXQxF1p966ik77rjj7JNPPvF9odD6hx9+uJ34w0Q++OAD69mzp9WpU8fX4sNrZAadMGGCQZDCTRSuqiw6jz5bt27t3UYp/jD3li1b2gUXXGAFBQW+RATu++c//+nrAEL4QVTiPsxFhwiIgAiIwE8EJP70NIiACEQItHDvbyj8DNY9Wo7YDEICn1N48We0nAIEYbI6eqFIgRCga2ayAum0MtEdM906fZh7aKHC+3TEH0RQKktktJ90BGOInOIvnfngPlpIE4nSOItmnCClZZCCLhTNjOeDS26Y2TPZLwvGwJFMLHNMxjHGZQel9Y+C8p+Fz6B+UYtCIJn4Q+F2WPQg4nCMGjXK/va3v9kPP/xgN910k7Vq1cp/DjGFGn1wH4UlEQLw7LPP9vehkDrq6kEQohbgAQcc4O+Bmyli+1544YVY8ffvf//bevTo4WP3IP5gZcQBax2sfqjjN3v2bC/udtttN28BPP74461x48ZbxR+sgA899JC9/vrrW5H8/Oc/9/OEYMUBsbhkyRIvAHWIgAiIgAj8REDiT0+DCIhAhMCt7v3+7kSBdxyh+KNlh1k/8cWttjuj8XPJ3D05XChSwlIN6AsigSKQrpehZQ+ijC6d6W5gNBYvHTfLshB/FGbpij+sl4Ixbu1x4o/Wv2SZP0MxyNeszRgV9nHjsuRDOm2RBATtGJ8Y7Y91A3H9C3f+N91NVrtCAqeeeqp3mYxz+0wm/sJi7VOnTvWumbNmzfL98BrEH6xwf//737cRZRg6vBZ1+4TAW7RokTVp0sRuvvlmmzNnjo8DjB5wPYX1rkGDBt5tc9iwYSnFH4q7o69jjz1Wz4AIiIAIiEASAhJ/ejxEQAQCAnDzHFX4xZwxfaznhma0+lE4QYAxa2aYhCSZuyeHo2CMq9EHsbIlS+AWK2PUlXNF4edF2TwImdCKl6qoOvpOJrI4dlS0pXLLjM6Z9fiKIv6SuZYmimVMFSvIeYE9RC9dMNMtoYH7cV+q9oyJpKUwTpDSCkxBCeufjqISmDlzpj322GM+Jg4H4vjgbgmLGtwt27VrZ/Xq1bP33nvPu30eeOCBWwUe2pem+EPClwcffNDH6CEW7/TTT7eBAwd6C9/q1attzz339MlgvvnmGzv44IP9nOGSCtEJARha/jD30047bRu3T8QFwmJ48cUXG9ZdtWpVb43EZzpEQAREQAR+IiDxp6dBBEQgIHCOe32ROyHqGH/HjIz4CYHHn3Tvg2iB4KGwwpf6dGL36NbHenssB4DphLX3KC7ZPy2DyWL7opvKovHhPWFdvbiHgG6iqcYJRVs6CWKiY/Geooi/ZHNLJP7AN0xGE8eIpR7CjJ2MF0wVJ4j+8GyE/1gQHYNCF/2jLdccZy1kTCDm/W93fqPf1CISQHkExM8deeSRtnbtWluwYIEv9fDZZ5/5+Lq4hC+lbflDLB5i+pCkBUldIPhY6gFupN26dfOrgni76KKLtrptfvTRR976BwsmjlD8waUT80fMIgQjhOIDDzxghx56qC8HAYEL8Ye1I2ZRhwiIgAiIwE8EJP70NIiACAQE7nev93EnxBfrrTHVPmPZYNmJs8TVdJ+n4+7J4fDlnmIEYyQrto57WBKB4rMoJQCiVj/0R8tWogcg3di9ULRRZBb1ocLa4uLfkvWTyCqZLItpnPUP88fJ+oF0+eTYtDIyaUsyd1sWn48mckFfvBbGBHINGDMqAPEZx17mXkMA6hABERABERABESgJAYm/ktDTvSKQVwQg3sYWigD+aWDyDdagS5SMBUKJFp9kcWUEBqHDeLJUboIhZIzDZCH4PJ2x0C5O/OHzZNa2dOL90EcYOxjOrSgPB0RZovi3RP0kcuNMJv6YvAVCi0l2omI+rL2HseMshugHR9QaiHvxWTS+EvvNa+F6MFeuOyoA6X4Kiy/26Y0I66LwVVsREAEREAEREAEQkPjTcyACIlBIoKX7ebU7w1g/fiGH0IA4THRAlNGKlyw7Ji1jEBzfurNWEelDxFGAQrxAFDC+MJGIpHtp3FDJhBJiDpNlHmV/ofhj7cIiLsuL01SF1aN90pIWVysvkasq7qHoTiSco+IP4yaKMYxaAynw8NyALRMDRRMChez4Dwz4LBSAtEiyDyR9WVhUsGovAiIgAiIgAiIQEJD40+MgAiJQSOAa9/O0QPDgCz/j0ZAIJtkRJvqACIzG/DFGjVYmlhJIVUYhHJNJQChsoqKOliyImlAIhrX9omtIJv7SSfaC/kLxx5i2oj5UxRF/GCPO+hfOhyKMogpsWKg9UUkGiK7otVTxgpgLxkDfEGvYI7LA85BKaIZjcq60NrNP1Px7q6hg1V4EREAEREAERCAgIPGnx0EERKCQAOL9UKuL4gqiCQe+zKdyzVzu2qDkAw+IEghAiAZ8iY+6FhalhAD7DK1++CxZ8hKMSdHAn3EbnUj8RROqMA4O64nGGoYxctFMn+nGJUJoM04uru5eooc0Kv4wF7rGoh/G8UXvB8tEgixO/JF3qoL3FJ4YGyeeoWSlH2gpjFoG8TlZh26hU9zndDlNxESfi4AIiIAIiIAIJCIg8adnQwREwBGAS+fj7qwb0IDbI76U75KCEMQVxR6b4ov79+5EEfaoyKA7YFGyW1JEhkIimfjjPNCGiV0gGlgrEHOiNSucM16jDa1VFDHJEIQlI4pa5oH90oU1FFd0qUSbMIEK4+wwNzBkOQS6jabKTor+sL5E7RKJv3RqBVLMMesna/klc0PFepjplesPs4Jivty7mYXPVYpHUpdFQAREQAREQARiCUj86cEQARFwBJBO/Vp30l2T4gcWolQunxB+OGgdpBUHX/z5JT4UgGiPWLpUpRbCjcE9URfRdMRfmOiF1iSKCQgO9It54gytZOkme0FfofhLN0No9KEDC8w1kZUMc2UyGVq+KPbIAX/OKZJSCUAKubjxEok/zDnV+sLyDfzfC/c77hctTAITWmG5JrqAMi4QNdu+1G+sCIiACIiACIhAMQlI/BUTnG4TgfwigHi/du5k/TVYYCDi4I4YunNGV804PCY6wX1RQcEYMwg+fKkPXUjTtf4VVfxxXnQVTVSjLnQ3pKsn7g0FFa1/LHEQFVahiE1WfD3VE/Oda4AxOHe2pzhNJOhCF07ypCtqMhfSRK6fcQlfOJdk1j9yi1p6MSeK0qjbaCj+aN3FWKFrJ19jLV+489NUIPPieqsrLrPvl31jbz/74nbr+VWnDlZn991s8kOw1usQAREQAREQgfQJSPylz0otRSCPCQx3a2vqTlqY8AWeLpP48p2oaDtFGdomS96CPiCMcITtkiVcIe5EbZjwhWKJljAKPQrSZFawRFko4fKaaD0UexRYtMjRdTHZYxLOha8pLuEmm4hzsj5pvUSbRGI6TgxSlEX7Bs9kR5z1jwXZE7HmPVHX1Gj5B+x11PLImD/Ma4U7Z+Xx7+FPS4PAO6ffDTb+1sHbCMBEn1cIKFqkCIiACIhAiQlI/JUYoToQgVwngNIOf3Un4vNYpJ0FxxnDxli5cK1MLgJLHpO6JGPB7KFoQ2GVSHyF/cAFMxRFFFmcYzKLWKpsoomEZSioUu1vaPkryn3RfpE0pzjiLxRx6YhpjEsxiD0Jk/GEyWuSrZuJZtCe9R2TJWLBvLhPTOQCi2ZU/LG2X2g9DBO/4PmcnmpD8uZ6VOhJ+OXN1mohIiACIlBuBCT+yg29BhaBbCFwtJvIn9wJixldMlmugW6aEAkQh+Gx0r1BnT4mHkmVCTLM1klLEGv0JWLBuoAcA+1YSoCJXBLdm6zEA++Js5SxIHm6+xPOozzEH+bJcdMVf1wbE7+E2UxT7SPuheCjxZPtwS2VlTXsm7GSoZsw+40mvsGYmCPGfNOdxS2pke6eZk87CL5zb/mjrflhlVWrufN2lsDsmalmIgIiIAIikAsEJP5yYZc0RxHIKIFfu947uxPijl/E8SU8GqMX1u+DGMQXdFpowsyUcZNN5I4IAYlxEpWSwHVY7zBOnLBIVaohlZAJa+Jx3lxbutBD8ZeshEKq/uDSmE5R+bh+WGexqOIPgiq0ypFHssyhzDAaFmfHnKJWvOg8o3UZw3uwt5w75hS6njLTKWMy/+Ouf5sKZl5d/8uHM6xS5Uq28MOP7b6LuufV2rQYERABERCBsiUg8Ve2vDWaCGQhgZvcnA51J0s64Es8RV2YoCVMJoLXURfFZFkio66bxEBBwOyiGDe0KEEQJKpHhz4SuY1CwCW7j+PHZRwtjoCjaAqL3Rd1q5HwJVU9xUR90vKXbgKdsJ9owphQMNOVE5/RvTR8NkJBnkr8MaFL1PqHufDZYX+hUAzLXODzBe78vKhwc7b9rzqfaec5y9+GdeutStUqsvzl7E5q4iIgAiKQHQQk/rJjHzQLEShHAkj20sCdqPWHI3TxDMUfrDEQCmiHL+tRccXYr+hSaF2KE2MUTegbfULsQVSiLQRNKjFE0RgdEwlb0o2fiwqmZMleEm0T+yiJ+MO4qSyVicYHR5ypkrXE3Y994xGXbIUultFsp1GrYSq3T4wRludgLB/nzf7RLhojSFGI+xEbCetf/h+M8atcpYotmTvP/jWmz9UPAAAgAElEQVR6bGwSmPwnoRWKgAiIgAiUFgGJv9IiqX5EIGcJjHMzh8hiPT988WaiFIo/uvjhTwZESlztv2gZBwKJK9PAa8wSGcZ9MZEMxozGGUYhJ0vYkko4sq9oH8URf6Vh+QsT4hTnYSqJeKSrK8Ujy3OEtQ8xJ7r3soREGOOYLOEL10PXTZa0YHZZFnpHO7yOun6Ge/WDe/NecQDl1D0UfhPvHm5nXv9b+/yDj+z+S3qakr7k1DZqsiIgAiKQdQQk/rJuSzQhEShLAvXdYE8WftlGvBkEVyiaIM4gBMKsmfjCjz8d0fi0oog/Ci580cfraG1Aun7iGoQA5hRXkDwuZi+0GqXDMuo6Why3z9Kw/KGPVEXUk60HpSLScXWN6wPiD3vKhCtR0Rd3D0U69oVWvHR40/rHgvDhvqIfHKwzGU38gmcRc0XSl/w+WOdv4X9m2++fHW2fTJtuj//2937RqvOX33uv1YmACIhAJglI/GWSrvoWgawncJyb4c3uZBHuqLUtarVjXBe+pONLfGiZixNxUasa+scRzfAYFS0QYNEyDRAmUSEYl/EznSyf4cbEFXov6saVVPxxHSXJFlpc8UcRl0i8J2PBou+My0uW7ZP90PrHMhPR/ikAo8XmyRg/Z7ozdFct6n7lTvsDWhxlPR+5z97++wQbd8ufc2fimqkIiIAIiEBWEpD4y8pt0aREoKwIXOwGusSdEGmwqkCU0fIXlzwE4iSMpQvjA+NqxDHRCy15cZapONGYSsCFFknW+yOzOOGYjGco/jAXio+i7AGtjZh3qtqCcf0y8UxJYgaxN+nMPayTiP8FcL8hHtN1lQ3XwHH5v5N04haxTmYUjeNB91L+owTa8B8S8Fx+4E64f+b/cdRZ7eyC2/5kkx963F594NH8X7BWKAIiIAIikFECEn8ZxavORSDbCdzoJnhK4RdrfLlmLB8tUSzETYsOxF6cuycEDzNC8ss/LUpgkMwdMSoaw9p+6fCDaMGBOWCeqbJORvsMxV/o8hnWvouKKowTnhTK0XjBODEWfsbX5M37o/2nwwH7FyZUCe9hQh2MExZ1D9sg22hxhCsT9YT7jn7jRGA4j1QJYmhdxnzDrKy47xN3LksHSs63adXrcmt9ZTcb+6fb7Z3nJ+b8erQAERABERCB8iUg8Ve+/DW6CJQzgQfc+Ae4EwKI4o+xX9GkLxRDca59FD8s2o6fsMzEJYaJW3Jo/Suu5Q5iAeKJ1iJaMRO5ImKOLBzOOdFSmY77YrgOWqWKkywG/bDgeZzlj/F0oWikOAwFFubADKksq4D1hfUYkz1uuLe4B9YdFfi0yJIlraP830468Y0s+RC6gGJNc935ZXEnm1P3/fqOW+yI9q3tgd9cafPfg8VThwiIgAiIgAgUn4DEX/HZ6U4RyAMCz7k1oHQD3SixpND1E+8ZCxZn9QsRUPDBMgghgPbpWpLCMhGpXD6j2MO4QoiQ0DLJ+DKWQuDaQutX6N5aXPFWUvHHxDXFSTbDUgnYJ1oxE1n3kj2y6CcdQRbtA4yZLTR6jRbNsHYk2oTJYpLNiZZCili2ne9e4Mz/45qxT9jeBx9o/U9uZ/9bvjL/F6wVioAIiIAIZJSAxF9G8apzEchmAqjt91ThBFlyAVYifFEP4/oozKLxftG1QURRRKaTLTK8n2OEpQDSZRdm/KTlDJ/RUgbBF80aibmyrAHaoQ3O4sbclVT8UYAmElFgQZHHkgr48815M0aO2VFDK206MXhkUVzxifnFZVllYfjQjRVtKepSWVhZcgL3hG0Xu/efpvuA5Gw71PcbNHOKrfvxR+t/UrucXYcmLgIiIAIikD0EJP6yZy80ExEoYwJHuPEGF45J6x4LejN+DpeZoTNqfQmnS7dNihDE4SETaFx5hrhlUnykU9g9ej/uZeZHzKM4SUuwRogriJ/on8VQuEBIUXRF149rxRGPYIb5o1/Mn8lxmEET/YJjMqEUClnsZbRtKjFIt8pk4jPR48kYy1A4ck3hvPls4DPONy6pUDgO95YCHdfw+ht3flTGvy9lP1yDpvv5Mg9z3nrHHu7Rp+wnoBFFQAREQATyjoDEX95tqRYkAukSOMQ1/EuhUMAXd4gMumlCBNQo7AhftnE9muiF40BshO6dEDL4Ug/rH67hvnSsT7gH4i/ROOG6GKtHIQbRhPvTGSeOD7N8xtUNjGsfZqOkCyPGpvCKii8KSPQVTeZC0Uera7pzCOcVxsRhr5KJ7jCGEGOHiXrStciFYzNxCwU4XWwTJfkJkwnhOUs2V/KkeGUxePzjQv4Xej/67A52/q032pQRo2zSvQ+m+4utdiIgAiIgAiKQkIDEnx4OEaiwBA52Kx/iTgg3xBLVKhQmAMLsirSi4TpiA8ODSUWiljZavyiAIAYgruBKmsx6hS/6LDcRtylRwRe2gfCIitCibCyLmxflnuj4EDGIGSyO5ZFuo7SYFXUeofAF/6IWe6fLJsRVUWoNhhk7MXck+UEfyUR4KD6jdSDDddMqiPa0hrKgPPY6/wu9nzfgRl/QHcXdUeRdhwiIgAiIgAiUlIDEX0kJ6n4RyFkCTd3Mh7oTouxbd9aNrIRF3JlFMyzozkyZcVYbCIAwZpDd0rUy7hrawJoTtfrxiz9+JhM06DuZdTLVJlE8FlU0sV8mWsHa001yE84pFEEQX0W1YIbiL5XlL8qCVkx8zr0O3X6TsaOVkuIxLJuR6D5mAcVYdCmOtmV8I58v9k9XWPQxLdWm5vz1P076m9Xfu5HdfFxrW/NDxahrmPObpgWIgAiIQJYTkPjL8g3S9EQgcwQau66HuROibrk7d4kZitkf8WU7Wvw9kUCheEl0nQXloyIQ1kUKTIiCVIIvnC7aFsfixT4gWjDv4gg39FGa4q+o4g3jh26fTN6T7pMT3ot7wqQxdAuN6wuWWMb5UaTR9TPZ2BiP7bFvcP0MRXdYfoPPEEs+UPxhjv9Kd4E52a7eXg3tpleetcWfzrGh53XNyTVo0iIgAiIgAtlHQOIv+/ZEMxKBMiLQ0I3zSOEXb3y5jrPIQfRBAOLLOb6wMytnMvdNulCmcn+kSKG1D+KNdQJTZYGMIoJgKIq7YvR+iM1omYiibAPFX0ndPjFmUUVsaLnD/YzbS3f+0VhJ9BeWfAjj7bAvEG+M6UTb8EgVM0iXz3B/If4oMulKjGctTDBE8YexmBE2v90gj+54hp0/8Cb7x+NP2Ut3D093M9VOBERABERABJISkPjTAyICFZZAPbfy0YVfpiHuEmXzpBjBl/5UljFm/SxK8hWINpyIOUzHbTBuwyAgorXkirKxEC1xbqfp9hGWekgleuP6DN0+iyr+mDkz7LcorqNRyx/6iSv5wKQ6WB8sciw5EV1PMhFOl8/wHpaDoBsorYLh8xi6h9IlNL/FHwgh2+e61att5VdL030Q1U4EREAEREAEkhKQ+NMDIgIVlgASuPzdnRAbFF5xwoX1+/Bz5xS0wmydcaIivD1MGMMSC3S9LKqAwhqSuSim2mTM5Tt3phK3ifqheCtuzF9Y8qCo4i+Oc7p9xAlHrJElH7hHURdcCLNEyXmSlYuIE39MckMGce7CjDHF3GCVxJH/CV9SPbW6LgIiIAIiIAJFJSDxV1Riai8CeUMAQudFd0Kw1Cn8Uh0VP+GXbljl8KU/UcIWgAnFH2sHRoFRUMDaSPc/iBW6fzIxDC156QhBip2oG2JRNgsxhyUVf8V1+wzLOxQ15i/OyppuH4kstCy7EVfTkEzxbDAGL3TjTBb3h+cnzqUX8+UR1ycT/6ANniu8n1GUzVVbERABERABERCBwv8Ll+TbkiCKgAjkLAF8CX+p8Ms0rICwXkWzXTIuD58ztoxZQKML5xf0MElHtD9ayKLWHfQZJg0Js4hCiOCECEwkBBmjVhR303D+ECUQkOkWpQ/vpZgFT4i/qIBMJ36xtMUf4+hSPZwhL4puFpVPZsELRRyfC+4prjE7Z5RxHAvGiPIa+4vuBfrEwdIhM1MtTtdFQAREQAREQAQiBGT50yMhAhWawPNu9fiyjiybcV/MV7jPaweE8EUdAgzCIFq3j8lg2Jy1AlnEPJEVKbQu4t7QBTK6ORQoEJUUghQFaBudQ7qbiz5CAUoBwgQl6If/ThZXpJ1zjhN/4RzCf2vja3Lie8brpevGGuf2yULrydbPZD5oA6EVFeTJrIdx7pthYpg44Rhm+cSYTNyCvWTcH+cb51KKPUIfmCf6fzvdzVU7ERABERABERCBQgISf3oURKBCE0DMH774408BBCC+hNPigtdRK19oHaTQYvvQ5ZNQ8SUdR7L6edFU/2ifTACy79A9lC6jTDiT7qZSeNLtEMKC4i7dPsL5ssB9Ue6l+yTviZZqoAANhWM4x2SJV0JB9//tnQW4HNX9hg+B4FC8xTW4u7uW4O4Ud5dCcS3SUrxAIFAoUJwi/ReKFSteHArFS3GH4vzPN7lfODnM7M6dJCR7887zzHN3d+bYe+be7JefOaFKarVrZZVslTSmyn1Ta7CozC13qWBMi8q7ja2fqShO+1AbnRL94vxAdyBzLwQgAAEIQAACXd9ycPvkUYDACEvA4k9WPFvQ5LZooSCBlRZet0XMosFZGG0NTF0eHSPYrnB6Gu+XCqC6LpiytmkMlxnQHNVWc0rFjZOUOKbMQk9jWvzVcdEse1gsXJqIv9TlU32LaVUilnxstbU4zC2FXpP3KLfutXORraoXWGb1y+clQS/eaeZO/1+jBXrOWv/RoM9s9fM+uW9nG9Vea88fHGF/a1k4BCAAAQhAoCkBLH9NydEOAj2CgOr8TRJPiT+n0JfY0xdxCTm7eaaL9TV/pi/ruk/3+wu92+kLvK63ElUSKXmcXB3Ln8eX4ErbW+xoPZqHxYRjBsvm4kQtVVa0dpttAVdWIqFd23yt3anTZwHnwui2ZNqlMhXu+TzaZWOtmkcd8ee4P1sI7dqaCsJ8PnYVTUs8pO6fum5hryRFD7UDy3UIQAACEIAABDICiD8eCQiM0AQOjqufL57O4Kkv1XptV1DHWKWQyhLDSBA6O6e+oKfWvnZxeGmsXTpOXQEo90Rb/jQHiYcqa6MtmrasyfonUWgB2s4aVvWw2HWzifhLa/y5/7KELU6o49g6v9f8y6ykLp9hQZtaBm3Bbffw5/NIrYzt2tptVG3Mt6yMQ77mVJzbMcX/MaH36kM1GR9uNwGuQwACEIAABCCQEUD88UhAYIQmsElc/frxtIVIIkZf+MeMZ5nwM6z8mgt7q72Lwacuf1Xe5bbSlW1CnYLvGs8iw+N1N+5Pc5OYUHutXT9zl0PH2FkU52LLlq3uij+No3VK0KRJZrQmHamLqsdOWbWy3jneMr3fY6TWtVa/AHncXx2rn/vzGmwprqoL6Pt1X5ll0P954GdFe4H4G6H/bLF4CEAAAhBoTADx1xgdDSHQEwgsGBdxYDxt+dMXbAkYF32vqnuXu4OqRp4Eo602dvuTqJSwqbL+SSBUlW+osvzZ4iX+toLlAqedq2m+d3b7rCsc0wydfm3hnFu3zCTNEqrxHXNYZvmrU6S9XVyg+q26x6LRbplVbrlNxZ/2SG3TDKBacysB6BjDdC52Y3XGWIvut2NfT/SEX0DWAAEIQAACEPhRCSD+flTcDAaB4Y2Ayjj0j+dYXRPzF3DHsFUVdE+zgqpNVe0/x43pS3uZa2JZspeUUSqMNKZdSi0QqmrR1RVxHstlDZq6fTq2sY5oy5+BpuKv3VzFPi2D4XHtupnOI3WDTT/XvvpoleEzvceiXeOU1furEoB5cXgn6JFI9n8m2J33+fjZq8PbLxPzgQAEIAABCAz3BBB/w/0WMUEIDG0C/eIAUyTiT5Y4fRHXl3hZ86oOXdcp66CsPFVWQrWXmLRFMe2vLNlLej1N8lEWL1ZVV6+74s+xbe2saa32wmusm6XUfTUVf3XWKL45t1buvBaxtkqmSV9auXymIt/j2fpXtm9lAjCt9efYTLO0e6zEn4TgI/FUfCoHBCAAAQhAAALdIYD46w4t7oVAjyRwZFzVAl0rs7ukxJ/Ehdw2q5KnSFg4VlAWonYlHeyGqC/ysijaMlQlDixS8vi7dBOqxF+ZO2jV5tmq5OtNBaDEi2Mfu/OglLm31rEgtrP8aQ7qJxejrcSf550mhNHe2vqWu4e6mLz2Pr8mrlWWWY2TCkDHhHqsXNim4k/P5j3dAcy9EIAABCAAAQh0EUD88ShAYIQnsH0ksFY8U1dOfXF3PJ5e5yUD/OXcQqluiQQLFn2Bl3DI+3WJglRMtMoW2qquXh3LmDZf96Xzr9suf3Cair+8zp9FWysxXTdbZy7+6u5TujYJbB1pXURb6cqS0LitS220yvBpAWirorPGlhWI15hi8kE8ZfnjgAAEIAABCECguwQQf90lxv0Q6HEEVoor2iOertXnBb4XXygm0Ba6MbouOMGJE7k4/X4dMPpy7wQvLgTuDI95PJ/7a2XhamVpqyvi8mLmddvl61U7Zwutw0L3mGV+fzvLX7safe4vF391rH75XGThtWXOMXztrLwWmXUsoWm8oe4ve57SrKj/jff8qy5g7oMABCAAAQhAICGA+ONxgMAIT2CqSODUri/dadyeLCxjJ3QkkiQA00yf+lIuy1BVYpgcbuqOKVEhIWix5VpuLsaeti0TZLYSVm1gXffNPKPl4Ig/uy3WfahcH7C74q+Oy6f6zGP+upsFVX1IQNo1VRY5W+mqMoSqjUVmK7dPr9lCUWNU7bP+o0Fs9bz9O54SgBwQgAAEIAABCHSXAOKvu8S4HwI9ksB5cVWTxDN10XPx9PQz1VeTNTD94v9ufK/SEHUPu3GqncRkmVugXTEtBMtEQZ4dsmz8OiIpt7LVtappPItZJyjJxU6ZQMpLGZTdkwvSfG111qU2Fkyea909ciyf7i/L2OmMoWV7l2YT1fitRKL611gaQ//xoD0tix20+NP9D3Stq+5auA8CEIAABCAAARNA/PEsQAACkcBR8Zy96wu4gbhIt62BFjoSHhJljsuya2HdLJdO/CKhlMf8lW2G79efq/T+OgXVW8ULeizX+PN7rVOCpKwkQlqzLxc+mmd3LX9pvT27Vmoedpd0bcCcS12Bqr1yTGErl09bUe2C6720W2pZyQjNqcwKmFoX1S5dV74O96vxNJYL3vu+NNmPXUJJ9sKfLAhAAAIQgEBTAoi/puRoB4EeRWDruJqfx9NxfRYgqRto6u5p8SERKBGmPyXt4sDUZ5rwJY8xbAdU99tNUvOSeGxVXkL91RFJKlDvuWsdEiJ12pUJmTLLVat1pUl20vtSi12a3CUVpK0SqbgvCyq9z10+U+teWbbOtI1LYZStxfMTN7+2SLYrb94urQGYCs1c/Gn+XqfmIKH+aLsHhesQgAAEIAABCFQQQPzxaEAAApHAovHcq4uEa/vZMqcv5PoS7kQtqbCQoPC1KiHj+22F058dtWmVqbNKZKQCRjGJzkApAZHPz32kLpIa1wLSQq+sXESTuD+1GRriL2dhC16aLCbNxJnf74Qtdk21oGon1nWfRVxZvcB8nDQRkK85UUvqymkro/mn/eTWXFv+XLD+9XjzC/zGQgACEIAABCDQkADiryE4mkGgZxEYKy7ngnjakiZhkIq/KnGhL+cScRKMTsVfRia1Gvq6inRXCbYquqkbp8ZNLX+2Jlm0SBBq3k5Wotdl1jLNI7cgDmvxl7pr5iyqRHYuBi10JagkGLXGdvF36VhpUfc64i+1UKbjpHF/mrsO/9OT70eaHdQiNXU3fiq2VawoBwQgAAEIQAACTQgg/ppQow0EeiSB38dVKemLvsTL/bOd5c8QnHjFYiG1KNnalFuZdK/OuolLPFaaLTQXf+k9jnOTAJT4cEZJWwhT0ZHH/KmfYe32qfEtlNKHLXertMBLs4ZqbXbBdDbWVvX4yh7m1Oqn63XEn/ffrqkWgHYZtaDW52mB93R8u7umReWdtVVM7k72skf+ErIoCEAAAhCAwFAlgPgbqnjpHAKdRGC/ONmF4ylrnISHvsQrwYqTmFTFmKW1+5z8RaUf7BJalgjGiT66K/7E0yLCpSL0mebqJC1l7oz5OHpvwZSKElsLUytW3T1Un3UykKb9VSVhSWP1dL/FsrnZilknyY5iGrWnFnR1rH+p1U/j5/UCcya5WEwFoNrquvfFCWDK5iGhqMOJbmzlFCfVnXy87mZwHwQgAAEIQAACJQQQfzwWEIBAF4E1489t4plmh5SI8xdwibyyBCup+FNXEkAWKY4fzCGnxdC762Jpq5yzP0pMtLNstRpDIjIVURYuaZKTPGOl3WAtwvRT80rFn/tJk7Tkn+W1CNPsli4bYUEqhk3EsmIjU/fatKh62cOfCznd087yl4tFz9XuqynfKquf2thFNP+PA+3f8/Gkvh9/riAAAQhAAAKDQwDxNzj0aAuBHkVghria33UJmDSbpi1+EiZlX/Jz8WdLof686LUsPrloTK12dYuxG7bmIWEksVXH8qV2nnt3aup1R5Q6sYkTvlSVaEgfGLuiVj1EErf5fLsr/sQojaNLx7J1M7folu1x2VzcV36/5mhLn8ZIx29l9VN/qYtoKljVx31d/faoXzoWAwEIQAACEPhRCSD+flTcDAaB4Z3AZXGCivezG6W+dCsZjEVWWeKWtOSCY9BcC9DCy+38hT6P16tTj8/xgy7FYAtlXaZVY1SVMeiu0Oqu22deeiFfR25tS+Md665ZjPLC82VtPZcqcZaWnsgFpN+nNfvSe7yOVrF+vl/jpPGa/vzN+OKJuovmPghAAAIQgAAEKggg/ng0IACBhMCJ8fXM8XQNPsd6yXrnmK1cAKbiL7UCSgyk8XeOY5MraV6jr5VlTtNTX2m2TouaduUK0s2tSuKiOZcd3RVb3RV/rYquaz65+OuuGLVlsZXVLl93mhk1veZyH/n9rhVYlUlV9zuOz9k7W8UcumakngdbJDXGs/F8g99UCEAAAhCAAAQGkwDibzAB0hwCPYvApnE5G8bTLpUfxtey/Fk4yX0zFy0SF0oMk7tJ2p0z/7Kvz5VhU21S174yy5wzXubunRqru+6i2qlcQEmQ2GJVtpPdyfqpe6uEZFnf7eoi5uKvO26oXqu4WXy1e1LTbJ1+nRZrT7OPipv61f61KzZvy2qrWD/NzbUf9YylcYdiem/XZ+3WwHUIQAACEIAABFoRQPzxfEAAAgmBceLrfvGU4HPiFlnq/OVcX+D1Pk3+oi/3ssCVxYrl1j8PZbdPx4dJRKgPCxxnt6yy7DmusI67aLrBZQK1rKSC23RHcA1p8Zdn2OyOEE3jCausdvmDnyd6seVT4k6WODHXvqTiv07mUD0ftuTZ+pePbQuiE96kc3k73vwYv6UQgAAEIAABCAwBAoi/IQCRLiDQswjsGZezbDwlGvRlv6yQuuICLfacdbOqYHtZnGBZjT6JMGd7VP+tDo0pYdjOXbRM4KSZOy06qsbqjvgTj7pWNo3XzvIn66jFb3etnGnfdaykZcLdTFwWwxlaHbvXzuLn9tprr6NM/Gl+FpFep/dIP1XYHZfPnvU3htVAAAIQgMCwIoD4G1bkGRcCwy2BaeLMjo+n3DJd6D2frESaXAolDFVHTpbCqkNf+PMv/WXiz+n9XWNQbTSHsoyeabbQ7gg0zTG9X69bZd20tS2N/0tLN1i06Kfuyd0+8xIRGt+fpYLO2UHTLKGp+OtuvF+aTKaqYLz3q6y0QyqKLbJdEqPs/qq9z7N96j4/C/qpcdS/X6f9OOnQ3xNmLR4zLkEAAhCAAAQg0JYA4q8tIm6AwIhI4Ji46Fm7vnSnmTtTFi5rIMHTzlKXW7kc8+f+nOHRLoa55UpCQELTQjAVjxYJdS1RqZDSGnKBZhGquflPZB33RsfB1X1eqrJ9ugTDR13CyIKpblmLPCbTiXaq5uV52MKncaoEt4VvXdYWxOn9zggrpvrcsYB25U2fCVn8nqkLlPsgAAEIQAACEGhDAPHHIwIBCJQQWDh+tnfXl3NZfBQLWHYoIYyOqmLuaZvU/TMVf7bEpQJLgiAteK5+9N7JWfQzFZzdtYylheJt1bMYaVpbT/3UzayZWg+rHkBb/nyvRaHj56oEaVkW0bJ5ibEFV1pIvmo+6sNW0jpi2KJO7VLxZzdPjZmWlsjFn94/3MWUX1IIQAACEIAABIYEAcTfkKBIHxDokQTO6hJ1jvnLC7Vr0fqCLiuc4v0kxtqJAlv0LP7K4gENs5U7p9pLPNh1UuJCwqRsjvnmaA7OZpoLjrKNrOtWqvHzDJ1VD0YrV1O3ccKXqpIQdqfV/Vq/2FfdKwGmQ9cd32cra7s9y+ej9+1qFKZuvs72aYufRV9e98+WZPWv12Ip8ccBAQhAAAIQgMCQIoD4G1Ik6QcCPY7AWnFF68VTX9Yl7tLaa16sa9v5mkRBKxdQW9wkbHRUJYlx/1XZPMtiBtOMkRIamrfiyVwU3p/5z54tde3cKetm2eyO+GtX40/rbyf+8gfOcXMWdc6Yqr1xRtbUAmcBXOfBtUtr2r6V26r6tKiU8MxLR4Qw72pLh+fufTR8/I5iRr8JGxy1V5h81j7hm6+/Dq89+Uy4+ujtwrdfk+ilzu5wDwQgAAEIQKAuAcRfXVLcB4ERjoCsaOd0CTQJOlnAUsuaRZF/uvyDSye4REQOToJO8WytksS4jYRLWVbMMvGnNqlYtPixW6f6SgWh+rUoare5dQRgd8Rfu0yfmo+tm2VJYzxfCz79dJ+pQPPr3CLZKrtnzsJup87Eml4vE4Cp1U/XNfYPS3Zse/aR4caTzg//efrfxdxnWmy+8Ozd98fX34YNj9kvvPjwNeG+K85utzFchwAEIAABCECgGwQQf92Axa0QGPEI7BCXvEI89cXftf8sAFOhJeGhPycSiLbmOQ4vd8VUXxJ/Y9fEWRb/lyeMcQuQHcUAACAASURBVFe6N40pqxrCGTAdj5Zm25RgkkhM3SHruH5q7Dy+rWr8OuJPAtdxj6kVT306PtFWS5e8yBOx2DVUIje32tVN2mKhaPfNfE3fWzF7jz5K2Pi4PcNPfjp+GKlXr3BrvyvDxFP/NMyy5AJhlNFGDa889my4+qgzwuzLLRLWPXy38NFb74WvvvgynLnlHuHr+HOAgO0dFttk8TDWeCOHm04/pOYzwm0QgAAEIAABCNQhgPirQ4l7IDDCEpg4rvzUeNrCo9ILOiQcJOIs9CQMJPLSuC5Dk0jUNVl/LAjrun26j1x85eLPFkLNqzvujHI59JryTbZwcrbMVGjlYtGulmlilTRRS57gReupEl8WnS6qLsbt4vLauZGKlw6XpKgr/FKWeRmLlJfu+y7MtuwCYcZF54oCr18x1mhjjxZ69fom/O+jAfu9/pF7hMduvis88/eHwrZnH5FY/tS3+ugdeo3yTdjpguPC9SfuFV565O58U3gPAQhAAAIQgMBgEED8DQY8mkJgxCCwT1ymsn/a+iThIMGUCjK59tnN00lYUsEi8SMR6PhB1+lLLYXtaKaWxtTt026maexeHUudxkvLKbQaP63JV3Vfdyx/7cSa5+ZELq3m5iygrQSi3T5dxsLitd2aU5HYSvxpb74OE001TdjqjAPDYzfdG5658+Eo3h6LgnChsNQWa4Xeo48WxvjJ2OHeS28Md5x/VSb+PL+Rw1oHbRW++vz1KP703HFAAAIQgAAEIDAkCSD+hiRN+oJAjyQwXlzVKV3CTaLPRdhTd05b/gygzK3RheFdT05i0Ra7H8aE/RBlWs9P4s8ZPsva2mrXzmIm0SFBVGf8dnF/3Yn5q5PtU1bJutlL2yWt0TpTq5/5VFkAdb1MvKe74r3TvU4I9F0YY9yxw0yLzxMWWGvZ8O/7/xkWXv/n4fRN9wkfvvlWWG77jYsObjnrT1H8Keavf4z5ezp+MqDY+3LbbRQmnWn88Md91gnffdcq1rFH/qKxKAhAAAIQgMBQJ4D4G+qIGQACPYHAz+MituwSBPqzIbEnwWFxUmZpS8s45HX47PZpS+CAL//tjwHuhSFIGLVLGFOn9p9EkY52IlH3tLMm1hV/dYSfxqsj/pzMpt38tU5nO00pW9DmQq+sxqL2U4eTy9gq+X3bcSYaN7p4fha+/vKrMPMS84b511wyTDXnzOH4vttE98/eYcfozvnELfcU4m/z3x0Q7rro6vDCgw8Vz9L8a64c5l9jmdBvh8Vj/F8rK2P7p4Q7IAABCEAAAhAoJ4D448mAAARqEjgm3jd1PGX9c/kACQBZ8KosbXbVzN0c9bmtTk6+4r5aTcc1+iQ+q2L10vbtBJtEkQRonQQs7cSkS0e0E2LtauRp/uLrbJ/teLSz+qn9h/GsKquRJ4spywTq/U4zilrEfr/ePovMEVbZY5Pw3bffxTIN34RrjjkjzLrMQmGulZYMH7/7fnjnldfDB/99O4q/P0Z30EXDSrtsFhO+fBETvuwdDrvzynjt1fDFZ5prCE/eek249Zyjaz6b3AYBCEAAAhCAQB0CiL86lLgHAhCIBCT8DovnOF00JOBseRozvk4TwBiYRIOSoOTui449S8GqL4k1tZFQycVKGvP3brzezvKnvlNX0bJNdHbOOjF4XmtZP050I1GaHmVCsI6VUyKrXQH6OiJSc3EsYjuR6JjO9D5b+XJx/0Ph9/2qLR7T/yAwB++Hx0hLbbwau3iW3zQIQAACEIAABIYiAcTfUIRL1xDoeQS2iEtaKZ4ScxZ7juHTastq+0m0SRCUibk85ixNFqN+JTI0Vh6XZ7fRuq6iVda4tDRDK+ufxaoFl/tzyQWtXXOt467ocSwmnQk0zSCqcfLyDPnTVMdaaZFWpwSFXUDNXfNxyQuJcvfVSvhpjl6P1pBaS/NMsBb7GkNWTtX4I86v5/3NYEUQgAAEIDA8EUD8DU+7wVwgMNwTkNg6Np7TdgmdtKafawGmgi61lqUxgFqoBEmZK2IahyYxYGugXksISiw422feZxXA1GqY3pOKIlv/7AZpIZLW/GsluFwSop2AaSfazEzujxq7LONnHaufs4CqfV7kPWVg0er6hrqWx/xZ1LYTfu7XrrwWya4D6WfDyWJ0Xfc+2LWnw/0vABOEAAQgAAEIdDQBxF9Hbx+Th8CwIDB3HHTvLmGSugi6CLgEwhjx1J+XPOYuFWsSJFXZLC0WchdJiwZbHSVG65SLqHL/tPizy6MzV1ZxbSW6bMlql9ClnXDT2rUuZzTVXOx2qdcSUGVxefmc0xp9ufjTtbR8RW5BzRPJiJOP1jGNRz/wx/DG86+EkUaKcX/ffBv+fNyZsbj7c0l77YXWMID96GO/HeZeZdHwj8vPKu4Zb9Kpw9RzLRIe/b9Lh+rDPe9qm8X4xF/HQvOvF+Pc+6czwoPX9A8TTT1j2PCYP8R6g73DNUfvFOd+X+g18sjhF6ddH/6w59qxDEXu2jtUp0nnEIAABCAAgSFKAPE3RHHSGQRGFAK7x4UuEs9cCChD5dhdwsLWo9y6Z0FYFguY8nM8WJnYUFsJT4kUCRmJQVsFq4qi57X61NZ1/ixi68T+Vd1j8ddK3NklstVzon605lT8pfc746k+qyrVkBe6l/hzu9TCl9+XjpOuw3Npl8zmu3DYXeeHwxbfMnb0WeizyNxh6a3WD+ds+6uuji38zOqDKPbeDVucfE04ef15inumnW/JsOTme4YLdl+r9i+TxNm339Spxfh9lxJ/U8w6XxSnewwyzqp7HR+eiMlm3n/95bDavr8Nf9x3g7DIBjvFRDQfh4evu7D2nLgRAhCAAAQgMDwSQPwNj7vCnCAw3BNQshVl/5w4nqn1TyLMcXpahGK5lJUzz8wp61Yrl027aeoLvQRDnqzEZQcMyhZBWbD82u6X+syCUO3Sz53tMwUucdoqlrDKbVP9Dih2Xi3K2ln9UjFWJv7S+EDNOU3E4j/nmn86jj7XvHKGrYSfeZi/xXarB1Nz6RXFX/8o/lTP76sw+/KLR6veUuGivY8No44xWtjspIPCGOOMFUYepVe46YzzwtN3nBw2PLZfmHWp1cLbL/8rPH/f38I08yweJplm5vDe6y+Fh6+/MNxzyWlh5d2ODtPNt1QYedTRwj8uOzPcf2W/QiSusNNhsbTEB/H+mcKjf70svn4v3H3xqcUkV9z5iPDJe28V7cuOKvG38m7HxPqEtxbib/kdD43Wv53DxsddHPrv0pfag622n2sQgAAEINARBBB/HbFNTBICwyMBWWq2i+cEyeQcoyfRIEuc4/fsmplaAe0+l1uvyjJL5glf9F59p0cqAHNeuuaafmqrxDSaS1lSldzlMe+rSsBZ/LWK6WtnWWwn/nzdFs/UxVSvLfDyuMtcLNcRflq3k7S0yzzqeXwTjn7gsuj2+XIYZdTeYdyJxg/n7HBweP3p56Pr5Cih9+ijhy8+/SyMOd5IYacLTgonrjFj4ebZyvK3wNpbh7HHnyTcdu6xYeTeo4Yd+t8RLt5vo9huqrDlKdeG3603TxRqLxX9bHriZeG0TRaKLqcjhb2veSqcsfliUTgeE+674uxYTP7hQTZS4m+lXY4Kn37wTnjn5efCDb9RIfrXwk9+NmVY/4jz4vxHC1dH4Tdv303D03+/Ibz40N+Hx19C5gQBCEAAAhDoFgHEX7dwcTMEIDAoga3i2wXiOX487RJod8689IMEgoSRhJdEisSS7skte1XJWfLYvjLh5ti+1MqlMfMxLMKcNTRP0qI2EocSUT5Tl8cyEVdH/LVLGJOOIaupk7akwtZJYPJn0YlqBljgvt8P10b0/XWFn+MK1Z/jOcuef+3L95lBB7h9blDcONWcM4W1D94lCrRdixi6vntvFaaZd5ZYB/DLMPHUU4XjV5sxiqzRW4q/jY+/NEzaZ47w5ecD4g5HH3vcwhr39VdfhuW2Oyj0237FgZPa6owbw19OPjCMM+EksWj8VlEkblj5CzvmTyaIrpyfhG9iPwuus02Yc8X1Yl/KZPv9MeGU0xcWxOuO3zP8fM/jCvF58xmHxXqFaQxj5RBcgAAEIAABCAx3BBB/w92WMCEIdBIBCZGj4jle1ynR4dgyWwFzsWIRqKQwEn+67sQu7YqypwJQlrwy90xbq8SxqqaeRZX6Kzt83WLM7pa2CuYCNXW5TNdQJirT7KEa22N4rqmItohtl2XTwi+93yLQ9RjNo129P6/d91XVHHSJj0FdegeIP4muAXM+8OY/xHi+PcJMi88bZlps7vCngw6PBeDvDftd/1Q4e9sVintaWf42OeFP4f6r+oXn7r15kI0qiw2cIwq4qedcOIwz0c+K+Lxn7/6/Wr9MI/XqFQ657c1w+FJyY/7+2OjXfww3nX5omG/1zYvx3//vy2GlnY+Ma9iiVr/cBAEIQAACEBjeCCD+hrcdYT4Q6DgCU8cZHxxPiZdx4ynRIEuRLGe2uklQ5EJN9+s+iUCJRluQ2iUVsfXM5R7KgLk0QSuh46QjuUBzf+3q/uXuqrZktnP7LJtTLjY1B60vTUTTai1V1jx9bpfPOhY/i8x0ba7TaE6pJfWHCWe+j/n7Okw8zZRh+3N/HY5eYYuYNGWVMOGUP41WtO3DdPPPEbY9++Zw3Kp9wpcxkcouF98Xjo+vdUw2yzxh1b1OiElili/ey+1zpsVWCRfvv2EUjV+HiabqEz586z9hitnm/0FimJGjdXH3yx6JMYWjhBPXnDVaGKszr0ogfvzOG8UYsy6zRlhqy33CmVssMfBhmnbeJeLnq0d30H3DqnufEJ4cmATmpHDRPut13G8pE4YABCAAAQiIAOKP5wACEBgCBNaIfawbT7nmKRmMhIbEX2ohk7jLSztI/NnyZzdR3dNOAMolUW6RVUXlnfilneCxsKkar7sCUOvpjmun0Ze1sfhrt4Z219WPeLWz+NnNM2ehNUn4pdlXdU85swGlHl4uFqbYu7+eFi1wdz0Y4/zGDFv8bv+Y+KV3eO3ph8JUcywUk6isFj6I1rQNjv5D+Fl07fzXPf8X7z84bHX6DWHMn0wYHrruD+GemMBlheh6OcsSq6rD8On7b4cL9143TDbT3KVZQdc88LTwv48/DH89dUCG0bUP/n1pzJ/i/WZZqm/MEvp1+OzD98K1x+4a3n7p2YG/C3IhveSXm8QkMu+HiaedOWxw1AXRdXWUcO0xu4SXH713CPzO0AUEIAABCEDgxyeA+PvxmTMiBHoogQPjumaNp0Wc/rzkbpeuYWfhYBdQWZDsAmqrnURkKxGoMg1qZ4ui3UxTC2OrJDDaBl2XOKrK7tkqO6fXkm6nxG9VDT6XcCjb/rIYQs3L66/i0E74aX0SyS6LUdVPlThU/1qT2tmlt6zovNekfiSobRFME9T8N37+2FB99iU2d7n4/iIhzLuvPj9Ux6JzCEAAAhCAQCcSQPx14q4xZwgMlwSU9VPlH1Tnz3FmElW5xcn12Py5i73LMpi6Eaaum4ory4WLyzTYalYmxgyqlTVOFq2q2EC1r2qrz33YJdJWMq8jdSm1+NNntpzpZ5VYlPjLE9WkG99O+Fm4upB9mWupYxnT+apfz0n7Z/HneMeq2oKpddCuobbAfhD7uS+e1W6Yg/tITzLtLDF28Orw5G3XhhtP2n9wu6M9BCAAAQhAoEcSQPz1yG1lURAYVgQWjwPv0DW4xJuzZubunrbI6XOJC4mEsiLd+syiydYpJxhxtk/H2qmPVpZCzaXMauUadlX1/Vx6wkJJy3PSltwyqL50X5lAqhKnFpFu5zVIMOXcvK/thF96XSI5FXfmmf7U/V5XOnfNzaLcltyytTm5jOs86r2Fnz77Rzxd2mNYPZuMCwEIQAACEIAA4o9nAAIQGMIENon9rdLVp1wzFfvnun+5e6UzYzr2r2oqFma2lLn4uPpLC8JbdFT1Y4GZikRnDZX4SkWT36uvsoQ1+jy3CtpKVjZ+mWArs/rpM52aV1oX0X22En627qUCLRV/6kOMbFXVfXn2UY+jvvLi7mXuqa4vKBbaC7uIWiw/GD97Zwg/Y3QHAQhAAAIQgEATAoi/JtRoAwEItCGwZry+TpcQ0Bf/MbtEhgSCkrSk4kSCQlYuxfi1OmwFTGP8JGwsBPXnzNdcm6+sP1vyPAe5V1pkuXi63S1TkVhmuSuz/KnfsgyiZTF/ZX1awNmFNC3e3kr4VZWDECOtw6UZbP1s5b7pMe0yao6p+PMa1Y8thCOHsSccJ/TdZ9swxax9wuefvBs+efeVcP2J+/xotfH2u/5fsZD8gPqNI408cpGl87Z+x4Svv8wL3bf/JR5noknDavud1LJeYFUvsy+/Tlh++4OLZDFnbLboD4rM5+16jz5G2Pi4S8IEU0wfs5R+UxSWd9Ka9N7lYp9fxvqEd1540iBdKHuq3F3zYvbtV8kdEIAABCAwIhFA/I1Iu81aIfCjElgujrZ5l/CwAJHIsviSCExdHPVa11u5bmoBqRXwvfhepSLSw0lk7HKqPnOLY2rls/izxU1iJhVc7rsq5i21/lks5Ra9MuFXlQDGAi+12HlNVVa6VBTqXgtlvZboUbs0frAs/k/rTEs96HVeB9Hiz26efu/xQtjx/GNjls7bw/1XXhDbPxSzeM4ZC7OPE1565O4f5emT+Dtt00XCZx+8GzOLjhXWOujMWCLiq3D5oVv/KON7EIk+lZpY61en1xJlEn9Tzr5geOHBO2Kpit5h67P+Gm4/97iYAfWvg8wb8fejbiODQQACEOhxBBB/PW5LWRAEhicCC8fJbBtPCzFbylzeQXOVCHTJBb13mYhW61A/6lPui1VxcWrvOD+JHVsInSFUglDixq6aqUC0QM2T1ZRZ3lLx5yQ0+X1V7XJRmloCUxdSJ6TxGrQ2Wyk9vv6ca76pRU/rS4vOp0xzK14ueO0amrexO6fH0/sB7p7TLTBbtHZtFM7eZpv4/qEfbOAqexwbZlx05ahDvwu3nntsePymy4OKtS+/wyHh81ie4WczzBYeu/nK8ObzT4RFN9ol9B5tjKKsw3uvvRDWPaxf+OqL/4XJZp47jD3+xOGKw7cL8/bdNEwVi7q/+vj94YrDNGaIxeO/F396P9pY44Rf3vhCOH61GYuyDUtsvleYc4V1w8ijjhaeislh/vb7I8JKux4dPnzz1fCPy35f9GGB9fjfrhpYgF6F4Ffe7Zg4/5Xi9L8ND1x1brj3T2cMrEs42phjh08/eCdcceg2A+sHqq+mFrm++/wmvPnvJ8MDV583CMdU/C2w1lZhtmXXjHUH1w+/OPW68N9/PVbw7DXyKOHKw7cNrz35YLGWCaeYLtZYnD6W25gw/P2C3xR9qs6hitiPNta4xf3XHrvLjybQW/1mcw0CEIAABIYuAcTf0OVL7xCAQJgjMtilSyAoE6hLMrien8SL/hRJQDiZi61wZTFvRqr7nfSlqlSD7nVymbwvjSGBY8uf3SEds6afZTGEuatmakVLM5Cmc8rblFn9coGotVnk+k+1s4Sm7qZV7pteXzv3Tlvxcotr6vJp8exajWVZWb8Li27YN4w/+ZixMPovfvDcz7bsWmGhdbeNtf36hrHGmyjsfOE94YwtFg8TTT1j2Oy3V4ST1pmzqLe373XPhgev6V+IMgnACSafpnAblfgbZbTRw6UHbBrr860W1j+yf/j9VkuHt6JA2vmie6PY2T6Kn0d/IP40kV0veSBcc/RO0QL5kzD78muHq4/aqahBuPnvrgp3RDEkN9G++5w4sLD8Hlc8GvrvvGoYqdfIA8XfQutuF6ZfcNk4/iaxNuA3YYxxxw9fxAL1251zS7hwz3UK4TfHiuuFGRdZIc5lu4Hrz8WfXEnXOeT34fzdVBuz/NA8d42F7/vtuEp4/z8vDnKTxd/XX34eZlho+XDx/huFb776shCZ77zyfFzbjmGaeRcPa/zy1HDy+vMU4m+2WMRerGUJ3TWWwjhj88XDXCtvUPC8/dxfx3X2Cr1HH7NwJ+WAAAQgAIGeTQDx17P3l9VBYDghMIO+gneJO1vqnGHSIklxf3qdlnXQPa2SrVg02lLXSiymGS2FxRYxu1dKLOUi0u6WjuOz1cuZR9WPY960Lgk2zSm1tll82oro9+lYdhO1ALM1rSx20UJMY5e5yNo9VePlyV7Sx8GWwzLh7Ayquj/lps/TMXXNa/0qir8lovgbPYq/fX/w3K269wmx+PsT4aFr5Q4aCvH2eLTyff7pR2GZrX8Zztvp58Xn2/W7Jca6HVQUUp9ugaVjn7uEi6L1T+Lv+ftuCf/8yyVxjGljIfjrw2/WnK1os94R5xWxfU/d/udS8bfbpQ8WokhxeHNE8aci8DpGG3OscPt5x4cHrz0/7HnlY6Hf9iuFsaJVcY0DTglnbbV0GG/SqQeKv01O+FNRLF5z8PHT6WcLO/S/I7zXJdB6RbH48Tv/DedF4eiju5a/XjFOcfPfXR2eu/fmcHcscJ8fhZiL1r4P33i1sIp++/WA/dE4t5xzdHjhgduL9/vf8Hw4eYP5wmKb7BaFbq8opg8fhNVnH70X1j307PDIjZdEC+ifC+HMAQEIQAACPZ8A4q/n7zErhMBwQmCyOI8d46mfqciRVUzCSVY4x/PZCpZbBy2gLHC0NFkrUkGpa1Ui0MIrtehpXM/HbqK5tSy33Nny5nZ+X2X5S2MAc6tfWaIWl0zIxZ3HSYuopywtSv1ZmfjzXCxayyyD2gcnSLEraZ7cJo0n1L0vRsvYlGG57Q6Kbp+K9xz0aCX+ltx8z3DB7msVDVKxJBdGX5P4e+bOG8MTt1w1iChTm/Ra7vY5anTHPOAvL4bj+vYJy25zQJF45v4r+/1gfsvvcGiME3wnjB3dIT95541wz6Wntxd/M8we1j7ojHDmlktW/o51V/ytEwWZLHDXnbBXaZ8SfxNNOUOYdKa5IrM1w/uvvzSQ2y1nH1XEDOqQ+PvdBvOGxTfZvbByypKqQ0L5iVuuDk/fcV10/Zw0zLzEKmHh9XcMd110cnjkhosq18EFCEAAAhDoGQQQfz1jH1kFBDqEgArB7xTPaeKZZ/y0lU9LsXjRZxZqEngWZ6mYKiuJ0Mpt1HX1LJR8rxE6GUyreDzdmwtCzdUlK/IELKmIS9uVlWZQ2+8TqAyYVWrNy7da/amfvIah2ljYepw8YYx5uk8LOsdo5lY+75mthnbh/Vfs4OWik50uuCs8cG3/IiZOx8/6zBHdLcctLGoLrrNNOH/X1cOY404Qdv7jvYX74cTTzDRQ4On+ISn+5Oa45oGnFYlXlPClz8LLhxV2PCz022Gl8OX/Pg3jTjxZ+CYmg/n0/bfDJNPNGtY++MzCJfXsbZcr4vZSy9+C62wb3SyXG8TtUyJtzysfDZcd/IvwymP3hV6jjBImmmrG8NYLTw3cpO6IvxV2OjxMEhPFXLzfhjGusCxj7PfxiK88fl9Y84DTCiujrI0a5+2Xng3XHLNLmHruRYtrJ0fxJ7E469KrhzNTt88tlggj9+4d4xxfK9gsssGORUyg3Gs5IAABCECgZxNA/PXs/WV1EBgOCaikg5LAyBVUmTotMCw8FGtWVvbBQlBWPYsW1/krc3/U0nMRmLtg5klTUlwaz/F//jwXfH5v91DXDHQcXRoP6D+3qUgrSwyjNbkgul08q1wzLYLz7KKar6x3FoZVWUJ93WwlsM0kZWp3V6/Le6Wfchd8YyA4WZOUrGTyWeYpyivIMiVR8e6rz4eyhC+zL7liWGHb/cNJmw2wFg4J8VeUeojWLsWyKanLrdEd0qUeFEe4wJpbFWN9+b9Pwp8O2rJIKKNj9z89XMTu9dt+xeJ9Kv7kjrnK7seGPjHhi7KHPnC1Er6cGSadca5YDuK3RTyhEqfcffEpRUKVWWOc3eqxTIRE7/8+/qBwq+y/c9/C2lYW8zfuJJOHA/7vxfDWi88MnKsSyij+MT3ShC99YnzhyjFZzbk7rRI2Of7SYoxp540JX2K20DThywTRTXaiqWYYJOHLvH03K5LfaC1fRA6XH7zVQCviIAPyBgIQgAAEehQBxF+P2k4WA4FOISAxo6Qgs8RT2T516nCRcMfOVZV+cA08ixpbqqrWbxFYlsBFbeQ6autZmuGzLFmMs2um1jmLs7SovftJBWMq1tIYw9Qyp/lIAOcunF6bM36mgs5CNb1HjKpEo8WexVwqSJ1EJ2XpMdWf2ph/8wLuk046Qdh999XC9jusUli5pp5qq/Dxxxa9nfIcD//zrCoNMfzPnBlCAAIQgMDQIID4GxpU6RMCEKhJYP143+JdwktWJyV7kQCU1co1AV3mIHUTTZOeSFyl8WlqV5XhUvc55i4VTxJ/Fkq2KqYiMLUC6rr6cHvH7GnM9+MpIZsmRrHg8zqExq/ThDKes+5P4xh1v9erP9l5+QmjthXP1krHH+p66tqaFqH3OtyH5pUKSbub+p8K9yOR9kA8P665z9/fNvvsU4e99l4rbLzxkmHUUXuHzz//Mlxw/i3h4IMvCu+8I/HMMSQJIP6GJE36ggAEIND5BBB/nb+HrAACHU5ghTh/pb1PRZkEjuLVnLjFcXj6k2WRJoFowWSLoUWSxaCEmMWg+rdQE7JUQMrSltcLzLORSvg4IY0LwVs8WeBJtFkU2lUy/zNri1/q0mlRpc+cpVM/Pecqt01f1xi2FHptqTBzX7rWymIoDrqeJoUxW61Zr9+M5z+77qn36CnhyMorzxv22HONsMIK8xSN3nvv4/D7M/8STjnluvDWW8r0ygEBCEAAAhCAwNAmgPgb2oTpHwIQqEFg/njP5vGUsJMFSyJLVsAy0ePEMKnbpIZwspV0uDS7pwWN+szdSWUl02HxlSc6sZBTWwtRZ8G0W6f6l3jSYfdIi0Nb+vzTbTROWkrBVkdZwNx/HnuncXSklkKN45ILFqapta+Mo/sxL1tF7QJqsat90GvxVDv1AQAAHo5JREFUfTaeL6WAW74eZ5wxwhZbLBd22bVvmHHGyYt7n3/+9XDKydeF/v3/Fj79tKyQfO3uuRECEIAABCAAgW4SQPx1Exi3QwACQ4tAn9jxDvFUsheJILtXyiJXFrum6xZOEixpbb2yOeq63Rh13dkU9WfQVsdUUKVC0FZGCya7XlpQui/Vj0sL1dv904LM89J7zT2t4+e4OmfpTMdwjJ7majFoceg+xcNrcbxfVSIctbHQ9Nol/jwvXfdYGltiVPF99dw8Z511qrBTrNu32ebLhHHGGbOY4G23PRZO/t2fw/XXPxC+jRkmOSAAAQhAAAIQ+PEJIP5+fOaMCAEIVBKYMF7ZKJ4q3i3hJEEiq5wEoC12qRDUdYskl1qQgMmFkQZMhZ8n4KQtjr2zZc+WPs/B4i61xtmqZyuf/pxK/MmqmKfpT7N+WjCmbqgeV/OS0JQF0fF9VUlv3KfHSuP3ypK2eM1ul8YtiqPFY+puqntfiafcPFsLtlFHHSWsvfaiRQKXpZaavRjss8++CBf/8fZw6qnXh8cff4nnHgIQgAAEIACBYUwA8TeMN4DhIQCBMgIzxg/XjedU8ZRrYFrfT4JEgiu1sNnCldb8k1hJLXWtipprDi7TkGbxtFtmKjhz0ZWKKcf85WuyFc3zdNKVVCQ6UYvEny2a6icfz33lSW1sSZSQS/tNRa/H8L2uKZjGC5qZ2j0Uz1dbPqIzzTRF2GabFcPmWywbJp74J8W9//rXf4p4vvPP/1v44AO71PKkQwACEIAABCAwrAkg/ob1DjA+BCDQgsBC8ZqSwch1MC3nYDdINZVIcb1ACZe87IG7131OBGMRloqyqtIIEmP+U2lRlYoru3bqp9wibcWzYM2Lr7dyxdRcNY/UDbXd/WqjdXuOnoM+T91KzcpWQccBuhB8ug3/jW9k7XMM46BbNNZYo4d1110sbLX1CmGJJWSljbvz1dfh6qv/Ec4+6y/RxfPxyiLlPO4QgAAEIAABCAw7Aoi/YceekSEAgVoEJGBUdHvJeMoF0hlA3VhiTwJNAkjuof5Z1rmTtZSVgnCNudw9NM8SmoqxXBRKeNlKaNfRdB65kEstgX4t19Hc0lgmOtN+7Uqqzxy75+tp4hd9lsY1OqPqSGH66ScKvXt/Ep555vp4z3uDwNt66xXD5FNMGG679bGw5ZbLhXXXW2xgLJ+sfOf2uylccMGtZO2s9TxzEwQgAAEIQGDYEUD8DTv2jAwBCHSLgKx7feOpUgEDkogMekj0SDTpp7NI6k+cE8bYAmeLXN7eGTPLLG2OLXRSljSRi/qx5a1OqQcnZSlz31Q/rjlYx+KnsV10Xq8tYG0ZTWMfPXfd5wQ5TvDyUVhllbHCn6/bMuyw/Rnh3HNvGgjngAPWC0cetWl4992PB7p1KkvnFVfcHc479+Zw551PdmsXuRkCEIAABCAAgWFHAPE37NgzMgQg0IiAksKsGs9ZuoRdWvTcGT/tymgBZeudRZoGLiuWnsYMenLuw+UZ9LnjCe1WKbGl/pQVU7GIeTIXv7fVTe/d1tdscbRbpsWhxqsSgi7s7vnY6ldmnUzdT8VHAlbrfS6ezxeLlYXv92ftFPbdt3/4+qtvwu57rB4tgpMO3KU77ngi/OGCW8Lll98dPvnEQrPRJtIIAhCAAAQgAIFhQADxNwygMyQEIDAkCEwdO5EIVP04CS+drhMooaN4tdxFNB1X4sUiyW0linJRmCZccaIU35PG9dn9VEJM83BNP2fJtLUwrU/oxC6+pvmUxeA5ltFC0dbDNPuoi7HnbC1M/bn616lELk90zfP7NhKAZ5+zS1Bhdh1vvPFeOP20G8JFF90eXn75rSGxcfQBAQhAAAIQgMAwIoD4G0bgGRYCEBhSBOaKHa0cz3G7RJeEnzNWWgCWJXjR+C5voNdqI1HkIvK2zNliZkucrWwWnGproSdLmu/PC7vb6qh+PD8LS8/ZJRf0ucfX/akgddxi+plrHqYWv7RvX9f6Xo7nM11rL9+Df7/QL0w77U+L8gxzzbnrkNoo+oEABCAAAQhAYBgTQPwN4w1geAhAYEgQ0J+ypeK5dDxHj6dr2DnZSVmReCdkcWkHiykJxrL7LQp1zQLOZRlcW9DlIiwIXTMvLdie1gz02i0YU6tfWkJC96UurGldQN2XWwu1JgtbzVdrerbrbF2vz66fDzzwXFhggT4/iAEcErtFHxCAAAQgAAEIDBsCiL9hw51RIQCBoUJA8XbLxFNFxhUbqEMiSCJNorAszs8TcfycXTFt4bPlLbeq2Z0yjQl0KYnU6qb+7eppC5+up3PxWHJFVYKa/EhjDPP4P8cIupSFrrsw/Afx9VPxHBDT1+6w8HPSl/x9u/ZchwAEIAABCEBg+CaA+Bu+94fZQQACjQlMGVvOF8+Z4qnsoLaOyRLmGDtb8dKyDBJRyrhZllFUk7FFLRdvuuYsm2kdQH2eunzqvV03Uwujs406rs/WvbQAewrD91u02g1Vn6tUg7JwvlSbXpXQQwDWRsiNEIAABCAAgeGeAOJvuN8iJggBCAw+gT6xi/njOW08LdrybJv6c6jPJMhkKbRAs+XP7qG5S6jus0BzYpa07p5nn2YL9WcuSK9xLU49jv8823XVgtLzVn8Wlern7Xi+Fk/F9NkCWZ/cIYdsGP7zn/cGKfPg1kWdv8knCEcccWn9DrkTAhCAAAQgAIHhjgDib7jbEiYEAQgMPQISTrPFc854ThNPuUdauKXulE7+YiuchZcFotqldQPTwu4SXmXWutwV1NZGCTfdr3jBtC6fx8rdTSX6NIbON7rE3uvxZ+tYvqHHlJ4hAAEIQAACEOgUAoi/Ttkp5gkBCAwFAhN0iUCVi5gknhPF066gEncuHJ8Pbaugk8CkbqOyGqblHOxiqj4k0Jw1NM0mqnHcp+7LXUrVTpZB1RF8JZ4vxfPDocCDLiEAAQhAAAIQ6MkEEH89eXdZGwQg0ICAROBU8Zwsnno9VjzHSASZRJqsbxJoefIVDacELKn4y6fgWoFum2bmtAVQIk9xe+93ne/GnxKVHBCAAAQgAAEIQKA5AcRfc3a0hAAERggC+jM5XjzHj6dqCY4dTyWDkSD0qSyjOpWp01Y8izvHBKbxgLpHIlCJZVKBJ8GH++YI8VixSAhAAAIQgMAwIID4GwbQGRICEOipBPQnVYLQSWNkrUPM9dTdZl0QgAAEIACBTiOA+Ou0HWO+EIAABCAAAQhAAAIQgAAEGhBA/DWARhMIQAACEIAABCAAAQhAAAKdRgDx12k7xnwhAAEIQAACEIAABCAAAQg0IID4awCNJhCAAAQgAAEIQAACEIAABDqNAOKv03aM+UIAAhCAAAQgAAEIQAACEGhAAPHXABpNIAABCEAAAhCAAAQgAAEIdBoBxF+n7RjzhQAEIAABCEAAAhCAAAQg0IAA4q8BNJpAAAIQgAAEIAABCEAAAhDoNAKIv07bMeYLAQhAAAIQgAAEIAABCECgAQHEXwNoNIEABCAAAQhAAAIQgAAEINBpBBB/nbZjzBcCEIAABCAAAQhAAAIQgEADAoi/BtBoAgEIQAACEIAABCAAAQhAoNMIIP46bceYLwQgAAEIQAACEIAABCAAgQYEEH8NoNEEAhCAAAQgAAEIQAACEIBApxFA/HXajjFfCEAAAhCAAAQgAAEIQAACDQgg/hpAowkEIAABCEAAAhCAAAQgAIFOI4D467QdY74QgAAEIAABCEAAAhCAAAQaEED8NYBGEwhAAAIQgAAEIAABCEAAAp1GAPHXaTvGfCEAAQhAAAIQgAAEIAABCDQggPhrAI0mEIAABCAAAQhAAAIQgAAEOo0A4q/Tdoz5QgACEIAABCAAAQhAAAIQaEAA8dcAGk0gAAEIQAACEIAABCAAAQh0GgHEX6ftGPOFAAQgAAEIQAACEIAABCDQgADirwE0mkAAAhCAAAQgAAEIQAACEOg0Aoi/Ttsx5gsBCEAAAhCAAAQgAAEIQKABAcRfA2g0gQAEIAABCEAAAhCAAAQg0GkEEH+dtmPMFwIQgAAEIAABCEAAAhCAQAMCiL8G0GgCAQhAAAIQgAAEIAABCECg0wgg/jptx5gvBCAAAQhAAAIQgAAEIACBBgQQfw2g0QQCEIAABCAAAQhAAAIQgECnEUD8ddqOMV8IQAACEIAABCAAAQhAAAINCCD+GkCjCQQgAAEIQAACEIAABCAAgU4jgPjrtB1jvhCAAAQgAAEIQAACEIAABBoQQPw1gEYTCEAAAhCAAAQgAAEIQAACnUYA8ddpO8Z8IQABCEAAAhCAAAQgAAEINCCA+GsAjSYQgAAEIAABCEAAAhCAAAQ6jQDir9N2jPlCAAIQgAAEIAABCEAAAhBoQADx1wAaTSAAAQhAAAIQgAAEIAABCHQaAcRfp+0Y84UABCAAAQhAAAIQgAAEINCAAOKvATSaQAACEIAABCAAAQhAAAIQ6DQCiL9O2zHmCwEIQAACEIAABCAAAQhAoAEBxF8DaDSBAAQgAAEIQAACEIAABCDQaQQQf522Y8wXAhCAAAQgAAEIQAACEIBAAwKIvwbQaAIBCEAAAhCAAAQgAAEIQKDTCCD+Om3HmC8EIAABCEAAAhCAAAQgAIEGBBB/DaDRBAIQgAAEIAABCEAAAhCAQKcRQPx12o4xXwhAAAIQgAAEIAABCEAAAg0IIP4aQKMJBCAAAQhAAAIQgAAEIACBTiOA+Ou0HWO+EIAABCAAAQhAAAIQgAAEGhBA/DWARhMIQAACEIAABCAAAQhAAAKdRgDx12k7xnwhAAEIQAACEIAABCAAAQg0IID4awCNJhCAAAQgAAEIQAACEIAABDqNAOKv03aM+UIAAhCAAAQgAAEIQAACEGhAAPHXABpNIAABCEAAAhCAAAQgAAEIdBoBxF+n7RjzhQAEIAABCEAAAhCAAAQg0IAA4q8BNJpAAAIQgAAEIAABCEAAAhDoNAKIv07bMeYLAQhAAAIQgAAEIAABCECgAQHEXwNoNIEABCAAAQhAAAIQgAAEINBpBBB/nbZjzBcCEIAABCAAAQhAAAIQgEADAoi/BtBoAgEIQAACEIAABCAAAQhAoNMIIP46bceYLwQgAAEIQAACEIAABCAAgQYEEH8NoNEEAhCAAAQgAAEIQAACEIBApxFA/HXajjFfCEAAAhCAAAQgAAEIQAACDQgg/hpAowkEIAABCEAAAhCAAAQgAIFOI4D467QdY74QgAAEIAABCEAAAhCAAAQaEED8NYBGEwhAAAIQgAAEIAABCEAAAp1GAPHXaTvGfCEAAQhAAAIQgAAEIAABCDQggPhrAI0mEIAABCAAAQhAAAIQgAAEOo0A4q/Tdoz5QgACEIAABCAAAQhAAAIQaEAA8dcAGk0gAAEIQAACEIAABCAAAQh0GgHEX6ftGPOFAAQgAAEIQAACEIAABCDQgADirwE0mkAAAhCAAAQgAAEIQAACEOg0Aoi/Ttsx5gsBCEAAAhCAAAQgAAEIQKABAcRfA2g0gQAEIAABCEAAAhCAAAQg0GkEEH+dtmPMFwIQgAAEIAABCEAAAhCAQAMCiL8G0GgCAQhAAAIQgAAEIAABCECg0wgg/jptx5gvBCAAAQhAAAIQgAAEIACBBgQQfw2g0QQCEIAABCAAAQhAAAIQgECnEUD8ddqOMV8IQAACEIAABCAAAQhAAAINCCD+GkCjCQQgAAEIQAACEIAABCAAgU4jgPjrtB1jvhCAAAQgAAEIQAACEIAABBoQQPw1gEYTCEAAAhCAAAQgAAEIQAACnUYA8ddpO8Z8IQABCEAAAhCAAAQgAAEINCCA+GsAjSYQgAAEIAABCEAAAhCAAAQ6jQDir9N2jPlCAAIQgAAEIAABCEAAAhBoQADx1wAaTSAAAQhAAAIQgAAEIAABCHQaAcRfp+0Y84UABCAAAQhAAAIQgAAEINCAAOKvATSaQAACEIAABCAAAQhAAAIQ6DQCiL9O2zHmCwEIQAACEIAABCAAAQhAoAEBxF8DaDSBAAQgAAEIQAACEIAABCDQaQQQf522Y8wXAhCAAAQgAAEIQAACEIBAAwKIvwbQaAIBCEAAAhCAAAQgAAEIQKDTCCD+Om3HmC8EIAABCEAAAhCAAAQgAIEGBBB/DaDRBAIQgAAEIAABCEAAAhCAQKcRQPx12o4xXwhAAAIQgAAEIAABCEAAAg0IIP4aQKMJBCAAAQhAAAIQgAAEIACBTiOA+Ou0HWO+EIAABCAAAQhAAAIQgAAEGhBA/DWARhMIQAACEIAABCAAAQhAAAKdRgDx12k7xnwhAAEIQAACEIAABCAAAQg0IID4awCNJhCAAAQgAAEIQAACEIAABDqNAOKv03aM+UIAAhCAAAQgAAEIQAACEGhAAPHXABpNIAABCEAAAhCAAAQgAAEIdBoBxF+n7RjzhQAEIAABCEAAAhCAAAQg0IAA4q8BNJpAAAIQgAAEIAABCEAAAhDoNAKIv07bMeYLAQhAAAIQgAAEIAABCECgAQHEXwNoNIEABCAAAQhAAAIQgAAEINBpBBB/nbZjzBcCEIAABCAAAQhAAAIQgEADAoi/BtBoAgEIQAACEIAABCAAAQhAoNMIIP46bceYLwQgAAEIQAACEIAABCAAgQYEEH8NoNEEAhCAAAQgAAEIQAACEIBApxFA/HXajjFfCEAAAhCAAAQgAAEIQAACDQgg/hpAowkEIAABCEAAAhCAAAQgAIFOI1BL/I066qjhtNNOC8svv3yYaKKJwmuvvRaOO+64cMEFFwxc7zjjjBPOPvvssOqqq4ZPPvkknHjiieG3v/3twOuTTTZZOPfcc8MSSywR3n777fCrX/0qXHzxxQOvzzLLLKFfv35h7rnnDi+//HLYbbfdwt/+9reWPL/77rsw++yzhyeffHKocF9zzTXDCSecEDT3++67L2y11VbhpZdeKsZaeumlwyGHHBLmnXfe8NVXX4WJJ5645RxGGWWUcPLJJ4eNNtoofPvttwWL/fffvza/vPOdd945bLnllmGOOeYI1113XVhvvfV+MP72228f9t5772L+b7zxRth6663DHXfc0XKe2t+nn366WOcCCyxQe/+GygbQKQQgAAEIQAACEIBAjybw4osvhl122SXccMMN3V6nvv/usccehX546qmnBvnuWtbZkP4+3u0JdzVopXtmmGGGcNFFF4U+ffqEXr16Fevab7/9wt133910uEHa1RJ/Y445ZiFUJPZeeOGFsNBCC4W//OUvYZ111gm33XZb0eH5558fxhtvvLDZZpuFqaeeOtxyyy2F2Lj++uuL67fffnsh0iRG1F6CRULw0UcfDdoICY7zzjsv/OY3vwkSXeecc06YccYZw5tvvlm50KEp/jT2gw8+WKzxzjvvDMccc0wxXwsi/ZxpppmChLGEcDvxd9hhh4VVVlkl9O3bN4w++ujh5ptvLgS1zjr8cghrrbVWISIlyH/2s5/9QPxtscUWxYMisfnYY48VAlAPkIR7q+PCCy8MU045ZRhrrLEG+QVqtX9D5EmkEwhAAAIQgAAEIACBEY7A4Ii/5ZZbLkwwwQSFUNJ349RwUQZySH8fb7VZ0ikjjSSpNejRTvfIoCZdIS7qQ+vq379/mGSSScKXX3452M9HLfFXNsqVV14Z/vnPf4YjjzwyjDHGGOH9998vgD/++OPF7UcddVSYddZZw9prrx2mm2668Mwzz4Sf/vSnxX06pGjfeuutsNdee4Vll102XHrppYWIkaDRcdddd4XLLrssnHLKKZWLTMXffPPNV1jWNKYscTfeeGPYddddCyukDgE8/fTTw/rrrx9mnnnm8I9//CNssskmhRWy7DjiiCPCbLPNVog/HWOPPXZxr4SrxJSPpZZaKlxxxRVtxd8rr7wSZK2T6NWxzTbbhJ122qmwHLbj12qXDz300ML6mVr+9KDJcqcxJDLrHiussEI46KCDigdMc/UvULv9q9s/90EAAhCAAAQgAAEIQMAE5AW4wQYbhC+++CJ88803hRfgnnvu2W1AMnrIethO/A3u93HpDXk2yvNOOkZiUhqm7KgSf93RPfpOv9pqq4Vrr722MM60M+LUAddI/I022mjh+eefD7vvvnu46qqrClPrAw88UFjBtFAd6667bmEtkwVNljyBkojwsc8++4QVV1yxOGWuXX311QsR6EMWMfW33XbbVa4jFX+agyyU999/fyHErrnmmsLFUdYvHRJ/H374YTGORJzE4cMPP1xYIssOtdd1iUAfTzzxRLGm1F21jviTRVSiVxZRPXQ65p9//sJ8K5bt+Ol+iUYJYlkZ06NM/E0xxRTh1VdfLcSv1jfyyCOHq6++urDefv7550XzvD8JUK1XYle/OOkvULv9q/OgcQ8EIAABCEAAAhCAAARyAmWWP3kGTjXVVKWw9F16rrnmGuRaHfE3uN/HZaSSF+O2225b6Ax9f7/pppuCjCePPPLID+ZaJf7q6h4ZcuS517t378I7Uh6VQ+JoJP7kGjj55JMHmVq1sMUXX7wQE+OPP/7AOckdUfdNOumkYdNNNy1EyDzzzDPwuqxSWsQiiyxSWJukpGXW9CHL4fTTT1+4LVYdrdw+ZdWTOF1wwQWL5nqw1Kdi7XTsuOOOhRVwmWWWKe1e8YZak6yJPiS+tKazzjpr4Gd1xJ/FmB46CVAd8ud97rnnChdQia1W/FptdJn4E9N77rkn/PWvfy34SURL/P39738Pv/zlL0u7k6jU/7gceOCBIf8Fard/Q+JBpA8IQAACEIAABCAAgRGPwOC4fZpWHfE3uN/H99133+I7u/SDDxmrPv3000HyePhalfjrju6RkUj6SAYuCcAhcXRb/J155pmFUJO4++ijj4o52HIlZepDFqRjjz12oOVPsXwScz4kBldaaaWBlj+ZNCUmfZx66qmFVUyWP1ncZDXToSQmtryl4k++vhpDFjXFqym+TRY+WxvzByt9SA444IBC9OhQfN/Pf/7zQtE/9NBDhVurD7m0ak1NLX/6HwxZ5HSIoQRaavmr4tdqo8vEn/43RC654nnrrbcWzeV+q7XIlTU/5pxzznD55ZcX/4siy2D+CyTLX6v9GxIPIn1AAAIQgAAEIAABCIx4BH4s8WfLX9Pv4wofU/JHe9FppxS/JwPL5ptvXhhczjjjjIEbqPE++OCDge8V7nXJJZcUHo+tdE/ZEyANIsOZElAO7tEt8adFL7zwwoWoSBfjmDUJLwk1HRYaVTF/sqBJnDnmTzBkTrXbqESYBEndmD9Z6pQNR2paolSWP1n6pp122mI+rcRfGUS5eyp+UO6rOiQoNV+tv2nMnzbdCXBk9VRcXRrzV8Wv1SaXiT/tx3vvvVeIWCfk0T44DjPvTxbSo48+Onz88cfFJbXX/zC8++67BQNZdPOYzXT/BvchpD0EIAABCEAAAhCAwIhJ4N///neR5T/N9pkafnIqqgqgfBfpUcfyp/vlMtr0+7jCpzSuklvWOVrF/HVX9+h7uL7HK2fK4B61xZ/MmnLvVFyehEV+KBPouOOOOzDbp8SYfGItdhR/J9WqWD+ZTLXBebZPBXmedNJJRVye3DOVTVMlCqqO1PInJawxVUJimmmmKZKwTDjhhI3Fn7N9ytQqd0+JI7l4OpBUAZhyp1xyySULS6BMyToUsFp2HH744YWVU0pfrp7yEdb/DjjbZzt+eZ+K49P/NkjsSqBtvPHGRbIcJbvRIX5yud1www0LX2EFimodZW6fEnvaOx8KvP3FL34RVl555YHZVlvt3+A+hLSHAAQgAAEIQAACEBgxCcgTTklTWhl8qsjI00/fcyXIdthhh7DYYosVhqSqrJiD831cIW/KjyGvRAtVec1pLCe8TOfZLttnle6xkU1efFqbhLGMPfLec8m5wXlSaok/mUelsmXm/PrrrweOJ/Wp2DkdSkuq8gyyNsn3VfXx8jp/8lV1nT+5WabukxIwaZ0/JSupU+dPIGTx02arzqDmqvdKRKOHoKnlT2uS8Evr/EkQGbqEoMof5EdZSlfdI6Gmhzqt8+dkNHX4KUGNrKFyO9Whh0AZhtJD83EMoyyVEpdrrLFG+OyzzworaprwJe8v7afsf08UcNpq/wbnIaQtBCAAAQhAAAIQgMCISUBl0BTuJTdJfdesSsZYRkffWVVuLj30Xd3f/xWupsN6ZXC/j8tjT3kyFPKm7/wSffp+rYST+VEl/nRfK90j/SErnzSNjEoaQ6K1THc0eWJqib8mHQ/tNhKbcu+Uq2irWoBDex70DwEIQAACEIAABCAAAQhAoBMIdKz4U+IXJWqRiycHBCAAAQhAAAIQgAAEIAABCLQm0JHiTzU2dKgWnROasNEQgAAEIAABCEAAAhCAAAQgUE2gI8UfGwoBCEAAAhCAAAQgAAEIQAAC3SMg8ccBAQhAAAIQgAAEIAABCEAAAj2cwP8DbJhU4AKo1HcAAAAASUVORK5CYII=\" width=\"999.4166666666666\">"
+      ],
+      "text/plain": [
+       "<IPython.core.display.HTML object>"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "# Plot current status of PASEOS and get a plotter\n",
+    "plotter = paseos.plot(sim, paseos.PlotType.SpacePlot)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 5,
+   "metadata": {
+    "scrolled": false
+   },
+   "outputs": [],
+   "source": [
+    "# Run some operations and inbetween update PASEOS\n",
+    "for i in range(100):\n",
+    "    sim.advance_time(10)\n",
+    "    plotter.update(sim)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {
+    "scrolled": true
+   },
+   "outputs": [],
+   "source": [
+    "# Write an animation of the next 50 steps a 100s to a file called test.mp4\n",
+    "plotter.animate(sim,dt=100,steps=50,save_to_file=\"test\")"
+   ]
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "Python 3 (ipykernel)",
+   "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.10.6"
+  },
+  "vscode": {
+   "interpreter": {
+    "hash": "cec805858b69cacb2b7ad611a1d16c309b9d5c2fd3283013a8f0cd0423ba3fc5"
+   }
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/paseos/__init__.py b/paseos/__init__.py
index f4b0f3cf..962470b7 100644
--- a/paseos/__init__.py
+++ b/paseos/__init__.py
@@ -4,10 +4,12 @@
 
 from .utils.set_log_level import set_log_level
 from .paseos import PASEOS
+from .visualization.plot import plot, PlotType
 from .actors.actor_builder import ActorBuilder
 from .actors.spacecraft_actor import SpacecraftActor
 from .actors.ground_station_actor import GroundstationActor
 
+
 set_log_level("DEBUG")
 
 logger.debug("Loaded module.")
@@ -27,4 +29,11 @@ def init_sim(local_actor: BaseActor):
     return sim
 
 
-__all__ = ["ActorBuilder", "GroundstationActor", "SpacecraftActor", "PASEOS"]
+__all__ = [
+    "ActorBuilder",
+    "GroundstationActor",
+    "PASEOS",
+    "plot",
+    "PlotType",
+    "SpacecraftActor",
+]
diff --git a/paseos/actors/ground_station_actor.py b/paseos/actors/ground_station_actor.py
index da2d95e6..e6706a5a 100644
--- a/paseos/actors/ground_station_actor.py
+++ b/paseos/actors/ground_station_actor.py
@@ -7,9 +7,7 @@
 class GroundstationActor(BaseActor):
     """This class models a groundstation actor."""
 
-    def __init__(
-        self, name: str, position, epoch: pk.epoch
-    ) -> None:
+    def __init__(self, name: str, position, epoch: pk.epoch) -> None:
         """Constructor for a groundstation actor.
 
         Args:
diff --git a/paseos/actors/spacecraft_actor.py b/paseos/actors/spacecraft_actor.py
index 6e10d5f4..4006415b 100644
--- a/paseos/actors/spacecraft_actor.py
+++ b/paseos/actors/spacecraft_actor.py
@@ -82,7 +82,6 @@ def charge(self, t0: pk.epoch, t1: pk.epoch):
         Args:
             t0 (pk.epoch): Start of the charging interval
             t1 (pk.epoch): End of the charging interval
-
         """
         time_interval = (t1.mjd2000 - t0.mjd2000) * pk.DAY2SEC
         logger.debug(f"Charging actor {self} for {time_interval}s.")
diff --git a/paseos/paseos.py b/paseos/paseos.py
index 424d91da..ee6f2346 100644
--- a/paseos/paseos.py
+++ b/paseos/paseos.py
@@ -144,7 +144,8 @@ def register_activity(
 
         Args:
             name (str): Name of the activity
-            requires_line_of_sight_to (list): List of strings with names of actors which need to be visible for this activity.
+            requires_line_of_sight_to (list): List of strings with names of actors which
+            need to be visible for this activity.
             power_consumption_in_watt (float, optional): Power consumption of performing
             the activity (per second). Defaults to None.
         """
diff --git a/paseos/visualization/animation.py b/paseos/visualization/animation.py
new file mode 100644
index 00000000..1be4e97d
--- /dev/null
+++ b/paseos/visualization/animation.py
@@ -0,0 +1,44 @@
+from abc import ABC, abstractmethod
+from paseos.paseos import PASEOS
+
+
+class Animation(ABC):
+    """Abstract class for visualization."""
+
+    def __init__(self, sim: PASEOS) -> None:
+        """Initialize the animation
+
+        Args:
+            sim (PASEOS): simulation object
+        """
+        self._local_actor = sim.local_actor
+        self._other_actors = sim.known_actors
+        self.objects = list()
+
+    def _sec_to_ddhhmmss(self, time: float) -> str:
+        """Convert seconds to ddhhmmss format
+
+        Args:
+            time (float): time in seconds
+
+        Returns:
+            str: time in ddhhmmss.
+        """
+        m, s = divmod(time, 60)
+        h, m = divmod(m, 60)
+        d, h = divmod(h, 24)
+        return f"T={d:.0f}d{h:.0f}h{m:.0f}m{s:.0f}s"
+
+    @abstractmethod
+    def _plot_actors(self) -> None:
+        """Function to plot all the actors"""
+        pass
+
+    @abstractmethod
+    def update(self, sim: PASEOS) -> None:
+        """Function to update all the objects in the animation
+
+        Args:
+            sim (PASEOS): simulation object
+        """
+        pass
diff --git a/paseos/visualization/plot.py b/paseos/visualization/plot.py
new file mode 100644
index 00000000..580cae60
--- /dev/null
+++ b/paseos/visualization/plot.py
@@ -0,0 +1,33 @@
+from enum import Enum
+
+from ..paseos import PASEOS
+from .space_animation import SpaceAnimation
+
+
+class PlotType(Enum):
+    """Describes the different plot types
+    1 - SpacePlot
+    """
+
+    SpacePlot = 1
+
+
+def plot(sim: PASEOS, plot_type: PlotType):
+    """Creates the animation object
+
+    Args:
+        sim (PASEOS): simulation object
+        plot_type (PlotType): enum deciding what kind of plot object to be made
+
+    Raises:
+        ValueError: supplied plot type not supported
+
+    Returns:
+        Animation: Animation object
+    """
+    if plot_type is PlotType.SpacePlot:
+        return SpaceAnimation(sim)
+    else:
+        raise ValueError(
+            f"PlotType {plot_type} not known. Available are {[e for e in PlotType]}"
+        )
diff --git a/paseos/visualization/space_animation.py b/paseos/visualization/space_animation.py
new file mode 100644
index 00000000..058b79e6
--- /dev/null
+++ b/paseos/visualization/space_animation.py
@@ -0,0 +1,430 @@
+import numpy as np
+from dotmap import DotMap
+from typing import List
+import matplotlib.pyplot as plt
+import matplotlib.animation as animation
+from matplotlib.artist import Artist
+from matplotlib.colors import LinearSegmentedColormap
+from mpl_toolkits.axes_grid1 import make_axes_locatable
+from loguru import logger
+
+from paseos.actors.base_actor import BaseActor
+from paseos.actors.spacecraft_actor import SpacecraftActor
+from paseos.actors.ground_station_actor import GroundstationActor
+from paseos.paseos import PASEOS
+from paseos.visualization.animation import Animation
+
+
+class SpaceAnimation(Animation):
+    """This class visualizes the central body, local actor and known actors over time."""
+
+    def __init__(self, sim: PASEOS, n_trajectory: int = 32) -> None:
+        """Initialize the space animation object
+
+        Args:
+            sim (PASEOS): simulation object
+            n_trajectory (int): number of samples in tail of actor
+        """
+        super().__init__(sim)
+        logger.debug("Initializing animation")
+        # Create list of objects to be plotted
+        current_actors = self._make_actor_list(sim)
+        self._norm_coeff = self._local_actor._central_body.radius
+
+        for known_actor in current_actors:
+            pos, _ = known_actor.get_position_velocity(self._local_actor.local_time)
+            pos_norm = [x / self._norm_coeff for x in pos]
+            self.objects.append(DotMap(actor=known_actor, positions=np.array(pos_norm)))
+
+        with plt.style.context("dark_background"):
+
+            # Create figure for 3d animation
+            self.fig, default_ax = plt.subplots(
+                1,
+                2,
+                figsize=(10, 5),
+                facecolor="black",
+                dpi=100,
+                layout="constrained",
+                gridspec_kw={"width_ratios": [3.5, 1]},
+            )
+
+            # Removing defaultax to add projection
+            default_ax[0].remove()
+            self.ax_3d = plt.subplot(121, projection="3d")
+
+            # Get rid of the panes
+            self.ax_3d.xaxis.set_pane_color((1.0, 1.0, 1.0, 0.0))
+            self.ax_3d.yaxis.set_pane_color((1.0, 1.0, 1.0, 0.0))
+            self.ax_3d.zaxis.set_pane_color((1.0, 1.0, 1.0, 0.0))
+
+            # Get rid of the spines
+            self.ax_3d.xaxis.line.set_color((1.0, 1.0, 1.0, 0.0))
+            self.ax_3d.yaxis.line.set_color((1.0, 1.0, 1.0, 0.0))
+            self.ax_3d.zaxis.line.set_color((1.0, 1.0, 1.0, 0.0))
+            self.ax_3d.get_xaxis().set_ticks([])
+            self.ax_3d.get_yaxis().set_ticks([])
+            self.ax_3d.get_zaxis().set_ticks([])
+
+            # how many samples from histories to visualize
+            self.n_trajectory = n_trajectory
+            self._textbox_offset = 0.1
+
+            # Create figure for LOS
+            default_ax[1].remove()
+            self.ax_los = plt.subplot(122)
+            xaxis = np.arange(len(current_actors))
+            self.ax_los.set_position([0.75, 0.7, 0.2, 0.2])
+            self.ax_los.set_xticks(xaxis)
+            self.ax_los.set_yticks(xaxis)
+            self.ax_los.set_xticklabels(current_actors, fontsize=8)
+            self.ax_los.set_yticklabels(current_actors, fontsize=8)
+
+            # plot the objects
+            self._plot_central_body()
+            self._plot_actors()
+            los_matrix = self._get_los_matrix(current_actors)
+            self._plot_los(los_matrix)
+
+            # Write text labels
+            self.date_label = plt.annotate(
+                self._local_actor.local_time,
+                xy=(0.01, 0.01),
+                xycoords="figure fraction",
+            )
+            self.time_label = plt.annotate(
+                f"t={sim._state.time:<10.2e}",
+                xy=(0.99, 0.01),
+                xycoords="figure fraction",
+                horizontalalignment="right",
+            )
+
+            plt.ion()
+            plt.show()
+            plt.pause(0.0001)
+
+    def _plot_central_body(self) -> None:
+        """Plot the central object as a sphere of radius 1"""
+        central_body = self._local_actor._central_body
+        central_body.radius
+
+        u, v = np.mgrid[0 : 2 * np.pi : 30j, 0 : np.pi : 20j]
+        x = np.cos(u) * np.sin(v)
+        y = np.sin(u) * np.sin(v)
+        z = np.cos(v)
+        self.ax_3d.plot_surface(x, y, z, color="blue", alpha=0.5)
+
+    def _get_los_matrix(self, current_actors: List[BaseActor]) -> np.ndarray:
+        """Compute line-of-sight (LOS) between all actors
+
+        Args:
+            current_actors (List[BaseActor]): All actors in the simulation
+
+        Returns:
+            np.ndarray: LOS matrix with nonzero elements if actors are in LOS
+        """
+        local_time = self._local_actor.local_time
+        los_matrix = np.identity(len(current_actors))
+
+        for i, a1 in enumerate(current_actors):
+            for j, a2 in enumerate(current_actors[i + 1 :]):
+                if a1.is_in_line_of_sight(a2, local_time) is True:
+                    los_matrix[i, j + i + 1] = 1.0
+
+        # make los_matrix symmetric with diagonal entries equal to 0.5 to make colorbar nicer
+        los_matrix = los_matrix + los_matrix.T - 1.5 * np.diag(np.diag(los_matrix))
+        return los_matrix
+
+    def _populate_textbox(self, actor: BaseActor) -> str:
+        """Extracts information from an actor and builds a string
+
+        Args:
+            actor (BaseActor): an actor
+
+        Returns:
+            str: text to populate the textbox.
+        """
+        info_str = f"{actor.name}"
+        if isinstance(actor, SpacecraftActor):
+            if actor.battery_level_in_Ws is not None:
+                battery_level = actor.battery_level_ratio * 100
+                info_str += f"\nBattery: {battery_level:.0f}%"
+
+            for name in actor.communication_devices.keys():
+                info = actor.communication_devices[name]
+                info_str += f"\nCommDevice1: {info.bandwidth_in_kbps} kbps"
+        elif isinstance(actor, GroundstationActor):
+            # TODO: implement textbox for groundstation
+            raise NotImplementedError(
+                "SpacePlot is currently not implemented for actor type" + type(actor)
+            )
+        else:
+            raise NotImplementedError(
+                "SpacePlot is currently not implemented for actor type" + type(actor)
+            )
+
+        return info_str
+
+    def _plot_los(self, los_matrix: np.ndarray) -> None:
+        """Plot the LOS links in a heat map
+
+        Args:
+            los_matrix (np.ndarray): matrix telling what satellites can see each other.
+        """
+        # Create new colormap, with black for two
+        colors = [(255, 0, 0), (0, 0, 0), (0, 255, 0)]
+        new_map = LinearSegmentedColormap.from_list("new_map", colors, N=3)
+        self._los_plot = self.ax_los.matshow(los_matrix, cmap=new_map, vmin=0, vmax=1)
+
+        divider = make_axes_locatable(self.ax_los)
+        cax = divider.append_axes("right", size="5%", pad=0.05)
+
+        cbar = self.fig.colorbar(self._los_plot, ticks=[0, 1], cax=cax)
+        cbar.ax.set_yticklabels(["no signal", "signal"])
+
+    def _plot_actors(self) -> None:
+        """Plots all the actors"""
+        logger.trace("Updating actors.")
+
+        for obj in self.objects:
+            data = obj.positions
+            if data.ndim == 1:
+                data = data[..., np.newaxis].T
+            n_points = np.minimum(data.shape[0], self.n_trajectory)
+
+            logger.trace(f"Position for object: {data}")
+            if "plot" in obj.keys():
+                # spacecraft and ground stations behave differently and are plotted separately
+                if isinstance(obj.actor, SpacecraftActor):
+                    logger.trace("Updating SpacecraftActor.")
+
+                    # update trajectory
+                    obj.plot.trajectory.set_data(data[-n_points:, :2].T)
+                    obj.plot.trajectory.set_3d_properties(data[-n_points:, 2].T)
+
+                    # update satellite position
+                    obj.plot.point.set_data_3d(data[-1, :])
+
+                    # update text box
+                    actor_info = self._populate_textbox(obj.actor)
+                    obj.plot.text.set_position_3d(data[-1, :] + self._textbox_offset)
+                    obj.plot.text.set_text(actor_info)
+
+                elif isinstance(obj.actor, GroundstationActor):
+                    # TODO: implement update of groundstation object
+                    pass
+            else:
+                if isinstance(obj.actor, SpacecraftActor):
+                    trajectory = self.ax_3d.plot3D(data[0, 0], data[0, 1], data[0, 2])[
+                        0
+                    ]
+                    obj.plot.trajectory = trajectory
+                    obj.plot.point = self.ax_3d.plot(
+                        data[0, 0],
+                        data[0, 1],
+                        data[0, 2],
+                        "x",
+                        color=trajectory.get_color(),
+                    )[0]
+                    actor_info = self._populate_textbox(obj.actor)
+                    if obj.actor == self._local_actor:
+                        obj.plot.text = self.ax_3d.text(
+                            data[0, 0] + self._textbox_offset,
+                            data[0, 1] + self._textbox_offset,
+                            data[0, 2] + self._textbox_offset,
+                            actor_info,
+                            # bbox=dict(facecolor="mediumspringgreen"),
+                            verticalalignment="bottom",
+                            clip_on=True,
+                            fontsize=8,
+                        )
+
+                    else:
+                        obj.plot.text = self.ax_3d.text(
+                            data[0, 0] + self._textbox_offset,
+                            data[0, 1] + self._textbox_offset,
+                            data[0, 2] + self._textbox_offset,
+                            actor_info,
+                            # bbox=dict(facecolor="white"),
+                            color="lightskyblue",
+                            verticalalignment="bottom",
+                            clip_on=True,
+                            fontsize=8,
+                        )
+
+                elif isinstance(obj.actor, GroundstationActor):
+                    # TODO: implement initial rendering of groundstation object
+                    raise NotImplementedError(
+                        "SpacePlot is currently not implemented for actor type"
+                        + type(obj.actor)
+                    )
+
+        self.ax_3d.set_box_aspect(
+            (
+                np.ptp(self.ax_3d.get_xlim()),
+                np.ptp(self.ax_3d.get_ylim()),
+                np.ptp(self.ax_3d.get_zlim()),
+            )
+        )
+
+    def _make_actor_list(self, sim: PASEOS) -> List[BaseActor]:
+        """Arranges all actors (including the local) into a list
+
+        Args:
+            sim (PASEOS): simulation object.
+
+        Returns:
+            List[BaseActor]: list of all the actors known to local actor (including itself)
+        """
+        if len(sim.known_actors) > 0:
+            current_actors = [sim.local_actor] + list(sim.known_actors.values())
+        else:
+            current_actors = [sim.local_actor]
+        return current_actors
+
+    def update(self, sim: PASEOS, creating_animation=False) -> None:
+        """Updates the animation with the current actor information
+
+        Args:
+            sim (PASEOS): simulation object.
+            creating_animation (bool): If currently creating an animation. Then draw_idle will be used. Defaults to False.
+        """
+        logger.trace("Updating animation")
+        # NOTE: the actors in sim are unique so make use of sets
+        objects_in_plot = set([obj.actor for obj in self.objects])
+        current_actors = set(self._make_actor_list(sim))
+
+        # if objects do not exist in known actors, remove from plot next update.
+        objects_to_remove = list(objects_in_plot.difference(current_actors))
+
+        # if known_actor does not exist in objects, add the actors and update in plot
+        objects_to_add = list(current_actors.difference(objects_in_plot))
+
+        plot_objects_to_remove = [
+            x for x in self.objects if x.actor in objects_to_remove
+        ]
+        for obj in plot_objects_to_remove:
+            obj.plot.trajectory.remove()
+            obj.plot.point.remove()
+            obj.plot.text.remove()
+
+        self.objects = [x for x in self.objects if x.actor not in objects_to_remove]
+
+        for obj_to_add in objects_to_add:
+            self.objects.append(DotMap(actor=obj_to_add))
+
+        # update positions of objects
+        for known_actor in current_actors:
+            for obj in self.objects:
+                if obj.actor == known_actor:
+                    pos, _ = known_actor.get_position_velocity(
+                        self._local_actor.local_time
+                    )
+                    pos_norm = [x / self._norm_coeff for x in pos]
+                    if "positions" in obj:
+                        if obj.positions.shape[0] > self.n_trajectory:
+                            obj.positions = np.roll(obj.positions, shift=-1, axis=0)
+                            obj.positions[-1, :] = pos_norm
+                        else:
+                            obj.positions = np.vstack((obj.positions, pos_norm))
+                    else:
+                        obj.positions = np.array(pos_norm)
+        self._plot_actors()
+
+        # Step through trajectories to find max and min values in each direction
+        coords_max = [
+            self.ax_3d.get_xlim()[1],
+            self.ax_3d.get_ylim()[1],
+            self.ax_3d.get_zlim()[1],
+        ]
+        coords_min = [
+            self.ax_3d.get_xlim()[0],
+            self.ax_3d.get_ylim()[0],
+            self.ax_3d.get_zlim()[0],
+        ]
+        for obj in self.objects:
+            coords_max = np.maximum(obj.positions.max(axis=0), coords_max)
+            coords_min = np.minimum(obj.positions.min(axis=0), coords_min)
+        self.ax_3d.set_xlim(coords_min[0], coords_max[0])
+        self.ax_3d.set_ylim(coords_min[1], coords_max[1])
+        self.ax_3d.set_zlim(coords_min[2], coords_max[2])
+
+        # Update LOS heatmap
+        current_actors = list(current_actors)
+        los_matrix = self._get_los_matrix(current_actors)
+        self._los_plot.set_data(los_matrix)
+        xaxis = np.arange(len(current_actors))
+        self.ax_los.set_xticks(xaxis)
+        self.ax_los.set_yticks(xaxis)
+        self.ax_los.set_xticklabels(current_actors, fontsize=8)
+        self.ax_los.set_yticklabels(current_actors, fontsize=8)
+
+        if creating_animation:
+            self.fig.canvas.draw_idle()
+        else:
+            self.fig.canvas.draw()
+        plt.pause(0.0001)
+
+        # on some systems the below line throws an error. presumably due to pykep?
+        try:
+            self.date_label.set_text(self._local_actor.local_time)
+        except RuntimeError:
+            logger.trace("Animation date label could not be updated.")
+
+        self.time_label.set_text(f"t={sim._state.time:<10.2e}")
+
+        logger.debug("Plot updated.")
+
+    def _animate(self, sim: PASEOS, dt: float) -> List[Artist]:
+        """Advances the time of sim, updates the plot, and returns the axis objects
+
+        Args:
+            sim (PASEOS): simulation object.
+            dt (float): size of time step
+
+        Returns:
+            List[Artist]: list of Artist objects
+        """
+        sim.advance_time(dt)
+        self.update(sim, creating_animation=True)
+        return self.ax_3d.get_children() + self.ax_los.get_children()
+
+    def _animation_wrapper(self, step: int, sim: PASEOS, dt: float) -> List[Artist]:
+        """Wrapper to allow for frame numbers from animation
+
+        Args:
+            step (int): current frame number of the animation
+            sim (PASEOS): simulation object.
+            dt (float): size of time step
+
+        Returns:
+            List[Artist]: list of Artist objects
+        """
+        return self._animate(sim, dt)
+
+    def animate(
+        self, sim: PASEOS, dt: float, steps: int = 1, save_to_file: str = None
+    ) -> None:
+        """Animates paseos for a given number of steps with dt in each step.
+
+        Args:
+            sim (PASEOS): simulation object.
+            dt (float): size of time step
+            steps (int, optional): number of steps to animate. Defaults to 1.
+            save_to_file (str, optional): filename to save the animation. Defaults to None.
+        """
+        if save_to_file is None:
+            self._animate(sim, dt)
+        else:
+            anim = animation.FuncAnimation(
+                self.fig,
+                self._animation_wrapper,
+                frames=steps,
+                fargs=(
+                    sim,
+                    dt,
+                ),
+                interval=20,
+                blit=True,
+            )  # blit means to only redraw parts that changed
+            anim.save(f"{save_to_file}.mp4", writer="ffmpeg", fps=30)
diff --git a/requirements.txt b/requirements.txt
index 5d292ddb..16d05d7e 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -3,4 +3,5 @@ loguru
 pykep
 scikit-spatial
 toml
-tqdm
\ No newline at end of file
+tqdm
+matplotlib
diff --git a/resources/images/animation.png b/resources/images/animation.png
new file mode 100644
index 00000000..74660eed
Binary files /dev/null and b/resources/images/animation.png differ


Test patch:
diff --git a/paseos/tests/visualization_test.py b/paseos/tests/visualization_test.py
new file mode 100644
index 00000000..ee0ec513
--- /dev/null
+++ b/paseos/tests/visualization_test.py
@@ -0,0 +1,30 @@
+"""Tests to check visualization."""
+import sys
+
+sys.path.append("../..")
+from paseos import ActorBuilder, SpacecraftActor
+from paseos.visualization.space_animation import SpaceAnimation
+from test_utils import get_default_instance
+import pykep as pk
+
+
+def test_animation():
+    """Simple test to verify that the animation executes without errors."""
+    sim, sat1, earth = get_default_instance()
+
+    sat2 = ActorBuilder.get_actor_scaffold(
+        "sat2", SpacecraftActor, [10000000, 0, 0], pk.epoch(0)
+    )
+    ActorBuilder.set_orbit(sat2, [0, 10000000, 0], [0, 0, 8000.0], pk.epoch(0), earth)
+    ActorBuilder.set_power_devices(sat2, 5000, 10000, 1)
+    sim.add_known_actor(sat2)
+
+    anim = SpaceAnimation(sim)
+
+    dt = 100
+    for t in range(10):
+        anim.animate(sim, dt)
+
+
+if __name__ == "__main__":
+    test_animation()