##// END OF EJS Templates
Added notebook to change LFR calibration signal @ MEB level...
jeandet -
r14:f0e952d2a4cf
parent child
Show More
This diff has been collapsed as it changes many lines, (1991 lines changed) Show them Hide them
@@ -0,0 +1,1991
1 {
2 "cells": [
3 {
4 "cell_type": "code",
5 "execution_count": 11,
6 "metadata": {
7 "ExecuteTime": {
8 "end_time": "2018-04-03T16:04:10.171721Z",
9 "start_time": "2018-04-03T16:04:10.156985Z"
10 }
11 },
12 "outputs": [],
13 "source": [
14 "import numpy as np\n",
15 "import matplotlib.pyplot as plt\n",
16 "import pandas as pds\n",
17 "%matplotlib notebook\n",
18 "\n",
19 "SAMPLING_FREQ = 218181.818\n",
20 "start = int(round(SAMPLING_FREQ*11))\n",
21 "snapshot_width = int(round(SAMPLING_FREQ*22))\n",
22 "second_width = int(round(SAMPLING_FREQ*1))"
23 ]
24 },
25 {
26 "cell_type": "markdown",
27 "metadata": {},
28 "source": [
29 "# Calibration CSV file loading"
30 ]
31 },
32 {
33 "cell_type": "code",
34 "execution_count": 39,
35 "metadata": {
36 "ExecuteTime": {
37 "end_time": "2018-04-03T16:35:08.062058Z",
38 "start_time": "2018-04-03T16:35:07.247444Z"
39 }
40 },
41 "outputs": [
42 {
43 "name": "stdout",
44 "output_type": "stream",
45 "text": [
46 "93600003 ./multisin_paquet2.csv\r\n"
47 ]
48 }
49 ],
50 "source": [
51 "!wc -l ./multisin_paquet2.csv"
52 ]
53 },
54 {
55 "cell_type": "code",
56 "execution_count": 41,
57 "metadata": {
58 "ExecuteTime": {
59 "end_time": "2018-04-03T16:35:44.885853Z",
60 "start_time": "2018-04-03T16:35:44.679374Z"
61 }
62 },
63 "outputs": [
64 {
65 "name": "stdout",
66 "output_type": "stream",
67 "text": [
68 "waveformName,Multisine_paquet2\r",
69 "\r\n",
70 "waveformPoints,93600000\r",
71 "\r\n",
72 "waveformType,WAVE_ANALOG_16\r",
73 "\r\n",
74 "0.100000\r",
75 "\r\n",
76 "0.100000\r",
77 "\r\n"
78 ]
79 }
80 ],
81 "source": [
82 "!head -n 5 ./multisin_paquet2.csv"
83 ]
84 },
85 {
86 "cell_type": "code",
87 "execution_count": 12,
88 "metadata": {
89 "ExecuteTime": {
90 "end_time": "2018-04-03T16:04:21.756250Z",
91 "start_time": "2018-04-03T16:04:13.394367Z"
92 }
93 },
94 "outputs": [],
95 "source": [
96 "df = pds.read_csv('./multisin_paquet2.csv', skiprows=3, header=None)"
97 ]
98 },
99 {
100 "cell_type": "markdown",
101 "metadata": {
102 "ExecuteTime": {
103 "end_time": "2018-04-03T15:27:20.097031Z",
104 "start_time": "2018-04-03T15:27:20.088523Z"
105 }
106 },
107 "source": [
108 "## Few verifications\n",
109 "### Is start position asumption good?"
110 ]
111 },
112 {
113 "cell_type": "code",
114 "execution_count": 13,
115 "metadata": {
116 "ExecuteTime": {
117 "end_time": "2018-04-03T16:04:22.794779Z",
118 "start_time": "2018-04-03T16:04:22.716928Z"
119 }
120 },
121 "outputs": [
122 {
123 "data": {
124 "application/javascript": [
125 "/* Put everything inside the global mpl namespace */\n",
126 "window.mpl = {};\n",
127 "\n",
128 "\n",
129 "mpl.get_websocket_type = function() {\n",
130 " if (typeof(WebSocket) !== 'undefined') {\n",
131 " return WebSocket;\n",
132 " } else if (typeof(MozWebSocket) !== 'undefined') {\n",
133 " return MozWebSocket;\n",
134 " } else {\n",
135 " alert('Your browser does not have WebSocket support.' +\n",
136 " 'Please try Chrome, Safari or Firefox β‰₯ 6. ' +\n",
137 " 'Firefox 4 and 5 are also supported but you ' +\n",
138 " 'have to enable WebSockets in about:config.');\n",
139 " };\n",
140 "}\n",
141 "\n",
142 "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n",
143 " this.id = figure_id;\n",
144 "\n",
145 " this.ws = websocket;\n",
146 "\n",
147 " this.supports_binary = (this.ws.binaryType != undefined);\n",
148 "\n",
149 " if (!this.supports_binary) {\n",
150 " var warnings = document.getElementById(\"mpl-warnings\");\n",
151 " if (warnings) {\n",
152 " warnings.style.display = 'block';\n",
153 " warnings.textContent = (\n",
154 " \"This browser does not support binary websocket messages. \" +\n",
155 " \"Performance may be slow.\");\n",
156 " }\n",
157 " }\n",
158 "\n",
159 " this.imageObj = new Image();\n",
160 "\n",
161 " this.context = undefined;\n",
162 " this.message = undefined;\n",
163 " this.canvas = undefined;\n",
164 " this.rubberband_canvas = undefined;\n",
165 " this.rubberband_context = undefined;\n",
166 " this.format_dropdown = undefined;\n",
167 "\n",
168 " this.image_mode = 'full';\n",
169 "\n",
170 " this.root = $('<div/>');\n",
171 " this._root_extra_style(this.root)\n",
172 " this.root.attr('style', 'display: inline-block');\n",
173 "\n",
174 " $(parent_element).append(this.root);\n",
175 "\n",
176 " this._init_header(this);\n",
177 " this._init_canvas(this);\n",
178 " this._init_toolbar(this);\n",
179 "\n",
180 " var fig = this;\n",
181 "\n",
182 " this.waiting = false;\n",
183 "\n",
184 " this.ws.onopen = function () {\n",
185 " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n",
186 " fig.send_message(\"send_image_mode\", {});\n",
187 " if (mpl.ratio != 1) {\n",
188 " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n",
189 " }\n",
190 " fig.send_message(\"refresh\", {});\n",
191 " }\n",
192 "\n",
193 " this.imageObj.onload = function() {\n",
194 " if (fig.image_mode == 'full') {\n",
195 " // Full images could contain transparency (where diff images\n",
196 " // almost always do), so we need to clear the canvas so that\n",
197 " // there is no ghosting.\n",
198 " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
199 " }\n",
200 " fig.context.drawImage(fig.imageObj, 0, 0);\n",
201 " };\n",
202 "\n",
203 " this.imageObj.onunload = function() {\n",
204 " fig.ws.close();\n",
205 " }\n",
206 "\n",
207 " this.ws.onmessage = this._make_on_message_function(this);\n",
208 "\n",
209 " this.ondownload = ondownload;\n",
210 "}\n",
211 "\n",
212 "mpl.figure.prototype._init_header = function() {\n",
213 " var titlebar = $(\n",
214 " '<div class=\"ui-dialog-titlebar ui-widget-header ui-corner-all ' +\n",
215 " 'ui-helper-clearfix\"/>');\n",
216 " var titletext = $(\n",
217 " '<div class=\"ui-dialog-title\" style=\"width: 100%; ' +\n",
218 " 'text-align: center; padding: 3px;\"/>');\n",
219 " titlebar.append(titletext)\n",
220 " this.root.append(titlebar);\n",
221 " this.header = titletext[0];\n",
222 "}\n",
223 "\n",
224 "\n",
225 "\n",
226 "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n",
227 "\n",
228 "}\n",
229 "\n",
230 "\n",
231 "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n",
232 "\n",
233 "}\n",
234 "\n",
235 "mpl.figure.prototype._init_canvas = function() {\n",
236 " var fig = this;\n",
237 "\n",
238 " var canvas_div = $('<div/>');\n",
239 "\n",
240 " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n",
241 "\n",
242 " function canvas_keyboard_event(event) {\n",
243 " return fig.key_event(event, event['data']);\n",
244 " }\n",
245 "\n",
246 " canvas_div.keydown('key_press', canvas_keyboard_event);\n",
247 " canvas_div.keyup('key_release', canvas_keyboard_event);\n",
248 " this.canvas_div = canvas_div\n",
249 " this._canvas_extra_style(canvas_div)\n",
250 " this.root.append(canvas_div);\n",
251 "\n",
252 " var canvas = $('<canvas/>');\n",
253 " canvas.addClass('mpl-canvas');\n",
254 " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n",
255 "\n",
256 " this.canvas = canvas[0];\n",
257 " this.context = canvas[0].getContext(\"2d\");\n",
258 "\n",
259 " var backingStore = this.context.backingStorePixelRatio ||\n",
260 "\tthis.context.webkitBackingStorePixelRatio ||\n",
261 "\tthis.context.mozBackingStorePixelRatio ||\n",
262 "\tthis.context.msBackingStorePixelRatio ||\n",
263 "\tthis.context.oBackingStorePixelRatio ||\n",
264 "\tthis.context.backingStorePixelRatio || 1;\n",
265 "\n",
266 " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n",
267 "\n",
268 " var rubberband = $('<canvas/>');\n",
269 " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n",
270 "\n",
271 " var pass_mouse_events = true;\n",
272 "\n",
273 " canvas_div.resizable({\n",
274 " start: function(event, ui) {\n",
275 " pass_mouse_events = false;\n",
276 " },\n",
277 " resize: function(event, ui) {\n",
278 " fig.request_resize(ui.size.width, ui.size.height);\n",
279 " },\n",
280 " stop: function(event, ui) {\n",
281 " pass_mouse_events = true;\n",
282 " fig.request_resize(ui.size.width, ui.size.height);\n",
283 " },\n",
284 " });\n",
285 "\n",
286 " function mouse_event_fn(event) {\n",
287 " if (pass_mouse_events)\n",
288 " return fig.mouse_event(event, event['data']);\n",
289 " }\n",
290 "\n",
291 " rubberband.mousedown('button_press', mouse_event_fn);\n",
292 " rubberband.mouseup('button_release', mouse_event_fn);\n",
293 " // Throttle sequential mouse events to 1 every 20ms.\n",
294 " rubberband.mousemove('motion_notify', mouse_event_fn);\n",
295 "\n",
296 " rubberband.mouseenter('figure_enter', mouse_event_fn);\n",
297 " rubberband.mouseleave('figure_leave', mouse_event_fn);\n",
298 "\n",
299 " canvas_div.on(\"wheel\", function (event) {\n",
300 " event = event.originalEvent;\n",
301 " event['data'] = 'scroll'\n",
302 " if (event.deltaY < 0) {\n",
303 " event.step = 1;\n",
304 " } else {\n",
305 " event.step = -1;\n",
306 " }\n",
307 " mouse_event_fn(event);\n",
308 " });\n",
309 "\n",
310 " canvas_div.append(canvas);\n",
311 " canvas_div.append(rubberband);\n",
312 "\n",
313 " this.rubberband = rubberband;\n",
314 " this.rubberband_canvas = rubberband[0];\n",
315 " this.rubberband_context = rubberband[0].getContext(\"2d\");\n",
316 " this.rubberband_context.strokeStyle = \"#000000\";\n",
317 "\n",
318 " this._resize_canvas = function(width, height) {\n",
319 " // Keep the size of the canvas, canvas container, and rubber band\n",
320 " // canvas in synch.\n",
321 " canvas_div.css('width', width)\n",
322 " canvas_div.css('height', height)\n",
323 "\n",
324 " canvas.attr('width', width * mpl.ratio);\n",
325 " canvas.attr('height', height * mpl.ratio);\n",
326 " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n",
327 "\n",
328 " rubberband.attr('width', width);\n",
329 " rubberband.attr('height', height);\n",
330 " }\n",
331 "\n",
332 " // Set the figure to an initial 600x600px, this will subsequently be updated\n",
333 " // upon first draw.\n",
334 " this._resize_canvas(600, 600);\n",
335 "\n",
336 " // Disable right mouse context menu.\n",
337 " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n",
338 " return false;\n",
339 " });\n",
340 "\n",
341 " function set_focus () {\n",
342 " canvas.focus();\n",
343 " canvas_div.focus();\n",
344 " }\n",
345 "\n",
346 " window.setTimeout(set_focus, 100);\n",
347 "}\n",
348 "\n",
349 "mpl.figure.prototype._init_toolbar = function() {\n",
350 " var fig = this;\n",
351 "\n",
352 " var nav_element = $('<div/>')\n",
353 " nav_element.attr('style', 'width: 100%');\n",
354 " this.root.append(nav_element);\n",
355 "\n",
356 " // Define a callback function for later on.\n",
357 " function toolbar_event(event) {\n",
358 " return fig.toolbar_button_onclick(event['data']);\n",
359 " }\n",
360 " function toolbar_mouse_event(event) {\n",
361 " return fig.toolbar_button_onmouseover(event['data']);\n",
362 " }\n",
363 "\n",
364 " for(var toolbar_ind in mpl.toolbar_items) {\n",
365 " var name = mpl.toolbar_items[toolbar_ind][0];\n",
366 " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
367 " var image = mpl.toolbar_items[toolbar_ind][2];\n",
368 " var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
369 "\n",
370 " if (!name) {\n",
371 " // put a spacer in here.\n",
372 " continue;\n",
373 " }\n",
374 " var button = $('<button/>');\n",
375 " button.addClass('ui-button ui-widget ui-state-default ui-corner-all ' +\n",
376 " 'ui-button-icon-only');\n",
377 " button.attr('role', 'button');\n",
378 " button.attr('aria-disabled', 'false');\n",
379 " button.click(method_name, toolbar_event);\n",
380 " button.mouseover(tooltip, toolbar_mouse_event);\n",
381 "\n",
382 " var icon_img = $('<span/>');\n",
383 " icon_img.addClass('ui-button-icon-primary ui-icon');\n",
384 " icon_img.addClass(image);\n",
385 " icon_img.addClass('ui-corner-all');\n",
386 "\n",
387 " var tooltip_span = $('<span/>');\n",
388 " tooltip_span.addClass('ui-button-text');\n",
389 " tooltip_span.html(tooltip);\n",
390 "\n",
391 " button.append(icon_img);\n",
392 " button.append(tooltip_span);\n",
393 "\n",
394 " nav_element.append(button);\n",
395 " }\n",
396 "\n",
397 " var fmt_picker_span = $('<span/>');\n",
398 "\n",
399 " var fmt_picker = $('<select/>');\n",
400 " fmt_picker.addClass('mpl-toolbar-option ui-widget ui-widget-content');\n",
401 " fmt_picker_span.append(fmt_picker);\n",
402 " nav_element.append(fmt_picker_span);\n",
403 " this.format_dropdown = fmt_picker[0];\n",
404 "\n",
405 " for (var ind in mpl.extensions) {\n",
406 " var fmt = mpl.extensions[ind];\n",
407 " var option = $(\n",
408 " '<option/>', {selected: fmt === mpl.default_extension}).html(fmt);\n",
409 " fmt_picker.append(option)\n",
410 " }\n",
411 "\n",
412 " // Add hover states to the ui-buttons\n",
413 " $( \".ui-button\" ).hover(\n",
414 " function() { $(this).addClass(\"ui-state-hover\");},\n",
415 " function() { $(this).removeClass(\"ui-state-hover\");}\n",
416 " );\n",
417 "\n",
418 " var status_bar = $('<span class=\"mpl-message\"/>');\n",
419 " nav_element.append(status_bar);\n",
420 " this.message = status_bar[0];\n",
421 "}\n",
422 "\n",
423 "mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n",
424 " // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n",
425 " // which will in turn request a refresh of the image.\n",
426 " this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n",
427 "}\n",
428 "\n",
429 "mpl.figure.prototype.send_message = function(type, properties) {\n",
430 " properties['type'] = type;\n",
431 " properties['figure_id'] = this.id;\n",
432 " this.ws.send(JSON.stringify(properties));\n",
433 "}\n",
434 "\n",
435 "mpl.figure.prototype.send_draw_message = function() {\n",
436 " if (!this.waiting) {\n",
437 " this.waiting = true;\n",
438 " this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n",
439 " }\n",
440 "}\n",
441 "\n",
442 "\n",
443 "mpl.figure.prototype.handle_save = function(fig, msg) {\n",
444 " var format_dropdown = fig.format_dropdown;\n",
445 " var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n",
446 " fig.ondownload(fig, format);\n",
447 "}\n",
448 "\n",
449 "\n",
450 "mpl.figure.prototype.handle_resize = function(fig, msg) {\n",
451 " var size = msg['size'];\n",
452 " if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n",
453 " fig._resize_canvas(size[0], size[1]);\n",
454 " fig.send_message(\"refresh\", {});\n",
455 " };\n",
456 "}\n",
457 "\n",
458 "mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n",
459 " var x0 = msg['x0'] / mpl.ratio;\n",
460 " var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n",
461 " var x1 = msg['x1'] / mpl.ratio;\n",
462 " var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n",
463 " x0 = Math.floor(x0) + 0.5;\n",
464 " y0 = Math.floor(y0) + 0.5;\n",
465 " x1 = Math.floor(x1) + 0.5;\n",
466 " y1 = Math.floor(y1) + 0.5;\n",
467 " var min_x = Math.min(x0, x1);\n",
468 " var min_y = Math.min(y0, y1);\n",
469 " var width = Math.abs(x1 - x0);\n",
470 " var height = Math.abs(y1 - y0);\n",
471 "\n",
472 " fig.rubberband_context.clearRect(\n",
473 " 0, 0, fig.canvas.width, fig.canvas.height);\n",
474 "\n",
475 " fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
476 "}\n",
477 "\n",
478 "mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n",
479 " // Updates the figure title.\n",
480 " fig.header.textContent = msg['label'];\n",
481 "}\n",
482 "\n",
483 "mpl.figure.prototype.handle_cursor = function(fig, msg) {\n",
484 " var cursor = msg['cursor'];\n",
485 " switch(cursor)\n",
486 " {\n",
487 " case 0:\n",
488 " cursor = 'pointer';\n",
489 " break;\n",
490 " case 1:\n",
491 " cursor = 'default';\n",
492 " break;\n",
493 " case 2:\n",
494 " cursor = 'crosshair';\n",
495 " break;\n",
496 " case 3:\n",
497 " cursor = 'move';\n",
498 " break;\n",
499 " }\n",
500 " fig.rubberband_canvas.style.cursor = cursor;\n",
501 "}\n",
502 "\n",
503 "mpl.figure.prototype.handle_message = function(fig, msg) {\n",
504 " fig.message.textContent = msg['message'];\n",
505 "}\n",
506 "\n",
507 "mpl.figure.prototype.handle_draw = function(fig, msg) {\n",
508 " // Request the server to send over a new figure.\n",
509 " fig.send_draw_message();\n",
510 "}\n",
511 "\n",
512 "mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n",
513 " fig.image_mode = msg['mode'];\n",
514 "}\n",
515 "\n",
516 "mpl.figure.prototype.updated_canvas_event = function() {\n",
517 " // Called whenever the canvas gets updated.\n",
518 " this.send_message(\"ack\", {});\n",
519 "}\n",
520 "\n",
521 "// A function to construct a web socket function for onmessage handling.\n",
522 "// Called in the figure constructor.\n",
523 "mpl.figure.prototype._make_on_message_function = function(fig) {\n",
524 " return function socket_on_message(evt) {\n",
525 " if (evt.data instanceof Blob) {\n",
526 " /* FIXME: We get \"Resource interpreted as Image but\n",
527 " * transferred with MIME type text/plain:\" errors on\n",
528 " * Chrome. But how to set the MIME type? It doesn't seem\n",
529 " * to be part of the websocket stream */\n",
530 " evt.data.type = \"image/png\";\n",
531 "\n",
532 " /* Free the memory for the previous frames */\n",
533 " if (fig.imageObj.src) {\n",
534 " (window.URL || window.webkitURL).revokeObjectURL(\n",
535 " fig.imageObj.src);\n",
536 " }\n",
537 "\n",
538 " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
539 " evt.data);\n",
540 " fig.updated_canvas_event();\n",
541 " fig.waiting = false;\n",
542 " return;\n",
543 " }\n",
544 " else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n",
545 " fig.imageObj.src = evt.data;\n",
546 " fig.updated_canvas_event();\n",
547 " fig.waiting = false;\n",
548 " return;\n",
549 " }\n",
550 "\n",
551 " var msg = JSON.parse(evt.data);\n",
552 " var msg_type = msg['type'];\n",
553 "\n",
554 " // Call the \"handle_{type}\" callback, which takes\n",
555 " // the figure and JSON message as its only arguments.\n",
556 " try {\n",
557 " var callback = fig[\"handle_\" + msg_type];\n",
558 " } catch (e) {\n",
559 " console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n",
560 " return;\n",
561 " }\n",
562 "\n",
563 " if (callback) {\n",
564 " try {\n",
565 " // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n",
566 " callback(fig, msg);\n",
567 " } catch (e) {\n",
568 " console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n",
569 " }\n",
570 " }\n",
571 " };\n",
572 "}\n",
573 "\n",
574 "// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n",
575 "mpl.findpos = function(e) {\n",
576 " //this section is from http://www.quirksmode.org/js/events_properties.html\n",
577 " var targ;\n",
578 " if (!e)\n",
579 " e = window.event;\n",
580 " if (e.target)\n",
581 " targ = e.target;\n",
582 " else if (e.srcElement)\n",
583 " targ = e.srcElement;\n",
584 " if (targ.nodeType == 3) // defeat Safari bug\n",
585 " targ = targ.parentNode;\n",
586 "\n",
587 " // jQuery normalizes the pageX and pageY\n",
588 " // pageX,Y are the mouse positions relative to the document\n",
589 " // offset() returns the position of the element relative to the document\n",
590 " var x = e.pageX - $(targ).offset().left;\n",
591 " var y = e.pageY - $(targ).offset().top;\n",
592 "\n",
593 " return {\"x\": x, \"y\": y};\n",
594 "};\n",
595 "\n",
596 "/*\n",
597 " * return a copy of an object with only non-object keys\n",
598 " * we need this to avoid circular references\n",
599 " * http://stackoverflow.com/a/24161582/3208463\n",
600 " */\n",
601 "function simpleKeys (original) {\n",
602 " return Object.keys(original).reduce(function (obj, key) {\n",
603 " if (typeof original[key] !== 'object')\n",
604 " obj[key] = original[key]\n",
605 " return obj;\n",
606 " }, {});\n",
607 "}\n",
608 "\n",
609 "mpl.figure.prototype.mouse_event = function(event, name) {\n",
610 " var canvas_pos = mpl.findpos(event)\n",
611 "\n",
612 " if (name === 'button_press')\n",
613 " {\n",
614 " this.canvas.focus();\n",
615 " this.canvas_div.focus();\n",
616 " }\n",
617 "\n",
618 " var x = canvas_pos.x * mpl.ratio;\n",
619 " var y = canvas_pos.y * mpl.ratio;\n",
620 "\n",
621 " this.send_message(name, {x: x, y: y, button: event.button,\n",
622 " step: event.step,\n",
623 " guiEvent: simpleKeys(event)});\n",
624 "\n",
625 " /* This prevents the web browser from automatically changing to\n",
626 " * the text insertion cursor when the button is pressed. We want\n",
627 " * to control all of the cursor setting manually through the\n",
628 " * 'cursor' event from matplotlib */\n",
629 " event.preventDefault();\n",
630 " return false;\n",
631 "}\n",
632 "\n",
633 "mpl.figure.prototype._key_event_extra = function(event, name) {\n",
634 " // Handle any extra behaviour associated with a key event\n",
635 "}\n",
636 "\n",
637 "mpl.figure.prototype.key_event = function(event, name) {\n",
638 "\n",
639 " // Prevent repeat events\n",
640 " if (name == 'key_press')\n",
641 " {\n",
642 " if (event.which === this._key)\n",
643 " return;\n",
644 " else\n",
645 " this._key = event.which;\n",
646 " }\n",
647 " if (name == 'key_release')\n",
648 " this._key = null;\n",
649 "\n",
650 " var value = '';\n",
651 " if (event.ctrlKey && event.which != 17)\n",
652 " value += \"ctrl+\";\n",
653 " if (event.altKey && event.which != 18)\n",
654 " value += \"alt+\";\n",
655 " if (event.shiftKey && event.which != 16)\n",
656 " value += \"shift+\";\n",
657 "\n",
658 " value += 'k';\n",
659 " value += event.which.toString();\n",
660 "\n",
661 " this._key_event_extra(event, name);\n",
662 "\n",
663 " this.send_message(name, {key: value,\n",
664 " guiEvent: simpleKeys(event)});\n",
665 " return false;\n",
666 "}\n",
667 "\n",
668 "mpl.figure.prototype.toolbar_button_onclick = function(name) {\n",
669 " if (name == 'download') {\n",
670 " this.handle_save(this, null);\n",
671 " } else {\n",
672 " this.send_message(\"toolbar_button\", {name: name});\n",
673 " }\n",
674 "};\n",
675 "\n",
676 "mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n",
677 " this.message.textContent = tooltip;\n",
678 "};\n",
679 "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",
680 "\n",
681 "mpl.extensions = [\"eps\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
682 "\n",
683 "mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n",
684 " // Create a \"websocket\"-like object which calls the given IPython comm\n",
685 " // object with the appropriate methods. Currently this is a non binary\n",
686 " // socket, so there is still some room for performance tuning.\n",
687 " var ws = {};\n",
688 "\n",
689 " ws.close = function() {\n",
690 " comm.close()\n",
691 " };\n",
692 " ws.send = function(m) {\n",
693 " //console.log('sending', m);\n",
694 " comm.send(m);\n",
695 " };\n",
696 " // Register the callback with on_msg.\n",
697 " comm.on_msg(function(msg) {\n",
698 " //console.log('receiving', msg['content']['data'], msg);\n",
699 " // Pass the mpl event to the overriden (by mpl) onmessage function.\n",
700 " ws.onmessage(msg['content']['data'])\n",
701 " });\n",
702 " return ws;\n",
703 "}\n",
704 "\n",
705 "mpl.mpl_figure_comm = function(comm, msg) {\n",
706 " // This is the function which gets called when the mpl process\n",
707 " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
708 "\n",
709 " var id = msg.content.data.id;\n",
710 " // Get hold of the div created by the display call when the Comm\n",
711 " // socket was opened in Python.\n",
712 " var element = $(\"#\" + id);\n",
713 " var ws_proxy = comm_websocket_adapter(comm)\n",
714 "\n",
715 " function ondownload(figure, format) {\n",
716 " window.open(figure.imageObj.src);\n",
717 " }\n",
718 "\n",
719 " var fig = new mpl.figure(id, ws_proxy,\n",
720 " ondownload,\n",
721 " element.get(0));\n",
722 "\n",
723 " // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n",
724 " // web socket which is closed, not our websocket->open comm proxy.\n",
725 " ws_proxy.onopen();\n",
726 "\n",
727 " fig.parent_element = element.get(0);\n",
728 " fig.cell_info = mpl.find_output_cell(\"<div id='\" + id + \"'></div>\");\n",
729 " if (!fig.cell_info) {\n",
730 " console.error(\"Failed to find cell for figure\", id, fig);\n",
731 " return;\n",
732 " }\n",
733 "\n",
734 " var output_index = fig.cell_info[2]\n",
735 " var cell = fig.cell_info[0];\n",
736 "\n",
737 "};\n",
738 "\n",
739 "mpl.figure.prototype.handle_close = function(fig, msg) {\n",
740 " var width = fig.canvas.width/mpl.ratio\n",
741 " fig.root.unbind('remove')\n",
742 "\n",
743 " // Update the output cell to use the data from the current canvas.\n",
744 " fig.push_to_output();\n",
745 " var dataURL = fig.canvas.toDataURL();\n",
746 " // Re-enable the keyboard manager in IPython - without this line, in FF,\n",
747 " // the notebook keyboard shortcuts fail.\n",
748 " IPython.keyboard_manager.enable()\n",
749 " $(fig.parent_element).html('<img src=\"' + dataURL + '\" width=\"' + width + '\">');\n",
750 " fig.close_ws(fig, msg);\n",
751 "}\n",
752 "\n",
753 "mpl.figure.prototype.close_ws = function(fig, msg){\n",
754 " fig.send_message('closing', msg);\n",
755 " // fig.ws.close()\n",
756 "}\n",
757 "\n",
758 "mpl.figure.prototype.push_to_output = function(remove_interactive) {\n",
759 " // Turn the data on the canvas into data in the output cell.\n",
760 " var width = this.canvas.width/mpl.ratio\n",
761 " var dataURL = this.canvas.toDataURL();\n",
762 " this.cell_info[1]['text/html'] = '<img src=\"' + dataURL + '\" width=\"' + width + '\">';\n",
763 "}\n",
764 "\n",
765 "mpl.figure.prototype.updated_canvas_event = function() {\n",
766 " // Tell IPython that the notebook contents must change.\n",
767 " IPython.notebook.set_dirty(true);\n",
768 " this.send_message(\"ack\", {});\n",
769 " var fig = this;\n",
770 " // Wait a second, then push the new image to the DOM so\n",
771 " // that it is saved nicely (might be nice to debounce this).\n",
772 " setTimeout(function () { fig.push_to_output() }, 1000);\n",
773 "}\n",
774 "\n",
775 "mpl.figure.prototype._init_toolbar = function() {\n",
776 " var fig = this;\n",
777 "\n",
778 " var nav_element = $('<div/>')\n",
779 " nav_element.attr('style', 'width: 100%');\n",
780 " this.root.append(nav_element);\n",
781 "\n",
782 " // Define a callback function for later on.\n",
783 " function toolbar_event(event) {\n",
784 " return fig.toolbar_button_onclick(event['data']);\n",
785 " }\n",
786 " function toolbar_mouse_event(event) {\n",
787 " return fig.toolbar_button_onmouseover(event['data']);\n",
788 " }\n",
789 "\n",
790 " for(var toolbar_ind in mpl.toolbar_items){\n",
791 " var name = mpl.toolbar_items[toolbar_ind][0];\n",
792 " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
793 " var image = mpl.toolbar_items[toolbar_ind][2];\n",
794 " var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
795 "\n",
796 " if (!name) { continue; };\n",
797 "\n",
798 " var button = $('<button class=\"btn btn-default\" href=\"#\" title=\"' + name + '\"><i class=\"fa ' + image + ' fa-lg\"></i></button>');\n",
799 " button.click(method_name, toolbar_event);\n",
800 " button.mouseover(tooltip, toolbar_mouse_event);\n",
801 " nav_element.append(button);\n",
802 " }\n",
803 "\n",
804 " // Add the status bar.\n",
805 " var status_bar = $('<span class=\"mpl-message\" style=\"text-align:right; float: right;\"/>');\n",
806 " nav_element.append(status_bar);\n",
807 " this.message = status_bar[0];\n",
808 "\n",
809 " // Add the close button to the window.\n",
810 " var buttongrp = $('<div class=\"btn-group inline pull-right\"></div>');\n",
811 " 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",
812 " button.click(function (evt) { fig.handle_close(fig, {}); } );\n",
813 " button.mouseover('Stop Interaction', toolbar_mouse_event);\n",
814 " buttongrp.append(button);\n",
815 " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n",
816 " titlebar.prepend(buttongrp);\n",
817 "}\n",
818 "\n",
819 "mpl.figure.prototype._root_extra_style = function(el){\n",
820 " var fig = this\n",
821 " el.on(\"remove\", function(){\n",
822 "\tfig.close_ws(fig, {});\n",
823 " });\n",
824 "}\n",
825 "\n",
826 "mpl.figure.prototype._canvas_extra_style = function(el){\n",
827 " // this is important to make the div 'focusable\n",
828 " el.attr('tabindex', 0)\n",
829 " // reach out to IPython and tell the keyboard manager to turn it's self\n",
830 " // off when our div gets focus\n",
831 "\n",
832 " // location in version 3\n",
833 " if (IPython.notebook.keyboard_manager) {\n",
834 " IPython.notebook.keyboard_manager.register_events(el);\n",
835 " }\n",
836 " else {\n",
837 " // location in version 2\n",
838 " IPython.keyboard_manager.register_events(el);\n",
839 " }\n",
840 "\n",
841 "}\n",
842 "\n",
843 "mpl.figure.prototype._key_event_extra = function(event, name) {\n",
844 " var manager = IPython.notebook.keyboard_manager;\n",
845 " if (!manager)\n",
846 " manager = IPython.keyboard_manager;\n",
847 "\n",
848 " // Check for shift+enter\n",
849 " if (event.shiftKey && event.which == 13) {\n",
850 " this.canvas_div.blur();\n",
851 " event.shiftKey = false;\n",
852 " // Send a \"J\" for go to next cell\n",
853 " event.which = 74;\n",
854 " event.keyCode = 74;\n",
855 " manager.command_mode();\n",
856 " manager.handle_keydown(event);\n",
857 " }\n",
858 "}\n",
859 "\n",
860 "mpl.figure.prototype.handle_save = function(fig, msg) {\n",
861 " fig.ondownload(fig, null);\n",
862 "}\n",
863 "\n",
864 "\n",
865 "mpl.find_output_cell = function(html_output) {\n",
866 " // Return the cell and output element which can be found *uniquely* in the notebook.\n",
867 " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n",
868 " // IPython event is triggered only after the cells have been serialised, which for\n",
869 " // our purposes (turning an active figure into a static one), is too late.\n",
870 " var cells = IPython.notebook.get_cells();\n",
871 " var ncells = cells.length;\n",
872 " for (var i=0; i<ncells; i++) {\n",
873 " var cell = cells[i];\n",
874 " if (cell.cell_type === 'code'){\n",
875 " for (var j=0; j<cell.output_area.outputs.length; j++) {\n",
876 " var data = cell.output_area.outputs[j];\n",
877 " if (data.data) {\n",
878 " // IPython >= 3 moved mimebundle to data attribute of output\n",
879 " data = data.data;\n",
880 " }\n",
881 " if (data['text/html'] == html_output) {\n",
882 " return [cell, data, j];\n",
883 " }\n",
884 " }\n",
885 " }\n",
886 " }\n",
887 "}\n",
888 "\n",
889 "// Register the function which deals with the matplotlib target/channel.\n",
890 "// The kernel may be null if the page has been refreshed.\n",
891 "if (IPython.notebook.kernel != null) {\n",
892 " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n",
893 "}\n"
894 ],
895 "text/plain": [
896 "<IPython.core.display.Javascript object>"
897 ]
898 },
899 "metadata": {},
900 "output_type": "display_data"
901 },
902 {
903 "data": {
904 "text/html": [
905 "<img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABMoAAAK4CAYAAACFyRHJAAAgAElEQVR4nOzdZ3Sd1Z33/euZWQ953jyz8uJZ973WZN33BhJawpCEJISQMkkmvTCZEEhj0tsA6Tez3Y3B2DTTbGyMDRjTbIobW8W9y5KL3GXZcpEs2bJc5aJ+zvk9L46OMOCicp2zz3Wd72eta61Yls7+2ShanB97738QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBW/F9BEHwgCIJ/4uHh4eHh4eHh4eHh4eGJ6POBIP3+FgAG5ANBEIiHh4eHh4eHh4eHh4eHJ+LPBwIAGKB/CoJA9fX1OnnyJA8PDw8PDw8PDw8PDw9PpJ76+vpMUfZPnt9fA4iBfwqCQCdPnhQAAAAAAFFz8uRJijIAoaEoAwAAAABEFkUZgDBRlAEAAAAAIouiDECYKMoAAAAAIOKSyaTa2tpi+ySTyfP+2SnKAISJogwAAAAAIqyjo0PV1dWqqqqK7VNdXa2Ojo5z/vkpygCEiaIMAAAAACIqlUqptrZWNTU1amlp8b7zKxtPS0uLampqVFtbq1Qq9Z6/A4oyAGGiKAMAAACAiOrs7FRVVZWam5t9R8mq5uZmVVVVqbOz8z2/R1EGIEwUZQAAAAAQUW1tbaqqqlJra6vvKFnV2tqqqqoqtbW1vef3KMoAhImiDAAAAAAiKlOUnatAipML/TkpygCEiaIMAAAAACKKooyiDEC4KMoAAAAAIKIoyijKAISLogwAAAAAIirqRdmECRNkjNH73vc+3XDDDaqoqDjn51GUAcgVijIAAAAAiKgoF2UzZszQJZdcoueee07bt2/Xb3/7W73//e9XU1PTez6XogxArlCUAQAAAEBERbkou+GGG3TnnXf2/DqZTOqf//mfNXbs2Pd8LkUZgFyhKAMAAACAiHp3gZRKpdTS0eXlSaVSvc7d0dGhf/zHf9Ts2bPf8fGf/exnuvnmmy/65zwbRRmAMFGUAQAAAEBEvbtAaunokrHOy9PS0dXr3AcOHFAQBCorK3vHx++++27dcMMNF/1zno2iDECYKMoAAAAAIKIoyijKAISLogwAAAAAIoqjlxRlAMJFUQYAAAAAERX1y/zvuuuunl8nk0l94AMf4DJ/AF5RlAEAAABAREW5KJsxY4be9773adq0aaqqqtLvfvc7vf/979ehQ4fe87kUZQByhaIMAAAAQEE6fqajT/dq5aMoF2WSNH78eP3v//2/dckll+iGG25QeXn5OT+PogxArlCUAQAAACg4K3cd0RVDi/WhIUW6ZeJqjZtfrdW7j6itM+E7Wp9EvSjrLYoyALlCUQYAAACgoOxoPKlrR5Sec3LjVcOKNWdjg++IvUZRRlEGIFwUZQAAAAAKxqGTbfrMmEUy1unWp8u0+/BpzVhbpz+9WqlPjV4oY50+MqJUTSejUTxRlFGUAQgXRRkAAACAgnCmvUvfemKFjHX60iNLdaKl4x2/n0ymdPOEVTLW6Y+vVHpK2TcUZRRlAMJFUQYAAAAg9roSSf3iuQoZ63T9vQtUd7TlnJ+3pb5Zlw1KH8NcXXMkxyn7jqKMogxAuCjKAAAAAMTeiDlbe+4g27j/xAU/d3j35375kaXq6ErmKGH/UJRRlAEIF0UZAAAAgFjbe+SMjHW6dJBTydbGi35+c2unPnHfAhnr9NTSmhwk7L9MgdTa2uo7Sla1trZSlAHICYoyAAAAALE2prhKxjr9/LmKXn/NG+vrZazT1cNK1HAif0uozs5OVVVVqbm52XeUrGpublZVVZU6Ozvf83sUZQDCRFEGAAAAILY6upI9u8NKt118N1lGKpXSrZPKZKzT76avy2LCgUmlUqqtrVVNTY1aWlrU1tYWu6elpUU1NTWqra1VKpV6z98BRRmAMFGUAQAAAIitoi0HZazTJ0cvVGeib/eNVTee0uWDi2Ss06o8vti/o6ND1dXVqqqqiu1TXV2tjo6Oc/75KcoAhImiDAAAAEBs3T61XMY6PVS6o19fP3jWFhnr9NcZG0NOFq5kMul951c2n2Ty/CUnRRmAMFGUAQAAAIil/cdadOkgJ2Od6o629Os11u47JmOdrh1RqrbORMgJEQaKMgBhoigDAAAAEEsPl1bLWKfbp5b3+zWSyZRuuH+hjHVasP1QiOkQFooyAGGiKAMAAAAQO12JpD41Ol1wuc0HB/Ra98zbJmOd/vxqZUjpECaKMgBhoigDAAAAEDvztzXKWKfr712gjq6+XeL/butr08cvPzy8hOOXeYiiDECYKMoAAAAAxM4vn18rY53GFFUN+LWSyZRuHLNIxjqVbmsMIR3CRFEGIEwUZQAAAABi5cCJVl3WfYn/nsOnQ3nNe9/aLmOd/vgKxy/zDUUZgDBRlAEAAACIlccW7pSxTj+cXBbaa26oO87xyzxFUQYgTBRlAAAAAGLl38Ytk7FOsysbQnvNVCqlm8YulrFOJVs5fplPKMoAhImiDAAAAEBsNDa3yVinywY5Nbd0hvrao136+OVdHL/MKxRlAMJEUQYAAAAgNt7cUC9jnb47fmXor71x/wkZ63TN8BK1dnD8Ml9QlAEIE0UZAAAAgNj428xNMtZpbPGO0F/77OOXxVsOhv766B+KMgBhoigDAAAAEAupVEo3jlkkY51W7DqclTXGFFXJWKc7Xt6QlddH31GUAQgTRRkAAACAWNhz+LSMdbpiSHHWjkZurk8fv7x6WIlaOrqysgb6hqIMQJgoygAAAADEwvQ1tTLW6UeT12RtjbOPXy7fmZ1da+gbijIAYaIoAwAAABALv5++XsY6jV+8K6vr/HXGRhnr9Mj86qyug96hKAMQJooyAAAAAJGXSKZ03T3zZazThrrjWV3rlYo6Get029NlWV0HvUNRBiBMFGUAAAAAIm9LfbOMdbp2RKm6EsmsrlXTlL4L7cqhxWrvys5daOg9ijIAYaIoAwAAABB5k5btlrFOv562NutrpVIpXX/vAhnrtL72WNbXw4VRlAEIE0UZAAAAgMi7fWq5jHV6duXenKz3u+nrZKzTxKW7c7Iezo+iDECYKMoAAAAARFp7V0JXDSuWsU7VjadysuaUFXtkrNMvn8/+DjZcGEUZgDBRlAEAAACItDV7jspYp0/ct1CpVCona26uPyFjnf5lZKmSydysiXOjKAMQJooyAAAAAJH2yPxqGev0x1cqc7ZmVyKpDw8vkbFOVQd5P+UTRRmAMFGUAQAAAIi0/3hqlYx1mrG2LqfrZu5Fe6FsX07XxTtRlAEIE0UZAAAAgMg61dapywcXyVin/cdacrr2E4t2yVinO1/ekNN18U4UZQDCRFEGAAAAILIWVR2SsU5feGhJztcu252+G+2G+3N3Nxrei6IMQJgoygAAAABE1mi3XcY6DXpzc87XbutM6END0rvZ6o7mdjcb3kZRBiBMFGUAAAAAIuvWp8tkrNNr6/Z7WT9zP9rr6+u9rA+KMgDhoigDAAAAEEnJZKpn8mR14ykvGcYUV8lYp/9+Pfc72pBGUQYgTBRlAAAAACKppum0jHW6alixuhJJLxkyd6R96eGlXtYHRRmAcFGUAQAAAIik2ZUNMtbpP55a5S1Dc0unjHUy1unwqXZvOQoZRRmAMFGUAQAAAIikUfPSF/mPnLvNa46vPbpcxjoVbznoNUehoigD4u3OIAhqgyBoD4KgIgiCGy7y+e8PguCpIAgagyDoCIJgVxAE3+rDehRlAAAAACLp1klleXGR/tDZW2Ss0z3z/BZ2hYqiDIivHwbpsuuXQRB8OAiCZ4IgOBEEwf84z+dfEgTBuiAIioIg+GwQBJcGQfCvQRB8tA9rUpQBAAAAiJzEWRf57zzk5yL/jDkb00dAv/3kCq85ChVFGRBfFUEQTDjr1/8QBMGBIAgGnefz/xAEwZ4gCP7vAaxJUQYAAAAgcmqaTslYp6uHlSiRTHnNcuBEq4x1unxwkdo6E16zFCKKMiCeLgmCIBEEwffe9fEXgiCYe56vKQ6C4KUgvfOsKQiCbUEQDAmC4B/7sC5FGQAAAIDImVVZL2Odbpm42ncUpVIpffzeBTLWadP+E77jFByKMiCe/jlI/x/7M+/6+ENBeqfZuVQH6bvMng2C4BNB+ujmsSAIRl5gnfcF6R8emecDAUUZAAAAgIi5Z962vLjIP+OnU8plrNMrFXW+oxQcijIgnvpTlO0KgmB/8M4dZH8L0hf7n8893eu846EoAwAAABAlP5i0WsY6vbnB70X+GWOKqmSs09DZW3xHKTgUZUA89efo5fIgCBa962PfDNI/IC45z9ewowwAAABApCWSKV3TfZH/Ls8X+WdkLvT/j6dW+Y5ScCjKgPiqCIJg/Fm//ocgCBqC81/mPyYIgtruz8v4cxAEB/uwJneUAQAAAIiUXYfSF/lfM9z/Rf4Z+TRcoNBQlAHx9cMgfefYz4MguCYIgslBEJwIguB/dv/+9CAIxp71+f8rCIJTQbpcuzIIgm8H6Uv9h/ZhTYoyAAAAAJHy5ob0Rf4/mOT/Iv+MRDKlq4eld7nVNJ32HaegUJQB8XZXEAR1QRB0BOkdZp8+6/eWBUEw7V2f/5kgCMqDdMG2J2DqJQAAAICYGzk3fZH/PfPy4yL/jO89tUrGOs3ddMB3lIJCUQYgTBRlAAAAACLllonpi/xnVebHRf4ZQ2ZtkbFOY4qrfEcpKBRlAMJEUQYAAAAgMt55xDE/LvLPeLm8TsY63T613HeUgkJRBiBMFGUAAAAAImNn90X+H86ji/wzNu0/IWOdrr93gVKp/MoWZxRlAMJEUQYAAAAgMt5Yn77I/9ZJZb6jvEdbZ0KXDy6SsU6NzW2+4xQMijIAYaIoAwAAABAZmYv8R83b7jvKOX310WUy1mnxjkO+oxQMijIAYaIoAwAAABAZ3+++yH92ZYPvKOf051crZazTk4t2+Y5SMCjKAISJogwAAADerdt3TBOW1KjhRKvvKMhjXYnkWRf5n/Yd55yeWb5Hxjr9fvp631EKBkUZgDBRlAEAAMCr4i0H9aEh6XudPji4SH9+tVLbD/Dvp3iv6sa3L/JP5tlF/hmra47IWKfPP7jEd5SCQVEGIEwUZQAAAPDmjfX1umyQk7FOn31gsYx1Pc/tU8u1vva474jII7Mq8/ci/4wTLR0938Mn2zp9xykIFGUAwkRRBgAAAC+ml+3rKRTufn2TEsmUtjY0665XKnsmB14xpFh7j5zxHRV5YmzxDhnrNGz2Vt9RLuimsenSt3zPUd9RCgJFGYAwUZQBAAAg555aWtNTkt0zb9t7jtHtP9aiWyeVyVin/3qJu56Q9qvn18pYp+ll+3xHuaDfvLBOxjo9u3Kv7ygFgaIMQJgoygAAAJBTr1TU9ZRk4+ZXK5U6911T1Y2neo5lcgQTkvT5B5fIWKey3fm9U+vRBTtlrNPfZm7yHaUgUJQBCBNFGQAAAHImkUz13EU2bsHOi37+3a9vkrFOt0xcfd5CDYWhtSOhS7uL06On233HuaD52xplrNM3Hl/hO0pBoCgDECaKMgAAAORMpkD46Kj5autMXPTzG5vbdNWwYhnrVLqtMQcJka+21DfLWKfr713gO8pFNZxo7Zni2t518e9zDAxFGYAwUZQBAAAgZ34yZY2MdRpbvKPXX/NwabWMdfrSw0vVmUhmMR3y2Rvr0xMvfzg5fydeZqRSKV13z3wZ67S1odl3nNijKAMQJooyAAAA5MTOQ6dkrNNlg5zqj7f0+utOtXXq+nsXpC9xX1ObxYTIZ2OKq2Ss0/A5+T3xMuPHz6RL4Zlr9/uOEnsUZQDCRFEGAACAnBgya4uMdfr99L5PsXyhbJ+MdfrEfQt0ur0rC+mQ736ZmXgZkbL0vre2y1inEREp9qKMogxAmCjKAAAAkHXNLZ26elhJvycWdiaS+uLDS3smZaLwZIZAlO/J74mXGbMq00dFb52U/0dFo46iDECYKMoAAACQdc8s3yNjnb7+2PJ+T68s2nJQxjp9bNR8dXFXWUE5094lY9MTL4+d6fAdp1e2NqSHD3w8AsMHoo6iDECYKMoAAACQVYlkSp97ML0b6NWKun6/TlciqY+NSl+Qvnr3kRATIt9trj/Rc/Q2Klo7Erp0ULrcO3q63XecWKMoAxAmijIAAABk1YLth2Ss03X3zFdrR2JAr3X365u496kAvd498fJHk9f4jtInmYI4KsdFo4qiDECYKMoAAACQVT+Zkp7+N6a4asCvtXhHunT79P2LlEz27wgnomdMUVUkC9JfPFchY51ejMgAgqiiKAMQJooyAAAAZE1N0ykZ63TZIKf64y0Dfr22zoQ+MqJUxjptqDseQkJEQVQLp/u7C76Rc7f5jhJrFGUAwkRRBgAAgKwZv3iXjHX65fNrQ3vNu16pTO9QKxr4DjVEw01j00cYK/Ye8x2lT2au2y9jnX46pdx3lFijKAMQJooyAAAAZM2tT5eFvhMoM/3yCw8t6fcETUTH2RMvj0dk4mXGhrrjMtbphvsX+o4SaxRlAMJEUQYAAICsON3epQ8OLpKxTrVHz4T2umfau3Tl0GIZ67T9AP8eG3cb92cmXkavbDrZ1tlT8p1s6/QdJ7YoygCEiaIMAAAAWbGwe9rl5x9cEvpr/+aFdTLWadyCnaG/NvJL5vjij5+J1sTLjE/fv4g79bKMogxAmCjKAAAAkBUj526TsU5DZm0J/bXf3FAvY52+9ujy0F8b+SXqF+L/dEq5jHWauXa/7yixRVEGIEwUZQAAAMiKLz2yVMY6lWxtDP21m1s6e4517jl8OvTXR/74effEy5fKozXxMiNTGN/P8ImsoSgDECaKMgAAAISu/niLjHW6fHCRmluzczfT7VPTO3WeWlqTlddHfshMvFy7L1oTLzNeKq+VsU6/eK7Cd5TYoigDECaKMgAAAITu1Yo6Gev0/Ymrs7bGy+XpNW4evzJra8Cv02dNvDzREq2Jlxnle47KWKfPPrDYd5TYoigDECaKMgAAAITujpc2yFinxxZm77L9w6fademgdInScKI1a+vAn8q64zLW6ZOjozfxMuPYmQ4Z63TpIKeWji7fcWKJogxAmCjKAAAAEKpEMqXr7pkvY53W12b3uNytk8pkrNOzK/dmdR34MXNteuLlT6ZEc+JlxvX3LpCxTlsbmn1HiSWKMgBhoigDAABAqDbtPyFjna4dUaquRDKra01ZsUfGOv3y+bVZXQd+3PfW9khPvMy49el0oTurst53lFiiKAMQJooyAAAAhGr84l0y1ul309dlfa0t9c0y1ulfRpYqmUxlfT3k1n8+m554+XJ5ne8oAzJk1hYZ6/RQ6Q7fUWKJogxAmCjKAAAAEKrM7pkX19Rmfa2uRFLXDC+RsU7Vjaeyvh5y68Yxi2Ss07qITrzMeH7VXhnr9NsXsl8eFyKKMgBhoigDAABAaE63d+mDg4tkrFPd0ZacrPnTKeU5K+aQO6faOnsmXja3dPqOMyArdx2RsU5fenip7yixRFEGIEwUZQAAAAjNwu2HZKzTFx5akrM1H1u4U8Y6/fnVypytiezbXJ++6+4T90V34mXGoZNtMtbp8sFFau9K+I4TOxRlAMJEUQYAAIDQjJizVcY6DZ29JWdrrqpJ79a5aezinK2J7JuzsUHGOt36dJnvKAOWSqV07YhSjghnCUUZgDBRlAEAACA0X3p4qYx1Kt3WmLM1z7R36fLu454HTrTmbF1k16ML0jsF//v1zb6jhOJ7T62SsU5vbT7gO0rsUJQBCBNFGQAAAEJxsLm153jZybbc3in13fErZazT3E2UEHHxx1cqZazTpGW7fUcJxd2vb5KxTo8t3Ok7SuxQlAEIE0UZAAAAQlGytVHGOn3j8RU5X3vUvO0y1mn4nK05XxvZ8Z0nV+Z8d2I2TV6+W8Y63fHyBt9RYoeiDECYKMoAAAAQigdLdshYJ/tG7o/KFW056K2kQ/jOvtNr16F43Om1ZEeTjHX62qPLfUeJHYoyAGGiKAMAAEAobp9aLmOdXiqvzfnaTd1TBS8d5HJ+7BPhO3yqveefZ1ymRO4/1iJjna4YUqyuRNJ3nFihKAMQJooyAAAADFgqldJ198yXsU5bG5q9ZPjCQ0tkrNPS6iYv6yM8FXuPyVinzz0Yn0mmyWRKVw8rkbFOew6f9h0nVijKAISJogwAAAADVnv0TM9umY4uP7tl/jYzfVn6w6XVXtZHeGasrZOxTv/5bIXvKKH69pMrYnXvWr6gKAMQJooyAAAADNjcTQdkrNPNE1Z5y/BqRbpcue3pMm8ZEI4xxVUy1mlEzIYz/GXGRhnrNGFJje8osUJRBiBMFGUAAAAYsNEuPXVy2Gx/xUZN02kZ63TlUH+72hCO376wTsY6Pb9qr+8ooXpy0S4Z6/T31zb5jhIrFGUAwkRRBgAAgAG77ekyGev02rr93jKkUil9bFT6nrQNdce95cDAffXRZTLWadnOw76jhGpe987L709c7TtKrFCUAQgTRRkAAAAGJJFM6cPD05eUVzee8prlN907kSYv3+01B/ovkUzpiqHFMtZp/7EW33FCtbWhWcY6XX/vAt9RYoWiDECYKMoAAAAwIDVNp2Ss09XDSpRIprxmmbx8t4x1+s0L67zmQP/tP9bSMxjC9/dT2M60d8lYJ2Odmls6fceJDYoyAGGiKAMAAMCAvLG+XsY6/WCS/+NkG+qOy1inj42ar1QqXiVLoVi+87CMdfrKuGW+o2TFp0YvlLFOG/ef8B0lNijKAISJogwAAAADMnLuNhnrdO9b231HUUdXUld2H9uraTrtOw76YdrqfbHeFZi5z292ZYPvKLFBUQYgTBRlAAAAGJDvPbVKxjrN2Zgfb/wzRcSMtXW+o6AfMsXrmKIq31GyYtCbm2Ws07gFO31HiQ2KMgBhoigDAABAv3Um3t7BtedwfuzgGu22y1in4XO2+o6CfvjPZytkrNOrFfEsOp9elr5H765XKn1HiQ2KMgBhoigDAABAv207kJ7id+3IUiXz5OL12ZUNMtbp+xP935mGvvv8g0tkrFP5nqO+o2TF/G2NMtbpO0+u9B0lNijKAISJogwAAAD99mpFnYx1+vEza3xH6bHzUHoK5zXDS/KmvEPvtHcldNmg9FTIplNtvuNkRWZK7EdGlDJwIiQUZQDCRFEGAACAfhv05hYZ6zS2eIfvKD268vA4KHqnEEqkQigDc42iDECYKMoAAADQb99+coWMdSractB3lHe4eUJ6wMC8TQd8R0EfFMqxxM89uFjGOlXsPeY7SixQlAEIE0UZAAAA+qWtM6EPDSmSsU71x1t8x3mHwbPSO90eKMmfnW64uEK56D4zsIDJrOGgKAMQJooyAAAA9MvG/SdkrNPH712Qd8fkXlxTK2Od/vPZCt9R0Af2jc0y1mncgp2+o2TViDlb8+7IcpRRlAEIE0UZAAAA+mV62T4Z6/Tz5/KvjKqsOy5jnT5xX/6VeDi/254uk7FOsysbfEfJqudX7ZWxTr+bvs53lFigKAMQJooyAAAA9MvfX9uU3v0zv9p3lPdo7Xj7wvRDJ7kwPSo+NXqhjHXatP+E7yhZtbS6ScY6ffXRZb6jxAJFGYAwUZQBAACgX7726HIZ67Rw+yHfUc7pK+OWyVinJTuafEdBL5xu75Kx6XKzubXTd5ysqjvaImOdrhharGSSHY8DRVEGIEwUZQAAAOizjq6kPjg4fZH/gROtvuOc059erZSxTuMX7/IdBb2wtaG557hs3CWSqbwdhBFFFGUAwkRRBgAAgD6rbjwlY52uHVGat3eATV6enqD4hxfX+46CXpi76YCMdbpl4mrfUXLiy48slbFOK3Yd9h0l8ijKAISJogwAAAB9Nq+71PiPp1b5jnJeq2qOyFinLzy0xHcU9MLjC3fJWKf/89om31Fy4tfT1slYp+ll+3xHiTyKMgBhoigDAABAn42bXy1jnewbm31HOa/jZzp67rw62RbvO6/i4C8zNspYp6eW1viOkhP3F1XJWKd75m3zHSXyKMoAhImiDAAAAH32++nrZazT1JV7fUe5oM+MWSRjncr3HPUdBRdx84RVMtapZOtB31Fy4uXyOhnr9PPnKnxHiTyKMgBhoigDAABAn30pIvcrZY63Pbcqvws9SNfdM1/GOu1oLIz3JmW7j8pYp3/laPCAUZQBCBNFGQAAAPqkvSuhy7snXh462eY7zgU9umCnjHX6e4HcexVVzS2dPcdkWzq6fL0RLPwAACAASURBVMfJiUMn22Ss0+WDi9TRlfQdJ9IoygCEiaIMAAAAfVJ18KSMdfqXkfk78TKjdFujjHX6xuMrfEfBBWyuPyFjnT45eqHvKDmTSqV0zfASGeu0+/Bp33EijaIMQJgoygAAANAnczY2yFinWyau9h3louqPt8hYpw8OLlJ7V8J3HJxHZopqFL6nwvTNx1fIWKdFVYd8R4k0ijIAYaIoAwAAQJ88XJqeeDnozS2+o1xUKpXquftqa0Oz7zg4jwlLamSs019nbvQdJafueHmDjHWasmKP7yiRRlEGIEwUZQAAAOiT374QrQvyf/zMGhnrNHPtft9RcB53v75Jxjo9vnCX7yg5lSmdB8/K/9I5n1GUAQgTRRkAAAD65F8fWiJjnVbVHPEdpVfue2u7jHUaMWer7yg4j9ueLpOxTrMrG3xHyak31tfLWKcfP7PGd5RIoygDECaKMgAAAPRaW2dClw5KTydsOpXfEy8zZlWmy4gfTCqs+6+i5MYxi2Ss04a6476j5NT62uMy1unGMYt8R4k0ijIAYaIoAwAAQK9tbWiWsU4fHTU/7ydeZuw8dErGOn14eImSyWhkLiRnl69HT7f7jpNTx890yNj0n721g2ET/UVRBiBMFGUAAADotczurFsnlfmO0mtdiaSuHFosY532HTnjOw7epabp7SIzKuVrmD46Kj1souog78n6i6IMQJgoygAAANBrD5TskLFOQyJ2+fi3nlghY53mb2v0HQXvsnjHIRnr9I3HV/iO4sW/T1glY52Ktxz0HSWyKMoAhImiDAAAAL3262lrZazTtNX7fEfpk7/M2ChjnSYsqfEdBe/y3Kq9Mtbp99PX+47ixZ9erZSxTpOW7fYdJbIoygCEiaIMAAAAvfb5B9MTL1fvjsbEy4wJS2pkrNOfX630HQXvMnLuNhnrNKaoyncUL8bNr5axToPejNYuzXxCUQYgTBRlAAAA6JXWjrcvXT8SsUvX529rlLFO33qiMI/35bNfPp/epfhSea3vKF68vj59799PpqzxHSWyKMoAhImiDAAAAL2ypT498fLj9y7wHaXP9h05I2OdrhxarASTL/PKlx9ZKmOdVu6K1i7FsKzdd0zGOn32gcW+o0QWRRmAMFGUAQAAoFfe6N75ctvT0Zl4mZFIpnomX9YeZfJlvkgmU7qi+5/L/mMtvuN40XSyTcY6XTbIqaMr6TtOJFGUAQgTRRkAAAB6ZUxxlYx1GjZ7q+8o/fLNx9OTLxduP+Q7CrodONEqY50+OLhIXYnCLIlSqZSuHlYiY532HqHE7Q+KMgBhoigDAABAr2Tukppets93lH7JTBd8aimTL/NF2e6jMtbpXx9a4juKV197dLmMdVpa3eQ7SiRRlAEIE0UZAAAAeuWzDyyWsU5r9hz1HaVfMpMv/zpjo+8o6DZjbZ2MdfrPZyt8R/HqNy+sk7FO01bv8x0lkijKAISJogwAAAAXdaa9S8amJ14eO9PhO06/lHZPvvzOkyt9R0G3B0t2RPo4b1jue2u7jHUaNW+77yiRRFEGIEwUZQAAALioTftPyFinT9wXvYmXGXsOn5axTlcPK1GSyZd54Y6XN8hYpykr9viO4tX0NbUy1unX09b6jhJJFGUAwkRRBgAAgIt6bd1+Gev0o8lrfEfpt65EsuAnLOab745fKWOd5m9r9B3Fq+U7D8tYp6+MW+Y7SiRRlAEIE0UZAAAALur+ovTEyxFzon1E7uuPpS9NX1TF5Mt8cN0982WsU3XjKd9RvKo9ekbGOl05tJjdjv1AUQYgTBRlAAAAuKjMxMsX19T6jjIgf3wlPfly0rLdvqMUvOaWzp5771o7Er7jeNWZSOrywUUy1qmxuc13nMihKAMQJooyAAAAXNQXH14qY51W1xzxHWVAnly0S8Y6/W3mJt9RCt7m+vS9d58cvdB3lLzw+QeXyFin8ohOlfWJogxAmCjKAAAAcEGdiaQ+2L3b5WBzq+84A1Ky9aCMdfrueCZf+jZv0wEZ63TLxNW+o+SF26eWy1inmev2+44SORRlAMJEUQYAAIAL2nskfX/SVcOif3/S7u7Jl9cMZ/KlbxOW1MhYp7/O3Og7Sl4YMmuLjHV6uLTad5TIoSgDECaKMgAAAFzQ4h2HZKzT1x9b7jvKgHUlkrpiSHryZf1xJl/6dPfrm2Ss0+MLd/mOkhcmL98tY53ueqXSd5TIoSgDECaKMgAAAFzQ1JV7ZazTH15c7ztKKDKTL5fsaPIdpaDd9nSZjHWaXdngO0peKNnaKGOdbuZYcJ9RlAEIE0UZAAAALmjo7PSRsAdLdviOEoo7X94gY50mL2fypU83jlkkY5021B33HSUvVB08KWOdPjpqvu8okUNRBiBMFGUAAAC4oJ9Oidcl448vTE++/PtrTL70pa0zoUsHORnrdPR0u+84eeFMe5eMTf+dNLd0+o4TKRRlAMJEUQYAAIALumnsYhnrtG7fMd9RQlG8JT358uYJq3xHKVg1TadkrNNHRpQqlWKoQsYnRy+UsU6b60/4jhIpFGUAwkRRBgAAgPM6e+fPkZjs/MmUNB8eXkJJ48miqvSAiG8+vsJ3lLxyy8TVMtZp3qYDvqNECkUZgDBRlAEAAOC8qhvTpdK1I+Oz86czkdSHhhTJWKeGE62+4xSk51bFa0BEWP46c6OMdZqwpMZ3lEihKAMQJooyAAAAnFdcJ/F99dFlMtZpaTWTL30YOXebjHUaU1zlO0peydyfd/fr3J/XFxRlQPzdGQRBbRAE7UEQVARBcEMvv+5HQfqHw5w+rEVRBgAAgPOauHS3jHX606uVvqOE6o6X0pMvn1m+x3eUgvSr59fKWKeXymt9R8krsysbZKzTbU+X+Y4SKRRlQLz9MAiCjiAIfhkEwYeDIHgmCIITQRD8j4t83aVBEDQEQbAioCgDAABASP779c0y1umxhTt9RwnVYwt3snPHo6+MS+/oW7HrsO8oeWVD3XEZ63TjmEW+o0QKRRkQbxVBEEw469f/EATBgSAIBl3ga/4xCILVQRD8OgiCaQFFGQAAAEJy66QyGes0Z2OD7yihcpvTky+/9xSTL3MtlUrpqmHFMtZp35EzvuPklaOn22Ws06WDnNo6E77jRAZFGRBflwRBkAiC4Hvv+vgLQRDMvcDXjQqCYHb3/54WXLgoe1+Q/uGReT4QUJQBAADgPD45eqGMddpcf8J3lFDtPNQ9pGBEfIYUREXTqTYZ63TZIKeOrqTvOHkllUrpIyNKZaxTTdMp33Eig6IMiK9/DtL/5/7Muz7+UJDeaXYunwvSRy7/v+5fTwsuXJTd073GOx6KMgAAALzbqbZOGetkrNPJtk7fcULV3pXQZYPSf7amU22+4xSU9bXp44U3jV3sO0pe+ubjK2Ss06KqQ76jRAZFGRBffS3K/t8gCPYFQfDNsz42LWBHGQAAAEKwtaFZxjp94r4FvqNkxRceWiJjndbsOeo7SkGZs5EL6y/kDy+ul7FOz67c6ztKZFCUAfHV16OXHwvSPwwSZz2p7icRBMEHe7Emd5QBAADgnOZuOiBjnW6ZuNp3lKz4+XMVMtbp5fI631EKypOLdslYp//zGoMUzmVMcZWMdRo5d5vvKJFBUQbEW0UQBOPP+vU/BOmjlee6zP//CYLg2nc9c4IgWNz9vy/pxXoUZQAAADinJ2JeaIyat13GOt331nbfUQrK3a9vkrFOTyza5TtKXnqlok7GOv38uQrfUSKDogyItx8GQdAeBMHPgyC4JgiCyUEQnAiC4H92//70IAjGXuDrpwVMvQQAAEAI/jJjo4x1mrCkxneUrHhxTa2MdfrV82t9RykoP5ycnqQ6uzJek1TDsrrmiIx1+tLDS31HiQyKMiD+7gqCoC4Igo4gvcPs02f93rIgXYadz7SAogwAAAxAZyKpJTuadPR0u+8o8OzfJ6ySsU7FWw76jpIVq3enC4kvUkjk1E1jF8tYp/W1x3xHyUv1x1tkrNOHhhQpkWQia29QlAEIE0UZAACQJKVSKZVsPagvPrxUxjp9avRCbdp/wncseHTdPfNlrFPVwXj+u2Jjc5uMdbp8cJE6upK+4xSEzkTy7WmjJ5k2ei6JZEofGlIkY53qj7f4jhMJFGUAwkRRBgAAtL72uL4/cbWMTb+BvbT7jeyVQ4v11uYDvuPBg+NnOnq+H1o7Er7jZEUqldKHh5fIWKeaptO+4xSE2qNnen62pFLsljqfL3X/B4vVNUd8R4kEijIAYaIoAwCggCWSKf115saeQuSqYcUaN79ah0626ZfPr+35+GMLd/KmtsCsrz0uY51uHLPId5Ss+vaTK2Ss0/xtjb6jFISVu9LHXf9t3DLfUfJaZiLrKxVMZO0NijIAYaIoAwCggL2xvr5nB9ndr29SY/PbR6ESyZRGu+09ZdmdL29QW2c8dxbhvTLfGz9+Zo3vKFn1x1cqZazTpGW7fUcpCC+Xpyc6/oKJjhc0Ys5WGes0tniH7yiRQFEGIEwUZQAAFKjORFKff3CJjHV6aun5pxrOXLu/576cB0p401YoHi6tlrFOg2dt8R0lqx5buFPGOv3365t9RykID5TskLFOI+Zs9R0lr01duVfGOv3XS+t9R4kEijIAYaIoAwCgQL1Skd7Z8Yn7Fqilo+uCnztv0wEZ63TtiFKdauvMUUL4dMfLG2Ss05QVe3xHyao5GxtkrNMPJq32HaUg3Fkg31cDtXD7IRnr9K0nVviOEgkUZQDCRFEGAEABautM6MYxi2Ss07Mr917085PJlL78SPpy6cnLOaJWCL75ePruroXbD/mOklVbG5plrNP19y7wHaUg3Dx+pYx1KuVOuAvadehUz3+c4H7Ii6MoAxAmijIAAArQ86vSx3o+ff+iXt87NnPtfhnrdMP9C9XRlcxyQviUSqV0Tfc0yN2H4z0N8kx7V889fM0t7JbMto/fu0DGOm0/wPuPC2nrTPR8Xx470+E7Tt6jKAMQJooyAAAKTGtHQp8cvVDGOr24prbXX9feldCnur/utXX7s5gQvh062SZjnS4b5AqiFP30/endlRvqjvuOEmunzyolOcJ9cZnvy0q+Ly+KogxAmCjKAAAoMJOX75axTp99YHGfS5BJy9Jf+2/jlimZ5DhQXK3Zc1TGOn3hoSW+o+TEjyavkbFOr6+v9x0l1qoOnpSxTh8bNd93lEi47ekyGes0u7LBd5S8R1EGIEwUZQAAFJDT7V362Kj5MtZpZj92hZ1s69RHRpQWxN1VhSwz6OFnz1b4jpITQ2ZtkbFOD5Uy1TWb5m9rlLFO3x2/0neUSLj79U0y1unxhbt8R8l7FGUAwkRRBgBAARm/eJeMdfriw0vVlejfkboxRVVMCYy5scU7ZKzTiDlbfUfJiakr03f2/eHF9b6jxNqUFXtkrNMdL23wHSUSJiypkbFOf5250XeUvEdRBiBMFGUAABSIRDKl67sv0p6zsf9HeQ6dbNOHhhTJWKf1tcdCTIh8ccdLG2Ss09ReTESNgyXVTTLW6WuPLvcdJdZGzt0mY53GFrNzrzfmbTogY51umch/lLgYijIAYaIoAwCgQKzdd0zGOl13z3x19nM3WUbmSNBvX1gXUjrkk+88uVLGOi0okOO1dUdbZKzTFUOLleDuvaz51fNrZazTS+W9HyJSyDbXn5CxTp8cvdB3lLxHUQYgTBRlAAAUiMyRyT+/Wjng16ppOiVjnS4d5LT3yJkQ0iGfXHdP+h676sZTvqPkRCKZ0hVDimWs0/5jLb7jxNZXxi2TsU4rdh32HSUSmls6e6aEtnR0+Y6T1yjKAISJogwAgALx5UeWylineZsOhPJ6t08tl7FOE5fuDuX1kB/OfnPe2pHwHSdnMiXO0uom31FiKZVK6aph6TJyH+V6r2VK6x2NvF+7EIoyAGGiKAMAoADsOXxaxjp9cHCRTrZ1hvKaL5Ttk7FOt04qC+X1kB+21DcX5HGv301fJ2OdnltVGPey5VrTqbaeXagdXQM7+l1Ivjs+fQy6dFuj7yh5jaIMQJgoygAAKADPLE9Pm/vplPLQXnP/sfS9TpcNcjrR0hHa68Ivt/mgjHX6foFdIP5ASXrS57DZhTHpM9fW1x6XsU43jV3sO0qk3PlyerDGM8v3+I6S1yjKAISJogwAgAJw29NlWdkt89VHlw14iibyy8Slu2Ws019mbPQdJadeW7dfxjr9ZMoa31Fiac7GBhnrdNvT7EDti4dK0wXu0NlbfEfJaxRlAMJEUQYAQMwdP9OhywcXZeWi8jHF4Q0IQH4Y9OYWGes0bsFO31Fyan1teirsjWMW+Y4SS08u2iVjnf7+2ibfUSJl5tp0gXv71PB2A8cRRRmAMFGUAQAQc7Mq62Ws09cfWx76a5fvOSpjnT46ar4SyVTor4/c++mU9JCGN9bX+46SU8fPdDBhMIvufn2TjHV6YtEu31EiJfMz9gsPLfEdJa9RlAEIE0UZAAAxd0f3HTcPl1aH/tpdiaT+ZWSpjHVat+9Y6K+P3Pvcg4tlrNPaAvzn+bFR6QmD2w40+44SOz+avEbGOs2qLKwCdqAam9NDEC4fXKTOBEMQzoeiDECYKMoAAIixjq6kPjIiXWRV1h3Pyhp3vVIpY50eLNmRlddH7nQmkj3HdA+dbPMdJ+e+P3G1jHWat+mA7yixc9PYdAG7vrbwCtiBSCZTunJosYx1qj16xnecvEVRBiBMFGUAAMTYyl1HZKzTJ+5bqGSWjkbOrmzI2tFO5Fbd0fQk0yuHFmft+yWf/f219PHAxxdyPDBMnYmkLhuUPtbaVIAF7EB9ZVx6aMrynYd9R8lbFGUAwkRRBgBAjI2cu03GOtk3NmdtjeNnOnreBDecaM3aOsi+TLH6b+OW+Y7ixVNLa2Ss058YThGq2qNnegrYVKrwCtiB+vW0tTLWafqaWt9R8hZFGYAwUZQBABBTqVSq57jTgu2HsrrWLd1H1l7kjVykvVxeJ2OdfvX8Wt9RvCjZ2ihjnb47fqXvKLFS6AXsQI2at13GOo12231HyVsUZQDCRFEGAEBM7Wg82bOLo7UjkdW1JiypKeiCJS7GFFfJWKeRc7f5juJFdeMpGet07chSdj6F6JWKdAH7i+cqfEeJpGmr98lYp9++sM53lLxFUQYgTBRlAADE1PjFu2Ss06+nZb+8qjqYLuWuGlasts7slnLInv96ab2MdXp25V7fUbxo60zI2PQx4qOn233HiY0HSnbIWKfhc7b6jhJJS6qbuAfyIijKAISJogwAgJj64eQyGev0Unn2j0OmUil9ZswiGeu0ZEdT1tdDdnz7yRUy1mlhlo/q5rPMceV1+5jOGJY7X94gY52mrNjjO0ok7Tl8WsY6XTO8hJ2O50FRBiBMFGUAAMRQVyKpa4aXyFinXYdO5WTNIbO2yFinYbPZNRJV/zKyVMY67czR90w++smUNTLW6bV1+31HiY2bx6+UsU4lWxt9R4mkjq6zpoaeYmrouVCUAQgTRRkAADG0/UD6KOS1I0qVTOZmB8LiHYdkrNNNYxez6yGCmls6e44dZvtOu3yWKXwfKt3hO0psfPzeBTLWafsB3nP0FzsdL4yiDECYKMoAAIihF9fUylin26eW52zN1o6ErhhSLGOd6o625GxdhGNz/QkZ6/Sp0Qt9R/Fqyoo9Mtbpv15a7ztKLJxu7+opYE+1dfqOE1mZnY5vrK/3HSUvUZQBCBNFGQAAMfS3mZtkrNO4+dU5Xfd7T62SsU6zKxtyui4G7q3NB2Ss0y0TV/uO4tWiqvTOyG88vsJ3lFjIDPr46Kj5vqNE2qA30zsdxy3Y6TtKXqIoAxAmijIAAGLoS48s9XKx/r1vbeeesoh6ammNjHX664yNvqN4tbv74vSrh3Fxehjmb2uUsU7fHb/Sd5RIm7Rst4x1+tOrlb6j5CWKMgBhoigDACBmTrR09Bx1On6mI6dru80HZazTt55gN07UDHpzs4x1erTAd6x0dCV1+eAiGevU2MzF6QM1deVeGet0x0sbfEeJtOIt6Z+t/z5hle8oeYmiDECYKMoAAIiZpdVNMtbpiw8vzfnaB5tbZazT5YOL1NLRlfP10X+ZO5De3MAdSF94aImMdSrbfdR3lMgbOXebjHUaU1zlO0qkbTvQLGOdPn7vAt9R8hJFGYAwUZQBABAzjy7Y6fUI3Y1jFlEyRNDnHmSqXsbPnq2QsU6vVNT5jhJ5v3p+rYx1eqm81neUSGMowoVRlAEIE0UZAAAxc/vUchnrNL1sn5f173hpg4x1mrCkxsv66LvOxNvHDZtOctwwswvq/iJ2QQ3UV8Ytk7FOy3ce9h0l8q6/d4GMddra0Ow7St6hKAMQJooyAABiJJlM6dqRpV7fTGXuJPrV82u9rI++qz16RsY6XTWsmAvsJU1bvU/GOv3mhXW+o0RaKpXS1cNKZKzTviNnfMeJvP/onipctOWg7yh5h6IMQJgoygAAiJGaplM9hUdXIuklQ2Xd8Z67dChdomHFrsMy1umrjy7zHSUvLNuZ/vv4yjj+Pgbi8Kl2Get06SCnji4/P4/i5C8zNspYp4lLd/uOkncoygCEiaIMAIAYmbluv4x1uvXpMm8ZOrqSumJosYx12ssukkh4qbxWxjr9ehq7ACWp7miLjHW6YkixEknK3v5aX5suzT8zZpHvKLGQuX/SvrHZd5S8Q1EGIEwUZQAAxMigN7fkxYS5709cLWOd3ljPBMUoGFNcJWOd7pm3zXeUvJBIpvShIek72/Yfa/EdJ7LmbGyQsU63eSzu4+TNDfUy1ulHk9f4jpJ3KMoAhImiDACAGPn6Y8tlrFPJ1kavOUa77TLWacisLV5zoHf+8OJ6Gev03Kq9vqPkjS8/slTGOq3YxSX0/fXkol0y1unvr23yHSUW1tcek7FON41d7DtK3qEoAxAmijIAAGLidHuXLhvkZKzTIc+TC4u3HJSxTt94fIXXHOidbz2xQsY6Lao65DtK3vj1tLUy1ukFT9Nj4+Du1zfJWKfHF+7yHSUWzr7zrb0r4TtOXqEoAxAmijIAAGJidc2RvNltcOhkm4x1umyQ0+n2Lt9xcAGpVErXjkhPSq1pOuU7Tt7I7IrkOGr//WjyGhnrNKuSI9hhSKVS+vDw9BTR3YdP+46TVyjKAISJogwAgJiYsKRGxjrd8fIG31EkSTeNXSxjnVbVHPEdBRdwoqVDxqZ3IrZ1skslIzPg4BfPVfiOElmZnwHr9h3zHSU2vvF4evfn4h3s/jwbRRmAMFGUAQAQE5mjYlNW7PEdRZJ01yuVMtbpyUUcu8pnm+tPyFinT41e6DtKXsns0Pziw0t9R4mkzkSy5yh4k+ej4HHy++ncJ3guFGUAwkRRBgBADKRSKV1/7wIZ67Sh7rjvOJKk51btZUdOBLjN6fvkbpm42neUvHKwuVXGOl0+uEidiaTvOJFTe/SMjHW6cmixUqmU7zixMaYoPaF25FyOBJ+NogxAmCjKAACIgbqjLTLW6YohxXlzyfOm/emdSh8dNV/JJG+U89XTy3bLWKc/v1rpO0peSSZTumpYsYx12nvkjO84kbNyV3pH3pcfWeo7SqxkjgT/8vm1vqPkFYoyAGGiKAMAIAbmbGyQsU7/PmGV7yg9OrqSunJocfcl8Vw8na+Gzd4qY50eLq32HSXvfP2x5TLWacmOJt9RIueVijp2lGYBBeS5UZQBCBNFGQAAMZCZ0Dd8zlbfUd7hB5NWy1inmev2+46C8/jFcxUy1unVijrfUfLOH15M3wc1dSX3QfXVAyU78vJnUtTtP/b27uEEO3V7UJQBCBNFGQAAMXD71HIZ6/RyeX6VHZn7dAa9udl3FJzHV8Ytk7FOK3cxnfTdMmXPsNmUPX1158sbZKzTM8vzY7hIXCSSKX1oSJGMdWo40eo7Tt6gKAMQJooyAABi4FOjF8pYp/W1+XGRf0bJ1kYZ6/T1x5b7joJzSKVSunpYiYx12sc9XO8xc+1+Get0+9Ry31Ei5+YJq2SsU8nWRt9RYueLDy+VsU6rd1NuZ1CUAQgTRRkAABF3/EyHjHUy1ul0e5fvOO/QcCI9OfCDg4vyZsgA3nb0dLuMdbp0kOOfzzms3XdMxjrdNHax7yiR8/HuKbzbDjT7jhI7P3uW49LvRlEGIEwUZQAARFzZ7qMy1umzD+Tfm/lUKqXr7pkvY522NvCGOd9kJpPeOGaR7yh56fCpt4vEtk6KxN463d7VU96fbOv0HSd2hs9JD+B4oGSH7yh5g6IMQJgoygAAiLjnV+2VsU6/nrbWd5Rz+uHkMi70z1Nu80EZ6/SDSat9R8lLqVRKHxlRKmOddh065TtOZFQdPCljnT46ar7vKLE0dWX6Z/4dL23wHSVvUJQBCBNFGQAAETfozc0y1umh0vzcXTBqXnoi5z3ztvmOgneZtGy3jHX6y4yNvqPkre88uVLGOpVu466t3pq/LX034XeeXOk7Siwt3H5Ixjp964kVvqPkDYoyAGGiKAMAIOK+91T60uy5mw74jvL/s3en0VVV+brw1zjvGPe+H973fLz3HfeOO6a9pQePVaXHrkpLrXPKOlWW1aKWWlZjVVnHsqrsyhn6QgUEQZBOkEZERQLSyUxDAgkQ0oeQDkISQnrSN6TPzt7reT+svTegENKsvedaaz+/MfLBZCd5xCS4n8z5/1/WzoIGCKnw+Los3VHoS2btKYGQCksPnNYdxbFe3FYIIRXWHT6jO4pr8MRTZFW29EJIhWlzk2Gapu44jsCijIjsxKKMiIjIxQIBE7fOsbYWVjj0alhZUw+EVLhtHp/UOc2vN1tDwbfncSj4lSw7cBpCKsTtKtYdxTXm7SuDkAoLE0/pjuJJQz5/eAZcZ/+I7jiOwKKMiOzEooyIiMjF6jsHIKTCDTMT4PMHdMe5rJHRAG6YmQAhFRq6BnTHoYt8d9lhCKlwrKpddxTH2l3IWfo0rwAAIABJREFUE5ET9bsP8yCkwsfZtbqjeNbdCw5CSIXCui7dURyBRRkR2YlFGRERkYulBGfVPLL8iO4oY3pk+REIqZByskV3FAoyTRM3z06EkAq1Hf264zhWYV0XhFS4a0Gq7iiu8e/BAvZIRZvuKJ41fZ21JGXviUbdURyBRRkR2YlFGRERkYutOlQJIRX+9lmh7ihjejn+BIRUWJFaqTsKBbX3DUNIhWviFEZGnXka0Qm6B0bC19z6h0d1x3E80zTxtdnWdfCz7SxgI+XvO4v4M/UiLMqIyE4syoiIiFzsz58eh5AKa9OdPWh8w9FqCKnwx635uqNQ0In6bgipcM/Cg7qjON7X5x+AkAplTT26ozheWy8L2GhYnVYFIRVejufGWoBFGRHZi0UZERGRi4VmTKWdbtUdZUyZVe0QUuH+xWm6o1DQ/uImCKkw/X3O3rqa0GZZVXxOdxTHK6i1rqreywI2or4osr5/f742U3cUR2BRRkR2YlFGRETkUsOjflw3wxqSf65nUHecMXX1X7i+1jvk0x2HAKxNP2OdSNnOEylX8/J26+rw6rQq3VEcb09hI5cfREFxg3Ui9M63ODsPYFFGRPZiUUZERORSZU09EFLhtnnJME1Td5yrumehtaUtr6ZTdxQCMHN3CYRUWHbgtO4ojrfyoDUL8JX4It1RHO+94J/Vazv4ZxVJPQO+8C8fBkY4O49FGRHZiUUZERGRS+063uCqq3O/+zAPQipsyazRHYUAPLspF0IqxOfV647ieKFrbj/jNberenWHNWR+1SEOmY+0f/2HNTvv1Dk+l/v4yCkWZURkGxZlRERELrUw4RSEVJi9p1R3lHFZeuA0hFSQnxfrjkIAHl6aDiEVMqvadUdxvNJG6/TmN99I0R3F8aavy4KQCntPNOqO4nmPrcqAkApJpc26o2j3+w1HWJQRkW1YlBEREblU6ETQx9m1uqOMS0LJOQip8KNVGbqjxDzTNHHTrEQIqVDXMaA7juP1DY+Gr7n1DHLG3ljuXmBdsS6s69IdxfNe3FYIIRXWH3H21uNo+I/FSSzKiMg2LMqIiIhcKvSENN8lM79q2vshpMKNsxIx6g/ojhPT2nqHIaTCtXEKI6P8bzEed76VCiEViuq7dUdxrCGfP1wodvQN647jee8kW6d0Z+wu0R1FK9M0cfPrn7MoIyLbsCgjIiJyoYsHOZ93yRbJQMDErXOSIKRCZUuv7jgxrbCuC0Iq3LvwoO4orjH9fV4pvJqq1j4IqXDrnCRXLBhxu50F1pzKpzZk646iVev5Ifyfl3awKCMi27AoIyIicqGc6g4IqXDfokO6o0zIz9ZmsmxwgNBwercsgnCC13cWQ0iF5akVuqM4Vlp5K4RU+P6Ko7qjxISC2k5X/j1gt5zqDhZlRGQrFmVEREQu9FFWDYRU+O2HebqjTMisPSUQUmFh4indUWLa2vQzEFLh5e0ndEdxjdCf2V8/K9QdxbG2ZFo/l/64NV93lJjQ0Wddob4mTmHI59cdR5vteXUsyojIVizKiIiIXGjGbqtwejupXHeUCfk0pw5CKjyzMUd3lJgW+vpZlsLTUeOVVGoto3iMyyiu6I39JyGkwlvqpO4oMcE0TUyblwwhFSpi+Dr7osRyFmVEZCsWZURERC7k1iuMJ+q7IaTCHW+m6o4S034V3Jgan1+vO4prnG7uhZAKt81L5vytK3huSz6EVNiaVaM7Ssz40aoMCKmQXNasO4o2f9yaz6KMiGzFooyIiMhlTNPEtLnWKYLyZnf9HT444se1cdYSgtbeId1xYtZDS9MhpELmmXbdUVyDGx2v7nvvHoGQCumnW3VHiRl/2VYIIRXWHT6jO4o233v3CIsyIrIVizIiIiKXaegagJAK189IwMhoQHecCXs4WNIcrmjTHSUmmaaJm2YlQkiF+s4B3XFc5d6FByGkQkFtp+4ojmOaJr4229pqe7a9X3ecmLEspQJCKsTtKtYdRYtAwPp5xqKMiOzEooyIiMhl0k5bm+X+493DuqNMyp8/PQ4hFdamx+4JCJ1ae4cgpMK1cQo+v/uKVp2e2pANIRV2FjTojuI4bb0XBsu7scB3q92FDRBS4fF1sbnBtql70Pp59spOFmVEZBsWZURERC6zKeMshFR4fmuB7iiTsjqtitsDNTpe1wUhFe5bdEh3FNeZGVyCsCTZXUs0oqGgll9XOhQGv5/vWhCbcx8zq9ohpML9byoWZURkGxZlRERELjNrj/VkfbHLNl6GpJxsgZAK/7niqO4oMWlfUROEVJgeoydQpmLD0WoIqfDCJ8d1R3Gc0MmmJ9bz6yqaugdGwrPzBkZGdceJuo+zayGkwtNr01iUEZFtWJQRERG5zC8/sK5/7XDpxsLajn4IqXDTrET4A9weGG1r0q0TfS/Hn9AdxXUOnmLJeyUrUishpMLfdxbpjhJzbp9/AEIqnGyKved0b+4/CSEVZmzPZVFGRLZhUUZEROQy94QHinfpjjIp/sCFYfK1HRz6HW0zgtcHl6VU6I7iOmfa+iCkwi1zkmCaLHkv9kp8EYRUWJ1WpTtKzPnx6mMQUiGh5JzuKFH33JY8CKmwPrWERRkR2YZFGRERkYsMjIyGr9l09Y/ojjNp/7niKIRUSD3ZojtKzHlmY46rTyTqNDIawLVx1vdfy/kh3XEcZfr7WRBSYV9Rk+4oMeel7SditqQMbVFOKqxmUUZEtmFRRkRE5CJlTT0QUuHr8w/ojjIlf/2sEEIqrEmPvSd2uj30jvXEMutMh+4orvTAkjQIqZBdzT+/i929wDrpeqK+W3eUmBO69vrajti69uoPmLhhZgKEVDhV28yijIhsw6KMiIjIRb4IDmL/6ZpjuqNMyapD1hO7l7dzTlY0BQImbgxee63vHNAdx5We3ZQLIRW25dbpjuIYQz5/+KRrp4tPurrV3hONEFLhF+9n6o4SVXUdAxBS4cZZieju7mFRRkS2YVFGRETkIu8dtAqmV11+ciC5rBlCKjy6MkN3lJjSen4IQipcNyMBo/6A7jiuNG9fGYRUWJhwSncUx6hq7YWQCtPmJnN2mwbFDd0QUuGON1N1R4mqwxVtEFLh35cdxvnz51mUEZFtWJQRERG5yN88cmWxOjgU/WuzkxDg5suoKajtgpAK9y06pDuKa23JrIGQCn/4KF93FMc4VM5toDqdH/KFT/T1Dvl0x4ma0Pfi7z/KZ1FGRLZiUUZEROQij63KsAYXl7p7u9moP4AbZ/IKYLSFrmg9vi5LdxTXuvgUC1k+PHYWQio8v7VAd5SY9c03UiCkQmljj+4oURM63bkg4RSLMiKyFYsyIiIilzBNE9PmJkNIhYqWXt1xpuyR5UcgpMKhcm6+jJbVaVUQUuGVeHdf3dXp4rlIPA1pmf/FyXBhQXr8bG0mhFT4Ioa2jl48L5BFGRHZiUUZERGRS7T1DkNIhWviFIZ8ft1xpuzFbdY10nWHz+iOEjPidpVASIV3Uyp0R3GtizftNXTxNCQAPLclH0IqbM2u1R0lZr0SXwQhFVYerNQdJWpCG2izznSwKCMiW7EoIyIicomc6g4IqfDtxd6YL+WVxQRu8szGHAipsCO/XncUV3t4aTqEVDha2aY7iiP8x7uHIaTCkQr+eegS3iQcHxubhH3+AK6bYRXWzT1DLMqIyFYsyoiIiFxiW24dhFT41aZc3VFskVhyDkIqPLb6mO4oMePBd6yCJ7u6Q3cUV3tuS551giqrRncU7UzTxM2zrXmDNe39uuPErP3FTRBS4adrYuPn6cULYUzTZFFGRLZiUUZEROQSCxJOQUiFefvKdEexRVVrL4RUuHWO9USHIisQMMMLFHhlcGre3G/N5Jr/xUndUbRr7R2CkArXximMjAZ0x4lZpY09EFLhG2+k6I4SFaFNq48sPwIALMqIyFYsyoiIiFzCa6dYfP5AeNZTY/eg7jie13LeKjSum5GAUT8Ljan4JKcWQir8ZrM3TndORUFtJ4RUuG+RN66Eu1Xf8CiEVBBSoWfQpztOxG04Wg0hFf70sbVplUUZEdmJRRkREZFLPBSci5RR2a47im1Cs43ST7fqjuJ5oULjW2+z0JiqzKp2CKnw4DvpuqNot7uwAUIqPLk+W3eUmHfnW6kQUqGovlt3lIibtcdaTLI4qRwAizIisheLMiIiIhfw+QO4Pji4uMlDp69e+OQ4hFTYcLRadxTP23uiEUIqPLE+S3cU12vqHoSQCtfzdB6Wp1ZASAX5ebHuKDFv+vtZEFJh74lG3VEi7ukN1mKS+OBiEhZlRGQnFmVEREQucLa9H0Iq3Dw7EYGAd+Z5vZtiPcl+fSefZEfa6rQqbhm1SSDAAfYhL8efgJAKq9OqdEeJea/vLIaQCstTK3RHibj7Fh2CkAp5NZ0AWJQRkb1YlBEREbnAwVPW4OLvrziqO4qtQpvafhIjm9p0itsVO0+io+GR5UcgpEJaeWxfG/7F+5kQUuGLoibdUWLe2vQzEFLhb58V6o4SUUM+P66Js+axtfUOA2BRRkT2YlFGRETkAqHBxS98clx3FFtVtFibL6fNTebmywh7ZqN1VWlnQYPuKJ7w/NYCCKmwKeOs7iha3bUgduZiOV1S6TkIqfDYam//4iH098a/XPT3BosyIrITizIiIiIXiNtlDS5eeuC07ii2GhkN4Lrg7LXmniHdcTztO0vSIKRCdnWH7iie8HZSOYRUmLO3VHcUbQZH/OFNi139I7rjxLzy5vMQUuFf/3FAd5SISi5rhpAKj67MCL+ORRkR2YlFGRERkQs8sd4a0ry70HungR4ObvM8WtmmO4pnBQImbphpFZKNHloGoVN8Xj2EVHhmY47uKNrESjHjFrFSXL5/2Lpi+uK2C1dMWZQRkZ1YlBEREbnAv71lXW864cHrTbzCFnnNPUPc0miz3LOdEFLhW28f0h1Fm6RS62TPY6syrv5giop7Fh6EkArH67p0R4mYV3cUQUiFFamV4dexKCMiO7EoIyIicrjeIV/4lEDPoE93HNstO3AaQirE7eLmy0jJr7FKnW8vjt1Sx25tvcMQUuGaOIXhUb/uOFqETvb81ePD493kyfXZEFLhcw/PIvzJmmMQUmF/8YUFEizKiLzvz4Zh1BqGMWwYRq5hGHeN8dg/GIaRYRhGd/Dl4FUe/2UsyoiIiByupKEHQirc8WaK7igRsa/I2nz587WZuqN41p7CRgip8OT6bN1RPMM0TfzL3GQIqVDZ0qs7jhahTarLUrhJ1Slm7bHmWS5OKtcdJSJM08S0edb3XXnzheewLMqIvO0JwzBGDMP4rWEYtxqG8YFhFWD/4wqP/9QwjBcMw/i6YRhfMwzjQ8MwegzD+N/j/HwsyoiIiBxu7wmr5Jj+fpbuKBFx6tyFOUfcfBkZqw5VQkiF13YU6Y7iKT9ceRRCKhwoa9YdRQsvz050q83HzkJIhT9uzdcdJSJae61r5NfGKQz5LpzkZFFG5G25hmGsvuif/8kwjCbDMOLG+f7/l2EYvYZhPDvOx7MoIyIicrh3UyogpMLrO715NXHI58e1cdbV0tZebr6MBPl58Vdm+tDUvbitEEIqrD9yRncULWJhHpbbHK1sg5AKDy9N1x0lIjLPtENIhQeWpF3yehZlRN713wzD8BuG8ZMvvf4jwzD2jfNj/L+GYQwZhvHoFd7+3w3rh0fo5X8bLMqIiIgcLfRkfN1h7z4Zf/Ada/Plsap23VE86ekNOZ6fW6RDLM/XG/LFxoZFt2nqHgwv7vB5cHHH1uxaCKnw2w/zLnk9izIi7/pfhvXNfe+XXr/EsE6ajcdawzCqDcP4v6/w9n8EP8clLyzKiIiInCsWrnf9/qN8CKmwJbNGdxRPemBJGoRUyKnu0B3FU3Ydb4CQCk+s9+a16LGcbu6FkAq3zUvmlWkHMU0Tt8xJgpAKVa19uuPYbt6+MgipsCDh1CWvZ1FG5F1TLcriDMPoMgzjX8d4DE+UERERuYhpmrjVw096QhYllkNIhbl7S3VH8Rx/wMQNMxMgpEJj96DuOJ5SWNcFIRXuXnBQd5SoSy5rhpAKj63K0B2FvuTRlRkQUiGp1Hu/XHlmo3U6dnte3SWvZ1FG5F1TuXr5mmEN8b9zgp+TM8qIiIgc7OLBxSOj3rtGExKfXw8hFZ7ekKM7iuec67lwFcsf4MkfO3UPjISvHw6MjOqOE1XrDp+BkAp/2VaoOwp9yUvbT0BIhdVpVbqj2C40F6+gtvOS17MoI/K2XMMwVl30z/9kGEajMfYw/9cNwzhvGMY9k/h8LMqIiIgcrKC2E0Iq3LfokO4oERX697x3YeydzIm0vBrrz/b+xWlXfzBN2O3zD0BIhZNNsfX/03G7SiCkwrIDp3VHoS9ZnVYFIRVe3n5CdxRb9Q2Phovp7oFL5+KxKCPyticMwxg2DOPXhmHcYhjGesMwug3D+J/Bt281DGPRRY+XhmGMGIbxc8Mw/r+LXv6fcX4+FmVEREQOFpqB9OT6bN1RIqqrP3ZP5kTa7kLra+iXH3j7a0iXn6w5BiEVEkrO6Y4SVU+uz4aQCruOc0GE0ySVnoOQCj/y2LXY4oZuCKlwx5spX3kbizIi73vRMIw6wyrAcg3DuPuitx02DGPLRf9ca1xmOL9hDe0fDxZlREREDvZuSgWEVJCfe3+r3jfeSIGQCqWNPbqjeMrKg5UQUuHvO4t0R/Gklz18zW0s94avwHXpjkJfUtVqLVq4dU6SpxYthEr/6eu+ujyDRRkR2YlFGRERkYOFnoSvSff+k/Cfr82EkAr7ipp0R/GU13cWQ0iF9w5W6o7iSe8Fi8hXd8ROETnk84dPgHb2j1z9HSiqRkYDuG6GtcDjXI93FngsSbaWvszYXfKVt7EoIyI7sSgjIiJysJ8Fy6P9xd4vj0KFzvLUCt1RPOWpDbwiF0lfFDVBSIWfr83UHSVqKlqsE0vT5iV76sSSlzy0NB1CKmRUtuuOYpvntxZASIWNGWe/8jYWZURkJxZlREREDnbHm6kQUqGkwfvXEUNb9F7kFj1bPbAkDUIq5J7tvPqDacJKG3sgpMI33/jq3CSvOlDW7MkZWF7yh4/yIaTCh8e+Wiq51XeXHYaQCocr2r7yNhZlRGQnFmVEREQONTByYcNXz6BPd5yISznZAiEVfvDeUd1RPMMfMHHDTOsKVlO3d65gOcnFm/jOD3n/+xQA1h9hqe10bydZ1xRn7fnqNUU38vkD4Z9lDV0DX3k7izIishOLMiIiIocqbz4PIRX+9R8HdEeJiuq2Pgip8LXZSQgEeJ3LDk3dgxBS4foZCfDzzzRi7nzLOvlZ3NCtO0pUzNhdAiEVlh04rTsKXcHnBd7amHzmKn8/sCgjIjuxKCMiInKoWLve5PMHcP0Mnn6yU+7ZTgipcP/iNN1RPG36+1kQUmHviUbdUaLilx9Yc+8+L+DcO6c6Ud8NIRXufCtVdxRbhP4+vNKJYxZlRGQnFmVEREQOteFoNYRU+POnx3VHiRovDqDWaddx61TJUxu8carEqf6+syimFlHct+gQhFQoqO3SHYWuoHfI56mr+2vSqyCkwl8/u/x1XxZlRGQnFmVEREQONXtPKYRUWJxUrjtK1Pw+OID6o6wa3VE84b2DlRBS4fWdxbqjeNradGtm19+u8CTeS4Z8flwTZxUwHX3DuuPQGO5aYF0JPl7n/kLzlXirjF55sPKyb2dRRkR2YlFGRETkUM9uyoWQCtvz6nRHiZqFiacgpMLcvaW6o3hC6KTTlZ5ckj2SSs9BSIXHVh/THSXiKlt6IaTCtLnJME3OvXOypzZYV2Tj8+t1R5myx1Yfg5AKCSXnLvt2FmVEZCcWZURERA714DvWNcTMM7FzDTE+rx5CKjyzMUd3FE8IzZLaXchZUpEUWrxx2zzvl0ehWVGProyN2YluNnevdSp5YeIp3VGmxDRNTJubDCEVKlp6L/sYFmVEZCcWZURERA7kD5i4YaY12L4xhgbbF9Raw+fvW3RIdxRPuH9xGoRUyKvp1B3F0y6+jtju8euIHxyJvdmJbvVRVg2EVHhuS57uKFPScn4IQipcG6cwPOq/7GNYlBGRnViUEREROVBD1wCEVLhxZiL8AW+fULlYV/9IeAD1wMio7jiu5g+Y4S2i53pip2zV5duLrQH3OdUduqNE1MzdJRBSYemB07qj0FVkVrVDSIUH30nXHWVKxvPvwaKMiOzEooyIiMiBQk8MHnL5E5zJ+Pr8AxBSoaypR3cUV2vsHoSQCjfMTIipslWX32y2Zgp+klOrO0pEheZe7SzgdV6nG89JLDcYz8k4FmVEZCcWZURERA60LbcOQir8enOu7ihR9/O1mRBS4YuiJt1RXC2nugNCKjywJE13lJjw5v6TEFLhH1+U6Y4SUfctsk7OFdTyOq/TXTzb63Tz5Wd7ucF4Zq2xKCMiO7EoIyIicqC3k8pjdvtjaFPj8tQK3VFc7fOCBgip8NSGbN1RYsJnwXLby4soYmkWm1dcbVukG4xneyeLMiKyE4syIiIiB3rhk+MQUmHD0WrdUaLu/cNnIKTCX7YV6o7iaitSKyGkgvy8WHeUmJBfYy2iuHfhQd1RIqaqtRdCKkyb6/3tnl7xSrz1i4f3DlbqjjJpdy84CCEVjtd1XfExLMqIyE4syoiIiBzo0ZUZEFIh5WSL7ihRl3KyBUIq/HDlUd1RXO21HdYT5FWH3PsE2U26By4sougf9uYiCn5vus/adOsXD3/9zJ2/eOgd8oW/r3oGfVd8HIsyIrITizIiIiIHum2eNVemosW9c2Um60xbH4RUuGVOEk+tTMGT663rSnsKG3VHiRl3vJkCIRWKG7p1R4mIDUerIaTCC58e1x2FxulAWTOEVPjBe+4sNwvruiCkwp1vpY75OBZlRGQnFmVEREQOc/HJlMER924qmyyfP4DrZyRASIVzPYO647jWtxdbQ9fzazh0PVoeX5cFIRV2F3pzI+TM3SUQUuGd5NO6o9A4VQd/8XDz7EQEXLj9dts4Z/+xKCMiO7EoIyIicpjihm4IqfBvV/kNupc9tDQdQiocq2rXHcWVRi8qG5t7hnTHiRmhImlJcrnuKBERGqq+Y4yh6uQso/4Abphp/Syo7xzQHWfCQhsvFyRceeMlwKKMiOzFooyIiMhhvihqgpAKv3g/U3cUbZ7bkg8hFT7KqtEdxZUaugYgpMINMxNceYrErTYfOwshFf64NV93lIi4Z6E1VL2g9spD1cl5Hll+xLUzL6cHT2nuOj72KU0WZURkJxZlREREDrM6rQpCKrwcf0J3FG0WJpyCkArz9pXpjuJK2dUdEFLhO0vSdEeJKUcq2iCkwsNL03VHsV3f8OiFoeoDVx6qTs7z0vYTEFJhpcs2X5qmiWnBeZ0nm8Z+vsqijIjsxKKMiIjIYV7fWQwhFVakuutJjZ3i8+rHNZeGLm9nQQOEVHh6A//8oqmpexBCKlw/IwE+f0B3HFuFroTf8WbsXgl3q/VHrM2X//VJge4oE9J40ffTyOjY308syojITizKiIiIHOaJ9Vkxv60wv6YTQirct+iQ7iiutDy1AkIqyM+LdUeJKaZp4tY5SRBSoarVWxtrdxda5evj67J0R6EJOlppnXR88J103VEm5OCpFgip8MjyI1d9LIsyIrITizIiIiKHuW/RoZifA9TZH9ubP6fq1R1FEFJhdVqV7igx50erMiCkQlLpOd1RbLUkuRxCKszcXaI7Ck1QW+8whFS4Jk5hYGRUd5xxW3WoEkIq/O2zwqs+lkUZEdmJRRkREZGDDI/6cU2cVRC19w3rjqPV7fMPQEiFsqYe3VFcJ3Qqce+J2D2VqMvLwXlQXispn99aACEVNmWc1R2FJuGON1MhpEJhnXt+AfPCp8chpMK6w2eu+lgWZURkJxZlREREDnKmrQ9CKtw6JwmmGdvbCn+65hiEVNhf3KQ7iut86+3QqcRO3VFiTmgZx0vbvbWM47vLDkNIhSMVbbqj0CQ8szEHQip8mlOnO8q4Pbw0HUIqHB7H1xyLMiKyE4syIiIiB0k73TrumSxeF7o+6LZNbbqN+gO4bkYChFRoOT+kO07MSS5rhpAKj67M0B3FNj5/ADfMtL6mGrsHdcehSQhtEp6zt1R3lHEZ8vlxbfB0des4fo6xKCMiO7EoIyIicpAtmTUQUuGPW/N1R9EudDLnZY+dzIm0hq4BCKlw48xEBAKxfSpRh6pW61ToLXOSPPPnHzrp6qV/p1gTWsbwi/czdUcZl9CW1W++kTKu09UsyojITizKiIiIHGT+FychpMKChFO6o2iXWHIOQio8tvqY7iiuknWmw5Ub7rzC5w/g+hneOn11IHhK7ocrj+qOQpNU3nweQipMm5vsimv98Xn1EFLhqQ3Z43o8izIishOLMiIiIgd5bks+hFTYml2rO4p2p5t7IaTCbfPc8cTOKXbkW08wn9mYoztKzArN8xrPbCU3WJNeNe7tg+RMF1+fre8c0B3nqubtK4OQCm/sPzmux7MoIyI7sSgjIiJykO+9e8RTT7CnYsjHDaCT8W5KBYRUiNtVrDtKzAptiNzokQ2Rr8RzXqAXfH/FUQipcKCsWXeUqwpt7t1Z0DCux7MoIyI7sSgjIiJyCNM0ceucJAipUN3WpzuOI4S2N+bVcHvjeIVKjdVpVbqjxKx3kk9DSIUZu0t0R7HFj1dbG2gTS87pjkJT8HL8CQipsCLV2YWnaZq4ff4BCKlQ2tgzrvdhUUZEdmJRRkRE5BCd/SMQ0jpBNTzq1x3HEZ7ZmAMhFeLz6nVHcY3H11knMfaeaNQdJWbtKWyEkArT12XpjjJlpmli2txkCKlQ0dKrOw5NwYaj1RBS4U8fF+iOMqZzPYMQUuG6GQkY8o3v70IWZURkJxZlREREDhHa8nXXglTdURxj7t5SCKmwMJHLDcbrvkXWKbyC2i7dUWJWaWOjvJImAAAgAElEQVRPeGOf27WeH4KQCtfGscB3u2NV7RBS4TtL0nRHGVNaeSuEVPiPdw+P+31YlBGRnViUEREROYQqtrY8/mxtpu4ojrElswZCKvzho3zdUVxh1B/AdcGNi63nh3THiVkDI6Ph06Fd/SO640xJZrBc4RZV9+voG4aQCtfEKfQPj+qOc0Wh5RF/2Tb+5REsyojITizKiIiIHGLd4TPcLPclRyraIKTCd5eN/2RBLKvvHICQCjfOSkQgwE2hOoVO9rl9vt7WLKusfm5Lnu4oZIN/eysVQiocr3PuidMXtxVCSIU16eOfs8iijIjsxKKMiIjIIWbvsa4ZvpN8WncUx2josoqfG2YmwM/i56qyznRASIWHePpHu19tyoWQCtty63RHmRJef/aWZ4Nfl5/k1OqOckX/vuwwhFRIO9067vdhUUZEdmJRRkRE5BC/3mw9gdme5+4n1nYKBEzcNCsRQirUdvTrjuN48fn1EFLhmY05uqPEvPlfnISQCm/uP6k7ypQ8vSG4UCOfCzW8YGHiKQipMGuPMzeyDvn84evjzT3jvz7OooyI7MSijIiIyCG+G/wt+rGqdt1RHOWR5UcmfLogVi1LqYCQCnG7nPkkOJZ8mlMHIRV+vTlXd5QpuXvBQcdf1aPx23vC2sj6c4fOwgwtwrh9/gGY5vhPEbMoIyI7sSgjIiJyANM0cfNsnpy6nD99XAAhFTZlnNUdxfFejj8BIRVWp41/tg9FRl5NJ4RUuHfhQd1RJq1v+MJSgp5Bn+44ZIOKll4IqfAvc5MdOcdwR/BU7JPrsyf0fizKiMhOLMqIiIgcoK3X2kZ2bZzCyGhAdxxHWZxU7uirQk4yfV0WhFTYe6JRd5SYd37I5/qSqbihG0Iq3PlWqu4oZJNRfwA3zrR+KVPXMaA7zle8sd+6svyPL8om9H4syojITizKiIiIHKCwrsv1p08iZWdBA4RUeGrDxE4YxKLQpsWCWl6Tc4LQf4/cs+7cfLnruPW998T6LN1RyEY/eO8ohFRIKm3WHeUrfvlBtjUTL29iM/FYlBGRnViUEREROcC+oiYIqTB9HZ+QfllBrVUi3sMScUw+fwDXxlknmFp7xz8EmyLnuS15EFJhS2aN7iiTsiTZOs05czdPc3rJqzuKIKTC8tQK3VEuYZomvvFGCoRUKGnomdD7sigjIjuxKCMiInKANelVEFLh5fgTuqM4TvfASPgK28DIqO44jlXfOQAhFW6alTihIdgUOe8knw4uVyjWHWVS/rg1H0IqbD7G+YBesjHjLIRU+OPWfN1RLlHXYf0Mu2FmAoZ8/gm9L4syIrITizIiIiIHiNtVAiEVlqU46zf8TvH1+QcgpMLJJv4/y5VknmmHkAoPLU3XHYWC9hdbJ0V/vPqY7iiTEtrEe6SiTXcUslFmlfWz4tuLD+mOconQRs7JfL+wKCMiO7EoIyIicoBnNuZASIUd+RObyxIrfrrmGIRU2F/cpDuKY8XnWdvifrUpV3cUCqpq7YOQCl+bneTIDYNj8fkDuH5GAoRUaOoe1B2HbNQzeGHRREffsO44YfP2lU1qkD/AooyI7MWijIiIyAEefCcdQipknenQHcWRQjN1Vh6s1B3FsZYdCF3z4zwppxj1B3DTLGvDYE17v+44E3KmzSr5bpmTxKu8HvTvwdOCqSdbdEcJ+9GqDAipsK9o4r8QYVFGRHZiUUZERKRZIGDixpnWk+mGrgHdcRxpdZo1w+2l7ZzhdiUvbT8BIRXWpp/RHYUu8ujKjOCGwXO6o0xIclkzhFR4dGWG7igUAa/vLIaQCm8nleuOAgAY8vnDJxgn8/cgizIishOLMiIiIs1azg9BSIXrZiRg1B/QHceRkkrPQUiFx1w66ykafrY2E0IqqGJ3FTJe91rwNOS7Lps/GFow8rfPCnVHoQgIXdV+3CGblvNqOiGkwp1vpU7qBCOLMiKy0z8bhoEH3lJ4eGk6X/jCF77whS98sfFl8Th/U58ffILwrbedNVjZSU4390JIhWnzknkN7ArufCsVQioUN3TrjkIXceqGwav562eFEFJhdVqV7igUAVWtveH5eT4H/IJm/ZEzU/o+YVFGRHb6Z8Mw8H9e2hEe6MgXvvCFL3zhC1/sebkmTo3rhNieQmvT15Prsyf1BCEWDPn8uCbO+nNtd9DwaacYHPGHv+66B0Z0x6GLhLaRPrAkTXeUCQnNsEorb9UdhSIgEDBx27xkCKlQ0tCjOw6e31oAIRXePzy5q+MsyojITv9sGAYOFdUgp7qDL3zhC1/4whe+2PCSXd0RLnVae4eu+j/4Kw9WQkiF13YUTeoJQqz41tuHIKRCXk2n7iiOU9nCE3dO1dk/Ei4x+4dHdccZlyGfH9cF50U191z9Zxi5068350JIhS2ZNVpzmKaJfwueiM2pntxCGxZlRGQnzigjIiKKgG+8kQIhFcqbr/53bGio8nvc6DimZzbmQEiF7Xl1uqM4zsFTLRBS4T9XHNUdhS7jrgVWCXC8rkt3lHEpaeiBkArfeCOFxauHvRf8Jc1fthVqzdHUPQghrTmdgyP+SX0MFmVEZCcWZURERBEQurZ0rKr9qo99akM2hFTYdbwhCsnca96+MgipsDDxlO4ojvPhMWsO1vNbC3RHoct4dpN1cufTHHeUvNvz6iCkwlMbeB3cyzIqrWvBuudj7i9ugpAKP1w5+aKfRRkR2YlFGRERUQQ8sT4LQirsK2q66mPvX5wGIRVyz/JK4Vi2ZNZASIXff+SuoejRMP+LkxBSYUECS0QnWph4CkIqzNlbqjvKuIRK6Tf3n9QdhSKod8iHa0NjAs7ru2L7xv6TU/7+YFFGRHZiUUZERBQBL3xyHEIqbD52dszH+QMmrg/OAjrXMxildO50tLINQip8d9lh3VEc57kt+RBSYWt2re4odBmhhR3T38/SHWVcpq/L4inXGPHI8iMQUiGp9Jy2DD9ZcwxCKuwunPzXG4syIrITizIiIqIImLO3FEIqLD1weszHNQZns9wwMwH+AGcBjaWha4B/VlfwvXetJ7vpp7mh0InKm8+7ZtmCaZqYFtyGeOocnyN43czdJVpPow6P+nHjzEQIqVDT3j/pj8OijIjsxKKMiIgoApanVkBIhbhdJWM+Lqe6A0IqfGdJWpSSuVcgYOKmWdYTqtqOyT+h8hrTNHHLnCQIqVDd1qc7Dl3GyGgAN8y0To42djv75Gh954VCemQ0oDsORdjnBQ0QUuFnazO1fP7jdV22LI5gUUZEdmJRRkREFAFbs2shpMIfrjJPa2fwScrTG3KilMzdQteE0nhyKqy9bxhCKlwTpzA8OrmNcRR5oa/dg6dadEcZ04GyZgip8H1uUI0JZ9v7IaTCjbMStfz82JhhLSL53Yd5U/o4LMqIyE4syoiIiCIgoeQchFT4+VV+Sx86eSY/L45SMnf708cFEFJhY8bYs99iSehExr0LD+qOQmN4afsJCKmwOq1Kd5QxrUithJAKr8QX6Y5CUWCaJr7xRgqEVDhe1xX1z//nT4/b8n3BooyI7MSijIiIKAJCVyoffCd9zMe9uqPIFU+enWJJcjmEVJi1Z+wrrbFk74ngoPh17hgUH6vWHT4DIRX+/Olx3VHG9PxWq4zecLRadxSKkue25Gn7b37fokMQUiGzqn1KH4dFGRHZiUUZERFRBFS19kJIhdvmJY/5uMeD2+X2nmiMUjJ3C11V/eUH2bqjOMaqQ9YJoFd38ASQkx2ucMfW1vsXp9lSXJB7rEmvgpAKL3wS3RK35fwQhFS4Nk6hb3h0Sh+LRRkR2YlFGRERUQR09Y9ASAUh1ZgDsUO/TS+ojf6VFzcqqLWuGd7Da4Zhf99pnUp872Cl7ig0htaLSoEhnzNnyfUO+cI/t7r6R3THoSjJDp6AvntBdH+uJpVaIwoeWX5kyh+LRRkR2YlFGRERUQQEAiaum2FtuWs5P3TZx/j8AVwbZz0pbb3CY+hS3QMXCsiBkamdQPCKJ9dnQ0iF3YUNuqPQGC6eBVXS0KM7zmXl13SyiI5BAyOj4b+vmqK4lXVhwqlxbYceDxZlRGQnFmVEREQRcsebqRBSoazp8k+K6zsHwtvGAgEzyunc6+vzD4z55xprLpxK7NQdha7ilx9YpWZ8fr3uKJf1UVYNhFT47RQ3EJL7PLoyA0IqfFHUFLXP+ZM1xyCkwg4bvh9YlBGRnViUERERRcgjy49ASIWjlW2XfXvmmXYIqfDQ0vToBnO5n63NhJAK+4uj94TOqUZGLzqV2MtTiU43/4uTEFJh3r4y3VEuK25XMYRUWJJcrjsKRdncvaVR/drs6BvGNcGfXc09U//ZxaKMiOzEooyIiChCQqdH9hReflB/fF49hFT41abcKCdzt9CmUM7kAmra+yGkws2zE2GaPJXodLsLrWUUP11zTHeUy3pstXXCRxWf0x2Fomx/cROEVPj3KC2b+Dy4mOUH7x215eOxKCMiO7EoIyIiipAXtxVCSIUNR6sv+/ZlB05DSIWZu6c+nyWWrE6zNrS9tP2E7ijaHa1si+qTW5qas8Fi88ZZiWMu+dDBHzBx8+xECKlQ3danOw5FWc+gD9cH55TVtPdH/PO98MlxCKmw9MBpWz4eizIishOLMiIiogiZt68MQiosTrr8NaaXt5+AkApr0quinMzdQpvSHlvtzFM50fRJTi2EVPgdZ0q5gmmauD04Y6+4oVt3nEtUtfZBSIWvzU6CnzMTY9JTG7LH/OWOXXz+AKbNTYaQCoV19mx8ZlFGRHZiUUZERBQhKw9WQkiF13cWX/bt09dlQUiFfVEcnuwFp5t7IaTCtHnJMX/dcGHiKUfPvKKvenZTLoRU+CirRneUS3xRZF29+zEL6Ji1+dhZCKnwxPqsiH6e0HzOb76RYtsiGxZlRGQnFmVEREQREjrt89yW/Mu+/cK2Qnt+ox4rhnz+8BDo9r5h3XG0Cl1f2phxVncUGqflqRWOvDq8OKkcQirM4FXwmBXaxHzdjAR0D4xE7PO8ud9aavFKfJFtH5NFGRHZiUUZERFRhCSVNkNIhZ9cZnD3qD+A64LzYFrOc1vhRH3rbatkzD3bqTuKVo+uzICQCiknW3RHoXFKP90KIRUefCddd5RL/HqzddJta3at7iikUWhb85WW0NjhoXfSIaRCQol9SyNYlBGRnViUERERRUh+TSeEVHhgSdpX3hb6zf2NMxNtu3oSS34VvL62Pa9OdxSt/vUf1ryr0829uqPQOHUPjEBI60RkJE/tTNRdC1KDJ1xju3yOde8kW0tmXvj0eEQ+fmihxfUzEtA75LPt47IoIyI7sSgjIiKKkOo2azj2v8xN/srbsqs7IKTCdy5TotHVhRYlLEw8pTuKNj2DvnDhMjAyqjsOTcCDwRM16adbdUcBAHT2Xyjv+ob5tRTLTtR3h//eisRm1o0Z1hy0X36QbevHZVFGRHZiUUZERBQhFxcZQz7/JW/7vKABQio8vSFHUzp325JZAyEVfv/R5ee/xYLSxh4IqXDHmym6o9AEvRTceLs8tUJ3FABARmU7i3sCAAQCJu58yzpdeLSyzfaPH6nNmizKiMhOLMqIiIgixDRN3DDTmkPW1D14ydtWpI69EZPGdrSyDUIqfHfZYd1RtEksOXfFGXjkbKGi99ebc3VHAQC8F9zQ++K2Qt1RyAHidhVDSIW5e0tt/bi9Q77w34ln2/tt/dgsyojITizKiIiIIig096ekoeeS1/99ZxGEVHjvYKWmZO7W0GXNeLthZgJG/fZfD3KDdYfPQEiFv37GcsNtioLX226ffwCmqX9GYWjm35bMGt1RyAEOnmqBkAr3LTpk69dnqNyPxCILFmVEZCcWZURERBH0/RVHLzuLKHT9ZNfxBk3J3C0QMHHTrEQIqVDbYe/JBLeYtacEQiq8k3xadxSaoJHRAG4Mfv3afbJmovwBE9PmJkNIhbKmnqu/A3nekM+Pm2dbX58nm+x7nvjqDusXRG/sP2nbxwxhUUZEdmJRRkREFEHPbMyBkAqfF1xaiD2wJA1CKuRUd2hK5n6PLD8CIRXSyp0xED3aQqeA4vPqdUehSfjpmmMQUmF3od6y/GTT+fDwdj838FLQ7z/Kh5AKK1LtOfUcCJi4480UCKmQWdVuy8e8GIsyIrITizIiIqII+utnhRBS4YMjFwYXBwImbpxp/ba+oWtAYzp3+9PHBRBSYWPGWd1RtAhtTsw6w7LVjeZ/cTIic6AmamuWNS/tmY1cLEIXxOfVQ0iFR1dm2PLxIr1Nk0UZEdmJRRkREVEEhZ4ML0w8FX5dy/khCKlw3YzYna9lhyXJ5RBSYdaeEt1Ros4fuLAoovFLiyLIHfYVNUFIhcdW2VNETFaozHfKBk5yhva+YVwTZ21tPtcz9Z8xb+63/i7808cFNqT7KhZlRGQnFmVEREQRtDqtCkIqvLajKPy6gtrO8KBkmrydBQ0QUuGXH2TrjhJ1Td2D4WUGvC7nTvWdFxZSDPn82nLct+gQhFTIqLT/Ohy528/WZkJIhU1TPLXbM+DDrXOSIKTCofIWm9JdikUZEdmJRRkREVEEfZZbByEVfvthXvh1e080QkiF6euyNCZzv+N1XRBS4Z6FB3VHibrs6g4IqfCdJWm6o9AkmaaJb75hzWwqqO3SkqG5xzrdem2cQt/wqJYM5Fyha7n3LDyI4dHJl7nvHayEkAqPLD8SsS2vLMqIyE4syoiIiCIo5WSLdb1q9bHw69akW6fMXo4/oTGZ+3UPjEBI62rQwEhsPckPzQ/iXCl3+92HeVrn7O0vtq5//nDlUS2fn5xtyOfH3QsOQkiFj7JqJvUxBkZG8fX5ByCkwr6iJnsDXoRFGRHZiUUZERFRBBXUWqeevvX2hWuWM3aXQEiFZQdOa0zmDaEnYGVNPbqjRNXbSdZ8tjmaB8HT1Kw6ZJ20eXFboZbPP29fGYRUmLevTMvnJ+cLnSq7a0HqpK4Ib8w4Gz79Gslr4izKiMhOLMqIiIgiqLajH0IqfG12Uvh1z27KhZAK8Xn1GpN5Q2iGzv7iyJ1UcKLQxs+pzg4ivTIq2yGkwrcX65lX+MOVRyGkwhcRPOlD7jY86sc9C61TZVsyayb8vqETadty6yITMIhFGRHZiUUZERFRBPUO+b5yPfC7yw5DSIVjVRyePVWv7iiCkArvHazUHSWqvr/iaEQHY1N0nB/yhTcLdvQNR/Vz9w+P4roZCbZtNSTv2ppdO6lTZdvz6sLvN5UZZ+PBooyI7MSijIiIKIJM08SNsxIhpEJ95wBM08TNs61/rmnv1x3P9ULz3v72mZ6razqYpolbghvkqtv6dMehKQoV5ykno1t6Hqtq5/ZdGpfhUT/uDZ4q23xsfKdY/QETD76TDiEVNhytjnBCFmVEZC8WZURERBEWurZSVN+Njr5hCKlwTZyK+G/YY0FSaTOEVPjRqgzdUaKm5by1qfC6GQkYGQ3ojkNTFJpZGO05YStSrflof9E0H43c5ZMc61TZnW+N71RZaFHE7fMPoD8KG1VZlBGRnViUERERRVhoDtCh8hYU1XeHr6LQ1FW19kFIhVvnJME0Izco2klyqjsgpML9i9N0RyEbJJdZZe+D76RH9fM+szFnStsMKbaMjAZw36JD49rSappm+Hr48tSKqORjUUZEdmJRRkREFGGh4f078uuRUHIOQir8dM0x3bE8wecP4PrgnKWm7tiYsxSa+/OrTbm6o5ANeod84a/h2o7oXMf2B0z8y9xkCKlwsonPA2h8tuVaP3vueDP1ij9vB0f8eC04O/KWOUnoHhiJSjYWZURkJxZlREREEfby9hMQUuH9w2fwwZFqXney2cNLrTk4RyvbdEeJikWJ5RBSYc7eUt1RyCaPr8uCkApbo3S662TTeQipMG1uMvyB2DiJSVM3MhrAtxcfCp/i3ZRx9pKvn6rWPnzv3SMQUuHaOIVPcmqjlo1FGRHZiUUZERFRhL2lTkJIhQUJpzB3bymEVHg7qVx3LM/449b8CQ2Zdrs/fVwAIRU2XeX6E7lHaCnFc1vyovL5PsqqgZAKz2zMicrnI++obuvDz9Zmhrc5P7oyA6WNPdhT2BheMnLnW6nIPBPdrc4syojITizKiIiIImxt+hkIqfBy/Ak8tyUPQip8nB2937R73eIk64TVzN0luqNExSPLrRMbaeWtuqOQTcqaesJX1aKx5OMv2wohpMKK1MqIfy7ynkDAxKc5dbhtXnJ4OU2oOHtyfTZae4einolFGRHZiUUZERFRhMXn10NIhWc35YZLjvTTLDnssut4A4RUeGJ9lu4oEWeaJr422zq1Ud3WpzsO2cQ0Tdz5ViqEVDhWFfmTOKGh7NH4XORdrb1DeDFYul4Tp7AspULbVV4WZURkJxZlREREEXbwVEv4isq04ADtqtZe3bE8o7ihOzxg2utazg9BSIXrZiTA5w/ojkM2ejU4AH1BwqmIfp7ajv7w11D/8GhEPxfFhoLaLpQ09GjNwKKMiOzEooyIiCjCTtRbRc604DUVIRUGRyJ/vSpW9A2Phv9cewZ8uuNEVHZ1B4RUeGBJmu4oZLMvipogpML33j0S0c/z/mHrKvjTGzifjLyDRRkR2YlFGRERUYTVdw6EixwhFb75RoruSJ5zz8KDEFKhoLZLd5SI2p5XByEVfrUpV3cUsllX/wiuDc56OtczGLHP8+PVxzgnkTyHRRkR2YlFGRERUYQNjIxeUpT9aFWG7kie88zGHAipEJ9XrztKRC1KtBYXzN1bqjsKRcBP1lgl1va8uoh8/HM9g+F5UjoGrhNFCosyIrITizIiIqIoCA1gF1Lhvz4p0B3Hc+btK4vKfCfdnt9aACEVNh87qzsKRcDy1IqI/ozYfOwshFT4xfuZEfn4RLqwKCMiO7EoIyIiioLQljkhFd5SJ3XH8Zyt2bUQUuF3H+bpjhJRoa2paeXcmupFF88zHI3AsobH12VBSIWNGSxayVtYlBGRnViUERERRcFjqzLCRdmHPA1ku8wz7Z4fcm+aZvhk4tn2ft1xKAL8ARNfn38AQirk1XTa+rHb+4bDM9AaugZs/dhEurEoI/K+PxuGUWsYxrBhGLmGYdx1lcdPNwzjdPDxpYZh/GACn4tFGRERURT8ZnNuuChLPdmiO47ntPYOQUiFa+MUhnze3Cja3GP9O143IwG+CJw2Imf4y7ZCCKnwTvJpWz/upzl1nJFInsWijMjbnjAMY8QwjN8ahnGrYRgfGIbRbRjG/7jC4+8zDMNvGMbfDcO4xTCMNw3D8BmGMW2cn49FGRERURS8uqMoXJSdOse/d+1mmiZum5cMIRXKm73555td3eH5U3MEfF7QACEVHl1pb6EVWnixJr3K1o9L5AQsyoi8LdcwjNUX/fM/GYbRZBhG3BUeH28YhvrS63IMw1g3zs/HooyIiCgKFiacChdl54d8uuN4Umhj4P7iJt1RIuKzXOtE0LObcnVHoQgKnY4UUuFcz6AtH7NnwIfrZyRASIXqtj5bPiaRk7AoI/Ku/2ZYp8N+8qXXf2QYxr4rvE+9YRgvfel18w3DKB7n52RRRkREFAXrj5yBkAq3zUvWHcWzXgue2lueWqE7SkQsTLTK1rl7S3VHoQibHhy6b9f1y9Apte+9e8SWj0fkNCzKiLzrfxnWN/e9X3r9EsM6aXY5PsMwfvml171gGEbrFR7/3w3rh0fo5X8bLMqIiIgibmfwier3VxzVHcWz1h22ysgXtxXqjhIRz28tgJAKm7kMwvMSS85BSIVvvJFiy8y957bkQ0iFd1O8WSITsSgj8q5oFGX/CH6OS15YlBEREUVWU/cgHlqajo0ZLDkiJfVki6fLyEeWH4GQCmmnW3VHoQgb9Qdw36JDEFIhPr9+Sh+rb3gUN85K9PT8PiIWZUTeFY2rlzxRRkRERJ5U094PIRVumpUIf8DUHcdWpmni5tlW2XG2vV93HIqC94MnJL+/4ihMc/Jfz/uLmyCkwneWpE3p4xA5GYsyIm/LNQxj1UX//E+GYTQaYw/z3/+l12UZHOZPREREMcYfMHHjTKtMqu8c0B3HVs091oD362YkwOcP6I5DUdA9MBIuR3OqOyb9cV745DiEVFiUWG5jOiJnYVFG5G1PGIYxbBjGrw3DuMUwjPWGYXQbhvE/g2/fahjGoosef59hGKOGYbxqGMbXDOtqpc8wjGnj/HwsyoiIiMgzvvdu8HpiubeuJ2ad6QifCqLYMWN3CYRUeH5rwaTev6q1F9cFt12WNPTYnI7IOViUEXnfi4Zh1BmGMWJYJ8zuvuhthw3D2PKlx083DKMi+PgywzB+MIHPxaKMiIiIPCN0euaDI9W6o9jqs9w6CKnw7KZc3VEoiipaeiGkwrVxCg1dEz8l+ZvNuRBS4bkt+RFIR+QcLMqIyE4syoiIiMgzlqVUQEgF+Xmx7ii2Wph4CkIqzNtXpjsKRdnTG3IgpMLChFMTer8jFW0QUuH6GQmobuuLUDoiZ2BRRkR2YlFGREREnrH3RCOEVPj52kzdUWz1x635EFLhw2PcmhprQttcb5uXjIGR0XG9z6g/gP949zCEVJj/xckIJyTSj0UZEdmJRRkRERF5RllTD4RUuH3+AU9t+HtkeXD22mlvzV6jqwsETDywJA1CKnySUzuu9/kkpzb8fdAz4ItwQiL9WJQRkZ1YlBEREZFnDI74cU2cgpAKHX3DuuPYIhAww9sPa9r7dcchDTZlnIWQCvctOoRzPYNjPvb8kA/ffCMFQips5glEihEsyojITizKiIiIyFO+9fYhCKmQU92hO4otmroHw7OmfP6A7jikQe+QD99ebH1d3784DY3dVy7LFiWWQ0iFh5am8+uFYgaLMiKyE4syIiIi8pRfBzf9jfeamtOFhrI/vDRddxTSqLF7EPcvtq5gfuvtQ6jv/OoWzJr2ftw40zp9ePBUi4aURHqwKA579DkAABw8SURBVCMiO7EoIyIiIk95S5301IbI0LW757cW6I5Cmp3rGcR3gvPK7lt0CHUdAwgETGRUtuPPnx4Pl2RPb8jx1Iw+oqthUUZEdmJRRkRERJ6ys6ABQio8sT5LdxRbxO0qgZAKSw+c1h2FHKDl/BAeeicdQirctSA1fCUz9PLYqgzUdXz1tBmRl7EoIyI7sSgjIiIiTylpsDZfft0jmy9/8X4mhFTYe6JRdxRyiNbzQ3h4aXq4HJs2Lxmz95SitLFHdzQiLViUEZGdWJQRERGRpwz5/Lg2uPmytXdId5wpMU0Tt88/ACEVyppYgtAFbb3DWJBwCp8XNGBwxK87DpFWLMqIyE4syoiIiMhzQlfTjla26Y4yJe19wxBS4Zo4hSEfyxAiosthUUZEdmJRRkRERJ7zp48LIKTChqPVuqNMSXZ1B4RUuH9xmu4oRESOxaKMiOzEooyIiIg8592UCgip8OqOIt1RpmRrdi2EVPjth3m6oxARORaLMiKyE4syIiIi8pzEknMQUuFHqzJ0R5mSefvKIKTCwoRTuqMQETkWizIishOLMiIiIvKc6rY+CKlw8+xE+APu3Xz51IZsCKkQn1+vOwoRkWOxKCMiO7EoIyIiIs/xB0zcNCsRQiqcbe/XHWfS/u2tVAipUFjXpTsKEZFjsSgjIjuxKCMiIiJP+uHKoxBSIan0nO4ok9Iz6IOQCkIq9A75dMchInIsFmVEZCcWZURERORJr8QXQUiFFamVuqNMSkFtF4RUuHvBQd1RiIgcjUUZEdmJRRkRERF50gdHqiGkwn99UqA7yqTE59VDSIVnNubojkJE5GgsyojITizKiIiIyJOOVLRBSIWHlqbrjjIpb6mTEFJh3r4y3VGIiByNRRkR2YlFGREREXlSy/khCKlwbZzCkM+vO86E/WZzLoRU+CSnVncUIiJHY1FGRHZiUUZERESeZJombp9/AEIqlDb26I4zYd96+xCEVMip7tAdhYjI0ViUEZGdWJQRERGRZz2+LgtCKnxe0KA7yoQMjIyGN1529o/ojkNE5GgsyojITizKiIiIyLPm7i2FkAoLEk7pjjIhpY09EFLhG2+k6I5CROR4LMqIyE4syoiIiMizPsmphZAKv9qUqzvKhOwubICQCtPXZemOQkTkeCzKiMhOLMqIiIjIswpqOyGkwt0LDuqOMiFLksshpMLM3SW6oxAROR6LMiKyE4syIiIi8qzeIV941lfPgE93nHH7w0f5EFJh87GzuqMQETkeizIishOLMiIiIvK0+xa5b3vkQ0vTIaRCRmW77ihERI7HooyI7MSijIiIiDzttx/mQUiFj7JqdEcZl5HRAK6bkQAhFZp7hnTHISJyPBZlRGQnFmVERETkaW8nuWveV0VLL4RUmDY3GaZp6o5DROR4LMqIyE4syoiIiMjT9p5ohJAKP1+bqTvKuKjicxBS4cerj+mOQkTkCizKiMhOLMqIiIjI08qbz1sntOa544TW8tQKCKnw2o4i3VGIiFyBRRkR2YlFGREREXnayGgA1wdnfjV2D+qOc1V//vQ4hFRYf+SM7ihERK7AooyI7MSijIiIiDzve+8egZAKKSdbdEe5qkeWW1kPlTs/KxGRE7AoIyI7sSgjIiIiz3t1RxGEVFiWUqE7ypiGfH5XnX4jInICFmVEZCcWZUREROR5H2XVQEiF32zO1R1lTMUN3RBS4evzD7hinhoRkROwKCMiO7EoIyIiIs8rrOuCkAp3vJni6ALq05w6CKnwzMYc3VGIiFyDRRkR2YlFGREREXnexVcamxx8pXHm7hIIqbAosVx3FCIi12BRRkR2YlFGREREMeE/VxyFkApJpc26o1zRY6uPQUiF/cVNuqMQEbkGizIishOLMiIiIooJ8vNiCKmwJNmZp7V8/gBunJUIIRVq2vt1xyEicg0WZURkJxZlREREFBM+yal19Pyv8ubzEFJh2txkBALOnaNGROQ0LMqIyE4syoiIiCgmlDT0QEiF2x26UXJnQQOEVHh8XZbuKERErsKijIjsxKKMiIiIYsLIaAA3zrSuNtZ1DOiO8xXz9pVBSIU39p/UHYWIyFVYlBGRnViUERERUcx4bFWGY4fl/+L9TAipsOt4g+4oRESuwqKMiOzEooyIiIhixqw9JRBSYWHCKd1RLhEImLh1ThKEVKho6dUdh4jIVViUEZGdWJQRERFRzIjPq4eQCk+uz9Yd5RLVbX0QUuHm2YkY9Qd0xyEichUWZURkJxZlREREFDNOnXPmZsl9RU0QUuEna47pjkJE5DosyojITizKiIiIKGaM+gO4aZY10L+6rU93nLCFCacgpMLsPaW6oxARuQ6LMiKyE4syIiIiiik/XXMMQirsPdGoO0rYUxuyIaTC9rw63VGIiFyHRRkR2YlFGREREcWUefvKIKTC/P+/vfuPtqsq7AT+xR/oqEXr0hkWcTxBQEEUf6O1zpTaqYJrau1S67R2htiqM1qnU52pR0EUqSJYarGK+At/UEWsxcXUY8JPfUUDBBDQjPwKSBJA+WHA8CskJG/PH+e+cvPyQt57Oe+93Hs/n7X2Ivecfc/erL3Ovfd9zz77/PNPF7orpZRSxsfHy0FHn12quikrb/7VQncHYOAIyoAuCcoAgJHyT5fdVKq6KW84eflCd6WUUsradfeVqm7Kvkd8t2x80EL+ADMlKAO6JCgDAEbKdbfeXaq6Kft/YFnZvAss6L9s5S9KVTflNZ+8YKG7AjCQBGVAlwRlAMBI2bxlvDz7qGWlqpty7a13L3R3yglnX1Oquinv/daPF7orAANJUAZ0SVAGAIycN372wlLVTfnWZTctdFfKki+tKFXdlFMvvHGhuwIwkARlQJcEZQDAyPnr7/y0VHVTPnjmyoXuSnnxR84tVd2UH625c6G7AjCQBGVAlwRlAMDIOfOKm0tVN+V1J/1wQftx2/oNpaqbsvf7mnL/xs0L2heAQSUoA7okKAMARs7P7ri3VHVTnnnk0gV90uT5V99aqropv/uJsQXrA8CgE5QBXRKUAQAjZ3x8vLzwmHNKVTflkhvXLVg/PnnedaWqm/Lu069YsD4ADDpBGdAlQRkAMJLe+fUflapuyonnXrdgfXjLly8pVd2UL/7gZwvWB4BBJygDuiQoAwBG0j9ctLpUdVPe9LkLF6T9BzdvKQd+8KxS1U1ZefOvFqQPAMNAUAZ0SVAGAIyk62+/p1R1U/Y7cmnZsGn+F9K/cu1dpaqb8twPnVU2bxmf9/YBhoWgDOiSoAwAGEnj4+Pl4I+eW6q6KctX3THv7Z88dn2p6qa89auXznvbAMNEUAZ0SVAGAIys//WNy0tVN+WEs6+Z97b/2ykrSlU35RTrkwHsFEEZ0CVBGQAwsr55ydpS1U15/WeWz2u7mzZvKQcctaxUdVN+eovfYQA7Q1AGdElQBgCMrLXr7itV3ZR93v/dcu8DD85bu5etvrNUdVOe/+GzyxbrkwHsFEEZ0CVBGQAw0l7+sfNLVTdl7Nrb563NT39vVanqpvz3Uy+btzYBhpWgDOiSoAwAGGn/5x+vLFXdlGOXXjVvbf7JFy8uVd2Uryy/cd7aBBhWgjKgS4IyAGCknfGjm0pVN+W1n/rBvLS38cEtZf8PtOuTXfOLu+elTYBhJigDuiQoAwBG2s9/dX+p6qbs/b6mrN+wac7bu+TGdaWqm/LCY84p4+PWJwPYWYIyoEuCMgBg5B3yN98vVd2Uc39665y39cnzritV3ZR3fu1Hc94WwCgQlAFdEpQBACPv/d/+SanqphzznZ/OeVt/9PmLSlU35dSLVs95WwCjQFAGdElQBgCMvH++8pZS1U059MQL5rSdBx7cXJ555NJS1U1Zdds9c9oWwKgQlAFdEpQBACPv9rsfKFXdlKpuyp33bpyzdi664Zelqpvy4o+ca30ygI4IyoAuCcoAAEopv/uJsVLVTVm28udz1sYnzrm2VHVT3nXa5XPWBsCoEZQBXRKUAQCUUj545spS1U056syVc9bGH372wlLVTfn6xWvmrA2AUSMoA7okKAMAKKUsW/mLUtVNecXx58/JbZEbNm0u+x3Rrk/2szvu7fz4AKNKUAZ0SVAGAFBKuX/j5vLso5aVqm7KJTeu6/z4y1fdUaq6KQd/1PpkAF0SlAFdEpQBAPS855tXlqpuyvvO+Ennxz6qd2vnu795RefHBhhlgjKgS4IyAICeH/ZmfT33Q2eVDZs2d3bcDZs2l4OOPrtUdVMuuO72zo4LgKAM6JagDACgZ/OW8fKyY88rVd2UpT/p7umXzY9/Xqq6KS879ryyeYvbLgG6JCgDuiQoAwDo87GlV5eqbspbv3ppZ8c8/EsrSlU35eNnXd3ZMQFoCcqALgnKAAD6XHvr3aWqm7LvEd8td967caePd+v6DWXv9zWedgkwRwRlQJcEZQAAk7zmkxeUqm7KqRfeuNPHOnns+lLVTXn9Z5bvfMcA2IagDOiSoAwAYJIvXHBDqeqmvO6kH+7UccbHx8srT/h+qeqmnH7Jmo56B0A/QRnQJUEZAMAkt93dze2Sl6+5s1R1U571gaXl7g2bOuwhABMEZUCXBGUAAFOYWID/b8++ZtbHeP+3f1Kquil/efoVHfYMgH6CMqBLgjIAgCmcecXNpaqb8orjzy/j4+Mzfv+GTZvLcz50Vqnqpixfdccc9BCAUgRlQLcEZQAAU7h/4+Zy4AfboOuSG9fN+P0TQdvLP3Z+2bJl5kEbANMjKAO6JCgDANiO//2PV5aqbsp/PWXFjGeV/ckXL25v3Tzn2jnqHQClCMqAbgnKAAC2Y9Vt95T9jlxaqropX7t49bTfd9XP15fFvYcBrPnlfXPYQwAEZUCXBGUAAA/jCxfcUKq6KQcctays/uWOn4C5fsOm8lsf/16p6qb82VcunYceAow2QRnQJUEZAMDD2LJlvLzxsxeWqm7KG05eXjY/zHpj4+Pj5W1fvfRf1yZbd+/GeewpwGgSlAFdEpQBAOzA2nX3lWcftaxUdVM+9y/Xb7feZ75/fanqpux3xNJy5dq75rGHAKNLUAZ0SVAGADANp61Y868h2LW33r3N/uWr7ih799Ylm8l6ZgDsHEEZ0CVBGQDANIyPj5fDv7SiVHVTDjvxgvKdH99SLrlxXVm77r6y+pf3lhcec06p6qa855tXzvgJmQDMnqAM6JKgDABgmm5dv6EcdPTZpaqbKcuhJ15Q7t+4eaG7CTBSBGVAlwRlAAAzcOXau8r/PO3y8oaTl5f/cPz3yjOPXFqquikvOOacaT0VE4BuCcqALgnKAAB2wvj4eLnrvo1mkgEsEEEZ0CVBGQAAAANLUAZ0SVAGAADAwBKUAV0SlAEAADCwBGVAlwRlAAAADCxBGdAlQRkAAAADS1AGdElQBgAAwMASlMFwenKSrye5O8mvkpyS5Ak7qP+pJNcm2ZBkbZK/T/LEGbYrKAMAAGBgCcpgOC1LcmWSlyZ5RZJVSU57mPrPSXJGkt9Lsk+SVya5Lsk/zbBdQRkAAAADS1AGw+eAtCf1i/u2HZpkPMleMzjOG5NsTPKoGbxHUAYAAMDAEpTB8PnTJHdN2vaoJJuT/MEMjvPWJHfsoM5j0n54TJRFEZQBAAAwoARlMHyOSLvW2GS3J3nHNI/xlCRrknx0B/WOTvsBslURlAEAADCIBGUwOI7LFKHUpLJ/dj4o2yPJirTrnD16B3XNKAMAAGBoCMpgcDw1bRD2cGX37Nytl7+W5MIk5yV57Cz6aI0yAAAABpagDIbPxGL+L+rb9qrseDH/PZJclGQsyeNm2bagDAAAgIElKIPhtCzJ5UkOTvKbSa5Lclrf/kVJruntT9oPgIuT/CTJPkn27CuPnEG7gjIAAAAGlqAMhtOT0wZj9yRZn+RLSZ7Qt39x2hP/kN7rQ7L9dc8Wz6BdQRkAAAADS1AGdElQBgAAwMASlAFdEpQBAAAwsARlQJcEZQAAAAwsQRnQJUEZAAAAA0tQBnRJUAYAAMDAEpQBXdojSbnpppvK+vXrFUVRFEVRFEVRFGWgyk033SQoAzqzOO0HiqIoiqIoiqIoiqIMclkUgJ20Rx76QNlDGbqyyPgObTG2w1uM7XAX4zu8xdgObzG2w12M7/CURUl2C8BO2iPtF8MeC90R5oTxHV7GdngZ2+FmfIeXsR1exna4GV8AtuKLYbgZ3+FlbIeXsR1uxnd4GdvhZWyHm/EFYCu+GIab8R1exnZ4GdvhZnyHl7EdXsZ2uBlfALbymCRH9/7L8DG+w8vYDi9jO9yM7/AytsPL2A434wsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAw4cgkFya5P8mvtlPn6Um+26tze5K/SfKoSXUOSXJ5ko1Jrk+ypPuuspMOSfuY66nKS3p1Fm9n/8vmt6vMwupsO27vm1TnoCQ/SPJAkpuSvHce+8fsLE5ySpIbk2xIckOSDyfZfVId5+3g+vO05+8DSVYkOXhBe8NsvD/JpUnuSfs76cwkz5pUZyzbnqOfnb8ushOOzrZjd03f/scmOSnJuiT3Jjkjyb+b3y4yS6sz9ffnSb39Y1Psc94CjIAPJ3l3kr/N1EHZI5OsTHJukucnOSzJHUmO7auzd5L7esc4IMm7kmxO8uo56zWzsXuSPSeVLyT5WZLdenUWp/0R8DuT6j16nvvKzK1OclS2HrfH9+3fI8mtSb6W5MAk/yVt+P32ee0lM3Voki8neVWSZyR5bZLbkpzQV2dxnLeD6k1pLzC9Jcmzk3w+yV1J/u1CdooZOyvtBcIDkzwv7cXFNdn6M3gs7fj2n6N7zGcnmbWjk/y/bD12T+nbf3KStUlemeRFSS5Ksnx+u8gsPTVbj+t/Svt9ekhv/1ictwAjbUmmDsoOS7IlW18Z+x9J1uehGQ3Hp/0B0e/0tD8c2XU9Ou2V76P6ti1O+wPh+QvRIXbK6iR/+TD735Hkzmw9E+m4bH1VnMHwV2kD7gmL47wdVCuSfLrv9SOS3JJtZ4MyWJ6a9pz8j33bxpKcuCC9YWcdneTK7ex7YpJNSd7Qt23/mNU7qE5Me2fMxAXksThvAUbakkwdlB2TbX8c7J32B8ALeq8vyLZfIm9JG6ax63p92hD0aX3bFqcd27VpQ7Qfpp3Bwq5vddoZY+uSXJE2TOm/RfrUtLcD9fvttOP96/PQP7rzkSSX9b1eHOftINo97ezr103a/tUk/3f+u0OH9k17Tj6nb9tY2hn5v0x7cfFjSR437z1jNo5Oe+fEz9NepPh62mVJknYWWUnypEnvWZP2jg0Gx+5pz88j+raNxXkLMNKWZOqg7PNJzp607XFpfxQc1nt9Xdr1Ofq9plfn33TXRTq2tFf6PSXJe5K8NO26ZcclGY8/ugfBe9LeKnBQ2lmfdyX5RN/+c5J8btJ7np32PD1gHvpHN/ZNexHibX3bnLeDaa+0599vTNr+8bQzzRhMj0jSpA2s+7097ZIUz03y5iQ3J/n2/HaNWTosyRvTfr++Ou3avmuS/FqSP057+/Rkl6S944LB8YdpL17s1bfNeQswRI7L9hdtnyj7T3rPkgjKBtVsxvtpaWeTvX4axz817QLwzL/ZjO2EP03yYJLH9F4LynYtsxnbRWlvCfniNI7vvN31CcqG08lpZ/g+bQf1JmYi7TPXHaJzT0p7weLPIigbJmcn+c4O6jhvAQbYU9P+gfVwZfdJ71kSt14OqtmM91Fpb9GazmLff57kF111lhmZzdhOODDteTrx5DW3Xu5aZjq2e6W9KHFq2hkrO+K83fW59XL4fDrtE4X3nkbdx6f9/PXgo8F0adrb8Nx6ORyqtBeQf38H9Zy3ACNmSR5+Mf/+J3C9PW0INjFT5fi0T8bsd1os5r+r2i3tGhsn7KhizxeSXD533WGOvDntuTsRgk0s5t8fjh4bi/kPgkVpQ7JvpH0S8XQ4bwfDiiSf6nv9iLS39ljMf7DsljYkuyXJftN8z2+m/YP7oLnqFHPmCWm/T/8iDy3m3z9D/1mxmP+gOTrtxaVH7aCe8xZgRDw97ZPSPpjknt6/n5/2R0DS/lG2Mu105OelvYJye9o/sCfsnXaR04+nnQXxzrRXyV1t2TX9TrZ/y97hSf4oD81oOSJt2PKWeesds/EbaZ94+bwkz0gbkt2edmbKhCemXez/1LSzzd6U9rx9+7z2lJlalGRVkvN6/+5/RP0E5+3gelOSB9KO4QFpb4++K1s/aZpd32fSXmz8rWx9jk4sP7FP2pncL0r78I3XJrkhyb/Md0eZlRPSju3iJC9Pcm7aBd6f2tt/ctoZZL+ddowv7BUGwyPSjt9xk7Y7bwFG2Fcy9do4h/TVqdIu+n5/2h8GJ2TbKy6HpH3S3sa0XyJL5qzH7KzTkizfzr7Dk1yVNkBZn3a2wxu2U5ddxwuTXJz2D7UNacfw/Xlo1ueEg9KuW/VA2lkr9Tz2kdlZku2vYTbBeTvY3pX2j7SNacfupQvbHWZhe+fokt7+f5/2j+t1aT9/V6W9uLjHfHeUWTk97RMvN6b97jw9W69R9dgkJ6WdZXZf2sXe9wyD4lVpz9dnTtruvAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6szjJKUluTLIhyQ1JPpxk92m+f7cky5KUJK+bRfuLknwtybpe+yuTvHgWxwEAAACAaRlLsmSK7Ycm+XKSVyV5RpLXJrktyQnTPO67kyzN7IKyX0+yutf+wUn27vVjnxkeBwAAAACmbSxTB2VT+askP5tGvecnuTnJnpk6KHtO2tlm96YN3/4hyVP69h+X5AfT7BMAAAAAdGIs0w/KPpLksh3UeVySq5L8fu/15KDsSUluT3Jskv2TvCDJOUm+11fnqiR/l+RbvbpXJHnbNPsIAAAAALMylukFZfsmWZ8dB1afS/LFvteTg7IPJDl70nue1qv3zN7rB3rl2LRB2tvTrlN2+DT6CQAAAADTckTaWx4nypa0oVT/tqdPes+iJNdn6wBsKq9NsirJE/q2TQ7KvpVk06T27u3VO6xXZ1OSCycd+++TXLSD9gEAAABg2p6cdnbYRFmR5L2Ttj2qr/5eSa5LcmqSR+zg2CcmGU+yua+UtGHcWK/OsiRnTGpvojy+V2dNtg3l3pHklun+TwIAAADATI1l+7deLkobkn0jySOncaw90y7U319Kkr9I++TKJPlokmuydRg32WnZdjH/v8u2s8wAAAAAoDNjmTooW5T2Nsrzev/es6/017kmycEPc/zJt17ulXaB/m8leUmSfZK8OsmX81AY95IkD6a9TXTfJH+c5L4kb57u/xQAAAAAzNRYpg7KlqQNuaYqExb3Xh/yMMefHJQlyX5Jvp3kriT3J7k67Yyx3frq/OckK9Oun3Z1PPUSAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmBf/H+5TpcBTarKxAAAAAElFTkSuQmCC\" width=\"1226\">"
906 ],
907 "text/plain": [
908 "<IPython.core.display.HTML object>"
909 ]
910 },
911 "metadata": {},
912 "output_type": "display_data"
913 },
914 {
915 "data": {
916 "text/plain": [
917 "<matplotlib.axes._subplots.AxesSubplot at 0x7f7d7dc060b8>"
918 ]
919 },
920 "execution_count": 13,
921 "metadata": {},
922 "output_type": "execute_result"
923 }
924 ],
925 "source": [
926 "df[start-100:start+100].plot()"
927 ]
928 },
929 {
930 "cell_type": "markdown",
931 "metadata": {},
932 "source": [
933 "### If start position is good we should get exactly 0"
934 ]
935 },
936 {
937 "cell_type": "code",
938 "execution_count": 14,
939 "metadata": {
940 "ExecuteTime": {
941 "end_time": "2018-04-03T16:04:30.382468Z",
942 "start_time": "2018-04-03T16:04:30.369427Z"
943 }
944 },
945 "outputs": [
946 {
947 "data": {
948 "text/plain": [
949 "0 0.0\n",
950 "Name: 2400000, dtype: float64"
951 ]
952 },
953 "execution_count": 14,
954 "metadata": {},
955 "output_type": "execute_result"
956 }
957 ],
958 "source": [
959 "df.iloc[start]"
960 ]
961 },
962 {
963 "cell_type": "code",
964 "execution_count": 15,
965 "metadata": {
966 "ExecuteTime": {
967 "end_time": "2018-04-03T16:04:30.824264Z",
968 "start_time": "2018-04-03T16:04:30.820242Z"
969 }
970 },
971 "outputs": [
972 {
973 "data": {
974 "text/plain": [
975 "(93600000, (93600000, 1))"
976 ]
977 },
978 "execution_count": 15,
979 "metadata": {},
980 "output_type": "execute_result"
981 }
982 ],
983 "source": [
984 "start + 19*snapshot_width , df.shapez"
985 ]
986 },
987 {
988 "cell_type": "markdown",
989 "metadata": {},
990 "source": [
991 "# Block Design\n",
992 "The idea is to be able to discriminate seconds inside a block (snapshot). The easy solution is to generate steps where the current position inside the block can be deduced by the DC level. \n",
993 "Then in order to cross validate with **TDS** which has high pass filters we also need a higher frequency marker."
994 ]
995 },
996 {
997 "cell_type": "code",
998 "execution_count": 75,
999 "metadata": {
1000 "ExecuteTime": {
1001 "end_time": "2018-04-03T17:35:27.380942Z",
1002 "start_time": "2018-04-03T17:35:27.063793Z"
1003 },
1004 "scrolled": false
1005 },
1006 "outputs": [
1007 {
1008 "data": {
1009 "application/javascript": [
1010 "/* Put everything inside the global mpl namespace */\n",
1011 "window.mpl = {};\n",
1012 "\n",
1013 "\n",
1014 "mpl.get_websocket_type = function() {\n",
1015 " if (typeof(WebSocket) !== 'undefined') {\n",
1016 " return WebSocket;\n",
1017 " } else if (typeof(MozWebSocket) !== 'undefined') {\n",
1018 " return MozWebSocket;\n",
1019 " } else {\n",
1020 " alert('Your browser does not have WebSocket support.' +\n",
1021 " 'Please try Chrome, Safari or Firefox β‰₯ 6. ' +\n",
1022 " 'Firefox 4 and 5 are also supported but you ' +\n",
1023 " 'have to enable WebSockets in about:config.');\n",
1024 " };\n",
1025 "}\n",
1026 "\n",
1027 "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n",
1028 " this.id = figure_id;\n",
1029 "\n",
1030 " this.ws = websocket;\n",
1031 "\n",
1032 " this.supports_binary = (this.ws.binaryType != undefined);\n",
1033 "\n",
1034 " if (!this.supports_binary) {\n",
1035 " var warnings = document.getElementById(\"mpl-warnings\");\n",
1036 " if (warnings) {\n",
1037 " warnings.style.display = 'block';\n",
1038 " warnings.textContent = (\n",
1039 " \"This browser does not support binary websocket messages. \" +\n",
1040 " \"Performance may be slow.\");\n",
1041 " }\n",
1042 " }\n",
1043 "\n",
1044 " this.imageObj = new Image();\n",
1045 "\n",
1046 " this.context = undefined;\n",
1047 " this.message = undefined;\n",
1048 " this.canvas = undefined;\n",
1049 " this.rubberband_canvas = undefined;\n",
1050 " this.rubberband_context = undefined;\n",
1051 " this.format_dropdown = undefined;\n",
1052 "\n",
1053 " this.image_mode = 'full';\n",
1054 "\n",
1055 " this.root = $('<div/>');\n",
1056 " this._root_extra_style(this.root)\n",
1057 " this.root.attr('style', 'display: inline-block');\n",
1058 "\n",
1059 " $(parent_element).append(this.root);\n",
1060 "\n",
1061 " this._init_header(this);\n",
1062 " this._init_canvas(this);\n",
1063 " this._init_toolbar(this);\n",
1064 "\n",
1065 " var fig = this;\n",
1066 "\n",
1067 " this.waiting = false;\n",
1068 "\n",
1069 " this.ws.onopen = function () {\n",
1070 " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n",
1071 " fig.send_message(\"send_image_mode\", {});\n",
1072 " if (mpl.ratio != 1) {\n",
1073 " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n",
1074 " }\n",
1075 " fig.send_message(\"refresh\", {});\n",
1076 " }\n",
1077 "\n",
1078 " this.imageObj.onload = function() {\n",
1079 " if (fig.image_mode == 'full') {\n",
1080 " // Full images could contain transparency (where diff images\n",
1081 " // almost always do), so we need to clear the canvas so that\n",
1082 " // there is no ghosting.\n",
1083 " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
1084 " }\n",
1085 " fig.context.drawImage(fig.imageObj, 0, 0);\n",
1086 " };\n",
1087 "\n",
1088 " this.imageObj.onunload = function() {\n",
1089 " fig.ws.close();\n",
1090 " }\n",
1091 "\n",
1092 " this.ws.onmessage = this._make_on_message_function(this);\n",
1093 "\n",
1094 " this.ondownload = ondownload;\n",
1095 "}\n",
1096 "\n",
1097 "mpl.figure.prototype._init_header = function() {\n",
1098 " var titlebar = $(\n",
1099 " '<div class=\"ui-dialog-titlebar ui-widget-header ui-corner-all ' +\n",
1100 " 'ui-helper-clearfix\"/>');\n",
1101 " var titletext = $(\n",
1102 " '<div class=\"ui-dialog-title\" style=\"width: 100%; ' +\n",
1103 " 'text-align: center; padding: 3px;\"/>');\n",
1104 " titlebar.append(titletext)\n",
1105 " this.root.append(titlebar);\n",
1106 " this.header = titletext[0];\n",
1107 "}\n",
1108 "\n",
1109 "\n",
1110 "\n",
1111 "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n",
1112 "\n",
1113 "}\n",
1114 "\n",
1115 "\n",
1116 "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n",
1117 "\n",
1118 "}\n",
1119 "\n",
1120 "mpl.figure.prototype._init_canvas = function() {\n",
1121 " var fig = this;\n",
1122 "\n",
1123 " var canvas_div = $('<div/>');\n",
1124 "\n",
1125 " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n",
1126 "\n",
1127 " function canvas_keyboard_event(event) {\n",
1128 " return fig.key_event(event, event['data']);\n",
1129 " }\n",
1130 "\n",
1131 " canvas_div.keydown('key_press', canvas_keyboard_event);\n",
1132 " canvas_div.keyup('key_release', canvas_keyboard_event);\n",
1133 " this.canvas_div = canvas_div\n",
1134 " this._canvas_extra_style(canvas_div)\n",
1135 " this.root.append(canvas_div);\n",
1136 "\n",
1137 " var canvas = $('<canvas/>');\n",
1138 " canvas.addClass('mpl-canvas');\n",
1139 " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n",
1140 "\n",
1141 " this.canvas = canvas[0];\n",
1142 " this.context = canvas[0].getContext(\"2d\");\n",
1143 "\n",
1144 " var backingStore = this.context.backingStorePixelRatio ||\n",
1145 "\tthis.context.webkitBackingStorePixelRatio ||\n",
1146 "\tthis.context.mozBackingStorePixelRatio ||\n",
1147 "\tthis.context.msBackingStorePixelRatio ||\n",
1148 "\tthis.context.oBackingStorePixelRatio ||\n",
1149 "\tthis.context.backingStorePixelRatio || 1;\n",
1150 "\n",
1151 " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n",
1152 "\n",
1153 " var rubberband = $('<canvas/>');\n",
1154 " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n",
1155 "\n",
1156 " var pass_mouse_events = true;\n",
1157 "\n",
1158 " canvas_div.resizable({\n",
1159 " start: function(event, ui) {\n",
1160 " pass_mouse_events = false;\n",
1161 " },\n",
1162 " resize: function(event, ui) {\n",
1163 " fig.request_resize(ui.size.width, ui.size.height);\n",
1164 " },\n",
1165 " stop: function(event, ui) {\n",
1166 " pass_mouse_events = true;\n",
1167 " fig.request_resize(ui.size.width, ui.size.height);\n",
1168 " },\n",
1169 " });\n",
1170 "\n",
1171 " function mouse_event_fn(event) {\n",
1172 " if (pass_mouse_events)\n",
1173 " return fig.mouse_event(event, event['data']);\n",
1174 " }\n",
1175 "\n",
1176 " rubberband.mousedown('button_press', mouse_event_fn);\n",
1177 " rubberband.mouseup('button_release', mouse_event_fn);\n",
1178 " // Throttle sequential mouse events to 1 every 20ms.\n",
1179 " rubberband.mousemove('motion_notify', mouse_event_fn);\n",
1180 "\n",
1181 " rubberband.mouseenter('figure_enter', mouse_event_fn);\n",
1182 " rubberband.mouseleave('figure_leave', mouse_event_fn);\n",
1183 "\n",
1184 " canvas_div.on(\"wheel\", function (event) {\n",
1185 " event = event.originalEvent;\n",
1186 " event['data'] = 'scroll'\n",
1187 " if (event.deltaY < 0) {\n",
1188 " event.step = 1;\n",
1189 " } else {\n",
1190 " event.step = -1;\n",
1191 " }\n",
1192 " mouse_event_fn(event);\n",
1193 " });\n",
1194 "\n",
1195 " canvas_div.append(canvas);\n",
1196 " canvas_div.append(rubberband);\n",
1197 "\n",
1198 " this.rubberband = rubberband;\n",
1199 " this.rubberband_canvas = rubberband[0];\n",
1200 " this.rubberband_context = rubberband[0].getContext(\"2d\");\n",
1201 " this.rubberband_context.strokeStyle = \"#000000\";\n",
1202 "\n",
1203 " this._resize_canvas = function(width, height) {\n",
1204 " // Keep the size of the canvas, canvas container, and rubber band\n",
1205 " // canvas in synch.\n",
1206 " canvas_div.css('width', width)\n",
1207 " canvas_div.css('height', height)\n",
1208 "\n",
1209 " canvas.attr('width', width * mpl.ratio);\n",
1210 " canvas.attr('height', height * mpl.ratio);\n",
1211 " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n",
1212 "\n",
1213 " rubberband.attr('width', width);\n",
1214 " rubberband.attr('height', height);\n",
1215 " }\n",
1216 "\n",
1217 " // Set the figure to an initial 600x600px, this will subsequently be updated\n",
1218 " // upon first draw.\n",
1219 " this._resize_canvas(600, 600);\n",
1220 "\n",
1221 " // Disable right mouse context menu.\n",
1222 " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n",
1223 " return false;\n",
1224 " });\n",
1225 "\n",
1226 " function set_focus () {\n",
1227 " canvas.focus();\n",
1228 " canvas_div.focus();\n",
1229 " }\n",
1230 "\n",
1231 " window.setTimeout(set_focus, 100);\n",
1232 "}\n",
1233 "\n",
1234 "mpl.figure.prototype._init_toolbar = function() {\n",
1235 " var fig = this;\n",
1236 "\n",
1237 " var nav_element = $('<div/>')\n",
1238 " nav_element.attr('style', 'width: 100%');\n",
1239 " this.root.append(nav_element);\n",
1240 "\n",
1241 " // Define a callback function for later on.\n",
1242 " function toolbar_event(event) {\n",
1243 " return fig.toolbar_button_onclick(event['data']);\n",
1244 " }\n",
1245 " function toolbar_mouse_event(event) {\n",
1246 " return fig.toolbar_button_onmouseover(event['data']);\n",
1247 " }\n",
1248 "\n",
1249 " for(var toolbar_ind in mpl.toolbar_items) {\n",
1250 " var name = mpl.toolbar_items[toolbar_ind][0];\n",
1251 " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
1252 " var image = mpl.toolbar_items[toolbar_ind][2];\n",
1253 " var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
1254 "\n",
1255 " if (!name) {\n",
1256 " // put a spacer in here.\n",
1257 " continue;\n",
1258 " }\n",
1259 " var button = $('<button/>');\n",
1260 " button.addClass('ui-button ui-widget ui-state-default ui-corner-all ' +\n",
1261 " 'ui-button-icon-only');\n",
1262 " button.attr('role', 'button');\n",
1263 " button.attr('aria-disabled', 'false');\n",
1264 " button.click(method_name, toolbar_event);\n",
1265 " button.mouseover(tooltip, toolbar_mouse_event);\n",
1266 "\n",
1267 " var icon_img = $('<span/>');\n",
1268 " icon_img.addClass('ui-button-icon-primary ui-icon');\n",
1269 " icon_img.addClass(image);\n",
1270 " icon_img.addClass('ui-corner-all');\n",
1271 "\n",
1272 " var tooltip_span = $('<span/>');\n",
1273 " tooltip_span.addClass('ui-button-text');\n",
1274 " tooltip_span.html(tooltip);\n",
1275 "\n",
1276 " button.append(icon_img);\n",
1277 " button.append(tooltip_span);\n",
1278 "\n",
1279 " nav_element.append(button);\n",
1280 " }\n",
1281 "\n",
1282 " var fmt_picker_span = $('<span/>');\n",
1283 "\n",
1284 " var fmt_picker = $('<select/>');\n",
1285 " fmt_picker.addClass('mpl-toolbar-option ui-widget ui-widget-content');\n",
1286 " fmt_picker_span.append(fmt_picker);\n",
1287 " nav_element.append(fmt_picker_span);\n",
1288 " this.format_dropdown = fmt_picker[0];\n",
1289 "\n",
1290 " for (var ind in mpl.extensions) {\n",
1291 " var fmt = mpl.extensions[ind];\n",
1292 " var option = $(\n",
1293 " '<option/>', {selected: fmt === mpl.default_extension}).html(fmt);\n",
1294 " fmt_picker.append(option)\n",
1295 " }\n",
1296 "\n",
1297 " // Add hover states to the ui-buttons\n",
1298 " $( \".ui-button\" ).hover(\n",
1299 " function() { $(this).addClass(\"ui-state-hover\");},\n",
1300 " function() { $(this).removeClass(\"ui-state-hover\");}\n",
1301 " );\n",
1302 "\n",
1303 " var status_bar = $('<span class=\"mpl-message\"/>');\n",
1304 " nav_element.append(status_bar);\n",
1305 " this.message = status_bar[0];\n",
1306 "}\n",
1307 "\n",
1308 "mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n",
1309 " // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n",
1310 " // which will in turn request a refresh of the image.\n",
1311 " this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n",
1312 "}\n",
1313 "\n",
1314 "mpl.figure.prototype.send_message = function(type, properties) {\n",
1315 " properties['type'] = type;\n",
1316 " properties['figure_id'] = this.id;\n",
1317 " this.ws.send(JSON.stringify(properties));\n",
1318 "}\n",
1319 "\n",
1320 "mpl.figure.prototype.send_draw_message = function() {\n",
1321 " if (!this.waiting) {\n",
1322 " this.waiting = true;\n",
1323 " this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n",
1324 " }\n",
1325 "}\n",
1326 "\n",
1327 "\n",
1328 "mpl.figure.prototype.handle_save = function(fig, msg) {\n",
1329 " var format_dropdown = fig.format_dropdown;\n",
1330 " var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n",
1331 " fig.ondownload(fig, format);\n",
1332 "}\n",
1333 "\n",
1334 "\n",
1335 "mpl.figure.prototype.handle_resize = function(fig, msg) {\n",
1336 " var size = msg['size'];\n",
1337 " if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n",
1338 " fig._resize_canvas(size[0], size[1]);\n",
1339 " fig.send_message(\"refresh\", {});\n",
1340 " };\n",
1341 "}\n",
1342 "\n",
1343 "mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n",
1344 " var x0 = msg['x0'] / mpl.ratio;\n",
1345 " var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n",
1346 " var x1 = msg['x1'] / mpl.ratio;\n",
1347 " var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n",
1348 " x0 = Math.floor(x0) + 0.5;\n",
1349 " y0 = Math.floor(y0) + 0.5;\n",
1350 " x1 = Math.floor(x1) + 0.5;\n",
1351 " y1 = Math.floor(y1) + 0.5;\n",
1352 " var min_x = Math.min(x0, x1);\n",
1353 " var min_y = Math.min(y0, y1);\n",
1354 " var width = Math.abs(x1 - x0);\n",
1355 " var height = Math.abs(y1 - y0);\n",
1356 "\n",
1357 " fig.rubberband_context.clearRect(\n",
1358 " 0, 0, fig.canvas.width, fig.canvas.height);\n",
1359 "\n",
1360 " fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
1361 "}\n",
1362 "\n",
1363 "mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n",
1364 " // Updates the figure title.\n",
1365 " fig.header.textContent = msg['label'];\n",
1366 "}\n",
1367 "\n",
1368 "mpl.figure.prototype.handle_cursor = function(fig, msg) {\n",
1369 " var cursor = msg['cursor'];\n",
1370 " switch(cursor)\n",
1371 " {\n",
1372 " case 0:\n",
1373 " cursor = 'pointer';\n",
1374 " break;\n",
1375 " case 1:\n",
1376 " cursor = 'default';\n",
1377 " break;\n",
1378 " case 2:\n",
1379 " cursor = 'crosshair';\n",
1380 " break;\n",
1381 " case 3:\n",
1382 " cursor = 'move';\n",
1383 " break;\n",
1384 " }\n",
1385 " fig.rubberband_canvas.style.cursor = cursor;\n",
1386 "}\n",
1387 "\n",
1388 "mpl.figure.prototype.handle_message = function(fig, msg) {\n",
1389 " fig.message.textContent = msg['message'];\n",
1390 "}\n",
1391 "\n",
1392 "mpl.figure.prototype.handle_draw = function(fig, msg) {\n",
1393 " // Request the server to send over a new figure.\n",
1394 " fig.send_draw_message();\n",
1395 "}\n",
1396 "\n",
1397 "mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n",
1398 " fig.image_mode = msg['mode'];\n",
1399 "}\n",
1400 "\n",
1401 "mpl.figure.prototype.updated_canvas_event = function() {\n",
1402 " // Called whenever the canvas gets updated.\n",
1403 " this.send_message(\"ack\", {});\n",
1404 "}\n",
1405 "\n",
1406 "// A function to construct a web socket function for onmessage handling.\n",
1407 "// Called in the figure constructor.\n",
1408 "mpl.figure.prototype._make_on_message_function = function(fig) {\n",
1409 " return function socket_on_message(evt) {\n",
1410 " if (evt.data instanceof Blob) {\n",
1411 " /* FIXME: We get \"Resource interpreted as Image but\n",
1412 " * transferred with MIME type text/plain:\" errors on\n",
1413 " * Chrome. But how to set the MIME type? It doesn't seem\n",
1414 " * to be part of the websocket stream */\n",
1415 " evt.data.type = \"image/png\";\n",
1416 "\n",
1417 " /* Free the memory for the previous frames */\n",
1418 " if (fig.imageObj.src) {\n",
1419 " (window.URL || window.webkitURL).revokeObjectURL(\n",
1420 " fig.imageObj.src);\n",
1421 " }\n",
1422 "\n",
1423 " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
1424 " evt.data);\n",
1425 " fig.updated_canvas_event();\n",
1426 " fig.waiting = false;\n",
1427 " return;\n",
1428 " }\n",
1429 " else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n",
1430 " fig.imageObj.src = evt.data;\n",
1431 " fig.updated_canvas_event();\n",
1432 " fig.waiting = false;\n",
1433 " return;\n",
1434 " }\n",
1435 "\n",
1436 " var msg = JSON.parse(evt.data);\n",
1437 " var msg_type = msg['type'];\n",
1438 "\n",
1439 " // Call the \"handle_{type}\" callback, which takes\n",
1440 " // the figure and JSON message as its only arguments.\n",
1441 " try {\n",
1442 " var callback = fig[\"handle_\" + msg_type];\n",
1443 " } catch (e) {\n",
1444 " console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n",
1445 " return;\n",
1446 " }\n",
1447 "\n",
1448 " if (callback) {\n",
1449 " try {\n",
1450 " // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n",
1451 " callback(fig, msg);\n",
1452 " } catch (e) {\n",
1453 " console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n",
1454 " }\n",
1455 " }\n",
1456 " };\n",
1457 "}\n",
1458 "\n",
1459 "// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n",
1460 "mpl.findpos = function(e) {\n",
1461 " //this section is from http://www.quirksmode.org/js/events_properties.html\n",
1462 " var targ;\n",
1463 " if (!e)\n",
1464 " e = window.event;\n",
1465 " if (e.target)\n",
1466 " targ = e.target;\n",
1467 " else if (e.srcElement)\n",
1468 " targ = e.srcElement;\n",
1469 " if (targ.nodeType == 3) // defeat Safari bug\n",
1470 " targ = targ.parentNode;\n",
1471 "\n",
1472 " // jQuery normalizes the pageX and pageY\n",
1473 " // pageX,Y are the mouse positions relative to the document\n",
1474 " // offset() returns the position of the element relative to the document\n",
1475 " var x = e.pageX - $(targ).offset().left;\n",
1476 " var y = e.pageY - $(targ).offset().top;\n",
1477 "\n",
1478 " return {\"x\": x, \"y\": y};\n",
1479 "};\n",
1480 "\n",
1481 "/*\n",
1482 " * return a copy of an object with only non-object keys\n",
1483 " * we need this to avoid circular references\n",
1484 " * http://stackoverflow.com/a/24161582/3208463\n",
1485 " */\n",
1486 "function simpleKeys (original) {\n",
1487 " return Object.keys(original).reduce(function (obj, key) {\n",
1488 " if (typeof original[key] !== 'object')\n",
1489 " obj[key] = original[key]\n",
1490 " return obj;\n",
1491 " }, {});\n",
1492 "}\n",
1493 "\n",
1494 "mpl.figure.prototype.mouse_event = function(event, name) {\n",
1495 " var canvas_pos = mpl.findpos(event)\n",
1496 "\n",
1497 " if (name === 'button_press')\n",
1498 " {\n",
1499 " this.canvas.focus();\n",
1500 " this.canvas_div.focus();\n",
1501 " }\n",
1502 "\n",
1503 " var x = canvas_pos.x * mpl.ratio;\n",
1504 " var y = canvas_pos.y * mpl.ratio;\n",
1505 "\n",
1506 " this.send_message(name, {x: x, y: y, button: event.button,\n",
1507 " step: event.step,\n",
1508 " guiEvent: simpleKeys(event)});\n",
1509 "\n",
1510 " /* This prevents the web browser from automatically changing to\n",
1511 " * the text insertion cursor when the button is pressed. We want\n",
1512 " * to control all of the cursor setting manually through the\n",
1513 " * 'cursor' event from matplotlib */\n",
1514 " event.preventDefault();\n",
1515 " return false;\n",
1516 "}\n",
1517 "\n",
1518 "mpl.figure.prototype._key_event_extra = function(event, name) {\n",
1519 " // Handle any extra behaviour associated with a key event\n",
1520 "}\n",
1521 "\n",
1522 "mpl.figure.prototype.key_event = function(event, name) {\n",
1523 "\n",
1524 " // Prevent repeat events\n",
1525 " if (name == 'key_press')\n",
1526 " {\n",
1527 " if (event.which === this._key)\n",
1528 " return;\n",
1529 " else\n",
1530 " this._key = event.which;\n",
1531 " }\n",
1532 " if (name == 'key_release')\n",
1533 " this._key = null;\n",
1534 "\n",
1535 " var value = '';\n",
1536 " if (event.ctrlKey && event.which != 17)\n",
1537 " value += \"ctrl+\";\n",
1538 " if (event.altKey && event.which != 18)\n",
1539 " value += \"alt+\";\n",
1540 " if (event.shiftKey && event.which != 16)\n",
1541 " value += \"shift+\";\n",
1542 "\n",
1543 " value += 'k';\n",
1544 " value += event.which.toString();\n",
1545 "\n",
1546 " this._key_event_extra(event, name);\n",
1547 "\n",
1548 " this.send_message(name, {key: value,\n",
1549 " guiEvent: simpleKeys(event)});\n",
1550 " return false;\n",
1551 "}\n",
1552 "\n",
1553 "mpl.figure.prototype.toolbar_button_onclick = function(name) {\n",
1554 " if (name == 'download') {\n",
1555 " this.handle_save(this, null);\n",
1556 " } else {\n",
1557 " this.send_message(\"toolbar_button\", {name: name});\n",
1558 " }\n",
1559 "};\n",
1560 "\n",
1561 "mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n",
1562 " this.message.textContent = tooltip;\n",
1563 "};\n",
1564 "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",
1565 "\n",
1566 "mpl.extensions = [\"eps\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
1567 "\n",
1568 "mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n",
1569 " // Create a \"websocket\"-like object which calls the given IPython comm\n",
1570 " // object with the appropriate methods. Currently this is a non binary\n",
1571 " // socket, so there is still some room for performance tuning.\n",
1572 " var ws = {};\n",
1573 "\n",
1574 " ws.close = function() {\n",
1575 " comm.close()\n",
1576 " };\n",
1577 " ws.send = function(m) {\n",
1578 " //console.log('sending', m);\n",
1579 " comm.send(m);\n",
1580 " };\n",
1581 " // Register the callback with on_msg.\n",
1582 " comm.on_msg(function(msg) {\n",
1583 " //console.log('receiving', msg['content']['data'], msg);\n",
1584 " // Pass the mpl event to the overriden (by mpl) onmessage function.\n",
1585 " ws.onmessage(msg['content']['data'])\n",
1586 " });\n",
1587 " return ws;\n",
1588 "}\n",
1589 "\n",
1590 "mpl.mpl_figure_comm = function(comm, msg) {\n",
1591 " // This is the function which gets called when the mpl process\n",
1592 " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
1593 "\n",
1594 " var id = msg.content.data.id;\n",
1595 " // Get hold of the div created by the display call when the Comm\n",
1596 " // socket was opened in Python.\n",
1597 " var element = $(\"#\" + id);\n",
1598 " var ws_proxy = comm_websocket_adapter(comm)\n",
1599 "\n",
1600 " function ondownload(figure, format) {\n",
1601 " window.open(figure.imageObj.src);\n",
1602 " }\n",
1603 "\n",
1604 " var fig = new mpl.figure(id, ws_proxy,\n",
1605 " ondownload,\n",
1606 " element.get(0));\n",
1607 "\n",
1608 " // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n",
1609 " // web socket which is closed, not our websocket->open comm proxy.\n",
1610 " ws_proxy.onopen();\n",
1611 "\n",
1612 " fig.parent_element = element.get(0);\n",
1613 " fig.cell_info = mpl.find_output_cell(\"<div id='\" + id + \"'></div>\");\n",
1614 " if (!fig.cell_info) {\n",
1615 " console.error(\"Failed to find cell for figure\", id, fig);\n",
1616 " return;\n",
1617 " }\n",
1618 "\n",
1619 " var output_index = fig.cell_info[2]\n",
1620 " var cell = fig.cell_info[0];\n",
1621 "\n",
1622 "};\n",
1623 "\n",
1624 "mpl.figure.prototype.handle_close = function(fig, msg) {\n",
1625 " var width = fig.canvas.width/mpl.ratio\n",
1626 " fig.root.unbind('remove')\n",
1627 "\n",
1628 " // Update the output cell to use the data from the current canvas.\n",
1629 " fig.push_to_output();\n",
1630 " var dataURL = fig.canvas.toDataURL();\n",
1631 " // Re-enable the keyboard manager in IPython - without this line, in FF,\n",
1632 " // the notebook keyboard shortcuts fail.\n",
1633 " IPython.keyboard_manager.enable()\n",
1634 " $(fig.parent_element).html('<img src=\"' + dataURL + '\" width=\"' + width + '\">');\n",
1635 " fig.close_ws(fig, msg);\n",
1636 "}\n",
1637 "\n",
1638 "mpl.figure.prototype.close_ws = function(fig, msg){\n",
1639 " fig.send_message('closing', msg);\n",
1640 " // fig.ws.close()\n",
1641 "}\n",
1642 "\n",
1643 "mpl.figure.prototype.push_to_output = function(remove_interactive) {\n",
1644 " // Turn the data on the canvas into data in the output cell.\n",
1645 " var width = this.canvas.width/mpl.ratio\n",
1646 " var dataURL = this.canvas.toDataURL();\n",
1647 " this.cell_info[1]['text/html'] = '<img src=\"' + dataURL + '\" width=\"' + width + '\">';\n",
1648 "}\n",
1649 "\n",
1650 "mpl.figure.prototype.updated_canvas_event = function() {\n",
1651 " // Tell IPython that the notebook contents must change.\n",
1652 " IPython.notebook.set_dirty(true);\n",
1653 " this.send_message(\"ack\", {});\n",
1654 " var fig = this;\n",
1655 " // Wait a second, then push the new image to the DOM so\n",
1656 " // that it is saved nicely (might be nice to debounce this).\n",
1657 " setTimeout(function () { fig.push_to_output() }, 1000);\n",
1658 "}\n",
1659 "\n",
1660 "mpl.figure.prototype._init_toolbar = function() {\n",
1661 " var fig = this;\n",
1662 "\n",
1663 " var nav_element = $('<div/>')\n",
1664 " nav_element.attr('style', 'width: 100%');\n",
1665 " this.root.append(nav_element);\n",
1666 "\n",
1667 " // Define a callback function for later on.\n",
1668 " function toolbar_event(event) {\n",
1669 " return fig.toolbar_button_onclick(event['data']);\n",
1670 " }\n",
1671 " function toolbar_mouse_event(event) {\n",
1672 " return fig.toolbar_button_onmouseover(event['data']);\n",
1673 " }\n",
1674 "\n",
1675 " for(var toolbar_ind in mpl.toolbar_items){\n",
1676 " var name = mpl.toolbar_items[toolbar_ind][0];\n",
1677 " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
1678 " var image = mpl.toolbar_items[toolbar_ind][2];\n",
1679 " var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
1680 "\n",
1681 " if (!name) { continue; };\n",
1682 "\n",
1683 " var button = $('<button class=\"btn btn-default\" href=\"#\" title=\"' + name + '\"><i class=\"fa ' + image + ' fa-lg\"></i></button>');\n",
1684 " button.click(method_name, toolbar_event);\n",
1685 " button.mouseover(tooltip, toolbar_mouse_event);\n",
1686 " nav_element.append(button);\n",
1687 " }\n",
1688 "\n",
1689 " // Add the status bar.\n",
1690 " var status_bar = $('<span class=\"mpl-message\" style=\"text-align:right; float: right;\"/>');\n",
1691 " nav_element.append(status_bar);\n",
1692 " this.message = status_bar[0];\n",
1693 "\n",
1694 " // Add the close button to the window.\n",
1695 " var buttongrp = $('<div class=\"btn-group inline pull-right\"></div>');\n",
1696 " 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",
1697 " button.click(function (evt) { fig.handle_close(fig, {}); } );\n",
1698 " button.mouseover('Stop Interaction', toolbar_mouse_event);\n",
1699 " buttongrp.append(button);\n",
1700 " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n",
1701 " titlebar.prepend(buttongrp);\n",
1702 "}\n",
1703 "\n",
1704 "mpl.figure.prototype._root_extra_style = function(el){\n",
1705 " var fig = this\n",
1706 " el.on(\"remove\", function(){\n",
1707 "\tfig.close_ws(fig, {});\n",
1708 " });\n",
1709 "}\n",
1710 "\n",
1711 "mpl.figure.prototype._canvas_extra_style = function(el){\n",
1712 " // this is important to make the div 'focusable\n",
1713 " el.attr('tabindex', 0)\n",
1714 " // reach out to IPython and tell the keyboard manager to turn it's self\n",
1715 " // off when our div gets focus\n",
1716 "\n",
1717 " // location in version 3\n",
1718 " if (IPython.notebook.keyboard_manager) {\n",
1719 " IPython.notebook.keyboard_manager.register_events(el);\n",
1720 " }\n",
1721 " else {\n",
1722 " // location in version 2\n",
1723 " IPython.keyboard_manager.register_events(el);\n",
1724 " }\n",
1725 "\n",
1726 "}\n",
1727 "\n",
1728 "mpl.figure.prototype._key_event_extra = function(event, name) {\n",
1729 " var manager = IPython.notebook.keyboard_manager;\n",
1730 " if (!manager)\n",
1731 " manager = IPython.keyboard_manager;\n",
1732 "\n",
1733 " // Check for shift+enter\n",
1734 " if (event.shiftKey && event.which == 13) {\n",
1735 " this.canvas_div.blur();\n",
1736 " event.shiftKey = false;\n",
1737 " // Send a \"J\" for go to next cell\n",
1738 " event.which = 74;\n",
1739 " event.keyCode = 74;\n",
1740 " manager.command_mode();\n",
1741 " manager.handle_keydown(event);\n",
1742 " }\n",
1743 "}\n",
1744 "\n",
1745 "mpl.figure.prototype.handle_save = function(fig, msg) {\n",
1746 " fig.ondownload(fig, null);\n",
1747 "}\n",
1748 "\n",
1749 "\n",
1750 "mpl.find_output_cell = function(html_output) {\n",
1751 " // Return the cell and output element which can be found *uniquely* in the notebook.\n",
1752 " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n",
1753 " // IPython event is triggered only after the cells have been serialised, which for\n",
1754 " // our purposes (turning an active figure into a static one), is too late.\n",
1755 " var cells = IPython.notebook.get_cells();\n",
1756 " var ncells = cells.length;\n",
1757 " for (var i=0; i<ncells; i++) {\n",
1758 " var cell = cells[i];\n",
1759 " if (cell.cell_type === 'code'){\n",
1760 " for (var j=0; j<cell.output_area.outputs.length; j++) {\n",
1761 " var data = cell.output_area.outputs[j];\n",
1762 " if (data.data) {\n",
1763 " // IPython >= 3 moved mimebundle to data attribute of output\n",
1764 " data = data.data;\n",
1765 " }\n",
1766 " if (data['text/html'] == html_output) {\n",
1767 " return [cell, data, j];\n",
1768 " }\n",
1769 " }\n",
1770 " }\n",
1771 " }\n",
1772 "}\n",
1773 "\n",
1774 "// Register the function which deals with the matplotlib target/channel.\n",
1775 "// The kernel may be null if the page has been refreshed.\n",
1776 "if (IPython.notebook.kernel != null) {\n",
1777 " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n",
1778 "}\n"
1779 ],
1780 "text/plain": [
1781 "<IPython.core.display.Javascript object>"
1782 ]
1783 },
1784 "metadata": {},
1785 "output_type": "display_data"
1786 },
1787 {
1788 "data": {
1789 "text/html": [
1790 "<img src=\"data:image/png;base64,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\" width=\"1400\">"
1791 ],
1792 "text/plain": [
1793 "<IPython.core.display.HTML object>"
1794 ]
1795 },
1796 "metadata": {},
1797 "output_type": "display_data"
1798 }
1799 ],
1800 "source": [
1801 "volatge_range = (-1., 1.) # normalized to -1.0 to 1.0 \n",
1802 "steps = 22\n",
1803 "voltage_step = (volatge_range[1]-volatge_range[0]-0.2)/(steps-1)\n",
1804 "frequency_range = (48.,48.+22*12)\n",
1805 "frequency_step = 12.\n",
1806 "\n",
1807 "block = 9999.*np.ones(snapshot_width) # set 9999 to see unset data normaly once updated, it should fit [-1.;1.] range\n",
1808 "for sec_idx in range(22):\n",
1809 " block_idx_slice = slice(sec_idx*second_width,(sec_idx+1)*second_width,1) \n",
1810 " block[block_idx_slice] = volatge_range[0] + (sec_idx * voltage_step) + 0.1\n",
1811 " N = len(block[block_idx_slice])\n",
1812 " F = (frequency_range[0] + ( 12. * sec_idx )) #/ SAMPLING_FREQ\n",
1813 " block[block_idx_slice] += 0.1*np.sin( 2 * np.pi / N * F * np.arange(N))\n",
1814 " \n",
1815 "plt.figure(figsize=(14,6))\n",
1816 "plt.plot(block)\n",
1817 "plt.show()"
1818 ]
1819 },
1820 {
1821 "cell_type": "code",
1822 "execution_count": 94,
1823 "metadata": {
1824 "ExecuteTime": {
1825 "end_time": "2018-04-05T10:26:06.813157Z",
1826 "start_time": "2018-04-05T10:26:06.377816Z"
1827 }
1828 },
1829 "outputs": [
1830 {
1831 "data": {
1832 "text/plain": [
1833 "(0.9999999999066982, -0.9999999999896335)"
1834 ]
1835 },
1836 "execution_count": 94,
1837 "metadata": {},
1838 "output_type": "execute_result"
1839 }
1840 ],
1841 "source": [
1842 "max(block),min(block)"
1843 ]
1844 },
1845 {
1846 "cell_type": "code",
1847 "execution_count": 90,
1848 "metadata": {
1849 "ExecuteTime": {
1850 "end_time": "2018-04-05T10:24:52.805851Z",
1851 "start_time": "2018-04-05T10:24:46.480886Z"
1852 }
1853 },
1854 "outputs": [],
1855 "source": [
1856 "block_ascii = \"\"\n",
1857 "for sample in block:\n",
1858 " block_ascii+=\"{:1.6f}\\n\".format(sample)\n",
1859 "\n",
1860 "with open('multisin_paquet2_synchro.csv','w') as multisin:\n",
1861 " multisin.write(\"\"\"waveformName,Multisine_paquet2\n",
1862 "waveformPoints,93600000\n",
1863 "waveformType,WAVE_ANALOG_16\n",
1864 "\"\"\")\n",
1865 " for i in range(start):\n",
1866 " multisin.write(\"0.100000\\n\")\n",
1867 " for blk in range(19):\n",
1868 " multisin.write(block_ascii)\n",
1869 " "
1870 ]
1871 },
1872 {
1873 "cell_type": "code",
1874 "execution_count": 95,
1875 "metadata": {
1876 "ExecuteTime": {
1877 "end_time": "2018-04-05T10:27:57.867698Z",
1878 "start_time": "2018-04-05T10:27:50.128517Z"
1879 }
1880 },
1881 "outputs": [
1882 {
1883 "name": "stdout",
1884 "output_type": "stream",
1885 "text": [
1886 "unix2dos: conversion du fichier multisin_paquet2_synchro.csv au format DOS…\r\n"
1887 ]
1888 }
1889 ],
1890 "source": [
1891 "!unix2dos multisin_paquet2_synchro.csv"
1892 ]
1893 },
1894 {
1895 "cell_type": "code",
1896 "execution_count": 96,
1897 "metadata": {
1898 "ExecuteTime": {
1899 "end_time": "2018-04-05T10:29:22.060090Z",
1900 "start_time": "2018-04-05T10:28:36.658160Z"
1901 }
1902 },
1903 "outputs": [
1904 {
1905 "name": "stdout",
1906 "output_type": "stream",
1907 "text": [
1908 " adding: multisin_paquet2_synchro.csv (deflated 70%)\n"
1909 ]
1910 }
1911 ],
1912 "source": [
1913 "!zip multisin_paquet2_synchro.zip multisin_paquet2_synchro.csv"
1914 ]
1915 }
1916 ],
1917 "metadata": {
1918 "kernelspec": {
1919 "display_name": "Python 3",
1920 "language": "python",
1921 "name": "python3"
1922 },
1923 "language_info": {
1924 "codemirror_mode": {
1925 "name": "ipython",
1926 "version": 3
1927 },
1928 "file_extension": ".py",
1929 "mimetype": "text/x-python",
1930 "name": "python",
1931 "nbconvert_exporter": "python",
1932 "pygments_lexer": "ipython3",
1933 "version": "3.6.4"
1934 },
1935 "toc": {
1936 "colors": {
1937 "hover_highlight": "#DAA520",
1938 "navigate_num": "#000000",
1939 "navigate_text": "#333333",
1940 "running_highlight": "#FF0000",
1941 "selected_highlight": "#FFD700",
1942 "sidebar_border": "#EEEEEE",
1943 "wrapper_background": "#FFFFFF"
1944 },
1945 "moveMenuLeft": true,
1946 "nav_menu": {
1947 "height": "118px",
1948 "width": "252px"
1949 },
1950 "navigate_menu": true,
1951 "number_sections": true,
1952 "sideBar": true,
1953 "threshold": 4,
1954 "toc_cell": false,
1955 "toc_section_display": "block",
1956 "toc_window_display": false,
1957 "widenNotebook": false
1958 },
1959 "varInspector": {
1960 "cols": {
1961 "lenName": 16,
1962 "lenType": 16,
1963 "lenVar": 40
1964 },
1965 "kernels_config": {
1966 "python": {
1967 "delete_cmd_postfix": "",
1968 "delete_cmd_prefix": "del ",
1969 "library": "var_list.py",
1970 "varRefreshCmd": "print(var_dic_list())"
1971 },
1972 "r": {
1973 "delete_cmd_postfix": ") ",
1974 "delete_cmd_prefix": "rm(",
1975 "library": "var_list.r",
1976 "varRefreshCmd": "cat(var_dic_list()) "
1977 }
1978 },
1979 "types_to_exclude": [
1980 "module",
1981 "function",
1982 "builtin_function_or_method",
1983 "instance",
1984 "_Feature"
1985 ],
1986 "window_display": false
1987 }
1988 },
1989 "nbformat": 4,
1990 "nbformat_minor": 2
1991 }
General Comments 0
You need to be logged in to leave comments. Login now