/ Jupyter_USB / MLX90640 Thermal Camera.ipynb
MLX90640 Thermal Camera.ipynb
1 { 2 "cells": [ 3 { 4 "cell_type": "markdown", 5 "metadata": {}, 6 "source": [ 7 "# MLX90640 Thermal Camera with CircuitPython\n", 8 "[Click here to visit the guide for this notebook!](https://learn.adafruit.com/jupyter-on-any-computer-with-circuitpython-and-mcp2221-ft232h/thermal-camera)" 9 ] 10 }, 11 { 12 "cell_type": "code", 13 "execution_count": 48, 14 "metadata": {}, 15 "outputs": [ 16 { 17 "name": "stdout", 18 "output_type": "stream", 19 "text": [ 20 "Requirement already satisfied: adafruit-circuitpython-mlx90640 in /opt/anaconda3/lib/python3.7/site-packages (1.0.1)\n", 21 "Requirement already satisfied: hidapi in /opt/anaconda3/lib/python3.7/site-packages (0.7.99.post21)\n", 22 "Requirement already satisfied: adafruit-circuitpython-register in /opt/anaconda3/lib/python3.7/site-packages (from adafruit-circuitpython-mlx90640) (1.7.1)\n", 23 "Requirement already satisfied: Adafruit-Blinka in /opt/anaconda3/lib/python3.7/site-packages (from adafruit-circuitpython-mlx90640) (3.2.0)\n", 24 "Requirement already satisfied: adafruit-circuitpython-busdevice in /opt/anaconda3/lib/python3.7/site-packages (from adafruit-circuitpython-mlx90640) (4.0.1)\n", 25 "Requirement already satisfied: setuptools>=19.0 in /opt/anaconda3/lib/python3.7/site-packages (from hidapi) (41.4.0)\n", 26 "Requirement already satisfied: sysv-ipc; platform_system != \"Windows\" in /opt/anaconda3/lib/python3.7/site-packages (from Adafruit-Blinka->adafruit-circuitpython-mlx90640) (1.0.1)\n", 27 "Requirement already satisfied: Adafruit-PlatformDetect in /opt/anaconda3/lib/python3.7/site-packages (from Adafruit-Blinka->adafruit-circuitpython-mlx90640) (1.3.8)\n", 28 "Requirement already satisfied: Adafruit-PureIO in /opt/anaconda3/lib/python3.7/site-packages (from Adafruit-Blinka->adafruit-circuitpython-mlx90640) (1.0.4)\n" 29 ] 30 } 31 ], 32 "source": [ 33 "# Set an Environment Variable so Adafruit Blinka knows we're using the MCP2221\n", 34 "import os\n", 35 "os.environ[\"BLINKA_MCP2221\"] = \"1\"\n", 36 "\n", 37 " # Python Software Package Installation\n", 38 "import sys\n", 39 "!{sys.executable} -m pip install adafruit-circuitpython-mlx90640 hidapi" 40 ] 41 }, 42 { 43 "cell_type": "code", 44 "execution_count": 49, 45 "metadata": {}, 46 "outputs": [ 47 { 48 "name": "stdout", 49 "output_type": "stream", 50 "text": [ 51 "Found 0 broken pixels, 0 outliers\n", 52 "MLX addr detected on I2C!\n", 53 "MLX refresh rate: 1 Hz\n" 54 ] 55 } 56 ], 57 "source": [ 58 "import time\n", 59 "import board\n", 60 "import busio\n", 61 "import adafruit_mlx90640\n", 62 "\n", 63 "i2c = busio.I2C(board.SCL, board.SDA, frequency=800000)\n", 64 "\n", 65 "mlx = adafruit_mlx90640.MLX90640(i2c)\n", 66 "print(\"MLX addr detected on I2C!\")\n", 67 "\n", 68 "# Set refresh rate\n", 69 "mlx.refresh_rate = adafruit_mlx90640.RefreshRate.REFRESH_1_HZ\n", 70 "print(\"MLX refresh rate: \", pow(2, (mlx.refresh_rate-1)), \"Hz\")" 71 ] 72 }, 73 { 74 "cell_type": "code", 75 "execution_count": 53, 76 "metadata": {}, 77 "outputs": [ 78 { 79 "name": "stdout", 80 "output_type": "stream", 81 "text": [ 82 "24 x 32\n" 83 ] 84 } 85 ], 86 "source": [ 87 "import numpy as np\n", 88 "\n", 89 "# read in frame from thermal camera and split into 32 x 24 numpy array of thermal readings\n", 90 "frame = [0] * 768\n", 91 "mlx.getFrame(frame)\n", 92 "pixels = np.split(np.asarray(frame), 24)\n", 93 "# rotate it around so its right side\n", 94 "pixels = np.rot90(pixels, 3)\n", 95 "print(len(pixels[0]), \"x\", len(pixels))" 96 ] 97 }, 98 { 99 "cell_type": "code", 100 "execution_count": 54, 101 "metadata": {}, 102 "outputs": [ 103 { 104 "data": { 105 "application/javascript": [ 106 "/* Put everything inside the global mpl namespace */\n", 107 "window.mpl = {};\n", 108 "\n", 109 "\n", 110 "mpl.get_websocket_type = function() {\n", 111 " if (typeof(WebSocket) !== 'undefined') {\n", 112 " return WebSocket;\n", 113 " } else if (typeof(MozWebSocket) !== 'undefined') {\n", 114 " return MozWebSocket;\n", 115 " } else {\n", 116 " alert('Your browser does not have WebSocket support. ' +\n", 117 " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", 118 " 'Firefox 4 and 5 are also supported but you ' +\n", 119 " 'have to enable WebSockets in about:config.');\n", 120 " };\n", 121 "}\n", 122 "\n", 123 "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", 124 " this.id = figure_id;\n", 125 "\n", 126 " this.ws = websocket;\n", 127 "\n", 128 " this.supports_binary = (this.ws.binaryType != undefined);\n", 129 "\n", 130 " if (!this.supports_binary) {\n", 131 " var warnings = document.getElementById(\"mpl-warnings\");\n", 132 " if (warnings) {\n", 133 " warnings.style.display = 'block';\n", 134 " warnings.textContent = (\n", 135 " \"This browser does not support binary websocket messages. \" +\n", 136 " \"Performance may be slow.\");\n", 137 " }\n", 138 " }\n", 139 "\n", 140 " this.imageObj = new Image();\n", 141 "\n", 142 " this.context = undefined;\n", 143 " this.message = undefined;\n", 144 " this.canvas = undefined;\n", 145 " this.rubberband_canvas = undefined;\n", 146 " this.rubberband_context = undefined;\n", 147 " this.format_dropdown = undefined;\n", 148 "\n", 149 " this.image_mode = 'full';\n", 150 "\n", 151 " this.root = $('<div/>');\n", 152 " this._root_extra_style(this.root)\n", 153 " this.root.attr('style', 'display: inline-block');\n", 154 "\n", 155 " $(parent_element).append(this.root);\n", 156 "\n", 157 " this._init_header(this);\n", 158 " this._init_canvas(this);\n", 159 " this._init_toolbar(this);\n", 160 "\n", 161 " var fig = this;\n", 162 "\n", 163 " this.waiting = false;\n", 164 "\n", 165 " this.ws.onopen = function () {\n", 166 " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", 167 " fig.send_message(\"send_image_mode\", {});\n", 168 " if (mpl.ratio != 1) {\n", 169 " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", 170 " }\n", 171 " fig.send_message(\"refresh\", {});\n", 172 " }\n", 173 "\n", 174 " this.imageObj.onload = function() {\n", 175 " if (fig.image_mode == 'full') {\n", 176 " // Full images could contain transparency (where diff images\n", 177 " // almost always do), so we need to clear the canvas so that\n", 178 " // there is no ghosting.\n", 179 " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", 180 " }\n", 181 " fig.context.drawImage(fig.imageObj, 0, 0);\n", 182 " };\n", 183 "\n", 184 " this.imageObj.onunload = function() {\n", 185 " fig.ws.close();\n", 186 " }\n", 187 "\n", 188 " this.ws.onmessage = this._make_on_message_function(this);\n", 189 "\n", 190 " this.ondownload = ondownload;\n", 191 "}\n", 192 "\n", 193 "mpl.figure.prototype._init_header = function() {\n", 194 " var titlebar = $(\n", 195 " '<div class=\"ui-dialog-titlebar ui-widget-header ui-corner-all ' +\n", 196 " 'ui-helper-clearfix\"/>');\n", 197 " var titletext = $(\n", 198 " '<div class=\"ui-dialog-title\" style=\"width: 100%; ' +\n", 199 " 'text-align: center; padding: 3px;\"/>');\n", 200 " titlebar.append(titletext)\n", 201 " this.root.append(titlebar);\n", 202 " this.header = titletext[0];\n", 203 "}\n", 204 "\n", 205 "\n", 206 "\n", 207 "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", 208 "\n", 209 "}\n", 210 "\n", 211 "\n", 212 "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", 213 "\n", 214 "}\n", 215 "\n", 216 "mpl.figure.prototype._init_canvas = function() {\n", 217 " var fig = this;\n", 218 "\n", 219 " var canvas_div = $('<div/>');\n", 220 "\n", 221 " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", 222 "\n", 223 " function canvas_keyboard_event(event) {\n", 224 " return fig.key_event(event, event['data']);\n", 225 " }\n", 226 "\n", 227 " canvas_div.keydown('key_press', canvas_keyboard_event);\n", 228 " canvas_div.keyup('key_release', canvas_keyboard_event);\n", 229 " this.canvas_div = canvas_div\n", 230 " this._canvas_extra_style(canvas_div)\n", 231 " this.root.append(canvas_div);\n", 232 "\n", 233 " var canvas = $('<canvas/>');\n", 234 " canvas.addClass('mpl-canvas');\n", 235 " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", 236 "\n", 237 " this.canvas = canvas[0];\n", 238 " this.context = canvas[0].getContext(\"2d\");\n", 239 "\n", 240 " var backingStore = this.context.backingStorePixelRatio ||\n", 241 "\tthis.context.webkitBackingStorePixelRatio ||\n", 242 "\tthis.context.mozBackingStorePixelRatio ||\n", 243 "\tthis.context.msBackingStorePixelRatio ||\n", 244 "\tthis.context.oBackingStorePixelRatio ||\n", 245 "\tthis.context.backingStorePixelRatio || 1;\n", 246 "\n", 247 " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", 248 "\n", 249 " var rubberband = $('<canvas/>');\n", 250 " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", 251 "\n", 252 " var pass_mouse_events = true;\n", 253 "\n", 254 " canvas_div.resizable({\n", 255 " start: function(event, ui) {\n", 256 " pass_mouse_events = false;\n", 257 " },\n", 258 " resize: function(event, ui) {\n", 259 " fig.request_resize(ui.size.width, ui.size.height);\n", 260 " },\n", 261 " stop: function(event, ui) {\n", 262 " pass_mouse_events = true;\n", 263 " fig.request_resize(ui.size.width, ui.size.height);\n", 264 " },\n", 265 " });\n", 266 "\n", 267 " function mouse_event_fn(event) {\n", 268 " if (pass_mouse_events)\n", 269 " return fig.mouse_event(event, event['data']);\n", 270 " }\n", 271 "\n", 272 " rubberband.mousedown('button_press', mouse_event_fn);\n", 273 " rubberband.mouseup('button_release', mouse_event_fn);\n", 274 " // Throttle sequential mouse events to 1 every 20ms.\n", 275 " rubberband.mousemove('motion_notify', mouse_event_fn);\n", 276 "\n", 277 " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", 278 " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", 279 "\n", 280 " canvas_div.on(\"wheel\", function (event) {\n", 281 " event = event.originalEvent;\n", 282 " event['data'] = 'scroll'\n", 283 " if (event.deltaY < 0) {\n", 284 " event.step = 1;\n", 285 " } else {\n", 286 " event.step = -1;\n", 287 " }\n", 288 " mouse_event_fn(event);\n", 289 " });\n", 290 "\n", 291 " canvas_div.append(canvas);\n", 292 " canvas_div.append(rubberband);\n", 293 "\n", 294 " this.rubberband = rubberband;\n", 295 " this.rubberband_canvas = rubberband[0];\n", 296 " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", 297 " this.rubberband_context.strokeStyle = \"#000000\";\n", 298 "\n", 299 " this._resize_canvas = function(width, height) {\n", 300 " // Keep the size of the canvas, canvas container, and rubber band\n", 301 " // canvas in synch.\n", 302 " canvas_div.css('width', width)\n", 303 " canvas_div.css('height', height)\n", 304 "\n", 305 " canvas.attr('width', width * mpl.ratio);\n", 306 " canvas.attr('height', height * mpl.ratio);\n", 307 " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n", 308 "\n", 309 " rubberband.attr('width', width);\n", 310 " rubberband.attr('height', height);\n", 311 " }\n", 312 "\n", 313 " // Set the figure to an initial 600x600px, this will subsequently be updated\n", 314 " // upon first draw.\n", 315 " this._resize_canvas(600, 600);\n", 316 "\n", 317 " // Disable right mouse context menu.\n", 318 " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", 319 " return false;\n", 320 " });\n", 321 "\n", 322 " function set_focus () {\n", 323 " canvas.focus();\n", 324 " canvas_div.focus();\n", 325 " }\n", 326 "\n", 327 " window.setTimeout(set_focus, 100);\n", 328 "}\n", 329 "\n", 330 "mpl.figure.prototype._init_toolbar = function() {\n", 331 " var fig = this;\n", 332 "\n", 333 " var nav_element = $('<div/>');\n", 334 " nav_element.attr('style', 'width: 100%');\n", 335 " this.root.append(nav_element);\n", 336 "\n", 337 " // Define a callback function for later on.\n", 338 " function toolbar_event(event) {\n", 339 " return fig.toolbar_button_onclick(event['data']);\n", 340 " }\n", 341 " function toolbar_mouse_event(event) {\n", 342 " return fig.toolbar_button_onmouseover(event['data']);\n", 343 " }\n", 344 "\n", 345 " for(var toolbar_ind in mpl.toolbar_items) {\n", 346 " var name = mpl.toolbar_items[toolbar_ind][0];\n", 347 " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", 348 " var image = mpl.toolbar_items[toolbar_ind][2];\n", 349 " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", 350 "\n", 351 " if (!name) {\n", 352 " // put a spacer in here.\n", 353 " continue;\n", 354 " }\n", 355 " var button = $('<button/>');\n", 356 " button.addClass('ui-button ui-widget ui-state-default ui-corner-all ' +\n", 357 " 'ui-button-icon-only');\n", 358 " button.attr('role', 'button');\n", 359 " button.attr('aria-disabled', 'false');\n", 360 " button.click(method_name, toolbar_event);\n", 361 " button.mouseover(tooltip, toolbar_mouse_event);\n", 362 "\n", 363 " var icon_img = $('<span/>');\n", 364 " icon_img.addClass('ui-button-icon-primary ui-icon');\n", 365 " icon_img.addClass(image);\n", 366 " icon_img.addClass('ui-corner-all');\n", 367 "\n", 368 " var tooltip_span = $('<span/>');\n", 369 " tooltip_span.addClass('ui-button-text');\n", 370 " tooltip_span.html(tooltip);\n", 371 "\n", 372 " button.append(icon_img);\n", 373 " button.append(tooltip_span);\n", 374 "\n", 375 " nav_element.append(button);\n", 376 " }\n", 377 "\n", 378 " var fmt_picker_span = $('<span/>');\n", 379 "\n", 380 " var fmt_picker = $('<select/>');\n", 381 " fmt_picker.addClass('mpl-toolbar-option ui-widget ui-widget-content');\n", 382 " fmt_picker_span.append(fmt_picker);\n", 383 " nav_element.append(fmt_picker_span);\n", 384 " this.format_dropdown = fmt_picker[0];\n", 385 "\n", 386 " for (var ind in mpl.extensions) {\n", 387 " var fmt = mpl.extensions[ind];\n", 388 " var option = $(\n", 389 " '<option/>', {selected: fmt === mpl.default_extension}).html(fmt);\n", 390 " fmt_picker.append(option);\n", 391 " }\n", 392 "\n", 393 " // Add hover states to the ui-buttons\n", 394 " $( \".ui-button\" ).hover(\n", 395 " function() { $(this).addClass(\"ui-state-hover\");},\n", 396 " function() { $(this).removeClass(\"ui-state-hover\");}\n", 397 " );\n", 398 "\n", 399 " var status_bar = $('<span class=\"mpl-message\"/>');\n", 400 " nav_element.append(status_bar);\n", 401 " this.message = status_bar[0];\n", 402 "}\n", 403 "\n", 404 "mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n", 405 " // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n", 406 " // which will in turn request a refresh of the image.\n", 407 " this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n", 408 "}\n", 409 "\n", 410 "mpl.figure.prototype.send_message = function(type, properties) {\n", 411 " properties['type'] = type;\n", 412 " properties['figure_id'] = this.id;\n", 413 " this.ws.send(JSON.stringify(properties));\n", 414 "}\n", 415 "\n", 416 "mpl.figure.prototype.send_draw_message = function() {\n", 417 " if (!this.waiting) {\n", 418 " this.waiting = true;\n", 419 " this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n", 420 " }\n", 421 "}\n", 422 "\n", 423 "\n", 424 "mpl.figure.prototype.handle_save = function(fig, msg) {\n", 425 " var format_dropdown = fig.format_dropdown;\n", 426 " var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n", 427 " fig.ondownload(fig, format);\n", 428 "}\n", 429 "\n", 430 "\n", 431 "mpl.figure.prototype.handle_resize = function(fig, msg) {\n", 432 " var size = msg['size'];\n", 433 " if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n", 434 " fig._resize_canvas(size[0], size[1]);\n", 435 " fig.send_message(\"refresh\", {});\n", 436 " };\n", 437 "}\n", 438 "\n", 439 "mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n", 440 " var x0 = msg['x0'] / mpl.ratio;\n", 441 " var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n", 442 " var x1 = msg['x1'] / mpl.ratio;\n", 443 " var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n", 444 " x0 = Math.floor(x0) + 0.5;\n", 445 " y0 = Math.floor(y0) + 0.5;\n", 446 " x1 = Math.floor(x1) + 0.5;\n", 447 " y1 = Math.floor(y1) + 0.5;\n", 448 " var min_x = Math.min(x0, x1);\n", 449 " var min_y = Math.min(y0, y1);\n", 450 " var width = Math.abs(x1 - x0);\n", 451 " var height = Math.abs(y1 - y0);\n", 452 "\n", 453 " fig.rubberband_context.clearRect(\n", 454 " 0, 0, fig.canvas.width / mpl.ratio, fig.canvas.height / mpl.ratio);\n", 455 "\n", 456 " fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n", 457 "}\n", 458 "\n", 459 "mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n", 460 " // Updates the figure title.\n", 461 " fig.header.textContent = msg['label'];\n", 462 "}\n", 463 "\n", 464 "mpl.figure.prototype.handle_cursor = function(fig, msg) {\n", 465 " var cursor = msg['cursor'];\n", 466 " switch(cursor)\n", 467 " {\n", 468 " case 0:\n", 469 " cursor = 'pointer';\n", 470 " break;\n", 471 " case 1:\n", 472 " cursor = 'default';\n", 473 " break;\n", 474 " case 2:\n", 475 " cursor = 'crosshair';\n", 476 " break;\n", 477 " case 3:\n", 478 " cursor = 'move';\n", 479 " break;\n", 480 " }\n", 481 " fig.rubberband_canvas.style.cursor = cursor;\n", 482 "}\n", 483 "\n", 484 "mpl.figure.prototype.handle_message = function(fig, msg) {\n", 485 " fig.message.textContent = msg['message'];\n", 486 "}\n", 487 "\n", 488 "mpl.figure.prototype.handle_draw = function(fig, msg) {\n", 489 " // Request the server to send over a new figure.\n", 490 " fig.send_draw_message();\n", 491 "}\n", 492 "\n", 493 "mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n", 494 " fig.image_mode = msg['mode'];\n", 495 "}\n", 496 "\n", 497 "mpl.figure.prototype.updated_canvas_event = function() {\n", 498 " // Called whenever the canvas gets updated.\n", 499 " this.send_message(\"ack\", {});\n", 500 "}\n", 501 "\n", 502 "// A function to construct a web socket function for onmessage handling.\n", 503 "// Called in the figure constructor.\n", 504 "mpl.figure.prototype._make_on_message_function = function(fig) {\n", 505 " return function socket_on_message(evt) {\n", 506 " if (evt.data instanceof Blob) {\n", 507 " /* FIXME: We get \"Resource interpreted as Image but\n", 508 " * transferred with MIME type text/plain:\" errors on\n", 509 " * Chrome. But how to set the MIME type? It doesn't seem\n", 510 " * to be part of the websocket stream */\n", 511 " evt.data.type = \"image/png\";\n", 512 "\n", 513 " /* Free the memory for the previous frames */\n", 514 " if (fig.imageObj.src) {\n", 515 " (window.URL || window.webkitURL).revokeObjectURL(\n", 516 " fig.imageObj.src);\n", 517 " }\n", 518 "\n", 519 " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n", 520 " evt.data);\n", 521 " fig.updated_canvas_event();\n", 522 " fig.waiting = false;\n", 523 " return;\n", 524 " }\n", 525 " else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n", 526 " fig.imageObj.src = evt.data;\n", 527 " fig.updated_canvas_event();\n", 528 " fig.waiting = false;\n", 529 " return;\n", 530 " }\n", 531 "\n", 532 " var msg = JSON.parse(evt.data);\n", 533 " var msg_type = msg['type'];\n", 534 "\n", 535 " // Call the \"handle_{type}\" callback, which takes\n", 536 " // the figure and JSON message as its only arguments.\n", 537 " try {\n", 538 " var callback = fig[\"handle_\" + msg_type];\n", 539 " } catch (e) {\n", 540 " console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n", 541 " return;\n", 542 " }\n", 543 "\n", 544 " if (callback) {\n", 545 " try {\n", 546 " // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n", 547 " callback(fig, msg);\n", 548 " } catch (e) {\n", 549 " console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n", 550 " }\n", 551 " }\n", 552 " };\n", 553 "}\n", 554 "\n", 555 "// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n", 556 "mpl.findpos = function(e) {\n", 557 " //this section is from http://www.quirksmode.org/js/events_properties.html\n", 558 " var targ;\n", 559 " if (!e)\n", 560 " e = window.event;\n", 561 " if (e.target)\n", 562 " targ = e.target;\n", 563 " else if (e.srcElement)\n", 564 " targ = e.srcElement;\n", 565 " if (targ.nodeType == 3) // defeat Safari bug\n", 566 " targ = targ.parentNode;\n", 567 "\n", 568 " // jQuery normalizes the pageX and pageY\n", 569 " // pageX,Y are the mouse positions relative to the document\n", 570 " // offset() returns the position of the element relative to the document\n", 571 " var x = e.pageX - $(targ).offset().left;\n", 572 " var y = e.pageY - $(targ).offset().top;\n", 573 "\n", 574 " return {\"x\": x, \"y\": y};\n", 575 "};\n", 576 "\n", 577 "/*\n", 578 " * return a copy of an object with only non-object keys\n", 579 " * we need this to avoid circular references\n", 580 " * http://stackoverflow.com/a/24161582/3208463\n", 581 " */\n", 582 "function simpleKeys (original) {\n", 583 " return Object.keys(original).reduce(function (obj, key) {\n", 584 " if (typeof original[key] !== 'object')\n", 585 " obj[key] = original[key]\n", 586 " return obj;\n", 587 " }, {});\n", 588 "}\n", 589 "\n", 590 "mpl.figure.prototype.mouse_event = function(event, name) {\n", 591 " var canvas_pos = mpl.findpos(event)\n", 592 "\n", 593 " if (name === 'button_press')\n", 594 " {\n", 595 " this.canvas.focus();\n", 596 " this.canvas_div.focus();\n", 597 " }\n", 598 "\n", 599 " var x = canvas_pos.x * mpl.ratio;\n", 600 " var y = canvas_pos.y * mpl.ratio;\n", 601 "\n", 602 " this.send_message(name, {x: x, y: y, button: event.button,\n", 603 " step: event.step,\n", 604 " guiEvent: simpleKeys(event)});\n", 605 "\n", 606 " /* This prevents the web browser from automatically changing to\n", 607 " * the text insertion cursor when the button is pressed. We want\n", 608 " * to control all of the cursor setting manually through the\n", 609 " * 'cursor' event from matplotlib */\n", 610 " event.preventDefault();\n", 611 " return false;\n", 612 "}\n", 613 "\n", 614 "mpl.figure.prototype._key_event_extra = function(event, name) {\n", 615 " // Handle any extra behaviour associated with a key event\n", 616 "}\n", 617 "\n", 618 "mpl.figure.prototype.key_event = function(event, name) {\n", 619 "\n", 620 " // Prevent repeat events\n", 621 " if (name == 'key_press')\n", 622 " {\n", 623 " if (event.which === this._key)\n", 624 " return;\n", 625 " else\n", 626 " this._key = event.which;\n", 627 " }\n", 628 " if (name == 'key_release')\n", 629 " this._key = null;\n", 630 "\n", 631 " var value = '';\n", 632 " if (event.ctrlKey && event.which != 17)\n", 633 " value += \"ctrl+\";\n", 634 " if (event.altKey && event.which != 18)\n", 635 " value += \"alt+\";\n", 636 " if (event.shiftKey && event.which != 16)\n", 637 " value += \"shift+\";\n", 638 "\n", 639 " value += 'k';\n", 640 " value += event.which.toString();\n", 641 "\n", 642 " this._key_event_extra(event, name);\n", 643 "\n", 644 " this.send_message(name, {key: value,\n", 645 " guiEvent: simpleKeys(event)});\n", 646 " return false;\n", 647 "}\n", 648 "\n", 649 "mpl.figure.prototype.toolbar_button_onclick = function(name) {\n", 650 " if (name == 'download') {\n", 651 " this.handle_save(this, null);\n", 652 " } else {\n", 653 " this.send_message(\"toolbar_button\", {name: name});\n", 654 " }\n", 655 "};\n", 656 "\n", 657 "mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n", 658 " this.message.textContent = tooltip;\n", 659 "};\n", 660 "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", 661 "\n", 662 "mpl.extensions = [\"eps\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n", 663 "\n", 664 "mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n", 665 " // Create a \"websocket\"-like object which calls the given IPython comm\n", 666 " // object with the appropriate methods. Currently this is a non binary\n", 667 " // socket, so there is still some room for performance tuning.\n", 668 " var ws = {};\n", 669 "\n", 670 " ws.close = function() {\n", 671 " comm.close()\n", 672 " };\n", 673 " ws.send = function(m) {\n", 674 " //console.log('sending', m);\n", 675 " comm.send(m);\n", 676 " };\n", 677 " // Register the callback with on_msg.\n", 678 " comm.on_msg(function(msg) {\n", 679 " //console.log('receiving', msg['content']['data'], msg);\n", 680 " // Pass the mpl event to the overridden (by mpl) onmessage function.\n", 681 " ws.onmessage(msg['content']['data'])\n", 682 " });\n", 683 " return ws;\n", 684 "}\n", 685 "\n", 686 "mpl.mpl_figure_comm = function(comm, msg) {\n", 687 " // This is the function which gets called when the mpl process\n", 688 " // starts-up an IPython Comm through the \"matplotlib\" channel.\n", 689 "\n", 690 " var id = msg.content.data.id;\n", 691 " // Get hold of the div created by the display call when the Comm\n", 692 " // socket was opened in Python.\n", 693 " var element = $(\"#\" + id);\n", 694 " var ws_proxy = comm_websocket_adapter(comm)\n", 695 "\n", 696 " function ondownload(figure, format) {\n", 697 " window.open(figure.imageObj.src);\n", 698 " }\n", 699 "\n", 700 " var fig = new mpl.figure(id, ws_proxy,\n", 701 " ondownload,\n", 702 " element.get(0));\n", 703 "\n", 704 " // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n", 705 " // web socket which is closed, not our websocket->open comm proxy.\n", 706 " ws_proxy.onopen();\n", 707 "\n", 708 " fig.parent_element = element.get(0);\n", 709 " fig.cell_info = mpl.find_output_cell(\"<div id='\" + id + \"'></div>\");\n", 710 " if (!fig.cell_info) {\n", 711 " console.error(\"Failed to find cell for figure\", id, fig);\n", 712 " return;\n", 713 " }\n", 714 "\n", 715 " var output_index = fig.cell_info[2]\n", 716 " var cell = fig.cell_info[0];\n", 717 "\n", 718 "};\n", 719 "\n", 720 "mpl.figure.prototype.handle_close = function(fig, msg) {\n", 721 " var width = fig.canvas.width/mpl.ratio\n", 722 " fig.root.unbind('remove')\n", 723 "\n", 724 " // Update the output cell to use the data from the current canvas.\n", 725 " fig.push_to_output();\n", 726 " var dataURL = fig.canvas.toDataURL();\n", 727 " // Re-enable the keyboard manager in IPython - without this line, in FF,\n", 728 " // the notebook keyboard shortcuts fail.\n", 729 " IPython.keyboard_manager.enable()\n", 730 " $(fig.parent_element).html('<img src=\"' + dataURL + '\" width=\"' + width + '\">');\n", 731 " fig.close_ws(fig, msg);\n", 732 "}\n", 733 "\n", 734 "mpl.figure.prototype.close_ws = function(fig, msg){\n", 735 " fig.send_message('closing', msg);\n", 736 " // fig.ws.close()\n", 737 "}\n", 738 "\n", 739 "mpl.figure.prototype.push_to_output = function(remove_interactive) {\n", 740 " // Turn the data on the canvas into data in the output cell.\n", 741 " var width = this.canvas.width/mpl.ratio\n", 742 " var dataURL = this.canvas.toDataURL();\n", 743 " this.cell_info[1]['text/html'] = '<img src=\"' + dataURL + '\" width=\"' + width + '\">';\n", 744 "}\n", 745 "\n", 746 "mpl.figure.prototype.updated_canvas_event = function() {\n", 747 " // Tell IPython that the notebook contents must change.\n", 748 " IPython.notebook.set_dirty(true);\n", 749 " this.send_message(\"ack\", {});\n", 750 " var fig = this;\n", 751 " // Wait a second, then push the new image to the DOM so\n", 752 " // that it is saved nicely (might be nice to debounce this).\n", 753 " setTimeout(function () { fig.push_to_output() }, 1000);\n", 754 "}\n", 755 "\n", 756 "mpl.figure.prototype._init_toolbar = function() {\n", 757 " var fig = this;\n", 758 "\n", 759 " var nav_element = $('<div/>');\n", 760 " nav_element.attr('style', 'width: 100%');\n", 761 " this.root.append(nav_element);\n", 762 "\n", 763 " // Define a callback function for later on.\n", 764 " function toolbar_event(event) {\n", 765 " return fig.toolbar_button_onclick(event['data']);\n", 766 " }\n", 767 " function toolbar_mouse_event(event) {\n", 768 " return fig.toolbar_button_onmouseover(event['data']);\n", 769 " }\n", 770 "\n", 771 " for(var toolbar_ind in mpl.toolbar_items){\n", 772 " var name = mpl.toolbar_items[toolbar_ind][0];\n", 773 " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", 774 " var image = mpl.toolbar_items[toolbar_ind][2];\n", 775 " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", 776 "\n", 777 " if (!name) { continue; };\n", 778 "\n", 779 " var button = $('<button class=\"btn btn-default\" href=\"#\" title=\"' + name + '\"><i class=\"fa ' + image + ' fa-lg\"></i></button>');\n", 780 " button.click(method_name, toolbar_event);\n", 781 " button.mouseover(tooltip, toolbar_mouse_event);\n", 782 " nav_element.append(button);\n", 783 " }\n", 784 "\n", 785 " // Add the status bar.\n", 786 " var status_bar = $('<span class=\"mpl-message\" style=\"text-align:right; float: right;\"/>');\n", 787 " nav_element.append(status_bar);\n", 788 " this.message = status_bar[0];\n", 789 "\n", 790 " // Add the close button to the window.\n", 791 " var buttongrp = $('<div class=\"btn-group inline pull-right\"></div>');\n", 792 " var button = $('<button class=\"btn btn-mini btn-primary\" href=\"#\" title=\"Stop Interaction\"><i class=\"fa fa-power-off icon-remove icon-large\"></i></button>');\n", 793 " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", 794 " button.mouseover('Stop Interaction', toolbar_mouse_event);\n", 795 " buttongrp.append(button);\n", 796 " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", 797 " titlebar.prepend(buttongrp);\n", 798 "}\n", 799 "\n", 800 "mpl.figure.prototype._root_extra_style = function(el){\n", 801 " var fig = this\n", 802 " el.on(\"remove\", function(){\n", 803 "\tfig.close_ws(fig, {});\n", 804 " });\n", 805 "}\n", 806 "\n", 807 "mpl.figure.prototype._canvas_extra_style = function(el){\n", 808 " // this is important to make the div 'focusable\n", 809 " el.attr('tabindex', 0)\n", 810 " // reach out to IPython and tell the keyboard manager to turn it's self\n", 811 " // off when our div gets focus\n", 812 "\n", 813 " // location in version 3\n", 814 " if (IPython.notebook.keyboard_manager) {\n", 815 " IPython.notebook.keyboard_manager.register_events(el);\n", 816 " }\n", 817 " else {\n", 818 " // location in version 2\n", 819 " IPython.keyboard_manager.register_events(el);\n", 820 " }\n", 821 "\n", 822 "}\n", 823 "\n", 824 "mpl.figure.prototype._key_event_extra = function(event, name) {\n", 825 " var manager = IPython.notebook.keyboard_manager;\n", 826 " if (!manager)\n", 827 " manager = IPython.keyboard_manager;\n", 828 "\n", 829 " // Check for shift+enter\n", 830 " if (event.shiftKey && event.which == 13) {\n", 831 " this.canvas_div.blur();\n", 832 " event.shiftKey = false;\n", 833 " // Send a \"J\" for go to next cell\n", 834 " event.which = 74;\n", 835 " event.keyCode = 74;\n", 836 " manager.command_mode();\n", 837 " manager.handle_keydown(event);\n", 838 " }\n", 839 "}\n", 840 "\n", 841 "mpl.figure.prototype.handle_save = function(fig, msg) {\n", 842 " fig.ondownload(fig, null);\n", 843 "}\n", 844 "\n", 845 "\n", 846 "mpl.find_output_cell = function(html_output) {\n", 847 " // Return the cell and output element which can be found *uniquely* in the notebook.\n", 848 " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", 849 " // IPython event is triggered only after the cells have been serialised, which for\n", 850 " // our purposes (turning an active figure into a static one), is too late.\n", 851 " var cells = IPython.notebook.get_cells();\n", 852 " var ncells = cells.length;\n", 853 " for (var i=0; i<ncells; i++) {\n", 854 " var cell = cells[i];\n", 855 " if (cell.cell_type === 'code'){\n", 856 " for (var j=0; j<cell.output_area.outputs.length; j++) {\n", 857 " var data = cell.output_area.outputs[j];\n", 858 " if (data.data) {\n", 859 " // IPython >= 3 moved mimebundle to data attribute of output\n", 860 " data = data.data;\n", 861 " }\n", 862 " if (data['text/html'] == html_output) {\n", 863 " return [cell, data, j];\n", 864 " }\n", 865 " }\n", 866 " }\n", 867 " }\n", 868 "}\n", 869 "\n", 870 "// Register the function which deals with the matplotlib target/channel.\n", 871 "// The kernel may be null if the page has been refreshed.\n", 872 "if (IPython.notebook.kernel != null) {\n", 873 " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", 874 "}\n" 875 ], 876 "text/plain": [ 877 "<IPython.core.display.Javascript object>" 878 ] 879 }, 880 "metadata": {}, 881 "output_type": "display_data" 882 }, 883 { 884 "data": { 885 "text/html": [ 886 "<img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAoAAAAHgCAYAAAA10dzkAAAgAElEQVR4XuydCZhWZfn/79ln2AZQIGQTkSVBDZUoSIxMpdIQLaNFpVIwkMIlSFAB2SLNrdTgzy8kizSNxUTUzNizjEVRBCNQSRAREGGGmWFm3v/1HHxfZ2CA8z3PzMg77+dc11yXOPd9lu99P8/5zP0sJy0Wi8WMAwVQAAVQAAVQAAVQIGUUSAMAUybWPCgKoAAKoAAKoAAKBAoAgCQCCqAACqAACqAACqSYAgBgigWcx0UBFEABFEABFEABAJAcQAEUQAEUQAEUQIEUUwAATLGA87gogAIogAIogAIoAACSAyiAAiiAAiiAAiiQYgoAgCkWcB4XBVAABVAABVAABQBAcgAFUAAFUAAFUAAFUkwBADDFAs7jogAKoAAKoAAKoAAASA6gAAqgAAqgAAqgQIopAACmWMB5XBRAARRAARRAARQAAMkBFEABFEABFEABFEgxBQDAFAs4j4sCKIACKIACKIACACA5gAIogAIogAIogAIppgAAmGIB53FRAAVQAAVQAAVQAAAkB1AABVAABVAABVAgxRQAAFMs4DwuCqAACqAACqAACgCA5AAKoAAKoAAKoAAKpJgCAGCKBZzHRQEUQAEUQAEUQAEAkBxAARRAARRAARRAgRRTAABMsYDzuCiAAiiAAiiAAigAAJIDKIACKIACKIACKJBiCgCAKRZwHhcFUAAFUAAFUAAFAEByAAVQAAVQAAVQAAVSTAEAMMUCzuOiAAqgAAqgAAqgAABIDqAACqAACqAACqBAiikAAKZYwHlcFEABFEABFEABFAAAyQEUQAEUQAEUQAEUSDEFAMAUCziPiwIogAIogAIogAIAIDmAAiiAAiiAAiiAAimmAACYYgHncVEABVAABVAABVAAACQHUAAFUAAFUAAFUCDFFAAAUyzgPC4KoAAKoAAKoAAKAIDkAAqgAAqgAAqgAAqkmAIAYIoFnMdFARRAARRAARRAAQCQHEABFEABFEABFECBFFMAAEyxgPO4n6wCL774ov3yl7+0ZcuW2c6dO61p06b2hS98wW666Sb7/Oc/H/rmxo0bZ+PHj7dYLBbaJ264aNEi69u3r/3973+3L37xi7J/WIf4ud31jnbcf//9Nnv2bNu4caPt3bvXWrRoYb169bLbbrvNunbtmnB94403bPr06cF9//e//7X09HT79Kc/bTfccIN94xvfCHtblexmzJhhTz31lK1Zs8a2b99urVq1sgsuuMBuv/12a9my5RHP6WxPO+0027Vrlz3++OORrx/ppnFCARRAgWpQAACsBhE5BQqEUeBXv/qVjRgxwj772c/a0KFDrV27dvb222/bAw88YP/617/svvvus+uvvz7Mqex///tf8PO5z30ulH1Fow8//NDWrVsXAEyjRo1k/7AOYQFw7NixAcydeeaZ1qRJE9u0aZP9/Oc/t3feecdWrlxpnTt3Di7561//OtDqyiuvtB49elhpaak99thjNmvWrACGHbSphwM+B8Nf/epXA/jbsGGDTZgwwcrKymz16tUBjFZ1OOD8xz/+YVu3bgUAVdGxRwEUOC4UAACPizBwE3VdgeXLl1ufPn0C0Jg7d65lZmYmHtmBzIABA+zpp5+2JUuWWO/evY8oR2FhodWrVy8p5AoLgFU9zOuvvx4AqqsC3nHHHYHJ+++/byeccIKlpaVVcrn44ouDqqCrxuXk5EjavPfee9a8efNKPv/+978DwHQgeOuttx52vj//+c82aNCgAEavvvpqAFBSHGMUQIHjRQEA8HiJBPdRpxVwkPLMM8/Ym2++aa1btz7sWbds2WLt27e3r3zlK/aXv/wl+H18mNdVwSZPnmx/+9vfLDc317Zt25b4XcUh4OLiYhs9erT94Q9/MFflO+ecc+yee+6xyy+/PBjqffjhh4PzVjUE7IDmiSeeCIZCf/zjHwcg6qpxV1xxRXDtimDlqm0OVv/zn/8EVbhTTz3Vhg0bZj/4wQ8qwZkPADrYa9asWajKngNEV0V01Tg3bOt8u3fvbm3atLHFixdbVlZW8Nyu6unA7rLLLrNHHnnkiPnmNHU+P/zhD23atGmV7BxkOjB1Op9xxhlB9ZAh4DrddHk4FKizCgCAdTa0PNjxooAbTnRDraeffrq5OYBHOnr27GmvvvpqAG8ZGRkJyHNDxQMHDrQvf/nLVlBQYP37968SAL/zne8EQ6IjR460L33pSwHwuPmG7nyXXnrpMQHwj3/8o3Xo0CEAn8985jMBBLoqmAPRisOr3//+9+3cc8+1tm3bBo/inslB4s9+9rNKdioAOp0cUG7evDk4lxtiddU4B3JHOxyEvfbaawEYO93c4Squ7vrDhw+3u+++21zl1MFfeXl5cM769esf8ZRxQHZD8g6GKx7f+973gvmH7vxOHwDweGll3AcKoICqAACoKoY9CogKuAUDn/rUpwKIc5B1pMP93gGcs3fDkvEKoIMvV3WreBy6CMTBnlswMWrUqGD+XPx49NFH7dvf/nYwVHmsCqCbS/enP/3JvvnNbyb8v/a1rwXAs379+ipv2wGV+5kyZUowh3HHjh2JKqAKgK666aqY7ujUqZPNmzcvWORxtMMt4rj22muDax8Ka7/4xS8CPdyQuzuXe7Z//vOfAYgf6XCLUByI79u3LwDoBg0aJEwXLFgQDNWvWrXKunXrlqikUgEUGwTmKIACx4UCAOBxEQZuoi4rEBYAv/WtbwWQ4ualueHPOOS9/PLLwXDj0QDwoYceChaWuOHis846K2HqKmp5eXn23e9+95gA+Lvf/S6olDkQix+33HKL3XvvvbZ///7E/3vhhReCit9LL70UVBcrHu+++25i4YQKgA6sSkpKAuB0Q9dukYsb9q64ErjitRYuXBhUNr/+9a8Huh06N9AN5V5yySXBOYqKiszBoqtuHulwNs5+xYoV5p7RgWD82LNnT3AfrvrpqqLuiFcKAcC63Hp5NhSouwoAgHU3tjzZcaKA7xBwHAiPBoATJ04MFkw4aHKrWSservrYr1+/YwKgmwPoKl9Hu45brey2aHFwN3jw4GA+Y3Z2dlBhmzRpUjB8e/LJJwenUAGw4nVdJc7NLXSrnOfPn39YJJ999tkA/s4//3ybM2dOcA9VHe6ZXEXTafDWW28d0c5VHt35HNS5bWHceSsebnW2qwC64e74fEi3lY8DRlc5dRCan59/GIQeJynIbaAACqDAYQoAgCQFCtSCAsdaBOLAzYFTVYtA3LDqiSeeeFQwq44KYBgAvPHGG81da/fu3ZUqhW61bHUCoHvY8847L6iGuhXBFY84/LnfOzg80spfNyfQzWU86aSTgjmC1113nbk9Bw894vDnVhK781100UWH2TiYdQtKjnY4TRo3blwL2cQlUAAFUMBfAQDQX0POgALHVCC+DYybU+fmpMUXKzhHVyF01Se3snbp0qVBhc0d8SHgMADoAMfNS3MLQKZOnZq4H2UOYBgAdBtWu82Y3WrY+OpaNzzcpUuXYE/D6qoAupW8bh6g2xInviraPdRzzz0XLIJxm2e7/19xuLpiEJymrorn5i66lc1uZfTNN99sbgsXtwo4fjj4c/P63DCxqyS6+FR1uHN88MEHlX7l/p/bhNrFycGou6eK2/scMykwQAEUQIFPUAEA8BMUn0unlgIVN4J2Q4puFW18I2i3OMHNtXOrVuOHAoDOx60CdnPh4quAHRTGVwE76Pntb38bnPpo28AcawjYzY1zYOU2QnZDwO5rJnfddVcwF9BtC6MCoJtb57684e69Y8eOwXxF98UPt6jDaeOqbm47G3e4IdcLL7wwmGPonsXZVjwqbmztKpJuYYoDxvhwrhumdYDt5hq6LXfc4YZw3ZDvmDFjzFVpKx5u5bY755EO5gCmVvvlaVGgrikAANa1iPI8x7UC8U/BORCp+Ck4V5069FNwKgDG9wH8/e9/HwCZG/50iync/D+3R5/bDsUXAJ3/zJkzgyqj29PQzTd0q3DdqmW3wEIFQHfPDoZdhdTthegWYrj5em7I1S1AqQhgcT2OFOD4p+3++te/Bs/s5kQ6n/jhqpZuf0AHkA4m3bzBQxeOVDy3q+od7TN2AOBx3dS4ORRAgWMoAACSIihQhxVwK1rdMKobAnVVNg4UQAEUQAEUcAoAgOQBCtQRBVzly22efPbZZwfDo277GLcnoFud+sorrxxxvlwdeXweAwVQAAVQQFAAABTEwhQFjmcF3DxCt0jDbWDstlFxK4fdilY3F859Io0DBVAABVAABeIKAIDkAgqgAAqgAAqgAAqkmAIAYIoFnMdFARRAARRAARRAAQCQHEABFEABFEABFECBFFMAAEyxgPO4KIACKIACKIACKAAAkgMogAIogAIogAIokGIKAIAeAS8vL7etW7daw4YN+Qi8h464ogAKoEAqKBCLxYIV+u771Onp6TX2yG5D9ZKSEu/zu83Sj/S5Re+Tc4JPXAEA0CME//vf/6xNmzYeZ8AVBVAABVAg1RRwX71p3bp1jTy2g7/27RrYu++VeZ/ffZXHfd0HCPSW8rg8AQDoERb3HdPGjRvbqT+63TJyckOdqaDDgVB2FY3Sc/SGHCtPk6+TsSNb9mn4pnadohPkS1hJ05juVB7BJUu/Trp4nfJGpfKNndjsQ9mn6ECW7NOt+TbZpzymxf9fr5wqXyNrZ4bsk7tLdrF0PTSWJsY/q1DPsdz39Rvb10qPf5R7KxcvE4tQ9ErTuz8raaTlpcuW7A/12OTP/peUaKV2wJbZ0/bBBx8EG7TXxOE+A+nO/dbKk61RwwiCf3RTH+4tt3Znv2nuPee+i81R9xQAAD1iGm9onUdMDg2A+zoexwD4ng6AjTZpHW3RibrgxSfoHbOJL2Z3V+XZ+nXSxZdTeb7+Mm/WfI8sWhQAPKPFVvk6KgD+Y00n+RrZ70cAwJ3yZSxdb5q1AoB5O/Sc2dtaJDMHQAV6/peJXUatAWC+1i8FALhHf/7Gs/4hJVpp7IAtsvk1ClXx99LON9p7A+AJnTbX6L1K4mFc7QoAgB6SAoBmAKCWQAAgAKhljBkAqCpmVgIA2nsb2nkDYPPObwGAevoljQcA6BEqABAApAKoVVqoAOpVJgBQ76QBwHx7d0NbbwD8VOe3QwOg++TknDlzbP369cG3yHv16mVTp061zp07HxZAtxjmq1/9qj3zzDM2d+5cu/TSS48Y5EGDBtmsWbMq/b5nz5724osv6omBRyUFAECPhAAAAUAAEABUupAo8+wAQEXhg7YAYO0DYL9+/WzgwIHWo0cPKy0ttTFjxtjatWuDb5PXr1+/UhDvuece++tf/2oLFy4MBYDbt2+3mTNnJs7hVic3bdpUTww8AMDqygEAEAAEAAFApT8BABW1DtpGWgTCELBt3dDauwJ4Uuf/ha4AHhrZHTt2WPPmzW3x4sXWp0+fxK9ffvllu/jii+2ll16yli1bhgJAt2hm3rx5evLgcVQFqAB6JAgACAACgACg0oUAgIpaAKCulln8vbRlfStvAGzT5R1zW9ZUXAWck5Nj7udYx8aNG61jx45BFbBbt26BeWFhoZ1zzjnmhov79+8f7J8bZgjYwZ+r+rldN8477zybNGlSAJccfgoAgB76AYAAIAAIACpdCACoqAUA6mpVPwAeeg9jx461cePGHfXW3Bw/B3i7d++2pUuXJmyHDBliZWVlNmPGjIPV3RAA+Nhjj1mDBg2sXbt2wZ6Et912WzDEvHLlylAgGkXDVPEBAD0iDQACgAAgAKh0IQCgohYAqKv1MQC+tf4k7wpguy5bI1UAhw0bZgsWLLBly5YlNrx+8skn7aabbrLVq1cHQBcWAA/VYNu2bQEMPvroo3bZZZdFkQifjxQAAD1SAQAEAAFAAFDpQgBARS0AUFfrYwDcvL6lNfTYCHrv3nJr32WbPAdw+PDhwXy9JUuWWPv27ROPMGLECLv//vsrfQLPVQPdJ/HOPfdcW7RoUejHdUPL11xzjY0aNSq0D4aHKwAAemQFAAgAAoAAoNKFAICKWgCgrtYnB4Bu2NfBn5vT52DOQVrF491337X333+/0v87/fTT7b777rNLLrmkEiwe7bl37txprVq1sunTp9tVV10VRSJ8qAD65wAACAACgACg0pMAgIpaAKCu1scA+N/1n/KuAHbo8m7oCuDQoUNt9uzZNn/+/Ep7/7nP0rl9Aas6qpoD2KVLl2CRyIABA2zfvn3BfMPLL788WDH85ptv2ujRo+3tt9+2119/3Ro2bBhFInwAQP8cAAABQAAQAFR6EgBQUQsA1NX6GADfeL2FNwB2+vT20ADoYK6qw+3f5zZzDguA7jxxn/379webRLt5g24rGAeBffv2tQkTJlibNm2iyINPBQUYAvZIBwAQAAQAAUClCwEAFbUAQF2tTw4Ao9wrPp+sAgCgh/4AIAAIAAKAShcCACpqAYC6Wh8D4PpqqAB2ESqAUe4Vn09WAQDQQ/84AHYZPtkycnJDnWl/S/1boFl7tJdscCPpoW6nklF6se4Ty9R8ShpFeP59+vMXn1Cu3ZiZxTL0e8so0oQua1Am31f2CUWyT272Admn8wk7ZJ+3Pmwi+XywsplkH6RyqexiWXt0n9KDO1NIR7ooc+Z+6fSBcVqE5y/L1q+TqaeZlYXr9hI30+hNPf8LPpUhP0zubr39F7bQ2rK7qSYbtAQoLS2y5c+PDT2sKj+4fQyAr73e3HsIuOun36vRe43yfPhUnwIAoIeWAKAZAKi9NABAAFDtcgBAAFDJmfh76ZV1/gB4xmkAoKJ9stkCgB4RAwABQCqAVACVLoQKIBXA2qoAAoBKy0xNWwDQI+4AIAAIAAKAShcCAAKAtQWAa6qhAvgZKoBK8046WwDQI2QAIAAIAAKAShcCAAKAtQWAq9a1sAYeXwLZt7fczjot/DYwSjvA9vhQAAD0iAMACAACgACg0oUAgAAgAKi0GGxrUgEA0ENdABAABAABQKULAQABwNoCwH+/5l8BPKcrFUClfSebLQDoETEAEAAEAAFApQsBAAHA2gLAf772Ke8h4J5dw38KTmkH2B4fCgCAHnEAAAFAABAAVLoQABAABACVFoNtTSoAAHqoCwACgAAgAKh0IQAgAFhbALjitZbeFcBeXbexEbTSwJPMFgD0CBgACAACgACg0oUAgABgbQHgsldP8gbAL3TbCgAqDTzJbAFAj4ABgAAgAAgAKl0IAAgAAoBKi8G2JhUAAD3UBQABQAAQAFS6EAAQAKwtAFz8aivvCuB53d6hAqg08CSzBQA9AgYAAoAAIACodCEAIABYWwD4wqttvAHwS922AIBKA08yWwDQI2AAIAAIAAKAShcCAAKAtQWAf1vb1up7fAmkYG+5nX/62wCg0sCTzBYA9AgYAAgAAoAAoNKFAIAAIACotBhsa1IBANBD3TgAdh0y2TKyc0OdKZYZyqySUWah7nOgvu5TrL3LgwuU58SkC2XuS5PsnXHxieWyT3l9/UWTtSNLvk72h5pLcRNNL3f2tLZ6ApQW6c+Ska1rVlaSIQmQuV2/r+zdes7EtNsKniGKT5qYmhlFklyBcUaJ7lPSSPdJL9Z9MsXnyXtfFMzMynL0+Bc31n2iwHnD/5VKopUeKLIVz95eo1W1+HvpubXtvCuAF57+Vo3eqyQextWuAADoISkACAACgBppAYB6hwMA6jAHAObbwlfaewPgV87YDADqTTZpPABAj1ABgAAgAAgAKl0IFUAqgLVVAQQAlZaZmrYAoEfcAUAAEAAEAJUuBAAEAGsLABe8corVb6i1z4q5XLC3zL52xiYqgEoDTzJbANAjYAAgAAgAai8YhoD1DochYIaAlayJv5eefKWDNwB+/Yz/AoCK+ElmCwB6BAwABAABQABQ6UKoAFIBrK0KIACotMzUtAUAPeIOAAKAACAAqHQhACAAWFsAOPfljt4VwAFn/ocKoNLAk8wWAPQIGAAIAAKAAKDShQCAAGBtAeCfX+7kDYCXn/kGAKg08CSzBQA9AgYAAoAAIACodCEAIAAIACotBtuaVAAA9FAXAAQAAUAAUOlCAEAAsLYA8PGXu1g9j1XAhXvL7JtnrqcCqDTwJLMFAD0CBgACgAAgAKh0IQAgAFhbAPjomtO8AXDgZ9YBgEoDTzLbOguAU6ZMsTlz5tj69estLy/PevXqZVOnTrXOnTsnQlRcXGw333yz/fGPf7T9+/fb+eefbw8++KC1bt06VBgBQAAQAAQAQ3UWHxkBgABgbQHg7DXdvAHwO595FQBUGniS2dZZAOzXr58NHDjQevToYaWlpTZmzBhbu3atrVu3zurXP/ih3B/96Ef2l7/8xR5++GE74YQT7KabbrJdu3bZypUrLSPj2C82ABAABACP3U4q9onsA6i/IdgHkH0AlayJv5cAQEW11LStswB4aDh37NhhzZs3t8WLF1ufPn2Cv2qaNWtmjzzyiH3rW98KzLdu3Wpt2rSxp59+2i666KJjZgQACAACgADgMTuKCgZUAKkA1lYF8JHVp3tXAK/svpYKoNLAk8w2ZQBw48aN1rFjx6AK2K1bN3vhhReCIV9X8WvSpEkibGeeeaZdeumlNn78+GOGEgAEAAFAAPCYHQUAmFAg730AsLYA8OHVZ3oD4KDuLwOASgNPMtuUAMBYLGb9+/e33bt329KlS4MQzZ49277//e+bmwdY8bjwwgutffv2Nm3atMNC6Wwr2jsAdBXDrkMmW0Z2bqjQxzJDmVUyyizUfQ4cHOWWjuKPOTi0X3lOLLStM8zcF2E450T9pVFev0y6L2ectSNL9gEAAUAlaagA6m25LCdCn9FY98ncr0TyoG3D/5VKTqUHigwAlCTDuAYVSAkAHDZsmC1YsMCWLVuWWOBxJAC84IILrEOHDvab3/zmMNnHjRtXZWXw5ImTLD235gCw/ha9Mytoq3e05Y20zswJlLZXI9pYtgaMATR+oEGG8yltoD9/ZqGuswrA5Q11ME0r0J+/vJ5+nfQI18ksSJe6p6wPJfPAOMofTdl79OuU1tN9yrX0t/QD+jXUPzKC/A/XHVW6GT37zWKiU4NterssPFHLsaDPiABzhS312KgeZcVF9p9fjK7Rqlp8ZOq3q7p7VwB/cNbqGr1XVT/sq1eBOg+Aw4cPt3nz5tmSJUuCyl78iDIEfKQKIAAYPikBQB3MAMDw+RW3BAB1zUSWOwjnohMAWHsA+P9Wne0NgNeetRIA1JtS0njUWQB0w74O/ubOnWuLFi0K5v9VPOKLQH7/+9/bFVdcEfxq27ZtQYVQXQQCAIbPdwAQAAyfLQctqQCqilEBpAKYbwCg3m5SzaPOAuDQoUODeX7z58+vtPdffn5+sC+gO9w2ME899VSwDUzTpk2DPQF37twpbwMDAIZvNgAgABg+WwBApwBDwAwBK20mPgQ8bdXZltdAnKNQ4UL795XaECqAivRJZ1tnATAtreqxiZkzZ9qgQYOCQBUVFdlPf/rTABQrbgTtFnaEOeINDQAMo9ZHL3PmAIYX6yNLhoBlyYwhYF0zcTT3YHVWdGIIuPaGgB9a1cMbAH901ksMAetNKWk86iwA1kYEAEAWgbAIRKvOsAhE75moAGo55hRmCDjfAEC9raWaBwDoEXEAEAAEALWXMwCodzgAoJZjAOCH5qY6/XplT+8K4PVn/5MKoN5kk8YDAPQIFQAIAAKA2ssZANQ7HABQyzEA8CAA3r/yc94A+OOzXwwNgFOmTLE5c+bY+vXrg3n2vXr1sqlTp1aagx/PfrdI86tf/ao988wzwUJN9/GFIx3O1n2YYfr06cFevj179rQHHnjAunbtqjcmPCopAAB6JAQACAACgNrLGQDUOxwAUMsxAPAgAN7z717eAHjDOStCA2C/fv1s4MCB1qNHDystLbUxY8YEX95at26d1a9f+csE99xzj/31r3+1hQsXHhMAHUROmjQpWKzZqVMnmzhxYrCt24YNG6xhw4Z6g8IjoQAA6JEMACAACABqL2cAUO9wAEAtxwDATwYAD83sHTt2WPPmzW3x4sXWp0+fxK9ffvllu/jii+2ll16yli1bHhUAXfXvpJNOshEjRtioUaOCc7j9eFu0aBFUF4cMGaI3KDwAwOrIAQAQAAQAtZczAKj3PACglmMA4EEAvOvfX/CuAN58zjLbsmWLNWrUKJG4OTk55n6OdWzcuDHYf9dVAbt16xaYFxYW2jnnnGNuuNh9ntXt1nG0IeBNmzYFX+ZatWqVde/ePXFJ59u4cWObNWvWsW6D3x9FASqAHukBAAKAAKD2cgYA9Q4HANRyDAA8CIC/eOlcbwAc2WPpYQk7duxYc59FPdrhKncO0tycvaVLPz6Hq9iVlZXZjBkzAvdjAeCKFSusd+/e9s477wSVwPgxePBge+utt+zZZ5/VGxQeVACrIwcAQAAQANRezgCg3vMAgFqOAYDVC4BRKoDDhg2zBQsW2LJly4Kva7njySeftJtuuslWr15tDRo0kABw69atwXBx/Lj22muDyqRbRMIRXQEqgNG1MwAQAAQAtZczAKh3OACglmMA4EEA/PlL51mux5dAivaV2s96LA69CCSe2e4TrPPmzQsWarRv3z6R8G4e3/3332/p6R/H01UD3b/PPffc4JOthx4MAev9heIBACpqHWILAAKAAKD2cgYA9Q4HANRyDAA8CICT/9XXGwBHf/bvoQHQDfs6+HNz+hzMufl/FY93333X3n///Ur/7/TTT7f77rvPLrnkkkqwGDeKLwK54YYbbOTIkcH/LikpCRaXsAhE70sO9QAAPTQEAAFAAFB7OQOAeocDAGo5BgB+MgA4dOjQ4LOq8+fPr7T3n4NRty9gVUdVcwC7dOkSLBIZMGBA4OJAz/3bfcbVQeXkyZMDwGQbGL0vAQD9NUucIQ6AbR4Yb+l5uaHOnPleVii7ikYZxbKLFZ9YJjtlt9gv+xTvOQMzBw8AACAASURBVPZqsIonzdmmP39pg5h8X+U55bJP9s4M2ScmuqSVypewsjz9+XN2ih9pNbPSylt1hbrRcvHbzpmF+n1l6GlpscxQt1/JKD1CO1M1U/PF3WAUaM4q1J+/5OOFnqGdVTgt1bqL4D6iaJaud3+W/aHezspytHwuKymytTNGh66qhQ5EBcP4e2nCv77kXQG87bMvhL5XB3NVHQ7cBg0aFBoA3Xkq+sQ3gp42bVqljaDjK4ujaITPQQWoAHpkAgBoBgBqCQQAai9Mpy4AqOVYAI0AoCxaXQPA8f/8sjcAju35fGgAlAXH4RNXAAD0CAEACACq1QkAEABUuxwqgKpiZlQA8w0A1PMm1TwAQI+IA4AAIACoDZsxBKx3OACgrhkAmG+3BxVAfcpNXO2ifQfsDiqAevIlkQcA6BEsABAABAABQKULUfMlGM79ULnCQVuGgHXN6toQ8K0vXugNgBM/9xxDwHoqJY0HAOgRKgAQAFRf6AwBMwSsdjkAoKoYQ8Bu5e0t/+jnDYBTPv8MAKinX9J4AIAeoQIAAUAAkAqg0oWo+UIFkFXASn452/h7CQBUlUs9ewDQI+YAIACovtCpAFIBVLscKoCqYlQAXQXwZ//4iuV4zAEs3nfAfv75hVQA9fRLGg8A0CNUACAACABSAVS6EDVfqABSAVTyq2IF8KcrvuYNgHf2WgAAqgFIInsA0CNYACAAqL7QqQBSAVS7HCqAqmJUAF0FEADU8ybVPABAj4gDgAAgAEgFUOlC1HyhAkgFUMmvihXAm5Zf7F0B/GXvp6gAqgFIInsA0CNYACAAqL7QqQBSAVS7HCqAqmJUAF0FcMTyr3sD4L29nwQA9fRLGg8A0CNUACAACABSAVS6EDVfqABSAVTyq2IFEABUlUs9ewDQI+YAIACovtCpAFIBVLscKoCqYlQAXQXwx8v6e1cA7//CfCqAevoljQcA6BEqABAABACpACpdiJovVACpACr5VbECeP2yAd4A+OsvzAUA1QAkkT0A6BEsABAAVF/oVACpAKpdDhVAVTEqgK4CCADqeZNqHgCgR8TjAHjl379t2Q2yQ51p454TQ9lVNNr6j1ayT5pWmAnOX5YjX8ZMvFBamQ4A5Vn6w2Tt069j+mUsrVzTLBbhtixdu0ZgXQvPEuGurLSe7hXL0B8m711d6AMN9Xsrz9R8Mgs1e2edu0v3iaJzeol+nZj4/OURcrksQs7k7tSf5UCE6+Ts0XKzrKTI1jwypkaravH30o+WXuZdAXzo3Dk1eq96lPCoTgUAQA81AUADAAFAqQVFARMAUJI4MI6iMwCo63w8A+CQJZd7A+C0Pn8GAPW0SBoPANAjVAAgAEgFUGtAUcAEANQ0BgDNqADm2+DF37Rsj0/Blew7YNPPexwA1Jtf0ngAgB6hAgABQABQa0AAoKYXQ8BmDAFrORN/LwGAmm6paA0AekQdAAQAAUCtAQGAml4AIACoZkz8vfTDxVd4VwD/77w/UQFUA5BE9gCgR7AAQAAQANQaEACo6QUAAoBqxsTfS99f5AAw3OLEqq5Rsq/EZn4RAFT1TyZ7ANAjWgAgAAgAag0IANT0AgABQDVjAEBVsdS1BwA9Yg8AAoAAoNaAAEBNLwAQAFQzJv5euvrvA70rgLP6PsoQsBqAJLIHAD2CBQACgACg1oAAQE0vABAAVDMmynvpSEPAj/T9IwCoBiCJ7AFAj2BFaWhsBK1v0MtG0BGSVNufNriACrMR7irS/nRsA6MrHQW02QdQ1/l43gdQ+UABAKjHvi54AIAeUQQAqQCq0MSXQPQGBwDqmgGAumZ17Usg33nhO95DwLO/NJsKoJ5KSeMBAHqECgAEAAFArQFFARMAUNPYWUfRmQqgrvPxXAEc+LfveQPgo+f/HgDU0yJpPABAj1ABgAAgAKg1oChgAgBqGgOAfAkkPz/frvjblZZd32MbmIIS+9P5jwCAevNLGg8A0CNUACAACABqDQgA1PRy1rm7dJ8oOlMB1HU+niuAAKAez1TzAAA9Ig4AAoAAoNaAooAJFUBNYyqAVABdBfCbf7vKsjwqgAcKSuzx839HBVBvfknjAQB6hAoABAABQK0BAYCaXlQA2QZGzZj4e+ny56/2BsA/f3kWAKgGIInsAUCPYEUBwK82ednuf/N86apb/9FKsnfGaRG2ASnLkS8jX6j+O2lW+CntOnVpG5j0YrOyXO35LV20d+YR4q/CbIS7svJMs3JxWhIVQF3pKKBdG0PA7knKxXwuq6c/f+5O3aeurQIGAPUcSDUPANAj4nEA3P3GKdaoYUaoM80rqB/KrqLRT+deKfuYvt2eZX+gO5VnabcWZT7T/hO1azjrjBLdJ8oLUH3RZhbo91WWp/tE8YiJL+aAMzO1K6WVavbOOj2CT5TrpJXp91Yu/tEU5b70uzJLP6B7qc/irpC3XbtOqd79Wan6B1PEVdAZRdqzOOvsvZpPWUmRvTp9dI1W1eLvpQF//b53BXDuBTNr9F419bCubgUAQA9FAUAzAFBLIABQ0wsA1PUKNAMAZeHqGgD2f+4H3gA4/8LfAoByJiWPAwDoESsAEACkAqg1oCgVMCqAmsYAYLR9EAHAynnmFoEAgHrbSyYPANAjWgAgAAgAag0IANT0impNBVBXrq4B4CXP/dC7AviXC/+PCqCeSknjAQB6hAoABAABQK0BAYCaXlGtAUBduboGgF979hpvAFxw0QwAUE+lpPEAAD1CBQACgACg1oAAQE2vqNYAoK4cAHj4EDAAqOdRMnkAgB7RAgABQABQa0AAoKZXVGsAUFeurgHgV5651rsCuLDf/6MCqKdS0ngAgB6hAgABQABQa0AAoKZXVGsAUFeurgHgRQsHewPgs1+ZDgDqqZQ0HgCgR6gAQAAQANQaEACo6RXVGgDUlatrAHjB00O8AfCvX50WGgCnTJlic+bMsfXr11teXp716tXLpk6dap07d04EY8iQIfb888/b1q1brUGDBgmbLl26HDFggwYNslmzZlX6fc+ePe3FF1/Ug4xHJQUAQI+EAAABQABQa0AAoKZXVGsAUFcOAKysmdsGRgHAfv362cCBA61Hjx5WWlpqY8aMsbVr19q6deusfv2DO4BPnz7dHOy1bdvWdu3aZePGjbM1a9bY5s2bLSOj6o8pOADcvn27zZw5M3GD2dnZ1rRpUz3IeACA1ZUDACAACABqrQkA1PSKag0A6srVNQD88tNDLLO++KmaCrKVFhTb80IF8FDFd+zYYc2bN7fFixdbnz59qgzIK6+8YmeeeaZt3LjROnToUKWNA8APPvjA5s2bpwcVj6MqQAXQI0EAQAAQANQaEACo6RXVGgDUlatrAPilBdd5A+ALX/tN6CHgQxV3UNexY8egCtitW7fDAlJQUGC33nqrzZ8/Pxg2dlW9qg4HgA7+3O8bN25s5513nk2aNCmASw4/BQBAD/0AQAAQANQaEACo6RXVGgDUlQMAK2vmKoAOALds2WKNGjVK/DInJ8fcz9GOWCxm/fv3t927d9vSpUsrmT744IM2cuRIcwDohoOfeuqpI1b/nONjjz0WzBds165dMFR82223BUPMK1euPOZ96FmQWh4AoEe8AUAAEADUGhAAqOkV1RoA1JWrawD4xad+5F0BXHTxQ4cJOXbs2GDu3tGOYcOG2YIFC2zZsmXWunXrSqZ79uyx9957z7Zt22Z33XWXvfPOO7Z8+XLLzc0NFTTn52Dw0UcftcsuuyyUD0ZVKwAAemQGAAgAAoBaAwIANb2iWgOAunJ1DQD7/GWoNwAuueRBuQI4fPjwYMh2yZIl1r59+6MGoqSkxJo0aWIzZsywb3/726GD5oaWr7nmGhs1alRoHwwPVwAA9MgKABAABAC1BgQAanpFtQYAdeUAwMqauSFgB4CuYldxCPhIyrphXwd/c+fOtUWLFgXz/451OAB08/rcsLCb6xfm2Llzp7Vq1SpYUXzVVVeFccHmCAoAgB6pEQfAdlMnWnrI8nXWnnT5irnvyy62r01MdkorT5N9Mgs0l7JwVf7KJ9Vvy9LKtfty1hn7dR/1+Q/k69fI2aX7lEbQubzqOdhHvXjpwd0dQh9pZaFNE4YZxbpPLELO6FcxUzXLjJBjke4rU/fK2a37FJ2o+WRHuEZ5hIWs6SXafTnrAx9PcwvtnLU3tGlgWFZcZK//enRoqNLOftA6/l76wpPDvCuAy77+QOh7HTp0qM2ePTtY1FFx77/8/PxgX8BNmzYF8/kuvPBCa9asWTD06/YJdHMEX3/99cSiDjcv0O0pOGDAANu3b18w3Hz55Zdby5Yt7c0337TRo0fb22+/Hfg0bNgwikT4fKQAAOiRCgCgmQpAAKCecACgrhkAqGsGAOqaHc8A2Hv+9d4AuLz/r0MDYFpa1X91uf37XHXPbf7shm3d4g23OKRFixbB9jC33357JWB054n77N+/3y699FJbvXp1sBWMg8C+ffvahAkTrE2bNnrA8KikAADokRAAIACoAjAVQL3BUQHUNSunAiiLVtcqgLUNgLLgOHziCgCAHiEAAAFAAFBrQAwBa3pFtQYAdeXqGgB+fv5w7wrgP/r/KnQFUFccj09aAQDQIwIAIAAIAGoNCADU9IpqDQDqytU1AOw578feAPjPS+8HAPVUShoPANAjVAAgAAgAag0IANT0imoNAOrK1TUA/Ozcn3gD4L8G3AcA6qmUNB4AoEeoAEAAEADUGhAAqOkV1RoA1JUDACtr5raBAQD1PEomDwDQI1oAIAAIAGoNCADU9IpqDQDqytU1ADxnzgjvCuC/L7uXCqCeSknjAQB6hAoABAABQK0BAYCaXlGtAUBduboGgGf/+QZvAFx5+T0AoJ5KSeMBAHqECgAEAAFArQEBgJpeUa0BQF05APDwIWAAUM+jZPIAAD2iBQACgACg1oAAQE2vqNYAoK5cXQPAs5640TLqR/iMykfSlRUU26pv3E0FUE+lpPGoswDoPkR95513BruOb9u2Lfg+odtRPH64nclnzZpVKVA9e/a0F198MXTwAEAAEAAM3VwCQwBQ0yuqNQCoK1fXALC7A8B6HgBYWGyrAUA9kZLIo84C4MKFC2358uV21llnBd8RrAoAt2/fHnxyJn5kZ2db06ZNQ4cPAAQAAcDQzQUANDO+Bazli7PmW8CaZvH3EgCo6ZaK1nUWACsG031bsCoAdN8WnDdvXuS4A4AAIACoNR8qgJpeUa2pAOrK1bUK4JlP3ORdAXz5G79kCFhPpaTxSGkAdPDnqn6NGze28847zyZNmmTNmzc/YvCKi4vN/cQPB4Dug9Ttpk609NzcUEHP2pMeyq6iUe77sovtaxOTndLKq/6Y99FOpAJQWTiZKl9Svy1LK5cf3zL26z7q8/MtYF1jvgWsawYA6prVNQA84/GbvQHwlW/eBQDqqZQ0HikLgI899pg1aNDA2rVrZ5s3b7bbbrvNSktLgzmDOTlVz5sYN26cjR8//rDgAoDh8x0ADK9V3DJnl+5TGgG0y7MjXKe+5kMFUNMrqjUAqCsHAFbWrKyw2ABAPY+SySNlAfDQILmFIg4GH330UbvsssuqjOGRKoBt7p5g6Xnh3rg5OzLk/EgvkV3sQCO9AphZoJfa5ApYQ/1ZYnrR1NIP6NexCNfJ2qNdJ6aH30obaNdw1hmFuk+U5y9T55jraWlpEXyi5Ext+KSX6XHJ+lD3KcnXfaJ4pJdqXukfD6CEdowyBzCjKPTpE4YHIvRNav9XVlxkG+4dXaNVtfjUpG5/+ql3BfDVK+6s0XvVo4RHdSoAAFZQs2PHjnbNNdfYqFGjQmkcb2gAYCi5AqMonWyUFzMAGD4mCcsIAAwAajoDgJpezhoA1DSLv5e6PuYPgK99CwDU1E8uawDwo3jt3LnTWrVqZdOnT7errroqVBQBQH0RCAAYKrUqGVEB1DWL8kdDbfgAgHosAUBNs/h76bRHR3pXANcN/AUVQE3+pLKuswC4b98+27hxYxCM7t2729133219+/YNtnlxP24+n9sepmXLlvbmm2/a6NGj7e2337bXX3/dGjYMNxYAAAKADAGL/V2E4VyGgEWNzYwhYF2zKH+cHs9DwACgngOp5lFnAXDRokUB8B16XH311fbQQw8Fm0KvXr3a3FYwDgKd7YQJE4JVvWEPABAABADDtpaP7ABAUTAz5gDKkhlzAPPt038c5V0BfP3bU6kA6umXNB51FgBrIwIAIAAIAIotDQAUBQMAGQLWUib+Xuo8+2feALjhOz8HADX5k8oaAPQIFwAIAAKAYgMCAEXBAEAAUEsZAFDTK5WtAUCP6AOAACAAKDYgAFAUDAAEALWUib+XOv3BvwL4xnepAGrqJ5c1AOgRLwAQAAQAxQYEAIqCAYAAoJYy8fdSx987AAy3P21VVygrLLL/fA8A1NRPLmsA0CNeACAACACKDQgAFAUDAAFALWUAQE2vVLYGAD2iDwACgACg2IAAQFEwABAA1FIm/l469ZFbvCuAG6+cwiIQTf6ksgYAPcIFAAKAAKDYgABAUTAAEADUUib+XupQDQD4XwBQEz/JrAFAj4ABgAAgACg2IABQFAwABAC1lAEANb1S2RoA9Ig+AAgAAoBiAwIARcEAQABQS5n4e+mU3432HgLedNVkhoA1+ZPKGgD0CBcACAACgGIDAgBFwQBAAFBLmQQAzqoGALwaANTUTy5rANAjXgAgAAgAig0IABQFAwABQC1lEgD48BhL99gGprywyDYNmkQFUJM/qawBQI9wJVZbjZpsGTnh9lsqradfMKtA94ml6z5pZbpPWZ7mk7NTs3fW5Zm6T1oE0LAoPmnavUV6lnLtGs46lqH7ZH+o+6gehS1VD7OYqLG7Qnqpfp20CD7qVcqzVY9oAFhaP8J19uk+BxpqPpmFmn1U61KxX3LXOZCvdwDpxVpylhcV2eaxo2sUqgDAqFmTen4AoEfMAUAzAFBLIABQ0yuAWe0dG1wAANR1zgIAZdGOZwBsP9O/Arj5+1QA5aRIIgcA0CNYACAAaCKcAIB6gwMAdc2oAOqa1bUK4Mm/vdV7CPjNH0ys0WqlHiU8qlMBANBDTQAQAAQAtQbEELCml7POijA0DwDqOgOAlTVzcwABQD2PkskDAPSIFgAIAAKAWgMCADW9AEBdL+fBHMB8O/n/bvOvAP5wAhXAaCmYFF4AoEeYAEAAEADUGhAAqOkFAOp6AYAfWn5+vrWb4Q+Ab10DAEbLwOTwAgA94gQAAoAAoNaAAEBNLwBQ1wsABACjZU3qeQGAHjEHAAFAAFBrQACgphcAqOsFAH4EgP+vGiqA11IBjJaByeEFAHrECQAEAAFArQEBgJpeAKCuFwB4EADbTr/dew7g24PvYA5gtBRMCi8A0CNMACAACABqDQgA1PQCAHW9AEAAMFrWpJ4XAOgRcwAQAAQAtQYEAGp6AYC6XgBgBQDMC/eFqqpULt9fZFQAo+VfsngBgB6RAgABQABQa0AAoKYXAKjrBQAeBMA208ZauicAbhkyPvQQ8JQpU2zOnDm2fv16y8vLs169etnUqVOtc+fOiSAOGTLEnn/+edu6das1aNAgYdOlS5cjBjoWi9n48eNt+vTptnv3buvZs6c98MAD1rVr12jJgVdCAQDQIxkAQAAQANQaEACo6QUA6noBgB8B4G+qAQCvCw+A/fr1s4EDB1qPHj2stLTUxowZY2vXrrV169ZZ/foHP07tIM7BXtu2bW3Xrl02btw4W7NmjW3evNkyMqr+gLmDyEmTJtnDDz9snTp1sokTJ9qSJUtsw4YN1rCh+DHqaOlUZ70AQI/QAoAAIACoNSAAUNMLANT1AgA/GQA8NFI7duyw5s2b2+LFi61Pnz5VBvKVV16xM8880zZu3GgdOnQ4zMZV/0466SQbMWKEjRo1Kvh9cXGxtWjRIqguuooiR3QFAMDo2hkACAACgFoDAgA1vQBAXS8AMA6A4/yHgK8bF3oI+NBIOajr2LFjUAXs1q3bYYEsKCiwW2+91ebPnx8MG2dnZx9ms2nTpgAMV61aZd27d0/8vn///ta4cWObNWtWtATBK1AAAPRIBAAQAAQAtQYEAGp6AYC6XgDgRwD4UDUA4I/G2ZYtW6xRo0aJQOTk5Jj7OdrhKncO0tycvaVLl1YyffDBB23kyJHmANANBz/11FNVVv+c04oVK6x37972zjvvBJXA+DF48GB766237Nlnn42WIHgBgL45EAfAziMmW0ZOuNVW5Yf/kXPM20g/cEyTwwxK8nWftHLdJ3Of5pNVqNk765II0zyyCvTrpJXqPgc+7hdDOZdXPc3lqL7pZaFO7W2UGUGz/S20y5blxjQHM8vYnyb7pEXQLBYlNmLOZBTJj2KmS2blWRGuE8FF7ZvKwnWTle4kSixL6+kPkxZB55iYmuVFRbZ53OjIVbUwTxV/L7WpJgA89Jpjx44N5u4d7Rg2bJgtWLDAli1bZq1bt65kumfPHnvvvfds27ZtdtdddwVwt3z5csvNPTw54gDoFo20bNkycZ5rr702ANNnnnkmjCTYHEEBKoAeqQEAmgGAWgIBgPpbFgDUcsxZA4C6ZnUOAB+shgrgUL0COHz4cJs3b16wUKN9+/ZHDURJSYk1adLEZsyYYd/+9rcPs2UIWM9jxQMAVNQ6xBYABACpAGoNiAqgpldgrTMzAEgF0No8MN5/DuCwsaGrlW7Y18Hf3LlzbdGiRcH8v2MdDgDdXD43LDxo0KDDzOOLQG644YZg2NgdzsctLmERyLHUPfbvAcBja3RECwAQAAQAtQYEAGp6AYBmDAFrOZMYAq5lABw6dKjNnj07WNRRce8/tyeh2xfQVfMee+wxu/DCC61Zs2bB0K+DODdH8PXXXw+gzh1uXqDbU3DAgAHBv52N+/fMmTMDqJw8eXIAmGwDo+VFVdYAoIeGACAACABqDQgA1PQCAAFANWPi76XWv/avAP7v+vAVwLS0qidEOnBz1T03j++aa66xlStXBotD3FYubnuY22+/vRIwuvPEfYIC+EcbQU+bNq3SRtBVrSxWtUp1ewDQIwMAQAAQANQaEACo6QUAAoBqxiQA8FfVAIDDwwOgep/Yf/IKAIAeMQAAAUAAUGtAAKCmFwAIAKoZAwCqiqWuPQDoEXsAEAAEALUGBABqegGAAKCaMQkAvP8O70Ug//vx7aEXgaj3if0nrwAA6BEDABAABAC1BgQAanoBgACgmjGJRSD3+QPglp8AgKr+yWQPAHpECwAEAAFArQEBgJpeACAAqGZMAgDvrQYAHAEAqvonkz0A6BEtABAABAC1BgQAanoBgACgmjEAoKpY6toDgB6xBwABQABQa0AAoKYXAAgAqhmTAMB7JnjPAdxyw23MAVQDkET2AKBHsABAABAA1BoQAKjpBQACgGrGJADw7moAwBsBQFX/ZLIHAD2iBQACgACg1oAAQE0vABAAVDMGAFQVS117ANAj9gAgAAgAag0IANT0AgABQDVjEgD4y2qoAN5EBVDVP5nsAUCPaAGAACAAqDUgAFDTCwAEANWMSQDgXdUAgDcDgKr+yWQPAHpEK97QThk72dJzc0OdKa00lFklo8wi3aeoWUx2Si+RXWSHnF1Vfy/yaCcqzZMvY7GMCD7puk/OLs2nLFyaVDppWpl2DWddnqX7lDTRcyaWoflk7tNFjukullauP38sU3sW/Qpm5Zm6V/Yevc3oVzEry9G90sX+LOtD/Rrl2bXjU3yCnjRqPpcXFdmm8aNrdGEFAKjnS6p6AIAekQcAdfEAQF0zADCCZvq73ABAXWcAUPvrpFYB8M6J/quAf3prjcKqnnF4VKcCAKCHmgCgLh4AqGsGAEbQDACURaMCqCfN8VwBbPsLfwB8eyQAKDekJHIAAD2CBQDq4gGAumYAYATN9Hc5FUCGgOVEAwBlyXA4jhQAAD2CAQDq4gGAumYAYATNAEBZNCqAetIc1wA4tRoqgKOoAMoNKYkcAECPYAGAungAoK4ZABhBM/1dTgWQCqCcaACgLBkOx5ECAKBHMABAXTwAUNcMAIygGQAoi0YFUE+a4xkA27kKYMjdKapKFrdg5S0qgHI7SiYHANAjWgCgLh4AqGsGAEbQTH+XUwGkAignGgAoS4bDcaQAAOgRDABQFw8A1DUDACNoBgDKolEB1JPmuAbAn0/yrwD+bAzbwMgtKXkcAECPWAGAungAoK4ZABhBM/1dTgWQCqCcaMc1AE6pBgC8BQCUkyKJHABAj2ABgLp4AKCuGQAYQTMAUBaNCqCeNACgnGY4HEcKAIAewQAAdfEAQF0zADCCZvq7nAogFUA50Y5rAJxcDRXA0VQA5aRIIgcA0CNYAKAuHgCoawYARtAMAJRFowKoJ83xDIAnT/IHwDfHAIByQ0oiBwDQI1gAoC4eAKhrBgBG0Ex/l1MBpAIoJxoAKEuGw3GkAADoEQwAUBcPANQ1AwAjaAYAyqJRAdST5rgGwInVUAG8lQqg3JCSyAEA9AgWAKiLBwDqmgGAETTT3+VUAKkAyol2XAPghGoAwNsAQDkpksgBAPQIVgIAb51sGSF3XC/P0i+YfkD3KTkpilO6fKH04jTJp/6b+jWKT5QuERinF+s+GRF8yrO166SVavbBs0TwOdBQv05MC+VBncu068T08Ft5pnYNZ12eHdOdInio18n6UBcgimYZJfrDlIm57K6g/nESixDLKHlZnqf/BZBRqMempJnWz5bvL7L/DR9bo3vrxd9LJwOAeiNIMQ8A0CPgAKADLY0aAEA94QBAXTMVzPQrHPRQrwMA6koDgJpm8fdS+zv8K4Cbb6cCqKmfXNYAoEe8AEAAkAqg1oCiVLOoAGoaO2sqgFQA24+f7P0lkM1jR9dotVLPbDyqUwEA0ENNABAABAC1BgQA6sOMUTQDAAHA9uOqAQDHAYBaD5dc1gCgR7wA3NfhmAAAIABJREFUQAAQANQaUBSYoQKoaUwF0Iw5gPkGAOrtJtU8AECPiAOAACAAqDUgAJAKoJYxZswB1BSLsjtFVVcoLyqyTeOpAGrqJ5c1AOgRLwAQAAQAtQYEAAKAWsYAgKpeiffS7f5DwJvuAABV/ZPJHgD0iBYACAACgFoDAgABQC1jAEBVLwBQVSx17QFAj9gDgAAgAKg1IAAQANQyBgBU9Uq8l24Lvz9tVdcoc0PAE6gAqvonkz0A6BEtABAABAC1BgQAAoBaxgCAql5R3ktHBMCJAKCqfzLZA4Ae0YrS0PgSiP4C5EsgepLyJRC+BKJmDV8C0fum4/lLIKcIX6gCANXWUjfs6ywALlmyxO68805buXKlbdu2zebOnWuXXnppImqxWMzGjx9v06dPt927d1vPnj3tgQcesK5du4aOLABIBZAKYOjmEhhSAdQhI4pm7APIPoCnjKmGIeBJVAC1Hi65rOssAC5cuNCWL19uZ511ll1++eWHAeDUqVNt0qRJ9vDDD1unTp1s4sSJ5qBxw4YN1rBhuA+pAoAAIACodXhRYIZ9ADWNnTUACAB2GO0PgP+dDADqrS95POosAFYMQVpaWiUAdNW/k046yUaMGGGjRo0KTIuLi61FixbmwHDIkCGhIggAAoAAYKim8nHlXS+AGQCoaQwAshF0fn6+AYB6u0k1j5QEwE2bNlmHDh1s1apV1r1790TM+/fvb40bN7ZZs2aFygMAEAAEAEM1FQDwIwWyPtQJOErVlAogFcDaBsApU6bYnDlzbP369ZaXl2e9evUKCiqdO3cOsn/Xrl02duxYe+6552zLli124oknBtOyJkyYYA5Yj3QMGjTosHeym7L14osvap0P1ocpkJIAuGLFCuvdu7e98847QSUwfgwePNjeeuste/bZZ6tMFVcldD/xwwFgmzZtTJlsyyIQ/QXIIhC952IRCItA1KxhEYjeNx3Pi0A63FINQ8BTwg8B9+vXzwYOHGg9evSw0tJSGzNmjK1du9bWrVtn9evXt1dffTUAQAd0p512WvCuve666+yMM86wJ5544qgAuH37dps5c2bCJjs725o2baqmOPaHKJDSALh161Zr2bJlQpJrr702+MvkmWeeqTJRxo0bFywcOfRoN2WSpefm1lhyZexPk8994IRS2Se9IEP3ES8T5VlK6+kv86wCXbMocJ4mPn+Ua5Q0PyDHJS1T1yxvY7Z8nbIczSWWqdk769L6ejUns0B/mZfl6JqpT5Neoudlepl6FYs2bJ6r66zeWfZuPS7FJ+j3FUuPEMsIbSatvtYBlBcW2duD77A9e/ZYo0aNVPlC2cdHpk79mT8Abvx5eAA89OZ27NhhzZs3t8WLF1ufPn2qvPfHH3/cvve971lBQYFlZlbdOThg/OCDD2zevHmhnh+j8AqkJABGHQI+UgUQAAyfcABgeK3ilgCgDgAAoJ5n5QCgLFoqAKArilSE1ZycHHM/xzo2btxoHTt2DKqA3bp1q9J8xowZdsstt5iDxSMdDgAd/Lmqn5uidd555wULOB1ccvgpkJIAGF8EcsMNN9jIkSMDBUtKSoKEirIIBAAMn4QAYHitAMCDClAB1HMm0sIZAFAW+rgHwJzoI1NlxUXmKoCHHm4Y142GHe1w71g3p95tsbZ06dIqTXfu3Bns0nHllVcGu3Ac6XjsscesQYMG1q5dO9u8ebPddtttwRCz2+ItDIjKQU0hhzoLgPv27TP3F4g73EKPu+++2/r27RvMG2jbtm0Aem7SqptX4P5KmTx5si1atCjSNjAAYPgWAwCG1woABACdAgwB6xVghoDz7dRRky3DFwCnjg6mRakVwGHDhtmCBQts2bJl1rp168M6PTdMfeGFF1qTJk3sySeftKysrNAdo9vX18Hgo48+apdddlloPwwPV6DOAqCDOQd8hx5XX311sPdffCPoadOmVdoI+kil6qqSJz7XAgAM37QAwPBaAYAAIABoxhxArc9IzAGsJgBU5ysOHz48GLJ1++q2b9/+sJvfu3evXXTRRVavXj176qmnLDfC/HlXtLnmmmsS27hpCmEdV6DOAmBthBgANEvX5kAbAKhnJnMA9QoQcwD1PGMOoL5w5HgeAu440r8C+J9fhF8E4ooqDv7cV7dcAcZB2qGHe2c6+HNDt08//XQAgerhho5btWoVfMXrqquuUt2xr6AAAOiRDgAgAMgqYK0BsQqYVcBaxlABVPWKv5c6/rQaAPDO8AA4dOhQmz17ts2fPz+x95+7d7fHn9sX0FX+LrjgAissLAwg0W0NEz+aNWtmGRkHd6Ho0qVLMD1rwIAB5qZyufmG7mtebseON99800aPHm1vv/22vf7666G/2qVqmCr2AKBHpAFAABAA1BoQAAgAahkDAKp6fVIA6L64VdXh5tm7lbxHmpblfNzijpNPPjlwd+eJ++zfvz/YLHr16tXBVjAOAt3ULrd5tNuDl8NPAQDQQz8AEAAEALUGBAACgFrGAICqXvH3Uqeb/SuAb9wVvgKo3if2n7wCAKBHDABAABAA1BoQAAgAahkDAKp6JQDwpmoAwF8CgKr+yWQPAHpECwAEAAFArQEBgACgljEAoKoXAKgqlrr2AKBH7AFAABAA1BoQAAgAahkDAKp6JQDwxmqoAN5NBVDVP5nsAUCPaAGAACAAqDUgABAA1DIGAFT1ir+XOt/gD4Ab7gEAVf2TyR4A9IgWAAgAAoBaAwIAAUAtYwBAVa8EAI6oBgC8FwBU9U8mewDQI1oAIAAIAGoNCAAEALWMAQBVvQBAVbHUtQcAPWIPAAKAAKDWgABAAFDLGABQ1SsBgD+phgrgfVQAVf2TyR4A9IhWvKG1eWC8peflhjpTeo747TQzK9+dE+rcFY1iuWWyT+YHmbJP7ODm7aGPzEL9BWj6F5pC309FwzT9i2NWmqfdXFm+HhfLinBjhWJgzCznfd3nQCPt+WMZmr2LT/YH6XI81ftyF4il6/em3ljWHv1Zyurp9xWL0MzSD+hOZXlabqaXRLhGrv78FiHPYhHaWX7zfVIKlBUW27qBvzD1+7rKReLvpS4/9gfA9fcDgIr2yWYLAHpEDAA0AwC1lxMAqOkFAJoBgHrOAID5BgB6vNxTxBUA9Ag0AAgAUgHUXs5UAKkAql1uGRVASbJEBXB4NVQAf0UFUBI/yYwBQI+AAYAAIAAIACpdCEPADAHX1hDwp6/3B8DXfw0AKu072WwBQI+IAYAAIAAIACpdCAAIAAKASovBtiYVAAA91AUAAUAAEABUuhAAEACsNQAcVg0VwAeoACrtO9lsAUCPiAGAACAACAAqXQgACADWGgAOrQYAfBAAVNp3stkCgB4RAwABQAAQAFS6EAAQAAQAlRaDbU0qAAB6qAsAAoAAIACodCEAIABYWwB4WjVUANdRAVSad9LZAoAeIQMAAUAAEABUuhAAEACsNQD8kf8Q8LqHGAJW2ney2QKAHhEDAAFAABAAVLoQABAArC0A7HqdPwC+9hsAUGnfyWYLAHpEDAAEAAFAAFDpQgBAABAAVFoMtjWpAADooS4ACAACgACg0oUAgABgrQHgkGqoAE6jAqi072SzBQA9IgYAAoAAIACodCEAIABYqwCYnaukZyXbspIiew0AjKxfMjgCgB5RAgABQAAQAFS6EAAQAAQAlRaDbU0qAAB6qAsAAoAAIACodCEAIABYWwDYbfBky/CsAL46nSFgpX0nmy0A6BGxOAB2nv0zy6iXE+pMbZvsDmVX0Wj7voayz77CcPdT8cQl7+XJ17F0zSXzwwzNIaJ1Wb1y2TOtTH85lWeKAJSj31f6flFkM0sr158l7YAsmcWyRJ80TS939vIIKZOmy2yxDP3eMvdqN1fasEwULGIsozy/njIWy9UulF6g6RXEv56uWVaTYlnnKA718rTrlBUW22vfutP27NljjRo1inLJY/rE30vdrq0GAPx/AOAxBU9iAwDQI3gAoBkAqEFDDACUWxwAqJNZJADWLwMAAoBye8bh+FEAAPSIBQAIAFIBFBsQFUBRMCqAVAC1lIm/l06/xr8CuHYGFUBN/eSyBgA94gUAAoAAoNiAAEBRMAAQANRSJgGAP6wGAPw/AFBTP7msAUCPeAGAACAAKDYgAFAUDAAEALWUAQA1vVLZGgD0iD4ACAACgGIDAgBFwQBAAFBLmfh76Ywf+FcAX/ktFUBN/eSyBgA94gUAAoAAoNiAAEBRMAAQANRSJgGA368GAJwJAGrqJ5c1AOgRLwAQAAQAxQYEAIqCAYAAoJYyCQAcVA0A+DAAqKmfXNYAoEe8AEAAEAAUGxAAKAoGAAKAWsoAgJpeqWwNAHpEHwAEAAFAsQEBgKJgACAAqKVM/L105tX+FcCXZ1EB1NRPLmsA0CNeACAACACKDQgAFAUDAAFALWUSAHhVNQDg7wBATf3ksgYAPeIFAAKAAKDYgABAUTAAEADUUgYA1PRKZWsA0CP6ACAACACKDQgAFAUDAAFALWXi76XPXDnJMrJzNecK1mUlRbbmkTE1+t3iyDeHY7UoAAB6yAgAAoAAoNiAAEBRMAAQANRSJgGA36sGAPw9AKipn1zWAKBHvABAABAAFBsQACgKBgACgFrKAICaXqlsDQB6RB8ABAABQLEBAYCiYAAgAKilTPy91P27/hXA1X+gAqipn1zWAKBHvOIN7Zt/u8qy6meHOtN/djcLZVfRqKA43Lkr+pSXp8nX2f9BnuyT9W6W5FOWG5PsnXEsS/cpzy2Xr5N2QNcsvSRduk5Zw1LJ3hmnF2TIPrXlEMsRdT6g6RU8R7oe/7RSPZZR8iyWrT1/2n49lmnaJQLJYo30PLMIcJ62R2v/cr6YWXbTIjmdSwq1+zp4AT1nsuuVSPdWVlhkm66eXKPz6hIA+J1qAMDZAKAU4CQzBgA9AgYAmgGAGtAAgJpeAKCrAOqdFAAIAHavZQCcMmWKzZkzx9avX295eXnWq1cvmzp1qnXu3DlI4F27dtnYsWPtueeesy1bttiJJ55ol156qU2YMMHy8/OPmOSxWMzGjx9v06dPt927d1vPnj3tgQcesK5du+oNA49KCgCAHgkBAAKAVABFOqECKPc4ACAVQCVp4u+ls77tXwFc9cfwFcB+/frZwIEDrUePHlZaWmpjxoyxtWvX2rp166x+/fr26quvBgA4aNAgO+200+ytt96y6667zs444wx74oknjviIDiInTZpkDz/8sHXq1MkmTpxoS5YssQ0bNljDhg0VabA9RAEA0CMlAEAAEAAEAJUuhCFgMV8YAlbSK7BNAODAagDAR8MD4KE3umPHDmvevLktXrzY+vTpU+VzPP744/a9733PCgoKLDMz8zAbV/076aSTbMSIETZq1Kjg98XFxdaiRYugujhkyBBZHxw+VgAA9MgGABAABADFFzoVQLnHoQJIBVBJmvh76exv+QPgysfGBMO1jRo1StxCTk6OuZ9jHRs3brSOHTsGVcBu3bpVaT5jxgy75ZZbzMFiVcemTZusQ4cOtmrVKuvevXvCpH///ta4cWObNWvWsW6D3x9FAQDQIz0AQAAQAAQAlS6ECqCYL1QAlfSqVAGsLgA89AbcMO64ceOOel+ucucgzc3ZW7p0aZW2O3futLPOOsuuvPLKYFi3qmPFihXWu3dve+edd4JKYPwYPHhwMIT87LPPyvrgQAWwWnIAAAQAAUDxhU4FUO57qABSAVSSJlEBvKIaKoB/ilYBHDZsmC1YsMCWLVtmrVu3Puz23T1eeOGF1qRJE3vyySctK6vqRTtxANy6dau1bNkycZ5rr702qEw+88wzijTYHqIAFUCPlAAAAUAAEABUuhAqgGK+UAFU0qtyBfCKSZaZFf1TcKUHimzln/Q5gMOHD7d58+YFCzXat29/2P3v3bvXLrroIqtXr5499dRTlpt75HtkCFgOv+QAAEpyVTYGAAFAAFB8oVMBlHscKoBUAJWkqVgBrE0AdMO+Dv7mzp1rixYtCub/HXq4e3Pw5+YQPv300wEEHu2ILwK54YYbbOTIkYFpSUlJsLiERSBKVlRtCwB6aAgAAoAAIACodCFUAMV8oQKopFflCuA3J/pXAB+/NfSm1UOHDrXZs2fb/PnzE3v/uRtye/y5fQFd5e+CCy6wwsLCABLd1jDxo1mzZpaRcXCT9C5dupjbU3DAgAHBvx3ouX/PnDkzgMrJkycHgMk2MHJqHOYAAHpoCAACgACg+EKnAij3OFQAqQAqSRN/L53zDX8A/PcT4QEwLa3qL6k4cHN7/zlo69u3b5WPsnnzZjv55JOD37nzxH3cv+MbQU+bNq3SRtBHWlmsaJXqtgCgRwYAgAAgAAgAKl0IFUAxX6gAKulVqQJY2wAo3ygOn7gCAKBHCABAABAAFF/oVADlHocKIBVAJWkSFcDLq6EC+OfwFUDlHrE9PhQAAD3iAAACgAAgAKh0IVQAxXyhAqikV6UKYI8B/gD40lwAUA5AEjkAgB7BAgABQABQfKFTAZR7HCqAVACVpIm/lwBARbXUtAUAPeIOAAKAACAAqHQhVADFfKECqKRX5QrgpdVQAZxHBVAOQBI5AIAewYoD4KmP3GIZ9cJtuNmxWdXfPDzabTTO3i/fZblVvSLraCdavqGDfB2LaddJ31X1ju9Hu3CsebF+XxE80tJjslf5B9mSTyxbfwGqGgc3FOFZosBJLK9Men4r1/LFnTwtimYRZNYe5CNrMf+t8OBWF8qRUaxrVlZfFyCWpfsozxHEMlO/Rna9A+plLKbGxcwyMvR7a1RPq06WFRTbqm/cHXprFfnBzSz+Xvpsf38A/Nd8ADBKDJLFBwD0iBQA6Nboay8nAFB/yagaA4BmFkHmSF2BmP8AoB4YAFDLzAQAfn2C9z6A/3rythqFVe3JsK5uBQBAD0UBQACQCiAVQKkLoQIoyeWMAUBNMgBQ0yuVrQFAj+gDgAAgAAgASl0IACjJBQDKciWGgHte4l8B/OdfqADqEUgeDwDQI1YAIAAIAAKAUhcCAEpyAYCyXB8D4MXVAIBPAYB6BJLHAwD0iBUACAACgACg1IUAgJJcAKAsFwCoS5ayHgCgR+gBQAAQAAQApS4EAJTkAgBluRIA+Lmv+VcAX1xABVCPQPJ4AIAesQIAAUAAEACUuhAAUJILAJTl+hgAv3qH9yrgF5++nVXAegiSxgMA9AgVAAgAAoAAoNSFAICSXACgLBcAqEuWsh4AoEfoAUAAEAAEAKUuBACU5AIAZbkSAPj5r/hXAP+xkAqgHoHk8QAAPWIFAAKAACAAKHUhAKAkFwAoy/UxAParBgB8BgDUI5A8HikLgOPGjbPx48dXilSLFi3s3XffDR09ABAABAABwNAdhjMEACW5AEBZLgBQlyxlPVIaAJ944gl7/vnnE8HPyMiwZs2ahU4GABAABAABwNAdBgDIt4Br8VvAvS7yrwCueJYKoNS+k8w4pQFw3rx5tmbNmsghAwABQAAQAJQ6ECqAklxUAGW5EhXAXheM914FvOKvY1kFrIcgaTxSGgDvvPNOy8/Pt5ycHOvZs6dNnjzZTjnllNDBAwABQAAQAAzdYVABpAJYmxXAL1cDAD4PAErtO8mMUxYAFy5caIWFhdapUyfbvn27TZw40davX2+vvfaanXDCCVWGsbi42NxP/HAA2KZNGzv1kVsso15uqNB3bLYjlF1Fo8bZ+2WfckuTfZZv6CD7WEy7TvquLPkaseYfay47Cw5p6THB+qApAAgASklDBVCSiwqgLNfHFUAAUBcvxTxSFgAPjXNBQYF16NDBRo4caTfeeGOVaVDVwhFn2Hv+9ZZZPydU6hSXZYayq2iUkV4u+7RvuEv22fRh1eB7tBN9UJgnXadgVz3J3hln5JXKPjFdMivbHyE2BRnSvZU3PiDZB8ZF2jUCHxHMnUvaAQ3mg8vUFwGwJF1//gjxt0I9lmkN9djEyjTNYiV6LNPEawQC54hxcfHP0htNrEyMZxQAbqL/AZiWpv8x16RhoZybn2qwV/I5UFBiz35leo0Oq8ZHpno7AMwMV5io6iFKS4tsORVAKb7JZgwAVojYBRdcYKeeeqo99NBDVcbxSBVAADB82gOAOmQAgPofAAAgABi+VzpoWecA8Pxx/gD4t3E1CqtqjLCvXgUAwI/0dHDnKoCDBw+222+/PZTKib+0qACG0ssZAYAAYOhkiRtSAZQlowJIBbA3AKi3mxTzSFkAvPnmm+2SSy6xtm3b2nvvvRfMAVy8eLGtXbvW2rVrFyoNAEAzhoC1IT2GgMUhQ9cSAcBQ/VElI4aAZc3qWgXwC1/yrwAue4EKoJxISeSQsgA4cOBAW7Jkib3//vvB3n+f+9znbMKECXbaaaeFDh8ACABmMAcwdHsJDJkDqOnl5uYxB1DXjDmA9oW+1QCAfwcA5eRLIoeUBcDqiBEACAACgOJcMwBQ7noAQBaBKEkTfy8BgIpqqWkLAHrEHQAEAAFAAFDpQlgFrE2ZcNpmsApYSbHENjDnfnGs9yKQpYvGswhEUj+5jAFAj3gBgAAgAAgAKl0IAAgA1tY2MOf2qQYAXAIAKu072WwBQI+IAYAAIAAIACpdCAAIAAKASovBtiYVAAA91AUAAUAAEABUuhAAEACsLQDsc+7t3kPAS5bewRCw0sCTzBYA9AgYAAgAAoAAoNKFAIAAYK0B4BeqAQCXAYBK+042WwDQI2IAIAAIAAKAShcCAAKAtQaAvW/zrwAun0AFUGngSWYLAHoEDAAEAAFAAFDpQgBAABAAVFoMtjWpAADooS4ACAACgACg0oUAgABgbQHgeb38K4CLV1ABVNp3stkCgB4RAwABQAAQAFS6EAAQAKw1APz8rd5DwIv/MZEhYKWBJ5ktAOgRMAAQAAQAAUClCwEAAUAAUGkx2NakAgCgh7pxAGw34zZLr5cb6kx59UpC2VU0isVkF/tC682y0+odrWSfUxrvknxefK2DZO+Mc5vul32K94SLR6UTF6fL11EdYtnlqoulZ4uQZWblRZnydSJ8PtUsS3yeNPm2zKLcWITr5NbX22ZRQbb0QGkRnqW8RIemnEb659OkB/nI+ICaZxHi0uyEvfKtfVCQJ/vUy9Xjr16krLDYXr3izhqtqsXfS1/s6V8BXPRPKoBqjJPJHgD0iBYAaAYAagkEAGp6BdYRoMkigAYAqMcGANQ0q1UA/OwY7yHgRf+aVKOwqqmHdXUrAAB6KAoAAoBq+gCAqmIAIBVAKoBKq0lUAAFARbaUtAUAPcIOAAKAavoAgKpiACAACAAqrSYBgD2qoQL4UvgK4JQpU2zOnDm2fv16y8vLs169etnUqVOtc+fOidufPn26zZ4921atWmV79+613bt3W+PGjY/6eOPGjbPx48dXsmnRooW9++67iizYVqEAAOiRFgAgAKimDwCoKgYAAoAAoNJq4u+lvueM9h4C/vu/J4ceAu7Xr58NHDjQevToYaWlpTZmzBhbu3atrVu3zurXrx88wr333mtFRUXBf99yyy2hAfCJJ56w559/PiFDRkaGNWvWTJEFWwCwenMAAAQA1YwCAFXFAEAAEABUWs0nBYCH3uOOHTusefPmtnjxYuvTp0+lXy9atMj69u0bGgDnzZtna9asUWTANoQCVABDiHQkEwAQAFTTBwBUFQMAAUAAUGk1CQA8+xb/CuDKKaErgIfe48aNG61jx45BFbBbt25eAHjnnXdafn6+5eTkWM+ePW3y5Ml2yimnKLJgSwWwenMAAAQA1YwCAFXFAEAAEABUWk0CAM+6xTIzImyH9dHFSsuK7O+rptiWLVusUaNGiVtwEOZ+jnbEYjHr379/UOFbunTpYaZKBXDhwoVWWFhonTp1su3bt9vEiRODeYavvfaanXDCCYo02B6iABVAj5QAAAFANX0AQFUxABAABACVVhN/L32p+8+8AfCF1T8/7NJjx441tzDjaMewYcNswYIFtmzZMmvdurUXAB7qXFBQYB06dLCRI0fajTfeqEiDLQBYfTkAAAKAajYBgKpiACAACAAqraa6AVCtAA4fPtzcnL0lS5ZY+/btq7x1pQJY1QkuuOACO/XUU+2hhx5SpMEWAKy+HAAAAUA1mwBAVTEAEAAEAJVWkwDAz7gK4NGHao923tKyYnthzc9DzwF0w74O/ubOnWsO8Nz8vyMdPgBYXFwcVAAHDx5st99+uyINtgBg9eUAAAgAqtkEAKqKAYAAIACotJoEAJ45yh8AX54aGgCHDh0a7PE3f/78Snv/ucUbbl9Ad7i9+9zPv//9b7v22muDKmHDhg2tbdu21rRp08Dm/PPPtwEDBtj1118f/Pvmm2+2Sy65JLB57733gjmAbmWxW1zSrl07RRpsAcDqywEAEABUswkAVBUDAAFAAFBpNZ8UAKalVf39xZkzZ9qgQYOCR6hqU2f3/yvanHzyyYF9fJ6h21vQgeL7778f7P33uc99ziZMmGCnnXaaIgu2VSjAIhCPtAAAAUA1fQBAVTEAEAAEAJVWkwDA06uhArg2fAVQuUdsjw8FAECPOACAAKCaPgCgqhgACAACgEqrib+Xzu820nsI+G+v/iL0ELByj9geHwoAgB5xAAABQDV9AEBVMQAQAAQAlVYDACpqpbYtAOgR/3hDa33/HZaeF3LDzbSYfMW8Jge/nagcJzQsUMwD27LydNknL6tE8nln19E//F3VyRo32C9dwxl/sO/gpGPlKNmp+8SyypVLWHpOmWTvjGMlGbKPHah6Ps7RTpTVpFi+Tql6b3r6W2YEzQ7sy5afJbuh/vwl+7Ok62Tllkr2zvjA/kzZJyOCZhbTcyYtXcv/enlaf+EePD1dT5oOTXbKmq3f0Vz2iYm3VlZYbG98N/zKWvmGzCwBgF1/6l8BfO1OKoBRgpAkPgCgR6AAQDMAUHsBAoB6gwMAAUA1awDAfDv/tJv9AXA1CDK7AAAVZ0lEQVTdXQCgmnxJZA8AegQLAAQAqQCK1UmxYuKaJwAIAKrdNACYb+d/+iZ/AHz9lwCgmnxJZA8AegQLAAQAAUAAUOlCGAJmCLjWhoABQKVppqQtAOgRdgAQAAQAAUClCwEAAcBaA8DO1VAB3EAFUGnfyWYLAHpEDAAEAAFAAFDpQgBAALC2APDLnW70HgJ+/o27GQJWGniS2QKAHgEDAAFAABAAVLoQABAABACVFoNtTSoAAHqoCwACgAAgAKh0IQAgAFhrANjxBv8K4H/uoQKoNPAkswUAPQIGAAKAACAAqHQhACAAWGsA2GGEPwD+914AUGngSWYLAHoEDAAEAAFAAFDpQgBAABAAVFoMtjWpAADooS4ACAACgACg0oUAgABgrQHgKT/xrwBuuo8KoNLAk8wWAPQIGAAIAAKAAKDShQCAAGDtAeCPLTM9R0nPSral5cX2/Kb7AcDICh7/jgCgR4wAQAAQAAQAlS4EAAQAAUClxWBbkwoAgB7qAoAAIAAIACpdCAAIANYaALYf7l8B3PwrKoBKA08yWwDQI2AAIAAIAAKAShcCAAKAtQaA7a73B8C3fg0AKg08yWwBQI+AAYAAIAAIACpdCAAIANYaALYd6g+Abz8IACoNPMlsAUCPgAGAACAACAAqXQgACAACgEqLwbYmFQAAPdSNA2Dnn0y2jJzcUGcqOLU0lF0lowNpsk/7Lttknz1FebJPfu5+yWf3/nqSvTPOSi+TfXZ+0ED2SUuPyT5l+zMln7SscsneGcdK02Wf7Pr6i/ZAkfYswb2Va/eWlq4/f3oEzRo2KJI121egr5gsO6ABcHqm/vyxMr39yw9vZlHu7cT8AulShSVZkr0zzsnU+8ziUj2X2zXeLd9bboZ2bwcKSmz+hb+t0apa/L305TY/8q8AbnmoRu9VFhyHalUAAPSQEwA0AwC1Fw0AqAMQAAgAqt00AJhvX251nT8AvvMbAFBNviSyBwA9ggUAAoBUAKkAKl1IlCobFUCtyubiAQACgEq7TFVbANAj8gAgAAgAAoBKFwIAMgRca0PAJw3xrwBunUYFUGngSWYLAHoEDAAEAAFAAFDpQgBAALDWALClA8BsJT0r2ZaWl9jz2wDAyAImgSMA6BEkABAABAABQKULAQABQABQaTHY1qQCAKCHugAgAAgAAoBKFwIAAoC1BoCfGuxfAXx3OkPASgNPMlsA0CNgACAACAACgEoXAgACgLUGgM2v8QfA92YAgEoDTzJbANAjYAAgAAgAAoBKFwIAAoAAoNJisK1JBQBAD3UBQAAQAAQAlS4EAAQAaw0Am/3QvwK44/+oACoNPMlsAUCPgAGAACAACAAqXQgACADWGgCe+AN/AHy/Zr9aorQdbKtfAQDQQ1MAEAAEAAFApQsBAAHAWgPApt/3B8BdM6kAKg08yWwBQI+AAYAAIAAIACpdCAAIAAKASovBtiYVAAA91AUAAUAAEABUuhAAEACsLQA8v8nV3hXAv+2eRQVQaeBJZgsAegQMAAQAAUAAUOlCAEAAsNYAsPFVlpnm8SWQWIn97YPfAYBKA08yWwDQI2AAIAAIAAKAShcCAAKAAKDSYrCtSQUAQA914wDY5q4Jlp6XG+pMmQXaC9OdtPTE0lDnrmh0duc3ZZ/X3v2U7NMwr0jyycwol+ydcePc/bLPG9uayz6xsjTZp7w4U/LJqHdAsnfGmVllsk8spj9L8e5wOVzxZpq0/FC6t/S0mGTvjPftz5F90iJcJ4pmudlaPPft0zXOydWu4cQqK9P7mbLSDFnnzGytbyqPcF8Xd3xVvq83PtTbv3wRM9u2r5HkVlZYbK98864ararF30vn51/pXwHc80iN3qskHsbVrgAA6CEpAGgGAAKAShMCAAFAJV+cLQCoKZYAwIbf9QfAvX8AADX5k8oaAPQIFwAIAFIBpAKodCFUAPXKJACoZJgZAKjplcrWAKBH9AFAABAABACVLgQABABrbQi4wXf8K4D7ZlMBVBp4ktkCgB4BAwABQAAQAFS6EAAQAKwtAPxSvYHeAPhC4aMAoNLAk8wWAPQIGAAIAAKAAKDShQCAAGBdBcApU6bYnDlzbP369ZaXl2e9evWyqVOnWufOnRNNZPr06TZ79mxbtWqV7d2713bv3m2NGzc+ZhN68MEH7c4777Rt27ZZ165d7d5777Vzzz33mH4YHF0BANAjQwBAABAABACVLgQABABrDQDzvuVfAdz/WOgKYL9+/WzgwIHWo0cPKy0ttTFjxtjatWtt3bp1Vr9+/aCZOHArKjq4c8Qtt9wSCgAfe+wxu/LKK81BYO/evW3atGk2Y8aM4Lxt27ZVmh+2hygAAHqkBAAIAAKAAKDShQCAAGCtAWDOFf4AWPyn0AB4aDvYsWOHNW/e3BYvXmx9+vSp9OtFixZZ3759QwFgz5497ayzzrKHHnoocY5Pf/rTdumll5qrOnJEVwAAjK5dYrUV+wCGF5F9APU93dgHkH0Aw7ewg5bsA8g+gF/K/qZlpukbb8dzrTR2wF4oeTwyAG7cuNE6duwYVAG7desWCQBLSkqsXr169vjjj9uAAQMS5/jJT35ia9asCeCSI7oCAGB07QBAowJIBZAKoNKFUAGkAlhrFcBqAsAtW7ZYo0Yfb3idk5Nj7udoRywWs/79+wcVvqVLlx5mGrYCuHXrVmvVqpUtX748mFMYPyZPnmyzZs2yDRs2KM0PW4aAqy8HGAIGAAFAAFDpUQBAALC2ALBv5je8K4B/L33isPQeO3asjRs37qhpP2zYMFuwYIEtW7bMWrdu7Q2AK1assM9//vOJ80yaNMkeeeSRYMEJR3QFUr4C6LO6CAAEAAFAAFDpfgFAALDWADDjMn8ALJtjagVw+PDhNm/ePFuyZIm1b9++yuYRtgLIELDSu+i2KQ2AvquLAEAAEAAEAJVuFwAEAJMNAPfs2VNpCPhI+e6GfR38zZ071xzgufl/RzrCAqDzd4tAzj777GAVcPw47bTTgiFmFoEovc/htikNgL6riwBAABAABACVLhgABABrCwC/mDbAuwK4KDY39CKQoUP/f3tnHqNTssbhau1iQmfsGqEHQ2LfE8u1ZewiM2GCP8QSjNgSjCUIYo0l0SY3ooUEsSaYGbGNWEIskVgTGpNYW0hbR8Y+V3PzK/n69vK1852vW6e/Os+b9B+iznfqfd465/yq6q2qsXaPv927d2fb++/rr7+2+wLK0tPT7d+5c+fMqFGj7ChhQkKC3c6lfPnytsx3331nF3yMHz/e/js0UJOSkmKngbWX4Nq1a01qaqpJSkry8/hRlhzATwSiGVp+9+6d0V/I1DNSw62+cJYpViqyQ96Lv/b/Anxf4b3vhtusbprva6499L9yLuGr//OI5IbxxT5EUixbmbKl3vi+5kZ6Jd/XfMyI833Nh3+K+7om/iv/q4Dj/5Xh6x4q/PGjf1/+eR5ZG85ambKJL3zVrVjcR1/lVfjlmxK+r4mL4j7RMCtVwt+z+eql/xXNJUr5bzPRrAL+8D7eN+d4n/5/zPD//utR55rvet144f/5930TY8zDVwm+Lst4/c6kDv2Pef78uZEw+hIWGpj4t+ltipt8rAI2/zUnzf6IBWBcXPh3zvr1682wYcOsq8odnDdvXi63s5b55ptvbPmseYYa/Vu2bJndCForipOTk3NtLfMlWLr+m4EdAYxmdVFejdf1RoJ/EIAABCBQcASUVxducURB3EEbLSv3TiNt+bXExERz+/ZtUyrCAY783o/rC5dA4AWgn9VFOUcA1YvTEHRaWtoX680VbnPwdzf1NGvUqJErSdjfr8Ruafwn/rR/nv+ciyQ+90ZTnpyOQKtWrZopVsz/aGikb0uJQM1y5ddKlCiB+MsvxCJ8fWAFYDRTwDnjGBpqjzRJtgi3g6iqhv9/W+FP/CNLEo+qkRXhi2j/tP8gP/9F+NGkahESCKwAFJ/8ri7iA8AHIMgfANo/7Z/2H9wOYIQag2JFmECgBWB+VxfxAeQDyAcwuB9Ann+e/yA//0VY11C1CAkEWgCKUX5WFyknUPsQzZgxw/NonAjjEVPF8J/40/55/nn/BfP9H1MfKyoblkDgBSDtAgIQgAAEIAABCASNAAIwaBHHXwhAAAIQgAAEAk8AARj4JgAACEAAAhCAAASCRgABGLSI4y8EIAABCEAAAoEngAAMfBMAAAQgAAEIQAACQSOAAIwy4lo9vHz5cns2YcOGDc3KlStNhw4dovy12Los3JF4VapUKZCjh4oiCR1YrlifP3/exvu3334zP/zwQ2ZVtbu/zrfUIeV//fWX3V9y1apVtl24YF7+69zOjRs3ZnNVDM6cORPz7muV86+//mquX79uD7Rv166dWbp0abbD7rUafsqUKWbbtm3mzZs39jB7vR++1FFfhQk1Ev87d+5sjh8/nq1aAwcONNu3by/Mqn6Re61evdro786dO/b39UzPmTPH9OrVy/7b5dh/EaD8aJEigACMIhyh/QP1km/fvr1Zs2aNWbdunbl69aqpWbNmFL8YW5dIAO7cudMcPnw4s+Lx8fGmUqXCOYC9sGkdOHDAnDp1yrRo0cL0798/lwCUIFi0aJHZsGGDqVevnlm4cKGRaPrzzz9NQoK/w+IL27dI7uflvwTgw4cPjQ50D5mOkCpfvnwkP1+ky/Ts2dMMGjTItG7d2rx//97MmjXLXL582T7rpUuXtnUfM2aM2bNnj41/hQoVzM8//2yePXtmOwx6LmLZIvFfAlDtfv78+ZmuSixrj7xYN8VVMfz222+tK+roqDN48eJFKwZdjn2sx476exNAAHozylVCoxsSA+oZhqx+/fp2VEg9ZtdNAvD33383ly5dct3VXP7FxcVlE4Aa/dO5nhMnTjTTp0+35TUqoBFRCcPRo0c7xSin/3JOAlDnYqtNuG6PHz82lStXtiNeHTt2tMcAquOzadMmo1Ev2YMHD+wZ2fv37zc9evRwCklO/+WcBGCzZs3sLEgQTB0bicAff/wxULEPQmyD5iMC0GfEC+IMYZ+3LHLFJQD1AlQPv2TJknbKc/HixaZ27dpFrq4FXaGcAujWrVumTp065sKFC6Z58+aZt/v+++9N2bJlc02NFnR9Cvv38hKAEn8a9ZPPnTp1siOiEkqu2Y0bN0zdunXtKGCjRo3M0aNH7ZSvRvzKlSuX6W7Tpk1th1CpAS5ZTv9DAjA1NdWoM6SOj6ZH586d68Tod9bYZWRkmB07dpihQ4faEcD09PRAxd6ldowvnwggAH22BPXuq1evbqcElQ8UMgkgTQ9o2s9105Tg69ev7bSPpv405akcKX0ENAXmsuUUQKdPn7ZpAPfv37cjgSH76aefzN27d83BgwedwhFOAColokyZMiYpKcncvn3bzJ49206XagpUHQRXTAJHwl55nidOnLBubd261QwfPtyO+ma17t27m1q1atn0EFcsnP/ybe3atdbXxMREc+XKFXsykqZMDx065ITrEvtt27Y1b9++te1cMe/du3egYu9EIHEiFwEEoM9GERKA+vDrpRAyjXhoGkhCKGj26tUrOwo2bdo0M3nyZKfdz0sAql1UrVo10/dRo0aZe/fumT/++MMpHuEEYE4HtVBGYlCLAPr16+eM/+PGjTP79u0zJ0+ezFzgkZcA7Natm30mUlJSnPY/nHMS/q1atbIdAKXKxLpp1ictLc2mOezatcvmeysFQCkw4cS/i7GP9RhS//AEEIA+WwZTwOGB6aWnXn/WvEifaGOiOFPA2XMg8wqapklHjhyZmRcZE8H9TCUnTJhgcxy1uEejXSELyhRwXv6HQ6aRQo38Zs2LjPX4Z61/165drbhXzmeQpv9diiG+fCKAAIyiJSjnrWXLlnarh5A1aNDATg8FYRFITmSa/tILUdOe2iLBZctrEcikSZPsCKhMnQTlvwVlEUjOeD99+tSmSWhbnCFDhsR0c5CYkfjR1j/Hjh2z+X9ZLbQIZPPmzWbAgAH2vzQCqi1gXFgE4uV/uOBqGrhx48aZC2ViugGEqbxEnxb5/PLLL3YRiKuxdy1u+JObAAIwilYR2gZG0zuaBtaHTnkwyoHT1Jfrpj3P+vbta7e8efTokc0B1JSIcmVc9P/ly5dGye8yLfRYsWKF6dKli93mRAwk9CT8tQ2KBILyQSUWXNkG5nP+i4EWBWl7HE2Ba7+0mTNn2imza9euxfxCgLFjx9pcr927d2fb+08LoLTViUxbgezdu9duAyMeej4kgl3YBsbL/5s3b5otW7bYnLiKFSva7XG0DY7YnD17Nua3wVFb1qIWCb4XL17YtIYlS5bY1A7Nergce9e/Y/jHCGDUbUCjf8uWLbO9fa0GTE5OtttCBMG0L5qmwp48eWJ7wG3atDELFiwwGgV10STmJPhymlYD6qMf2ghaCf9ZN4JWu3DBPue/pvy12lWrIpUjJREoVmoP+mjGumnEN5xJ7Gv7G5kWB0ydOtUKxawbQQfBf+W5Dh482C7+UEdBPvfp08euAnZhH8gRI0aYI0eO2Pe8RH+TJk1sWoPEn+uxj/Vnl/p7E2AE0JsRJSAAAQhAAAIQgIBTBBCAToUTZyAAAQhAAAIQgIA3AQSgNyNKQAACEIAABCAAAacIIACdCifOQAACEIAABCAAAW8CCEBvRpSAAAQgAAEIQAACThFAADoVTpyBAAQgAAEIQAAC3gQQgN6MKAEBCEAAAhCAAAScIoAAdCqcOAMBCEAAAhCAAAS8CSAAvRlRAgIQgAAEIAABCDhFAAHoVDhxBgIQgAAEIAABCHgTQAB6M6IEBCAAAQhAAAIQcIoAAtCpcOIMBCAAAQhAAAIQ8CaAAPRmRAkIQAACEIAABCDgFAEEoFPhxBkIQAACEIAABCDgTQAB6M2IEhCAAAQgAAEIQMApAghAp8KJMxCAAAQgAAEIQMCbAALQmxElIAABCEAAAhCAgFMEEIBOhRNnIAABCEAAAhCAgDcBBKA3I0pAAAIQgAAEIAABpwggAJ0KJ85AAAIQgAAEIAABbwIIQG9GlIAABCAAAQhAAAJOEUAAOhVOnIEABCAAAQhAAALeBBCA3owoAQEIQAACEIAABJwigAB0Kpw4AwEIQAACEIAABLwJIAC9GVECAhCAAAQgAAEIOEUAAehUOHEGAhCAAAQgAAEIeBNAAHozogQEIAABCEAAAhBwigAC0Klw4gwEIAABCEAAAhDwJoAA9GZECQhAAAIQgAAEIOAUAQSgU+HEGQhAAAIQgAAEIOBNAAHozYgSEIAABCAAAQhAwCkCCECnwokzEIAABCAAAQhAwJvA/wCNhwEPdABTOQAAAABJRU5ErkJggg==\" width=\"640\">" 887 ], 888 "text/plain": [ 889 "<IPython.core.display.HTML object>" 890 ] 891 }, 892 "metadata": {}, 893 "output_type": "display_data" 894 } 895 ], 896 "source": [ 897 "#%matplotlib notebook\n", 898 "import math\n", 899 "import time\n", 900 "\n", 901 "from scipy.interpolate import griddata\n", 902 "import matplotlib.pyplot as plt\n", 903 "import matplotlib.animation as animation\n", 904 "\n", 905 "grid_x, grid_y = np.mgrid[0:31:32j, 0:23:24j]\n", 906 "\n", 907 "plt.figure()\n", 908 "plt.pcolormesh(grid_x, grid_y, pixels)\n", 909 "plt.colorbar()\n", 910 "plt.title(\"Original 32x24\")\n", 911 "\n", 912 "plt.show()" 913 ] 914 }, 915 { 916 "cell_type": "code", 917 "execution_count": 43, 918 "metadata": {}, 919 "outputs": [ 920 { 921 "data": { 922 "application/javascript": [ 923 "/* Put everything inside the global mpl namespace */\n", 924 "window.mpl = {};\n", 925 "\n", 926 "\n", 927 "mpl.get_websocket_type = function() {\n", 928 " if (typeof(WebSocket) !== 'undefined') {\n", 929 " return WebSocket;\n", 930 " } else if (typeof(MozWebSocket) !== 'undefined') {\n", 931 " return MozWebSocket;\n", 932 " } else {\n", 933 " alert('Your browser does not have WebSocket support. ' +\n", 934 " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", 935 " 'Firefox 4 and 5 are also supported but you ' +\n", 936 " 'have to enable WebSockets in about:config.');\n", 937 " };\n", 938 "}\n", 939 "\n", 940 "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", 941 " this.id = figure_id;\n", 942 "\n", 943 " this.ws = websocket;\n", 944 "\n", 945 " this.supports_binary = (this.ws.binaryType != undefined);\n", 946 "\n", 947 " if (!this.supports_binary) {\n", 948 " var warnings = document.getElementById(\"mpl-warnings\");\n", 949 " if (warnings) {\n", 950 " warnings.style.display = 'block';\n", 951 " warnings.textContent = (\n", 952 " \"This browser does not support binary websocket messages. \" +\n", 953 " \"Performance may be slow.\");\n", 954 " }\n", 955 " }\n", 956 "\n", 957 " this.imageObj = new Image();\n", 958 "\n", 959 " this.context = undefined;\n", 960 " this.message = undefined;\n", 961 " this.canvas = undefined;\n", 962 " this.rubberband_canvas = undefined;\n", 963 " this.rubberband_context = undefined;\n", 964 " this.format_dropdown = undefined;\n", 965 "\n", 966 " this.image_mode = 'full';\n", 967 "\n", 968 " this.root = $('<div/>');\n", 969 " this._root_extra_style(this.root)\n", 970 " this.root.attr('style', 'display: inline-block');\n", 971 "\n", 972 " $(parent_element).append(this.root);\n", 973 "\n", 974 " this._init_header(this);\n", 975 " this._init_canvas(this);\n", 976 " this._init_toolbar(this);\n", 977 "\n", 978 " var fig = this;\n", 979 "\n", 980 " this.waiting = false;\n", 981 "\n", 982 " this.ws.onopen = function () {\n", 983 " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", 984 " fig.send_message(\"send_image_mode\", {});\n", 985 " if (mpl.ratio != 1) {\n", 986 " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", 987 " }\n", 988 " fig.send_message(\"refresh\", {});\n", 989 " }\n", 990 "\n", 991 " this.imageObj.onload = function() {\n", 992 " if (fig.image_mode == 'full') {\n", 993 " // Full images could contain transparency (where diff images\n", 994 " // almost always do), so we need to clear the canvas so that\n", 995 " // there is no ghosting.\n", 996 " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", 997 " }\n", 998 " fig.context.drawImage(fig.imageObj, 0, 0);\n", 999 " };\n", 1000 "\n", 1001 " this.imageObj.onunload = function() {\n", 1002 " fig.ws.close();\n", 1003 " }\n", 1004 "\n", 1005 " this.ws.onmessage = this._make_on_message_function(this);\n", 1006 "\n", 1007 " this.ondownload = ondownload;\n", 1008 "}\n", 1009 "\n", 1010 "mpl.figure.prototype._init_header = function() {\n", 1011 " var titlebar = $(\n", 1012 " '<div class=\"ui-dialog-titlebar ui-widget-header ui-corner-all ' +\n", 1013 " 'ui-helper-clearfix\"/>');\n", 1014 " var titletext = $(\n", 1015 " '<div class=\"ui-dialog-title\" style=\"width: 100%; ' +\n", 1016 " 'text-align: center; padding: 3px;\"/>');\n", 1017 " titlebar.append(titletext)\n", 1018 " this.root.append(titlebar);\n", 1019 " this.header = titletext[0];\n", 1020 "}\n", 1021 "\n", 1022 "\n", 1023 "\n", 1024 "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", 1025 "\n", 1026 "}\n", 1027 "\n", 1028 "\n", 1029 "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", 1030 "\n", 1031 "}\n", 1032 "\n", 1033 "mpl.figure.prototype._init_canvas = function() {\n", 1034 " var fig = this;\n", 1035 "\n", 1036 " var canvas_div = $('<div/>');\n", 1037 "\n", 1038 " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", 1039 "\n", 1040 " function canvas_keyboard_event(event) {\n", 1041 " return fig.key_event(event, event['data']);\n", 1042 " }\n", 1043 "\n", 1044 " canvas_div.keydown('key_press', canvas_keyboard_event);\n", 1045 " canvas_div.keyup('key_release', canvas_keyboard_event);\n", 1046 " this.canvas_div = canvas_div\n", 1047 " this._canvas_extra_style(canvas_div)\n", 1048 " this.root.append(canvas_div);\n", 1049 "\n", 1050 " var canvas = $('<canvas/>');\n", 1051 " canvas.addClass('mpl-canvas');\n", 1052 " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", 1053 "\n", 1054 " this.canvas = canvas[0];\n", 1055 " this.context = canvas[0].getContext(\"2d\");\n", 1056 "\n", 1057 " var backingStore = this.context.backingStorePixelRatio ||\n", 1058 "\tthis.context.webkitBackingStorePixelRatio ||\n", 1059 "\tthis.context.mozBackingStorePixelRatio ||\n", 1060 "\tthis.context.msBackingStorePixelRatio ||\n", 1061 "\tthis.context.oBackingStorePixelRatio ||\n", 1062 "\tthis.context.backingStorePixelRatio || 1;\n", 1063 "\n", 1064 " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", 1065 "\n", 1066 " var rubberband = $('<canvas/>');\n", 1067 " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", 1068 "\n", 1069 " var pass_mouse_events = true;\n", 1070 "\n", 1071 " canvas_div.resizable({\n", 1072 " start: function(event, ui) {\n", 1073 " pass_mouse_events = false;\n", 1074 " },\n", 1075 " resize: function(event, ui) {\n", 1076 " fig.request_resize(ui.size.width, ui.size.height);\n", 1077 " },\n", 1078 " stop: function(event, ui) {\n", 1079 " pass_mouse_events = true;\n", 1080 " fig.request_resize(ui.size.width, ui.size.height);\n", 1081 " },\n", 1082 " });\n", 1083 "\n", 1084 " function mouse_event_fn(event) {\n", 1085 " if (pass_mouse_events)\n", 1086 " return fig.mouse_event(event, event['data']);\n", 1087 " }\n", 1088 "\n", 1089 " rubberband.mousedown('button_press', mouse_event_fn);\n", 1090 " rubberband.mouseup('button_release', mouse_event_fn);\n", 1091 " // Throttle sequential mouse events to 1 every 20ms.\n", 1092 " rubberband.mousemove('motion_notify', mouse_event_fn);\n", 1093 "\n", 1094 " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", 1095 " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", 1096 "\n", 1097 " canvas_div.on(\"wheel\", function (event) {\n", 1098 " event = event.originalEvent;\n", 1099 " event['data'] = 'scroll'\n", 1100 " if (event.deltaY < 0) {\n", 1101 " event.step = 1;\n", 1102 " } else {\n", 1103 " event.step = -1;\n", 1104 " }\n", 1105 " mouse_event_fn(event);\n", 1106 " });\n", 1107 "\n", 1108 " canvas_div.append(canvas);\n", 1109 " canvas_div.append(rubberband);\n", 1110 "\n", 1111 " this.rubberband = rubberband;\n", 1112 " this.rubberband_canvas = rubberband[0];\n", 1113 " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", 1114 " this.rubberband_context.strokeStyle = \"#000000\";\n", 1115 "\n", 1116 " this._resize_canvas = function(width, height) {\n", 1117 " // Keep the size of the canvas, canvas container, and rubber band\n", 1118 " // canvas in synch.\n", 1119 " canvas_div.css('width', width)\n", 1120 " canvas_div.css('height', height)\n", 1121 "\n", 1122 " canvas.attr('width', width * mpl.ratio);\n", 1123 " canvas.attr('height', height * mpl.ratio);\n", 1124 " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n", 1125 "\n", 1126 " rubberband.attr('width', width);\n", 1127 " rubberband.attr('height', height);\n", 1128 " }\n", 1129 "\n", 1130 " // Set the figure to an initial 600x600px, this will subsequently be updated\n", 1131 " // upon first draw.\n", 1132 " this._resize_canvas(600, 600);\n", 1133 "\n", 1134 " // Disable right mouse context menu.\n", 1135 " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", 1136 " return false;\n", 1137 " });\n", 1138 "\n", 1139 " function set_focus () {\n", 1140 " canvas.focus();\n", 1141 " canvas_div.focus();\n", 1142 " }\n", 1143 "\n", 1144 " window.setTimeout(set_focus, 100);\n", 1145 "}\n", 1146 "\n", 1147 "mpl.figure.prototype._init_toolbar = function() {\n", 1148 " var fig = this;\n", 1149 "\n", 1150 " var nav_element = $('<div/>');\n", 1151 " nav_element.attr('style', 'width: 100%');\n", 1152 " this.root.append(nav_element);\n", 1153 "\n", 1154 " // Define a callback function for later on.\n", 1155 " function toolbar_event(event) {\n", 1156 " return fig.toolbar_button_onclick(event['data']);\n", 1157 " }\n", 1158 " function toolbar_mouse_event(event) {\n", 1159 " return fig.toolbar_button_onmouseover(event['data']);\n", 1160 " }\n", 1161 "\n", 1162 " for(var toolbar_ind in mpl.toolbar_items) {\n", 1163 " var name = mpl.toolbar_items[toolbar_ind][0];\n", 1164 " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", 1165 " var image = mpl.toolbar_items[toolbar_ind][2];\n", 1166 " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", 1167 "\n", 1168 " if (!name) {\n", 1169 " // put a spacer in here.\n", 1170 " continue;\n", 1171 " }\n", 1172 " var button = $('<button/>');\n", 1173 " button.addClass('ui-button ui-widget ui-state-default ui-corner-all ' +\n", 1174 " 'ui-button-icon-only');\n", 1175 " button.attr('role', 'button');\n", 1176 " button.attr('aria-disabled', 'false');\n", 1177 " button.click(method_name, toolbar_event);\n", 1178 " button.mouseover(tooltip, toolbar_mouse_event);\n", 1179 "\n", 1180 " var icon_img = $('<span/>');\n", 1181 " icon_img.addClass('ui-button-icon-primary ui-icon');\n", 1182 " icon_img.addClass(image);\n", 1183 " icon_img.addClass('ui-corner-all');\n", 1184 "\n", 1185 " var tooltip_span = $('<span/>');\n", 1186 " tooltip_span.addClass('ui-button-text');\n", 1187 " tooltip_span.html(tooltip);\n", 1188 "\n", 1189 " button.append(icon_img);\n", 1190 " button.append(tooltip_span);\n", 1191 "\n", 1192 " nav_element.append(button);\n", 1193 " }\n", 1194 "\n", 1195 " var fmt_picker_span = $('<span/>');\n", 1196 "\n", 1197 " var fmt_picker = $('<select/>');\n", 1198 " fmt_picker.addClass('mpl-toolbar-option ui-widget ui-widget-content');\n", 1199 " fmt_picker_span.append(fmt_picker);\n", 1200 " nav_element.append(fmt_picker_span);\n", 1201 " this.format_dropdown = fmt_picker[0];\n", 1202 "\n", 1203 " for (var ind in mpl.extensions) {\n", 1204 " var fmt = mpl.extensions[ind];\n", 1205 " var option = $(\n", 1206 " '<option/>', {selected: fmt === mpl.default_extension}).html(fmt);\n", 1207 " fmt_picker.append(option);\n", 1208 " }\n", 1209 "\n", 1210 " // Add hover states to the ui-buttons\n", 1211 " $( \".ui-button\" ).hover(\n", 1212 " function() { $(this).addClass(\"ui-state-hover\");},\n", 1213 " function() { $(this).removeClass(\"ui-state-hover\");}\n", 1214 " );\n", 1215 "\n", 1216 " var status_bar = $('<span class=\"mpl-message\"/>');\n", 1217 " nav_element.append(status_bar);\n", 1218 " this.message = status_bar[0];\n", 1219 "}\n", 1220 "\n", 1221 "mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n", 1222 " // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n", 1223 " // which will in turn request a refresh of the image.\n", 1224 " this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n", 1225 "}\n", 1226 "\n", 1227 "mpl.figure.prototype.send_message = function(type, properties) {\n", 1228 " properties['type'] = type;\n", 1229 " properties['figure_id'] = this.id;\n", 1230 " this.ws.send(JSON.stringify(properties));\n", 1231 "}\n", 1232 "\n", 1233 "mpl.figure.prototype.send_draw_message = function() {\n", 1234 " if (!this.waiting) {\n", 1235 " this.waiting = true;\n", 1236 " this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n", 1237 " }\n", 1238 "}\n", 1239 "\n", 1240 "\n", 1241 "mpl.figure.prototype.handle_save = function(fig, msg) {\n", 1242 " var format_dropdown = fig.format_dropdown;\n", 1243 " var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n", 1244 " fig.ondownload(fig, format);\n", 1245 "}\n", 1246 "\n", 1247 "\n", 1248 "mpl.figure.prototype.handle_resize = function(fig, msg) {\n", 1249 " var size = msg['size'];\n", 1250 " if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n", 1251 " fig._resize_canvas(size[0], size[1]);\n", 1252 " fig.send_message(\"refresh\", {});\n", 1253 " };\n", 1254 "}\n", 1255 "\n", 1256 "mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n", 1257 " var x0 = msg['x0'] / mpl.ratio;\n", 1258 " var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n", 1259 " var x1 = msg['x1'] / mpl.ratio;\n", 1260 " var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n", 1261 " x0 = Math.floor(x0) + 0.5;\n", 1262 " y0 = Math.floor(y0) + 0.5;\n", 1263 " x1 = Math.floor(x1) + 0.5;\n", 1264 " y1 = Math.floor(y1) + 0.5;\n", 1265 " var min_x = Math.min(x0, x1);\n", 1266 " var min_y = Math.min(y0, y1);\n", 1267 " var width = Math.abs(x1 - x0);\n", 1268 " var height = Math.abs(y1 - y0);\n", 1269 "\n", 1270 " fig.rubberband_context.clearRect(\n", 1271 " 0, 0, fig.canvas.width / mpl.ratio, fig.canvas.height / mpl.ratio);\n", 1272 "\n", 1273 " fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n", 1274 "}\n", 1275 "\n", 1276 "mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n", 1277 " // Updates the figure title.\n", 1278 " fig.header.textContent = msg['label'];\n", 1279 "}\n", 1280 "\n", 1281 "mpl.figure.prototype.handle_cursor = function(fig, msg) {\n", 1282 " var cursor = msg['cursor'];\n", 1283 " switch(cursor)\n", 1284 " {\n", 1285 " case 0:\n", 1286 " cursor = 'pointer';\n", 1287 " break;\n", 1288 " case 1:\n", 1289 " cursor = 'default';\n", 1290 " break;\n", 1291 " case 2:\n", 1292 " cursor = 'crosshair';\n", 1293 " break;\n", 1294 " case 3:\n", 1295 " cursor = 'move';\n", 1296 " break;\n", 1297 " }\n", 1298 " fig.rubberband_canvas.style.cursor = cursor;\n", 1299 "}\n", 1300 "\n", 1301 "mpl.figure.prototype.handle_message = function(fig, msg) {\n", 1302 " fig.message.textContent = msg['message'];\n", 1303 "}\n", 1304 "\n", 1305 "mpl.figure.prototype.handle_draw = function(fig, msg) {\n", 1306 " // Request the server to send over a new figure.\n", 1307 " fig.send_draw_message();\n", 1308 "}\n", 1309 "\n", 1310 "mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n", 1311 " fig.image_mode = msg['mode'];\n", 1312 "}\n", 1313 "\n", 1314 "mpl.figure.prototype.updated_canvas_event = function() {\n", 1315 " // Called whenever the canvas gets updated.\n", 1316 " this.send_message(\"ack\", {});\n", 1317 "}\n", 1318 "\n", 1319 "// A function to construct a web socket function for onmessage handling.\n", 1320 "// Called in the figure constructor.\n", 1321 "mpl.figure.prototype._make_on_message_function = function(fig) {\n", 1322 " return function socket_on_message(evt) {\n", 1323 " if (evt.data instanceof Blob) {\n", 1324 " /* FIXME: We get \"Resource interpreted as Image but\n", 1325 " * transferred with MIME type text/plain:\" errors on\n", 1326 " * Chrome. But how to set the MIME type? It doesn't seem\n", 1327 " * to be part of the websocket stream */\n", 1328 " evt.data.type = \"image/png\";\n", 1329 "\n", 1330 " /* Free the memory for the previous frames */\n", 1331 " if (fig.imageObj.src) {\n", 1332 " (window.URL || window.webkitURL).revokeObjectURL(\n", 1333 " fig.imageObj.src);\n", 1334 " }\n", 1335 "\n", 1336 " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n", 1337 " evt.data);\n", 1338 " fig.updated_canvas_event();\n", 1339 " fig.waiting = false;\n", 1340 " return;\n", 1341 " }\n", 1342 " else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n", 1343 " fig.imageObj.src = evt.data;\n", 1344 " fig.updated_canvas_event();\n", 1345 " fig.waiting = false;\n", 1346 " return;\n", 1347 " }\n", 1348 "\n", 1349 " var msg = JSON.parse(evt.data);\n", 1350 " var msg_type = msg['type'];\n", 1351 "\n", 1352 " // Call the \"handle_{type}\" callback, which takes\n", 1353 " // the figure and JSON message as its only arguments.\n", 1354 " try {\n", 1355 " var callback = fig[\"handle_\" + msg_type];\n", 1356 " } catch (e) {\n", 1357 " console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n", 1358 " return;\n", 1359 " }\n", 1360 "\n", 1361 " if (callback) {\n", 1362 " try {\n", 1363 " // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n", 1364 " callback(fig, msg);\n", 1365 " } catch (e) {\n", 1366 " console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n", 1367 " }\n", 1368 " }\n", 1369 " };\n", 1370 "}\n", 1371 "\n", 1372 "// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n", 1373 "mpl.findpos = function(e) {\n", 1374 " //this section is from http://www.quirksmode.org/js/events_properties.html\n", 1375 " var targ;\n", 1376 " if (!e)\n", 1377 " e = window.event;\n", 1378 " if (e.target)\n", 1379 " targ = e.target;\n", 1380 " else if (e.srcElement)\n", 1381 " targ = e.srcElement;\n", 1382 " if (targ.nodeType == 3) // defeat Safari bug\n", 1383 " targ = targ.parentNode;\n", 1384 "\n", 1385 " // jQuery normalizes the pageX and pageY\n", 1386 " // pageX,Y are the mouse positions relative to the document\n", 1387 " // offset() returns the position of the element relative to the document\n", 1388 " var x = e.pageX - $(targ).offset().left;\n", 1389 " var y = e.pageY - $(targ).offset().top;\n", 1390 "\n", 1391 " return {\"x\": x, \"y\": y};\n", 1392 "};\n", 1393 "\n", 1394 "/*\n", 1395 " * return a copy of an object with only non-object keys\n", 1396 " * we need this to avoid circular references\n", 1397 " * http://stackoverflow.com/a/24161582/3208463\n", 1398 " */\n", 1399 "function simpleKeys (original) {\n", 1400 " return Object.keys(original).reduce(function (obj, key) {\n", 1401 " if (typeof original[key] !== 'object')\n", 1402 " obj[key] = original[key]\n", 1403 " return obj;\n", 1404 " }, {});\n", 1405 "}\n", 1406 "\n", 1407 "mpl.figure.prototype.mouse_event = function(event, name) {\n", 1408 " var canvas_pos = mpl.findpos(event)\n", 1409 "\n", 1410 " if (name === 'button_press')\n", 1411 " {\n", 1412 " this.canvas.focus();\n", 1413 " this.canvas_div.focus();\n", 1414 " }\n", 1415 "\n", 1416 " var x = canvas_pos.x * mpl.ratio;\n", 1417 " var y = canvas_pos.y * mpl.ratio;\n", 1418 "\n", 1419 " this.send_message(name, {x: x, y: y, button: event.button,\n", 1420 " step: event.step,\n", 1421 " guiEvent: simpleKeys(event)});\n", 1422 "\n", 1423 " /* This prevents the web browser from automatically changing to\n", 1424 " * the text insertion cursor when the button is pressed. We want\n", 1425 " * to control all of the cursor setting manually through the\n", 1426 " * 'cursor' event from matplotlib */\n", 1427 " event.preventDefault();\n", 1428 " return false;\n", 1429 "}\n", 1430 "\n", 1431 "mpl.figure.prototype._key_event_extra = function(event, name) {\n", 1432 " // Handle any extra behaviour associated with a key event\n", 1433 "}\n", 1434 "\n", 1435 "mpl.figure.prototype.key_event = function(event, name) {\n", 1436 "\n", 1437 " // Prevent repeat events\n", 1438 " if (name == 'key_press')\n", 1439 " {\n", 1440 " if (event.which === this._key)\n", 1441 " return;\n", 1442 " else\n", 1443 " this._key = event.which;\n", 1444 " }\n", 1445 " if (name == 'key_release')\n", 1446 " this._key = null;\n", 1447 "\n", 1448 " var value = '';\n", 1449 " if (event.ctrlKey && event.which != 17)\n", 1450 " value += \"ctrl+\";\n", 1451 " if (event.altKey && event.which != 18)\n", 1452 " value += \"alt+\";\n", 1453 " if (event.shiftKey && event.which != 16)\n", 1454 " value += \"shift+\";\n", 1455 "\n", 1456 " value += 'k';\n", 1457 " value += event.which.toString();\n", 1458 "\n", 1459 " this._key_event_extra(event, name);\n", 1460 "\n", 1461 " this.send_message(name, {key: value,\n", 1462 " guiEvent: simpleKeys(event)});\n", 1463 " return false;\n", 1464 "}\n", 1465 "\n", 1466 "mpl.figure.prototype.toolbar_button_onclick = function(name) {\n", 1467 " if (name == 'download') {\n", 1468 " this.handle_save(this, null);\n", 1469 " } else {\n", 1470 " this.send_message(\"toolbar_button\", {name: name});\n", 1471 " }\n", 1472 "};\n", 1473 "\n", 1474 "mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n", 1475 " this.message.textContent = tooltip;\n", 1476 "};\n", 1477 "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", 1478 "\n", 1479 "mpl.extensions = [\"eps\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n", 1480 "\n", 1481 "mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n", 1482 " // Create a \"websocket\"-like object which calls the given IPython comm\n", 1483 " // object with the appropriate methods. Currently this is a non binary\n", 1484 " // socket, so there is still some room for performance tuning.\n", 1485 " var ws = {};\n", 1486 "\n", 1487 " ws.close = function() {\n", 1488 " comm.close()\n", 1489 " };\n", 1490 " ws.send = function(m) {\n", 1491 " //console.log('sending', m);\n", 1492 " comm.send(m);\n", 1493 " };\n", 1494 " // Register the callback with on_msg.\n", 1495 " comm.on_msg(function(msg) {\n", 1496 " //console.log('receiving', msg['content']['data'], msg);\n", 1497 " // Pass the mpl event to the overridden (by mpl) onmessage function.\n", 1498 " ws.onmessage(msg['content']['data'])\n", 1499 " });\n", 1500 " return ws;\n", 1501 "}\n", 1502 "\n", 1503 "mpl.mpl_figure_comm = function(comm, msg) {\n", 1504 " // This is the function which gets called when the mpl process\n", 1505 " // starts-up an IPython Comm through the \"matplotlib\" channel.\n", 1506 "\n", 1507 " var id = msg.content.data.id;\n", 1508 " // Get hold of the div created by the display call when the Comm\n", 1509 " // socket was opened in Python.\n", 1510 " var element = $(\"#\" + id);\n", 1511 " var ws_proxy = comm_websocket_adapter(comm)\n", 1512 "\n", 1513 " function ondownload(figure, format) {\n", 1514 " window.open(figure.imageObj.src);\n", 1515 " }\n", 1516 "\n", 1517 " var fig = new mpl.figure(id, ws_proxy,\n", 1518 " ondownload,\n", 1519 " element.get(0));\n", 1520 "\n", 1521 " // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n", 1522 " // web socket which is closed, not our websocket->open comm proxy.\n", 1523 " ws_proxy.onopen();\n", 1524 "\n", 1525 " fig.parent_element = element.get(0);\n", 1526 " fig.cell_info = mpl.find_output_cell(\"<div id='\" + id + \"'></div>\");\n", 1527 " if (!fig.cell_info) {\n", 1528 " console.error(\"Failed to find cell for figure\", id, fig);\n", 1529 " return;\n", 1530 " }\n", 1531 "\n", 1532 " var output_index = fig.cell_info[2]\n", 1533 " var cell = fig.cell_info[0];\n", 1534 "\n", 1535 "};\n", 1536 "\n", 1537 "mpl.figure.prototype.handle_close = function(fig, msg) {\n", 1538 " var width = fig.canvas.width/mpl.ratio\n", 1539 " fig.root.unbind('remove')\n", 1540 "\n", 1541 " // Update the output cell to use the data from the current canvas.\n", 1542 " fig.push_to_output();\n", 1543 " var dataURL = fig.canvas.toDataURL();\n", 1544 " // Re-enable the keyboard manager in IPython - without this line, in FF,\n", 1545 " // the notebook keyboard shortcuts fail.\n", 1546 " IPython.keyboard_manager.enable()\n", 1547 " $(fig.parent_element).html('<img src=\"' + dataURL + '\" width=\"' + width + '\">');\n", 1548 " fig.close_ws(fig, msg);\n", 1549 "}\n", 1550 "\n", 1551 "mpl.figure.prototype.close_ws = function(fig, msg){\n", 1552 " fig.send_message('closing', msg);\n", 1553 " // fig.ws.close()\n", 1554 "}\n", 1555 "\n", 1556 "mpl.figure.prototype.push_to_output = function(remove_interactive) {\n", 1557 " // Turn the data on the canvas into data in the output cell.\n", 1558 " var width = this.canvas.width/mpl.ratio\n", 1559 " var dataURL = this.canvas.toDataURL();\n", 1560 " this.cell_info[1]['text/html'] = '<img src=\"' + dataURL + '\" width=\"' + width + '\">';\n", 1561 "}\n", 1562 "\n", 1563 "mpl.figure.prototype.updated_canvas_event = function() {\n", 1564 " // Tell IPython that the notebook contents must change.\n", 1565 " IPython.notebook.set_dirty(true);\n", 1566 " this.send_message(\"ack\", {});\n", 1567 " var fig = this;\n", 1568 " // Wait a second, then push the new image to the DOM so\n", 1569 " // that it is saved nicely (might be nice to debounce this).\n", 1570 " setTimeout(function () { fig.push_to_output() }, 1000);\n", 1571 "}\n", 1572 "\n", 1573 "mpl.figure.prototype._init_toolbar = function() {\n", 1574 " var fig = this;\n", 1575 "\n", 1576 " var nav_element = $('<div/>');\n", 1577 " nav_element.attr('style', 'width: 100%');\n", 1578 " this.root.append(nav_element);\n", 1579 "\n", 1580 " // Define a callback function for later on.\n", 1581 " function toolbar_event(event) {\n", 1582 " return fig.toolbar_button_onclick(event['data']);\n", 1583 " }\n", 1584 " function toolbar_mouse_event(event) {\n", 1585 " return fig.toolbar_button_onmouseover(event['data']);\n", 1586 " }\n", 1587 "\n", 1588 " for(var toolbar_ind in mpl.toolbar_items){\n", 1589 " var name = mpl.toolbar_items[toolbar_ind][0];\n", 1590 " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", 1591 " var image = mpl.toolbar_items[toolbar_ind][2];\n", 1592 " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", 1593 "\n", 1594 " if (!name) { continue; };\n", 1595 "\n", 1596 " var button = $('<button class=\"btn btn-default\" href=\"#\" title=\"' + name + '\"><i class=\"fa ' + image + ' fa-lg\"></i></button>');\n", 1597 " button.click(method_name, toolbar_event);\n", 1598 " button.mouseover(tooltip, toolbar_mouse_event);\n", 1599 " nav_element.append(button);\n", 1600 " }\n", 1601 "\n", 1602 " // Add the status bar.\n", 1603 " var status_bar = $('<span class=\"mpl-message\" style=\"text-align:right; float: right;\"/>');\n", 1604 " nav_element.append(status_bar);\n", 1605 " this.message = status_bar[0];\n", 1606 "\n", 1607 " // Add the close button to the window.\n", 1608 " var buttongrp = $('<div class=\"btn-group inline pull-right\"></div>');\n", 1609 " var button = $('<button class=\"btn btn-mini btn-primary\" href=\"#\" title=\"Stop Interaction\"><i class=\"fa fa-power-off icon-remove icon-large\"></i></button>');\n", 1610 " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", 1611 " button.mouseover('Stop Interaction', toolbar_mouse_event);\n", 1612 " buttongrp.append(button);\n", 1613 " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", 1614 " titlebar.prepend(buttongrp);\n", 1615 "}\n", 1616 "\n", 1617 "mpl.figure.prototype._root_extra_style = function(el){\n", 1618 " var fig = this\n", 1619 " el.on(\"remove\", function(){\n", 1620 "\tfig.close_ws(fig, {});\n", 1621 " });\n", 1622 "}\n", 1623 "\n", 1624 "mpl.figure.prototype._canvas_extra_style = function(el){\n", 1625 " // this is important to make the div 'focusable\n", 1626 " el.attr('tabindex', 0)\n", 1627 " // reach out to IPython and tell the keyboard manager to turn it's self\n", 1628 " // off when our div gets focus\n", 1629 "\n", 1630 " // location in version 3\n", 1631 " if (IPython.notebook.keyboard_manager) {\n", 1632 " IPython.notebook.keyboard_manager.register_events(el);\n", 1633 " }\n", 1634 " else {\n", 1635 " // location in version 2\n", 1636 " IPython.keyboard_manager.register_events(el);\n", 1637 " }\n", 1638 "\n", 1639 "}\n", 1640 "\n", 1641 "mpl.figure.prototype._key_event_extra = function(event, name) {\n", 1642 " var manager = IPython.notebook.keyboard_manager;\n", 1643 " if (!manager)\n", 1644 " manager = IPython.keyboard_manager;\n", 1645 "\n", 1646 " // Check for shift+enter\n", 1647 " if (event.shiftKey && event.which == 13) {\n", 1648 " this.canvas_div.blur();\n", 1649 " event.shiftKey = false;\n", 1650 " // Send a \"J\" for go to next cell\n", 1651 " event.which = 74;\n", 1652 " event.keyCode = 74;\n", 1653 " manager.command_mode();\n", 1654 " manager.handle_keydown(event);\n", 1655 " }\n", 1656 "}\n", 1657 "\n", 1658 "mpl.figure.prototype.handle_save = function(fig, msg) {\n", 1659 " fig.ondownload(fig, null);\n", 1660 "}\n", 1661 "\n", 1662 "\n", 1663 "mpl.find_output_cell = function(html_output) {\n", 1664 " // Return the cell and output element which can be found *uniquely* in the notebook.\n", 1665 " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", 1666 " // IPython event is triggered only after the cells have been serialised, which for\n", 1667 " // our purposes (turning an active figure into a static one), is too late.\n", 1668 " var cells = IPython.notebook.get_cells();\n", 1669 " var ncells = cells.length;\n", 1670 " for (var i=0; i<ncells; i++) {\n", 1671 " var cell = cells[i];\n", 1672 " if (cell.cell_type === 'code'){\n", 1673 " for (var j=0; j<cell.output_area.outputs.length; j++) {\n", 1674 " var data = cell.output_area.outputs[j];\n", 1675 " if (data.data) {\n", 1676 " // IPython >= 3 moved mimebundle to data attribute of output\n", 1677 " data = data.data;\n", 1678 " }\n", 1679 " if (data['text/html'] == html_output) {\n", 1680 " return [cell, data, j];\n", 1681 " }\n", 1682 " }\n", 1683 " }\n", 1684 " }\n", 1685 "}\n", 1686 "\n", 1687 "// Register the function which deals with the matplotlib target/channel.\n", 1688 "// The kernel may be null if the page has been refreshed.\n", 1689 "if (IPython.notebook.kernel != null) {\n", 1690 " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", 1691 "}\n" 1692 ], 1693 "text/plain": [ 1694 "<IPython.core.display.Javascript object>" 1695 ] 1696 }, 1697 "metadata": {}, 1698 "output_type": "display_data" 1699 }, 1700 { 1701 "data": { 1702 "text/html": [ 1703 "<img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAoAAAAHgCAYAAAA10dzkAAAgAElEQVR4XuydC5hVZfX/15wZGAaQUVTMEhURMUVNzVQ0ywCvGZal/PprYt4xK/MOKhCIF8xb5i0Lb6F5A+9madw0M/ESSlgoKiUmgpqAwzBnzv9ZG/d4gBnY3/2eOc6Z89nPw9Pv56x13r2/a73v+9nrfffeFblcLmccKIACKIACKIACKIACZaNABQBYNrHmQlEABVAABVAABVAgUgAAJBFQAAVQAAVQAAVQoMwUAADLLOBcLgqgAAqgAAqgAAoAgOQACqAACqAACqAACpSZAgBgmQWcy0UBFEABFEABFEABAJAcQAEUQAEUQAEUQIEyUwAALLOAc7kogAIogAIogAIoAACSAyiAAiiAAiiAAihQZgoAgGUWcC4XBVAABVAABVAABQBAcgAFUAAFUAAFUAAFykwBALDMAs7logAKoAAKoAAKoAAASA6gAAqgAAqgAAqgQJkpAACWWcC5XBRAARRAARRAARQAAMkBFEABFEABFEABFCgzBQDAMgs4l4sCKIACKIACKIACACA5gAIogAIogAIogAJlpgAAWGYB53JRAAVQAAVQAAVQAAAkB1AABVAABVAABVCgzBQAAMss4FwuCqAACqAACqAACgCA5AAKoAAKoAAKoAAKlJkCAGCZBZzLRQEUQAEUQAEUQAEAkBxAARRAARRAARRAgTJTAAAss4BzuSiAAiiAAiiAAigAAJIDKIACKIACKIACKFBmCgCAZRZwLhcFUAAFUAAFUAAFAEByAAVQAAVQAAVQAAXKTAEAsMwCzuWiAAqgAAqgAAqgAABIDqAACqAACqAACqBAmSkAAJZZwLlcFEABFEABFEABFAAAyQEUQAEUQAEUQAEUKDMFAMAyCziXiwIogAIogAIogAIAIDmAAiiAAiiAAiiAAmWmAABYZgHnclEABVAABVAABVAAACQHUAAFUAAFUAAFUKDMFAAAyyzgXC4KoAAKoAAKoAAKAIDkAAqgAAqgAAqgAAqUmQIAYJkFnMtFARRAARRAARRAAQCwneTA1VdfbT/5yU9s++23t5dffjnoqkaNGmWjR4+2XC4X9DtpnGfPnm133XWXDR061Lbccss0P9GiT9Lr8rZvueUW69q1qy1YsCD63/zjzTfftF69ekX6jBw50vx3/ZgyZYrtu+++dvfdd9t3v/vdZs9j6tSpkc0555xj48aNW8Xmtddes5122skOOOAAu+eee5r1r6ioSKTJn//858huXeeT6MfaoJHrkK/92k7xf//7n/3yl7+0SZMm2T//+U9bvny5bbrppvaNb3zDfvSjH9kuu+zSBq+wOKd066232umnn26vv/66rbfeelGjI0aMsEceecQ8z5ctW2af//znbeDAgdF/32KLLZpObObMmfbb3/7Wpk2bZm+88YZ17tzZdthhBxs+fHikrXpks1m76qqr7PHHH4/GsMWLF0ftDR48OOov66+/fos/6ePGzjvvbPX19fa3v/3NvvzlLzfZnn/++fbwww/bc889Z5lMRj0t7FGg3SoAALaT0H7pS1+yl156KbqaZ555xnbffffUV/bvf//b/N8ee+yR+jfSOjr4fO973zMHmK9//etpf6ZZPwUAJ06caJWVlXbNNdfYscceu8rv+e9cccUV5mChAqD/0E9/+tPod59++mn7yle+Ev12Y2Oj7bPPPhGgvPLKK7bxxhs3ew0e2/xjzJgxkVZPPvnkKv99u+22s+eff77sAdCher/99rN3333XTjrppCinHOgdWPxGw0Hngw8+sNra2oLmWin8mMPdNttsE+XjGWec0XTKp5xySgReX/ziFyModLgaO3ZslKOemxtuuGFk6z5+Q/P9738/unFZunSpXX/99ZGmfgP1gx/8QJJhyZIlEWz+3//9nw0aNMg22mijKIe9bQd2B7iampo1ftPBca+99rL58+fb22+/vQYAfvjhh9HN5OWXX27HHHOMdE4Yo0B7VgAAbAfR9YFxt912s4MPPji60z3++OPtxhtvLMkraysA6OdxyCGH2FtvvWVPPfVUk5Ze9fPqn0PFr3/961QA+PHHH5sDu1cjXnjhBevUqZNdeumldvbZZ9u9995r3/nOdxLHzquVfq4+ea5+JKlIJm5oLYYOEl79KeaRpALoYOBVIa9keQz79eu3xik++uij9rWvfa3o5x+iVaH0vu666+xnP/tZVOVeW3XNz9V1Ouigg+w3v/mN/fCHP4xO36G6R48eq1yKa+4VVYfBuXPnSpfpvg7jMWDGzvGYcNttt9mRRx65xm9edtllduWVV9pZZ50VrYKsXgF0h1NPPTWqLM6ZM8eSVtGlk8cYBUpQAQCwBIO2+imffPLJ0Z33rFmz7MQT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BTBdBpaGFwAYECcAEAAEALUOBABqegGAul4A4CcAeEEBAPDnAGC6DCwNLwAwIE4AIAAIAGodCADU9AIAdb0AQAAwXdaUnxcAGBBzABAABAC1DgQAanoBgLpeAOAnABj4ftpsXZ29PoYKYLoMLA0vADAgTgAgAAgAah0IANT0AgB1vQDATwDwvLAPFEQAODY5AF500UV233332Zw5c6ympsb69+9vl1xyifXt23eNIOZyOTvooIPsscces0mTJtmhhx6aLtB4BSkAAAbIBwACgACg1oEAQE0vAFDXCwD8bADwgAMOsCFDhthuu+1mDQ0NNmLECJs1a5bNnj3bunTpskogr7jiCvvjH/9ojz76KACYLsUL4tVuAXDatGk2fvx4mzlzpi1YsGCNJPM7kNGjR9uNN95o77//vu2+++72q1/9yrbffvvEwgKAACAAmLi7RIYAoKYXAKjrBQB+AoAjClABvDB5BXD1SC1cuNB69OhhU6dOtX322afpzy+99JJ985vftL/97W+26aabAoDpUrwgXu0WAP3O4qmnnrJddtnFDjvssDWSzEvTF154od188822zTbb2NixY82h8dVXX7X11lsvkbgAIAAIACbqKk1GAKCmFwCo6wUArgTA3sPDAfC1cekBcO7cudanT5+oCtivX78okMuWLbMvf/nL5svFgwcPtoqKCgAwXYoXxKvdAmC+OqsnmVf/Pv/5z9tPf/pTO/vss1dWJpYvt0022STas3DiiScmEhcABAABwERdBQD8RIGKrKYXAKjrBQAWFgDnz59v3bp1awpEdXW1+b+1HT7HOuD56tr06dObTH1uzWazdtNNN0X/DQBMl9+F8ipLAHz99detd+/e9vzzz9vOO+/cpKUn7Prrr2+33HJLIn0BQAAQAEzUVQBAADBSoLFjhZYwKa35FFzhKoCrh2DkyJE2atSotUbmlFNOsYcffthmzJhhm222WWT7wAMP2Omnn24vvPCCde3aFQBMmduFdCtLAHz66adtr732sv/85z9RJTA+TjjhBHvzzTftD3/4Q7Mae5XQ/8WHA2DPnj1tq8DH7dcV0Iaa3LpM1vh7Y3Wj7JPrqLdjGc2n5s0O8nltOFu/ls73PiO3k+ncWfYBADXJWALW9HLrXKXuk2nQfRqrdJ/MCq3/A4B19vydI+zDDz9cpaqmK9+yR1yY6H1uAZaALxpuagXw1FNPtcmTJ0dbqnr16tV0or7idvXVV1smk2n6b14N9P//q1/9qk2ZMqWQMvBbCRQoawB8++23o02o8XH88cdHye6Ppjd3+F2PPziy+rGVsNk2l2KQbazSBlk/v+x6OjSZ3oxZpeZU+aE+m1V/oFcNus3Tr7/L2/UJusyqJh1mzdN8Vugzc0XXVZ+gS9RgTadEZvlGi/b6tC8kdV6+vhab/32lLulPN9nlslob7thp3tqXqJo7iYwefuv2ppb/Of1SrHK51kYEjSnGmQo9NeVYZrL6tTRW6aI1dkjhk0IzFYAbVtTZzLvPKwoAbn1OOADOvTj5HkBf9nX489e6OMz5/r/845133rH33ntvlf+2ww472FVXXWWHHHLIKrAoJxYOqRQoSwBMuwTcYgUQAEycfACgPssCgPpkDgAm7pJNhgCgrhkA+Klmw4YNs4kTJ9r999+/yrv//IEUfy9gcwd7APWcK6RHWQJg/BDIaaedZmeddVakZ319ffTIeqqHQADAxDkJAAKAiZPlE0MqgHrVjAqgftNQjCXwolcAq/WVgLh/ZpfXmVIBdJhr7pgwYYINHToUAFQHviLYt1sAXLJkiflj6H74gx6XX3657bvvvta9e3fbfPPNI9DzR9E9Ob1UPW7cuKhsneo1MABg4lQFAAHAxMkCAEYKsAScAuZYAratzx5nlaEAeEnyJWC1X2P/2SvQbgHQYc6Bb/Xj6KOPjt79F78I+oYbbljlRdDx+4qShKbpKWAAMIlcKycz9gAm1io2ZAlYBwCWgOU0M5aAdc3a9BIwAKgHtMw82i0AFiOOAKATnbY8BQBSAVT7JkvAWh9zfVkC1m8a2tsScJ+zwiuA/7qUCqA6XpWSPQAYEC0AEADkKWBtouUpYH3AYQlYyzFXmKeAa63PmQUAwPEAoN5jS8cDAAyIFQAIAAKA2uQMAOoDDgCo5RgAuPJLIACg3tfKzQMADIg4AAgAAoDa5AwA6gMOAKjlGAC4EgC3OSO8AvjPy6gA6j22dDwAwIBYAYAAIACoTc4AoD7gAIBajgGAnwDg6QUAwF8AgHqPLR0PADAgVgAgAAgAapMzAKgPOACglmMAIACo97Ly9AAAA+IOAAKAAKA2OQOA+oADAGo5BgB+AoA/K0AF8HIqgHqPLR0PADAgVgAgAAgAapMzAKgPOACglmMA4EoA7HtaOAC+egUAqPfY0vEAAANiBQACgACgNjkDgPqAAwBqOQYAfgKAPy0AAF4JAOo9tnQ8AMCAWAGAACAAqE3OAKA+4ACAWo4BgACg3svK0wMADIg7AAgAAoDa5AwA6gMOAKjlGAD4CQD+pAAVwKuoAOo9tnQ8AMCAWMUA2Hv4OKvs1CnRL+X0scwauuqfgmrs2JjofPKNctW6j4kX1PG9Kvm8qhfLLqm+a7piPb2dhi6aT2WdZu/Wn3tmhexU/f5y2ee9HbvKPu/303LmiK/9RW5j+5p/yz6PL+4n+0x/qa/ss/4sLZ+rP9T7sqVwyTSkcEoxNqnnpn471wNSoaVYFMNUXwLpoAvQWKmlTLa+zp6/c4R9+OGH1q1bN805oXU8L23743AAnHM1AJhQ9pI0AwADwgYA+kdHtUETANQTDgAEANWsAQC1cSk1NAKAampi34YUAAADggEAAoBUALXyDBXAFJW5FC4AIAC47akFqAD+kgpgACK0eVcAMCBEACAACAACgMoQwhKwTrMsASsZZhbPS1/8UTgA/uMaAFBTv7SsAcCAeAGAACAACAAqQwgACAAWaw8gAKj0zPK0BQAD4g4AAoAAIACoDCEAIABYNAA8pQAVwF9RAVT6d6nZAoABEQMAAUAAEABUhhAAEAAsGgAOKwAAXgsAKv271GwBwICIAYAAIAAIACpDCAAIAAKASo/BtjUVAAAD1AUAAUAAEABUhhAAEAAsFgBuV4AK4GwqgEr3LjlbADAgZAAgAAgAAoDKEAIAAoBFA8CTw5eAZ1/HErDSv0vNFgAMiBgACAACgACgMoQAgABgsQBw+5PCAfCV6wFApX+Xmi0AGBAxABAABAABQGUIAQABQABQ6THYtqYCAGCAugAgAAgAAoDKEAIAAoBFA8ATC1ABvIEKoNK/S80WAAyIGAAIAAKAAKAyhACAAGBRAbBjJyU9V7HN1tfZKwBgav1KwREADIgSAAgAAoAAoDKEAIAAIACo9BhsW1MBADBAXQAQAAQAAUBlCAEAAcBiAWC/E8ZZZWAF8OUbWQJW+nep2QKAARGLAbDXqHGW6ZSs1N7YSR8Ac5kUPp20iTmSoUpvx6q0dqre6Sgr3vWtCtnnc7f8XfaxCr2dFbv0kdqp27CDZO/GH25VKfvUry+7WHarj2Wn7rVLJJ/Naz+Q7N14w45LZZ9Nqv8n+7y+bCPZ56V7t5N8KrTuEv129Qd6v8ylyOWqOr0d6eLNrNOiBtXFKpfrojV2zMjtNHTWfVaIPr6sOvOuEfbhhx9at27d5HNM4hDPS/2OLwAA/hoATKJ5qdoAgAGRAwAdGrXBGQAEANUuBwDqYAYA6jAHAK7aMx1WXwYA1eGqpOwBwIBwAYAAIBVAKoDKEEIFkApgsSqAOxwXXgGcdRMVQKV/l5otABgQMQAQAAQAAUBlCAEAAcCiAeCxBQDA3wCASv8uNVsAMCBiACAACAACgMoQAgACgACg0mOwbU0FAMAAdQFAABAABACVIQQABACLBYA7/jC8Avj331IBVPp3qdkCgAERAwABQAAQAFSGEAAQACwaAB5TAACcAAAq/bvUbAHAgIgBgAAgAAgAKkMIAAgAFg0AhxYAAG8GAJX+XWq2AGBAxABAABAABACVIQQABAABQKXHYNuaCgCAAeoCgAAgAAgAKkMIAAgAFgsAdzo6vAL40i1UAJX+XWq2AGBAxABAABAABACVIQQABACLBoA/KAAA3goAKv271GwBwICIAYAAIAAIACpDCAAIALZXALzooovsvvvuszlz5lhNTY3179/fLrnkEuvbt2/URRYvXmwjR460xx9/3ObPn28bbbSRHXrooTZmzBirra1VuhG2BVIAAAwQEgAEAAFAAFAZQgBAALBYAPiloy60yo7JvlHfXA77p+BevC35d4sPOOAAGzJkiO22227W0NBgI0aMsFmzZtns2bOtS5cu9vLLL0cAOHToUNtuu+3szTfftJNOOsl23HFHu+eee5RuhG2BFAAAA4QEAAFAABAAVIYQABAALBoAHlkAALw9OQCu3g8WLlxoPXr0sKlTp9o+++zTbDe5++677cgjj7SlS5daVVWV0pWwLYACAGCAiAAgAAgAAoDKEAIAAoClBoC+XNutW7emNK+urjb/t65j7ty51qdPn6gK2K9fv2bNb7rpJjv33HPNYZGj+AoAgAGaA4AAIAAIACpDCAAIABYLAHf+f+EVwBd+N2KN9PZl3FGjRq017XO5nA0ePNjef/99mz59erO2ixYtsl122cWOOuooGzt2rNKNsC2QAgBggJAxAG459kLLdEq216IiWyG32NAtK/tYdaPuU6X7VFTkpHYq306mU/6PVi+WmoiMv/DkR7JT5QdLZZ9ctbZsUbF0udxGdqNP776TOtdv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lO2U050aK3SfTIp2clo7uSq9jTQ+jdUp2umgT05dui+TdF5ep9+R13bT2vATqqzQr2X9mo+la3Hj5dkqyWeb2oWSvRtnTI/lPz/cWG7nzXc2lH06vJms38c/XL1IbsKqP9Cvv7Jeb6dRC2XUQGW9dm65jDZe6Fex0iOrdzPLaPcyUTvLu2nXk62vs1duGJ6qqpZUi3heGlB7VHgF8MPbbP78+datW7em5qurq83/re1orgJYX19vvgx86623WlVVlWUymWg5+Kijjkp6adgVWAEAMEBQANDMAEApgwBAAFBKGDMAUBUMALTa2lobsN7/CwfAj363hvojR460UaNGyQB42WWX2a9//Wvz/91iiy3MHxo599xzo6XigQMHpogyLqEKAIABCgKAACAVQK1sRAVQH3CoAOqaUQEsHAAWogL48ccfR1DqsHfwwQc3BfS4446zf//73/bYY4/pQcYjWAEAMEBCABAABAABQGUIYQlYWzJVtM23BQBrbUDX74dXAJdMTLVcvfoScDxXPvLII3bggQc2herEE0+0efPmRU8EcxRfAQAwQHMAEAAEAAFAZQgBAAHAYu0B/EbnIcEA+OSyOxMDoL/nb+7cuVF32Hnnne3yyy+3fffd17p3726bb765ff3rX7f33nvPrrnmmmgJeOrUqdE7AN2OdwEqo0jhbAHAAC0BQAAQAAQAlSEEAAQA2ysA+lO9DnyrH0cffbTdfPPN9s4770R7/rzat3jx4ggCTzjhBDvttNPMK4YcxVcAAAzQHAAEAAFAAFAZQgDA4kz0LAHX2jdqjgivAH78+8QVQKUfYNs2FAAAA+IAAAKAACAAqAwhACAAWLQKYPXh4QC4/C4AUOngJWYLAAYEDAAEAAFAAFAZQgBAALBoANjxe1ZV0UFJz1VsG3Ir7Mn6uwHA1Aq2fUcAMCBGACAACAACgMoQAgACgACg0mOwbU0FAMAAdQFAABAABACVIQQABACLBYD7Vn03uAL454Z7qAAqHbzEbMseAK+99lobP368LViwwLbffnu78sor7atf/WqiMAKAACAACAAmGiw+MQIAAcCiAWDld8IBMHsfAKh08BKzLWsA/P3vfx99h9AhcK+99rIbbrgh+jbh7Nmzo/cWresAAAFAABAAXNc4kf93ABAABACVHoNtaypQ1gC4++67///2zjXEqqqN44+jr5qa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\" width=\"640\">" 1704 ], 1705 "text/plain": [ 1706 "<IPython.core.display.HTML object>" 1707 ] 1708 }, 1709 "metadata": {}, 1710 "output_type": "display_data" 1711 } 1712 ], 1713 "source": [ 1714 "\"\"\"Animated MLX Thermal Camera Demo\n", 1715 "\"\"\"\n", 1716 "%matplotlib notebook\n", 1717 "\n", 1718 "# Set up plot\n", 1719 "fig, ax = plt.subplots()\n", 1720 "grid_x, grid_y = np.mgrid[0:31:32j, 0:23:24j]\n", 1721 "\n", 1722 "def animate(i):\n", 1723 " # read in frame from thermal camera and split into 32 x 24 numpy array of thermal readings\n", 1724 " frame = [0] * 768\n", 1725 " mlx.getFrame(frame)\n", 1726 " pixels = np.split(np.asarray(frame), 24)\n", 1727 " # rotate it around so its right side\n", 1728 " pixels = np.rot90(pixels, 3)\n", 1729 " \n", 1730 " # Clear the current figure\n", 1731 " plt.clf()\n", 1732 " \n", 1733 " # Create a color plot with a rectangular grid\n", 1734 " plt.pcolormesh(grid_x, grid_y, pixels)\n", 1735 " plt.colorbar()\n", 1736 " plt.title(\"Animated MLX Thermal Camera (32x24)\")\n", 1737 " plt.show()\n", 1738 " plt.pause(0.05)\n", 1739 "\n", 1740 "ani = animation.FuncAnimation(fig, animate)" 1741 ] 1742 } 1743 ], 1744 "metadata": { 1745 "kernelspec": { 1746 "display_name": "Python 3", 1747 "language": "python", 1748 "name": "python3" 1749 }, 1750 "language_info": { 1751 "codemirror_mode": { 1752 "name": "ipython", 1753 "version": 3 1754 }, 1755 "file_extension": ".py", 1756 "mimetype": "text/x-python", 1757 "name": "python", 1758 "nbconvert_exporter": "python", 1759 "pygments_lexer": "ipython3", 1760 "version": "3.7.4" 1761 } 1762 }, 1763 "nbformat": 4, 1764 "nbformat_minor": 2 1765 }