You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

2890 lines
198 KiB

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Import supporting package"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import xarray as xr\n",
"import numpy as np\n",
"\n",
"from uncertainties import ufloat\n",
"from uncertainties import unumpy as unp\n",
"from uncertainties import umath\n",
"\n",
"import matplotlib.pyplot as plt\n",
"plt.rcParams['font.size'] = 18\n",
"\n",
"from DataContainer.ReadData import read_hdf5_file\n",
"from Analyser.ImagingAnalyser import ImageAnalyser\n",
"from Analyser.FitAnalyser import FitAnalyser\n",
"from ToolFunction.ToolFunction import *\n",
"\n",
"from ToolFunction.HomeMadeXarrayFunction import errorbar, dataarray_plot_errorbar\n",
"xr.plot.dataarray_plot.errorbar = errorbar\n",
"xr.plot.accessor.DataArrayPlotAccessor.errorbar = dataarray_plot_errorbar\n",
"\n",
"imageAnalyser = ImageAnalyser()\n",
"\n",
"%matplotlib notebook"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Start a client for parallel computing"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
" <div style=\"width: 24px; height: 24px; background-color: #e1e1e1; border: 3px solid #9D9D9D; border-radius: 5px; position: absolute;\"> </div>\n",
" <div style=\"margin-left: 48px;\">\n",
" <h3 style=\"margin-bottom: 0px;\">Client</h3>\n",
" <p style=\"color: #9D9D9D; margin-bottom: 0px;\">Client-ecaa07af-ed7b-11ed-8620-80e82ce0771f</p>\n",
" <table style=\"width: 100%; text-align: left;\">\n",
"\n",
" <tr>\n",
" \n",
" <td style=\"text-align: left;\"><strong>Connection method:</strong> Cluster object</td>\n",
" <td style=\"text-align: left;\"><strong>Cluster type:</strong> distributed.LocalCluster</td>\n",
" \n",
" </tr>\n",
"\n",
" \n",
" <tr>\n",
" <td style=\"text-align: left;\">\n",
" <strong>Dashboard: </strong> <a href=\"http://127.0.0.1:8787/status\" target=\"_blank\">http://127.0.0.1:8787/status</a>\n",
" </td>\n",
" <td style=\"text-align: left;\"></td>\n",
" </tr>\n",
" \n",
"\n",
" </table>\n",
"\n",
" \n",
"\n",
" \n",
" <details>\n",
" <summary style=\"margin-bottom: 20px;\"><h3 style=\"display: inline;\">Cluster Info</h3></summary>\n",
" <div class=\"jp-RenderedHTMLCommon jp-RenderedHTML jp-mod-trusted jp-OutputArea-output\">\n",
" <div style=\"width: 24px; height: 24px; background-color: #e1e1e1; border: 3px solid #9D9D9D; border-radius: 5px; position: absolute;\">\n",
" </div>\n",
" <div style=\"margin-left: 48px;\">\n",
" <h3 style=\"margin-bottom: 0px; margin-top: 0px;\">LocalCluster</h3>\n",
" <p style=\"color: #9D9D9D; margin-bottom: 0px;\">6078f62b</p>\n",
" <table style=\"width: 100%; text-align: left;\">\n",
" <tr>\n",
" <td style=\"text-align: left;\">\n",
" <strong>Dashboard:</strong> <a href=\"http://127.0.0.1:8787/status\" target=\"_blank\">http://127.0.0.1:8787/status</a>\n",
" </td>\n",
" <td style=\"text-align: left;\">\n",
" <strong>Workers:</strong> 6\n",
" </td>\n",
" </tr>\n",
" <tr>\n",
" <td style=\"text-align: left;\">\n",
" <strong>Total threads:</strong> 60\n",
" </td>\n",
" <td style=\"text-align: left;\">\n",
" <strong>Total memory:</strong> 55.88 GiB\n",
" </td>\n",
" </tr>\n",
" \n",
" <tr>\n",
" <td style=\"text-align: left;\"><strong>Status:</strong> running</td>\n",
" <td style=\"text-align: left;\"><strong>Using processes:</strong> True</td>\n",
"</tr>\n",
"\n",
" \n",
" </table>\n",
"\n",
" <details>\n",
" <summary style=\"margin-bottom: 20px;\">\n",
" <h3 style=\"display: inline;\">Scheduler Info</h3>\n",
" </summary>\n",
"\n",
" <div style=\"\">\n",
" <div>\n",
" <div style=\"width: 24px; height: 24px; background-color: #FFF7E5; border: 3px solid #FF6132; border-radius: 5px; position: absolute;\"> </div>\n",
" <div style=\"margin-left: 48px;\">\n",
" <h3 style=\"margin-bottom: 0px;\">Scheduler</h3>\n",
" <p style=\"color: #9D9D9D; margin-bottom: 0px;\">Scheduler-e6a3aa0a-fed0-4b9a-abe3-fabccbaa6b6c</p>\n",
" <table style=\"width: 100%; text-align: left;\">\n",
" <tr>\n",
" <td style=\"text-align: left;\">\n",
" <strong>Comm:</strong> tcp://127.0.0.1:60950\n",
" </td>\n",
" <td style=\"text-align: left;\">\n",
" <strong>Workers:</strong> 6\n",
" </td>\n",
" </tr>\n",
" <tr>\n",
" <td style=\"text-align: left;\">\n",
" <strong>Dashboard:</strong> <a href=\"http://127.0.0.1:8787/status\" target=\"_blank\">http://127.0.0.1:8787/status</a>\n",
" </td>\n",
" <td style=\"text-align: left;\">\n",
" <strong>Total threads:</strong> 60\n",
" </td>\n",
" </tr>\n",
" <tr>\n",
" <td style=\"text-align: left;\">\n",
" <strong>Started:</strong> Just now\n",
" </td>\n",
" <td style=\"text-align: left;\">\n",
" <strong>Total memory:</strong> 55.88 GiB\n",
" </td>\n",
" </tr>\n",
" </table>\n",
" </div>\n",
" </div>\n",
"\n",
" <details style=\"margin-left: 48px;\">\n",
" <summary style=\"margin-bottom: 20px;\">\n",
" <h3 style=\"display: inline;\">Workers</h3>\n",
" </summary>\n",
"\n",
" \n",
" <div style=\"margin-bottom: 20px;\">\n",
" <div style=\"width: 24px; height: 24px; background-color: #DBF5FF; border: 3px solid #4CC9FF; border-radius: 5px; position: absolute;\"> </div>\n",
" <div style=\"margin-left: 48px;\">\n",
" <details>\n",
" <summary>\n",
" <h4 style=\"margin-bottom: 0px; display: inline;\">Worker: 0</h4>\n",
" </summary>\n",
" <table style=\"width: 100%; text-align: left;\">\n",
" <tr>\n",
" <td style=\"text-align: left;\">\n",
" <strong>Comm: </strong> tcp://127.0.0.1:60985\n",
" </td>\n",
" <td style=\"text-align: left;\">\n",
" <strong>Total threads: </strong> 10\n",
" </td>\n",
" </tr>\n",
" <tr>\n",
" <td style=\"text-align: left;\">\n",
" <strong>Dashboard: </strong> <a href=\"http://127.0.0.1:60990/status\" target=\"_blank\">http://127.0.0.1:60990/status</a>\n",
" </td>\n",
" <td style=\"text-align: left;\">\n",
" <strong>Memory: </strong> 9.31 GiB\n",
" </td>\n",
" </tr>\n",
" <tr>\n",
" <td style=\"text-align: left;\">\n",
" <strong>Nanny: </strong> tcp://127.0.0.1:60954\n",
" </td>\n",
" <td style=\"text-align: left;\"></td>\n",
" </tr>\n",
" <tr>\n",
" <td colspan=\"2\" style=\"text-align: left;\">\n",
" <strong>Local directory: </strong> C:\\Users\\control\\AppData\\Local\\Temp\\dask-worker-space\\worker-7nkau0kr\n",
" </td>\n",
" </tr>\n",
"\n",
" \n",
"\n",
" \n",
"\n",
" </table>\n",
" </details>\n",
" </div>\n",
" </div>\n",
" \n",
" <div style=\"margin-bottom: 20px;\">\n",
" <div style=\"width: 24px; height: 24px; background-color: #DBF5FF; border: 3px solid #4CC9FF; border-radius: 5px; position: absolute;\"> </div>\n",
" <div style=\"margin-left: 48px;\">\n",
" <details>\n",
" <summary>\n",
" <h4 style=\"margin-bottom: 0px; display: inline;\">Worker: 1</h4>\n",
" </summary>\n",
" <table style=\"width: 100%; text-align: left;\">\n",
" <tr>\n",
" <td style=\"text-align: left;\">\n",
" <strong>Comm: </strong> tcp://127.0.0.1:60972\n",
" </td>\n",
" <td style=\"text-align: left;\">\n",
" <strong>Total threads: </strong> 10\n",
" </td>\n",
" </tr>\n",
" <tr>\n",
" <td style=\"text-align: left;\">\n",
" <strong>Dashboard: </strong> <a href=\"http://127.0.0.1:60975/status\" target=\"_blank\">http://127.0.0.1:60975/status</a>\n",
" </td>\n",
" <td style=\"text-align: left;\">\n",
" <strong>Memory: </strong> 9.31 GiB\n",
" </td>\n",
" </tr>\n",
" <tr>\n",
" <td style=\"text-align: left;\">\n",
" <strong>Nanny: </strong> tcp://127.0.0.1:60955\n",
" </td>\n",
" <td style=\"text-align: left;\"></td>\n",
" </tr>\n",
" <tr>\n",
" <td colspan=\"2\" style=\"text-align: left;\">\n",
" <strong>Local directory: </strong> C:\\Users\\control\\AppData\\Local\\Temp\\dask-worker-space\\worker-i87yzqt6\n",
" </td>\n",
" </tr>\n",
"\n",
" \n",
"\n",
" \n",
"\n",
" </table>\n",
" </details>\n",
" </div>\n",
" </div>\n",
" \n",
" <div style=\"margin-bottom: 20px;\">\n",
" <div style=\"width: 24px; height: 24px; background-color: #DBF5FF; border: 3px solid #4CC9FF; border-radius: 5px; position: absolute;\"> </div>\n",
" <div style=\"margin-left: 48px;\">\n",
" <details>\n",
" <summary>\n",
" <h4 style=\"margin-bottom: 0px; display: inline;\">Worker: 2</h4>\n",
" </summary>\n",
" <table style=\"width: 100%; text-align: left;\">\n",
" <tr>\n",
" <td style=\"text-align: left;\">\n",
" <strong>Comm: </strong> tcp://127.0.0.1:60984\n",
" </td>\n",
" <td style=\"text-align: left;\">\n",
" <strong>Total threads: </strong> 10\n",
" </td>\n",
" </tr>\n",
" <tr>\n",
" <td style=\"text-align: left;\">\n",
" <strong>Dashboard: </strong> <a href=\"http://127.0.0.1:60988/status\" target=\"_blank\">http://127.0.0.1:60988/status</a>\n",
" </td>\n",
" <td style=\"text-align: left;\">\n",
" <strong>Memory: </strong> 9.31 GiB\n",
" </td>\n",
" </tr>\n",
" <tr>\n",
" <td style=\"text-align: left;\">\n",
" <strong>Nanny: </strong> tcp://127.0.0.1:60956\n",
" </td>\n",
" <td style=\"text-align: left;\"></td>\n",
" </tr>\n",
" <tr>\n",
" <td colspan=\"2\" style=\"text-align: left;\">\n",
" <strong>Local directory: </strong> C:\\Users\\control\\AppData\\Local\\Temp\\dask-worker-space\\worker-2bq9qo65\n",
" </td>\n",
" </tr>\n",
"\n",
" \n",
"\n",
" \n",
"\n",
" </table>\n",
" </details>\n",
" </div>\n",
" </div>\n",
" \n",
" <div style=\"margin-bottom: 20px;\">\n",
" <div style=\"width: 24px; height: 24px; background-color: #DBF5FF; border: 3px solid #4CC9FF; border-radius: 5px; position: absolute;\"> </div>\n",
" <div style=\"margin-left: 48px;\">\n",
" <details>\n",
" <summary>\n",
" <h4 style=\"margin-bottom: 0px; display: inline;\">Worker: 3</h4>\n",
" </summary>\n",
" <table style=\"width: 100%; text-align: left;\">\n",
" <tr>\n",
" <td style=\"text-align: left;\">\n",
" <strong>Comm: </strong> tcp://127.0.0.1:60993\n",
" </td>\n",
" <td style=\"text-align: left;\">\n",
" <strong>Total threads: </strong> 10\n",
" </td>\n",
" </tr>\n",
" <tr>\n",
" <td style=\"text-align: left;\">\n",
" <strong>Dashboard: </strong> <a href=\"http://127.0.0.1:60996/status\" target=\"_blank\">http://127.0.0.1:60996/status</a>\n",
" </td>\n",
" <td style=\"text-align: left;\">\n",
" <strong>Memory: </strong> 9.31 GiB\n",
" </td>\n",
" </tr>\n",
" <tr>\n",
" <td style=\"text-align: left;\">\n",
" <strong>Nanny: </strong> tcp://127.0.0.1:60957\n",
" </td>\n",
" <td style=\"text-align: left;\"></td>\n",
" </tr>\n",
" <tr>\n",
" <td colspan=\"2\" style=\"text-align: left;\">\n",
" <strong>Local directory: </strong> C:\\Users\\control\\AppData\\Local\\Temp\\dask-worker-space\\worker-vqv2w3r4\n",
" </td>\n",
" </tr>\n",
"\n",
" \n",
"\n",
" \n",
"\n",
" </table>\n",
" </details>\n",
" </div>\n",
" </div>\n",
" \n",
" <div style=\"margin-bottom: 20px;\">\n",
" <div style=\"width: 24px; height: 24px; background-color: #DBF5FF; border: 3px solid #4CC9FF; border-radius: 5px; position: absolute;\"> </div>\n",
" <div style=\"margin-left: 48px;\">\n",
" <details>\n",
" <summary>\n",
" <h4 style=\"margin-bottom: 0px; display: inline;\">Worker: 4</h4>\n",
" </summary>\n",
" <table style=\"width: 100%; text-align: left;\">\n",
" <tr>\n",
" <td style=\"text-align: left;\">\n",
" <strong>Comm: </strong> tcp://127.0.0.1:60981\n",
" </td>\n",
" <td style=\"text-align: left;\">\n",
" <strong>Total threads: </strong> 10\n",
" </td>\n",
" </tr>\n",
" <tr>\n",
" <td style=\"text-align: left;\">\n",
" <strong>Dashboard: </strong> <a href=\"http://127.0.0.1:60986/status\" target=\"_blank\">http://127.0.0.1:60986/status</a>\n",
" </td>\n",
" <td style=\"text-align: left;\">\n",
" <strong>Memory: </strong> 9.31 GiB\n",
" </td>\n",
" </tr>\n",
" <tr>\n",
" <td style=\"text-align: left;\">\n",
" <strong>Nanny: </strong> tcp://127.0.0.1:60958\n",
" </td>\n",
" <td style=\"text-align: left;\"></td>\n",
" </tr>\n",
" <tr>\n",
" <td colspan=\"2\" style=\"text-align: left;\">\n",
" <strong>Local directory: </strong> C:\\Users\\control\\AppData\\Local\\Temp\\dask-worker-space\\worker-32c9d6r5\n",
" </td>\n",
" </tr>\n",
"\n",
" \n",
"\n",
" \n",
"\n",
" </table>\n",
" </details>\n",
" </div>\n",
" </div>\n",
" \n",
" <div style=\"margin-bottom: 20px;\">\n",
" <div style=\"width: 24px; height: 24px; background-color: #DBF5FF; border: 3px solid #4CC9FF; border-radius: 5px; position: absolute;\"> </div>\n",
" <div style=\"margin-left: 48px;\">\n",
" <details>\n",
" <summary>\n",
" <h4 style=\"margin-bottom: 0px; display: inline;\">Worker: 5</h4>\n",
" </summary>\n",
" <table style=\"width: 100%; text-align: left;\">\n",
" <tr>\n",
" <td style=\"text-align: left;\">\n",
" <strong>Comm: </strong> tcp://127.0.0.1:60992\n",
" </td>\n",
" <td style=\"text-align: left;\">\n",
" <strong>Total threads: </strong> 10\n",
" </td>\n",
" </tr>\n",
" <tr>\n",
" <td style=\"text-align: left;\">\n",
" <strong>Dashboard: </strong> <a href=\"http://127.0.0.1:60994/status\" target=\"_blank\">http://127.0.0.1:60994/status</a>\n",
" </td>\n",
" <td style=\"text-align: left;\">\n",
" <strong>Memory: </strong> 9.31 GiB\n",
" </td>\n",
" </tr>\n",
" <tr>\n",
" <td style=\"text-align: left;\">\n",
" <strong>Nanny: </strong> tcp://127.0.0.1:60959\n",
" </td>\n",
" <td style=\"text-align: left;\"></td>\n",
" </tr>\n",
" <tr>\n",
" <td colspan=\"2\" style=\"text-align: left;\">\n",
" <strong>Local directory: </strong> C:\\Users\\control\\AppData\\Local\\Temp\\dask-worker-space\\worker-j439vfn0\n",
" </td>\n",
" </tr>\n",
"\n",
" \n",
"\n",
" \n",
"\n",
" </table>\n",
" </details>\n",
" </div>\n",
" </div>\n",
" \n",
"\n",
" </details>\n",
"</div>\n",
"\n",
" </details>\n",
" </div>\n",
"</div>\n",
" </details>\n",
" \n",
"\n",
" </div>\n",
"</div>"
],
"text/plain": [
"<Client: 'tcp://127.0.0.1:60950' processes=6 threads=60, memory=55.88 GiB>"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from dask.distributed import Client\n",
"client = Client(n_workers=6, threads_per_worker=10, processes=True, memory_limit='10GB')\n",
"client"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Set global path for experiment"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"groupList = [\n",
" \"images/MOT_3D_Camera/in_situ_absorption\",\n",
" \"images/ODT_1_Axis_Camera/in_situ_absorption\",\n",
" \"images/ODT_2_Axis_Camera/in_situ_absorption\",\n",
"]\n",
"\n",
"dskey = {\n",
" \"images/MOT_3D_Camera/in_situ_absorption\": \"camera_0\",\n",
" \"images/ODT_1_Axis_Camera/in_situ_absorption\": \"camera_1\",\n",
" \"images/ODT_2_Axis_Camera/in_situ_absorption\": \"camera_2\",\n",
"}\n"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"img_dir = 'C:/Users/control/DyLab/Experiments/DyBEC/'\n",
"SequenceName = \"Repetition_scan\" + \"/\"\n",
"folderPath = img_dir + SequenceName + '2023/' + get_date()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Repetition Scans"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## scan MOT freq - Z Comp 0"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"scrolled": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"The detected scaning axes and values are: /n\n",
"{'initial_freq': array([100.75, 100.98, 101.21, 101.44, 101.67, 101.9 , 102.13, 102.36,\n",
" 102.59, 102.82]), 'runs': array([0., 1., 2.])}\n"
]
},
{
"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,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cI2yy7xYmy8QAI0RaQEZy3PVHoOPK1xiseAqtspNIZi6QRUlFFyj7DIv1uYLBEBjRFpAxvJctcfg4wqXWCy4iq1yUwimblBFCQXXKLvMi7X5AgHQGJEWkLE8V+0x+LjCJRYLrmKr3BSCqRtUUULBNcou82JtvkAANEakBWQsz1V7DD6ucInFgqvYKjeFYOoGVZRQcI2yy7xYmy8QAI0RaQEZy3PVHoOPK1xiseAqtspNIZi6QRUlFFyj7DIv1uYLBEBjRFpAxvJctcfgk11cO3cSLV1KtH49Ufv2RH36EDVpItMLrjKfPFWBqSdacq3gKvcqjUptvkAANKakBWQsz1V7DD7ZxDV3LtGIEURr1vxXX8eORFOmEA0ZUlozuJb2yFsFmHojJtMLrjKf0qrS5otMBsC1a9fS6NGj6cknn6SPP/6YDjvsMPr5z39Oxx57bPC1srKSxowZQ9OmTaMPPviAevToQbfffjt169atyvft27fTqFGjaNasWaHHiSeeSHfccQd15G+m/2y87yWXXEKPPfZY+JNTTz2Vbr31VmrVqlVVzXvvvUcXX3wxPf3007T33nvT8OHD6eabb6Y999xTxFgLSHSQBlKEwSd7oDn8nX46fyara2vU6NN/nzOndAgE1+xx1SoCU62D2dwfXLPFRZsvMhcAOZR1796d+vXrRxdeeCG1a9eO/vKXv1CnTp2oc+fOwf3x48fT2LFj6b777gvh8IYbbqAlS5bQypUrqUWLFqGG93388cdDzf7770+XX345bdq0iV566SVq8p97UyeddBKtWbMmBEnezj///HAc3o+3nTt30tFHH01t27aliRMn0saNG+mss86iIUOGhKAo2bSAJMdoKDUYfLJFmm/7dupUfeavWCGHQP7vrVWrdn87GFyzxTUJNWCahIvZ6wGu2WKizReZC4BXXXUVPffcc7SUHyiqZePZvw4dOtCll14aZgl549m+Aw44IATDCy64gLZs2RJC24wZM+jMM88MNevWraOKigqaN28eDRw4kF5//XXq2rUrPf/882EGkTf+5549e9KKFSvo8MMPDzOQp5xyCq1evTock7fZs2fT2WefTRs2bKCWLVuWvBq0gEoeoAEVYPDJFuzFi4n69SutadEior59664D19IeeqsAU2/EZHrBVeZTWlXafJG5AMihjAMaz8w988wzdOCBB9JF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\" width=\"640\">"
],
"text/plain": [
"<IPython.core.display.HTML object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"shotNum = \"0000\"\n",
"filePath = folderPath + \"/\" + shotNum + \"/*.h5\"\n",
"\n",
"dataSetDict = {\n",
" dskey[groupList[i]]: read_hdf5_file(filePath, groupList[i])\n",
" for i in range(len(groupList))\n",
"}\n",
"\n",
"dataSet = dataSetDict[\"camera_1\"]\n",
"\n",
"print_scanAxis(dataSet)\n",
"\n",
"scanAxis = get_scanAxis(dataSet)\n",
"\n",
"auto_rechunk(dataSet)\n",
"\n",
"dataSet = imageAnalyser.get_absorption_images(dataSet)\n",
"\n",
"imageAnalyser.center = (310, 825)\n",
"imageAnalyser.span = (550, 1200)\n",
"imageAnalyser.fraction = (0.1, 0.1)\n",
"\n",
"dataSet_cropOD = imageAnalyser.crop_image(dataSet.OD)\n",
"dataSet_cropOD = imageAnalyser.substract_offset(dataSet_cropOD).load()\n",
"\n",
"Ncount = imageAnalyser.get_Ncount(dataSet_cropOD)\n",
"Ncount_mean = Ncount.mean(dim='runs')\n",
"Ncount_std = Ncount.std(dim='runs')\n",
"\n",
"fig = plt.figure()\n",
"ax = fig.gca()\n",
"Ncount_mean.plot.errorbar(ax=ax, yerr = Ncount_std, fmt='ob')\n",
"plt.xlabel('MOT AOM Freq (MHz)')\n",
"plt.ylabel('NCount')\n",
"plt.tight_layout()\n",
"plt.grid(visible=1)\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## scan Push freq"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"The detected scaning axes and values are: /n\n",
"{'push_freq': array([100.5 , 100.85, 101.2 , 101.55, 101.9 , 102.25, 102.6 , 102.95,\n",
" 103.3 , 103.65]), 'runs': array([0., 1., 2.])}\n"
]
},
{
"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,iVBORw0KGgoAAAANSUhEUgAAAoAAAAHgCAYAAAA10dzkAAAAAXNSR0IArs4c6QAAIABJREFUeF7snQm0VcWV/jcgIAgICtggKEqQBO2gbZaI/hNlGbFlESWYMJkWiYpB04gCKrYaaOcAgu2IHRUUGRKXyhAQMIiaGDVxStJhMA4MQkRGRQQj8l+7yH2+Cep8tW/xbt37nbWyIlTtW6d++9vvfVSdOrfW7t27dwsvEiABEiABEiABEiCBkiFQiwawZHLNiZIACZAACZAACZCAI0ADSCGQAAmQAAmQAAmQQIkRoAEssYRzuiRAAiRAAiRAAiRAA0gNkAAJkAAJkAAJkECJEaABLLGEc7okQAIkQAIkQAIkQANIDZAACZAACZAACZBAiRGgASyxhHO6JEACJEACJEACJEADSA2QAAmQAAmQAAmQQIkRoAEssYRzuiRAAiRAAiRAAiRAA0gNkAAJkAAJkAAJkECJEaABLLGEc7okQAIkQAIkQAIkQANIDZAACZAACZAACZBAiRGgASyxhHO6JEACJEACJEACJEADGFkDX375paxdu1YaN24stWrVijwaP54ESIAESIAESKAUCOzevVs++eQTad26tdSuXRueMg0gjAwLWLNmjbRt2xYLYm8SIAESIAESIAESyEBg9erV0qZNmww9K3ahAYSRYQFbt26Vpk2biiaoSZMmWHCG3v/4xz9k4cKF0r17d6lbt26GCHYhszANkBvOjcxwZhpBbjg3Mis9Zh9//LFbYNqyZYscfPDBMAAaQBgZFqAJ0sSoEYxlAOfNmyc9evSgAcyYGv1BSWYZYZXrRm5khhMIi6DWcG5kVnrMrP6CBhDXDBRhTZBvMBa9j1DVdjLDmeVWZWicMXbUGsYr15vccG5kVnrMrP6CBhDXDBRhTZBvMBa9jxANIE6o+ghqDSdJZjgz/mODzMII4FGp16fVX9AA4pqBIqwJ8g2WuoB984vRTmZhVMkN50ZmODMaQDILI4BHpV6fVn9BA4hrBoqwJsg3WOoC9s0vRjuZhVElN5wbmeHMaADJLIwAHpV6fVr9BQ0grhkowpog32CpC9g3vxjtZBZGldxwbmSGM6MBJLMwAnhU6vVp9Rc0gLhmoAhrgnyDpS5g3/xitJNZGFVyw7mRGc6MBpDMwgjgUanXp9Vf0ADimoEirAnyDZa6gH3zi9FOZmFUyQ3nRmY4MxpAMgsjgEelXp9Wf0EDiGsGirAmyDdY6gL2zS9GO5mFUSU3nBuZ4cxoAMksjAAelXp9Wv0FDSCuGSjCmiDfYKkL2De/GO1kFkaV3HBuZIYzowEkszACeFTq9Wn1FzSAuGagCGuCfIOlLmDf/GK0k1kYVXLDuZEZzowGkMzCCOBRqden1V/QAOKagSKsCfINlrqAffOL0U5mYVTJDedGZjgzGkAyCyOAR6Ven1Z/QQOIawaKsCbIN1jqAvbNL0Y7mYVRJTecG5nhzGgAySyMAB6Ven1a/QUNIK4ZKMKaIN9gqQvYN78Y7WQWRpXccG5khjOjASSzMAJ4VOr1afUXNIC4ZqAIa4J8g6UuYN/8YrSTWRhVcsO5kRnOjAaQzMII4FGp16fVX9AA4pqBIqwJ8g2WuoB984vRTmZhVMkN50ZmODMaQDILI4BHpV6fVn9BA4hrBoqwJsg3WOoC9s0vRjuZhVElN5wbmeHMaACrMvv0U5FGjfb8/bZtIgcdVLUPtYZrLXVmVn9BA4hrBoqwJsg3WOoC9s0vRjuZhVElN5wbmeHMaABpAMNUg0elXp9Wf0EDiGsGirAmyDdY6gL2zS9GO5mFUSU3nBuZ4cxoAGkAw1SDR6Ven1Z/QQOIawaKsCbIN1jqAvbNL0Y7mYVRJTecG5nhzGgAaQDDVINHpV6fVn9BA4hrBoqwJsg3WOoC9s0vRjuZhVElN5wbmeHMaABpAMNUg0elXp9Wf0EDiGsGirAmyDdY6gL2zS9GO5mFUSU3nBuZ4cxoAGkAw1SDR6Ven1Z/UXAG8IsvvpDRo0fL448/Ln//+9+lVatWcuGFF8r1118vtWvXdhnWP0+ZMqVCtrt06SIvv/xy2d/t3LlTRowYIdOnT5fPPvtMzjjjDLnvvvukTZs2ZX02b94sQ4cOldmzZ7u/O+ecc+Tuu++Wpk2blvVZtWqVXH755bJ48WJp0KCBDBgwQMaNGyf16tXLpDZrgnyDpC5g3/xitJNZGFVyw7mRGc6MBpAGMEw1eFTq9Wn1FwVnAG+55RaZMGGCM3jHHnus/PGPf5RBgwbJzTffLFdccUWZAfzwww/lkUceKcu4GrJDDjmk7M9DhgyROXPmyOTJk+XQQw+V4cOHy6ZNm+S1116TOnXquH5nn322rFmzRh588EH358GDB0u7du1cnF67du2S448/Xlq0aCHjx4+XjRs3ysCBA6V3797OKGa5rAnyjZG6gH3zi9FOZmFUyQ3nRmY4MxpAGsAw1eBRqden1V8UnAHs2bOnHHbYYfLQQw+VZfO8886Thg0bymOPPVZmALds2SJPP/10tRnfunWrM23av2/fvq7P2rVrpW3btjJv3jw566yzZOnSpdKpUye3aqirh3rpf3ft2lWWLVsmHTt2lPnz54vez+rVq6V169auz4wZM9wK5Pr166VJkyZexVkT5BsgdQH75hejnczCqJIbzo3McGY0gDSAYarBo1KvT6u/KDgDePvtt8sDDzwgCxculGOOOUbeeust6d69u0ycOFH69+9fZgDV/Omqn27XnnbaaaIrhy1btnTtul2rW7664tesWbMyVXTu3Fl69eolY8aMkYcffliuuuoqUSNZ/tLP0xVIXXW88cYbZdasWe4ecpduG+tKo47RrVu3KorTrWf9X+7SBKnx3LBhQybDiEpYBbxo0SI588wzpW7dumh4SfYns7C0kxvOjcxwZjkDGPJzTV+Y3KzZnp+Dmzf/o9oXJofdUc1GZZkXtYbnKHVm6i+aN28uuuiVZUGqMqGCM4C7d++W6667Tu644w63VavbsGruRo0aVXbvM2fOlEaNGsmRRx4p7733ntxwww2izw7q9m79+vVl2rRpzsCVN2IarEbyqKOOkkmTJsmtt97qtodXrFhRgYmaTo3V8XRL+P3333dmtPylY2hszpCWb9PnF9VgVr70nnQVkxcJkAAJkEAcAjt21JF+/Xq6D58xY64ceOCuOAPt508t1nntZ4xFN9z27dvduYSiMYC6xTpy5EgZO3asewbwzTfflGHDhsmdd97pnr+r7lq3bp0zgxqrz+ftzQDqKln79u3dCqMaQH3OcPny5RU+skOHDnLRRRfJtdde6wzgypUrZcGCBRX66Mrjo48+Kv369atyO1wBLPwaS/1ffTVFmNxw8mSGM9OIUG5ZVsrC7qhmo7LMK5RZTc4sy7xi3l+KzMrzKLoVQN0uVfOlJ29zlx4AmTp1qns2b2+XGreLL75YrrnmmhrdAq58f9Y9ep/4U3+GwTe/GO1kFkaV3HBuZIYzyxlAfV67R48e0KMtWb4zN+yOajYqy7xS1FqWecUknyKzygbw4IMPLp4VQD2xq4ZPT/Hmrttuu82d+K28XZtr19O5hx9+uDvNe8EFFzgYeghETWOfPn1cN10l1FfAVD4E8sorr8hJJ53k+uh/n3zyyVUOgehJYX0djV66/awrkTwEErMs43526kUfl87eP53ccPJkhjOjAazKLItRSlFrWeYVpqBsUSkyK2oDqCdsn332Wfecnm4Bv/HGG24r9sc//rF7LnDbtm3uPYF6MlhNmT6jp88M6vv69GRv48aNHR81kHPnznXP6umhDX0noBrFyq+B0dPBOpZeOo5uJVd+DYyeStYtaT1UovenB0n4GphsBVaIvVIv+ppiSm44eTLDmdEAVmX28cciBx+85+/nzdPn2UX++Tazss4pai3LvMIUlC0qRWZFbQA/+eQTd6jjqaeecqts+voVPWyhJ3L12Tt9qbMaMDWGeoJXTaCexr3pppvcadvctWPHDvcsoT4PWP5F0OX7qKGr/CLoe+65p8qLoC+77LIqL4LWgyBZLm4BZ6G0f/ukXvT7l9ZXo5EbTp7McGY0gBWZPfmkyNChIh988NXf6/cZ3HWXSO/e6dZn1nmFKShbVOr1afUXBXcKOFva0ullTZBvpqkL2De/GO1kFkaV3HBuZIYzowH8ipmapB/8QGT37ooca9Xa8+cnnvjKBKakNWReYQrKFpUSs+pmZPUXNIDZdBLcy5og38CpC9g3vxjtZBZGldxwbmSGM6MB3MNs1y6Rdu1E1qypnqGaQF0JfO+9PdvBqWgNnVeYgrJFpcJsb7Ox+gsawGw6Ce5lTZBv4NQF7JtfjHYyC6NKbjg3MsOZ0QDuYbZkiUg13zVQBehzz4mcfno6BhCdV5iCskWlXp9Wf0EDmE0nwb2sCfINnLqAffOL0U5mYVTJDedGZjgzGsA9zKZPFxkwwM9v2jQR/ZKsVLSGzstPILxHKsy4Ahie4xqNpAGsUfzVDp560dcUUXLDyZMZzowGkCuASiC3shmmoGxRqden1V9wBTCbToJ7WRPkGzh1AfvmF6OdzMKokhvOjcxwZjSAe5jlnpXT07+VD4Foe+rPAGadV5iCskWlXp9Wf0EDmE0nwb2sCfINnLqAffOL0U5mYVTJDedGZjgziwGs6ffKhc1271G507Lao7wJLJZTwFnmlW+m5T8v9fq0+gsawJjqEhFrgny3l7qAffOL0U5mYVTJDedGZjizUANYCO+VC5vtvqOqm5e+8nbixOJ7D2B184rBNPeZqden1V/QAMZUFw1gZLphH5960YfN2h5FbjhDMsOZhRjAQnmvXNhs/VFZVjZT1FqWefnphPdIkVn52dIAhud+v0RaE+S7ydQF7JtfjHYyC6NKbji3QmVW09/B6iOJcCuk98r55hXaniVfCLPQ+8h3XJZ55XvM8p+XIjMawJiKyPNn0wDmGWgePi71os8DgqCPIDccW6Eyq+lfvD6SCLdCeq+cb16h7VnyhTALvY98x2WZV77HpAH8igC3gGOqi1vAkemGfXyKPyjDZprfqFLkZv0FVajMrPPKr7KqfhrCrZDeKxeLS5Z8Icxi3Sf6uVnmhX4m0j8ms/0xN+sCEw0gopaAvtYE+YaMKWDf2Km2k1lY5kqRm/WHeKEys84rTEHZoxBuXAHcwxVhlj0Txd0zJrP98Xyj1V/QAEbWtzVBvtuLKWDf2Km2k1lY5kqRm9UoFSoz67zCFJQ9CuGGvi8v+10UTs8s+UKYFc7MavZOYjHbXyfSrf6CBjCy/qwJ8t1eLAH7xk25nczCsleK3LL84t0XzUJlZp1XmIKyR6HckPflZb+LwumZJV8os8KZXc3dSQxm+/NEutVf0ABG1p41Qb7biyFg35ipt5NZWAZLkZt1G6dQmVnnFaag7FEh3LK+Ly/7XRROTxrAOLkI0dm+7mR/n0i3+gsawDi6KvtUa4J8t5dvAfvGK4Z2MgvLYqlxy8c2TiEyy8e8whSUPSqUW6Eb2+wEKvakAQwlt++4UJ3t7VP39/OoVn9BAxhHVzSAkblaPj7fRW+5l5RiS4lbvrZxCo1ZvuYVW7eh3LIYpdj3HuPzs8wrlFmM+03lM/PNbH+fSKcBLHClWRPkm16+BewbrxjaySwsi6XCLZ/bOIXELJ/zClNQ9qhQblmMUva7KJyeWeYVyqxwZrn/7yTfzLgCuP9zWNAj0gAWXnryXfSFN8M4d1Qq3PL5Q7yQmOVzXnEU9tWnhnLLYpRi33uMz88yr1BmMe43lc/MN7P9fSLd6i+4BRxZqdYE+W4v3wL2jVcM7WQWlsVS4ZbPbZxCYpbPeYUpKHtUKLcsRin7XRROzyzzCmVWOLPc/3cSg9n+PJFu9Rc0gJE1Z02Q7/ZiCNg3ZurtZBaWwVLhls+VskJils95hSkoe1QotyxGKftdpNUzlFlas8zv3cZitr9OpFv9BQ1gfvVU5dOsCfLdXiwB+8ZNuZ3MwrJXKtzyuY1TSMzyOa8wBWWPCuVGAzhPevToIXXr1s0Ou4R7huosCzKttxdfFFm3TqRVK5Fvf1ukTp0skdn7WP0FDWB21kE9rQnyDRpTwL6xU20ns7DMlRK3fG3jFBqzfM0rTEHZo0K50QDSAGZXWfpfn2f1FzSAiFoC+loT5Bsy9Ael73OLuZ3MwrJbatzysY1TiMzyMa8wBWWPCuVGA0gDmF1lNIA0gIhaAvrSAAZAixwS+ssl8m0V/MeXIjfri4ULlZl1XrHFGsqNBpAGENFmqM6QMWL2tfoLGsCY2RERa4J8t5e6gH3zi9FOZmFUS5Gb1VAUKjPrvMIUlD0qlFuhzys7AbxnKDN8pOKJSJ2Z1V/QAEbWsjVBvttLXcC++cVoJ7MwqqXIzWooCpWZdV5hCsoeFcqt0OeVnQDeM5QZPlLxRKTOzOovaAAja9maIN/tpS5g3/xitJNZGNVS5GY1FIXKzDqvMAVljwrlVujzyk4A7xnKDB+peCJSZ2b1FzSAkbVsTZDv9lIXsG9+MdrJLIwqueHcCpVZoRulQuWGK2D/RZAZzjp1ZlZ/QQOIawaKsCbIN1jqAvbNL0Y7mYVRJTecG5nhzDSC3HBuZFZ6zKz+ggYQ1wwUYU2QbzAWvY9Q1XYyw5nxlzKZhREIi2KN4tzIrPSYWf0FDSCuGSjCmiDfYCx6HyEaQJxQ9RHUGk6SzHBm/McGmYURwKNSr0+rv6ABxDUDRVgT5BssdQH75hejnczCqJIbzo3McGY0gGQWRgCPSr0+rf6CBhDXDBRhTZBvsNQF7JtfjHYyC6NKbjg3MsOZ0QCSWRgBPCr1+rT6CxpAXDNQhDVBvsFSF7BvfjHaySyMKrnh3MgMZ0YDSGZhBPCo1OvT6i9oAHHNQBHWBPkGS13AvvnFaCezMKrkhnMjM5wZDSCZhRHAo1KvT6u/oAHENQNFWBPkGyx1AfvmF6OdzMKokhvOjcxwZjSAZBZGAI9KvT6t/oIGENcMFGFNkG+w1AXsm1+MdjILo0puODcyw5nRAJJZGAE8KvX6tPoLGkBcM1CENUG+wVIXsG9+MdrJLIwqueHcyAxnRgNIZmEE8KjU69PqL2gAcc1AEdYE+QZLXcC++cVoJ7MwquSGcyMznBkNIJmFEcCjUq9Pq7+gAcQ1A0VYE+QbLHUB++YXo53MwqiSG86NzHBmNIBkFkYAj0q9Pq3+ggYQ1wwUYU2Qb7DUBeybX4x2MgujSm44NzLDmdEAklkYATwq9fq0+gsaQFwzUIQ1Qb7BUhewb34x2sksjCq54dzIDGdGA0hmYQTwqNTr0+ovaABxzUAR1gT5BktdwL75xWgnszCq5IZzIzOcGQ0gmYURwKNSr0+rv6ABxDUDRVgT5BssdQH75hejnczCqJIbzo3McGY0gGQWRgCPSr0+rf6CBhDXDBRhTZBvsNQF7JtfjHYyC6NKbjg3MsOZ0QCSWRgBPCr1+rT6CxpAXDNQhDVBvsFSF7BvfjHaySyM6r64ffqpSKNGez532zaRgw4KG6PYoqi1sIySG86NzEqPmdVf0ADimoEirAnyDcai9xGq2k5mODPfqgwNYPVMqbX8ay3sE4s/ilrDc5w6M6u/oAHENQNFWBPkGyx1AfvmF6OdzMKocgUQ50at4cx8/9gI+8Tij6LW8BynzszqL2gAcc1AEdYE+QZLXcC++cVoJ7MwqjSAODdqDWdGA0hmYQTwqNTr0+ovaABxzUAR1gT5BktdwL75xWgnszCq++L28cciBx+853PnzRPp3l2kTp2wcYopiloLyya54dzIrPSYWf0FDSCuGSjCmiDfYCx6H6Gq7WSGM9vXqsyTT4oMHSrywQdffW6bNiJ33SXSu3fYWMUSRa2FZZLccG5kVnrMrP6CBhDXDBRhTZBvMBa9jxANIE6o+ojqtKbm7wc/ENm9u2JMrVp7/vzEE6VtAlmfYeojN5wbmZUeM6u/KDgD+MUXX8jo0aPl8ccfl7///e/SqlUrufDCC+X666+X2rVruwzv3r1bxowZIw8++KBs3rxZunTpIvfee68ce+yxZQrYuXOnjBgxQqZPny6fffaZnHHGGXLfffdJG12a+OelsUOHDpXZs2e7vznnnHPk7rvvlqZNm5b1WbVqlVx++eWyePFiadCggQwYMEDGjRsn9erVy6Q2a4J8g7DofYRoAHFC2Qzgrl0i7dqJrFlTfX81gVpu771XutvBrM8w9ZEbzo3MSo+Z1V8UnAG85ZZbZMKECTJlyhRn6P74xz/KoEGD5Oabb5YrrrjCZfiOO+4Q7Td58mQ55phjXNsLL7wgy5cvl8aNG7s+Q4YMkTlz5rg+hx56qAwfPlw2bdokr732mtT558NJZ599tqxZs8YZSb0GDx4s7dq1c3F67dq1S44//nhp0aKFjB8/XjZu3CgDBw6U3r17O6OY5bImyDcGi95HiAYQJ5TNAC5ZItKtm//Tn3tO5PTT/f2KsQfrMyyr5IZzI7PSY2b1FwVnAHv27CmHHXaYPPTQQ2XZPO+886Rhw4by2GOPudW/1q1by7Bhw+Saa65xfXS1T2PUGF566aWydetWZ9q0f9++fV2ftWvXStu2bWXevHly1llnydKlS6VTp07y8ssvuxVEvfS/u3btKsuWLZOOHTvK/PnzRe9n9erVbky9ZsyY4VYk169fL02aNPEqzpog3wAseh8hGkCcUDYDOH26yIAB/k+fNk2kf39/v2LswfoMyyq54dzIrPSYWf1FwRnA22+/XR544AFZuHChW9176623pHv37jJx4kTp37+/vPvuu9K+fXt5/fXX5YQTTijL+Lnnnuu2bnXlULdrdctXV/yaNWtW1qdz587Sq1cvt3388MMPy1VXXSVbtmypoBr9DF2B1FXHG2+8UWbNmuXuIXfptvEhhxzixuhWzfKHmlH9X+7SBKnx3LBhQybDiEpYi37RokVy5plnSt26ddHwkuxPZmFpr8zt+edryZlnHuD9sEWLvpDTTqv0kKA3qjg6UGtheSQ3nBuZlR4z9RfNmzd3i15ZFqQqEyo4A6grfNddd51bzdOtWt2G1e3eUaNGuXt/6aWX5NRTT5UPPvigbFVO/163b1euXCkLFiyQadOmOQNX3ohpHzWSRx11lEyaNEluvfVWtz28YsWKCkzUdGqsjqef+f777zszWv6qX7++i1VDWvnS5xfVYFa+9J50FZMXCRQLAX0GcPDg7rJx44Ei8s9THxUmt1uaN/9MJk1axFfCFEvSOQ8SIIGCIbB9+3Z3LqFoDKBusY4cOVLGjh3rngF888033XbvnXfe6Z6/yxlA3dLVAyK565JLLnFbtc8888xeDaCukunqoa4wqgHU1UJ9brD81aFDB7nooovk2muvrWAqy/fRAyCPPvqo9OvXr4oQuAJYMLWx1xvhv5TDclQdt6eeqiX9+u154d/u3V+ZwFq19qz4zZixS77//dJc/dP5U2v501rYJ5VOFLWG5zp1ZkW3AqjbpWq+9ORt7tJDHlOnTnXP5hX6FnBlCVr36H2S5nMfPkJV28kMZ5YzM/oMbY8ePSo8blDdewDbthWZOLG0XwGzL2ZhGSidKNYonmsyKz1mVn9RcFvAemJXDZ+e4s1dt912mzzyyCNuuzZ3COTKK6+Uq6++2nX5/PPPpWXLllUOgahp7NOnj+uzbt069wqYyodAXnnlFTnppJNcH/3vk08+ucohED0pnFttnDlzpluJ5CEQvNgKJYI/KMMysS9u/CaQ6plSa/nXWtgnFn8UtYbnOHVmRWcA9YTts88+657T0y3gN954w23F/vjHP3YGTy/9/5wp1C1b3c5dsmRJldfAzJ071z2rp4c29J2A+hqXyq+B0a1kHUsvHefII4+s8hoYPWGsW9J6qETvTw+S8DUweLEVSkTqRV9THPfF7dNPRRo12nNn27aJHHRQTd1lYY1LrYXlg9xwbmRWesyKzgB+8skncsMNN8hTTz3lVtn09St62EJP5OZevpx7EbQat/Ivgj7uuOPKFLBjxw73LKEevij/ImjdYs5daugqvwj6nnvuqfIi6Msuu6zKi6D1IEiWy5og3xgseh+hqu1khjPTCBpAnBu1hjPzaS3sE4s/ilrDc5w6M6u/KLgtYDyFhR1hTZBvdqkL2De/GO1kFkaVBhDnRq3hzGgAySyMAB6Ven1a/QUNIK4ZKMKaIN9gqQvYN78Y7WQWRpXccG5khjOjASSzMAJ4VOr1afUXNIC4ZqAIa4J8g6UuYN/8YrSTWRhVcsO5kRnOjAaQzMII4FGp16fVX9AA4pqBIqwJ8g2WuoB984vRTmZhVMkN50ZmODMaQDILI4BHpV6fVn9BA4hrBoqwJsg3WOoC9s0vRjuZhVElN5wbmeHMaADJLIwAHpV6fVr9BQ0grhkowpog32CpC9g3vxjtZBZGldxwbmSGM6MBJLMwAnhU6vVp9Rc0gLhmoAhrgnyDpS5g3/xitJNZGFVyw7mRGc6MBpDMwgjgUanXp9Vf0ADimoEirAnyDZa6gH3zi9FOZmFUyQ3nRmY4MxpAMgsjgEelXp9Wf0EDiGsGirAmyDdY6gL2zS9GO5mFUSU3nBuZ4cxoAMksjAAelXp9Wv0FDSCuGSjCmiDfYKkL2De/GO1kFkaV3HBuZIYzowEkszACeFTq9Wn1FzSAuGagCGuCfIOlLmDf/GK0k1kYVXLDuZEZzowGkMzCCOBRqden1V/QAOKagSKsCfINlrqAffOL0U5mYVTJDedGZjgzGkAyCyOAR6Ven1Z/QQOIawaKsCbIN1jqAvbNL0Y7mYVRJTecG5nhzGgAySyMAB6Ven1a/QUNIK4ZKMKaIN9gqQvYN78Y7WQWRpXccG5khjOjASSzMAJ4VOr1afUXNIC4ZqAIa4J8g6UuYN/8YrSTWRhVcsO5kRnOjAaQzMII4FGp16fVX9AA4pqBIqwJ8g2WuoB984vRTmZhVMkN50ZmODMaQDILI4BHpV6fVn9BA4hrBoqwJsg3WOqFinelAAAgAElEQVQC9s0vRjuZhVElN5wbmeHMaADJLIwAHpV6fVr9BQ0grhkowpog32CpC9g3vxjtZBZGldxwbmSGM6MBJLMwAnhU6vVp9Rc0gLhmoAhrgnyDpS5g3/xitJNZGFVyw7mRGc6MBpDMwgjgUanXp9Vf0ADimoEirAnyDZa6gH3zi9FOZmFUyQ3nRmY4MxpAMgsjgEelXp9Wf0EDiGsGirAmyDdY6gL2zS9GO5mFUSU3nBuZ4cxoAMksjAAelXp9Wv0FDSCuGSjCmiDfYKkL2De/GO1kFkaV3HBuZIYzowEkszACeFTq9Wn1FzSAuGagCGuCfIOlLmDf/GK0k1kYVXLDuZEZzowGkMzCCOBRqden1V/QAOKagSKsCfINlrqAffOL0U5mYVTJDedGZjgzGkAyCyOAR6Ven1Z/QQOIawaKsCbIN1jqAvbNL0Y7mYVRJTecG5nhzGgAySyMAB6Ven1a/QUNIK4ZKMKaIN9gqQvYN78Y7WQWRpXccG5khjOjASSzMAJ4VOr1afUXNIC4ZqAIa4J8g6UuYN/8YrSTWRhVcsO5kRnOjAaQzMII4FGp16fVX9AA4pqBIqwJ8g2WuoB984vRTmZhVMkN50ZmODMaQDILI4BHpV6fVn9BA4hrBoqwJsg3WOoC9s0vRjuZhVElN5wbmeHMaADJLIwAHpV6fVr9BQ0grhkowpog32CpC9g3vxjtZBZGldxwbmSGM6MBJLMwAnhU6vVp9Rc0gLhmoAhrgnyDpS5g3/xitJNZGFVyw7mRGc6MBpDMwgjgUanXp9Vf0ADimoEirAnyDZa6gH3zi9FOZmFUyQ3nRmY4MxpAMgsjgEelXp9Wf0EDiGsGirAmyDdY6gL2zS9GO5mFUSU3nBuZ4cxoAMksjAAelXp9Wv0FDSCuGSjCmiDfYKkL2De/GO1kFkaV3HBuZIYzowEkszACeFTq9Wn1FzSAuGagCGuCfIOlLmDf/GK0k1kYVXLDuZEZzowGkMzCCOBRqden1V/QAOKagSKsCfINlrqAffOL0U5mYVTJDedGZjgzGkAyCyOAR6Ven1Z/QQOIawaKsCbIN1jqAvbNL0Y7mYVRJTecG5nhzGgAySyMAB6Ven1a/QUNIK4ZKMKaIN9gqQvYN78Y7WQWRpXccG5khjOjASSzMAJ4VOr1afUXNIC4ZqAIa4J8g6UuYN/8YrSTWRhVcsO5kRnOjAaQzMII4FGp16fVX9AA4pqBIqwJ8g2WuoB984vRTmZhVMkN50ZmODMaQDILI4BHpV6fVn9BA4hrBoqwJsg3WOoC9s0vRjuZhVElN5wbmeHMaADJLIwAHpV6fVr9BQ0grhkowpog32CpC9g3vxjtZBZGldxwbmSGM6MBJLMwAnhU6vVp9Rc0gLhmoAhrgnyDpS5g3/xitJNZGFVyw7mRGc6MBpDMwgjgUanXp9Vf0ADimoEirAnyDZa6gH3zi9FOZmFUyQ3nRmY4MxpAMgsjgEelXp9Wf0EDiGsGirAmyDdY6gL2zS9GO5mFUSU3nBuZ4cxoAMksjAAelXp9Wv0FDSCuGSjCmiDfYKkL2De/GO1kFkaV3HBuZIYzowEkszACeFTq9Wn1FzSAuGagCGuCfIOlLmDf/GK0k1kYVXLDuZEZzowGkMzCCOBRqden1V/QAOKagSKsCfINlrqAffOL0U5mYVTJDedGZjgzGkAyCyOAR6Ven1Z/QQOIawaKsCbIN1jqAvbNL0Y7mYVRJTecG5nhzGgAySyMAB6Ven1a/QUNIK4ZKMKaIN9gqQvYN78Y7WQWRpXccG5khjOjASSzMAJ4VOr1afUXNIC4ZqAIa4J8g6UuYN/8YrSTWRhVcsO5kRnOjAaQzMII4FGp16fVX9AA4pqBIqwJ8g2WuoB984vRTmZhVMkN50ZmODMaQDILI4BHpV6fVn9BA4hrBoqwJsg3WOoC9s0vRjuZhVElN5wbmeHMaADJLIwAHpV6fVr9BQ0grhkowpog32CpC9g3vxjtZBZGldxwbmSGM6MBJLMwAnhU6vVp9RcFZwDbtWsnK1eurJLJyy67TO6991658MILZcqUKRXau3TpIi+//HLZ3+3cuVNGjBgh06dPl88++0zOOOMMue+++6RNmzZlfTZv3ixDhw6V2bNnu78755xz5O6775amTZuW9Vm1apVcfvnlsnjxYmnQoIEMGDBAxo0bJ/Xq1cusNGuCfAOlLmDf/GK0k1kYVXLDuZEZzowGkMzCCOBRqden1V8UnAH86KOPZNeuXWWZ/Mtf/iJnnnmmPPfcc3L66ac7A/jhhx/KI488UtZHDdkhhxxS9uchQ4bInDlzZPLkyXLooYfK8OHDZdOmTfLaa69JnTp1XL+zzz5b1qxZIw8++KD78+DBg0XNp8bppfdw/PHHS4sWLWT8+PGyceNGGThwoPTu3dsZxayXNUG+cVIXsG9+MdrJLIwqueHcyAxnRgNIZmEE8KjU69PqLwrOAFZO4bBhw2Tu3Lny9ttvS61atZwB3LJlizz99NPVZnvr1q3OtD322GPSt29f12ft2rXStm1bmTdvnpx11lmydOlS6dSpk1s11NVDvfS/u3btKsuWLZOOHTvK/PnzpWfPnrJ69Wpp3bq16zNjxgw3/vr166VJkyaZ1GZNkG+Q1AXsm1+MdjILo0puODcyw5nRAJJZGAE8KvX6tPqLgjaAn3/+uTNfV111lVx33XUuu2rA1Pzpqp9u15522mlyyy23SMuWLV27btfqlq+u+DVr1qxMEZ07d5ZevXrJmDFj5OGHH3afqUay/KWfN2HCBBk0aJDceOONMmvWLHnrrbfKuui2sa406hjdunWrVm26/az/y12aIDWfGzZsyGwaERmrgBctWuRWSevWrYuElmxfMgtLPbnh3MgMZ5YzgPy5hrGj1jBexaAz9RfNmzcXXfjKuihVnlJBG8Bf/vKX7rk7fRYvtwo3c+ZMadSokRx55JHy3nvvyQ033CBffPGF296tX7++TJs2zRm48iZMJ9y9e3c56qijZNKkSXLrrbe67eEVK1ZUUMwxxxzjYkeNGuW2hN9//31ZuHBhhT46hsb279+/WrWNHj3amczKl95Xw4YNcYUyggRIgARIgARIgAQqEdi+fbvzSEVpAHW7Vlf6cs/lVZf9devWOTOo27P6fN7eDKCukLVv314eeOABZwD1IMny5csrfGSHDh3koosukmuvvdYZQD2MsmDBggp99H4effRR6devX7Vi5Apg4dco/6UcliNyw7mRGc6sGFZmwmZti6LWcH6pMyvaFUA1X0cffbQ8+eSTcu655+4zs2rcLr74YrnmmmtqfAu48o1a9+h9kk79GQbf/GK0k1kYVXLDuZEZzixnAPWZ7R49evDRlowIqbWMoMp1S52Z1V8U7BawbqXqdq0ewjjggAP2mlk9nXv44Ye707wXXHCBWwrVQyBTp06VPn36uDhdJdRXwFQ+BPLKK6/ISSed5Prof5988slVDoHoSeFWrVq5Prr9rCeBeQgEL7RCiki96GuKJbnh5MkMZ0YDSGZhBPCo1OuzKA3gl19+6Z7X0+fsbr/99rKsbtu2TdQYnnfeec6U6TN6ejhEnxHUk72NGzd2ffU1MHpyWJ/V00Mb+k5ANYqVXwOjp4PVZOqlW766lVz5NTCHHXaYjB071h0q0QMoepCEr4HBC62QIlIv+ppiSW44eTLDmdEAklkYATwq9fosSgOoBy/0+T99Rk8PZuQufamzGrA33njDneBVE6incW+66SZ30jZ37dixQ0aOHOmeByz/IujyfdTQVX4R9D333FPlRdD6AurKL4LWgyBZL2uCfOOkLmDf/GK0k1kYVXLDuZEZzowGkMzCCOBRqden1V8U7BYwnsrCjLAmyDer1AXsm1+MdjILo0puODcyw5nRAJJZGAE8KvX6tPoLGkBcM1CENUG+wVIXsG9+MdrJLIwqueHcyAxnRgNIZmEE8KjU69PqL2gAcc1AEdYE+QZLXcC++cVoJ7MwquSGcyMznBkNIJmFEcCjUq9Pq7+gAcQ1A0VYE+QbLHUB++YXo53MwqiSG86NzHBmNIBkFkYAj0q9Pq3+ggYQ1wwUYU2Qb7DUBeybX4x2MgujSm44NzLDmdEAklkYATwq9fq0+gsaQFwzUIQ1Qb7BUhewb34x2sksjCq54dzIDGdGA0hmYQTwqNTr0+ovaABxzUAR1gT5BktdwL75xWgnszCq5IZzIzOcGQ0gmYURwKNSr0+rv6ABxDUDRVgT5BssdQH75hejnczCqJIbzo3McGY0gGQWRgCPSr0+rf6CBhDXDBRhTZBvsNQF7JtfjHYyC6NKbjg3MsOZ0QCSWRgBPCr1+rT6CxpAXDNQhDVBvsFSF7BvfjHaySyMKrnh3MgMZ0YDSGZhBPCo1OvT6i9oAHHNQBHWBPkGS13AvvnFaK8pZp9+KtKo0Z4ZbdsmctBBMWYX7zNrilu8GcX/ZDILY0xuODcyKz1mVn9BA4hrBoqwJsg3GIveR6hqe00xowHEc5V6RE1pjdxSJ4DfP7VWesys/oIGENcMFGFNkG8wFr2PEA0gTqj6CGoNJ0lmODONIDecG5mVHjOrv6ABxDUDRVgT5BuMRe8jRAOIE6IBJLN8EQj7HP5cw7mRWekxs/oLGkBcM1CENUG+wVj0PkI0gDghGkAyyxeBsM/hzzWcG5mVHjOrv6ABxDUDRVgT5BuMRe8jRAOIE6IBJLN8EQj7HP5cw7mRWekxs/oLGkBcM1CENUG+wVj0PkKFYwA//ljk4IP33M+8eSLdu4vUqYPff01FUGs4eTLDmWkEueHcyKz0mFn9BQ0grhkowpog32Aseh+hwjCATz4pMnSoyAcffHU/bdqI3HWXSO/e+BxqIoJaw6mTGc6MBpDMwgjgUanXp9Vf5M0AvvDCC3LKKafIAQccUCELX3zxhbz00kvyne98B89OEURYE+RDkLqAffOL0b6/man5+8EPRHbvrjibWrX2/PmJJ9IwgfubW4zc7+/PJLMw4uSGcyOz0mNm9Rd5M4B16tSRdevWScuWLStkYePGje7vdu3ahWenCCKsCfIhYNH7CNXsCqDKvl07kTVrqr9PNYG6Evjee4W/HUytFbbW8Lsr3AhqDc8NmZUeM6u/yJsBrF27tnz44YfSokWLCllYsWKFfOtb3xK90VK8rAnyMWPR+wjVrAFcskSkWzf/PT73nMjpp/v71WQPag2nT2Y4M40gN5wbmZUeM6u/MBvA3v98gGnWrFny7//+71K/fv2yLOiq35/+9Cfp2LGjPPPMM3h2iiDCmiAfAha9j1DNGsDp00UGDPDf47RpIv37+/vVZA9qDadPZjgzGkAyCyOAR6Ven1Z/YTaAgwYNctSnTJkiffr0kQYNGpRloV69etKuXTu55JJLpHnz5nh2iiDCmiAfgtQF7JtfjPb9yYwrgDEymM5n7k+tpUPFf6fk5mdUuQeZlR4zq78wG8Ac8jFjxsiIESPkoNS+4R7XDBRhTZBvMBa9j1DNrgDmngHU07+VD4HonfEZQDx/KUWwPsOyRW44NzIrPWZWf5E3A4ijL40Ia4J8lFj0PkI1awB19NwpYP3v8iaQp4Dx3KUWwfoMyxi54dzIrPSYWf1F3gygHgDRFcDf/OY3sn79etldabmDp4C3SpMmTXCFeiJY9DjSmmBW3XsA27YVmTgxjVfAKOWa4IZnt7AiyCwsH+SGcyOz0mNWMAbw7LPPllWrVslPf/pTadWqldTKLW/8Myfnnnsunp0iiLAmyIeARe8jVPMrgLk74DeB4LlKPYL1GZZBcsO5kVnpMbP6i7ytADZu3FhefPFFOf744/EsFHGENUE+NCx6H6HCMYCffirSqNGe+9m2TSS1x2WptXS0ht9pYUVQa3g+yKz0mFn9Rd4MYKdOneTxxx+XE044Ac9CEUdYE+RDw6L3EaIBxAlVH0Gt4STJDGemEeSGcyOz0mNm9Rd5M4ALFy6U8ePHy6RJk9yrX3jtIWBNkI8ji95HiAYQJ0QDSGb5IhD2Ofy5hnMjs9JjZvUXeTOAzZo1k+3bt4t+92/Dhg2lbt26FbKxadMmPDtFEGFNkA8Bi95HiAYQJ0QDSGb5IhD2Ofy5hnMjs9JjZvUXeTOA+iLofV0DBw7Es1MEEdYE+RCw6H2EaABxQjSAZJYvAmGfw59rODcyKz1mVn+RNwOIoy+NCGuCfJRY9D5ChWMA8TstrAhqDc8HmeHMNILccG5kVnrMrP4ibwZQXwGzr+uII47As1MEEdYE+RCw6H2EaABxQlwBJLN8EQj7HP5cw7mRWekxs/qLvBnA2rVrV3n3X/l08EXQfBE0Xp5xIviDMowrueHcyAxnxhVAMgsjgEelXp8FYwDfeuutCvQV7BtvvCF33nmn3HLLLdK7d288O0UQYU2QD0HqAvbNL0Y7mYVRJTecG5nhzGgAySyMAB6Ven1a/UXeVgD3hv7Xv/61jB07VpYsWYJnpwgirAnyIUhdwL75xWgnszCq5IZzIzOcGQ0gmYURwKNSr0+rv4huAN9++2337SCf6tcglOBlTZAPWeoC9s0vRjuZhVElN5wbmeHMaADJLIwAHpV6fVr9Rd4MoN5I+Wv37t2ybt06GT16tCxbtkzefPNNPDtFEGFNkA9B6gL2zS9GO5mFUSU3nBuZ4cxoAMksjAAelXp9Wv1F3gxgdYdA1AS2bdtWZsyYIV27dsWzUwQR1gT5EKQuYN/8YrSTWRhVcsO5kRnOjAaQzMII4FGp16fVX+TNAD7//PMV6KshbNGihXzta1+TAw44AM9MkURYE+TDkLqAffOL0U5mYVTJDedGZjgzGkAyCyOAR6Ven1Z/kTcDiKMvjQhrgnyUUhewb34x2sksjCq54dzIDGdGA0hmYQTwqNTr0+ov8moA33nnHZk4caIsXbrUvRPwG9/4hlxxxRXSvn17PDNFEmFNkA9D6gL2zS9GO5mFUSU3nBuZ4cxoAMksjAAelXp9Wv1F3gzgggUL5JxzznEnfk899VTR5/9eeukl0fcDzpkzR84880w8O0UQYU2QD0HqAvbNL0Y7mYVRJTecG5nhzGgAySyMAB6Ven1a/UXeDOAJJ5wgZ511ltx+++0VsnDttdfKwoUL5fXXX8ezUwQR1gT5EKQuYN/8YrSTWRhVcsO5kRnOjAaQzMII4FGp16fVX+TNAB544IHy5z//WTp06FAhCytWrJBvfvObsmPHDjw7RRBhTZAPQeoC9s0vRjuZhVElN5wbmeHMaADJLIwAHpV6fVr9Rd4MoL7uRb/27Yc//GGFLPzyl7+UESNGyKpVq/DsFEGENUE+BKkL2De/GO1kFkaV3HBuZIYzowEkszACeFTq9Wn1F3kzgP/93/8tEyZMEN3yPeWUU9whkN/+9rdyxx13yPDhw+X666/Hs1MEEdYE+RCkLmDf/GK0k1kYVXLDuZEZzowGkMzCCOBRqden1V/kzQDqoQ89ATx+/HhZu3aty0Tr1q1l5MiRMnToUGcIS/GyJsjHLHUB++YXo53MwqiSG86NzHBmNIBkFkYAj0q9Pq3+Im8GsDz6Tz75xP2xcePGeEaKLMKaIB+O1AXsm1+MdjILo0puODcyw5nRAJJZGAE8KvX6tPoLswH87LPPZNGiRdKtW7cqhk9vbsmSJe50cP369fHsFEGENUE+BKkL2De/GO1kFkaV3HBuZIYzowEkszACeFTq9Wn1F2YDeNddd8ns2bPlN7/5TbX0v/vd78r3v/99ufzyy/HsFEGENUE+BKkL2De/GO1kFkaV3HBuZIYzowEkszACeFTq9Wn1F2YDeNJJJ8kNN9wg3/ve96qlP3fuXNEDIq+++iqenSKIsCbIhyB1AfvmF6OdzMKokhvOjcxwZjSAZBZGAI9KvT6t/sJsAJs1a+a+7eOII46olr6+/qVz586yefPmTNlp166drFy5skrfyy67TO699173DSNjxoyRBx980H1mly5d3N8fe+yxZTE7d+50r56ZPn266Bb1GWecIffdd5+0adOmrI/G6uEUXb3US7/F5O6775amTZuW9dF715XLxYsXS4MGDWTAgAEybtw4qVevXqa5aCdrgnwDpS5g3/xitJNZGFVyw7mRGc6MBpDMwgjgUanXp9VfmA2gHvTQ5/xOPPHEaum/9tprcvrpp0vuYIgvRR999JHs2rWrrNtf/vIX9zVyzz33nPscfa3MLbfcIpMnT5ZjjjlGbr75ZnnhhRdk+fLlZc8gDhkyxH39nPY59NBD3WtoNm3aJHovderUcZ999tlny5o1a5yR1Gvw4MGi5lPj9NJ70K+1a9GihTvZvHHjRhk4cKD07t3bGcWslzVBvnFSF7BvfjHaySyMKrnh3MgMZ0YDSGZhBPCo1OvT6i/MBvDkk092z/hdc8011dLXr4Z7+umn5eWXX8azIyLDhg0T3UZ+++23Xby+Wkb/LjeervYddthhzhheeumlsnXrVmfaHnvsMenbt6+L0dfS6Iuq582b5w6kLF26VDp16uTuSVcQ9dL/7tq1qyxbtkw6duwo8+fPl549e8rq1avdmHrNmDFDLrzwQlm/fr00adIk03ysCfINkrqAffOL0U5mYVTJDedGZjgzGkAyCyOAR6Ven1Z/YTaAuoJ21VVXOXOkhqn8patp/fv3d98Qoits6PX5558786Wff91118m7774r7du3d98rrN89nLvOPfdct3U7ZcoUt12rW7664qfb07lLt6F79erlto8ffvhh95lbtmypcEv6Gfoy60GDBsmNN94os2bNctvbuUu3jQ855BA3hp56znJZE+QbI3UB++YXo53MwqiSG86NzHBmNIBkFkYAj0q9Pq3+wmwAFfmPfvQjmTZtmnz96193q2f60mddZdPvAe7Tp497Fi/k0q+R0+fu9Fk8NYIvvfSSnHrqqfLBBx+Urcrp56q51OcGFyxY4O5DDZyuDJa/unfvLkcddZRMmjRJbr31Vrc9rPdX/tItZY0dNWqU+8z3339fFi5cWKGPvs5GY9XYVnfpuOXH1gTp6uOGDRsyrxoirFTA+hoe3SavW7cuElqyfcksLPXkhnMjM5xZzgDy5xrGjlrDeBWDztRfNG/e3O18Zt2VLE8pLwZQP1DN2uOPPy5/+9vf3EENNVNq3tQAhl66XasHLnLP5eUMoG7ptmrVquxjL7nkErdV+8wzz+zVAKpB0tXDBx54wBlAXS3U5wbLXx06dJCLLrrIfZ1deVNZvo/ez6OPPir9+vWrdlqjR492q4yVLzWmDRs2DEXBOBIgARIgARIgARIoI7B9+3bns2rcAOY7J7qid/TRR8uTTz4pusWrVwpbwFwBzLcS8v95/JdyGFNyw7mRGc6sGFZmwmZti6LWcH6pM6vxFcDatWt7v+dXt4S/+OILKDu6kqbbtbqyd8ABB7hYXVnUreArr7xSrr76avd3+pxgy5YtqxwCmTp1atnq47p169wrYCofAnnllVdE32Ool/63HmipfAhETwrnVhtnzpzpTgLzEAiUyoLrnPpzHzUFlNxw8mSGM8sZQP153aNHDz7akhEhtZYRVLluqTOr8WcA9aDE3i7dstVXpqhx0/fxZb2+/PJL97yePmenp4jLX3ra97bbbpNHHnlEdMtWt3P1NTSVXwOjJ4f1WT09tKHvBNTXuFR+DYxuJavJ1Eu3fI888sgqr4HRE8Zjx451h0r0BLAeJOFrYLJmsjD7pV70NUWV3HDyZIYzowEkszACeFTq9VnjBrA65LqKpgcp9Nm9888/X2666aa9vii6ung9eKHP/6mp02cJy1+5F0GrcSv/IujjjjuurNuOHTtk5MiR7nnA8i+C1sMYuUsNXeUXQd9zzz1VXgStL6Cu/CJo5HuNrQnySTp1AfvmF6OdzMKokhvOjcxwZjSAZBZGAI9KvT6t/iJvh0AUva6o/exnP3MHLNTA6ercv/7rv+JZKaIIa4J8KFIXsG9+MdrJLIwqueHcyAxnRgNIZmEE8KjU69PqL/JiAPUEipo93RrVb8/Qbdpvf/vbeDaKMMKaIB+S1AXsm1+MdjILo0puODcyw5nRAJJZGAE8KvX6tPoLswH8+c9/7gzfv/zLvzgTmDuxi6eiOCOsCfJRSV3AvvnFaCezMKrkhnMjM5wZDSCZhRHAo1KvT6u/MBtAPQXcoEED+e53v1v2PbvVpUFf51KKlzVBPmapC9g3vxjtZBZGldxwbmSGM6MBJLMwAnhU6vVp9RdmA6gnY/U1L75LT+2W4mVNkI9Z6gL2zS9GO5mFUSU3nBuZ4cxoAMksjAAelXp9Wv2F2QDiyEsrwpogH63UBeybX4x2MgujSm44NzLDmdEAklkYATwq9fq0+gsaQFwzUIQ1Qb7BUhewb34x2sksjCq54dzIDGdGA0hmYQTwqNTr0+ovaABxzUAR1gT5BktdwL75xWgnszCq5IZzIzOcGQ0gmYURwKNSr0+rv6ABxDUDRVgT5BssdQH75hejnczCqJIbzo3McGY0gGQWRgCPSr0+rf6CBhDXDBRhTZBvsNQF7JtfjHYyC6NKbjg3MsOZ0QCSWRgBPCr1+rT6CxpAXDNQhDVBvsFSF7BvfjHaySyMKrnh3MgMZ0YDSGZhBPCo1OvT6i9oAHHNQBHWBPkGS13AvvnFaCezMKrkhnMjM5wZDSCZhRHAo1KvT6u/oAHENQNFWBPkGyx1AfvmF6OdzMKokhvOjcxwZjSAZBZGAI9KvT6t/oIGENcMFGFNkG+w1AXsm1+MdjILo0puODcyw5nRAJJZGAE8KvX6tPoLGkBcM1CENUG+wVIXsG9+MdrJLIwqueHcyAxnRgNIZmEE8KjU69PqL2gAcc1AEdYE+QZLXcC++cVoJ7MwquSGcyMznBkNIJmFEcCjUq9Pq7+gAcQ1A0VYE+QbLHUB++YXo53MwqiSG86NzHBmNIBkFkYAj0/FdpkAACAASURBVEq9Pq3+ggYQ1wwUYU2Qb7DUBeybX4x2MgujSm44NzLDmdEAklkYATwq9fq0+gsaQFwzUIQ1Qb7BUhewb34x2sksjCq54dzIDGdGA0hmYQTwqNTr0+ovaABxzUAR1gT5BktdwL75xWgnszCq5IZzIzOcGQ0gmYURwKNSr0+rv6ABxDUDRVgT5BssdQH75hejnczCqJIbzo3McGY0gGQWRgCPSr0+rf6CBhDXDBRhTZBvsNQF7JtfjHYyC6NKbjg3MsOZ0QCSWRgBPCr1+rT6CxpAXDNQhDVBvsFSF7BvfjHaySyMKrnh3MgMZ0YDSGZhBPCo1OvT6i9oAHHNQBHWBPkGS13AvvnFaCezMKrkhnMjM5wZDSCZhRHAo1KvT6u/oAHENQNFWBPkGyx1AfvmF6OdzMKokhvOjcxwZjSAZBZGAI9KvT6t/oIGENcMFGFNkG+w1AXsm1+MdjILo0puODcyw5nRAJJZGAE8KvX6tPoLGkBcM1CENUG+wVIXsG9+MdrJLIwqueHcyAxnRgNIZmEE8KjU69PqL2gAcc1AEdYE+QZLXcC++cVoJ7MwquSGcyMznBkNIJmFEcCjUq9Pq7+gAcQ1A0VYE+QbLHUB++YXo53MwqiSG86NzHBmNIBkFkYAj0q9Pq3+ggYQ1wwUYU2Qb7DUBeybX4x2MgujSm44NzLDmdEAklkYATwq9fq0+gsaQFwzUIQ1Qb7BUhewb34x2sksjCq54dzIDGdGA0hmYQTwqNTr0+ovaABxzUAR1gT5BktdwL75xWgnszCq5IZzIzOcGQ0gmYURwKNSr0+rv6ABxDUDRVgT5BssdQH75hejnczCqJIbzo3McGY0gGQWRgCPSr0+rf6CBhDXDBRhTZBvsNQF7JtfjHYyC6NKbjg3MsOZ0QCSWRgBPCr1+rT6CxpAXDNQhDVBvsFSF7BvfjHaySyMKrnh3MgMZ0YDSGZhBPCo1OvT6i9oAHHNQBHWBPkGS13AvvnFaCezMKrkhnMjM5wZDSCZhRHAo1KvT6u/oAHENQNFWBPkGyx1AfvmF6OdzMKokhvOjcxwZjSAZBZGAI9KvT6t/oIGENcMFGFNkG+w1AXsm1+MdjILo0puODcyw5nRAJJZGAE8KvX6tPoLGkBcM1CENUG+wVIXsG9+MdrJLIwqueHcyAxnRgNIZmEE8KjU69PqL2gAcc1AEdYE+QZLXcC++cVoJ7MwquSGcyMznBkNIJmFEcCjUq9Pq7+gAcQ1A0VYE+QbLHUB++YXo53MwqiSG86NzHBmNIBkFkYAj0q9Pq3+ggYQ1wwUYU2Qb7DUBeybX4x2MgujSm44NzLDmdEAklkYATwq9fq0+gsaQFwzUIQ1Qb7BUhewb34x2sksjCq54dzIDGdGA0hmYQTwqNTr0+ovaABxzUAR1gT5BktdwL75xWgnszCq5IZzIzOcGQ0gmYURwKNSr0+rv6ABxDUDRVgT5BssdQFXN79PPxVp1GhPy7ZtIgcd5KOAtRcjM4xAWG9yw7mRGc6MBpDMwgjgUanXp9Vf0ADimoEirAnyDZa6gGkAfRkunPZi1FpsumQWRpjccG5kVnrMrP6CBhDXDBRhTZBvsGIseq4A+rJeM+3FqLXYJMksjDC54dzIrPSYWf0FDSCuGSjCmiDfYMVY9DSAvqzXTHsxai02STILI0xuODcyKz1mVn9BA4hrBoqwJsg3WDEWPQ2gL+s1016MWotNkszCCJMbzo3MSo+Z1V/QAOKagSKsCfINVoxFTwPoy3rNtBej1mKTJLMwwuSGcyOz0mNm9Rc0gLhmoAhrgnyDFWPR0wD6sl4z7cWotdgkySyMMLnh3Mis9JhZ/QUNIK4ZKMKaIN9gxVj0NIC+rNdMezFqLTZJMgsjTG44NzIrPWZWf0EDiGsGirAmyDdYMRY9DaAv6zXTXoxai02SzMIIkxvOjcxKj5nVX9AA4pqBIqwJ8g1WjEVPA+jLes20F6PWYpMkszDC5IZzI7PSY2b1FwVpAD/44AO55pprZP78+fLZZ5/JMcccIw899JCceOKJLsMXXnihTJkypUK2u3TpIi+//HLZ3+3cuVNGjBgh06dPd59xxhlnyH333Sdt2rQp67N582YZOnSozJ492/3dOeecI3fffbc0bdq0rM+qVavk8ssvl8WLF0uDBg1kwIABMm7cOKlXr14mtVkT5BukGIueBtCX9ZppL0atxSZJZmGEyQ3nRmalx8zqLwrOAKopO+GEE6Rbt24yZMgQadmypbzzzjvSrl07ad++fZkB/PDDD+WRRx4py7gaskMOOaTszxo7Z84cmTx5shx66KEyfPhw2bRpk7z22mtSp04d1+/ss8+WNWvWyIMPPuj+PHjwYDeOxum1a9cuOf7446VFixYyfvx42bhxowwcOFB69+7tjGKWy5og3xjFWPQ0gL6s10x7MWotNkkyCyNMbjg3Mis9ZlZ/UXAG8Nprr5Xf/e538uKLL+41m7oCuGXLFnn66aer7bN161Zn2h577DHp27ev67N27Vpp27atzJs3T8466yxZunSpdOrUya0a6uqhXvrfXbt2lWXLlknHjh3dCmTPnj1l9erV0rp1a9dnxowZbgVy/fr10qRJE6/irAnyDVCMRU8D6Mt6zbQXo9ZikySzMMLkhnMjs9JjZvUXBWcA1ZSpQdOVueeff14OP/xwueyyy+SSSy4py64aMDV/uuqn27WnnXaa3HLLLW61UC/drtUtX13xa9asWVlc586dpVevXjJmzBh5+OGH5aqrrnJGsvylnzdhwgQZNGiQ3HjjjTJr1ix56623yrroCqWuNOoYukrpu6wJ8n1+MRY9DaAv6zXTXoxai02SzMIIkxvOjcxKj5nVXxScATzwwANdFtWc/fCHP5RXX31Vhg0bJpMmTZILLrjAtc2cOVMaNWokRx55pLz33ntyww03yBdffOG2d+vXry/Tpk1zBk6fAyx/de/eXY466ij3WbfeeqvbHl6xYkWFPvq8ocaOGjXKbQm///77snDhwgp9dAyN7d+/fxXF6Zjlx9UE6crjhg0bMq0YohLWol+0aJGceeaZUrduXTS8IPurAWzWbM9cNm/+hxx0UH5vsxiZ5ZdQ9Z9GbjhlMsOZaQS54dzIrPSYqb9o3ry56K5nlh3JyoQKzgDqqt63vvUteemll8ruVQ9q/OEPf5Df//731WZ43bp1zgzq9qw+n7c3A6gmSZ8jfOCBB5wB1IMky5cvr/CZHTp0kIsuukh0K1oN4MqVK2XBggUV+ug9Pvroo9KvX78q9zN69Gi3wlj50ntq2LAhrtASjNixo47069fTzXzGjLly4IG7SpACp0wCJEACJEACeyewfft2dzC1aAygGjk1ar/4xS/KZn3//ffLzTffLHo6eG+XGreLL77YnR6uyS1grgDay5UrgHaGMT6BKww4VTLDmXEFkMzCCOBRqddn0a0AqpvVQxflD4FceeWV8sorr1RYFSyfaj2dq88K6mle3SbOHQKZOnWq9OnTx3XVVUJ9BUzlQyD6uSeddJLro/998sknVzkEos8jtmrVyvXR7Wc9CcxDIHixZY34+GORgw/e03vePJHu3UX+eXA760fssx+flQnDSG44NzLDmeUMoP6s7tGjR9E82hJGInsUtZadVa5n6syK7hlA3eo95ZRT3Daqmjd9BlAPgKi5O//882Xbtm2i26znnXeeM2X6jN51110n+r4+PdnbuHFjl1t9DczcuXPds3p6aEPfCahGsfJrYPR0sD4TqJdu+eoKZOXXwBx22GEyduxYd6hED6DoQRK+BgYvtiwRTz4pMnSoSPnFXn114113ifTuneUT/H1SL3r/DOP0IDecK5nhzGgAySyMAB6Ven0WnQHUFKpx00MYb7/9tju0oQdCcqeA9aXOasDeeOMNd4JXTaCexr3pppvcYYvctWPHDhk5cqR7HrD8i6DL91FDV/lF0Pfcc0+VF0HrKeTKL4LWgyBZLmuCfGOkLuDy81Pz94MfiOzeXXHWtWrt+fMTT+THBBYTM58+8tlObjhNMsOZ0QCSWRgBPCr1+rT6i4I7BIKnsLAjrAnyzS51Aefmt2uXSLt2ImvWVD9jNYG6Evjee/bt4GJh5tNGvtvJDSdKZjgzGkAyCyOAR6Ven1Z/QQOIawaKsCbIN1jqAs7Nb8kSkQyvVZTnnhM5/XQflX23FwszGwU8mtzIDCcQFkGt4dzIrPSYWf0FDSCuGSjCmiDfYMVS9NOniwwY4JutyLRpItW8ftEfWK5HsTCDJp2HzuSGQyQznBlXAMksjAAelXp9Wv0FDSCuGSjCmiDfYKkLmCuAvgwXTnuxaG1/EiWzMNrkhnMjs9JjZvUXNIC4ZqAIa4J8gxVL0eeeAdTTv5UPgSgDPgPoU0L89mLRWnxSX41AZmG0yQ3nRmalx8zqL2gAcc1AEdYE+QYrpqLPnQLWOZc3gTwF7FPB/mkvJq3tH2J7vtKM77PDaZMbmeEE8IjUdWb1FzSAuGagCGuCfIOlLuDK86vuPYD6dp+JE/PzChgdr9iY+TSSr3Zyw0mSGc6MNUpmYQTwqNTr0+ovaABxzUAR1gT5BktdwNXNj98E4st6zbQXo9ZikySzMMLkhnMjs9JjZvUXNIC4ZqAIa4J8gxVj0et3ATdqtGfm27aJHHSQjwLWXozMMAJhvckN50ZmODOuAJJZGAE8KvX6tPoLGkBcM1CENUG+wVIXcHXzowH0Zb1m2otRa7FJklkYYXLDuZFZ6TGz+gsaQFwzUIQ1Qb7BirHoaQB9Wa+Z9mLUWmySZBZGmNxwbmRWesys/oIGENcMFGFNkG+wYix6GkBf1mumvRi1FpskmYURJjecG5mVHjOrv6ABxDUDRVgT5BusGIueBtCX9ZppL0atxSZJZmGEyQ3nRmalx8zqL2gAcc1AEdYE+QYrxqKnAfRlvWbai1FrsUmSWRhhcsO5kVnpMbP6CxpAXDNQhDVBvsGKsehpAH1Zr5n2YtRabJJkFkaY3HBuZFZ6zKz+ggYQ1wwUYU2Qb7BiLHoaQF/Wa6a9GLUWmySZhREmN5wbmZUeM6u/oAHENQNFWBPkG6wYi54G0Jf1mmkvRq3FJklmYYTJDedGZqXHzOovaABxzUAR1gT5BivGoqcB9GW9ZtqLUWuxSZJZGGFyw7mRWekxs/oLGkBcM1CENUG+wYqx6GkAfVmvmfZi1FpskmQWRpjccG5kVnrMrP6CBhDXDBRhTZBvsGIsehpAX9Zrpr0YtRabJJmFESY3nBuZlR4zq7+gAcQ1A0VYE+QbrBiLngbQl/WaaS9GrcUmSWZhhMkN50ZmpcfM6i9oAHHNQBHWBPkGK8aipwH0Zb1m2otRa7FJklkYYXLDuZFZ6TGz+gsaQFwzUIQ1Qb7BirHoaQB9Wa+Z9mLUWmySZBZGmNxwbmRWesys/oIGENcMFGFNkG+wYix6GkBf1mumvRi1FpskmYURJjecG5mVHjOrv6ABxDUDRVgT5BuMRe8jVLWdzHBmGkFuODcyw5lRa2QWRgCPSr0+rf6CBhDXDBRhTZBvsNQF7JtfjHYyC6NKbjg3MsOZ0QCSWRgBPCr1+rT6CxpAXDNQhDVBvsFSF7BvfjHaySyMKrnh3MgMZ0YDSGZhBPCo1OvT6i9oAHHNQBHWBPkGS13AvvnFaCezMKrkhnMjM5wZDSCZhRHAo1KvT6u/oAHENQNFWBPkGyx1AfvmF6OdzMKokhvOjcxwZjSAZBZGAI9KvT6t/oIGENcMFGFNkG+w1AXsm1+MdjILo0puODcyw5nRAJJZGAE8KvX6tPoLGkBcM1CENUG+wVIXsG9+MdrJLIwqueHcyAxnRgNIZmEE8KjU69PqL2gAcc1AEdYE+QZLXcC++cVoJ7MwquSGcyMznBkNIJmFEcCjUq9Pq7+gAcQ1A0VYE+QbLHUB++YXo53MwqiSG86NzHBmNIBkFkYAj0q9Pq3+ggYQ1wwUYU2Qb7DUBeybX4x2MgujSm44NzLDmdEAklkYATwq9fq0+gsaQFwzUIQ1Qb7BUhewb34x2sksjCq54dzIDGdGA0hmYQTwqNTr0+ovaABxzUAR1gT5BktdwL75xWgnszCq5IZzIzOcGQ0gmYURwKNSr0+rv6ABxDUDRVgT5BssdQH75hejnczCqJIbzo3McGY0gGQWRgCPSr0+rf6CBhDXDBRhTZBvsNQF7JtfjHYyC6NKbjg3MsOZ0QCSWRgBPCr1+rT6CxpAXDNQhDVBvsFSF7BvfjHaySyMKrnh3MgMZ0YDSGZhBPCo1OvT6i9oAHHNQBHWBPkGS13AvvnFaCezMKrkhnMjM5wZDSCZhRHAo1KvT6u/oAHENQNFWBPkGyx1AfvmF6OdzMKokhvOjcxwZjSAZBZGAI9KvT6t/oIGENcMFGFNkG+w1AXsm1+MdjILo0puODcyw5nRAJJZGAE8KvX6tPoLGkBcM1CENUG+wVIXsG9+MdrJLIwqueHcyAxnRgNIZmEE8KjU69PqL2gAcc1AEdYE+QZLXcC++cVoJ7MwquSGcyMznBkNIJmFEcCjUq9Pq7+gAcQ1A0VYE+QbLHUB++YXo53MwqiSG86NzHBmNIBkFkYAj0q9Pq3+ggYQ1wwUYU2Qb7DUBeybX4x2MgujSm44NzLDmdEAklkYATwq9fq0+gsaQFwzUIQ1Qb7BUhewb34x2sksjCq54dzIDGdGA0hmYQTwqNTr0+ovaABxzUAR1gT5BktdwL75xWgnszCq5IZzIzOcGQ0gmYURwKNSr0+rv6ABxDUDRVgT5BssdQH75hejnczCqJIbzo3McGY0gGQWRgCPSr0+rf6CBhDXDBRhTZBvsNQF7JtfjHYyC6NKbjg3MsOZ0QCSWRgBPCr1+rT6CxpAXDNQhDVBvsFSF7BvfjHaySyMKrnh3MgMZ0YDSGZhBPCo1OvT6i9oAHHNQBHWBPkGS13AvvnFaCezMKrkhnMjM5wZDSCZhRHAo1KvT6u/oAHENQNFWBPkGyx1AfvmF6OdzMKokhvOjcxwZjSAZBZGAI9KvT6t/oIGENcMFGFN0L4G+/RTkUaN9vTYvPkf0rRpXejeSrVz6kVfU3kjN5w8meHMaADJLIwAHpV6fVr9RUEawA8++ECuueYamT9/vnz22WdyzDHHyEMPPSQnnniiy/Du3btlzJgx8uCDD8rmzZulS5cucu+998qxxx5bpoCdO3fKiBEjZPr06e4zzjjjDLnvvvukTZs2ZX00dujQoTJ79mz3d+ecc47cfffd0rRp07I+q1atkssvv1wWL14sDRo0kAEDBsi4ceOkXr16mdRmTRANYCbMUKfUix6abB47kxsOk8xwZjSAZBZGAI9KvT6t/qLgDKCashNOOEG6desmQ4YMkZYtW8o777wj7dq1k/bt27sM33HHHXLLLbfI5MmTnTm8+eab5YUXXpDly5dL48aNXR+NnTNnjutz6KGHyvDhw2XTpk3y2muvSZ06dVyfs88+W9asWeOMpF6DBw9242icXrt27ZLjjz9eWrRoIePHj5eNGzfKwIEDpXfv3s4oZrmsCaIBzEIZ65N60WOzzV9vcsNZkhnOjAaQzMII4FGp16fVXxScAbz22mvld7/7nbz44ovVZlNX/1q3bi3Dhg1zq4R66WrfYYcd5ozhpZdeKlu3bnWm7bHHHpO+ffu6PmvXrpW2bdvKvHnz5KyzzpKlS5dKp06d5OWXX3YriHrpf3ft2lWWLVsmHTt2dCuQPXv2lNWrV7sx9ZoxY4ZceOGFsn79emnSpIlXcdYE0QB6EcMdUi96eMJ5CiA3HCSZ4cxoAMksjAAelXp9Wv1FwRlANWVq0HRl7vnnn5fDDz9cLrvsMrnkkktcdt999123Evj666+7lcLcde6557qt2ylTprjtWt3y1RW/Zs2alfXp3Lmz9OrVy20fP/zww3LVVVfJli1bKqhGP2PChAkyaNAgufHGG2XWrFny1ltvlfXRFcpDDjnEjaGrlL7LmiAaQB9hvD31osdnnJ8IcsM5khnOjAaQzMII4FGp16fVXxScATzwwANdFtWc/fCHP5RXX33VrfZNmjRJLrjgAnnppZfk1FNPFX1OMLcqp/11+3blypWyYMECmTZtmjNwujJY/urevbscddRR7rNuvfVWtz28YsWKCn10S1ljR40a5T7z/fffl4ULF1boU79+fRfbv3//KorTMcuPqwnSlccNGzZkWjFEJKyHQJo123PwY/367TwEkhGeFv2iRYvkzDPPlLp1eXAmIzYht6ykvupHZjiznAFkjWLsqDWMVzHoTP1F8+bN3a5nlh3JyoQKzgDq4YpvfetbzujlLj2o8Yc//EF+//vflxlA3dJt1apVWR9dIdSt2meeeWavBlB/4evq4QMPPOAMoK4W6nOD5a8OHTrIRRddJLoVXd5Ulu+j9/joo49Kv379qihu9OjRboWx8qWmtGHDhrhC9xGxY0cd6devp+sxY8ZcOfDAXXn9fH4YCZAACZAACZBAYRLYvn27O5haNAbwyCOPdCszv/jFL8qI33///e6gh676FfoWMFcAC7NQyt8V/6UcliNyw7mRGc6sGFZmwmZti6LWcH6pMyu6FUB1s7qSV/4QyJVXXimvvPKKW/3LHQLRv7v66qtdxj///HN3WrjyIZCpU6dKnz59XJ9169a5V8BUPgSin3vSSSe5PvrfJ598cpVDIPo8Ym61cebMme4kMA+B4MVWKBGpP/dRUxzJDSdPZjiznAHUn9U9evTgYxoZEVJrGUGV65Y6s6J7BlC3ek855RS3jarmTZ8B1O1dfVXL+eef71KnRu+2226TRx55RHTLVrdzlyxZUuU1MHPnznXP6umhDX0noL7GpfJrYHQrWZ8J1Eu3fHUFsvJrYPSE8dixY92hEj0BrAdJ+BoYvNgKJSL1oq8pjuSGkycznBkNIJmFEcCjUq/PojOAmkI1bnoI4+2333aHNvRASO4UsLbnXgStxq38i6CPO+64MgXs2LFDRo4c6Z4HLP8iaD2QkbvU0FV+EfQ999xT5UXQegq58oug9SBIlsuaoH2NwW8CyZKBqn1SL/qwWdujyA1nSGY4MxpAMgsjgEelXp9Wf1Fwh0DwFBZ2hDVBNID5z2/qRZ9/Itk+kdyycSrfi8xwZjSAZBZGAI9KvT6t/oIGENcMFGFNEA0ghDtT59SLPtMkI3QiNxwqmeHMaADJLIwAHpV6fVr9BQ0grhkowpogGkAId6bOqRd9pklG6ERuOFQyw5nRAJJZGAE8KvX6tPoLGkBcM1CENUE0gBDuTJ1TL/pMk4zQidxwqGSGM6MBJLMwAnhU6vVp9Rc0gLhmoAhrgmgAIdyZOqde9JkmGaETueFQyQxnRgNIZmEE8KjU69PqL2gAcc1AEdYE0QBCuDN1Tr3oM00yQidyw6GSGc6MBpDMwgjgUanXp9Vf0ADimoEirAmiAYRwZ+qcetFnmmSETuSGQyUznBkNIJmFEcCjUq9Pq7+gAcQ1A0VYE7SvwT7+WOTgg/f0mDPnCzn77AOkTh3o9kqyc+pFX1NJIzecPJnhzGgAySyMAB6Ven1a/QUNIK4ZKMKaoL0N9uSTIkOHinzwwVc92rQRuesukd69oVssuc6pF31NJYzccPJkhjOjASSzMAJ4VOr1afUXNIC4ZqAIa4KqG0zN3w9+oN+IUrG1Vq09f37iCZrAfSUp9aKHBJjHzuSGwyQznBkNIJmFEcCjUq9Pq7+gAcQ1A0VYE1R5sF27RNq1E1mzpvrbUBOoK4HvvSfcDt5LplIvekiAeexMbjhMMsOZ0QCSWRgBPCr1+rT6CxpAXDNQhDVBlQdbskSkWzf/LTz3nMjpp/v7lWKP1Iu+pnJGbjh5MsOZ0QCSWRgBPCr1+rT6CxpAXDNQhDVBlQebPl1kwAD/LUybJtK/v79fKfZIvehrKmfkhpMnM5wZDSCZhRHAo1KvT6u/oAHENQNFWBPEFUAId6bOqRd9pklG6ERuOFQyw5nRAJJZGAE8KvX6tPoLGkBcM1CENUGVB8s9A6infysfAtG+fAbQn57Ui94/wzg9yA3nSmY4MxpAMgsjgEelXp9Wf0EDiGsGirAmqLrBcqeAta28CeQp4GypSb3os80y/73IDWdKZjgzGkAyCyOAR6Ven1Z/QQOIawaKsCZob4NV9x7Atm1FJk7kK2B8CUq96H3zi9VObjhZMsOZ0QCSWRgBPCr1+rT6CxpAXDNQhDVB+xqM3wQCpaKsc+pFHzZrexS54QzJDGdGA0hmYQTwqNTr0+ovaABxzUAR1gTta7BPPxVp1GhPj82b/yFNm9aF7q1UO6de9DWVN3LDyZMZzowGkMzCCOBRqden1V/QAOKagSKsCaIBhHBn6px60WeaZIRO5IZDJTOcGQ0gmYURwKNSr0+rv6ABxDUDRVgTRAMI4c7UOfWizzTJCJ3IDYdKZjgzGkAyCyOAR6Ven1Z/QQOIawaKsCaIBhDCnalz6kWfaZIROpEbDpXMcGY0gGQWRgCPSr0+rf6CBhDXDBRhTRANIIQ7U+fUiz7TJCN0IjccKpnhzGgAySyMAB6Ven1a/QUNIK4ZKMKaIBpACHemzqkXfaZJRuhEbjhUMsOZ0QCSWRgBPCr1+rT6CxpAXDNQhDVBNIAQ7kydUy/6TJOM0InccKhkhjOjASSzMAJ4VOr1afUXNIC4ZqAIa4JoACHcmTqnXvSZJhmhE7nhUMkMZ0YDSGZhBPCo1OvT6i9oAHHNQBHWBNEAQrgzdU696DNNMkIncsOhkhnOjAaQzMII4FGp16fVX9AA4pqBIqwJogGEcGfqnHrRZ5pkhE7khkMlM5wZDSCZhRHAo1KvT6u/oAHENQNFWBNEAwjhztQ59aLPNMkIncgNh0pmODMaQDILI4BHpV6fVn9BA4hrBoqwJogGEMKdqXPqRZ9pkhE6kRsOlcxwh0eOrgAAF8FJREFUZjSAZBZGAI9KvT6t/oIGENcMFGFNEA0ghDtT59SLPtMkI3QiNxwqmeHMaADJLIwAHpV6fVr9BQ0grhkowpogGkAId6bOqRd9pklG6ERuOFQyw5nRAJJZGAE8KvX6tPoLGkBcM1CENUE0gBDuTJ1TL/pMk4zQidxwqGSGM6MBJLMwAnhU6vVp9Rc0gLhmoAhrgmgAIdyZOqde9JkmGaETueFQyQxnRgNIZmEE8KjU69PqL2gAcc1AEdYE0QBCuDN1Tr3oM00yQidyw6GSGc6MBpDMwgjgUanXp9Vf0ADimoEirAnyDZa6gH3zi9FOZmFUyQ3nRmY4MxpAMgsjgEelXp9Wf0EDiGsGirAmyDdY6gL2zS9GO5mFUSU3nBuZ4cxoAMksjAAelXp9Wv0FDSCuGSjCmiDfYKkL2De/GO1kFkaV3HBuZIYzowEkszACeFTq9Wn1FzSAuGagCGuCfIOlLmDf/GK0k1kYVXLDuZEZzowGkMzCCOBRqden1V/QAOKagSKsCfINlrqAffOL0U5mYVTJDedGZjgzGkAyCyOAR6Ven1Z/QQOIawaKsCbIN1jqAvbNL0Y7mYVRJTecG5nhzGgAySyMAB6Ven1a/QUNIK4ZKMKaIN9gqQvYN78Y7WQWRpXccG5khjOjASSzMAJ4VOr1afUXNIC4ZqAIa4J8g6UuYN/8YrSTWRhVcsO5kRnOjAaQzMII4FGp16fVX9AA4pqBIqwJ8g2WuoB984vRTmZhVMkN50ZmODMaQDILI4BHpV6fVn9BA4hrBoqwJsg3WOoC9s0vRjuZhVElN5wbmeHMaADJLIwAHpV6fVr9BQ0grhkowpog32CpC9g3vxjtZBZGldxwbmSGM6MBJLMwAnhU6vVp9Rc0gLhmoAhrgnyDpS5g3/xitJNZGFVyw7mRGc6MBpDMwgjgUanXp9Vf0ADimoEirAnyDZa6gH3zi9FOZmFUyQ3nRmY4MxpAMgsjgEelXp9Wf0EDiGsGirAmyDdY6gL2zS9GO5mFUSU3nBuZ4cxoAMksjAAelXp9Wv0FDSCuGSjCmiDfYKkL2De/GO1kFkaV3HBuZIYzowEkszACeFTq9Wn1FzSAuGagCGuCfIOlLmDf/GK0k1kYVXLDuZEZzowGkMzCCOBRqden1V/QAOKagSKsCfINlrqAffOL0U5mYVTJDedGZjgzGkAyCyOAR6Ven1Z/QQOIawaKsCbIN1jqAvbNL0Y7mYVRJTecG5nhzGgAySyMAB6Ven1a/QUNIK4ZKGLr1q3StGlTWb16tTRp0gSKzdJZBbxw4ULp3r271K1bN0tIyfchszAJkBvOjcxwZjkDyJ9rGDtqDeNVDDpTA9i2bVvZsmWLHHzwwTAAGkAYGRawZs0alyBeJEACJEACJEACJJBvArrA1KZNG/hjaQBhZFjAl19+KWvXrpXGjRtLrVq1sOAMvXP/Aoi1wpjhFpLrQmZhKSM3nBuZ4cw0gtxwbmRWesx2794tn3zyibRu3Vpq164NA6ABhJEVVoD1GYDCms3+uRsyC+NMbjg3MsOZ5QygbmnpIzQxHp0Ju6vCjqLW8PyUOjMaQFwzBRVR6gIOSQaZhVDbsyrDX8oYOzLDeOV6kxvOjczIDCVAA4gSK7D+LHo8IWSGM+OqDJmFEQiLYo3i3MiMzFACNIAosQLrv3PnTrnttttk1KhRUr9+/QK7u8K8HTILywu54dzIDGemEeSGcyMzMkMJ0ACixNifBEiABEiABEiABBInQAOYeAJ5+yRAAiRAAiRAAiSAEqABRImxPwmQAAmQAAmQAAkkToAGMPEE8vZJgARIgARIgARIACVAA4gSy2P/F154QcaOHSuvvfaarFu3Tp566inp1atX2Qj6kscxY8bIgw8+KJs3b5YuXbrIvffeK8cee2xZH33wd8SIETJ9+nT57LPP5IwzzpD77rtvn28FHz16tPvc8tdhhx0mf//73/M4uzgflQ9mynPatGny+uuvu5doKlv9uj7fpVw1X5orzcHEiRPl29/+ti+sxttrilnKOtOkWblt2rRJfvazn7mvatQXtTdv3tzV90033eT92qZS1Voos1LXmur10ksvlWeffdZ98UCjRo3klFNOkTvuuEO+/vWv7/NnUKlqLZRZ6lorLwYawBr89Tx//nz53e9+J//2b/8m5513XhUDqMV7yy23yOTJk+WYY46Rm2++2f1SWr58uftmEb2GDBkic+bMcX0OPfRQGT58uOgPUTWVderUqXZ2KuAnnnjC/bDIXdq3RYsWNUgj29D5YKbGbceOHW5APT2dxQDOnDlT/uM//sOZ61NPPVUmTZokv/jFL+Svf/2rHHHEEdluvoZ61RSzlHWmqbJy+8tf/uIM4IUXXiidOnWSlStXyk9+8hP55je/6epvb1cpay2UWalrTbWk/7BVs6c/j/R3gDJ588035b333tvr74JS1loos9S1RgNYQ7+I9zWsfk1c+RVAXf3Tr3cZNmyYXHPNNS5UV/t0pU6Nof5rT9+Sr6btsccek759+7o++q8//e7hefPmyVlnnbVXA/j000+7Hw4pXyHMys93yZIl0q1bt0wGUFdf1ajff//9ZR/xjW98w63o6Gt4Urn2JzP9QVkMOtPcWrnl9PGrX/1KfvSjH8mnn34qBxxwQLWyodYqYsnCjFqrKqU//elP0rlzZ/nb3/4m7du3p9Yq/f6sDkgWZkWltd3qNHjVOIHKv2DeffddV7S6TXnCCSeU3d+5557rtiunTJkiixcvdlu++q+9Zs2alfXRoldjUnmbN9dBBaxbmfqtDvruQP2Fc+utt8rRRx9d4xyQGwhhFmIAP//8c2nYsKHoL6Lvf//7ZR9xxRVXOBP9/PPPI7ddo333FzOdZLHorDoDmKU+q0u0rhrrqvNHH31UrQ6otapYfMyotSlVoOk/MK6//nqZNWuWLFu2TOrVq1elD7VWEUkWZkWnNRrAGv19XDZ45V/ML730kttq/OCDD9xKYO4aPHiw20pasGCBe45t0KBBbmWw/NW9e3c56qij3DZldZdubW3fvt1tK3/44Ydua1l/SPzf//2f20ZO5QphFmIAdVX18MMPd9v1+lxN7lLTrEZct+RTufYXM+VRLDqrzgBmqc/Kmti4caNbRdZHCbTmqruotYpUsjCj1haUQdNHVK6++mq3wqzbwXPnzt3r6h+1tgcbwqzotEYDWBi/uvf2i1mLtFWrVmU3eckll7gHyp955pm9GsAzzzzTFf0DDzyQaXL6w0L76w+Oq666KlNMIXQKYWYxgPpLv2vXrmUfoc9n6va7mudUrv3FrDoeqepsXwZwX/VZnoF+TZf+w0xX6mfPni1169bdpwGk1vZ893QWZtTaM2UI9LGg9evXu4Nq48aNcwsI+g/XAw88sAqmnAEsda0hzIpOazSAhfGrO2RrLnQLuLoZq2n82te+VuEZt8Igs/e7CGEWYgC5VfIVNeS5yWLRWXUGENkC1pPm+jyuPkagKzLV/TLOsaLW9pBAmO3tJ0SKP9OsWivPQrWk/+DQLfT+/ftXwUStVVWOj1nRaY0GsDBszt4eMr/yyivdypxeKs6WLVtWOQQydepU6dOnj+uj//Jr06bNPg+BVJ6xbiHrCqBuL994442FASTDXYQwCzGAGqPPSZ544oluuyB36clOfSazGA6B7EtnocyKRWfV/VLOHdLycdNVLDV/+qytHsxSE+i7Sl1rIcyoterNjD4vrj+z9CR6dVepa60yE/0d62NWVFqjAfT9OI7Xvm3bNndCSy896HHnnXe6U6mHHHKIO8qvp33VXDzyyCPSoUMHd1BDV2AqvwZGVxX0NTAap+8E1Odmyr8GRg+K6OGFn/70p24s7fO9733PjaHbBfo8kh5k+POf/yxHHnlkvAnn4ZPzwUzfd6j/++Mf/yi6pa6v1tHX6igPZahXZWa51yXotrpuA+srF/73f//XPTdJZtUzS1lnqgGr1nQVS1eh9HlbPeF/0EEHlVWAnt7PvaaJWvvqZ1oos1LXmq5I688o3TJXbenWr/7+ePHFF2Xp0qVu4YA/1yr+/gxllrrWyv8a5nsA82BKQj8it51WOX7gwIHO0OVeBK2HOcq/CPq4444rC9H32Y0cOdI9D1j+RdD6Kpjc1a5dO/cvQD2VqVe/fv2c6dmwYYP7YXHyySe7l9PqilahX/lgVt2LPHXearRz/1KuzEzb9V/SP//5z90qq+ZgwoQJ8p3vfKfQkbl/NOg/LCw6C2GWss6UlZXb3uL1s/XdbKoxvai1e1097Yu5j1mpa02f57v44ovdP/z1d4W+Lkx/NumOTseOHff6u6CUf66FMktdazSABf8rmzdIAiRAAiRAAiRAAvEIcAUwHlt+MgmQAAmQAAmQAAkUJAEawIJMC2+KBEiABEiABEiABOIRoAGMx5afTAIkQAIkQAIkQAIFSYAGsCDTwpsiARIgARIgARIggXgEaADjseUnkwAJkAAJkAAJkEBBEqABLMi08KZIgARIgARIgARIIB4BGsB4bPnJJEACJEACJEACJFCQBGgACzItvCkSIAESIAESIAESiEeABjAeW34yCZDAfiag3+SyZcsWefrpp/fzyMU7nH615De+8Q159dVXy769pCZme88998jChQtl9uzZNTE8xySBoiNAA1h0KeWESKBwCahBmzJlirvBAw44QPQrC3v37i1jxoyp8F25oTOwGED9KsXWrVtLrVq13HepNmjQoMpt6L3fe++97juga9eu7b7D++qrr5aePXuW9c19BZx+qbx+beCBBx5Y1qYmqkuXLu7P+lWPe7v06+FWrlxZofnwww+XNWvWhKIJjtPvPtWvF3vooYfcZ7z//vty1FFHue8y1nvU+8pdOl/N6a5du8q+7i7X/4033pDjjz++wn2cfvrp7u8mTpzovb+dO3c6A/qrX/1K/t//+3/e/uxAAiSwbwI0gFQICZDAfiOgBu3DDz9037v8j3/8w31ZvX6HqX7/9f3332++D4sBnDp1quj3bqsxGzJkiJx//vkV7keNkK5C3XzzzdKrVy93/xpz++23y1133SU//elPXf+cAVQjdMcdd0j//v3LPucnP/mJzJ8/X1atWuU1gBdddJFccsklZbFquPS7uytfeh9169Y1s6vuA3KmeN68edK1a9cKBlDnp5xGjRpVFqosNI86v9z3HefLAOogw4cPdyZ45syZUebLDyWBUiJAA1hK2eZcSaCGCVRn0NTkzJ07162WVdc+bNgwefPNN52x0uuJJ55wK4Z/+9vfpGHDhm4VbtasWW4FMRevK0Tjx4+Xzz//XPTL23WFyWeSunXr5vqqAfzlL38pixcvLqP18ssvOwP0P//zP/Kf//mfFSiqKbn77rvlnXfecatfOQN4/fXXi8YtWrTI9Vcz1apVKxk6dKjcdNNNXgOo89b/Vb50hVJNlhrJZ599VtSYKo85c+bI6NGj3eqkrmSqqf6v//ovt9Kq19tvvy1qKnUV8uijj3amtXv37vLUU085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\" width=\"640\">"
],
"text/plain": [
"<IPython.core.display.HTML object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"shotNum = \"0001\"\n",
"filePath = folderPath + \"/\" + shotNum + \"/*.h5\"\n",
"\n",
"dataSetDict = {\n",
" dskey[groupList[i]]: read_hdf5_file(filePath, groupList[i])\n",
" for i in range(len(groupList))\n",
"}\n",
"\n",
"dataSet = dataSetDict[\"camera_1\"]\n",
"\n",
"print_scanAxis(dataSet)\n",
"\n",
"scanAxis = get_scanAxis(dataSet)\n",
"\n",
"auto_rechunk(dataSet)\n",
"\n",
"dataSet = imageAnalyser.get_absorption_images(dataSet)\n",
"\n",
"imageAnalyser.center = (310, 825)\n",
"imageAnalyser.span = (550, 1200)\n",
"imageAnalyser.fraction = (0.1, 0.1)\n",
"\n",
"dataSet_cropOD = imageAnalyser.crop_image(dataSet.OD)\n",
"dataSet_cropOD = imageAnalyser.substract_offset(dataSet_cropOD).load()\n",
"\n",
"Ncount = imageAnalyser.get_Ncount(dataSet_cropOD)\n",
"Ncount_mean = Ncount.mean(dim='runs')\n",
"Ncount_std = Ncount.std(dim='runs')\n",
"\n",
"fig = plt.figure()\n",
"ax = fig.gca()\n",
"Ncount_mean.plot.errorbar(ax=ax, yerr = Ncount_std, fmt='ob')\n",
"plt.xlabel('Push AOM Freq (MHz)')\n",
"plt.ylabel('NCount')\n",
"plt.tight_layout()\n",
"plt.grid(visible=1)\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## scan cMOT final Amp"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"shotNum = \"0002\"\n",
"filePath = folderPath + \"/\" + shotNum + \"/*.h5\"\n",
"\n",
"dataSetDict = {\n",
" dskey[groupList[i]]: read_hdf5_file(filePath, groupList[i])\n",
" for i in range(len(groupList))\n",
"}\n",
"\n",
"dataSet = dataSetDict[\"camera_1\"]\n",
"\n",
"print_scanAxis(dataSet)\n",
"\n",
"scanAxis = get_scanAxis(dataSet)\n",
"\n",
"auto_rechunk(dataSet)\n",
"\n",
"dataSet = imageAnalyser.get_absorption_images(dataSet)\n",
"\n",
"imageAnalyser.center = (306, 874)\n",
"imageAnalyser.span = (550, 500)\n",
"imageAnalyser.fraction = (0.1, 0.1)\n",
"\n",
"dataSet_cropOD = imageAnalyser.crop_image(dataSet.OD)\n",
"dataSet_cropOD = imageAnalyser.substract_offset(dataSet_cropOD).load()\n",
"\n",
"Ncount = imageAnalyser.get_Ncount(dataSet_cropOD)\n",
"Ncount_mean = Ncount.mean(dim='runs')\n",
"Ncount_std = Ncount.std(dim='runs')\n",
"\n",
"fig = plt.figure()\n",
"ax = fig.gca()\n",
"Ncount_mean.plot.errorbar(ax=ax, yerr = Ncount_std, fmt='ob')\n",
"plt.xlabel('cMOT final Amp (%)')\n",
"plt.ylabel('NCount')\n",
"plt.tight_layout()\n",
"plt.grid(visible=1)\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## scan Z comp current"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"shotNum = \"0003\"\n",
"filePath = folderPath + \"/\" + shotNum + \"/*.h5\"\n",
"\n",
"dataSetDict = {\n",
" dskey[groupList[i]]: read_hdf5_file(filePath, groupList[i])\n",
" for i in range(len(groupList))\n",
"}\n",
"\n",
"dataSet = dataSetDict[\"camera_1\"]\n",
"\n",
"print_scanAxis(dataSet)\n",
"\n",
"scanAxis = get_scanAxis(dataSet)\n",
"\n",
"auto_rechunk(dataSet)\n",
"\n",
"dataSet = imageAnalyser.get_absorption_images(dataSet)\n",
"\n",
"imageAnalyser.center = (310, 825)\n",
"imageAnalyser.span = (550, 1200)\n",
"imageAnalyser.fraction = (0.1, 0.1)\n",
"\n",
"dataSet_cropOD = imageAnalyser.crop_image(dataSet.OD)\n",
"dataSet_cropOD = imageAnalyser.substract_offset(dataSet_cropOD).load()\n",
"\n",
"Ncount = imageAnalyser.get_Ncount(dataSet_cropOD)\n",
"Ncount_mean = Ncount.mean(dim='runs')\n",
"Ncount_std = Ncount.std(dim='runs')\n",
"\n",
"fig = plt.figure()\n",
"ax = fig.gca()\n",
"Ncount_mean.plot.errorbar(ax=ax, yerr = Ncount_std, fmt='ob')\n",
"plt.xlabel('MOT AOM Freq (MHz)')\n",
"plt.ylabel('NCount')\n",
"plt.tight_layout()\n",
"plt.grid(visible=1)\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Evaporative Cooling"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"img_dir = 'C:/Users/control/DyLab/Experiments/DyBEC/'\n",
"SequenceName = \"Evaporative_Cooling\" + \"/\"\n",
"folderPath = img_dir + SequenceName + get_date()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"l = list(np.arange(120, 151, 1))\n",
"# l = np.logspace(np.log10(100e-3), np.log10(20), num=20)\n",
"\n",
"l = [round(item, 7) for item in l]\n",
"#random.shuffle(l)\n",
"\n",
"print(l)\n",
"print(len(l))\n",
"np.mean(l)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## ODT 1 Calibration"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"v_high = 2.7\n",
"\"\"\"High Power\"\"\"\n",
"P_arm1_high = 5.776 * v_high - 0.683\n",
"\n",
"v_mid = 0.2076\n",
"\"\"\"Intermediate Power\"\"\"\n",
"P_arm1_mid = 5.815 * v_mid - 0.03651\n",
"\n",
"v_low = 0.0587\n",
"\"\"\"Low Power\"\"\"\n",
"P_arm1_low = 5271 * v_low - 27.5\n",
"\n",
"print(round(P_arm1_high, 3))\n",
"print(round(P_arm1_mid, 3))\n",
"print(round(P_arm1_low, 3))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## ODT 2 Power Calibration"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"v = 0.7607\n",
"P_arm2 = 2.302 * v - 0.06452\n",
"print(round(P_arm2, 3))"
]
}
],
"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.9.12"
},
"vscode": {
"interpreter": {
"hash": "c05913ad4f24fdc6b2418069394dc5835b1981849b107c9ba6df693aafd66650"
}
}
},
"nbformat": 4,
"nbformat_minor": 2
}