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

1030 lines
84 KiB

{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"%matplotlib notebook\n",
"%matplotlib notebook\n",
"\n",
"import matplotlib.pyplot as plt\n",
"from matplotlib import cm\n",
"import numpy as np\n",
"import h5py as h5py\n",
"import cartopy.crs as ccrs\n",
"import cartopy.feature as cfeature\n",
"from cartopy.io.shapereader import Reader\n",
"from cartopy.feature import ShapelyFeature"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"# hdf5 = '/notebooks/resources/3B-MO.MS.MRG.3IMERG.20150801-S000000-E235959.08.V03D.HDF5'\n",
"# hdf5 = '/notebooks/resources/3B-MO.MS.MRG.3IMERG.20150801-S000000-E235959.08.V06A.HDF5'\n",
"hdf5 = '/notebooks/resources/3B-MO.MS.MRG.3IMERG.20190101-S000000-E235959.01.V06A.HDF5'\n",
"dataset = h5py.File(hdf5,'r') # Change this to the proper path"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"precip = dataset['Grid/precipitation'][:]\n",
"\n",
"precip = np.transpose(precip[0])\n",
"\n",
" \n",
"\n",
"theLats= dataset['Grid/lat'][:]\n",
"\n",
"theLons = dataset['Grid/lon'][:]"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"scrolled": false
},
"outputs": [
{
"data": {
"application/javascript": [
"/* Put everything inside the global mpl namespace */\n",
"window.mpl = {};\n",
"\n",
"\n",
"mpl.get_websocket_type = function() {\n",
" if (typeof(WebSocket) !== 'undefined') {\n",
" return WebSocket;\n",
" } else if (typeof(MozWebSocket) !== 'undefined') {\n",
" return MozWebSocket;\n",
" } else {\n",
" alert('Your browser does not have WebSocket support.' +\n",
" 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
" 'Firefox 4 and 5 are also supported but you ' +\n",
" 'have to enable WebSockets in about:config.');\n",
" };\n",
"}\n",
"\n",
"mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n",
" this.id = figure_id;\n",
"\n",
" this.ws = websocket;\n",
"\n",
" this.supports_binary = (this.ws.binaryType != undefined);\n",
"\n",
" if (!this.supports_binary) {\n",
" var warnings = document.getElementById(\"mpl-warnings\");\n",
" if (warnings) {\n",
" warnings.style.display = 'block';\n",
" warnings.textContent = (\n",
" \"This browser does not support binary websocket messages. \" +\n",
" \"Performance may be slow.\");\n",
" }\n",
" }\n",
"\n",
" this.imageObj = new Image();\n",
"\n",
" this.context = undefined;\n",
" this.message = undefined;\n",
" this.canvas = undefined;\n",
" this.rubberband_canvas = undefined;\n",
" this.rubberband_context = undefined;\n",
" this.format_dropdown = undefined;\n",
"\n",
" this.image_mode = 'full';\n",
"\n",
" this.root = $('<div/>');\n",
" this._root_extra_style(this.root)\n",
" this.root.attr('style', 'display: inline-block');\n",
"\n",
" $(parent_element).append(this.root);\n",
"\n",
" this._init_header(this);\n",
" this._init_canvas(this);\n",
" this._init_toolbar(this);\n",
"\n",
" var fig = this;\n",
"\n",
" this.waiting = false;\n",
"\n",
" this.ws.onopen = function () {\n",
" fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n",
" fig.send_message(\"send_image_mode\", {});\n",
" if (mpl.ratio != 1) {\n",
" fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n",
" }\n",
" fig.send_message(\"refresh\", {});\n",
" }\n",
"\n",
" this.imageObj.onload = function() {\n",
" if (fig.image_mode == 'full') {\n",
" // Full images could contain transparency (where diff images\n",
" // almost always do), so we need to clear the canvas so that\n",
" // there is no ghosting.\n",
" fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
" }\n",
" fig.context.drawImage(fig.imageObj, 0, 0);\n",
" };\n",
"\n",
" this.imageObj.onunload = function() {\n",
" fig.ws.close();\n",
" }\n",
"\n",
" this.ws.onmessage = this._make_on_message_function(this);\n",
"\n",
" this.ondownload = ondownload;\n",
"}\n",
"\n",
"mpl.figure.prototype._init_header = function() {\n",
" var titlebar = $(\n",
" '<div class=\"ui-dialog-titlebar ui-widget-header ui-corner-all ' +\n",
" 'ui-helper-clearfix\"/>');\n",
" var titletext = $(\n",
" '<div class=\"ui-dialog-title\" style=\"width: 100%; ' +\n",
" 'text-align: center; padding: 3px;\"/>');\n",
" titlebar.append(titletext)\n",
" this.root.append(titlebar);\n",
" this.header = titletext[0];\n",
"}\n",
"\n",
"\n",
"\n",
"mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n",
"\n",
"}\n",
"\n",
"\n",
"mpl.figure.prototype._root_extra_style = function(canvas_div) {\n",
"\n",
"}\n",
"\n",
"mpl.figure.prototype._init_canvas = function() {\n",
" var fig = this;\n",
"\n",
" var canvas_div = $('<div/>');\n",
"\n",
" canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n",
"\n",
" function canvas_keyboard_event(event) {\n",
" return fig.key_event(event, event['data']);\n",
" }\n",
"\n",
" canvas_div.keydown('key_press', canvas_keyboard_event);\n",
" canvas_div.keyup('key_release', canvas_keyboard_event);\n",
" this.canvas_div = canvas_div\n",
" this._canvas_extra_style(canvas_div)\n",
" this.root.append(canvas_div);\n",
"\n",
" var canvas = $('<canvas/>');\n",
" canvas.addClass('mpl-canvas');\n",
" canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n",
"\n",
" this.canvas = canvas[0];\n",
" this.context = canvas[0].getContext(\"2d\");\n",
"\n",
" var backingStore = this.context.backingStorePixelRatio ||\n",
"\tthis.context.webkitBackingStorePixelRatio ||\n",
"\tthis.context.mozBackingStorePixelRatio ||\n",
"\tthis.context.msBackingStorePixelRatio ||\n",
"\tthis.context.oBackingStorePixelRatio ||\n",
"\tthis.context.backingStorePixelRatio || 1;\n",
"\n",
" mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n",
"\n",
" var rubberband = $('<canvas/>');\n",
" rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n",
"\n",
" var pass_mouse_events = true;\n",
"\n",
" canvas_div.resizable({\n",
" start: function(event, ui) {\n",
" pass_mouse_events = false;\n",
" },\n",
" resize: function(event, ui) {\n",
" fig.request_resize(ui.size.width, ui.size.height);\n",
" },\n",
" stop: function(event, ui) {\n",
" pass_mouse_events = true;\n",
" fig.request_resize(ui.size.width, ui.size.height);\n",
" },\n",
" });\n",
"\n",
" function mouse_event_fn(event) {\n",
" if (pass_mouse_events)\n",
" return fig.mouse_event(event, event['data']);\n",
" }\n",
"\n",
" rubberband.mousedown('button_press', mouse_event_fn);\n",
" rubberband.mouseup('button_release', mouse_event_fn);\n",
" // Throttle sequential mouse events to 1 every 20ms.\n",
" rubberband.mousemove('motion_notify', mouse_event_fn);\n",
"\n",
" rubberband.mouseenter('figure_enter', mouse_event_fn);\n",
" rubberband.mouseleave('figure_leave', mouse_event_fn);\n",
"\n",
" canvas_div.on(\"wheel\", function (event) {\n",
" event = event.originalEvent;\n",
" event['data'] = 'scroll'\n",
" if (event.deltaY < 0) {\n",
" event.step = 1;\n",
" } else {\n",
" event.step = -1;\n",
" }\n",
" mouse_event_fn(event);\n",
" });\n",
"\n",
" canvas_div.append(canvas);\n",
" canvas_div.append(rubberband);\n",
"\n",
" this.rubberband = rubberband;\n",
" this.rubberband_canvas = rubberband[0];\n",
" this.rubberband_context = rubberband[0].getContext(\"2d\");\n",
" this.rubberband_context.strokeStyle = \"#000000\";\n",
"\n",
" this._resize_canvas = function(width, height) {\n",
" // Keep the size of the canvas, canvas container, and rubber band\n",
" // canvas in synch.\n",
" canvas_div.css('width', width)\n",
" canvas_div.css('height', height)\n",
"\n",
" canvas.attr('width', width * mpl.ratio);\n",
" canvas.attr('height', height * mpl.ratio);\n",
" canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n",
"\n",
" rubberband.attr('width', width);\n",
" rubberband.attr('height', height);\n",
" }\n",
"\n",
" // Set the figure to an initial 600x600px, this will subsequently be updated\n",
" // upon first draw.\n",
" this._resize_canvas(600, 600);\n",
"\n",
" // Disable right mouse context menu.\n",
" $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n",
" return false;\n",
" });\n",
"\n",
" function set_focus () {\n",
" canvas.focus();\n",
" canvas_div.focus();\n",
" }\n",
"\n",
" window.setTimeout(set_focus, 100);\n",
"}\n",
"\n",
"mpl.figure.prototype._init_toolbar = function() {\n",
" var fig = this;\n",
"\n",
" var nav_element = $('<div/>')\n",
" nav_element.attr('style', 'width: 100%');\n",
" this.root.append(nav_element);\n",
"\n",
" // Define a callback function for later on.\n",
" function toolbar_event(event) {\n",
" return fig.toolbar_button_onclick(event['data']);\n",
" }\n",
" function toolbar_mouse_event(event) {\n",
" return fig.toolbar_button_onmouseover(event['data']);\n",
" }\n",
"\n",
" for(var toolbar_ind in mpl.toolbar_items) {\n",
" var name = mpl.toolbar_items[toolbar_ind][0];\n",
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
" var image = mpl.toolbar_items[toolbar_ind][2];\n",
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
"\n",
" if (!name) {\n",
" // put a spacer in here.\n",
" continue;\n",
" }\n",
" var button = $('<button/>');\n",
" button.addClass('ui-button ui-widget ui-state-default ui-corner-all ' +\n",
" 'ui-button-icon-only');\n",
" button.attr('role', 'button');\n",
" button.attr('aria-disabled', 'false');\n",
" button.click(method_name, toolbar_event);\n",
" button.mouseover(tooltip, toolbar_mouse_event);\n",
"\n",
" var icon_img = $('<span/>');\n",
" icon_img.addClass('ui-button-icon-primary ui-icon');\n",
" icon_img.addClass(image);\n",
" icon_img.addClass('ui-corner-all');\n",
"\n",
" var tooltip_span = $('<span/>');\n",
" tooltip_span.addClass('ui-button-text');\n",
" tooltip_span.html(tooltip);\n",
"\n",
" button.append(icon_img);\n",
" button.append(tooltip_span);\n",
"\n",
" nav_element.append(button);\n",
" }\n",
"\n",
" var fmt_picker_span = $('<span/>');\n",
"\n",
" var fmt_picker = $('<select/>');\n",
" fmt_picker.addClass('mpl-toolbar-option ui-widget ui-widget-content');\n",
" fmt_picker_span.append(fmt_picker);\n",
" nav_element.append(fmt_picker_span);\n",
" this.format_dropdown = fmt_picker[0];\n",
"\n",
" for (var ind in mpl.extensions) {\n",
" var fmt = mpl.extensions[ind];\n",
" var option = $(\n",
" '<option/>', {selected: fmt === mpl.default_extension}).html(fmt);\n",
" fmt_picker.append(option)\n",
" }\n",
"\n",
" // Add hover states to the ui-buttons\n",
" $( \".ui-button\" ).hover(\n",
" function() { $(this).addClass(\"ui-state-hover\");},\n",
" function() { $(this).removeClass(\"ui-state-hover\");}\n",
" );\n",
"\n",
" var status_bar = $('<span class=\"mpl-message\"/>');\n",
" nav_element.append(status_bar);\n",
" this.message = status_bar[0];\n",
"}\n",
"\n",
"mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n",
" // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n",
" // which will in turn request a refresh of the image.\n",
" this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n",
"}\n",
"\n",
"mpl.figure.prototype.send_message = function(type, properties) {\n",
" properties['type'] = type;\n",
" properties['figure_id'] = this.id;\n",
" this.ws.send(JSON.stringify(properties));\n",
"}\n",
"\n",
"mpl.figure.prototype.send_draw_message = function() {\n",
" if (!this.waiting) {\n",
" this.waiting = true;\n",
" this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n",
" }\n",
"}\n",
"\n",
"\n",
"mpl.figure.prototype.handle_save = function(fig, msg) {\n",
" var format_dropdown = fig.format_dropdown;\n",
" var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n",
" fig.ondownload(fig, format);\n",
"}\n",
"\n",
"\n",
"mpl.figure.prototype.handle_resize = function(fig, msg) {\n",
" var size = msg['size'];\n",
" if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n",
" fig._resize_canvas(size[0], size[1]);\n",
" fig.send_message(\"refresh\", {});\n",
" };\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n",
" var x0 = msg['x0'] / mpl.ratio;\n",
" var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n",
" var x1 = msg['x1'] / mpl.ratio;\n",
" var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n",
" x0 = Math.floor(x0) + 0.5;\n",
" y0 = Math.floor(y0) + 0.5;\n",
" x1 = Math.floor(x1) + 0.5;\n",
" y1 = Math.floor(y1) + 0.5;\n",
" var min_x = Math.min(x0, x1);\n",
" var min_y = Math.min(y0, y1);\n",
" var width = Math.abs(x1 - x0);\n",
" var height = Math.abs(y1 - y0);\n",
"\n",
" fig.rubberband_context.clearRect(\n",
" 0, 0, fig.canvas.width, fig.canvas.height);\n",
"\n",
" fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n",
" // Updates the figure title.\n",
" fig.header.textContent = msg['label'];\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_cursor = function(fig, msg) {\n",
" var cursor = msg['cursor'];\n",
" switch(cursor)\n",
" {\n",
" case 0:\n",
" cursor = 'pointer';\n",
" break;\n",
" case 1:\n",
" cursor = 'default';\n",
" break;\n",
" case 2:\n",
" cursor = 'crosshair';\n",
" break;\n",
" case 3:\n",
" cursor = 'move';\n",
" break;\n",
" }\n",
" fig.rubberband_canvas.style.cursor = cursor;\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_message = function(fig, msg) {\n",
" fig.message.textContent = msg['message'];\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_draw = function(fig, msg) {\n",
" // Request the server to send over a new figure.\n",
" fig.send_draw_message();\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n",
" fig.image_mode = msg['mode'];\n",
"}\n",
"\n",
"mpl.figure.prototype.updated_canvas_event = function() {\n",
" // Called whenever the canvas gets updated.\n",
" this.send_message(\"ack\", {});\n",
"}\n",
"\n",
"// A function to construct a web socket function for onmessage handling.\n",
"// Called in the figure constructor.\n",
"mpl.figure.prototype._make_on_message_function = function(fig) {\n",
" return function socket_on_message(evt) {\n",
" if (evt.data instanceof Blob) {\n",
" /* FIXME: We get \"Resource interpreted as Image but\n",
" * transferred with MIME type text/plain:\" errors on\n",
" * Chrome. But how to set the MIME type? It doesn't seem\n",
" * to be part of the websocket stream */\n",
" evt.data.type = \"image/png\";\n",
"\n",
" /* Free the memory for the previous frames */\n",
" if (fig.imageObj.src) {\n",
" (window.URL || window.webkitURL).revokeObjectURL(\n",
" fig.imageObj.src);\n",
" }\n",
"\n",
" fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
" evt.data);\n",
" fig.updated_canvas_event();\n",
" fig.waiting = false;\n",
" return;\n",
" }\n",
" else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n",
" fig.imageObj.src = evt.data;\n",
" fig.updated_canvas_event();\n",
" fig.waiting = false;\n",
" return;\n",
" }\n",
"\n",
" var msg = JSON.parse(evt.data);\n",
" var msg_type = msg['type'];\n",
"\n",
" // Call the \"handle_{type}\" callback, which takes\n",
" // the figure and JSON message as its only arguments.\n",
" try {\n",
" var callback = fig[\"handle_\" + msg_type];\n",
" } catch (e) {\n",
" console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n",
" return;\n",
" }\n",
"\n",
" if (callback) {\n",
" try {\n",
" // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n",
" callback(fig, msg);\n",
" } catch (e) {\n",
" console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n",
" }\n",
" }\n",
" };\n",
"}\n",
"\n",
"// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n",
"mpl.findpos = function(e) {\n",
" //this section is from http://www.quirksmode.org/js/events_properties.html\n",
" var targ;\n",
" if (!e)\n",
" e = window.event;\n",
" if (e.target)\n",
" targ = e.target;\n",
" else if (e.srcElement)\n",
" targ = e.srcElement;\n",
" if (targ.nodeType == 3) // defeat Safari bug\n",
" targ = targ.parentNode;\n",
"\n",
" // jQuery normalizes the pageX and pageY\n",
" // pageX,Y are the mouse positions relative to the document\n",
" // offset() returns the position of the element relative to the document\n",
" var x = e.pageX - $(targ).offset().left;\n",
" var y = e.pageY - $(targ).offset().top;\n",
"\n",
" return {\"x\": x, \"y\": y};\n",
"};\n",
"\n",
"/*\n",
" * return a copy of an object with only non-object keys\n",
" * we need this to avoid circular references\n",
" * http://stackoverflow.com/a/24161582/3208463\n",
" */\n",
"function simpleKeys (original) {\n",
" return Object.keys(original).reduce(function (obj, key) {\n",
" if (typeof original[key] !== 'object')\n",
" obj[key] = original[key]\n",
" return obj;\n",
" }, {});\n",
"}\n",
"\n",
"mpl.figure.prototype.mouse_event = function(event, name) {\n",
" var canvas_pos = mpl.findpos(event)\n",
"\n",
" if (name === 'button_press')\n",
" {\n",
" this.canvas.focus();\n",
" this.canvas_div.focus();\n",
" }\n",
"\n",
" var x = canvas_pos.x * mpl.ratio;\n",
" var y = canvas_pos.y * mpl.ratio;\n",
"\n",
" this.send_message(name, {x: x, y: y, button: event.button,\n",
" step: event.step,\n",
" guiEvent: simpleKeys(event)});\n",
"\n",
" /* This prevents the web browser from automatically changing to\n",
" * the text insertion cursor when the button is pressed. We want\n",
" * to control all of the cursor setting manually through the\n",
" * 'cursor' event from matplotlib */\n",
" event.preventDefault();\n",
" return false;\n",
"}\n",
"\n",
"mpl.figure.prototype._key_event_extra = function(event, name) {\n",
" // Handle any extra behaviour associated with a key event\n",
"}\n",
"\n",
"mpl.figure.prototype.key_event = function(event, name) {\n",
"\n",
" // Prevent repeat events\n",
" if (name == 'key_press')\n",
" {\n",
" if (event.which === this._key)\n",
" return;\n",
" else\n",
" this._key = event.which;\n",
" }\n",
" if (name == 'key_release')\n",
" this._key = null;\n",
"\n",
" var value = '';\n",
" if (event.ctrlKey && event.which != 17)\n",
" value += \"ctrl+\";\n",
" if (event.altKey && event.which != 18)\n",
" value += \"alt+\";\n",
" if (event.shiftKey && event.which != 16)\n",
" value += \"shift+\";\n",
"\n",
" value += 'k';\n",
" value += event.which.toString();\n",
"\n",
" this._key_event_extra(event, name);\n",
"\n",
" this.send_message(name, {key: value,\n",
" guiEvent: simpleKeys(event)});\n",
" return false;\n",
"}\n",
"\n",
"mpl.figure.prototype.toolbar_button_onclick = function(name) {\n",
" if (name == 'download') {\n",
" this.handle_save(this, null);\n",
" } else {\n",
" this.send_message(\"toolbar_button\", {name: name});\n",
" }\n",
"};\n",
"\n",
"mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n",
" this.message.textContent = tooltip;\n",
"};\n",
"mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n",
"\n",
"mpl.extensions = [\"eps\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
"\n",
"mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n",
" // Create a \"websocket\"-like object which calls the given IPython comm\n",
" // object with the appropriate methods. Currently this is a non binary\n",
" // socket, so there is still some room for performance tuning.\n",
" var ws = {};\n",
"\n",
" ws.close = function() {\n",
" comm.close()\n",
" };\n",
" ws.send = function(m) {\n",
" //console.log('sending', m);\n",
" comm.send(m);\n",
" };\n",
" // Register the callback with on_msg.\n",
" comm.on_msg(function(msg) {\n",
" //console.log('receiving', msg['content']['data'], msg);\n",
" // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
" ws.onmessage(msg['content']['data'])\n",
" });\n",
" return ws;\n",
"}\n",
"\n",
"mpl.mpl_figure_comm = function(comm, msg) {\n",
" // This is the function which gets called when the mpl process\n",
" // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
"\n",
" var id = msg.content.data.id;\n",
" // Get hold of the div created by the display call when the Comm\n",
" // socket was opened in Python.\n",
" var element = $(\"#\" + id);\n",
" var ws_proxy = comm_websocket_adapter(comm)\n",
"\n",
" function ondownload(figure, format) {\n",
" window.open(figure.imageObj.src);\n",
" }\n",
"\n",
" var fig = new mpl.figure(id, ws_proxy,\n",
" ondownload,\n",
" element.get(0));\n",
"\n",
" // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n",
" // web socket which is closed, not our websocket->open comm proxy.\n",
" ws_proxy.onopen();\n",
"\n",
" fig.parent_element = element.get(0);\n",
" fig.cell_info = mpl.find_output_cell(\"<div id='\" + id + \"'></div>\");\n",
" if (!fig.cell_info) {\n",
" console.error(\"Failed to find cell for figure\", id, fig);\n",
" return;\n",
" }\n",
"\n",
" var output_index = fig.cell_info[2]\n",
" var cell = fig.cell_info[0];\n",
"\n",
"};\n",
"\n",
"mpl.figure.prototype.handle_close = function(fig, msg) {\n",
" var width = fig.canvas.width/mpl.ratio\n",
" fig.root.unbind('remove')\n",
"\n",
" // Update the output cell to use the data from the current canvas.\n",
" fig.push_to_output();\n",
" var dataURL = fig.canvas.toDataURL();\n",
" // Re-enable the keyboard manager in IPython - without this line, in FF,\n",
" // the notebook keyboard shortcuts fail.\n",
" IPython.keyboard_manager.enable()\n",
" $(fig.parent_element).html('<img src=\"' + dataURL + '\" width=\"' + width + '\">');\n",
" fig.close_ws(fig, msg);\n",
"}\n",
"\n",
"mpl.figure.prototype.close_ws = function(fig, msg){\n",
" fig.send_message('closing', msg);\n",
" // fig.ws.close()\n",
"}\n",
"\n",
"mpl.figure.prototype.push_to_output = function(remove_interactive) {\n",
" // Turn the data on the canvas into data in the output cell.\n",
" var width = this.canvas.width/mpl.ratio\n",
" var dataURL = this.canvas.toDataURL();\n",
" this.cell_info[1]['text/html'] = '<img src=\"' + dataURL + '\" width=\"' + width + '\">';\n",
"}\n",
"\n",
"mpl.figure.prototype.updated_canvas_event = function() {\n",
" // Tell IPython that the notebook contents must change.\n",
" IPython.notebook.set_dirty(true);\n",
" this.send_message(\"ack\", {});\n",
" var fig = this;\n",
" // Wait a second, then push the new image to the DOM so\n",
" // that it is saved nicely (might be nice to debounce this).\n",
" setTimeout(function () { fig.push_to_output() }, 1000);\n",
"}\n",
"\n",
"mpl.figure.prototype._init_toolbar = function() {\n",
" var fig = this;\n",
"\n",
" var nav_element = $('<div/>')\n",
" nav_element.attr('style', 'width: 100%');\n",
" this.root.append(nav_element);\n",
"\n",
" // Define a callback function for later on.\n",
" function toolbar_event(event) {\n",
" return fig.toolbar_button_onclick(event['data']);\n",
" }\n",
" function toolbar_mouse_event(event) {\n",
" return fig.toolbar_button_onmouseover(event['data']);\n",
" }\n",
"\n",
" for(var toolbar_ind in mpl.toolbar_items){\n",
" var name = mpl.toolbar_items[toolbar_ind][0];\n",
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
" var image = mpl.toolbar_items[toolbar_ind][2];\n",
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
"\n",
" if (!name) { continue; };\n",
"\n",
" var button = $('<button class=\"btn btn-default\" href=\"#\" title=\"' + name + '\"><i class=\"fa ' + image + ' fa-lg\"></i></button>');\n",
" button.click(method_name, toolbar_event);\n",
" button.mouseover(tooltip, toolbar_mouse_event);\n",
" nav_element.append(button);\n",
" }\n",
"\n",
" // Add the status bar.\n",
" var status_bar = $('<span class=\"mpl-message\" style=\"text-align:right; float: right;\"/>');\n",
" nav_element.append(status_bar);\n",
" this.message = status_bar[0];\n",
"\n",
" // Add the close button to the window.\n",
" var buttongrp = $('<div class=\"btn-group inline pull-right\"></div>');\n",
" var button = $('<button class=\"btn btn-mini btn-primary\" href=\"#\" title=\"Stop Interaction\"><i class=\"fa fa-power-off icon-remove icon-large\"></i></button>');\n",
" button.click(function (evt) { fig.handle_close(fig, {}); } );\n",
" button.mouseover('Stop Interaction', toolbar_mouse_event);\n",
" buttongrp.append(button);\n",
" var titlebar = this.root.find($('.ui-dialog-titlebar'));\n",
" titlebar.prepend(buttongrp);\n",
"}\n",
"\n",
"mpl.figure.prototype._root_extra_style = function(el){\n",
" var fig = this\n",
" el.on(\"remove\", function(){\n",
"\tfig.close_ws(fig, {});\n",
" });\n",
"}\n",
"\n",
"mpl.figure.prototype._canvas_extra_style = function(el){\n",
" // this is important to make the div 'focusable\n",
" el.attr('tabindex', 0)\n",
" // reach out to IPython and tell the keyboard manager to turn it's self\n",
" // off when our div gets focus\n",
"\n",
" // location in version 3\n",
" if (IPython.notebook.keyboard_manager) {\n",
" IPython.notebook.keyboard_manager.register_events(el);\n",
" }\n",
" else {\n",
" // location in version 2\n",
" IPython.keyboard_manager.register_events(el);\n",
" }\n",
"\n",
"}\n",
"\n",
"mpl.figure.prototype._key_event_extra = function(event, name) {\n",
" var manager = IPython.notebook.keyboard_manager;\n",
" if (!manager)\n",
" manager = IPython.keyboard_manager;\n",
"\n",
" // Check for shift+enter\n",
" if (event.shiftKey && event.which == 13) {\n",
" this.canvas_div.blur();\n",
" event.shiftKey = false;\n",
" // Send a \"J\" for go to next cell\n",
" event.which = 74;\n",
" event.keyCode = 74;\n",
" manager.command_mode();\n",
" manager.handle_keydown(event);\n",
" }\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_save = function(fig, msg) {\n",
" fig.ondownload(fig, null);\n",
"}\n",
"\n",
"\n",
"mpl.find_output_cell = function(html_output) {\n",
" // Return the cell and output element which can be found *uniquely* in the notebook.\n",
" // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n",
" // IPython event is triggered only after the cells have been serialised, which for\n",
" // our purposes (turning an active figure into a static one), is too late.\n",
" var cells = IPython.notebook.get_cells();\n",
" var ncells = cells.length;\n",
" for (var i=0; i<ncells; i++) {\n",
" var cell = cells[i];\n",
" if (cell.cell_type === 'code'){\n",
" for (var j=0; j<cell.output_area.outputs.length; j++) {\n",
" var data = cell.output_area.outputs[j];\n",
" if (data.data) {\n",
" // IPython >= 3 moved mimebundle to data attribute of output\n",
" data = data.data;\n",
" }\n",
" if (data['text/html'] == html_output) {\n",
" return [cell, data, j];\n",
" }\n",
" }\n",
" }\n",
" }\n",
"}\n",
"\n",
"// Register the function which deals with the matplotlib target/channel.\n",
"// The kernel may be null if the page has been refreshed.\n",
"if (IPython.notebook.kernel != null) {\n",
" IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n",
"}\n"
],
"text/plain": [
"<IPython.core.display.Javascript object>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"<img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAsAAAAIQCAYAAACPEdjAAAAgAElEQVR4nOydd3xUVfrG3/QektBrwAABQkmQHukgIL33jhCQEkIJIAIiIiAIIqB0pDcVFrHhrr2AiKgIAmHVjWX3p66y6roq8vz+OJlJJlNIJjNzz8w83/08nzV3bjn3zoR8c3LOewSEEEIIIYT4EWJ0AwghhBBCCPEkFGBCCCGEEOJXUIAJIYQQQohfQQEmhBBCCCF+BQWYEEIIIYT4FRRgQgghhBDiV1CACSGEEEKIX0EBJoQQQgghfgUFmBBCCCGE+BUUYEIIIYQQ4ldQgAkhhBBCiF9BASaEEEIIIX4FBZgQQgghhPgVFGBCCCGEEOJXUIAJIYQQQohfQQEmhBBCCCF+BQWYEEIIIYT4FRRgQgghhBDiV1CACSGEEEKIX0EBJoQQQgghfgUFmBBCCCGE+BUUYEIIIYQQ4ldQgAkhhBBCiF9BASaEEEIIIX4FBZgQQgghhPgVFGBCCCGEEOJXUIAJIYQQQohfQQEmhBBCCCF+BQWYEEIIIYT4FRRgQgghhBDiV1CACSGEEEKIX0EBJoQQQgghfgUFmBBCCCGE+BUUYEIIIYQQ4ldQgAkhhBBCiF9BASaEEEIIIX4FBZgQQgghhPgVFGBCCCGEEOJXUIAJIYQQQohfQQEmhBBiRdu2bZGYmFjk/UUEo0ePdlt7iN6kp6cjKSnJ6GYQUmQowIQYzO+//45y5cpBRHDfffcZ3RyX8corr2Dx4sX44YcfinzMuXPnMHfuXDRp0gSlS5dGdHQ0GjRogIULF9o9zy+//ILs7GwkJiYiNDQUiYmJmDdvHn755RerfV966SVkZGSgefPmiIiIgIhgz549dtuTmJgIEbGZEydOFOmeFi9ebD5mx44dNvfJyclBQEAARAQdO3Ys0nldwdq1a7Fz506br+kowGlpaRARjBw50q3X8UXS09MtPr9BQUEoX748+vTpg3feeccl53eHAF+9etXqey8sLAy1a9fG7Nmzi/Xviy2+//57LF68GK+99pqLWky8BQowIQZz9OhRiAhq1qyJKlWq4MaNG0Y3ySWYxO+zzz4r8jGDBw9GfHw8xo4diw0bNmDTpk3o378/RASJiYn417/+ZbH/jRs30LZtW7MUbd26FVOnTkVQUBA6dOiAP//802L/0aNHIzg4GA0bNkSzZs2KJMB16tTBnj17rPLll18W6zmEh4cjPT3d5j7z589HeHi4xwU4MTERbdu2tfmabgJ89uxZ8/dJREREicXH30hPT0dISIj587t161ZMnz4dkZGRCAkJwVtvvVWi8//222/47bffXNTafEwC3KFDB3Pb161bhy5dukBEkJqaij/++KPE53/ggQdc2GriDVCACTGYLl26oFatWjhx4gREBM8++6zRTXIJzgjwm2++if/+979W2+fPnw8RwZw5cyy2b9++HSKCadOmWWxfvXo1RARPPvmkxfYvv/wSv/76KwBg586dRRJge4JYVEzPYdiwYRARfPrppxav37hxA5UqVcLw4cMpwA6YNGkSYmNjcfr0aYgINmzY4LZrFZUbN27Y/EuDjqSnpyMsLMxq+5EjRyAi6NOnjwGtujUmQZ00aZLVa927d4eI4NixYyU+PwXY/6AAE2Ign3/+OQIDA/Hggw/ixo0bqFixot0fRPZk5bPPPoOIYPHixRbbr1+/jnvuuQfly5dHeHg4GjdujKefftqmmDqSHVtis3fvXrRo0QLx8fEIDw9H1apV0bdvX3zyySfm89kaNlC4jUXlww8/hIigS5cuFttN1/n8888ttv/3v/9FRESEQ5ksjgD/8ccfuH79Om7evFnstpue97PPPovIyEgriT9+/DhEBK+88opdAX7++efRrl07xMTEIDw8HI0aNcKGDRus2jN69GiICK5fv46pU6eiQoUKCA0NRVpaGl544QXzfqbPjK2YPhemz8Q333yDESNGICEhAeHh4WjdujXee+89qzYW/pykpKSgUqVKNv+i8f7770NEMGvWrCI9w59//hkxMTG4++67AQBNmzZFamqq1X7Z2dkQEbz77rtWr928eRM1atRAjRo1LJ7blStXMHLkSFSsWBEhISGoUqUKpkyZgu+//97i+Hvvvdf8C8ysWbNQtWpVBAUFmT8/zz//PAYPHowaNWogPDwcsbGxaNu2rd1faN955x20a9cOERERiI+Px+DBg5Gbm4vKlSvb/Ay8/PLL6NKlC+Li4hAaGoq6deti1apVRf6LkT0B/uGHHyAiSElJsXptw4YN6Ny5MypVqoSQkBCUK1cOAwYMMH+fFz5/4SEQpm1fffUVhg0bZv4MtWnTBu+//36R2u1IgNeuXQsRwcMPP2yxPTc3F1lZWUhNTUV8fLx5yMTChQvNvwADwNatW21+DxS+j5I+e6InFGBCDOS+++5DYGAgcnNzAQBz585FcHAwvvnmG6t9iyPAf/zxB1q0aAERwYABA7BhwwbMmzcPsbGxaNKkSYkEeO/evRARpKenY926ddi2bRvuv/9+tG3bFk8//TQANda2b9++EBGsXbvW/KfLDz/8sNjPCACee+45iAhGjRpl3nbz5k1ERkaiUqVKNo9p2bIlYmNj7Z6zqAIcHh6O0NBQiAgiIyPRq1cvnD9/vshtNwnwG2+8gVGjRqF8+fIWf7Lt2bMnatasiZs3b9oU4G3btiEgIACJiYlYunQpHnnkEbRq1QoiYhZCEyYBbtGiBbp27YpHH30UDz30EMqXL4/Q0FB88cUXAJRQ7tmzB2XKlLEa4vHzzz8DUJ+JMmXKoGbNmhg8eDA2btyIRYsWISYmBmXKlMF//vMfi2sX/pysX78eIoLjx49bPZOMjAyICC5fvlykZ2jq6X/77bcBAJs2bYKIWIn4pUuXICLIyMiwOofpF4wlS5aYt509exaxsbGoXLkyFi5ciC1btmDWrFmIiopC3bp1Le7RJMCpqalo1qwZVq1ahQ0bNphle+DAgejYsSMWLVqErVu3YtmyZahVqxZEBEePHrVoyzvvvIPw8HDExcVhwYIF2LBhA/r06YOkpCQkJCRYfQY2b96MgIAANGnSBCtWrMDjjz+O4cOHIyAgAMOHDy/SM7QnwKahJW3atLF6rWrVqhgyZAgeeughbNmyBbNnz0ZcXBxiY2Px97//3er8tgS4XLlyuO222zB06FBs3LgRCxcuRHR0NMqXL2/+rDnCkQBPnTrV5tj6EydOoHr16sjMzMRjjz2G9evXo0+fPhAR9OzZ07xfTk6O+a9FAwYMMH8PFOxRdsWzJ3pCASbEIG7cuIHKlStb9Gp++umnEBEsX77cav/iCPCWLVtsDhk4e/asebKVswLct29fxMTE4Pfff3d4f84MgbDFH3/8gebNm0NE8Le//c28/bvvvoOIoFmzZjaPGzhwoLk31BZFEeBu3bphyZIlOHToEI4cOYLs7GxERUUhPDwcr7/+epHaX1CAX3vtNYgInnnmGQDA119/jaCgIPP7XViAf/zxR0RHR6NixYr49ttvLZ5J586dzec1YRLgiRMnWrThnXfegYhg/vz5FttvNQTC1mfxwIEDEBFs3rzZYnvhz8mPP/6IyMhI9OjRw2K/X375xdw7WlRatGiB5ORk89c//PADwsPDre7TtG9cXBz+97//WWwfPXo0AgICzJ/HmzdvokGDBkhKSrIaT/zWW28hMDAQy5YtM28zCXC7du1sjjm1JXM//fQTkpKS0LBhQ4vtzZo1Q3BwsFVP6pQpU6w+A19++SXCwsLQv39/q/OvWLECIoI333zT6rXCmAT422+/xbfffosvv/wSzz//POrVqwcRwbZt24p0Tx999BGCg4Mxffp0q/PbEmARwapVqyy279mzByKC7du337LdJgEePXq0ue2XL1/G2rVrERISglKlSuG7776zOOa///2vzb/WmP5CcO7cOavz2xoC4apnT/SEAkyIQZjG/B48eNBie6tWrZCUlGT1D3hxBLhbt24QEasfDABw5513lkiAx44di6CgIDz11FNWk8wK4ioBvvvuuyEimDFjhsX2f/zjHxARtG7d2uZxI0eOhIjY7E0HiibAtjh//jxCQ0NRp06dIu1fUIABoHbt2mYpfPDBBxEUFISvv/4agLUAHz582O4vRCaZzszMNG8zCfCVK1es9o+Ojrb6QX4rAQ4MDLT4kzGQ/4tH4eELtobKjBs3DkFBQRYTBnfs2AERwb59+2xetzAff/wxRAQrVqyw2D5s2DDExMRYSdoTTzxh9X31008/ISoqCu3btzdv++CDDyAiWLhwoVmsCiYpKcnis2US4KJU//j555/x3Xff4dtvv8WECRMQEBBgHiv89ddf2x1za/pMF/wMmP7M//zzz1u18cKFCxApWvWYwlUgTClTpgzWr1/v8NibN2/i+vXr5uvWrVsXzZs3tzq/LQEODg62mhz3z3/+EyKC7OzsW7bbVhUIU1q0aHHLoRS///47vv/+e3z77bd4+eWXISJ4/PHHrc5vS4Bd9eyJnlCACTGIXr16ISIiAhcuXMDVq1fNWbJkCUQEf/3rXy32L44AJycno0yZMjavO2PGjBIJcE5OjvlPu/Hx8ejRowceeeQR/POf/7Q4zhUCPHPmTIgIhg4dajXezhM9wPYYPHgwRARXr1695b6FBXjFihVmKUxKSrL4k2xh+TH1MtmSrn//+99Wf9I1CbCtsYmJiYlo166d1TZHAlylShWbr4kIxowZY7WtsACfOXMGIoKlS5eat7Vs2RKlS5e26qG1x/Tp0yEieO211yy+T7Zt22azF/HHH39EREQEunbtat5meq8LTorcv3+/XbEypXbt2ub9TQJsb9jG3//+d/M4V1vn+uqrrwAAb7zxBkQE8+bNs3me6Ohoi8/AxIkTb9lOWz3hhTFVgTh16hROnTqFI0eOYMCAAQgKCsLatWttHvPKK6+gQ4cO5pKBBVOrVi2r89sS4OrVq1ud948//oCIYMKECbdst0lQe/TogVOnTuHFF1/E448/bq6ac/HiRZvnX758OZKTk81/8SqYBx980Or8tgTYVc+e6AkFmBAD+OqrrxAUFOTwH9ahQ4daHFO9enWbsmL6B7wkAtyuXTubAmz6QVVYbH7//Xe89NJLyM7ORqtWrRAYGIioqCiLWpolFWCT+IwYMcKm0HliDLA95s2bBxEpUumowgL8zTffIDg42NwTX3CMrKsE2Ba2ZNfZKhC2PhO2tgFA48aNkZiYiD///NPca5aVlWXzvIX59ddfER8f7/D7pGXLllbHDR061KJn3TSBsGDFBtNY9szMTLMUFk7B99ckwKbx+gX5z3/+g0qVKqFUqVJYtGgRjhw5ghdffBGnTp0y/7JkOq64AjxhwgSICHbu3Gm3nbYksDD2xgAPGzYMAQEBVr9wnz59GkFBQUhOTsbatWtx7NgxvPTSSzh16hTq1Kljd8LbrbYB+f+ujB8//pbttjcG+Ouvv0bp0qVRu3Ztq1+mTGODBw8ejJ07d+LkyZM4deqUeSx5Qdl1JMCuevZETyjAhBjAsmXLIKImiB05csQqXbt2RVhYmMUQhsaNG6NBgwZW53rxxRetBLi4QyD69euHmJgYq30vX75sV2wK8uGHHyIkJMRCpkw92cUV4Js3b5rHQo4dO9bhMIs2bdpAxH1VIOzRr18/iAiuXbt2y30LCzAA9O7dGyKCihUrWownLSzAphJVhf/8DwCvv/66WeBMFFeA7f1SBbhOgE3j0V944QXzL1+FS8HZwySp8+fPt/l9MmrUKIgILly4YHGc6Xti5cqV+OyzzxAQEIBx48ZZ7GPqnZ45c2aR2uJIgJ966imrHmYTps+K6bivvvoKIkUfArFq1SqrX5ScwZ4Af/PNN4iKikL9+vUtvtemTZsGETFPnDRx8+ZNlC5d2nABBvInWq5cudJie0xMjMVwFxN/+ctfrGQ3JyfHrgC76tkTPaEAE+JhTOWYqlatareslml8cME/TQ4dOhQhISEW4yn//PNPs9AWFODNmzdDpOiT4Ex1dk+fPm2xv6kHpKDY/N///Z9Ve3///XfExcWhfv365m2m2dVFLXcEqGczadIk8w+8W5UdM5UxKlwHeM2aNRAR7Nq1y+6xtxJgW788AEo8g4KCbP4yYgtbAvz+++9j8eLF5slwJgrLj2kSXJUqVfDvf//bvP3GjRvmhQBsTYKzhS0Brl+/vt37cJUA//TTT4iJiUH37t2RkJBgs9qAPdq2bYvw8HD89NNPNl83jQ8uPD78zz//RJUqVVCvXj3zL2IFn5Npn3r16iEqKsqmkP/5558Wn3VHAnzs2DGbn7dz584hJCTE6rimTZsWeRLcF198gdDQUKSmptqclPbLL79YVeSwhT0BBoDZs2dDRLB3717ztszMTJu/XD722GMQsS4VZoQA/+9//0OVKlVQunRpi6FOcXFxVsN9fvvtN7Rs2dJKdk3jkW39IuSqZ0/0hAJMiId56aWXbtnz9Ntvv6FUqVIWtTlNM/lr166NRx55BGvWrEHz5s3N5c4KCvDvv/9uXuls4MCB2Lhxo7kMWtOmTa1+sH3++ecIDQ1FxYoVsWLFCqxfvx5dunQxn7ug2KSlpaFNmzbmslHr1q0z77d69Wrzfm+++SZEBJ06dcLOnTtx4MABfPzxxw6fjekHcXJyMnbv3m21+tpLL71ksf+NGzfQunVriKgSadu2bcO0adMQFBSEdu3aWQ2d+PDDD/HAAw/ggQceMPfMDRgwwLytYJm2tWvXom7dupg5cybWr1+PDRs2YOzYsQgODkZMTAzOnDnj8F5M2BJgexSWHyC/DNptt92GZcuWYe3ateYJTfbKoNnClgCbJmgtXLgQ+/btw4EDByzKoLlCgAFg8uTJ5iELBSXLEaa/PvTt29fhfnXq1LE5pnjBggUQEcTGxqJmzZo2jz137hzi4+MRERGBKVOmYNOmTVi3bh1mzJiBxMREC1FyJMDff/89ypcvj7i4OPP3RWZmJqKionD77bdbHffWW28hLCzMXAZt48aNFmXQOnXqZHH+7du3IzAwEJUrV8aCBQuwdetWrFixAmPGjEFsbGyRPluOBPhf//oXIiMjUatWLfP3zOuvv47AwEDUrl0bq1evxsaNGzF48GCUKVMGNWrU0EKAAVWrWERw//33m7eZJs4OHDgQmzdvxvLly1GvXj3zv32Fe3urV6+OcuXK4dFHH8WBAwcsaje74tkTPaEAE+JhTJOzbjV+1FTFwFT7FAD27duHunXrIiQkBJUrV8b8+fPNpdMKLzLxww8/YPLkyShXrhzCwsLMC2FkZWVBRKyWFX7xxRdx++23IzQ0FGXLlkVGRgZ+/PFHK7HZunUrunTpgooVK5r3bdOmDQ4dOmR1DytXrkSNGjUQHBxss42FsbeAhim2/lz/008/Yc6cOahWrRpCQkJQrVo1zJ0712aPjanX11527txp3vfNN99E7969kZiYiMjISISGhqJGjRqYOHGiVQ1UR5RUgAFVB7lt27aIjo5GWFgYGjZsiMcee8zuQhi2sCXA//rXv9CvXz/Ex8db/WXAlQJsWsgkISGhyJPf5syZA5FbV4u47777ICLYv3+/xfYrV66Y31dHq3z94x//wJQpU1CjRg2EhoYiPj4eDRs2xMyZM3Hp0iXzfo4EGFDlwbp164b4+HhERUWhZcuWePbZZ+0e99Zbb6FNmzYIDw+3WAgjNjbWYly3ibfffhv9+/dH+fLlERISgvLly6NVq1ZYtmyZxV8H7OFIgAFg1qxZELGcVPjMM8/g9ttvR2RkJOLj49G7d29cunSpyLLrCQH+3//+h8qVK6NUqVLm5/DLL79gzpw5SExMNH/f3nvvvea/GBT+PLzzzjto2bIlIiMjbfZul/TZEz2hABPiZ9x1112IiopyOLaWEFdiWqCiqONt/RVTibSpU6ca3RRCfB4KMCE+SsEZ7ybee+89BAYGonfv3ga0iPgrkydPRkBAgEWPqj9z8+ZNq/rKQP4Y4KLUGiaElAwKMCE+yqhRo9CzZ0+sXLkSTzzxBKZOnYrw8HBERUXho48+Mrp5xMf5+eefceDAASxZsgRBQUEYMGCA0U3Shl9//RVlypTBtGnTsGnTJjz88MPo2LGjecz8rSZ/EkJKDgWYEB9l7969aNmyJRISEhAcHIxy5cphwIABt5yIRogrMC3QEhUVhV69elks5ezv3LhxA+PGjUPNmjURFRWFsLAwJCcnY9GiRTZ7hgkhrocCTAghhBBC/AoKMCGEEEII8SsowIQQQgghxK+gABNCCCGEEL+CAkwI0YKMjAykp6czDKNpMjIyjP5nghCXQQEmhGhBeno6JDQaUuV230+5epCKDa23x1RQq5fFVYOUqqL+OyzW9r6mxFVT+0XEQyoX2J6czDgTd7zfzrQjSfRKRATS09ON/meCEJdBASaEaEF6erqShXnX/DPZOZDIBCWyA7dDAoIgSe0h2VftH9N3EyQgEJLYCjL7ovXrh48wxY073ltn27JFjI+pLcnJFGDiU1CACSFa4PcCPO8apP9mJbQikNhKkBln7e877AAkKBRSPgUy87zr5csf48731tskuHA7KMDEx6AAE0K0gAKcl24rINHlISOP2t9n1FOQsBg1/GHaafeIlz/G3e+tN0iwvTZQgImPQQEmhGgBBbhAsnNsb894DZLSW/UQR5WBTPqre8XLn+Kp91ZXCb7V9SnAxMegABNCtIAC7CDT34M0GauGPASGqP+e/p5nxMtf4sn3UycJLuq1KcDEx6AAE0K0gAJsI1kfQ9pkqeoYEgBJ6QPJeNWz0uUPMeK9NVqCi3tdCjDxMSjAhBAtoAAXyNzLkC4PQKLKquEONVpDxp4wTrp8OUa+z0ZIsLPXpAATH4MCTAjRAgrwNTX2t+8mSEINJb4V6kOG7NZDunw1Rr/nnpLgkj4nCjDxMSjAhBAt8HsBHv88pFJq/kIYvdc7rgFMAfZ++S3Je+Ip8aUAEx+FAkwI0QK/FuCp76hV4MLjIJ2XQOZccrz/3MuQjFfU/1OCvV+A3SHBrn5WFGDiY1CACSFa4LcCPPui6vkNClX1fW0K7xXI6Gcg7bMhSe3yJsUJJCQSUq05pEWGWj3OXvk0CrDe8utKCXbX86IAEx+DAkwI0QK/FODsHFXZQQTSc62l8I45DumwAJLUARKWJ7wikFJVIA0GQDouhKQOgZStk796XPOJ7pUtX4rR7723vS8UYOJjUIAJIVrglwLcfp4S14gESJ27INXvgFRsCAmLzRfe2IqQ+n0hd61UC2HYOk/WR0qKRdQ5vV22/FV+dX5fKMDEx6AAE0K0wC8FOKmd6r0NLwUpVRVSPgVSrYXqFe72kBrnW9RhDXMvQ2p2UhLcZ4P3ihYFWM/3hgJMfAwKMCFEC/xSgLNzXFvpYdYnkNJJkDK1OB7Ym+VXx/eFAkx8DAowIUQL/FKA3ZE771e9wMMOeK9sUYD1e18owMTHoAATQrSAAuyizDwPCY2C1O3unaJFAdbzvaEAEx+DAkwI0QIKsAuTNhwSGAKZ+q73iRYFWM/3hgJMfAwKMCFECyjALsyYY2oYRLeHvE+0KL96vjcUYOJjUIAJIVpAAXZh5l5RtYMbDPAuyaIA6/v+UICJj0EBJoRoAQXYxanRGhJf3bskiwKs7/tDASY+BgWYEKIFFGAXp/VMNQxi2mnvkSwKsL7vDwWY+BgUYEKIFlCAXZyhe5UA993kHYJF+dX7PaIAEx+DAkwI0QIKsIsz7bQS4A4LvEOwKMB6v0cUYOJjUIAJIVpAAXZx5l6BSACk+UTvECwKsN7vEQWY+BgUYEKIFlCA3ZDIBEiD/t4hWBRgvd8jCjDxMSjAhBAtoAC7IWVrQ5LaeYdgUYD1fn+ShAJMfAoKMCFECyjAbkhSB0hsZe8QLIqwnu/NFlGhABMfgwJMCNECCrAb0n6+mgiX8arekkUJ1u89MYkvBZj4KBRgQogWUIDdkHHPKQFuNVVv2aII6/N+FBZfCjDxUSjAhBAtoAC7KUkdICGRkKnv6itdRsfo90iX98Ce/FKAiQ9CASaEaAEF2E0Z/zwkIBCSNlxv+TI6Rr9PRj5/R+JLASY+CgWYEKIFFGA3puFASEAQZOLLegqYTjH6vfLkcy+K+FKAiY9CASaEaAEF2I2Z8iYkOAyS0kdPEdMtRr9fnnjmxZFfCjDxQSjAhBAtoAC7OcndINHlINk5+smYrjHqvdJJfCnAxEehABNCtIAC7OaYSqJNeUNPMdM5viC/zoovBZj4KBRgQogWUIDdnD6PKQEeflA/OfOG+Kv4UoCJj0IBJoRoAQXYzbl9NCQwBJL1sX6S5k3xR/mlABMfhAJMCNECCrAbM/45SHgpSGJLPUXNG+Mv4ksBJj4KBZgQogUUYDdl1NOQyNKQyATI3af0FDZvjW7P0h3iSwEmPgoFmBCiBRRgN+TuU6r8WUwFtSxySc9ntHDqGh2eoTvllwJMfBAKMCFECyjALs7cy5Dkrmrcb8Zrrjuv0bKpa4x6du4WXwow8VEowIQQLaAAF0qXByDl6kKaT4SMPArJvlr0Y2d+CElqp6o+tJri2nYZLZq6x5PPzFPySwEmPggFmBCiBRTgAum1DiIBkOjy6v9F1H8nd4M0HgFJnw7pvATSez1kyG61f7u5kMYjITU7QWIrquM6LnR+4QsKsGtE2BfklwJMfBAKMCFECyjAeRn8pBq2UClVlSybdhrSbTkkqT2kVBVISIQSYlsJDoMk1IBUT4cM2Oae9hktlozn5ZcCTHwQCjAhRAv8XoCzcyADtkJCIiGlkyAzztrfd9YFyOTXIaOfUcI85jhk+nuu7+2lAOsXI+SXAkx8EAowIUQL/FaAs3NUb23FRqoXt1QVyOS85YrnXIJknoNMPwOZ+o5axjjjVciUN4s3JpgS7BsxSn4pwMQHoQATQrTArwQ4Owcy5i+QNrMg5erlj/e/m/wAACAASURBVPHtuBAybL/antgSEhRqf7hDSCSkQn1ISh+1f+/1arnjnmsh3VepYRODdrpHlI0WQX+MkfJLASY+CAWYEKIFPi/AmecgvR+F1O8HiSqbL7JlaqmJbUkdIGGx+dtLJ6lJbe3mQjosgHS6D3Ln/ZCuy5Qopw2DVG2mFriwJ8kikLhqkG4rKMDeGqPFlwJMfBQKMCFEC3xWgFtnWktprc5KZCf9VVV0CAyBhMWo3tzuq9QQh+JcY8ZZNR54zDHIuJOQCS+qc/dYDSmbrK456a8UYG+L0dJLASY+DAWYEKIFPivAAYGW8hsQBOn6oFqiuEwtta12F8jUd91z/RGH1TX6PEYB9qYYLbwUYOLjUIAJIVrgswI89zJk0t8gww+pKg9Vm+WJcCAkqgykz0b3Xn/mh65fEMNoOfT1GC27FGDiB1CACSFa4LMCXDizLkDqdoc0GgyZ8b77r9ftISXAnRa59rxGS6KvxmjRpQATP4ECTAjRAr8RYE/m7lNq4YzKjVVPNAVY/xgtuhRg4idQgAkhWkABdnH6b4GEx6nJdRmvuf78Rouir8Zo0aUAEz+BAkwI0QIKsIsy+yKkyZj8Emvjn3PftYyWRV+N0bJLASZ+AAWYEKIFFGAXZOLLkPIpSn4bDVbjjd19TaNl0RdjtOxSgIkfQAEmhGgBBbiE6bFarQ4XFq1WhfPktY0WRl+M0cJLASY+DgWYEKIFFGAnk/URpH5f1etbsREk41XPt8FoWfTVGC29FGDiw1CACSFaQAF2ImP+AomvruS3+UTInE+Na4vRsuiLMVp6KcDEh6EAE0K0gAJcjGSeh7TPhgSFQiJLQwbtNL5NlGDflmAKMPExKMCEEC2gAN8i2VchQ/dBUvpAgsNVr2/1dPctoUwJ1idGyy8FmPggFGBCiBZQgO2Jbw6k40JIXDUlvSERkAb9IcMPqteMbh8FmAJMiBdCASaEaAEF2E66P5w3wa2hWtZ45ofGt4kS7H8STAEmPgYFmBCiBRRgG8l4FRIarao7GDnBjRKsRyjAhLgMCjAhRAsowIUy94p6HiGRaoELo9tDATY+FGBCXAYFmBCiBRTgQmmTpYY+dFtufFsowfqEAkyIS6AAE0K0gAJcIKOfgQQGQ2p10nOiGyXY/ySYAkx8DAowIUQLKMB5yfoYklADElUWMv2M8e2hBOsXT4qv6ZrJyRRg4lNQgAkhWkABzkvqUDX0YdAO49tCAdY3npDegqEAEx+DAkwI0QIK8DVI/y1KfhuPNL4tlGC9427hpQATH4cCTAjRAr8X4GmnIZEJkNI1IbM+Mb49lGD9427ppQATH4YCTAjRAr8W4NkXIdVaQAJDIGNPGN8eSrD3xF3CSwEmPg4FmBCiBX4rwHMvQ2rf6f0lzyjA+gmwK69DASY+BgWYEKIFfinA2TmQhgOV/LadY3x7KMHeGXcILwWY+DgUYEKIFvidAGfnQJpNUPLbbIL31/ulBPt2KMDEx6AAE0K0wO8EuO0cJb8NBvif/FKAvS8UYOJjUIAJIVrgVwLcdZmS31qd1Rhgo9sz7xok+yolmKEAE7+BAkwI0QK/EeA+j0EkAJLYUlV/cPf1Zl9USysP2Abp9hCkzSzI7aMhde6CVG0OSbgNEhar2pTUHjLmOCWYoQATn4cCTAjRAq8W4JkfQmp2gpRPgdTrBWmdqUR33HOWkjt4lyp1VqGBOsbd7cp4VS2rLGKZoFBIbGVIxUaQmh0hjQZB0oZDQqPV67W7QMY/RwkuSTwxMY0CTIjTUIAJIVrgtQI8+yIksZXqQa3SFBJdrpBwBkDiqkGS2kFCIlSP6/Qz7m/XmOOQqDKQsGhVXm3YAcjElyGZ5+2POZ5xFtJikmqnBEDq9VTHUIIpwBRg4mNQgAkhWuC1Atx+vhLdUlUhPVZDZrwPyfwAMvIIpMsDqmc1PjFfiMvWUT2tNTu6bwjEoJ2Q0ChIdHnIuJPFP37aaUiTsaqnOCAQ0qC/6k2mABdPgI1uAwWYELtQgAkhWuC1Ajz5dVXLNyIhv8c3MMR62IEppapCanVS/53UHjLnkmvb030VJDBYLak8+Y2Sneuet5TAB4aoc6YOgdzzNgXYH0MBJj4GBZgQogVeK8CmzL0CGX4I0nIypOk4SIsMSPp0NensrpWQUU9Dsj7K37/jQiXByV1dU4EhO0ddS0QNxZjxvuvuLeM1SMNBkIAgNXZ4+nsUYH8LBZj4GBRgQogWeL0AO5PqdyhhnVLCntq5VyBpw/KEupv7hlYMP6h6g6u1gMz5lALsT6EAEx+DAkwI0QK/E+ARh9RwiUaDS3aeWRfyh1TcPlrJsDvbbaphfPsoCrA/hQJMfAwKMCFEC/xKgIfshsRUUJPUMj9w/jyZH0AqpykhbT/PcyvKmXqb71pJAfaXUICJj0EBJoRogV8IcNbHkMYj8yfDjXra+XPN+VSVXwsIgvRc69n7mHMJUqWJqhIx8igF2B9CASY+BgWYEKIFPi/AIw7nl0NLHVqyhTAmv64muomoUmtG3M+003m92OVcUxnCaMFjKMDEr6AAE0K0wGcFePZFSPOJqp5uTAVVo7ck55vwglq6OCQC0vVBY+9tzDFIcBikUmrJJ94ZLXgMBZj4FRRgQogW+KQATzutFr4QgdTvW7LxvvOuqTG+5epBwktBJrxo/P3Nu6aGX4hAGgwo2RhkowWPoQATv4ICTAjRAp8T4MzzSlaDQiF9NrrmnNNOK9lsk2X8/RVMswmqXZ0WUYB9NRRg4mNQgAkhWuBTAjzrE0jVZmrYQ78nXHfeoXuVaA7Yavw9FszcK5AardWEvFFPUYB9MRRg4mNQgAkhWuAzAjznU0jNjq4vEzbvGqTzEnXeSX81/j4LZ8b7kLAYSK3OFGBfDAWY+BgUYEKIFviEAGdfhaT0UZLaYYHrz189XZ2740Lj79VWmo5Xvd4Zr1KAfS0UYOJjUIAJIVrg9QKcnQNpMlYJasvJrj//lDfUuUUgk0u4dLK7kvGKWt2u2QQKsK+FAkx8DAowIUQLvF6A22Tl1/h19YpsmechZWur0mdjjhl/r45Ss5Mq05b1MeXXl0IBJj4GBZgQogVeLcB3LlXyW+cuNSHMleeedhpSrbkaWqDb5DdbGbK7+At0GC13DAWY+B0UYEKIFnitAPd+VP3Zv/odJV8MomBmfgjpvgoSHgcJDDZ+0YuiJjsHUqYWpEIDCrAvhQJMfAwKMCFEC7xSgAfthASGqJXQsj4q+fkmvABpNEgJpASontTyKZCxzxp/r8VJs/GqJNqsCxRgX4mPCPCuXbuQkJCAb775BgBw4sQJpKWlYcGCBQa3jHgaCjAhRAu8ToBHHlFjcsvUgsw4W7JzZbymVooLCIQEh6tqDy0nqxrCcz41/l6Lmz6PKXkfcYgC7CsxQIB/+OEH5Obm3jJffPGF1bbr16/bPW/btm3NAtyrVy/k5OQgJSXFU7dFNIECTAjRAq8R4FkXIN2Wq+WIS1WB3PNWyc7X7SHVixwYAmk8EjL1XePvsaSZ/HpeKbh7KcC+Eg8L8A8//IBSpUrlVz5xkIiICKttixcvtntuCjABKMCEEE3QXoAnvqzKnIXFqh+ypWuqbc6eLzsHcscMda6qzZ2rnatrsnMgkaUhdXtQgH0lHhbg3NxciAie3LABJw8csJsnN2yAiODMmTNF6gHes2cPEhISUK5cOezbtw/Hjx9Hamoq5s2b57F7I3pAASaEaIEhAtx/CyQ0GhJdTg1lqNJUrWTWcCCk+d2QtnPU6ms1WitRDQhUrw/ZXbJSZ3Mvq7G+psoRrpw8p0uSOkDiqlGAfSUGCfDJzZtx9uhRuzm5eTNEBLm5uR5rG/ENKMCEEC0wRIAn/U31VIpAEmpAKqVB4qtDIuKV7Jr+pBqZoMbkumIBiqyPIUnt1Xmbjlerxxktq+5I4xHqlwsKsG/EKAFetQpnt22zm5OrVlGAiVNQgAkhWmDYEIjxzysJji6vSo+ZtmdfhWSeU6ubuaqHdvoZSMWG7lsqWac0Ha/GNVOAfSNGCfD06Ti7cKHdnJw+nQJMnIICTAjRApcJ8KwLaohBcY4Ztl9JaYtJ7hPCSX+DxCdCgkIhvdYZL6juTsvJ6pkWpYfbaLlj9BXgMWNwdupUuzk5ZgwFmDgFBZgQogUlEuDsq5BBOyA1O+bXzw2LVlUaKtSHJLVTFQkyXrF/jlp5S/i6eiW3edcgo59RwyjCYiBD9xkvp56IaYLfrE8owL4QowS4b1+cHTHCbk727UsBJk5BASaEaIFTApx5Tg0liE9UshUeB7l9tOp9TBumJpgltoKUqpo/nrdsbUirKUpKC/ZO3rVSvT7mmGtFcOA2VS84pgJk3HPGi6mn0m6uep6ZH1B+fSFGCXDHjjjbo4fdnOzYkQJMnIICTAjRgmIL8PCDapKViOrlvWul/d7G7BzIhBdVVYdKafm9xNHlIalDIQO3q5JmIpD22a6TwG4r1IpoZWpBprhgAp03peNC9TxvVdfYaLFj9Bbg5GScrV/fbk4mJ1OAiVNQgAkhWlAsAR55BBIapcpsjTxa9JJkcy5BRj2teic73adKdQWHKVELjVL/f1ubkstfdg6kdWZejd9mqqfaaCH1dLo8oO5/8uuUX1+IUQJcoQLOVqliNycrVKAAE6egABNCtKDIAjz6GTW+N7byrcuSTX0H0ncTpNkEdW6T7IpA2s9X+2R9rPZp0B8SkQCp1rxk4jf3MqTRYN+u8VuUmIaU3H2KAuwLMUqAIyNxNjrabk5GRlKAiVNQgAkhWlAkAR57Qk1Ui6lgPaFtzqdKjjstgtTrqSbAmWQ3IAhSPkXVpu2xRvUcV2thQ16vWPYmZ56D9NmoFsWo2kwtf9xzrf32ZedAkrupazYZ67s1fouSXmvVcxh3kvLrCzFKgEVw1kFO5n2PU4BJcaEAE0K04JYC3H+zWqAiulz+EsRzL6tJZnW7q4lmJuGNiFcVIdrOVlUXsj62PFeTMZDAYMjM8/avN+opSFTZ/BXgytWFxFZU8m2vV7fHarV/q6nGC6jR6btJPYsBWynAvhCDBPgFEXzgIC9QgImTUIAJIVqQnp4OqdjIWpSmnVZDCUQgCbepyWzjTkKajc8X1LBoSIMBkO4PKzm+1ZjgwU+q4/pstCOya1S93tiKkEE78wV64DZ1XMeF1sdMf08NoSifUvw6xL6Ye95Spd9Co6x7gY2WOcZrBPhFEZx3kBcpwMRJKMCEEC1IT09XclkpDXJHppqsdtdKNewgMFiNq203F1KuXn6v7G1t1KISRak1WzCzL0JCIpU0F9yefRXSIiO/HYUrGGTnQCo3VmJXWHIb9FdtcnUZNW9Oxmtqlb3YipbP0miZY7xGgF8SwUcO8hIFmDgJBZgQogVmAbaV2EpqHK+pjm/7eZB73i6ZnNXqpHqQC47TbTVVXaN+X/vDHJqOV0I+51L+tqH78sb9jjFeOnXLyKNq8mHFRmqVPqNFjvEqAT4lgo8d5BQFmDgJBZgQogXp6emqskPBSg3mMb0JaoGLMceLXvLsVun6oOXCF9NOq17hmp0cX6NGa0jpmvlfz7kESaihxgbP/NB44dQxvderZ53cDXLwkPEyx3iNAP9NBBcd5G8UYOIkFGBCiBaYJ8FlvAK5ra0ag1u7i5r8NudT10vZlDeVlLXOVF83m+C4aoEpMRWUyJm+7r9ZHdfLQXUIBtImSz2nkaOMlznGawT4FRFccpBXKMDESSjAhBAtsKoC4aqeXkcpV1dNWhuyBxIcribbOdrftFpc+vT8bfV6qkl4/lrvt6jJzoE0bAgJC4Ns2mS80DFeIcCviuBTB3mVAkychAJMCNGCYi+F7IqYxvyaJtWNf96xwFVroYZJmFY3y/pYlV9r0N94wdQ9h49AHl0PCQqCdO1mvNAxXiHAr4vgioO8TgEmTkIBJoRogSECnPWxqlPb7wm1iIajfe+8X4lyp/vyt/Vap7YN2mm8YOqcQiIlSUnGCx3jFQL8hghyHOQNCjBxEgowIUQLDBHgoqbXWtVDXK25Wi3OtL1WZ9sl0Rj7AnzXXaoXeN9+46WO0V6A3xLB3x3kLQowcRIKMCFEC7QV4MFPqhJsldKsqzzEVLj1uGF/T2GRmpRXZ3ndOuOljtFegN8VwRcO8i4FmDgJBZgQogVaCnDmB0py4xPVfxd8bfZFiASohTOMbqfOKSxS4/OqbXAinHfFIAE+I4IvHeQMBZg4CQWYEKIFWgpww4FKcocfsn7NVBGi6zLj26lrbInU8BHque3YYbzUMdoL8Aci+JeDfEABJk5CASaEaIF2AjzlTSW/jUfYfn3QTiVyg580vq26xpZI9euvntt+jgH2qhgkwB+J4DsH+YgCTJyEAkwI0QLtBLh9thK1CS/Yfr3LA+r1SX81vq06xp5I3dUdEhxsvNAxXiHAH4vg3w7yMQWYOAkFmBCiBdoJcNk6apEMe6+3zlQCnPWR8W3VMfZEqkNHSHS08ULHeIUAXxbBzw5ymQJMnIQCTAjRAq0EeNxJJbft59vfx7SIBleAK7r8Hj4CadECUras8ULHeIUAXxHBfx3kCgWYOAkFmBCiBVoJcPOJavzvPW/b36dFXjmv7KvGt1en3EqkKlSApKYaL3RM0bNFIEliiABfE8FvDnKNAkychAJMCNECbQR47hVV+qx6uuP9mo1Xi2MY3V7d4kiktm3LWzlvkPFSxxRdfg0U4M9FcMNBPqcAEyehABNCtEAbAW6WV6e211rH+90+GhIUanx7dcqtZGruXPVsF95nvNgxRRNfgwU4N1yACPvJDacAE+egABNCtMBwAZ57GdJkjBK0hoMg2TmO9288AhIaZbx06pRbSVXv3pCAAMiuJ40XPKbo8mukACcIUNZ+chMowMQ5KMCEEC0wVIAzP4DUaK3kN3UIZM6ntz6myRhIYAhk1gXjxVOHFEWs6taFJCYaL3iM9whwVQFq2E9uVQowcQ4KMCFECwwT4IxXIQm3QQKCIJ0X2+75zfwA0v1hSM2OkHq91D4Dtiph7ve48fJpdIoiVfsPQEJCIHfeabzgMcWXYKMEuI4ADewntw4FmDgHBZgQogWGCPDcK5DKaZDQaNsrumVfhbSeqXp6RdR+IpAea1T5s7AY1XNstIDqLr+Hj0CWP6Se3dSpxssdU3wJNkqAWwvQ2X5yW1OAiXNQgAkhWmCIAHdapKSs64PWr808D6nVWb1esxNk2AHInEuQssmQ6PJKnttk5VU12Gm8iBbMrcYve1p+Dx+BjMkbX73+MePFjim+BBslwF0F6Gs/uV0pwMQ5KMCEEC3wuADf8xYkJBJSrYW1MN59ClI6SdUCbjvH8nVT/d/ZFyGzPlEl06q1MF56511TwzKq3K6qU4w5po/8Hj4CadUKUqoU5NBh46WOKb4EGyXA/QQYaT+5/SjAxDkowIQQLfC4AHdfpUR21NOW2/tvgYRFQ8JiIYN2WB9Xt4fqATZ93XgEJDjM2BXhJv1NVa4QgcRWVtUpElupXmod5PfwEUjp0pCmTY2XOca5GCXAIwWYbD+5IynAxDkowIQQLfC4ADcbDwkMzhfX7KuQO2YoiSxbW0mlreMqpUKqNMn/ulve2NYxxz0rvXM+hfTdBKl+h7q+BEAaj1S90h0Xqm11e6ivjZbfx59Q7Rk+wniRY5yLQUsh52YJcL/95GYVT4BPnDiBtLQ0LFiwAACwd+9eNGzYEF27dnXn7RANoQATQrTA4wJc/Q5ImVrqvzPPq3G+IpA6d0GyPrJ/XGQCJKVP/teJrSDhpdQ5PNHu7BzInUshUWVVe6PKQFpOhmS8ZrlP+rR8me+/uWil3dwhv4ePQMaNU215YJnxIsd4lwDfJ8Aa+8m9TwnwmTNnkJuba87169dtnrdXr17IyclBSkoKAODo0aOoUKEChg0b5rF7I3pAASaEaIHHBTiqrOohzfoIUqG+Wta43VzHE8iyPlIilz5NfT10n/q67WzPtHnuZUjacHXNymmQPhvUxDx7+/d7HBJdTu0fmQDpeYvV7dwhv3v3QuLjITVrcvyvN8coAV4hwGb7yV0heX8BsczixYttnrewAC9duhQnTpxAy5YtPXZvRA8owIQQLfCoAE8/o35Qtp6pavtKAKTPY7c+bvxz6rjuq5QoV2mixNJRj7GrMvN8/mIdjUcqGZ53TfXsdlwISRumqloM2QOZdjpf5GdfVKJcPkVNjis85tndAjxqtGrzgnuNlzjG+wT4YQG220/uw8XrAT5+/DhSU1PRtWtXrFmzBjt37kTt2rUxcOBAj90b0QMKMCFECzwqwEP2KCmrlTfsof28oh3Xf7Paf9gBVfpMBNLhXve3d+o7qvxaQKCSXNP2kUfVdhEltwV7weITIVkf5+877bSqWBFbETL9Pc/I7+49qvJDcjJ7f709RgnwegH22U/uek6CI85BASaEaIFHBdhUyiwwGFKubtHr5poml015A1KxkaoG4epJZoUz6wKkYkNVaWLAVrUt83zeUIgANQa496NqEl/Ga2qftGF5or7f8lwjj6hFPaqnF71ChLPCdOAgpEdP1Y5Fi40XOMY7BXiTAIfsJ3cTBZg4BwWYEKIFHhPgiS9b9pb2Xl/0Y5uMUceahlCkT3dvW7OvQpK75bczO0cN1TBNgEsbppZpLnzclDfzerazrV/rvFi9ltLH8fjhksjvggWQqlXVdZo1M17efCEHD0EW3geZm62GkyxeoiYVrlgB2b/fdwV4iwBP2U/uFgowcQ4KMCFECzwmwDVaqwUwktpBQiKKVx2hZkdIfHXI8ENK7vpucm9bW03JG6ucqXp3k9rlV3YYcdiBOOeoyW917rL9WsvJ6jxVm6mJcdNOOye/hw5Dtm6DLFsGmToNMmgQpH59de7SpSHTpytxM1oefSFDhtic7CUikMREyIaNvinA2wU4bj+52ynAxDkowIQQLfCYAJetAwkOV0MHiruCW7l6quxZt+VKPCa86L529t2UX8u3fbaS9eAwtTJdUaS9Vie1KIa917s8oBbMMElU2dqqh7v/FsjKVZBlD0KW3A9ZuBAybx5k1mzIhLshPXuqXt3EREh4uLWMlSoFGTpMVX8wWhp9JY8/AQkLgzRqBFn6gBpSsuBe1Rs8foJ6H2JiIEuW+J4A7xXgRfvJ3UsBJs5BASaEaIHHBPiet1Qvrgik1T3FO7ZSGqRK0/wxxK6orWsrM8+rHtyg0LwlmUX1XGe8UvRztJmljrPVu2vKnE8hIw5B7shUvcGBIfZ7GU0JDISUKwdp0ADSqTNkxAhI1izIqlWQXU8aL4u+mPR0SFAQZN2jtl9fvQZSvrzaZ8IE3xLggwL81X5yD1KAiXNQgAkhWuDRSXD3vAVpOBCS8WrxjktqrxbPaDU1T4BvMYbW2TQZmy+ckaUhvdYWfaKeKYOfVMcP2Fb0Y7I+hty7EJI5EzJ7DmT+Ash9iyBLl0KWL4esfwyy/4DxQuhPuX+peh979XK83/Yd6pcSEfWLiavHBRslwEcEeM1+co9QgIlzUIAJIVrg8YUwnEn9vmroRPtsJRozzrr+GhNfVuXORCCNBkMyzzl3nsxzlot2FCVGy56/ZckSNWY6KkoNHSldWvXkVq6shpgkJantcXFF610/cBDSLW/SZJ8+viHAzwjwlv3kPkMBJs5BASaEaIFXCHCTsap0WocFSjKK24NclEx+XU1eG36o5OeKT1S91pRfvXL/UkhKivoMxcRA2rWHtGsHueMOSIsWkCZNIGlpqkc3JUVVfyjO+WvVUvEFAX5OgPftJ/c5CjBxDgowIUQLvEKA+z1hOR62OCXUjEhUWUjd7pRfXbJ0af4whZgYyLBhkN27XX+dLl0gISGqR9jLBfiLFwR/fmA/X7xAASbOQQEmhGiBVwjwvGuqOoOpjnCpKsa3x16mvqva2G4uBdjoPLAsX3yjo1WVjCfdIL6mZOSVuVu92usF+POXBDc+sp/PX6IAE+egABNCtMBrBHjeNci4k0owwqKNb4u9DNyu2jh4F+XXqCxbpkqXiahxvkOGeKZSxqqH81YsnOK6cxokwNdeEfx2yX6uvUIBJs5BASaEaIFXCfC8a6pU2eTXjW+HvZjKoE0/Q/n1dB5cbim+gz0kvqbsP6CGQHTt5rpzGiTAOa8L/nfFfnJepwAT56AAE0K0wOsEWPckd4PEVKD8ejLLl6vJaybxHTQYsmtXyc65dRskMxPSqROkYkVIbCwkIQFStqz6umpVSI0akORkNfY3axZk23ZVQSI52esF+Oqbgl+v2c/VNynAxDkowIQQLaAAuzhx1SBJHSjAHhHfh/LFNzISMnAQZGcJxHfbNshddym5NU24DA2FNGyoKkbc0RrSsiWkadP8ahG1akGCg/P3Dw5Wq8cddNFEOIME+Mrbgl8+s58rb1OAiXNQgAkhWkABdmEyz+etdDeV8uvOPLQC0vh29awjIiADBpZMfE1p2xYSEACpW1fJ9P1LIfuKsLDF3r1qmeQBA9SxNWt6vQB/+p7gp6/s59P3KMDEOSjAhBAtoAC7MMMOKCnru4ny646sWAG5vYD49u8P2bHTNefevVv13LZpY/x9FoxBAnzxfcH1b+zn4vsUYOIcFGBCiBZQgF2YjgvzFup4jQLsyqxcpRapMIlvv/6QHTtce43JU9T5Fy0y/n4LxiAB/uS84Mf/s59PzlOAiXNQgAkhWkABdmHq94OExUKycyjArsiqVWq8rQgkPBzSty9ku4vF1xRT9YhmzSB9+kKm3ANZ9qDrRbu4MUiAL3wk+OF7+7nwEQWYOAcFmBCiBRRgF6ZsHUi15pTfkubh1UpERdSwhD5uFF9Tpk5TEly2rBoHXHDlwZgYtTTyuHGuGWvsBQJ87hPBP3+0n3OfUICJc1CACSFaQAF2UWZfhAQGQ5qOowA7m9WrIc2b54tv796qtJin27F3r2pLVhZk6s9KuAAAIABJREFUyFBIm7aQChVUuxo08GxbDBLgMxcFX163nzMXKcDEOSjAhBAtoAC7KGOOKUHqsZryW9Ts3w95/AnI0qWQFi3yxbdXb1WSzOj2Fcyhw5CePVUbNz2utj3+hFp8Y/lyJc0+JMDvfCr4/Cf7eedTCjBxDgowIUQLKMAuimkC3IQX/VeADx1WVRnWrVMlxLJmQcZPUGXK7rxT9e7WqaMWkoiKshxmEBqqBHOrZuJbMGseUW0dNRqyd5/lPXTq7FMC/MZlQc7P9vPGZQowcQ4KMCFECyjALkrFhpDSNa0nwBktbe7M/gNKclNT1SppQUGWUlswERGQ8uUhtWtDmjRVK6z16w8ZO06tuKaz+BZMUBCkRw/IvPnqvgYOgtSvD4mOVs/DRwT45auCC7/az8tXKcDEOSjAhBAtoAC7IBNfVjLUJss/5HfHTiWvcXHqvuPiIOnpkO7dIcOGQTImQ7LnqZXaNm6C7HHT8AAjEhYG6dpVCXxICGT3HiXwIpCFC31GgF/MEZz/n/28mEMBJs5BASaEaAEF2AVJn5ZX//dV/xDgxo3zJ4RlzXJPz6euiYpS8hsfrxblOHxELaIREgLp2NH11zNIgE9eE5z9zX5OXqMAE+egABNCtIACXMJk50Diqtl+hkbLmjsyf4GS30GDjW+LEYmNhVSrpp7BpIz87c2aqXJpB1y0BLIpBgnwXz4TvPuH/fzlMwowcQ4KMCFECyjAJcyop5QM3bnU9+V3/341ga1sWfdVPdA98fH545ofXZ+/ffp0te0+F68kZ5AAH/5C8Oqf9nP4CwowcQ4KMCFECyjAJUzjkar+74yzvi/Ao0YryZs12/i2GJWyZdUzCAmBHCzQ27vrSUhwMKRrN9dezyABPpAreBn2cyCXAkycgwJMCNECCnAJMudTSGQCpGZH69eMFjV3JC1NLQhx6LDxbTEqdesqAa5Qwfq1SpUgTZq49noGCfC2XMEx2M82CjBxEgowIUQLKMAlSOclSoZ6r/d9+T18RJX7Skoyvh1GZuLE/CEQhV+rU0eVeXPl9QwS4LW5gidhP2spwMRJKMCEEC2gADuZ0c9AgkIhiS0hc6/4hwDXrq16QI1uh5HZtcu+ADdrZrtnuCQxSIDn5AqWwX7mUICJk1CACSFaQAF2IpnnIKWqQKLKQqadtn7daElzV2rUgDRsaHw7jM6UKZDZc6y3d+oEiYx07bUMEuCMXMEc2E8GBZg4CQWYEKIFFOBiJjsHUrMTJCAQMmy//8jv4SOQevUgNWsa3w5d06+f6hnev9915zRIgIfnCibBfoZTgImTUIAJIVpAAS5GZn0CuSNv1a+2c2zvY7SEuTPp6ZDSpY1vh665805VHcKVC4MYJMC9cgVDYD+9KMDESSjAhBAtoAAXSHaOqueb0gdSOQ1Srh6kbndIi0mQ6ndAgsOU/Ca1h2Rf9T8B7tETEhgIOXjI+LbomCpVICkprj2nQQLcJFeQDvtpQgEmTkIBJoRoAQW4gPw2HqkEN7I0pHJjNcEturzaFp8ISRsO6bsJMueSb8jvpsch2fMgmTPVuNbxEyAjRkJmZNruxbyruxLgfS78E7+vZOu2vBXyBrn2vAYJcHKuoD7sJ7mYAnzixAmkpaVhwYIFAIBLly6hefPmGDlypDtvh2gIBZgQogUU4Dz5bTJGCUzacPV1wddnXyzaeYyWsKJmzSOQFi2UzJoqGhRO2bKQCRMge/flH1ejBqRWLePbr2NmZqnntuR+157XIAGumCuoCvupmCfAZ86cQW5urjnXr1+3ed5evXohJycHKSkpAICsrCykpKRg7NixHrs3ogcUYEKIFlCAr0Ga59V2TR1iObQh85ya6HbnUsiEF3xDgHftUsv5hodDunWDLFkCWbESsnYdZNMmyLZtkKwsSPXqeT3f8errnbsgAQGQ3r2Nvwcd06WLGv9b8BcGV8QgAZZcgcP/5dr+xWnx4sU2z1tYgKdNm4ZnnnkGjRo1sivNxDehABNCtMDvBfjul9QP75Q+Sn5nX4Q0HASJrWT5wz00GjLisHfL7+EjkE6d1f0sXep4v0OHIfMXQKpVg4SGQhYthgQFQUqVUsMmjL4PnbJtOyQqSq2U5+pzGyXAnwvkhoN8Xrwe4OPHjyM1NRVdu3bFmjVr8O677yI1NRV9+vTx2L0RPaAAE0K0wO8FuOl4VdJsyptq6ENKbyUANTupig/9noCMPAqJrQwJjbJd99dbBDgzr4JFly5FP2bDBkhYGKRBA8jyhyCVK6tzdOoEOXjQ+HvSIXfeqXrHV65y/bmNEuC/C+R3B/k7J8ER56AAE0K0wK8FePZFSES8quow7xqkwwL1w7/VPdb71u8HCQ6HzPzQOwV45SrVk5uUBNm7t3jHjhqlnsuUKerYTp3U1/MXGH9fRmfVw0p+O3Z0z/mNEuCrAvnVQa5SgIlzUIAJIVrg1wLc+1H1w77fE2o545gKkCpNrCfBzfwQEhKhhkl4o/xu3QYpUwYSFwd54oniH3/woBLnqCjIlq2Q3XuUTHdwk/R5Sw4dVouDREaqsdPuuIZRAnxJIP9xkEsUYOIcFGBCiBb4tQAntoJEl4PMvQwZvEv94O+x2nq/bg+p14bu9U4BbtYMEhwMWbbM+XOsXq2qRnTtmn/OmBjIAT8ZBrFzF2T6DMi8eZAVKyBPbFbl4kQgo8e477pGCfAFgfzgIBcowMQ5KMCEEC3wWwGe9Df1g77lZCXAVZuriW6zLljul/mBqgVcOsn24hdGi1lRkpQESU4u+XmaNVe9nXv2QibmVc545BHj78+deXI3ZMgQ1fttq1xc5cquXfmtcIwS4I8E8p2DfEQBJs5BASaEaIHfCnDLyeoHfcYraqU3EVXurPB+DQdBJAAy4pB3yu/hI5DWrVX1hpKe596F+WOBJ09R/71unfH3547s3QsZOUr1cotAGjWCLFqk6vxmZkLGjIH06QtZ5YaJbwVjlACfF8j/Och5CjBxDgowIUQL/FKAZ12ARJWFVE9XK7uJqEluhcf+moZFNBnjvfJ7+Ahk0GB1H7t2lew8Bw9BypVTi2HcndcDvGGD8ffn6uzYASmftwJg3bquX9yiODFKgM8I5EsHOUMBJs5BASaEaIFfCfCsC5Ahu9VwBhFImVqQoFBIuXqQWZ9Y7jvxZUhEAiSuGiTrY++V38NH1FLHIpDly0t+rqHD1Lk6dFT/78ykOp1z6LAa6hEYCJkzV31tZHuMEuDTAvmHg5ymABPnoAATQrTAZwU4Owcy5jik40JVvaFMLVXvt/AYzuRukHvesj62yu2QsBjLFeCMljNns+phda9Tp5X8XFu2qAUxQkPVObdtN/7+XJlJGeq+Bg02vi2HjxgnwG8L5DMHeZsCTJyDAkwI0YL09HTrCVJGy2tJknlejeUtVy9fcsPjINVaQGIr5m+r0kQtcGHrHEN25/VyLvB++T18RJUtE4H06++a87Vokf8cdz1p/P25KuvWqUU/6tTRZ5EPowT4DYHkOMgbFGDiHBRgQogW2BTgwjFaaovS2zvqKUjDgaper4ga5tDhXiW5rTNVjV/T9v6brcf7WvT+NoVEls6vCGG0BLkipUtDWrR0zbkW3pcvwHv3GX9vrsj+/ZAaNVSVi42bjG+PKUYJ8Ct5tX7t5RUKMHEOCjAhRAuKJMCFY7TwFszgJyFl66gf2kGharjD8IOQ4YcgdXtAAkPUa1WbQXqvVyXPHJ1v6D61f/t5viO/h4+opYwTE11zroOH8ieJ6dJTWpI8uTt/THNmpvHtKRijBPjlvFq/9vIyBZg4BwWYEKIFTglw4RghvrMvquoMIpBSVSGd7oNMeRPSdVm+EIdEQtKGQcY9V/TzVmuuSl/t3mO8/Lgyd3ZR43YPHnLN+aZOVaXBjL4vZ7NpE2TsOEi79vmlzu7sYny7CscoAX4pr9avvbxEASbOQQEmhGiBSwS4YDwhv+NOqkltIpBGg9RktyZj1KQ1EUjCbZBOi9R44KKe8/ARVe5KBDJsuPHi4+qMGavubZNGf943Io+uV73hAQHqeURGQtLSjC115ihGCfALAvnAQV6gABPnoAATQrTA5QJcOK4U3+yramJaUKia2NZwIKRGa/UDOyAQUvtONYHN3vhee+JrSv36eb2/u40XH1dnwb3qOS28z/i2GJX1j0ESEpT09umrVrEzuszZrZKUZIwAn8ir9WsvJzwnwNOnT8e6devw6KOPuv1axP1QgAkhWuB2AS6Ykgpw58Xqh3P1dDVUQQQSmaBWdZv8hnPSa8rSpep8Q4YaLz3uyIYN6v7GjTe+LUZk7z5ImTKq53fxEuPbU9QkJBgjwMcF8o6DHPeMAB87dgyTJ0/G0aNHcezYMbdei3gGCjAhRAs8KsAF44wA39YWEltZTXQTUeI7+6Lz0lswDRtCoqJ8q6xXwRw8CAkJgXTtZnxbjMjuPWoFOxFIRASkRw/9V7HbvRsSGGiMAD8tkDcd5GnPCPD999+Pixcv4osvvsAXX3zh1msRz0ABJoRogWECXDi3Eti5VyBh0fmLWbScXLShDkW59rJl6pyDhxj/HNyZqlW9e+JaSXPosBrr26y56gkOCIC0aqVKoBndNluZOg0iYowAHxXI6w5y1DMC/Oeff+Ldd9/Fjh07sH37dnzwwQduvR5xPxRgQogWaCPABWNLZMc+m197tul4x/Jb3Oulpub1/u4y/t7dmWbNIWXLGt8OHbJhAyQlRX2etu8wvj22kjHZOAE+kFfqzF4OeG4M8P79+7Fu3TqsW7fO7dci7ocCTAjRAi0FuGBMUtv9YfWDufFI2/Lr7PmXL1fnHTjI+Ht1d/r0Vb2ee/ca3xYdkpoKqVDB+HYcOgx5cLmq1PFYgWEZM7OME+B9eaXO7GWf5wT4sccec/s1iOegABNCtEB7ATZlxw5I1ixL+XXFedPSVFWAnT7e+3v4CGTKFCU3q9cY3xajc/CQet/btjW+LT175v91IyQEMmwYZP8Bc+UOQwR4t0Ced5DdnhPge+65B6tXr2YVCB+BAkwI0QKvEWB35KEV6of9gAHGt8UTMY11zpplfFuMzuo16llMnGhcG7ZsVWOQRZSIr1ihfiETUeO1F94HCQ83RoB3CeRZB9nlOQGeNGkSdu/ejePHj7v9WsT9UIAJIVrg1wJ8++2qIsAOTceAujo7dvh2qbfi5O6J6lmsecTz1z50GDJ5ihp3HhSkhqYcOJj/2swsSFycal9srDECvFUgzzjIVs8JcI8ePbBr1y48+eSTbr8WcT8UYEKIFvitAK9YqX7Q9+tnfFs8mZgYPf7sb2QOHVYT4GJiXLc0dFGzfr1acEUEkpQEeXi17f127YJ06WLcEIjNeZUe7GWz5wR4yZIlWLNmDSfB+QgUYEKIFvitADdpCgkP17cCgKuTmal6O5OTVT1co9tjZOYvUJI3YoTnrrn/gBrbGxICCQuDjBmjajPf6rjERGME+HGBHHaQxz0nwCtXrnT7NYjnoAATQrTALwV41Sr1Q75PH+Pb4hH52p8/yapde/Wnd92XAHZXDh6EVKsGKV1arQ7niWsufwiSmKief1oaZOOmoh+bnGyMAD8qkL0O8qjnBHj+/Pl45JFHOAnOR6AAE0K0wC8FuFlz1Qu3bbvxbfFE1jxSoIZyU/X//nLvhXPPVHX/U+7xzPWmTVel52JjIdNnFP8XD6MEeN3/t3dmsVVda57/wIwhhDmEKU7iQCAOlzGEeZ6nECCEC4QQIIQQQggQAoaAmY0xjjHENsYYY4yxD7oqpaKWalSp6tJqdeqh1Wq1Wl0dVCrlvUqpl3qoh68fPp9rCD4e9tnnrOV9fj/prxvOsPbaZ1v3/Lz87W81dXpIlJL0CTBECwQYALwg4wT4SpF9wa991/1c0pWmfrIiYqu/Iipnz7mfV7pTd19l8GBbAW5P+UGyuVVln3dOTvBSG1cCfFVU7rSSqwgwBAMBBgAvyDgBnj7DVn9vVbmfS7qyaZNJzfjxzSK89zP380p3tn1o537seHqON3eeSteuVnITdAxXAlwoKlWtpBABhmAgwADgBRklwFeL7c/Rq9e4n0s6M3OmyoABKvu/aBbgdzNoBTz2UKX6jq3G5uamp/751Gn7nFevTm4cVwJ8uadKZa/EudwTAYZAIMAA4AUZJcAzZ9pd+JW33M8lncnOttXf39YCu55XOrP2XTvvi5dSf6yGRtvIYtAgldra5MZyJsD9VW4NSpzL/RFgCAQCDABekDECXPydrf6uXOV+LulMQ4NJ//IVKvef6AYxYoT7uaUrZeX2GcyYkZ7jHf2mqcxkb/JjuRLgK8NUbo9KnCvDEGAIBAIMAF6QMQI8e7ZJ0M1K93NJZ0pLTWh277ZetHEBzspKz41gPmT+fDvf0tL0HG/sWCs5uV+f/FiuBLgoR6V6bOIU5SDAEAgEGAC8ICMEuKTEVn9XrHA/l3Tn6FETmvx8q4MVse2fRVRKr7ufX6pTVGTXftmy9Bzv3Hn7bLeGtMmGKwH+bprK3TmJ8900BBgCgQADgBdkhADPmaPSrZtKRYX7uaQ7W7aa0NyqUqm5ayuh8VXgogTb8EYpkyfbjn/p6voxdar9glFTE854zvoAz1epXZ44JfMRYAgEAgwAXhB5AS65lt4VQN8ye7ZK377NnQ8qK1WKrnZsN7J05Ha1yqpVKhU3wxsz3olh06b0nEPxd+F32HC2E9wKlXsbEufaCgQYAoEAA4AXRFqAa2rsbvyePe1GKNfzSXceNKg8/7z1PnY9l7Zy/oKJ17BhyddpN8Zsx7devawWN9lODO3N/AX2l4Yw68xdCXDpepX7HyZO6XoEGAKBAAOAF0RWgOvrredr167p2/jAt5w6ZTJz4Ev3c2krtbW2Ui+iMnx4cImsqVGZNcvGGT06fXXOZeVWXrJwUbjjuhLgG3tUHhxOnBt7OiTAP/74o06aNEnz8vL+9Nj+/ft12bJlqToV8BQEGAC8IJIC3BhTmT3Hvsj3fOp+Pq6yfLlJWVj1qKnOqFFWrtG9u7Vpq+yABNfXq3xxQGXIEBPp9eut60U65t0YU5kyxVZ/r4XcacKVAJd9qdL4beKUfakioj/99JP+8ssvf8qvv/7a4rhr167Vn3/+WXNzc1VV9S//8i/10qVLCHAGggADgBdEUoDXvWdf4us3uJ+LqzTGbCOGiRPdz6W9mTdP5bnnVE6ebJbgtm5crL5jN/oNHGjXfOhQ63iRznkfOGDH3rw5/LFdCXD5cZVYQeKUH2++mfKJnD59usVxfyvA33zzjc6dO1cHDx6s//RP/5S28wP3IMAA4AWRE+Ddu+3LeO689Gx562suXmpaAd/jfi7tzc6dNueCy80S3KuX3cR27rxKWZlK3X2Vy4UqO3dZqUNP25JXxo5VOXIk/b2NK29ZnfWrr6ZmxdmZAJ9QiV1JnPITHVoB/uGHH3TixIm6fPlyvXr1qqqq/vM//zMrwBkIAgwAXhApAT561P78/bvf2Z/EXc/HZda9Z59FZ9r2+WaltRAbN85u4LtarDJpUosrjSJi5RKzZ6tcvOhuztOnW5lJ4ZXUjO9MgPNVYiWJU57PTXAQCAQYALwgMgJ84aJKjx4q2dnW79b1fFxn+HBbFXU9j45m5y4TsDfeULlxwx4rKlI58rWtEK9fr7Jvn7W3c73Cf+iQzXXjxtQdw5kAn1WJXU+c8rMIMAQCAQYAL4iMAL/yiv05PBM3u/ht4v1ot293P5eOpjFmu6iJqOTkuJ9PolTdVunXz27cS+VfG5wJ8HmV2PeJU34eAYZAIMAA4AWREeAPNtsX95cH3c8lUerq0nOczb9vamV1w/05dzTXb1gv4G7dbIXV9XwSZe48a7F3qSC1x3EmwJdUYhWJU34JAYZAIMAA4AWREeD6B7YK3Levrc65ns+TuXhRZcIEE4vi4tQfLyfHSkFcn3dH0hhTOXPWVlV797Zd3FzPKVGKi62+esWK1B/LmQBfUYndTpzyKwgwBAIBBgAviIwAxx6qfH3UvryP57mfS+yhdSuYPMXmFN/k4dz51B6zrNyO836atv8NmoZGlStFKjs+Vpn2jv3iImI7t10pcj+/1jJzlnWo6Eif4qBxJsDFKrGaxCkvRoAhEAgwAHhBpAR472fpW2VtLUVFKtOm2Vx697abpD5uavF1NcVzix/HR4m8U6OyY4fK1LetdVi8m0P//iaVuz9RuVXlfp6tJb76u2pVeo7nTICvqcTuJU75NQQYAoEAA4AXREqA462/6u67Of53JSozZ9ocevZUWbdO5Xa1PRfvblBWnto55ObaZhCuOyQ8mfoHJubxVd6BA22nvj2f+tHNoSNJ5+pv7KFDAS5Vid1PnPJSBBgCgQADgBdESoBzc20r3HQft7RUZe5cE9/u3VVWr352JTN+Y1oqtyW+XW03Zq1e4/5axHP+vN3UFm9tdv585xLeJ1P/wG7OW7Qofcd0JsBtdFMpr0CAIRAIMAB4QWQEuOBy+mtfvy9TWbjQpLNbN5Xly1Uqbrb82nfftfk1NKZuPvv2pafOuL359pSthA8apHLocOcV33gKr9jnu29f+o7pSoC/v6XS8GeJ8/0tBBgCgQADgBdERoBnzjTZipccpDIPGmxDhqwsy+LFtk1va+9ZutTqgVM5rylTrJ42lZLd3hw7bqvhw4dHpzfzvs9NDgsL03dMVwJ8447Kgx8T58YdBBgCgQADgBdEQoBLr6evLdWtKpW33jJJmD7D+ta2532z51jta6rmVVtrwrl4ifvrceSI/WLw8sudayvmtrJypZ1XOrfZdiXA1+pV6v46ca7VI8AQCAQYALwgEgK8ZImVIXzfxipssjl33tp0deumsnt3x/6kP3mKyogRqZtbfFvevBNur8WBL+1avPpqelbj05ncXOs1nc5jOhPgmMq9v0ucazEEGAKBAAOAF3R6Aa68ZSufc+ak7hiNMetXm5WlMniwbWzR0THGjVMZPTp1c5w9W+W559K7Ovnb7P3MVuLHjLGWZ65/NsJOTo5JcDqP6UqAS/6gUvvHxCn5AwIMgUCAAcALOr0Av/eefWEXpajvbd19qy8Wsd3cgu4y98or9v5UzLG+3uR39mx31yHe5i0318oxXP9cpCJjxtgvMuk8pisBLv5Bpea/JU7xDwgwBAIBBgAv6NQC/KDBNlSYNCl1x4i3L9u4UaWhIfg4Q4eqTJ+emjnmnbA5HjqU/mvQGFPZ9mHzLwj36tz/XHR0/tV3VK6Vtn3zYKpX8VuKKwEu+guV6v+ROEV/gQBDIBBgAPCCTi3Ap/Pty/rAgdSMX1Oj0qePyvjxyY/Vt6+1TEvFPBcvsTKQdK+83qpSmTHDrsHUqSr3HZZfdDSNMavjjm/O8dtfIMrKnz2ft95See219M7TlQAX/rVK1f9KnMK/RoAhEAgwAHhBpxbglausLjdV9aYb3zcZOH8hednKykrN9rkNDSr9+lkLtHR85vfqVA4etJv6srKs5nfjRtskwvXPQ3tTVma/1IjYim5WlsoLL6hUN920d+qUPTZ2rErdEyvaEyaoZGend66uBPjy36nc+j+Jc/nvEGAIBAIMAF7QaQW4Maby4ovhrM62lOpq69sbRnlF3f2mMor3w5/n2XOp35yhocE2tZg/3z4TEZPulStVrqSo9vrJVN1W+fqoys0Qth8+nW/n0L27ykc7mss39n9hzxdctuf7929e2Y6XvkyeojJyZOrP98k4E+B/UKn8f4lz+R8QYAgEAgwAXtBpBbjoqn1Rf7wzNeOva7q5rqAg+bEqK22s7dvDn+fqNdZ2LBUtx+rrVdZvsNZvIrbRyOw5Knl5Vn+dqmtbX6+Sn283OObk2CqziMqaJLd4rq+3bZmHDFEpKbHHRo2ylm1nz9pn2b27ye+NG7blsYhKyTV77dtv2/tTdd4txZUAn3+k8v3jxDn/CAGGQCDAAOAFnVaAN29u2rI1Bb1/b1WZ7L39djjjHTnS1KM3L9x5Nsbs5rpUtOa6W2t/8hexVfb9++2xjoxx6rRtD92e95WU2C8zk6fYZy9i4puTYxuciKh8sDm5c9qxo6nW93DzY8OHN9cAd+lixy+vsM82O9tWfM+ftzlMn27yHPZn3VpcCfCZRyqljxPnDAIMwUCAAcALOq0Ajx6dunrM1atNAsL68/78+Sq9eoV/k9iVotSsglfeslXRLl1Udu0ONkZxcXO5xOjRzfW1LWXlqmYJHTTIbhY8+FXzqnbxd/bcZ0mUecRvaBw37ukNTDZtMrHdv//pVfTb1XbM5cub55aba/NLxc9corgS4PxHKiWPEycfAYZgIMAA4AWdVoD79VOZNy/8cStu2p/BZ8wIZ7yGBrvBato74c/1/U0mK2Xl4Y1ZWmqryt27qxw+EmyM2lobo29fK/vIyrJSg4qbz7525047h7nzVL4raXl3vZPf2mtOnAx+XqdO2RhHj7bzHO41r0TH88or9nMX9nVsLa4E+NtHKlcfJ863CDAEAwEGAC/olALcGLO619VJ1oS2lOXLbeWz+Ltwxjt3vukmtc/Dn2t2tpUIhDXepQKT9T59VM6ctcfq69vuj/vbbNnydMnHsWMm1P36Pb1V8+l8+6wnTGi9pnjfvqbNGYqDn9ueT5vqeUva/554i7esLPvfIUOs73TY17G1uBLg449UCh4nznEEGIKBAAOAF3RKAb5TY1/SW7aEO25ZmUq3bipz54Y35rp1JnlVVeHOtarKPoOXX1a5EGBr5t8mL89WPAcOtBsMG2NWctC3r7UDa62E4cncrTVJfOutpx+/XGg3kImorF1rYr2paQW7rV82dnycfElK/Dp0pAzl900iP39B8yrwiy+Gex3biisBPvpI5cLjxDmKAEMwEGAA8IJOKcClpfYlvefTcMddvNhWlktLwxtz5MjUfL4NjSaQzz1nYnfsePCxDhywVc6RI62c4voNq5UVsdJfl3xjAAAgAElEQVSFrCyVESPsF4S2xjp0OHG5Qm2tla2IqLz+upUjiKhs3db6mBUVNocFC4Kf4/QZKoMHd+w9dfdt5X77R80CvHhJ+NeytbgS4MOPVM4+TpzDCDAEAwEGAC/olAJ8/kLTl3TAGtWWcv2GSVaYu7WVXm+f4CWT6moT1379TNg6+v6aGpUePZ6+UW3SJFsN3rnTapjzTti/BwxoexV25Ur7HOta2RJ5/34br3dvW3EfMaLl2t8ns2iRjdseCW8pI0cG75aRm9sswO2tIQ4rrgT4q0cq+Y8T5ysEGIKBAAOAF3ROAW6qq/06RBmZN88EK8y2ah/tePpP/C3dBBZGjufZcVas6Ph7d+229549Z/+urTUpXbrs6dcVFJhk9+5t7c0SjZeTozJmTNvHLblmnSbiYnnxUuuvLy21le7lAc6xpKSpZGZrx99bXGx/FRCxzyXd2027EuD9j1TyHifOfgQYgoEAA4AXdEoBLi62L+nP94czXkmJydXSpeHOMzdX5aWXbHUzXk8axsYav01Do5UqdLQv8pO9buMrsF83lSUcb6Fn8fUbVhM8YEDiMQcPVpk5q33Hv1/f3AKtPfXcs2fbzXS3OlhPHa81vnGj45/rG2+YAGdlqfzud+Ffu7biSoD3PVI59jhx9iHAEAwEGAC8oFMKcHmFfUnvDKn/7axZJlYVFeHNsfpOU6eK1c1dDERUCgvD/SweNKjMmdO8AtxWKcGTuXjJ3vfRjubHFi6y8oSWyimuFjf9orAs8Zh9+li5QkfO4UpR+1ZWi5r6Hq97r2PjjxxpNccd/Ww/2fP0JhlfHQr32rUnrgR41yOVg48TZxcCDMFAgAHACzqlANfctS/pzb9Pfqzb1U1/Wl8e7hwPfNnc8aBr1+Y/o1dWhneM+/Uq06bZuOvXd0x+Yw9NVLt1a94AojFmq7tTprT8+qlTTY4TnUNjzFZKV69O3bWfOtXKMO7UtO/1V4uDbUN9s9JuMBQxqW9pRTwdcSXAWx+pfPo4cbYiwBAMBBgAvKBTCnBDo0nr2neTH+vQIfvCb62utSOpqbGx3nyzuW501CjrMNGli91UFtbnsGZN8NrW2lrbnW7WE+UKJdeaVv9a2P3t7Dl7bsMG+3d5hbUHy85Wmfq2Cfi6dfaaHTuCnU97Er8BcnM7t0VeutQ+945uFjJzph0nO9tuZkzV+bQVVwK88pHKxseJsxIBhmAgwADgBZ1SgGMPbRVwSQgtqZYssfKHIB0UnkxjzFY+u3R5evewQYNMFufOC38Xsddfb98NZy3l071N4n+q+bGzZ+2xb449/dr6evsZ6dvXVt9jD61XclaWif6LLzafb3Z26x0gkk1dnV37d9qxs168s8f8AO3T3njDboy8l8Jzaec8nAjwwkcqqx4nzkIEGIKBAAOAF3RaAR406OnVy6B56aXkb25qjFl/WBGb0+5PTLz69GnevWzCBJPDsM6/odHKEYL2pY1vQTxrlglu7KHK0W/ssXPnm19X/0Bl/Pimvst7ms+3X7+nt3euu29dLuofpPa672jqrPHkjnKJMreps8eN79P/8xlWXAnwjEcqCx4nzgwEGIKBAAOAF3RaAR41SmXy5OTGKCsLXkLwZC4V2DhLl1oJRHa2rSo/KZLZ2SbBYZ1/fDOQnbuCvb8xprJxo40xcaJK7T3b9OG3O7NduGiPbdrU/NiVppvRPtmT3mted99qlEePbrveubg4NbXd6Y4rAZ70SGX648SZhABDMBBgAPCCTivAY8bYbmXJjPFZU3eGS0m2Jtu2zca5VmpbAHfp8uyGCf362Z/Uwzr/I0fsmPlnkhvn46aV4DFjrL5XRKXyVvPz55p6Ln+274nz/dAeu97BtmLJJj7Xtm5Ia4ypTJ5iG3yEedOhi7gS4FceqYx+nDivIMAQDAQYALyg0wrwxInJlxTMnm1lCsnemPb229b/dvWalrdobmgwKX43hJv24on3tq2+k/xYXzRthRyvX46XRMQeqtytVRk61Mot4rI9YYI9ls7rffGi/RLx+uttr/7Gyzvae6Ocz3ElwC89Uhn5OHFeQoAhGAgwAHhBpxXgGTNUhgwJ/v7GmEr//k/XsSYzl549TSDntrDKW1n5bL/dZDN3brg31R07biumvXo9+1xZebMEnzhp5R1h3IDYntTWqnyw2QR9wICWNxJZv8Hm9+VBW83v1s3qlsPsuOEqrgS4/yOVQY8Tp3/HBPjHH3/USZMmaV5enqqqVldX65QpU3Tr1q2pPB3wEAQYALyg0wrw/PnWlSDo+78vC69l18qVTdLQX6W6+tnnCwvt+QNfhnj+C1ReeCHcz7TgssrBr1p+Li7B8VXiI0dSd20bY1Z7vHCRCbmItVqruv3sa0+dsud79GjuRNG//9NlHJ05rgRYHqnI41ZiAvzTTz/pL7/88qf8+uuvLY67du1a/fnnnzU3N1dVVf/zP/9T//3f/13ffPPNtJ0b+AECDABe0GkFeMyYYLt7xXP+fHgit/0jG+vroy0/n5cXbq/h2EO7uatnz/R+5nEJ7tat/RtRdDR5ec3bOnfvbl0qTp1queyhpsa6gQwZYpt5ZGeH/zm7jjMB/nsV+b+t5O+fbvfXlNOnT7c47m8F+D/+4z90/fr1+sc//jFt5wZ+gAADgBd0SgF+0GBy1NqWvG3lcNNNZOcvJD+fu7Wt34wW3wr5ye4KyWbtuzZmR3d/Sza3q1UKr4Q/bkND80YaQ4faDW8trabHU3vP2td16dL82d+pSf6GRt/iTID/VkX+dyv52w6tAP/www86ceJEXb58uV69elUvXbqkw4cP1yVLlqTt3MAPEGAA8IJOKcCFV57tTNDR7NptY3xflvr5btkS3g1r8bzfdBNcKjedSGfi5zN3rtX9tvba29XWCq1LF5XdLexaF6U4E+C/UpH/2Ur+ipvgIBAIMAB4QacU4L1Nu5gVFQUfI94DN9kd4NqTlSutbCDM1dp467XbraySdpZcvKTStavK9On2S0JrK8zlFSojR9pNcV8edD/3VMeZAP+5ivz3VvLnCDAEAgEGAC/olAK8ZInVvz5I4i7/uEDeqkr9fGfOtDZpYY4ZX8EuK3d/PZLNokXNq7+9etnKbkvlIiXX7HPs2dNqhV3POx1xJsB/piL/tZX8GQIMgUCAAcALOqUAv/pq8nM+eNC+6FtqqxV2cnOTu2GvpcTrir8rcX89ks2WrXYuXbqoTJ1qq8GLFz/9moIC63rRp4/dwOh6zumKMwF+2HSjW6I8RIAhEAgwAHhBpxPg/DP2Bb3x/eTGORdiF4i2MmKEiV2YYx78qkngL7u/JsmmMaZSUdFczrFokcnwlaYSl1OnVXr3tj7AV4vdzzedcSbADU03uiVKAwIMgUCAAcALOpUANzRYq6v+/a3zQjJjlVeE1we4rfTp8+yKZrI5dszmf/as++sSdqqqrMvHggX2C0q3birDhqnc+N793NIdZwJ8V0X+Syu5iwBDIBBgAPCCTiXAn+yxL+d9nyc/VkOD7aQ2fnxq51x3v2nFemO44546beOeOOn+uqQiEyc276736qvpqdX2Mc4E+LaK/NBKbiPAEAgEGAC8oNMIcPUd2/nt9ddVGhrDGXNTU+utwsLUzTu+49yukNt1XbiYvhIOF5k9x84vN1el5q77+biKMwGuVJE/tJJKBBgCgQADgBd0GgGObzd84WJ4Y8b/1D53XurmHd9x7nDIonqlyMb94oD7a5OKHDumsnxFetrU+RxHAtxVyjVLYgnTVcoRYAgEAgwAXtApBLi42DoDpEJUFy+2nrIVN1Mz93i7spKQuzWcOmXjHs+QdmCZGkcCPERu6EvyIGGGyA0EGAKBAAOAF3gvwI0x2/K2Vy+Vm5Xhj/9diYnkunWpmf+cOSrPPx/+lsXxzUCi0AaNJI4jAc6W65oj9QmTLdcRYAgEAgwAXuC9AB89aqK3ZWvqjjF5snVqaGsL3iAZOlRl0qTwx12/Pn072RF3cSTAY+Wajpe6hBkr1xBgCAQCDABe4LUA3683gRw61P47VceJd1TYuTPccW9V2bgfbA5/zrNnW19c19eIpDaOBHiSXNPpci9hJiHAEBAEGAC8wGsBju8QdvRoao/TGLNWW0OHWnu0sMaN7zb37anw5zxmjL/XjYQXRwK8WIp1jdQkzGIpRoAhEAgwAHiBtwJ8s9LqfidMCL9+tqXs/yLctmK191SGDFF58cXwyxTu19tns2CB++tEUhtHArxWrupmuZMwa+UqAgyBQIABwAu8FeC586zzQ3Gatr6tf6AycGB4n8XqNSbUJ1OwUUXeCRv70GH314mkNo4EeLMU6S6pTpjNUoQAQyAQYADwAi8FOL7Jw8qV6T3u1m123ItJ9houuGw7mM2dm5p5Lltm2wMnux008T+OBPhjKdQvpCphPpZCBBgCgQADgBd4J8ANjbbbW9++Kndq0nvsm7a7lWzdltw4EyZYV4mq2+HPsTGmMniwHcP1tSKpjyMBPiKX9ZxUJswRuYwAQyAQYADwAu8EeN/nJqF79qT/2I0xq61dvDj4GEVWGykbNqRmjoVXmjpW7HJ/rUjq40iAj8klvSQVCXNMLiHAEAgEGAC8wCsBvlur0r+/yiuvhNuNoSPJzlYZPz74++fPt+2VK2+lZn4fbDYB/r7M/fUiqY8jAf5GLupFKU+Yb+QiAgyBQIABwAu8EuBNm0zuzpx1N4dp71j3hqDv79dPZerU1MytodFateXkuL9WJD1xJMBH5YJekLKEOSoXEGAIBAIMAF7glQBPmKAyapTbOaxebTewBV2BHj9eZfjw1Mzt2DH7BWHfPvfXiqQnjgT4sJzVs3I9YQ7LWQQYAoEAA4AXeCXAQ4aovPOO2znMnmOruEHfv+kDk9TKyvDnNmGC3RzI9seZE0cCfEjO6BkpTZhDcgYBhkAgwADgBV4J8AsvqMx3vLnDq6+q5OYGf3++iYF8dSjceZWU2Ljvvef+OpH0xZEAfyX5elpKEuYryUeAIRAIMAB4gVcCPGSIysyZ7o7f0KjSo4fK0mXBx6i7bzfBLUtijJayfIVtDFJe4f46kfTFkQB/Kaf0WylOmC/lFAIMgUCAAcALvBLgESNUJk9xd/zT+U01tp8nN86bb4Zby1xVpdK7t8r06e6vEUlvHAnwF3JST0hRwnwhJxFgCAQCDABe4JUA5+SovPWWu+MvWGCrtzV3kxtnwwYT6dvV4cxr2TK7Ma+w0P01IumNIwHeLyc0T64kzH45gQBDIBBgAPACrwR43DiV0aPdHPtena2yzpyV/Fjf2p+H5cjXyY9VUmKlD65ro4mbOBLgzyVPj0thwnwueQgwBAIBBgAv8EqAJ060jShcHPvLgyatx/OSH+tenUpWlsrKVcmPNXWqSs+eKhXU/mZkHAnwLvlKD0p+wuySrxBgCAQCDABe4JUAT3vHNnpwcexJk6z92YMkd6BrjKkcOmTSOnZscmMd+dqkfONG99eGuIkjAd4qe/VT+TphtspeBBgCgQADgBd4JcBz5thWyOk+buUtKzNIdsX2SpG1UBOxG/qS2dEuL0+lWze7ma621v21IW7iSIDXy0f6oXyeMOvlIwQYAoEAA4AXeCXAU99WGTYs/cfdvdukteBysPffqrLWaV26WB3x9o9U6h8En8/Jb+1mvJEjbWzX14W4iyMBXinv60bZkTAr5X0EGAKBAAOAF3glwDk51kIs3cdduFDlueesfKEj7ysuVlm4yGS1Sxf772SF9dRpG2/48NTsJkc6VxwJ8AxZqAtkVcLMkIUIMAQCAQYAL/BKgAcMUJk9O/3Hff319n8GjTGVkyfthj0Ru9lt/nyVoqLk55F/xmqHhw1Tqbjp/noQ93EkwJNkuk6X+QkzSaYjwBAIBBgAvMAbAS6vMKHc/Pv0Hreh0aRz8ZK2X3vypMrLL9s8n39eZf16lZshrdKePWfzGDqU3d5IcxwJ8DiZoBPk7YQZJxMQYAgEAgwAXuCNAO/bZ2J58VJ6j3v9hh13567WX1dVZWUSQ4ao7P7EWp2FNYfzF6x2eMgQlbIy99eC+BNHAvyKjNHRkpswr8gYBBgCgQADgBd4I8Cz56j06aPSkGQbso7m6FET4Pz81l+3eElqdmO7eMnkd/BglRvfu78OxK84EuD+MlAHyZCE6S8DOyTAP/74o06aNEnz8vJUVfUf//EfdcqUKbpjx45Ung54CAIMAF7ghQA3xqwH77R30n/szZvb3ra4sNDkd/HicI9dcNmkf9AgldLr7mWL+BdHAtxTemkv6Z0wPaWXioj+9NNP+ssvv/wpv/76a4vjrl27Vn/++WfNzc1VVdUDBw7o3/zN3+icOXP0X//1X9N2fuAeBBgAvMALAS4qMgnd/Ul6j1tfr/LSS9azN9FrGmO2RfNzz1kZRFjHLrxidcQDBqhcK3UvWsTPpFmA/+3f/k0HDrTV3bbSu3fvZx47ffp0i+MiwBAHAQYAL/BCgD/fb1+gV0LopNCRfLjdjnvk68SvOWhbvspHO8I7bn29iW+/fiolJe4li/ibNAuwqknwk6u6ifIv//IvzzyWaAX4hx9+0IkTJ+ry5cv16tWr+tNPP+nkyZN1+/btaT03cA8CDABe4IUA/36LSeadmvQd88YNq719663E/X/v1Vlt7ogRyW1s8dvE644PHXYvWMTvOBBggFSCAAOAF3ghwMuW2eYPHd2IImjq7qu8+qpKr14qJdcSv+79TSaqeSfCPf7MmVZSUXffvWARv4MAQ8RAgAHAC7wQ4F1NWxF/cyw9x1u61I538KvErykrU+nRQ2XKlHCPfbfWxl2wwL1cEf+DAEPEQIABwAu8EOD79dYJITvbNqZI5bEuXDT5Xbo08WsaY9aRIitLpTTEG9Tu11s7NRGVb0+5lyvifxBgiBgIMAB4gRcCHHuosvczE8MvD6buGI0xO9fnn2+93njz720uGzeGd+zLhSb4IiqLFqVe9Ek0ggBDxECAAcALvBHgBw0qw4ZZW7Iwbzh7MoePmIDu+Djxaw4etNdMeyccSS0pUZkxw8bs00fl0CH3nzXpPEGAIWIgwADgBd4IcOxhc8uxIUNU5s5T+XSvyncl4dwcF+/5O2yY/XdLrzl33m7Gy8lJfqvjsjKVhQtVuna1MdesUam67f4zJp0rCDBEDAQYALzAKwFuaLQb4iZNsi4J8Qb7L7ygMnmyyrx5KitWqKzfoLJtm8one0yaq1vZxS2eHTuaev4eafn50usqffta27PKyuDncKtKZeVKlW7drIZ4yRKVigr3ny3pnEGAIWIgwADgBV4J8JNpaLCNMXbtVpk5S2X4cNs4onv3Z3el6tlTZdUqlfIEoll9x+p+x41reTW5+o6N37u3StHVYPO9U6Oyfr3NpUsXlTlz2N6YJB8EGCIGAgwAXuCtALeW+nqV29Uq12+onM5XmT7dpDMrS2X+/GdvcNvftNNcfn7LY+XmWqnCyZMdn0vtPZUtW6y+V0Tl7beDSzQhvw0CDBEDAQYAL+iUAtxSSq6pLFxkErply9PPbXzfHv9tXW9jzMoqRFT2fNqx492vV9m501alRVTGj7cWa64/BxKtIMAQMRBgAPCCyAhwPL16Pdvj9733TFIbGp5+/IPN9vjadzt2jJJrdqOeiMro0Sqn6OlLUhQEGCIGAgwAXhA5AR42TGXq208/9u67JqtP1v/m59tj73Sw3VlDo9US9+6t8vXR9G3fTDIzCDBEDAQYALwgcgL85pvWxuzJx3buMtm9UtT82L7P7bHCwo6Nv2ePvW/3bvfnSqIfBBgiBgIMAF4QOQGeNcu2VX7ysfIKu8ntydKIs+dab4vWUm5WWnu2N95gJzeSniDAEDEQYADwgsgJ8Oo1Jru/FdTZs1V69FCprbV/l1wzAd6+vf1jT59hnSauFrs/T5IZQYAhYiDAAOAFkRPgLVtMbCtvPf143gl7/OBXdjPchAkmswUF7Rv36Df2/g0b3J8jyZwgwBAxEGAA8IJICfCVItvwYuBAlbr7Tz9X/8CEd9Uqlb17TWY/2tG+ce/WWlnFsGHPjktIKoMAQ8RAgAHACyIjwMXFtpVxv34q35W0/Jq+fVUmT7HWZUOHtr+Od8WKxBtpEJLKIMAQMRBgAPCCSAhwSYmJb9++rdfnjhrVvH3y7NntG/vCRdtlbuEi9+dJMi8IMEQMBBgAvKDTC3BpqcqAAVb6UHil9ddev6HyzTFL1e22x65/oPLyyybX1XfcnyvJvCDAEDEQYADwgk4twKfzrTb3uedUCi6HP378hrqDB92fK8nMIMAQMRBgAPCCTinANTUqi5eYnA4apHLxYvjHKC1V6d5dZfJkdnsj7oIAQ8RAgAHACzqdAB/9xro8iKgsXaZSczf8YzTGVN56S6VnT5Xvy9yfM8ncIMAQMRBgAPCCTiPAVVW2y5uItSM7czZ1x4pvk9zeNmmEpCoIMEQMBBgAvKBTCHB5hUr//rbD27r3UtuL91aV3VCXk2MbZrg+d5LZQYAhYiDAAOAF3gtwQ4PKuHFWj3shBbW+v83sOSbahYXuz50QBBgiBgIMAF7gvQBvfN/KEfbsSf2x4tslr33X/XkTEnuIAEPkQIABwAu8FuDT+bYJxYwZqe/EUHtPZcgQ2yHuXp37cyck9hABhsiBAAOAF3grwA2NJqRDhljbs1Qfb80aW/09edL9uRMSDwIMEQMBBgAv8FaAz18wId37WTjjVVWp7PlU5f1NKkuXqkybZuc9dKhKr152rLlz3Z83IU8GAYaIgQADgBd4K8Dr3rPyh1tVyY1T/0Blx8cqffqY5IqY8A4dauc97R0T4i1bU9NTmJBkggBDxECAAcALvBXgUaOSn9fpfBtHxDpJnL9gtb6uz42Q9gYBhoiBAAOAF3gnwI0xlXXrTFq3bw8+TkmJtTMbNEjl4EG2MyadMwgwRAwEGAC8wCsBrn+gMndeUz3uPPt30LHmL1Dp1s020XB9XoQEDQIMEQMBBgAv8EaAS0qsTEHE6n+TWbH9vkwlK0tl8WL350VIMkGAIWIgwADgBc4F+F6dCW9Wlt2cFsaGF8uW2Q10pdfdCwwhyQQBhoiBAAOAFzgV4OLvrBuDiG12URFCuUJlpW2bPHuOe3khJNkgwBAxEGAA8AJnAnzyW5XnnlN5/nmVvLzwxl37rgn11WL38kJIskGAIWIgwADgBU4E+HiedWgYNkyltDS8caurrYxi2jT34kJIGEGAIWIgwADgBU4EePRolcGDTVjDHHfTJlv9vVTgXlwICSMIMEQMBBgAvCDtAnzxoknqtm3hjltba+UUEya4lxZCwgoCDBEDAQYAL0i7AK9YYf15w1793fahiXX+GffSQkhYQYAhYiDAAOAFaRfg114L/3jVd1T69VMZO9a9sBASZhBgiBgIMAB4QVoFuPae3fy2ek244y5aZH1/L1x0LyyEhBkEGCIGAgwAXpBWAc7PtzKFw0dCHPOMjbl8hXtZISTsIMAQMRBgAPCCtArwli0mqzcrwxnvfr3K8OEqgwap3K11LyuEhB0EGCIGAgwAXpBWAZ4yRWXIkPDG2/i+CfXRo+5FhZBUBAGGiIEAA4AXpE2A6x+o9O2rMmtWOOMVFKhkZam88457SSEkVUGAIWIgwADgBWkT4H2f22rtocPJj3X+gkqfPioDBqhU3HQvKYSkKggwRAwEGAC8IC0CfP6CyosvqowYodLQmNxY+fm23fHgweFuo0yIj0GAIWIgwADgBSkV4IIClUmTbOW3Tx+VvBPJjZd3QqV7d5WXXlIpK3MvJ4SkOggwRAwEGAC8ICUCXFSkMm2aiW/v3iobN6rcqQk+Xl2dyo6PbQe5kSPD6yJBiO9BgCFiIMAA4AVJCXB1tcqZsyqf7LE+vG+9ZTuyiaj07Kmybp3K7SS2PL5bq7J1W/OYb7yhUlXlXkoISVcQYIgYCDAAeEGHBbi8QmX7RyqjR5uUxtO9u0p2tnV52LJV5VZAUW1oVCkrt1XjPn1s7HHjVPLyVBpj7oWEkHQGAYaIgQADgBe0S4AfNKjs2q0ydmyz8I4YobJ+vcqRIyol1+w17flCb4ypVN6ybYsPHrTNMRYvUZkwwTa16N69+RgTJ9oKs2sJIcRVEGCIGAgwAHhBuwR4+3YT0pdeMuktKmr/auzlQpWVK+1muBEjVHr0eHrlWMS6Orz8sm2UsXyFrTBfLnQvH4S4DgIMEQMBBgAvaFOAGxps97acnPZLb0ODytdHVd580wS3WzeVUaNUJk9WWbZM5cPt1g+4oMBqhCltIKTlIMAQMRBgAPCCNgX4yNcmsV8caN8X9uf7VYYOtfcMGKCyebNK1W33IkFIZwwCDBEDAQYAL2hTgHNzTWTr69v+so6XSmRnq+z/on3vIYQkDgIMEQMBBgAvaFWArxSZ0G76oO0v6o932munTEF8CQkrCDBEDAQYALygVQHev9+ktuBy61/Suz9p7tpwH/klJLQgwBAxEGAA8IJWBfjUKRPb43mJv6ALCuw148fbjm2uhYGQKAUBhoiBAAOAF7QqwNdKTW737En8Bb1qlUrXrtzoRkgqggBDxECAAcALWhXgujoT4PUbWn6+oVFl4EDbxMK1KBASxSDAEDEQYADwgja7QPTtqzJvXsvPnT1ngrz3M/eiQEgUgwBDxECAAcAL2hTgN95QGTmy5eeWr1DJylKpvuNeFAiJYhBgiBgIMAB4QZsCvG2brfJ+V/LscyNHWp9g15JASFSDAEPEQIABwAvaFODS6ybAm3//7HO5uSqvvupeEgiJahBgiBgIMAB4QZsCHHtoO7u99tqzjy9erNKrl0pjzL0oEBLFIMAQMRBgAPCCdgnwpg9sFfjG908//mHT1sc3K92LAiFRDAIMEQMBBgAvaJcAl1xT6dJFZfXqpx8/etQEOP+Me1EgJIpBgCFiIMAA4AXtEuDYQ5UZM1R69Fg8sOIAAAS0SURBVFCpvNX82HclJsCf7nUvCoREMQgwRAwEGAC8oN0CXHTVZHf1mubH6uttZXjtu+5FgZAoBgGGiIEAA4AXtFuAYw9VpjetAt+qan5s6FCVt992LwqERDEIMEQMBBgAvKBDAhxfBV65qvmxiRNVRo1yLwqERDEIMEQMBBgAvKBDAhx7qDJ3rpU9XLxk/16+QqV7d5WGBveyQEjUggBDxECAAcALOizAt6tV+vWzXeDu16vs3NlyizRCSPJBgCFiIMAA4AUdFuDYQ5UjX5v0vveeSt4J+++TJ93LAiFRCwIMEQMBBgAvCCTAsYcqs2apdO2q8tUhE+Cdu9zLAiFRCwIMEQMBBgAv6LAA19SY7I4Y0dwWrVs3lZUr3csCIVELAgwRAwEGAC9otwAXXFZZuEilZ08T31GjTISrqlR691aZM8e9LBAStSDAEDEQYADwglYF+F6dymf7VHJyTHq7dVOZPUfl7DmVxpi9ZtuH9typ0+5lgZCoBQGGiIEAA4AXtCjA9Q9U1qxR6dPH5HbgQBPdqttPv+5enXWEGDeuWYgJIeEFAYaIgQADgBe0KMAVFVbWINKcfv1U3nxTZfESle0fqRzPU9mwwZ779pR7USAkikGAIWIgwADgBQlLIOru285vhw6pfLDZSh9ee625BjiesWNZ/SUkVUGAIWIgwADgBR3uAtEYUymvUDn5rcru3SrXb7iXBEKiGgQYIgYCDABeELgPMCEk9UGAIWIgwADgBQgwIR4HAYaIgQADgBcgwIR4HAQYIgYCDABegAAT4nEQYIgYCDAAeAECTIjHQYAhYiDAAOAFCDAhHgcBhoiBAAOAFyDAhHgcBBgiBgIMAF6AABPicRBgiBgIMAB4AQJMiMdBgCFiIMAA4AUIMCEeBwGGiIEAA4AXIMCEeBwEGCIGAgwAXoAAE+JxEGCIGAgwAHjBrFmzVERMggkhfqV3bwQYIgUCDADeMGvWLEKIp9m7d6/r/4sACA0EGAAAAAAyCgQYAAAAADIKBBgAAAAAMgoEGAAAAAAyCgQYAAAAADIKBBgAAAAAMgoEGAAAAAAyCgQYAAAAADIKBBgAAAAAMgoEGAAAAAAyCgQYAAAAADIKBBgAAAAAMgoEGAAAAAAyCgQYAAAAADIKBBgAAAAAMgoEGAAAAAAyCgQYAAAAADIKBBgAAAAAMgoEGAAAAAAyCgQYAAAAADIKBBgAAAAAMgoEGAAAAAAyCgQYAAAAADIKBBgAAAAAMgoEGAAAAAAyCgQYAAAAADIKBBgAAAAAMgoEGAAAAAAyCgQYAAAAADIKBBgAAAAAMgoEGAAAAAAyCgQYAAAAADIKBBgAAAAAMgoEGAAAAAAyCgQYAAAAADIKBBgAAAAAMgoEGAAAAAAyCgQYAAAAADIKBBgAAAAAMgoEGAAAAAAyCgQYAAAAADIKBBgAAAAAMgoEGAAAAAAyCgQYAAAAADIKBBgAAAAAMgoEGAAAAAAyCgQYAAAAADIKBBgAAAAAMgoEGAAAAAAyCgQYAAAAADIKBBgAAAAAMgoEGAAAAAAyCgQYAAAAADIKBBgAAAAAMgoEGAAAAAAyCgQYAAAAADIKBBgAAAAAMor/D30RqmwIygNOAAAAAElFTkSuQmCC\" width=\"704\">"
],
"text/plain": [
"<IPython.core.display.HTML object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# Plot the figure, define the geographic bounds\n",
"fig = plt.figure(dpi=110)\n",
"# fig = plt.figure(figsize=(5,3))\n",
"\n",
"latcorners = ([-60,60])\n",
"\n",
"loncorners = ([-180,180])"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<cartopy.mpl.feature_artist.FeatureArtist at 0x7f8536c3d6d8>"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ax = plt.axes(projection=ccrs.PlateCarree())\n",
"# ax.coastlines()\n",
"# ax.add_feature(cfeature.BORDERS)\n",
"ax.add_feature(cfeature.STATES.with_scale('10m'))"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"# Draw filled contours.\n",
"\n",
"clevs = np.arange(0,1.26,0.125)"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"# Define the latitude and longitude data\n",
"\n",
"x, y = np.float32(np.meshgrid(theLons, theLats))"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"# Mask the values less than 0 because there is no data to plot.\n",
"\n",
"masked_array = np.ma.masked_where(precip < 0,precip)"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
"cmap = 'nipy_spectral'"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"scrolled": false
},
"outputs": [],
"source": [
"# Plot the data\n",
"\n",
"cs = ax.contourf(x,y,precip,clevs,transform=ccrs.PlateCarree(),cmap=cmap)"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
"# Set the title and fonts\n",
"\n",
"plt.title('August 2015 Monthly Average Rain Rate')\n",
"\n",
"font = {'weight' : 'bold', 'size' : 3}\n",
"\n",
"plt.rc('font', **font)\n",
"\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<matplotlib.colorbar.Colorbar at 0x7f8526e64cc0>"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"sm = plt.cm.ScalarMappable(cmap=cmap,norm=plt.Normalize(0,1))\n",
"sm._A = []\n",
"plt.colorbar(sm, ax=ax, label='mm/h', shrink=0.5)"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [],
"source": [
"# ax.set_extent([-180, 180, -90, 90])"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [],
"source": [
"# fname = r'./layers/POLYGON.shp'\n",
"\n",
"# # ax = plt.axes(projection=ccrs.Robinson())\n",
"# shape_feature = ShapelyFeature(Reader(fname).geometries(),\n",
"# ccrs.PlateCarree(), edgecolor='black')\n",
"# ax.add_feature(shape_feature)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.2"
}
},
"nbformat": 4,
"nbformat_minor": 2
}