##// END OF EJS Templates
Merge pull request #1211 from minrk/localfiles...
Min RK -
r5842:a50ac36b merge
parent child Browse files
Show More
@@ -1,628 +1,637 b''
1 1 """Tornado handlers for the notebook.
2 2
3 3 Authors:
4 4
5 5 * Brian Granger
6 6 """
7 7
8 8 #-----------------------------------------------------------------------------
9 9 # Copyright (C) 2008-2011 The IPython Development Team
10 10 #
11 11 # Distributed under the terms of the BSD License. The full license is in
12 12 # the file COPYING, distributed as part of this software.
13 13 #-----------------------------------------------------------------------------
14 14
15 15 #-----------------------------------------------------------------------------
16 16 # Imports
17 17 #-----------------------------------------------------------------------------
18 18
19 19 import logging
20 20 import Cookie
21 21 import time
22 22 import uuid
23 23
24 24 from tornado import web
25 25 from tornado import websocket
26 26
27 27 from zmq.eventloop import ioloop
28 28 from zmq.utils import jsonapi
29 29
30 30 from IPython.external.decorator import decorator
31 31 from IPython.zmq.session import Session
32 32 from IPython.lib.security import passwd_check
33 33
34 34 try:
35 35 from docutils.core import publish_string
36 36 except ImportError:
37 37 publish_string = None
38 38
39 39 #-----------------------------------------------------------------------------
40 40 # Monkeypatch for Tornado <= 2.1.1 - Remove when no longer necessary!
41 41 #-----------------------------------------------------------------------------
42 42
43 43 # Google Chrome, as of release 16, changed its websocket protocol number. The
44 44 # parts tornado cares about haven't really changed, so it's OK to continue
45 45 # accepting Chrome connections, but as of Tornado 2.1.1 (the currently released
46 46 # version as of Oct 30/2011) the version check fails, see the issue report:
47 47
48 48 # https://github.com/facebook/tornado/issues/385
49 49
50 50 # This issue has been fixed in Tornado post 2.1.1:
51 51
52 52 # https://github.com/facebook/tornado/commit/84d7b458f956727c3b0d6710
53 53
54 54 # Here we manually apply the same patch as above so that users of IPython can
55 55 # continue to work with an officially released Tornado. We make the
56 56 # monkeypatch version check as narrow as possible to limit its effects; once
57 57 # Tornado 2.1.1 is no longer found in the wild we'll delete this code.
58 58
59 59 import tornado
60 60
61 61 if tornado.version_info <= (2,1,1):
62 62
63 63 def _execute(self, transforms, *args, **kwargs):
64 64 from tornado.websocket import WebSocketProtocol8, WebSocketProtocol76
65 65
66 66 self.open_args = args
67 67 self.open_kwargs = kwargs
68 68
69 69 # The difference between version 8 and 13 is that in 8 the
70 70 # client sends a "Sec-Websocket-Origin" header and in 13 it's
71 71 # simply "Origin".
72 72 if self.request.headers.get("Sec-WebSocket-Version") in ("7", "8", "13"):
73 73 self.ws_connection = WebSocketProtocol8(self)
74 74 self.ws_connection.accept_connection()
75 75
76 76 elif self.request.headers.get("Sec-WebSocket-Version"):
77 77 self.stream.write(tornado.escape.utf8(
78 78 "HTTP/1.1 426 Upgrade Required\r\n"
79 79 "Sec-WebSocket-Version: 8\r\n\r\n"))
80 80 self.stream.close()
81 81
82 82 else:
83 83 self.ws_connection = WebSocketProtocol76(self)
84 84 self.ws_connection.accept_connection()
85 85
86 86 websocket.WebSocketHandler._execute = _execute
87 87 del _execute
88 88
89 89 #-----------------------------------------------------------------------------
90 90 # Decorator for disabling read-only handlers
91 91 #-----------------------------------------------------------------------------
92 92
93 93 @decorator
94 94 def not_if_readonly(f, self, *args, **kwargs):
95 95 if self.application.read_only:
96 96 raise web.HTTPError(403, "Notebook server is read-only")
97 97 else:
98 98 return f(self, *args, **kwargs)
99 99
100 100 @decorator
101 101 def authenticate_unless_readonly(f, self, *args, **kwargs):
102 102 """authenticate this page *unless* readonly view is active.
103 103
104 104 In read-only mode, the notebook list and print view should
105 105 be accessible without authentication.
106 106 """
107 107
108 108 @web.authenticated
109 109 def auth_f(self, *args, **kwargs):
110 110 return f(self, *args, **kwargs)
111
111 112 if self.application.read_only:
112 113 return f(self, *args, **kwargs)
113 114 else:
114 115 return auth_f(self, *args, **kwargs)
115 116
116 117 #-----------------------------------------------------------------------------
117 118 # Top-level handlers
118 119 #-----------------------------------------------------------------------------
119 120
120 121 class RequestHandler(web.RequestHandler):
121 122 """RequestHandler with default variable setting."""
122 123
123 124 def render(*args, **kwargs):
124 125 kwargs.setdefault('message', '')
125 126 return web.RequestHandler.render(*args, **kwargs)
126 127
127 128 class AuthenticatedHandler(RequestHandler):
128 129 """A RequestHandler with an authenticated user."""
129 130
130 131 def get_current_user(self):
131 132 user_id = self.get_secure_cookie("username")
132 133 # For now the user_id should not return empty, but it could eventually
133 134 if user_id == '':
134 135 user_id = 'anonymous'
135 136 if user_id is None:
136 137 # prevent extra Invalid cookie sig warnings:
137 138 self.clear_cookie('username')
138 139 if not self.application.password and not self.application.read_only:
139 140 user_id = 'anonymous'
140 141 return user_id
141 142
142 143 @property
143 144 def logged_in(self):
144 145 """Is a user currently logged in?
145 146
146 147 """
147 148 user = self.get_current_user()
148 149 return (user and not user == 'anonymous')
149 150
150 151 @property
151 152 def login_available(self):
152 153 """May a user proceed to log in?
153 154
154 155 This returns True if login capability is available, irrespective of
155 156 whether the user is already logged in or not.
156 157
157 158 """
158 159 return bool(self.application.password)
159 160
160 161 @property
161 162 def read_only(self):
162 163 """Is the notebook read-only?
163 164
164 165 """
165 166 return self.application.read_only
166 167
167 168 @property
168 169 def ws_url(self):
169 170 """websocket url matching the current request
170 171
171 172 turns http[s]://host[:port] into
172 173 ws[s]://host[:port]
173 174 """
174 175 proto = self.request.protocol.replace('http', 'ws')
175 176 return "%s://%s" % (proto, self.request.host)
176 177
177 178
179 class AuthenticatedFileHandler(AuthenticatedHandler, web.StaticFileHandler):
180 """static files should only be accessible when logged in"""
181
182 @authenticate_unless_readonly
183 def get(self, path):
184 return web.StaticFileHandler.get(self, path)
185
186
178 187 class ProjectDashboardHandler(AuthenticatedHandler):
179 188
180 189 @authenticate_unless_readonly
181 190 def get(self):
182 191 nbm = self.application.notebook_manager
183 192 project = nbm.notebook_dir
184 193 self.render(
185 194 'projectdashboard.html', project=project,
186 195 base_project_url=u'/', base_kernel_url=u'/',
187 196 read_only=self.read_only,
188 197 logged_in=self.logged_in,
189 198 login_available=self.login_available
190 199 )
191 200
192 201
193 202 class LoginHandler(AuthenticatedHandler):
194 203
195 204 def _render(self, message=None):
196 205 self.render('login.html',
197 206 next=self.get_argument('next', default='/'),
198 207 read_only=self.read_only,
199 208 logged_in=self.logged_in,
200 209 login_available=self.login_available,
201 210 message=message
202 211 )
203 212
204 213 def get(self):
205 214 if self.current_user:
206 215 self.redirect(self.get_argument('next', default='/'))
207 216 else:
208 217 self._render()
209 218
210 219 def post(self):
211 220 pwd = self.get_argument('password', default=u'')
212 221 if self.application.password:
213 222 if passwd_check(self.application.password, pwd):
214 223 self.set_secure_cookie('username', str(uuid.uuid4()))
215 224 else:
216 225 self._render(message={'error': 'Invalid password'})
217 226 return
218 227
219 228 self.redirect(self.get_argument('next', default='/'))
220 229
221 230
222 231 class LogoutHandler(AuthenticatedHandler):
223 232
224 233 def get(self):
225 234 self.clear_cookie('username')
226 235 if self.login_available:
227 236 message = {'info': 'Successfully logged out.'}
228 237 else:
229 238 message = {'warning': 'Cannot log out. Notebook authentication '
230 239 'is disabled.'}
231 240
232 241 self.render('logout.html',
233 242 read_only=self.read_only,
234 243 logged_in=self.logged_in,
235 244 login_available=self.login_available,
236 245 message=message)
237 246
238 247
239 248 class NewHandler(AuthenticatedHandler):
240 249
241 250 @web.authenticated
242 251 def get(self):
243 252 nbm = self.application.notebook_manager
244 253 project = nbm.notebook_dir
245 254 notebook_id = nbm.new_notebook()
246 255 self.render(
247 256 'notebook.html', project=project,
248 257 notebook_id=notebook_id,
249 258 base_project_url=u'/', base_kernel_url=u'/',
250 259 kill_kernel=False,
251 260 read_only=False,
252 261 logged_in=self.logged_in,
253 262 login_available=self.login_available,
254 263 mathjax_url=self.application.ipython_app.mathjax_url,
255 264 )
256 265
257 266
258 267 class NamedNotebookHandler(AuthenticatedHandler):
259 268
260 269 @authenticate_unless_readonly
261 270 def get(self, notebook_id):
262 271 nbm = self.application.notebook_manager
263 272 project = nbm.notebook_dir
264 273 if not nbm.notebook_exists(notebook_id):
265 274 raise web.HTTPError(404, u'Notebook does not exist: %s' % notebook_id)
266 275
267 276 self.render(
268 277 'notebook.html', project=project,
269 278 notebook_id=notebook_id,
270 279 base_project_url=u'/', base_kernel_url=u'/',
271 280 kill_kernel=False,
272 281 read_only=self.read_only,
273 282 logged_in=self.logged_in,
274 283 login_available=self.login_available,
275 284 mathjax_url=self.application.ipython_app.mathjax_url,
276 285 )
277 286
278 287
279 288 #-----------------------------------------------------------------------------
280 289 # Kernel handlers
281 290 #-----------------------------------------------------------------------------
282 291
283 292
284 293 class MainKernelHandler(AuthenticatedHandler):
285 294
286 295 @web.authenticated
287 296 def get(self):
288 297 km = self.application.kernel_manager
289 298 self.finish(jsonapi.dumps(km.kernel_ids))
290 299
291 300 @web.authenticated
292 301 def post(self):
293 302 km = self.application.kernel_manager
294 303 notebook_id = self.get_argument('notebook', default=None)
295 304 kernel_id = km.start_kernel(notebook_id)
296 305 data = {'ws_url':self.ws_url,'kernel_id':kernel_id}
297 306 self.set_header('Location', '/'+kernel_id)
298 307 self.finish(jsonapi.dumps(data))
299 308
300 309
301 310 class KernelHandler(AuthenticatedHandler):
302 311
303 312 SUPPORTED_METHODS = ('DELETE')
304 313
305 314 @web.authenticated
306 315 def delete(self, kernel_id):
307 316 km = self.application.kernel_manager
308 317 km.kill_kernel(kernel_id)
309 318 self.set_status(204)
310 319 self.finish()
311 320
312 321
313 322 class KernelActionHandler(AuthenticatedHandler):
314 323
315 324 @web.authenticated
316 325 def post(self, kernel_id, action):
317 326 km = self.application.kernel_manager
318 327 if action == 'interrupt':
319 328 km.interrupt_kernel(kernel_id)
320 329 self.set_status(204)
321 330 if action == 'restart':
322 331 new_kernel_id = km.restart_kernel(kernel_id)
323 332 data = {'ws_url':self.ws_url,'kernel_id':new_kernel_id}
324 333 self.set_header('Location', '/'+new_kernel_id)
325 334 self.write(jsonapi.dumps(data))
326 335 self.finish()
327 336
328 337
329 338 class ZMQStreamHandler(websocket.WebSocketHandler):
330 339
331 340 def _reserialize_reply(self, msg_list):
332 341 """Reserialize a reply message using JSON.
333 342
334 343 This takes the msg list from the ZMQ socket, unserializes it using
335 344 self.session and then serializes the result using JSON. This method
336 345 should be used by self._on_zmq_reply to build messages that can
337 346 be sent back to the browser.
338 347 """
339 348 idents, msg_list = self.session.feed_identities(msg_list)
340 349 msg = self.session.unserialize(msg_list)
341 350 try:
342 351 msg['header'].pop('date')
343 352 except KeyError:
344 353 pass
345 354 try:
346 355 msg['parent_header'].pop('date')
347 356 except KeyError:
348 357 pass
349 358 msg.pop('buffers')
350 359 return jsonapi.dumps(msg)
351 360
352 361 def _on_zmq_reply(self, msg_list):
353 362 try:
354 363 msg = self._reserialize_reply(msg_list)
355 364 except:
356 365 self.application.log.critical("Malformed message: %r" % msg_list)
357 366 else:
358 367 self.write_message(msg)
359 368
360 369
361 370 class AuthenticatedZMQStreamHandler(ZMQStreamHandler):
362 371
363 372 def open(self, kernel_id):
364 373 self.kernel_id = kernel_id.decode('ascii')
365 374 try:
366 375 cfg = self.application.ipython_app.config
367 376 except AttributeError:
368 377 # protect from the case where this is run from something other than
369 378 # the notebook app:
370 379 cfg = None
371 380 self.session = Session(config=cfg)
372 381 self.save_on_message = self.on_message
373 382 self.on_message = self.on_first_message
374 383
375 384 def get_current_user(self):
376 385 user_id = self.get_secure_cookie("username")
377 386 if user_id == '' or (user_id is None and not self.application.password):
378 387 user_id = 'anonymous'
379 388 return user_id
380 389
381 390 def _inject_cookie_message(self, msg):
382 391 """Inject the first message, which is the document cookie,
383 392 for authentication."""
384 393 if isinstance(msg, unicode):
385 394 # Cookie can't constructor doesn't accept unicode strings for some reason
386 395 msg = msg.encode('utf8', 'replace')
387 396 try:
388 397 self.request._cookies = Cookie.SimpleCookie(msg)
389 398 except:
390 399 logging.warn("couldn't parse cookie string: %s",msg, exc_info=True)
391 400
392 401 def on_first_message(self, msg):
393 402 self._inject_cookie_message(msg)
394 403 if self.get_current_user() is None:
395 404 logging.warn("Couldn't authenticate WebSocket connection")
396 405 raise web.HTTPError(403)
397 406 self.on_message = self.save_on_message
398 407
399 408
400 409 class IOPubHandler(AuthenticatedZMQStreamHandler):
401 410
402 411 def initialize(self, *args, **kwargs):
403 412 self._kernel_alive = True
404 413 self._beating = False
405 414 self.iopub_stream = None
406 415 self.hb_stream = None
407 416
408 417 def on_first_message(self, msg):
409 418 try:
410 419 super(IOPubHandler, self).on_first_message(msg)
411 420 except web.HTTPError:
412 421 self.close()
413 422 return
414 423 km = self.application.kernel_manager
415 424 self.time_to_dead = km.time_to_dead
416 425 self.first_beat = km.first_beat
417 426 kernel_id = self.kernel_id
418 427 try:
419 428 self.iopub_stream = km.create_iopub_stream(kernel_id)
420 429 self.hb_stream = km.create_hb_stream(kernel_id)
421 430 except web.HTTPError:
422 431 # WebSockets don't response to traditional error codes so we
423 432 # close the connection.
424 433 if not self.stream.closed():
425 434 self.stream.close()
426 435 self.close()
427 436 else:
428 437 self.iopub_stream.on_recv(self._on_zmq_reply)
429 438 self.start_hb(self.kernel_died)
430 439
431 440 def on_message(self, msg):
432 441 pass
433 442
434 443 def on_close(self):
435 444 # This method can be called twice, once by self.kernel_died and once
436 445 # from the WebSocket close event. If the WebSocket connection is
437 446 # closed before the ZMQ streams are setup, they could be None.
438 447 self.stop_hb()
439 448 if self.iopub_stream is not None and not self.iopub_stream.closed():
440 449 self.iopub_stream.on_recv(None)
441 450 self.iopub_stream.close()
442 451 if self.hb_stream is not None and not self.hb_stream.closed():
443 452 self.hb_stream.close()
444 453
445 454 def start_hb(self, callback):
446 455 """Start the heartbeating and call the callback if the kernel dies."""
447 456 if not self._beating:
448 457 self._kernel_alive = True
449 458
450 459 def ping_or_dead():
451 460 self.hb_stream.flush()
452 461 if self._kernel_alive:
453 462 self._kernel_alive = False
454 463 self.hb_stream.send(b'ping')
455 464 else:
456 465 try:
457 466 callback()
458 467 except:
459 468 pass
460 469 finally:
461 470 self.stop_hb()
462 471
463 472 def beat_received(msg):
464 473 self._kernel_alive = True
465 474
466 475 self.hb_stream.on_recv(beat_received)
467 476 loop = ioloop.IOLoop.instance()
468 477 self._hb_periodic_callback = ioloop.PeriodicCallback(ping_or_dead, self.time_to_dead*1000, loop)
469 478 loop.add_timeout(time.time()+self.first_beat, self._really_start_hb)
470 479 self._beating= True
471 480
472 481 def _really_start_hb(self):
473 482 """callback for delayed heartbeat start
474 483
475 484 Only start the hb loop if we haven't been closed during the wait.
476 485 """
477 486 if self._beating and not self.hb_stream.closed():
478 487 self._hb_periodic_callback.start()
479 488
480 489 def stop_hb(self):
481 490 """Stop the heartbeating and cancel all related callbacks."""
482 491 if self._beating:
483 492 self._beating = False
484 493 self._hb_periodic_callback.stop()
485 494 if not self.hb_stream.closed():
486 495 self.hb_stream.on_recv(None)
487 496
488 497 def kernel_died(self):
489 498 self.application.kernel_manager.delete_mapping_for_kernel(self.kernel_id)
490 499 self.application.log.error("Kernel %s failed to respond to heartbeat", self.kernel_id)
491 500 self.write_message(
492 501 {'header': {'msg_type': 'status'},
493 502 'parent_header': {},
494 503 'content': {'execution_state':'dead'}
495 504 }
496 505 )
497 506 self.on_close()
498 507
499 508
500 509 class ShellHandler(AuthenticatedZMQStreamHandler):
501 510
502 511 def initialize(self, *args, **kwargs):
503 512 self.shell_stream = None
504 513
505 514 def on_first_message(self, msg):
506 515 try:
507 516 super(ShellHandler, self).on_first_message(msg)
508 517 except web.HTTPError:
509 518 self.close()
510 519 return
511 520 km = self.application.kernel_manager
512 521 self.max_msg_size = km.max_msg_size
513 522 kernel_id = self.kernel_id
514 523 try:
515 524 self.shell_stream = km.create_shell_stream(kernel_id)
516 525 except web.HTTPError:
517 526 # WebSockets don't response to traditional error codes so we
518 527 # close the connection.
519 528 if not self.stream.closed():
520 529 self.stream.close()
521 530 self.close()
522 531 else:
523 532 self.shell_stream.on_recv(self._on_zmq_reply)
524 533
525 534 def on_message(self, msg):
526 535 if len(msg) < self.max_msg_size:
527 536 msg = jsonapi.loads(msg)
528 537 self.session.send(self.shell_stream, msg)
529 538
530 539 def on_close(self):
531 540 # Make sure the stream exists and is not already closed.
532 541 if self.shell_stream is not None and not self.shell_stream.closed():
533 542 self.shell_stream.close()
534 543
535 544
536 545 #-----------------------------------------------------------------------------
537 546 # Notebook web service handlers
538 547 #-----------------------------------------------------------------------------
539 548
540 549 class NotebookRootHandler(AuthenticatedHandler):
541 550
542 551 @authenticate_unless_readonly
543 552 def get(self):
544 553
545 554 nbm = self.application.notebook_manager
546 555 files = nbm.list_notebooks()
547 556 self.finish(jsonapi.dumps(files))
548 557
549 558 @web.authenticated
550 559 def post(self):
551 560 nbm = self.application.notebook_manager
552 561 body = self.request.body.strip()
553 562 format = self.get_argument('format', default='json')
554 563 name = self.get_argument('name', default=None)
555 564 if body:
556 565 notebook_id = nbm.save_new_notebook(body, name=name, format=format)
557 566 else:
558 567 notebook_id = nbm.new_notebook()
559 568 self.set_header('Location', '/'+notebook_id)
560 569 self.finish(jsonapi.dumps(notebook_id))
561 570
562 571
563 572 class NotebookHandler(AuthenticatedHandler):
564 573
565 574 SUPPORTED_METHODS = ('GET', 'PUT', 'DELETE')
566 575
567 576 @authenticate_unless_readonly
568 577 def get(self, notebook_id):
569 578 nbm = self.application.notebook_manager
570 579 format = self.get_argument('format', default='json')
571 580 last_mod, name, data = nbm.get_notebook(notebook_id, format)
572 581
573 582 if format == u'json':
574 583 self.set_header('Content-Type', 'application/json')
575 584 self.set_header('Content-Disposition','attachment; filename="%s.ipynb"' % name)
576 585 elif format == u'py':
577 586 self.set_header('Content-Type', 'application/x-python')
578 587 self.set_header('Content-Disposition','attachment; filename="%s.py"' % name)
579 588 self.set_header('Last-Modified', last_mod)
580 589 self.finish(data)
581 590
582 591 @web.authenticated
583 592 def put(self, notebook_id):
584 593 nbm = self.application.notebook_manager
585 594 format = self.get_argument('format', default='json')
586 595 name = self.get_argument('name', default=None)
587 596 nbm.save_notebook(notebook_id, self.request.body, name=name, format=format)
588 597 self.set_status(204)
589 598 self.finish()
590 599
591 600 @web.authenticated
592 601 def delete(self, notebook_id):
593 602 nbm = self.application.notebook_manager
594 603 nbm.delete_notebook(notebook_id)
595 604 self.set_status(204)
596 605 self.finish()
597 606
598 607 #-----------------------------------------------------------------------------
599 608 # RST web service handlers
600 609 #-----------------------------------------------------------------------------
601 610
602 611
603 612 class RSTHandler(AuthenticatedHandler):
604 613
605 614 @web.authenticated
606 615 def post(self):
607 616 if publish_string is None:
608 617 raise web.HTTPError(503, u'docutils not available')
609 618 body = self.request.body.strip()
610 619 source = body
611 620 # template_path=os.path.join(os.path.dirname(__file__), u'templates', u'rst_template.html')
612 621 defaults = {'file_insertion_enabled': 0,
613 622 'raw_enabled': 0,
614 623 '_disable_config': 1,
615 624 'stylesheet_path': 0
616 625 # 'template': template_path
617 626 }
618 627 try:
619 628 html = publish_string(source, writer_name='html',
620 629 settings_overrides=defaults
621 630 )
622 631 except:
623 632 raise web.HTTPError(400, u'Invalid RST')
624 633 print html
625 634 self.set_header('Content-Type', 'text/html')
626 635 self.finish(html)
627 636
628 637
@@ -1,403 +1,405 b''
1 1 """A tornado based IPython notebook server.
2 2
3 3 Authors:
4 4
5 5 * Brian Granger
6 6 """
7 7
8 8 #-----------------------------------------------------------------------------
9 9 # Copyright (C) 2008-2011 The IPython Development Team
10 10 #
11 11 # Distributed under the terms of the BSD License. The full license is in
12 12 # the file COPYING, distributed as part of this software.
13 13 #-----------------------------------------------------------------------------
14 14
15 15 #-----------------------------------------------------------------------------
16 16 # Imports
17 17 #-----------------------------------------------------------------------------
18 18
19 19 # stdlib
20 20 import errno
21 21 import logging
22 22 import os
23 23 import signal
24 24 import socket
25 25 import sys
26 26 import threading
27 27 import webbrowser
28 28
29 29 # Third party
30 30 import zmq
31 31
32 32 # Install the pyzmq ioloop. This has to be done before anything else from
33 33 # tornado is imported.
34 34 from zmq.eventloop import ioloop
35 35 # FIXME: ioloop.install is new in pyzmq-2.1.7, so remove this conditional
36 36 # when pyzmq dependency is updated beyond that.
37 37 if hasattr(ioloop, 'install'):
38 38 ioloop.install()
39 39 else:
40 40 import tornado.ioloop
41 41 tornado.ioloop.IOLoop = ioloop.IOLoop
42 42
43 43 from tornado import httpserver
44 44 from tornado import web
45 45
46 46 # Our own libraries
47 47 from .kernelmanager import MappingKernelManager
48 48 from .handlers import (LoginHandler, LogoutHandler,
49 49 ProjectDashboardHandler, NewHandler, NamedNotebookHandler,
50 50 MainKernelHandler, KernelHandler, KernelActionHandler, IOPubHandler,
51 ShellHandler, NotebookRootHandler, NotebookHandler, RSTHandler
51 ShellHandler, NotebookRootHandler, NotebookHandler, RSTHandler,
52 AuthenticatedFileHandler,
52 53 )
53 54 from .notebookmanager import NotebookManager
54 55
55 56 from IPython.config.application import catch_config_error, boolean_flag
56 57 from IPython.core.application import BaseIPythonApplication
57 58 from IPython.core.profiledir import ProfileDir
58 59 from IPython.lib.kernel import swallow_argv
59 60 from IPython.zmq.session import Session, default_secure
60 61 from IPython.zmq.zmqshell import ZMQInteractiveShell
61 62 from IPython.zmq.ipkernel import (
62 63 flags as ipkernel_flags,
63 64 aliases as ipkernel_aliases,
64 65 IPKernelApp
65 66 )
66 67 from IPython.utils.traitlets import Dict, Unicode, Integer, List, Enum, Bool
67 68
68 69 #-----------------------------------------------------------------------------
69 70 # Module globals
70 71 #-----------------------------------------------------------------------------
71 72
72 73 _kernel_id_regex = r"(?P<kernel_id>\w+-\w+-\w+-\w+-\w+)"
73 74 _kernel_action_regex = r"(?P<action>restart|interrupt)"
74 75 _notebook_id_regex = r"(?P<notebook_id>\w+-\w+-\w+-\w+-\w+)"
75 76
76 77 LOCALHOST = '127.0.0.1'
77 78
78 79 _examples = """
79 80 ipython notebook # start the notebook
80 81 ipython notebook --profile=sympy # use the sympy profile
81 82 ipython notebook --pylab=inline # pylab in inline plotting mode
82 83 ipython notebook --certfile=mycert.pem # use SSL/TLS certificate
83 84 ipython notebook --port=5555 --ip=* # Listen on port 5555, all interfaces
84 85 """
85 86
86 87 #-----------------------------------------------------------------------------
87 88 # The Tornado web application
88 89 #-----------------------------------------------------------------------------
89 90
90 91 class NotebookWebApplication(web.Application):
91 92
92 93 def __init__(self, ipython_app, kernel_manager, notebook_manager, log, settings_overrides):
93 94 handlers = [
94 95 (r"/", ProjectDashboardHandler),
95 96 (r"/login", LoginHandler),
96 97 (r"/logout", LogoutHandler),
97 98 (r"/new", NewHandler),
98 99 (r"/%s" % _notebook_id_regex, NamedNotebookHandler),
99 100 (r"/kernels", MainKernelHandler),
100 101 (r"/kernels/%s" % _kernel_id_regex, KernelHandler),
101 102 (r"/kernels/%s/%s" % (_kernel_id_regex, _kernel_action_regex), KernelActionHandler),
102 103 (r"/kernels/%s/iopub" % _kernel_id_regex, IOPubHandler),
103 104 (r"/kernels/%s/shell" % _kernel_id_regex, ShellHandler),
104 105 (r"/notebooks", NotebookRootHandler),
105 106 (r"/notebooks/%s" % _notebook_id_regex, NotebookHandler),
106 (r"/rstservice/render", RSTHandler)
107 (r"/rstservice/render", RSTHandler),
108 (r"/files/(.*)", AuthenticatedFileHandler, {'path' : notebook_manager.notebook_dir}),
107 109 ]
108 110 settings = dict(
109 111 template_path=os.path.join(os.path.dirname(__file__), "templates"),
110 112 static_path=os.path.join(os.path.dirname(__file__), "static"),
111 113 cookie_secret=os.urandom(1024),
112 114 login_url="/login",
113 115 )
114 116
115 117 # allow custom overrides for the tornado web app.
116 118 settings.update(settings_overrides)
117 119
118 120 super(NotebookWebApplication, self).__init__(handlers, **settings)
119 121
120 122 self.kernel_manager = kernel_manager
121 123 self.log = log
122 124 self.notebook_manager = notebook_manager
123 125 self.ipython_app = ipython_app
124 126 self.read_only = self.ipython_app.read_only
125 127
126 128
127 129 #-----------------------------------------------------------------------------
128 130 # Aliases and Flags
129 131 #-----------------------------------------------------------------------------
130 132
131 133 flags = dict(ipkernel_flags)
132 134 flags['no-browser']=(
133 135 {'NotebookApp' : {'open_browser' : False}},
134 136 "Don't open the notebook in a browser after startup."
135 137 )
136 138 flags['no-mathjax']=(
137 139 {'NotebookApp' : {'enable_mathjax' : False}},
138 140 """Disable MathJax
139 141
140 142 MathJax is the javascript library IPython uses to render math/LaTeX. It is
141 143 very large, so you may want to disable it if you have a slow internet
142 144 connection, or for offline use of the notebook.
143 145
144 146 When disabled, equations etc. will appear as their untransformed TeX source.
145 147 """
146 148 )
147 149 flags['read-only'] = (
148 150 {'NotebookApp' : {'read_only' : True}},
149 151 """Allow read-only access to notebooks.
150 152
151 153 When using a password to protect the notebook server, this flag
152 154 allows unauthenticated clients to view the notebook list, and
153 155 individual notebooks, but not edit them, start kernels, or run
154 156 code.
155 157
156 158 If no password is set, the server will be entirely read-only.
157 159 """
158 160 )
159 161
160 162 # Add notebook manager flags
161 163 flags.update(boolean_flag('script', 'NotebookManager.save_script',
162 164 'Auto-save a .py script everytime the .ipynb notebook is saved',
163 165 'Do not auto-save .py scripts for every notebook'))
164 166
165 167 # the flags that are specific to the frontend
166 168 # these must be scrubbed before being passed to the kernel,
167 169 # or it will raise an error on unrecognized flags
168 170 notebook_flags = ['no-browser', 'no-mathjax', 'read-only', 'script', 'no-script']
169 171
170 172 aliases = dict(ipkernel_aliases)
171 173
172 174 aliases.update({
173 175 'ip': 'NotebookApp.ip',
174 176 'port': 'NotebookApp.port',
175 177 'keyfile': 'NotebookApp.keyfile',
176 178 'certfile': 'NotebookApp.certfile',
177 179 'notebook-dir': 'NotebookManager.notebook_dir',
178 180 })
179 181
180 182 # remove ipkernel flags that are singletons, and don't make sense in
181 183 # multi-kernel evironment:
182 184 aliases.pop('f', None)
183 185
184 186 notebook_aliases = [u'port', u'ip', u'keyfile', u'certfile',
185 187 u'notebook-dir']
186 188
187 189 #-----------------------------------------------------------------------------
188 190 # NotebookApp
189 191 #-----------------------------------------------------------------------------
190 192
191 193 class NotebookApp(BaseIPythonApplication):
192 194
193 195 name = 'ipython-notebook'
194 196 default_config_file_name='ipython_notebook_config.py'
195 197
196 198 description = """
197 199 The IPython HTML Notebook.
198 200
199 201 This launches a Tornado based HTML Notebook Server that serves up an
200 202 HTML5/Javascript Notebook client.
201 203 """
202 204 examples = _examples
203 205
204 206 classes = [IPKernelApp, ZMQInteractiveShell, ProfileDir, Session,
205 207 MappingKernelManager, NotebookManager]
206 208 flags = Dict(flags)
207 209 aliases = Dict(aliases)
208 210
209 211 kernel_argv = List(Unicode)
210 212
211 213 log_level = Enum((0,10,20,30,40,50,'DEBUG','INFO','WARN','ERROR','CRITICAL'),
212 214 default_value=logging.INFO,
213 215 config=True,
214 216 help="Set the log level by value or name.")
215 217
216 218 # Network related information.
217 219
218 220 ip = Unicode(LOCALHOST, config=True,
219 221 help="The IP address the notebook server will listen on."
220 222 )
221 223
222 224 def _ip_changed(self, name, old, new):
223 225 if new == u'*': self.ip = u''
224 226
225 227 port = Integer(8888, config=True,
226 228 help="The port the notebook server will listen on."
227 229 )
228 230
229 231 certfile = Unicode(u'', config=True,
230 232 help="""The full path to an SSL/TLS certificate file."""
231 233 )
232 234
233 235 keyfile = Unicode(u'', config=True,
234 236 help="""The full path to a private key file for usage with SSL/TLS."""
235 237 )
236 238
237 239 password = Unicode(u'', config=True,
238 240 help="""Hashed password to use for web authentication.
239 241
240 242 To generate, type in a python/IPython shell:
241 243
242 244 from IPython.lib import passwd; passwd()
243 245
244 246 The string should be of the form type:salt:hashed-password.
245 247 """
246 248 )
247 249
248 250 open_browser = Bool(True, config=True,
249 251 help="Whether to open in a browser after starting.")
250 252
251 253 read_only = Bool(False, config=True,
252 254 help="Whether to prevent editing/execution of notebooks."
253 255 )
254 256
255 257 webapp_settings = Dict(config=True,
256 258 help="Supply overrides for the tornado.web.Application that the "
257 259 "IPython notebook uses.")
258 260
259 261 enable_mathjax = Bool(True, config=True,
260 262 help="""Whether to enable MathJax for typesetting math/TeX
261 263
262 264 MathJax is the javascript library IPython uses to render math/LaTeX. It is
263 265 very large, so you may want to disable it if you have a slow internet
264 266 connection, or for offline use of the notebook.
265 267
266 268 When disabled, equations etc. will appear as their untransformed TeX source.
267 269 """
268 270 )
269 271 def _enable_mathjax_changed(self, name, old, new):
270 272 """set mathjax url to empty if mathjax is disabled"""
271 273 if not new:
272 274 self.mathjax_url = u''
273 275
274 276 mathjax_url = Unicode("", config=True,
275 277 help="""The url for MathJax.js."""
276 278 )
277 279 def _mathjax_url_default(self):
278 280 if not self.enable_mathjax:
279 281 return u''
280 282 static_path = self.webapp_settings.get("static_path", os.path.join(os.path.dirname(__file__), "static"))
281 283 if os.path.exists(os.path.join(static_path, 'mathjax', "MathJax.js")):
282 284 self.log.info("Using local MathJax")
283 return u"static/mathjax/MathJax.js"
285 return u"/static/mathjax/MathJax.js"
284 286 else:
285 287 self.log.info("Using MathJax from CDN")
286 288 return u"http://cdn.mathjax.org/mathjax/latest/MathJax.js"
287 289
288 290 def _mathjax_url_changed(self, name, old, new):
289 291 if new and not self.enable_mathjax:
290 292 # enable_mathjax=False overrides mathjax_url
291 293 self.mathjax_url = u''
292 294 else:
293 295 self.log.info("Using MathJax: %s", new)
294 296
295 297 def parse_command_line(self, argv=None):
296 298 super(NotebookApp, self).parse_command_line(argv)
297 299 if argv is None:
298 300 argv = sys.argv[1:]
299 301
300 302 # Scrub frontend-specific flags
301 303 self.kernel_argv = swallow_argv(argv, notebook_aliases, notebook_flags)
302 304 # Kernel should inherit default config file from frontend
303 305 self.kernel_argv.append("--KernelApp.parent_appname='%s'"%self.name)
304 306
305 307 def init_configurables(self):
306 308 # force Session default to be secure
307 309 default_secure(self.config)
308 310 # Create a KernelManager and start a kernel.
309 311 self.kernel_manager = MappingKernelManager(
310 312 config=self.config, log=self.log, kernel_argv=self.kernel_argv,
311 313 connection_dir = self.profile_dir.security_dir,
312 314 )
313 315 self.notebook_manager = NotebookManager(config=self.config, log=self.log)
314 316 self.notebook_manager.list_notebooks()
315 317
316 318 def init_logging(self):
317 319 super(NotebookApp, self).init_logging()
318 320 # This prevents double log messages because tornado use a root logger that
319 321 # self.log is a child of. The logging module dipatches log messages to a log
320 322 # and all of its ancenstors until propagate is set to False.
321 323 self.log.propagate = False
322 324
323 325 def init_webapp(self):
324 326 """initialize tornado webapp and httpserver"""
325 327 self.web_app = NotebookWebApplication(
326 328 self, self.kernel_manager, self.notebook_manager, self.log,
327 329 self.webapp_settings
328 330 )
329 331 if self.certfile:
330 332 ssl_options = dict(certfile=self.certfile)
331 333 if self.keyfile:
332 334 ssl_options['keyfile'] = self.keyfile
333 335 else:
334 336 ssl_options = None
335 337 self.web_app.password = self.password
336 338 self.http_server = httpserver.HTTPServer(self.web_app, ssl_options=ssl_options)
337 339 if ssl_options is None and not self.ip and not (self.read_only and not self.password):
338 340 self.log.critical('WARNING: the notebook server is listening on all IP addresses '
339 341 'but not using any encryption or authentication. This is highly '
340 342 'insecure and not recommended.')
341 343
342 344 # Try random ports centered around the default.
343 345 from random import randint
344 346 n = 50 # Max number of attempts, keep reasonably large.
345 347 for port in range(self.port, self.port+5) + [self.port + randint(-2*n, 2*n) for i in range(n-5)]:
346 348 try:
347 349 self.http_server.listen(port, self.ip)
348 350 except socket.error, e:
349 351 if e.errno != errno.EADDRINUSE:
350 352 raise
351 353 self.log.info('The port %i is already in use, trying another random port.' % port)
352 354 else:
353 355 self.port = port
354 356 break
355 357
356 358 @catch_config_error
357 359 def initialize(self, argv=None):
358 360 super(NotebookApp, self).initialize(argv)
359 361 self.init_configurables()
360 362 self.init_webapp()
361 363
362 364 def cleanup_kernels(self):
363 365 """shutdown all kernels
364 366
365 367 The kernels will shutdown themselves when this process no longer exists,
366 368 but explicit shutdown allows the KernelManagers to cleanup the connection files.
367 369 """
368 370 self.log.info('Shutting down kernels')
369 371 km = self.kernel_manager
370 372 # copy list, since kill_kernel deletes keys
371 373 for kid in list(km.kernel_ids):
372 374 km.kill_kernel(kid)
373 375
374 376 def start(self):
375 377 ip = self.ip if self.ip else '[all ip addresses on your system]'
376 378 proto = 'https' if self.certfile else 'http'
377 379 info = self.log.info
378 380 info("The IPython Notebook is running at: %s://%s:%i" %
379 381 (proto, ip, self.port) )
380 382 info("Use Control-C to stop this server and shut down all kernels.")
381 383
382 384 if self.open_browser:
383 385 ip = self.ip or '127.0.0.1'
384 386 b = lambda : webbrowser.open("%s://%s:%i" % (proto, ip, self.port),
385 387 new=2)
386 388 threading.Thread(target=b).start()
387 389 try:
388 390 ioloop.IOLoop.instance().start()
389 391 except KeyboardInterrupt:
390 392 info("Interrupted...")
391 393 finally:
392 394 self.cleanup_kernels()
393 395
394 396
395 397 #-----------------------------------------------------------------------------
396 398 # Main entry point
397 399 #-----------------------------------------------------------------------------
398 400
399 401 def launch_new_instance():
400 402 app = NotebookApp.instance()
401 403 app.initialize()
402 404 app.start()
403 405
@@ -1,85 +1,85 b''
1 1 <!DOCTYPE HTML>
2 2 <html>
3 3
4 4 <head>
5 5 <meta charset="utf-8">
6 6
7 7 <title>{% block title %}IPython Notebook{% end %}</title>
8 8
9 <link rel="stylesheet" href="static/jquery/css/themes/aristo/jquery-wijmo.css" type="text/css" />
10 <link rel="stylesheet" href="static/css/boilerplate.css" type="text/css" />
11 <link rel="stylesheet" href="static/css/layout.css" type="text/css" />
12 <link rel="stylesheet" href="static/css/base.css" type="text/css"/>
9 <link rel="stylesheet" href="/static/jquery/css/themes/aristo/jquery-wijmo.css" type="text/css" />
10 <link rel="stylesheet" href="/static/css/boilerplate.css" type="text/css" />
11 <link rel="stylesheet" href="/static/css/layout.css" type="text/css" />
12 <link rel="stylesheet" href="/static/css/base.css" type="text/css"/>
13 13 {% block stylesheet %}
14 14 {% end %}
15 15
16 16 {% block meta %}
17 17 {% end %}
18 18
19 19 </head>
20 20
21 21 <body {% block params %}{% end %}>
22 22
23 23 <div id="header">
24 <span id="ipython_notebook"><h1><img src='static/ipynblogo.png' alt='IPython Notebook'/></h1></span>
24 <span id="ipython_notebook"><h1><img src='/static/ipynblogo.png' alt='IPython Notebook'/></h1></span>
25 25
26 26 {% block login_widget %}
27 27
28 28 <span id="login_widget">
29 29 {% if logged_in %}
30 30 <button id="logout">Logout</button>
31 31 {% elif login_available and not logged_in %}
32 32 <button id="login">Login</button>
33 33 {% end %}
34 34 </span>
35 35
36 36 {% end %}
37 37
38 38 {% block header %}
39 39 {% end %}
40 40 </div>
41 41
42 42 <div id="header_border"></div>
43 43
44 44 <div id="main_app">
45 45
46 46 <div id="app_hbox">
47 47
48 48 <div id="left_panel">
49 49 {% block left_panel %}
50 50 {% end %}
51 51 </div>
52 52
53 53 <div id="content_panel">
54 54 {% if message %}
55 55
56 56 {% for key in message %}
57 57 <div class="message {{key}}">
58 58 {{message[key]}}
59 59 </div>
60 60 {% end %}
61 61 {% end %}
62 62
63 63 {% block content_panel %}
64 64 {% end %}
65 65 </div>
66 66 <div id="right_panel">
67 67 {% block right_panel %}
68 68 {% end %}
69 69 </div>
70 70
71 71 </div>
72 72
73 73 </div>
74 74
75 <script src="static/jquery/js/jquery-1.6.2.min.js" type="text/javascript" charset="utf-8"></script>
76 <script src="static/jquery/js/jquery-ui-1.8.14.custom.min.js" type="text/javascript" charset="utf-8"></script>
77 <script src="static/js/namespace.js" type="text/javascript" charset="utf-8"></script>
78 <script src="static/js/loginmain.js" type="text/javascript" charset="utf-8"></script>
79 <script src="static/js/loginwidget.js" type="text/javascript" charset="utf-8"></script>
75 <script src="/static/jquery/js/jquery-1.6.2.min.js" type="text/javascript" charset="utf-8"></script>
76 <script src="/static/jquery/js/jquery-ui-1.8.14.custom.min.js" type="text/javascript" charset="utf-8"></script>
77 <script src="/static/js/namespace.js" type="text/javascript" charset="utf-8"></script>
78 <script src="/static/js/loginmain.js" type="text/javascript" charset="utf-8"></script>
79 <script src="/static/js/loginwidget.js" type="text/javascript" charset="utf-8"></script>
80 80 {% block script %}
81 81 {% end %}
82 82
83 83 </body>
84 84
85 85 </html>
@@ -1,298 +1,298 b''
1 1 <!DOCTYPE HTML>
2 2 <html>
3 3
4 4 <head>
5 5 <meta charset="utf-8">
6 6
7 7 <title>IPython Notebook</title>
8 8
9 9 {% if mathjax_url %}
10 10 <script type="text/javascript" src="{{mathjax_url}}?config=TeX-AMS_HTML" charset="utf-8"></script>
11 11 {% end %}
12 12 <script type="text/javascript">
13 13 // MathJax disabled, set as null to distingish from *missing* MathJax,
14 14 // where it will be undefined, and should prompt a dialog later.
15 15 window.mathjax_url = "{{mathjax_url}}";
16 16 </script>
17 17
18 <link rel="stylesheet" href="static/jquery/css/themes/aristo/jquery-wijmo.css" type="text/css" />
19 <link rel="stylesheet" href="static/codemirror/lib/codemirror.css">
20 <link rel="stylesheet" href="static/codemirror/mode/markdown/markdown.css">
21 <link rel="stylesheet" href="static/codemirror/mode/rst/rst.css">
22 <link rel="stylesheet" href="static/codemirror/theme/ipython.css">
23 <link rel="stylesheet" href="static/codemirror/theme/default.css">
18 <link rel="stylesheet" href="/static/jquery/css/themes/aristo/jquery-wijmo.css" type="text/css" />
19 <link rel="stylesheet" href="/static/codemirror/lib/codemirror.css">
20 <link rel="stylesheet" href="/static/codemirror/mode/markdown/markdown.css">
21 <link rel="stylesheet" href="/static/codemirror/mode/rst/rst.css">
22 <link rel="stylesheet" href="/static/codemirror/theme/ipython.css">
23 <link rel="stylesheet" href="/static/codemirror/theme/default.css">
24 24
25 <link rel="stylesheet" href="static/prettify/prettify.css"/>
25 <link rel="stylesheet" href="/static/prettify/prettify.css"/>
26 26
27 <link rel="stylesheet" href="static/css/boilerplate.css" type="text/css" />
28 <link rel="stylesheet" href="static/css/layout.css" type="text/css" />
29 <link rel="stylesheet" href="static/css/base.css" type="text/css" />
30 <link rel="stylesheet" href="static/css/notebook.css" type="text/css" />
31 <link rel="stylesheet" href="static/css/renderedhtml.css" type="text/css" />
27 <link rel="stylesheet" href="/static/css/boilerplate.css" type="text/css" />
28 <link rel="stylesheet" href="/static/css/layout.css" type="text/css" />
29 <link rel="stylesheet" href="/static/css/base.css" type="text/css" />
30 <link rel="stylesheet" href="/static/css/notebook.css" type="text/css" />
31 <link rel="stylesheet" href="/static/css/renderedhtml.css" type="text/css" />
32 32
33 33 {% comment In the notebook, the read-only flag is used to determine %}
34 34 {% comment whether to hide the side panels and switch off input %}
35 35 <meta name="read_only" content="{{read_only and not logged_in}}"/>
36 36
37 37 </head>
38 38
39 39 <body
40 40 data-project={{project}} data-notebook-id={{notebook_id}}
41 41 data-base-project-url={{base_project_url}} data-base-kernel-url={{base_kernel_url}}
42 42 >
43 43
44 44 <div id="header">
45 <span id="ipython_notebook"><h1><a href='..' alt='dashboard'><img src='static/ipynblogo.png' alt='IPython Notebook'/></a></h1></span>
45 <span id="ipython_notebook"><h1><a href='..' alt='dashboard'><img src='/static/ipynblogo.png' alt='IPython Notebook'/></a></h1></span>
46 46 <span id="save_widget">
47 47 <input type="text" id="notebook_name" size="20"></textarea>
48 48 <button id="save_notebook"><u>S</u>ave</button>
49 49 </span>
50 50 <span id="quick_help_area">
51 51 <button id="quick_help">Quick<u>H</u>elp</button>
52 52 </span>
53 53
54 54 <span id="login_widget">
55 55 {% comment This is a temporary workaround to hide the logout button %}
56 56 {% comment when appropriate until notebook.html is templated %}
57 57 {% if logged_in %}
58 58 <button id="logout">Logout</button>
59 59 {% elif not logged_in and login_available %}
60 60 <button id="login">Login</button>
61 61 {% end %}
62 62 </span>
63 63
64 64 <span id="kernel_status">Idle</span>
65 65 </div>
66 66
67 67 <div id="main_app">
68 68
69 69 <div id="left_panel">
70 70
71 71 <div id="notebook_section">
72 72 <div class="section_header">
73 73 <h3>Notebook</h3>
74 74 </div>
75 75 <div class="section_content">
76 76 <div class="section_row">
77 77 <span id="new_open" class="section_row_buttons">
78 78 <button id="new_notebook">New</button>
79 79 <button id="open_notebook">Open</button>
80 80 </span>
81 81 <span class="section_row_header">Actions</span>
82 82 </div>
83 83 <div class="section_row">
84 84 <span>
85 85 <select id="download_format">
86 86 <option value="json">ipynb</option>
87 87 <option value="py">py</option>
88 88 </select>
89 89 </span>
90 90 <span class="section_row_buttons">
91 91 <button id="download_notebook">Download</button>
92 92 </span>
93 93 </div>
94 94 <div class="section_row">
95 95 <span class="section_row_buttons">
96 96 <span id="print_widget">
97 97 <button id="print_notebook">Print</button>
98 98 </span>
99 99 </span>
100 100 </div>
101 101 </div>
102 102 </div>
103 103
104 104 <div id="cell_section">
105 105 <div class="section_header">
106 106 <h3>Cell</h3>
107 107 </div>
108 108 <div class="section_content">
109 109 <div class="section_row">
110 110 <span class="section_row_buttons">
111 111 <button id="delete_cell"><u>D</u>elete</button>
112 112 </span>
113 113 <span class="section_row_header">Actions</span>
114 114 </div>
115 115 <div class="section_row">
116 116 <span id="cell_type" class="section_row_buttons">
117 117 <button id="to_code"><u>C</u>ode</button>
118 118 <!-- <button id="to_html">HTML</button>-->
119 119 <button id="to_markdown"><u>M</u>arkdown</button>
120 120 </span>
121 121 <span class="button_label">Format</span>
122 122 </div>
123 123 <div class="section_row">
124 124 <span id="cell_output" class="section_row_buttons">
125 125 <button id="toggle_output"><u>T</u>oggle</button>
126 126 <button id="clear_all_output">ClearAll</button>
127 127 </span>
128 128 <span class="button_label">Output</span>
129 129 </div>
130 130 <div class="section_row">
131 131 <span id="insert" class="section_row_buttons">
132 132 <button id="insert_cell_above"><u>A</u>bove</button>
133 133 <button id="insert_cell_below"><u>B</u>elow</button>
134 134 </span>
135 135 <span class="button_label">Insert</span>
136 136 </div>
137 137 <div class="section_row">
138 138 <span id="move" class="section_row_buttons">
139 139 <button id="move_cell_up">Up</button>
140 140 <button id="move_cell_down">Down</button>
141 141 </span>
142 142 <span class="button_label">Move</span>
143 143 </div>
144 144 <div class="section_row">
145 145 <span id="run_cells" class="section_row_buttons">
146 146 <button id="run_selected_cell">Selected</button>
147 147 <button id="run_all_cells">All</button>
148 148 </span>
149 149 <span class="button_label">Run</span>
150 150 </div>
151 151 <div class="section_row">
152 152 <span id="autoindent_span">
153 153 <input type="checkbox" id="autoindent" checked="true"></input>
154 154 </span>
155 155 <span class="checkbox_label" id="autoindent_label">Autoindent:</span>
156 156 </div>
157 157 </div>
158 158 </div>
159 159
160 160 <div id="kernel_section">
161 161 <div class="section_header">
162 162 <h3>Kernel</h3>
163 163 </div>
164 164 <div class="section_content">
165 165 <div class="section_row">
166 166 <span id="int_restart" class="section_row_buttons">
167 167 <button id="int_kernel"><u>I</u>nterrupt</button>
168 168 <button id="restart_kernel">Restart</button>
169 169 </span>
170 170 <span class="section_row_header">Actions</span>
171 171 </div>
172 172 <div class="section_row">
173 173 <span id="kernel_persist">
174 174 {% if kill_kernel %}
175 175 <input type="checkbox" id="kill_kernel" checked="true"></input>
176 176 {% else %}
177 177 <input type="checkbox" id="kill_kernel"></input>
178 178 {% end %}
179 179 </span>
180 180 <span class="checkbox_label" id="kill_kernel_label">Kill kernel upon exit:</span>
181 181 </div>
182 182 </div>
183 183 </div>
184 184
185 185 <div id="help_section">
186 186 <div class="section_header">
187 187 <h3>Help</h3>
188 188 </div>
189 189 <div class="section_content">
190 190 <div class="section_row">
191 191 <span id="help_buttons0" class="section_row_buttons">
192 192 <a id="python_help" href="http://docs.python.org" target="_blank">Python</a>
193 193 <a id="ipython_help" href="http://ipython.org/documentation.html" target="_blank">IPython</a>
194 194 </span>
195 195 <span class="section_row_header">Links</span>
196 196 </div>
197 197 <div class="section_row">
198 198 <span id="help_buttons1" class="section_row_buttons">
199 199 <a id="numpy_help" href="http://docs.scipy.org/doc/numpy/reference/" target="_blank">NumPy</a>
200 200 <a id="scipy_help" href="http://docs.scipy.org/doc/scipy/reference/" target="_blank">SciPy</a>
201 201 </span>
202 202 </div>
203 203 <div class="section_row">
204 204 <span id="help_buttons2" class="section_row_buttons">
205 205 <a id="matplotlib_help" href="http://matplotlib.sourceforge.net/" target="_blank">MPL</a>
206 206 <a id="sympy_help" href="http://docs.sympy.org/dev/index.html" target="_blank">SymPy</a>
207 207 </span>
208 208 </div>
209 209 <div class="section_row">
210 210 <span class="help_string">run selected cell</span>
211 211 <span class="help_string_label">Shift-Enter :</span>
212 212 </div>
213 213 <div class="section_row">
214 214 <span class="help_string">run selected cell in-place</span>
215 215 <span class="help_string_label">Ctrl-Enter :</span>
216 216 </div>
217 217 <div class="section_row">
218 218 <span class="help_string">show keyboard shortcuts</span>
219 219 <span class="help_string_label">Ctrl-m h :</span>
220 220 </div>
221 221 </div>
222 222 </div>
223 223
224 224 <div id="config_section">
225 225 <div class="section_header">
226 226 <h3>Configuration</h3>
227 227 </div>
228 228 <div class="section_content">
229 229 <div class="section_row">
230 230 <span id="tooltipontab_span">
231 231 <input type="checkbox" id="tooltipontab" checked="true"></input>
232 232 </span>
233 233 <span class="checkbox_label" id="tooltipontab_label">Tooltip on tab:</span>
234 234 </div>
235 235 <div class="section_row">
236 236 <span id="smartcompleter_span">
237 237 <input type="checkbox" id="smartcompleter" checked="true"></input>
238 238 </span>
239 239 <span class="checkbox_label" id="smartcompleter_label">Smart completer:</span>
240 240 </div>
241 241 <div class="section_row">
242 242 <span id="timebeforetooltip_span">
243 243 <input type="text" id="timebeforetooltip" value="1200" size='6'></input>
244 244 <span class="numeric_input_label" id="timebeforetooltip_unit">milliseconds</span>
245 245 </span>
246 246 <span class="numeric_input_label" id="timebeforetooltip_label">Time before tooltip : </span>
247 247 </div>
248 248 </div>
249 249 </div>
250 250
251 251 </div>
252 252 <div id="left_panel_splitter"></div>
253 253 <div id="notebook_panel">
254 254 <div id="notebook"></div>
255 255 <div id="pager_splitter"></div>
256 256 <div id="pager"></div>
257 257 </div>
258 258
259 259 </div>
260 260
261 <script src="static/jquery/js/jquery-1.6.2.min.js" type="text/javascript" charset="utf-8"></script>
262 <script src="static/jquery/js/jquery-ui-1.8.14.custom.min.js" type="text/javascript" charset="utf-8"></script>
263 <script src="static/jquery/js/jquery.autogrow.js" type="text/javascript" charset="utf-8"></script>
261 <script src="/static/jquery/js/jquery-1.6.2.min.js" type="text/javascript" charset="utf-8"></script>
262 <script src="/static/jquery/js/jquery-ui-1.8.14.custom.min.js" type="text/javascript" charset="utf-8"></script>
263 <script src="/static/jquery/js/jquery.autogrow.js" type="text/javascript" charset="utf-8"></script>
264 264
265 <script src="static/codemirror/lib/codemirror.js" charset="utf-8"></script>
266 <script src="static/codemirror/mode/python/python.js" charset="utf-8"></script>
267 <script src="static/codemirror/mode/htmlmixed/htmlmixed.js" charset="utf-8"></script>
268 <script src="static/codemirror/mode/xml/xml.js" charset="utf-8"></script>
269 <script src="static/codemirror/mode/javascript/javascript.js" charset="utf-8"></script>
270 <script src="static/codemirror/mode/css/css.js" charset="utf-8"></script>
271 <script src="static/codemirror/mode/rst/rst.js" charset="utf-8"></script>
272 <script src="static/codemirror/mode/markdown/markdown.js" charset="utf-8"></script>
265 <script src="/static/codemirror/lib/codemirror.js" charset="utf-8"></script>
266 <script src="/static/codemirror/mode/python/python.js" charset="utf-8"></script>
267 <script src="/static/codemirror/mode/htmlmixed/htmlmixed.js" charset="utf-8"></script>
268 <script src="/static/codemirror/mode/xml/xml.js" charset="utf-8"></script>
269 <script src="/static/codemirror/mode/javascript/javascript.js" charset="utf-8"></script>
270 <script src="/static/codemirror/mode/css/css.js" charset="utf-8"></script>
271 <script src="/static/codemirror/mode/rst/rst.js" charset="utf-8"></script>
272 <script src="/static/codemirror/mode/markdown/markdown.js" charset="utf-8"></script>
273 273
274 <script src="static/pagedown/Markdown.Converter.js" charset="utf-8"></script>
274 <script src="/static/pagedown/Markdown.Converter.js" charset="utf-8"></script>
275 275
276 <script src="static/prettify/prettify.js" charset="utf-8"></script>
276 <script src="/static/prettify/prettify.js" charset="utf-8"></script>
277 277
278 <script src="static/js/namespace.js" type="text/javascript" charset="utf-8"></script>
279 <script src="static/js/utils.js" type="text/javascript" charset="utf-8"></script>
280 <script src="static/js/cell.js" type="text/javascript" charset="utf-8"></script>
281 <script src="static/js/codecell.js" type="text/javascript" charset="utf-8"></script>
282 <script src="static/js/textcell.js" type="text/javascript" charset="utf-8"></script>
283 <script src="static/js/kernel.js" type="text/javascript" charset="utf-8"></script>
284 <script src="static/js/kernelstatus.js" type="text/javascript" charset="utf-8"></script>
285 <script src="static/js/layout.js" type="text/javascript" charset="utf-8"></script>
286 <script src="static/js/savewidget.js" type="text/javascript" charset="utf-8"></script>
287 <script src="static/js/quickhelp.js" type="text/javascript" charset="utf-8"></script>
288 <script src="static/js/loginwidget.js" type="text/javascript" charset="utf-8"></script>
289 <script src="static/js/pager.js" type="text/javascript" charset="utf-8"></script>
290 <script src="static/js/panelsection.js" type="text/javascript" charset="utf-8"></script>
291 <script src="static/js/printwidget.js" type="text/javascript" charset="utf-8"></script>
292 <script src="static/js/leftpanel.js" type="text/javascript" charset="utf-8"></script>
293 <script src="static/js/notebook.js" type="text/javascript" charset="utf-8"></script>
294 <script src="static/js/notebookmain.js" type="text/javascript" charset="utf-8"></script>
278 <script src="/static/js/namespace.js" type="text/javascript" charset="utf-8"></script>
279 <script src="/static/js/utils.js" type="text/javascript" charset="utf-8"></script>
280 <script src="/static/js/cell.js" type="text/javascript" charset="utf-8"></script>
281 <script src="/static/js/codecell.js" type="text/javascript" charset="utf-8"></script>
282 <script src="/static/js/textcell.js" type="text/javascript" charset="utf-8"></script>
283 <script src="/static/js/kernel.js" type="text/javascript" charset="utf-8"></script>
284 <script src="/static/js/kernelstatus.js" type="text/javascript" charset="utf-8"></script>
285 <script src="/static/js/layout.js" type="text/javascript" charset="utf-8"></script>
286 <script src="/static/js/savewidget.js" type="text/javascript" charset="utf-8"></script>
287 <script src="/static/js/quickhelp.js" type="text/javascript" charset="utf-8"></script>
288 <script src="/static/js/loginwidget.js" type="text/javascript" charset="utf-8"></script>
289 <script src="/static/js/pager.js" type="text/javascript" charset="utf-8"></script>
290 <script src="/static/js/panelsection.js" type="text/javascript" charset="utf-8"></script>
291 <script src="/static/js/printwidget.js" type="text/javascript" charset="utf-8"></script>
292 <script src="/static/js/leftpanel.js" type="text/javascript" charset="utf-8"></script>
293 <script src="/static/js/notebook.js" type="text/javascript" charset="utf-8"></script>
294 <script src="/static/js/notebookmain.js" type="text/javascript" charset="utf-8"></script>
295 295
296 296 </body>
297 297
298 298 </html>
@@ -1,43 +1,43 b''
1 1 {% extends layout.html %}
2 2
3 3 {% block title %}
4 4 IPython Dashboard
5 5 {% end %}
6 6
7 7 {% block stylesheet %}
8 <link rel="stylesheet" href="static/css/projectdashboard.css" type="text/css" />
8 <link rel="stylesheet" href="/static/css/projectdashboard.css" type="text/css" />
9 9 {% end %}
10 10
11 11 {% block meta %}
12 12 <meta name="read_only" content="{{read_only}}"/>
13 13 {% end %}
14 14
15 15 {% block params %}
16 16 data-project={{project}}
17 17 data-base-project-url={{base_project_url}}
18 18 data-base-kernel-url={{base_kernel_url}}
19 19 {% end %}
20 20
21 21 {% block content_panel %}
22 22 {% if logged_in or not read_only %}
23 23
24 24 <div id="content_toolbar">
25 25 <span id="drag_info">Drag files onto the list to import
26 26 notebooks.</span>
27 27
28 28 <span id="notebooks_buttons">
29 29 <button id="new_notebook">New Notebook</button>
30 30 </span>
31 31 </div>
32 32
33 33 {% end %}
34 34
35 35 <div id="notebook_list">
36 36 <div id="project_name"><h2>{{project}}</h2></div>
37 37 </div>
38 38 {% end %}
39 39
40 40 {% block script %}
41 <script src="static/js/notebooklist.js" type="text/javascript" charset="utf-8"></script>
42 <script src="static/js/projectdashboardmain.js" type="text/javascript" charset="utf-8"></script>
41 <script src="/static/js/notebooklist.js" type="text/javascript" charset="utf-8"></script>
42 <script src="/static/js/projectdashboardmain.js" type="text/javascript" charset="utf-8"></script>
43 43 {% end %}
@@ -1,924 +1,963 b''
1 1 {
2 2 "metadata": {
3 3 "name": "00_notebook_tour"
4 4 },
5 5 "nbformat": 2,
6 6 "worksheets": [
7 7 {
8 8 "cells": [
9 9 {
10 10 "cell_type": "markdown",
11 11 "source": [
12 12 "# A brief tour of the IPython notebook",
13 13 "",
14 14 "This document will give you a brief tour of the capabilities of the IPython notebook. ",
15 15 "You can view its contents by scrolling around, or execute each cell by typing `Shift-Enter`.",
16 16 "After you conclude this brief high-level tour, you should read the accompanying notebook ",
17 17 "titled `01_notebook_introduction`, which takes a more step-by-step approach to the features of the",
18 18 "system. ",
19 19 "",
20 20 "The rest of the notebooks in this directory illustrate various other aspects and ",
21 21 "capabilities of the IPython notebook; some of them may require additional libraries to be executed.",
22 22 "",
23 23 "**NOTE:** This notebook *must* be run from its own directory, so you must ``cd``",
24 24 "to this directory and then start the notebook, but do *not* use the ``--notebook-dir``",
25 25 "option to run it from another location.",
26 26 "",
27 27 "The first thing you need to know is that you are still controlling the same old IPython you're used to,",
28 28 "so things like shell aliases and magic commands still work:"
29 29 ]
30 30 },
31 31 {
32 32 "cell_type": "code",
33 33 "collapsed": false,
34 34 "input": [
35 35 "pwd"
36 36 ],
37 37 "language": "python",
38 38 "outputs": [
39 39 {
40 40 "output_type": "pyout",
41 41 "prompt_number": 1,
42 42 "text": [
43 43 "u&apos;/home/fperez/ipython/ipython/docs/examples/notebooks&apos;"
44 44 ]
45 45 }
46 46 ],
47 47 "prompt_number": 1
48 48 },
49 49 {
50 50 "cell_type": "code",
51 51 "collapsed": false,
52 52 "input": [
53 53 "ls"
54 54 ],
55 55 "language": "python",
56 56 "outputs": [
57 57 {
58 58 "output_type": "stream",
59 59 "stream": "stdout",
60 60 "text": [
61 61 "00_notebook_tour.ipynb python-logo.svg",
62 62 "01_notebook_introduction.ipynb sympy.ipynb",
63 63 "animation.m4v sympy_quantum_computing.ipynb",
64 64 "display_protocol.ipynb trapezoid_rule.ipynb",
65 65 "formatting.ipynb"
66 66 ]
67 67 }
68 68 ],
69 69 "prompt_number": 2
70 70 },
71 71 {
72 72 "cell_type": "code",
73 73 "collapsed": false,
74 74 "input": [
75 75 "message = 'The IPython notebook is great!'",
76 76 "# note: the echo command does not run on Windows, it's a unix command.",
77 77 "!echo $message"
78 78 ],
79 79 "language": "python",
80 80 "outputs": [
81 81 {
82 82 "output_type": "stream",
83 83 "stream": "stdout",
84 84 "text": [
85 85 "The IPython notebook is great!"
86 86 ]
87 87 }
88 88 ],
89 89 "prompt_number": 3
90 90 },
91 91 {
92 92 "cell_type": "markdown",
93 93 "source": [
94 94 "Plots with matplotlib: do *not* execute the next below if you do not have matplotlib installed or didn't start up ",
95 95 "this notebook with the `--pylab` option, as the code will not work."
96 96 ]
97 97 },
98 98 {
99 99 "cell_type": "code",
100 100 "collapsed": false,
101 101 "input": [
102 102 "x = linspace(0, 3*pi, 500)",
103 103 "plot(x, sin(x**2))",
104 104 "title('A simple chirp');"
105 105 ],
106 106 "language": "python",
107 107 "outputs": [
108 108 {
109 109 "output_type": "display_data",
110 110 "png": "iVBORw0KGgoAAAANSUhEUgAAAX0AAAECCAYAAAASDQdFAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJztfXl0VtW5/vOFIAnzkIkhzJEQEAkCERUMSkGrYlutys+F\nS6FepLXSex1WvfVW6Kpee60XvV4XpX94FYe2FrRo1VJQY0SF4AQKsRKEEmQKCYSMkOH7/bHdycnJ\nGfZ4zvmS/ayVBUnOHr4v33n2c5733e+OxePxOAwMDAwMugWSwp6AgYGBgUFwMKRvYGBg0I1gSN/A\nwMCgG8GQvoGBgUE3giF9AwMDg24EQ/oGBgYG3QiG9A0SHi+88AIWLFigpe9bb70V//Ef/6G0z5Ur\nV2Lx4sWuv588eTKKi4uVjmlgQGFI3yB0FBYWYvDgwTh79qxQ+5tvvhmbNm1SPCuCWCyGWCymvE8v\nfPHFF5gzZ47SMQ0MKAzpG4SKAwcOoKSkBBkZGXj11VfDno4jVO9flOmvpaVF4UwMuiMM6RuEinXr\n1mHevHlYvHgxnn32Wc9rN27ciLlz52LgwIEYO3YsXnzxRQDAM888g9mzZ7ddl5SUhOeeew5Tp07F\n8OHDsXr1ahw9ehQLFizAiBEj8OCDD6K5uRkAUFRUhBEjRuB///d/MXr0aCxYsADbt293ncOuXbtw\nxx13YOTIkbj77rtx8OBB12vLy8uxatUqjB8/HllZWfjP//xPAETpt7S04M4770RWVhZuuOEGlJaW\ntrUbPXo03n77bQDEClq0aBGWL1+OoUOH4plnnsHKlStx00034fbbb0dWVhaWLVuG8vJyn3fawIDA\nkL5BqFi3bh1uvPFG3HDDDdi0aROOHz/ueF1TUxNWrFiBRx55BKdOncKHH36IqVOnuvb73HPPYf36\n9Xj++edx77334uabb8YvfvELFBcX47nnnsOHH37Ydu3x48dRUlKCbdu2YdGiRbj88stRV1fXqc/K\nykoUFhbiyiuvxBdffIG0tDQsWrTIdQ5XX301Tp8+jeLiYpSVleHyyy8HQJT+hg0bcP7556O0tBQD\nBgzAww8/3NbObv9s2LABeXl52L9/P26++WYAwMsvv4zc3Fx8/vnnSE1NxQ033OA6DwMDKwzpG4SG\nrVu34ptvvsHChQuRk5ODvLy8NvVuRywWw9mzZ1FWVob6+npkZmYiLy/Pte/ly5dj/PjxmDt3LsaO\nHYupU6dizpw5GDt2LObNm4e33nqr7drm5masXLkSWVlZuPXWWzFlyhT87W9/6zA2QIj2+uuvx7XX\nXov+/fvjvvvuQ1lZGY4dO9Zp/NLSUhw6dAiPPvoohg0bhr59+2LmzJltv58wYQJuv/12DBo0CEuX\nLsWWLVtcX0t2djZ++tOfIiUlBSkpKQCAoUOH4u6770Z6ejoeeughfPbZZ6ioqHDtw8CAwpC+QWh4\n9tlnMX/+fPTr1w8A8MMf/tDV4klOTsaGDRuwfv16jBgxAkuXLsX+/ftd+z7//PPb/p+Zmdnp+2++\n+abt+759+2Ls2LFt30+bNg3btm3r1OeWLVvwwgsvYNCgQRg0aBDS0tJQV1eH9957r9O177zzDgoK\nCpCU5HyLWeeTlZWFY8eOobW11fHagoKCTj+bMmVK2//79OmDcePGoaSkxLG9gYEVhvQNQkFDQwNe\neuklvP322xg6dCiGDh2Kxx57DDt37sSuXbsc28yaNQuvvPIKDhw4gJ49e+K+++5TMpfa2lrs27ev\n7fuPP/4Ys2bN6nTdZZddhltuuQUnT55s+6qtrcX111/veG1JSYlj4JU3G6hHjx6dfrZz585O83da\nHAwM7DCkbxAK/vKXvyA5ORmlpaXYuXMndu7cidLSUsyePRvr1q3rdP3x48exceNG1NXVoUePHkhJ\nSWl7QmCBNWPGnj3To0cP/OpXv8LRo0exbt06fPHFF5g/f37btfT6G264AS+//DL+8pe/oK6uDnV1\ndXj99ddRW1vbabzc3FyMGDECP//5z3H48GHU1NS0KXEV2UBHjx7F6tWrUVFRgV/+8pfIz89HWlqa\ndL8GXR+G9A1Cwbp167BkyRKMGDECGRkZyMjIQGZmJu688068+OKLnayO1tZWrF69GsOHD0dubi6q\nqqqwatUqAJ1z6Z2UtP331u+zsrIwc+ZMFBQU4Pnnn8ff//539O3bt9O1gwYNwqZNm/DOO+/g3HPP\nRU5OjuMCRfHaa68hNTUVF110Ec4991wUFRU5ju82Z69rr7vuOuzZsweTJ09GbW0t/vjHP7rOw8DA\nipg5RMWgO6OoqAiLFy9OqJTHVatWoaysDM8991zYUzFIQEgp/SVLliAzMxPnnXee6zX3338/xo4d\niwsuuABffvmlzHAGBgZQv1nMoHtBivRvu+22DqltdpSUlOC9997DRx99hHvuuQf33HOPzHAGBlqg\nusyCbugoDWHQfSBt7xw4cADXXHMNPv/8806/e/LJJ9HS0oKf/exnAIBx48Z1yJIwMDAwMAgWyTo7\nLykp6VBNMD09Hfv27cO4ceM6XWuUi4GBgYEYeLS71uwda7obhRe50+uj9FVZGceYMXH89rdxtLbG\n8cEHcaSnx7Fjh74xH3zwQe2vKy8vjoceiiM7O46mpuDf1/vui+O88+KYN0/fe9HUFAdAvurq1M19\n2zbS5403qulv2rQ4pk6V+1y8+y6Z08aNYnM4cIC0X72av21LC2n72GP8bQcNIm152nzwQRzAgzh+\nnL3NggV84+zaRf6+Bw+yXf9f/xXHrFnqPmM8X7zQSvoFBQXYs2dP2/cVFRUddj4mAu66C1i4ELj7\nbiAWA2bNAv77v4F/+RcgUQsefv01UFUF3H8/MGAA8Omnwc/hww+Bn/8c+OgjQOBzy4RPPgEmTwYm\nTQK++kpdv2VlwMiRgAqnsqEB+PJL0ldVlXg/39Znw969Yu3pBuUdO/jb0nJJlnJGzDh5EuClBFqb\n7vBh9jaDBpF/WT9r770H/OlPgMs+wU44fhz45z/Z5xMmtJP+hg0bUFlZiRdffBETJ07UOZxy7NhB\nbqZf/7rjz2++GUhOBiJaCdgXmzYB8+eTRezSS4Ggz+tobQV27iRz6NuXLEI68OWXwNSpwMSJ7USh\nAmVlwLXXkj5dKicw48svgXHjgOxsPhKz49gx8jpFF7dDh4DevYETJ/jb0kKjZWV87RoayL+NjXzt\nqI60VNLwRVMT+Zf1PT59uuO/fqioAI4cAQSPhAgUUqS/aNEiXHTRRfjHP/6B7OxsPP3001i7di3W\nrl0LAJg5cyYuueQSTJ8+HY899hgeffRRJZMOCvfdB/zqV4SYrIjFgHvvBZ54Qs+4hYWFejr+Fjt2\nABddRP4/ezawdavW4TrhwAGgf38gLQ3Izwc++8z9Wpn34uBBosh1kP706eQ1HDok19fx40BWFpCR\n0a6Y3eD1XlRUABdfLKf0p04VI/3ycuC884Dqar52p04BAweSMXme9vbvB/r0KeQifVoTj/XpjJf0\njx8nr0H28xAEpEj/D3/4Aw4fPoyzZ8+ivLwcS5YswbJly7Bs2bK2ax555BHs378fH3/8cUIp/U8+\nIR+QW291/v3ChcDnn+v5I+sm/c8+Izc4AEyZAnzxhdbhOmHvXiA3l/x/7Fjvx2IVpD9+vBorhmLf\nPjLvzEx/ovbDiRNAejrpy6FYZwf4kf5554nP59AhedI/dYqv3alTZME75xx2cgWAmhpg8mQ+0j96\nlDxROVTMcMTp03zzqqgAUlPbn3qiDFOGwQVPPgn8+MfExnFCr17A974HvPRSsPOSxdmzxFKg++nG\njyc3LX3UDgKUjAHyry4vlI7DQqg8OH6c9JmeLkaSVlRUkCce2TlWVAA5OfzES3H4MBEAIq+nooJ8\njk6f5lPsVOmnp5M+WFFbS17r0aPsbY4dIws1K+nX1AAjRvAp/bFjSbuow5C+AyorgVdeAX70I+/r\nbroJSLSSJ/v2kQ9z797k+549iQJSGej0g5X0R43Sp450kX5lJTBkCD9ZOYEqfRZ7xwuypH/qFPlc\ntLYC9fV8bWtqSKA0JYWdVOmYoqSflQU4nHPjiDNnSNxg2DD2NqdPk/eDlcQrKshnLUjxJApD+g74\n05+AK68kCswLc+cSf1cmABc09u4l5GCFas/bD0Ep/cOHyY2ukvSbmwkRiJCVE1Qo/ZYWkgUzahQh\nNxq05EFNDdCvH5lLZSVf29pa0nbgQL5F5+RJsliIkH5mJjuB19cDffqQLx7SHz6cTek3N5OFJT3d\nkH7C4oUXSIaOH5KTgcJC4NviiQmBvXvJo7gVY8aQ4GpQKC/vqPR1kH5TE7nBKTlXVZGbUxZVVYSo\nkpKio/Srqkjqbc+e5F8ef5zCSvq8r6m2liQ7DBzIF8ylSr9fP3YypuNlZLA/kTQ0EL9dF+k3NpKn\nnNRU/qekMGBI34avvyZWx4IFbNdfdll7jnQioKyss9IfPTp40h8xgvw/LY3cWKpT3SorgcGDSaZV\ncjL5v6z/DpA+hgwh/1fp6fMSphWUPAF+tU1BSX/AAP55WNvyjE3n3bs3H1lS0udR+r1785M+q6dP\nF5XUVKP0ExJ//jNw/fVENbFg7tzEI3270h89OtiNJTRNESCKecgQNYRsxYkTHe05VRZPZWV7vyqU\nflUVWZD69RNT6EC7vQLIkz4PMVrHl1H6PKRPrZS0NH6l37cvX/YOK+lTpd+7tyH9hMTGjSQrhxV5\neeQm8TiuNVI4eJBYKlYEae80NpKv/v3bfyYbxHSClZwBNQQNdFT6Q4bw+992nD5N3ov+/cUzPyjp\nAnKk37+/GOnX1LSTPs/Yp0+ThaZ3b/Yx6+r4/XndSr+x0Sj9hMWxY2S3H09qeCwGzJkDvP++tmkp\nQzxOSD87u+PPR40ipK+rHIIVx48TkreWYMrIUEPIVljJGSA+vKh9YgXN3AHkiJqCKmwZpU/7AMRI\nv6mJKOiUFHGl368feT94XkNDAyFjHqVPF7g+ffR5+i0tpE1WFtvft6Gh3dM3pJ9geP11UhqgVy++\ndjNmkBoyUceJE+QGs+8w7tOHvGbRdD8eUNK3QofSt9s7AweSbBFZnDrVXseFl+TsiMfbCVumL1ml\nT+cQi8nZO7ykR8lYhPR5ng54lf6ZM+R+SE1lKxFhArkJjI0bSU0VXkyfnhikb02VtGPYsGBST48d\n60z66el6SN+q9EVtDzuoJQHIk35jIwky9+xJSCYeJ4TDCyvp9+vH//RhfVIQtXeoTcNDejKkr1Pp\nUxLv1Yvt70HtHePpJxjq64F33iH5+by44AJS2kBFSqBOOFk7FEGRflBK32rDAOpIn3rfQLslI2qL\nWck2FhMjbHs/vMRrb89L+tQK6d2bX+nX14uTfkoKIWSWSreiSj8lhU3pG3snQfH228C0aSSTghcD\nBpCc3iA3OIng8OH2VEk7hg4NjvTT0zv+TCQ33A/V1e1pjIBapU9Jv1cvkn0kos6BjmQLiD85WJW+\njFIXaU8Dq0lJwdk7ffqQRZJVWfNm75w5Q0j8nHNIvMOvkqoJ5CYo/v534IorxNsngsVz9Gh7qqQd\nQSn9qqqOChwgC60Kv92K6uqOGUKDBqkZw0r6gJzFY31qoH2JKH0r6atQ+jylFGTGFiF9+lRBx2NZ\noHiVfmMjWdBjMUL8fntIqNIXee/DgCH9b7F5M/Cd74i3v+AC4OOP1c1HB6JA+tZAKIUqQraiupo8\ngVGotHdUqHOnvkQzeGTtHaqeAULgvEqfkrCo0ufx56n1ArC/VrpQsNo11jFY2lgDuUbpJwjKy0ng\nLz9fvI/Jk4Hdu9XNSQe8SF9H2qQTTp7saLsAiUX6qpV+FOwdSr4i7am1AQRj71CC5ZkrjR3wBGbp\nGCxtjL2TgNi8Gbj8cuJLiiLRSV/V5iU/OCl9XfZOUKQvmv/vpPTDCOSGSfq8efp2pc8yVzoOK+lb\nx2BpYwK5CYjNm0l+vgyGDiVBH9VZKCrhRfppaepLITjBTenLnA/rBDvp89aFcYNKe8ea/gnw2RxW\n2H11XqVvJW4R0qeqOAhP3zoezeDxA6/St9s7LErfePoJhNZWYMsWOT8fIEGfSZOiq/ZbW0mOfGam\n8+/DVPr9+5ObRWXKq530RVW0HSrtHWvNHECcNKy+usjCIaP0qcoFgrF3eFU4Had37/agrF+Krd3e\nYfH0U1PZYwZho9uT/s6dxF5wy1/nQZRJ/+RJogbddhtTpa+7FIOT0k9KUqfEAXJjNzW1EyHQHqCU\neX3WHbQUIh46Ba3zTiFK+vaMlqDtHRHSb2pqr4DK83TC67cD5P1ISSGfs549/bNxRO0dmuIZdXR7\n0n/3XVIpUwWi7Ot7WTtA+2YUmR2mfojHO5YBtkKlxUNVvrW+T3IyeY0yj98NDYQ0rBVYZUnfujDJ\nkD4lbRF7x9qeV61arSHe1EvajkVNU4go/bNn29uwpGDSPH3WMeh7wNJ3FGBI/13g0kvV9DVpUvCH\njLPCj/QBPZukrKitJTfROed0/p3KDB67tUMha/HU1TnXLYoS6cvaO7ykL2rv2EmfxXYBxJS+lfRZ\nSZwnZdOq9P1If+tWsV3/KtGtSb+1FXjvPVIlUwUmTAj2rFkesJC+ikNBvECPx3OCioqVFHbfnaJv\nX7kx7CQNRI/0ZZU+a5ExClF7xzpmUhJ5EmNRySJK/8yZdqHB0oZ3DHp9cjKxd7wWr8bG8J8GujXp\n795NrIbhw9X0N2wYUbM6LRJRREHpOwVxKWSLl1nhpMgBeaWfKKQfpNIXTdm0jgnoy6EHCMnykD7v\nGE1NxPKLxci/Xr5+czNZHMJEtyb94mJ11g5A/ug5OeQc2qghKkrfyc8H1GXXAB1TGFWO4UT6Isra\nrT8VpJ+aSkjKr16MW3tKSKyZVE72DotNI0r6sp4+r9JnWQQp6QP+Fo/12rDQrUlfpZ9PEVXSdypp\nbIfutM2glH6QpB+20m9uJl9UycZi/HXd7QTMo/atqrhHD3abxtoOEFP655yjz94RUfp0Tn5K35B+\nSIjHCemr8vMpokr6J050rm5ph+4NWkEpfVr50WkMnmJidkSR9ClhWzOVRIKxMqQvq9hF29EAsB9E\n7B2eJwOrZcOi9I29ExL+8Q/y4R49Wm2/USZ960lSTjBK3xtupC+aBqqK9O1zYiVQax8qlD7P2FYi\n5mkn4ulbFwrWlE2eHblWpe+3D8DYOyFCh7UDRJf07YeKOCFspa8ykOum9LuavWMnbEAu7ZK3vb1t\n0EpfRyDXbu+o9PSNvRMiVAdxKaJK+omg9BMxkBtF0k8EpS9K+kFl7/AsLLyBXGPvhADq5+sg/YwM\n8kdXXTVSBmfPEjJx2rBkRVdX+jIETftNBNJnLUTm1kcQnr6ovSOapy+avaNa6Rt7JyR8/TVJaRs3\nTn3fsRgwZgxw4ID6vkVRVUXqC1mDfU7QUdfeiqA2Z7kpfdkqiLqVvuxuWgqesgZAZ+KOur2jW+nz\nZOMAnQO5Jk8/gqAq348ERTFmDLB/v56+RcBi7QBEhVdX6yu65lYeAQhmc5YO0hfN04/H20v+UqSm\nyu2mpRCxd0Q9/TDsHd1K3x6Y9SN9E8hNAOjy8ylGj46W0mcl/eRkQiCqFLcd9jNhrVC9OcvN3tFB\n+o2NfJuhAEIMPXuS3HaKXr38t/HboSKQa1XPvO1lSF/U3uFR+i0t5G9D32fdpG8CuRGFLj+fImpK\nv7KSjfQBYr+oKnFsh70ssRWJqvSTktg3Cdn7spM1PYibpy+nfniUfjze2V/nIX1RxW7dJcvTzrpY\nsLxXTU3kOvpUz9pGF+mbQG4IOHiQkEJurr4xoqj0/dI1KQYO1Ofr20+KsiIIpS9TMgFwJn1A7Jg8\nu49OIbuxircP+sRhPSpUhvR5dsmKLhZWf54n5561DS/pW9W7CeRGEHQXri4/H4gm6Udd6ffpQwis\npUV+nCCVPiBO+k4H2vBm3titGYBP6dtJkc6BZ9EQtWlE2llJk6WNyPxElD7rjlxj74QA3dYOQEh/\n/379p1Cxgsfe0aX0m5vJzeBEmgBRmn36qFH7XkpfB+mLHJPnRNYifbmRNivp2z153jkEae/E4x1J\nkzX9kpf0rRk2ycn+xed4Fglj74QA3UFcgGSonHMOIdsogMfe0aX0a2qI+vZ6wlKVtumm9HUEcgG1\nSp833dKJ9EVPoqLgVfqyO2tZ21HCpJ8hVqVvHUckG0e1p2+UfoA4coQQ4OTJ+seKUjCXx97RpfS9\nrB0KVRu0vPL0ZT19pycIUaXvZu/w9GW3L2gfsvYO6yImk4UjY7uwtrG/P2GTvsnTDxjvvgvMnt0x\naKULUfL1o5C9w0L6KpR+SwshAqcgadQ8fTd7h9fTV630WatXOrXXae/QTByeNvbFRQfp81bZNEo/\nQATh51NkZwOHDgUzlh+ikL3DSvqySp8Ss5ONFCXSd1P6quwdGaXPc8B3kIFcmmlEwULIUbN3TCA3\nYATh51OMGAGUlwczlh9OniRlGFigU+m7bcyiUJG26RbEBcgN2drqfxO7QWUg10vpqwjkyih91rTL\neFxNtUzWdnaVzEr6OpV+a2vHzV8mTz9CqKggyvv884MZLypKv7WVqGe/YmsUia703YK4AFH/vXvz\nq3KKIJS+CtLnUfpOiw+r0m9pIVapfVcx68EmdtJnIWNeAtdt71jPx6XXG3snIiguBi6+OLhVNipK\nv6aGKF/rjemFMD193UofUFsrh0K10ufx9N0CuUF4+nZCBcSOMAT8yRIQt3eCIH0Kc1xihBCktQMQ\n0o+C0j91yr2csRMSPXvHS+kD4r5+UxNRtU43bHf19GXGdtrJy0PGrPPUTfr2bBy/Ra9L2DvFxcWY\nOHEicnJy8OSTT3b6fVFREQYMGID8/Hzk5+fj17/+teyQQggyiAsAw4aRw8j9NnboBi/ph6n0+/aV\nS6kE3NM1KURz9d2sHUCc9KOwOUvG03d6yhDN3mFR+iL2jkgcQEbp814fBqTXnBUrVmDt2rUYNWoU\nFixYgEWLFiHNlh946aWX4tVXX5UdShgnTwL79gEXXBDcmD17kjTJo0eJ6g8LXgeXOCFMpd+nD3m/\nZOB2gAqFqNL3In1Re0enpx+UvSOj9HkJ3G7vJCeTuEI87r7pT4T0repdhPS9hF7C2zvV1dUAgDlz\n5mDUqFGYP38+tm/f3um6eMj1CLZuBS68MPg3OwrBXK8jCp3Qpw+5uVhT9ljBSvq6lb6op69D6bvZ\nO7KeflD2jl2t84ztZO/wFEIDCNEnJ6tV4vY2vKTPMp+Etnd27NiBXEu5yry8PGzbtq3DNbFYDB98\n8AGmTp2Kf/u3f8O+fftkhhRC0NYORRR8fV57JxYj16u2eIIifV1K3+moRIrU1MRN2XR64hANxgLi\nxyWykrFT4Fgl6dtTMFk8fZ7+o6D0ta8506ZNQ3l5OXr27Ilnn30WK1aswF//+lfHa1euXNn2/8LC\nQhQWFiqZw7vvAo89pqQrLkQhg4fX3gHaST8jQ908Ep30/ewdEaWvoqSDikCuaMqm21MCyz4IO+mL\nBHKB9liA299c1HO3pmDyKHc/e0eF0i8qKkJRUZFwe6nhZ8yYgXvvvbft+927d+OKK67ocE0/y52+\ndOlS/OIXv8CZM2fQy+HZ1kr6qlBTA5SWAjNnKu/aF1Gxd3hJX+V5tRRBkb4XOdMxohDI9VL6PE9Z\nOjZn8eTaOylvlrZOZMybsknb6Qy06rB3ZJW+XRCvWrWKq72UvTPg2x0/xcXFOHDgADZv3oyCgoIO\n1xw7dqzN03/ttdcwZcoUR8LXhfffB6ZPd77BdCMKSp/X0wfUnmJFERTpOx0qYoUOT19lwTVeTz9q\nKZs8pK9K6UeJxLuFvfP4449j2bJlaGpqwl133YW0tDSsXbsWALBs2TKsX78ea9asQXJyMqZMmYLH\nAvZZ6KEpYSCRlb4O0vcrw6BK6Wdluf9e1N7xWkxUK/2gq2zad2vzpGzKBIF5lb6Tpx+E0veza3iv\nDzuQKz38pZdeitLS0g4/W7ZsWdv/f/KTn+AnP/mJ7DDCKC4GfvWrcMaOQiBXxNMPU+nX1sqNw6L0\nRUjf7XhDIJplGGRr78jsyNWl9J3sHdWBXBHlbiXxIOwdWXTpHbl1dcDOncCsWeGMP2wYyTtXcQSg\nKKKk9BPZ03dT5kA0C66xKn23tEvd9o6o0ncL5LK2EVX6blnniWjvdGnS37oVmDbNmwR0wrpBKyxE\nwdOPx4PbkatT6buRfph5+iqUvqhad7KWWMjbfuwhbSeSsqlbucdiJH3TzbJJRHunS5P+W28Bl18e\n7hzCDuZGQemfPetet8YKmu/e2io+lp/SFw3kNjSoVfpRqbLploEjssGKtmVR7NZjD1nbhZG949cm\njOwdWXRp0t+yJXzSHzaMHNMYFqLg6fvtkqVISiLEL3PQSaJ4+joDudTnZlk83Xb0yqRs6lDstF3U\nSZ/3SSIMdFnSr6wEysrCyc+3YujQ8Ei/uZmQEQvhWqGa9P02TFkh6+u7lT+29h91e4eV9FtbSbzI\nTlKxmHjhM0DO3hFV7KKLBe/xhKpJ307iiVBwrcuS/jvvAJdc0vlDEjTCJP3qapKOx3smsA6lHxTp\nNzT42ztRD+TypFuec45zsTHWObn58k1N7sFLChESdmsX5OYs3kNOeO2dLl1wLcqIgp8PENI/fDic\nsUX8fECP0md92lBB+jo2Z3l5+mGlbLr1AYjXwAHIIiJKwrqVfqLbOyaQqxFRIv2wlL6Inw8kvr3j\npfRF6uQA/vZOGCmbXqTP+sTgRPoAm68vau94EavX04Wq7B2eFEy/MVQsKkGjS5J+eTkhvClTwp5J\nuKQfFaUftL3jpfRFVDngHcilRMKzH0OFp+9G2Dz9uPUhY9P4kbfb04WfNaJC6SclkS/WFEy/MZxS\nT936tlfwDAtdkvTfeguYO5ffy9aBsEmfN0cfSGx7x0/pi6hywFvpx2L8i4kqT1+X0mdJ23Syaag1\nJKJ2/SwlETtJVrmzXM+6I5cGfd0OfAkKEaBF9fj734F588KeBUFGBskkCuPYxKgo/aDsnZYW8j57\nBe9llL4JlMGbAAAgAElEQVRX0T4V+fW8/fh5+rqVvmhbt3aq/Xbaxu6hqyZ9VnsnCtYO0AVJv6WF\nkP6VV4Y9E4LkZGDIEOD48eDHFvX0U1IIeao6PYvH3pHZlUutHS8lJUr6XoFc3n5bW52tEaDdS2c5\nbE5XINc6Dy+4vQYR9c3aTtbTp+OwpmD6jcGzIzcKOfpAFyT9HTuIpZKdHfZM2hGWxSOq9GMxtTX1\ng7J3/Px8QI+nz9svJVqnxYnaIzKEDbA/MTiVYQD0Kn23xcKPwFWkbPq10bkj1yh9TXjjDeC73w17\nFh0R1q5cUU8fUGvxBGXv+G3MAtpvOr/0QDtU2jtuh6Jb+xItg0Ahq/RFPX1AzJunY6pU7W5teEnf\nK8DMU0MoCjn6QBck/TffjI61QxFWrr6o0gfUkn5Q2Tt+G7MoRNI2/UifR+k7HVFonx+rSlfh6btl\nEem0d9yUvoi9E6VArpe9E4UcfaCLkf6xY8DevcDFF4c9k44Iy94R9fQB9Uqfx94RranPovQBtbVy\nKFQFYAF2wvYjfdFSCoD+QK6I0jf2jhp0KdLftIlsyIrCG2tFonn6QNdW+iJpmyrz/1UtIF6kL1M/\nh7W9jE0jqvR5Sd/JUtFN+i0tzoF4Y+9oQBStHSBc0u9Onj5LIBfQp/RV5Nfz9OW3OUu3py9q76hc\nLKKm9L02mRl7RzGilqppRXdX+kFl7/htzKII296JitKnO4iddoiKlmFgGVul0g8ikMtTZRNwt3iM\nvaMYW7cCI0cCw4eHPZPO6O6efpD2jg6lTzd9ed2wUfT0WbJv3J4UZO0dEaUvmrIZdiCX9XqTp68Y\nr7wCfP/7Yc/CGVlZJMgscyIULxobCVmxkKATwrR3RA9R0RXIPXPGf9OXSqXPas3IKn0/0tdl76hs\np9rekd2c5XW9UfoKEY8T0v/BD8KeiTN69SLnw544EdyY1dXEzxet8xGmvSNK+jyBXB7S99uNC/Cf\nS+un9IPI01eh9FV6+rrKMASt9N08fRPIVYhPPyUftEmTwp6JO6jaDwoyfj4Qnr0jWu8eYFf6vHn6\nfsqc9qlqc5ZsEBZgI2233bh0DrrsHa8yDImesul1vQnkKsTLLxNrJ+zqdV7IzAyW9GX8fCA8pS96\nshWgL2VTNen7bc5SpfRl7Z0wCq6JBHLD9PR57CBj7yhElP18iqBJPypKv6Wl3RNnge4yDIC6MshW\n8KRsqlL6fp4+i70j015HwbVET9mk1xt7RyO++IKQU0FB2DPxRhikL5qjD6gjfUrErE9hQSl9XtL3\nW0y6mtLXae+IKv1EsXe8UjaNvaMAL74ILFoUjQNTvJBoSr9fPzWkz2PtAOQGisX4C6IB+pQ+SyBX\ndcqmCk8/rECuiE1Dx1RJ4PE4edIMsp6+1/XG3lGA1lZC+jffHPZM/NFdPX2eIC6FzOHlYdo7UUrZ\nDMLTj0rBNb9iaPanTNWePo+9Y5S+JD78kKjIKJyF64fuau/w5OhTiFo8Ou2dREvZVKH0RUsri2Th\nAGJWjdcC46asVdk19HqzIzdAvPAC8P/+X7SzdigSzd7p25cQL89h307gtXcA8WCuzpRNlZ5+Iij9\nMMowiOT38xK4SBs35e51vduO3CiQfgQeNsTQ2Aj8+c/kpKxEQKKRflJSe5njAQPE+xG1d6Kk9MPw\n9FmesnQrfS8CjsfdSUzH5qx4XI3f7tdG1Y5cU3BNAzZsAKZNA0aPDnsmbMjIACoqgivFIOvpAySY\nK3tkYpD2Dk8gV0eeftApm7qUOuC/aFCyc3rK1qH0W1pIYTh7wkZQSl9V9k4UlH7Ckv7atcCyZWHP\ngh29ehHyO3kymPFkPX1AHekHZe+E6elHLWWTRel77cgVVesybb3IVSR+EATp8zwZRMXeSUjS37MH\nKCsDrrkm7JnwIUiLR9beAdSkbQZp7+jcnKXa0w+i9o5OT99NrQNySt+LjHkzfsJS+sbe0YDf/x5Y\nsiQaqyYPMjKA48eDGUsV6Ydh7xilH40duSIbrFjbupGxbgIXadPV7J0IrDt8OHUKeO45UmQt0RCU\n0o/Ho0X6vPZO1JR+Q4P/a+BJ2UwEpe+3aMjYOyJKX8QSClPpG3tHIdasAa66ihyYkmgIivTr68mH\ny+2GZkX//vKkH8XNWWFX2WRR+ix96dyR67fwyNg7XV3pR73KZgSmwI6GBuCJJ4AtW8KeiRiCIn0V\nKh9Qp/R5F2iRmvotLYQw/MgZiIa9kwhK32+DVRQ8/SgGcr3q6bPYj7qRUEr/mWeAmTOByZPDnokY\nuiPp19YGY+9QYmbZqCeSsskSyOVJ2YyKp68je0ekcJpfOy8Cj2Ig1yh9BWhoAB5+mGzISlQERfoq\ncvQBNdk7ooHcw4f52rAGcQGj9Cl0qHXWtqpSNqO6OSvKgdyEUfpPPEFU/oUXhj0TcQSp9GVz9IHE\n2pzFGsQF9JA+JQq37fr2/hKh9o7O7B3ezVleKZth2Ttuu5KjflxiQij9I0eAxx4Dtm4NeyZySDR7\nR1UgV8Te4Q3kiij9eJzNDmIhfaBd7fu9XlUpm17Em5xMdn/Tnay87WU3Z/EWTgPECby52flvqZv0\n6XvLWsUzKvZOQij9FSuAf/kXYMKEsGciB0r68bjecaLk6YvaOzqVfnIy2c7vRUxWsNTeAdizblQo\nfaok3UgkFvMnbtkduUEGct0WmViMPy9eJO+eZ7OVsXcksWED8MknwAMPhD0TefTuTf7oqs6edYNK\nTz9R7B3WdE0KHouHV+n7QYXS94sL0H5kiDtqKZtu4/GSrG6P3m1HblTsnUiT/v79wPLlwB/+wHdD\nRxlBWDwqPX0VZRiCqL1TX8+XDseTq6+a9P2UPksmEAvps2ywCqP2jsr0SyB6pN/lj0ssLi7GxIkT\nkZOTgyeffNLxmvvvvx9jx47FBRdcgC+//JKp38pKsgnrl78EZsyQnWV0EBTpG6XvDZ60TR7S9yPr\neFxN9o4XYVv78SPuRCnD4JciGpa9w9N/l7F3VqxYgbVr12LLli146qmncOLEiQ6/LykpwXvvvYeP\nPvoI99xzD+655x7fPo8eBRYsAK6+GrjzTtkZRguJRPqygdx4XJz0RZS+TnuHdaev30LS1ESCf27B\nVUCdvSOr9Jua3ONPUSm4Bqgjfd4zdd2OP/SydxJe6VdXVwMA5syZg1GjRmH+/PnYvn17h2u2b9+O\n66+/HoMHD8aiRYtQWlrq2ecbbwAFBcDChcBvfiMzu2giCNKPiqd/9mx7QJEHIoFcnuwdIDxP38/P\nBzpm3nj1o9PTj8X88+ajUIbBazwRJc5zpq6IvZPwSn/Hjh3Izc1t+z4vLw/btm3rcE1JSQny8vLa\nvk9PT8e+ffsc+7vgApKp8/vfE1snEY5B5EWiefo1NeLZRiIqHxDP008U0vcj61jMX+3rVvq0vYjd\n4tWOLmY8WS9AMJ6+F4mrsHeiEsjV/rARj8cRt7FGzIXNJ01aiTFjyIHnvXoVorCwUPf0AkdGBrBr\nl94xVNk7PXuSDzyviqYQCeICYoHcKGTvsKRs+gVxrX2dOeP+vrOSvqjS92svau9QonQ7cYs3ZRNQ\nR/pedo2K7B1VgdyioiIUFRUJt5eawowZM3Dvvfe2fb97925cccUVHa4pKCjAnj17sGDBAgBARUUF\nxo4d69jfunUrZaaTEEgkTx9oV/sipC+q9Hk3TwH6lD5L4JVClb0D+Ct91kCuTqUvSvpe3nyYKZsq\nnwx02juFhR0F8apVq7jaS9k7A749Mbu4uBgHDhzA5s2bUVBQ0OGagoICbNiwAZWVlXjxxRcxceJE\nmSETHrpJv7WVpFnKHGZuhUwwV5T0k5IIYfHWvOdR+qwpm3QDE8viw0L6vErfa15hKn2WgmtOtqCI\nYgfCtXd4A7Nd3t55/PHHsWzZMjQ1NeGuu+5CWloa1q5dCwBYtmwZZs6ciUsuuQTTp0/H4MGD8fzz\nz0tPOpGRman39KyaGkK0XtkhPJAJ5oraO0B7MJdVvTc0AOnp7P2zKn1Wawdgz69XofRZA7l+feiw\nd5KSyOfPieT8bKEw7R1Vyj3qZRikp3DppZd2yshZZjux/JFHHsEjjzwiO1SXQEaGXqWv0toB5Ehf\nVOkD/MFckZRN1o1UPKTf1ZS+2xxY2jqRomhJZlF7x0k08JI+FVD2OkaqAr9BI9I7crsi+vcnf3yR\n4wBZ0FVInzeYqytlUzXpR0np67J3vNqykLeTLRRUyqbXgmQnclWB4qBhSD9gxGJ6D0hXlaNPIVOK\nQcbeCULps5I+a79BKn2WQC6L0vfbGSyivL3G9losrLYQTzvd9g7gbPG4efRdfkeuAT90+vqqcvQp\nwgjkAvy7cnWlbPIofZaUza6k9EXa+i0WXoSpKntHxH5xGsPNo496PX1D+iFAp6/flewdXqWfCPZO\nonn6qu0dvzFFrRfdSl+FvROVQK4h/RCgW+lHhfSDtHd0pWyy1tKnfarYkQtEX+nrsHe82omQvtvr\nE/HcneydbltwzYAfOpW+Dk8/EQK5UVH6QaVs+vnxQDSVvqi94zVXmWwcluvdxhDJ6zek302RSJ5+\nogRydZVWjrK9I7MjlxKe134OP9L3eh0ySl+3vePWhvd6NxLv8vX0DfiRSJ6+TCBXlvQTUelHKZAr\nE4iVbS/j6fPaO6osIb/sHSdP3xyXaMAE4+n7gzeQG4XsnagFcr1SLsMifRl7J2pKX1XZhqBhSD8E\ndCdPP8g8/bCVftRSNr121LLYQzI7ct0Uu4y9I+Lp87RRRfpO9k48bjz9bo1E8/TDUvqs9k5rKyET\nVnIGusfmrERV+iqzd1QqfZmUTVrCIQpnhBjSDwFDhhBF7vQIKIuo2TtB1N6haZU8N1R38fS9lLpO\ne0h1nn7Y9o7bjlzW4xKjEsQFDOmHguRkosYrK9X3rdre6d8/vOwdVqXP6+cD+vL0/VI2u5Onz0ve\nXu1U7sh1a6PT3olKEBcwpB8adPj6TU2EpPr1U9dnIgRyRU72CitlM8jNWTKePG2fyPaOatKXsXei\n4ucDhvRDgw5fn1o7Kn3D1FTyARaxooJS+rzF1oBws3eCrL0TNU/fT+mLELhIyiaPXeN2PQ/pG3vH\nQIvSV23tAGQB6duXX+3Tk5P8iMUNQSj9sDz9IKtsRk3py9hCvPaOXxtW5e42htfmLJ6+g4Yh/ZCg\nQ+mfPKk2c4dCxOKh6ZqiTx08gVwZpe9Uu92KRE7ZjKLS72r2DuvmrKjk6AOG9EODDqWvOl2TQiSY\nK5O5A+gP5PboQW5Cr9o0QGJvztKp9EWPWtRh74SVvcNT28cofYMur/Rl/HyAz97h3ZhFwWLx8Cr9\nM2e8nx4STenLHJcoovRFbKGoZe8AnS0eE8g10ObpdxXS1630Aba0TZ7NWUlJ/pUto6L0WXfkRiVP\nP2ylLxsDMIFcA6P0fcDr6etS+jx5+oC/xaOytHJYO3LjcX+7ojvYO17q3Yn0jdLv5ujqSl+m7g5A\nCKu5mS1VVFTps+Tq89g7gD/pR0Xpy+zIpQSW5MEeOuwd3pRNXktIZJFwU+/2JwNj7xi0HY7ulz3C\nA12kL1JeWVbpx2Lsaj8qnj7ApvQTfUcuS1vRgmuqiqf5PY0E4ekbe8egA3r3Jh8Y0RIHTtCp9IPO\n3gHYg7kySl816fulbarcnOXXj67sHZ1tVR2i0tJCnkTcnkZ40yp5c++NvWPgCNW+fpTsHVmlD7AH\nc7uj0mexicJU+iI1dAB1efp+JKtb6Rt7x8ARqn19HTtygXBJP9GUPounL6v0W1v9yRPQl70ju2Dw\nkrHf0Y5hkT5P2QZj7xgAMErfD6z2jqjSZ03Z5CV9r3NpW1vZbn4v0qdPC367nSnxOsWNZI5blCF9\nlkCuKgLnTQ3VmbJplL4BAEL6qpV+VAK5stk7ALu9o1Ppq0zZpD48S2kKFtL3Q1KS+yHdYZG+yIlb\nIqTv90TB69Hzlku2LxJG6RsAaM/gUYGWFqKuBwxQ058ViRDIFfX0vayY5maiknluVi/SZ03XBNSQ\nPu3HiXxlUj6DtndENoKF7ek72TtG6RsoVfqnThFF7pU7LYpECOTqUPp0Ny5P0TgWpc8Cr5IOPJaT\nG3F3B3tHNekbe8dAGiqVvi5rB+i+gVxePx/wTtnkUfrUmhFV6db5yCj9MAK5ulW7SBve+vumDIOB\nI1Qq/a5I+roDuTpIX5XSB9wtHh7Sl1H6bguGbk+f196JYsqmPWZg7B0DAImj9MPYkQuEH8hVTfo8\nSh9wJ33eyp9RUvoiZRhEA7kme8cZhvRDhGpPXxfp9+1LSJynZISK7J1EVfoqArBA+Eo/Knn6Qdk7\nqo5LdOrf2DsGAMhGqvp6752XrNCp9Hv0IGTGWuoYUJO9o1vp++XpR1Xp89hEbuTLQvqUuOyLvUzt\nHdX580G1cVskjL1jwIVYTJ3Fo2s3LgWvrx9kIFdG6XulbPLm6AP+pM+zOHnZO7KpnyykH4s5k53O\n3bxO7aKcsskayDXHJRq0QSXp61L6AB/px+NEoSd6wTXVSp93nqrsHZkMIBES9ho3yvYOT2DW73pT\ncM3AFap8fd2kzxPMbWggN72ssmGxd1pb+bNiKMJI2VSVvcOb7+/Uh27SFym4JpKn36MH+Ry0trK3\nMQXXDEJDV1T6KqwdgE3pU6tDZFMa6+YsHqhU+m5BYR57R4XSt88h6Dx9v/GcbCgd2TuyO3KNvWMA\nIHGUPk8pBhWZOwCb0hf184FwUjaDtnd0KX1dmT8iVo1TuyDsHd7NWUbpGwDoukpf1s8H2AK5on4+\nEHzKJm9gWEWevqzSd8rzF1X6LS1ElbuVSKbtgiB9WY+e2kle5Z6NvWPgCFVKv6oqWqQflL0jo/SD\nTtkMI5AblqdPyZDWwqftWMhbZDzdSt+tf7e6TMbeMXCFKqVfWQkMGSLfjxt4ArmqSJ/F3omi0g8i\nkBv17B2ntn5BXEDc3nEaS+XmLKdSyTz9G3vHoA0qlP7Zs0Tx6iirTBFVpS9aVhkIPk9fldLnLcMQ\nhtJ3aiua9SNq76iMHfCWSnayd4zSNwCgRulTa0dHWWUKnkBukEq/rk6f0q+v549NBJWymYhKX9Te\nEXlC4N0PEI/z19LxInFTT9/AFenpwIkTHXOMeVFZCaSlqZuTE3iUvsrsnfp675o/MmNRpe/Wv0i8\nIChPX0bpUwXKojyjYO+wLhYynn5LCxFNbsJJ1t7pEoHcmpoaXHvttRg5ciS+973voba21vG60aNH\nY8qUKcjPz8fMmTOFJ9pV0bMn8curqsT70O3nA3ykX1OjJnsnOZl8edUmknmqSEoi779b/6pJP4wy\nDE6kLfukoFPpB5W9I5LtI9t/wts7a9aswciRI7F3716MGDECv/vd7xyvi8ViKCoqwqeffoqSkhLh\niXZlyPr6USP906fVxRf80jZlyz14WTyipK87ZVP2EJWgSN9u1YgWaosC6cumhHYJe6ekpARLly5F\nr169sGTJEmzfvt312jhPTd5uCFlfPwjS58neOX2aXK8CfsFc2fiBV9pmVJU+b5VNex+ypZl12zv0\nbGKe+QZB+jwHnUfZ3hF+4NixYwdyc3MBALm5ua4qPhaL4bLLLsOYMWOwZMkSLFy40LXPlStXtv2/\nsLAQhYWFotNLKCSK0mcN5Kokfb9gbhSVvpenz6v0T53q/HPeKpth2js8wVWA5L1TK4WOcfas//vm\nZCV5PW2qsHd4soNU2jtFRUUoKioSbu85je985zs4evRop58/9NBDzOr9/fffx9ChQ1FaWoprrrkG\nM2fORFZWluO1VtLvTkgEpT9wIFBdzXatatL3s3dkSkp7pW1GOZAro9Rl7SGdSh9oJ0wr6fvZhWHY\nO16vRae9YxfEq1at4mrvSfqbN292/d2zzz6L0tJS5Ofno7S0FDNmzHC8bujQoQCAiRMnYuHChXjt\ntddw++23c02yq0OF0s/JUTcfJwwYEA7p9+njrfRra4Hhw8X7V630k5NJJpZTSp+qlE3Z4xLDDOTy\nkD5Pu6BJn7eGUJfI0y8oKMDTTz+NhoYGPP3007jwwgs7XVNfX4+ab43giooKbNq0CVdccYX4bLso\nEkHp9+9PCJYltTToQK6Mp+9F+nV1/KQfi7mTdSIq/aCzd5zasRzaIkviLHn3VuXOuw+gSwRyly9f\njoMHD2LChAn45ptvcMcddwAADh8+jKuuugoAcPToUcyePRtTp07FTTfdhLvvvhvZ2dlqZt6FkAie\nflISUd0svn7QgdwoefqAu8UTxuasKCl9HntHJOtHZ3aNPcDM4unb+2d57UFA+IGjX79+2LhxY6ef\nDxs2DK+//joAYOzYsfjss8/EZ9dNMHQocOSIePsgSB9o9/X9PPSgA7m6lL4M6etU+rxVNlUrfRbl\n7dSWVenbFyqWUs4q7BqvMWh1UJqF47cQ2QO/rAtlEDA7ciOAYcOAw4fF2wdF+gMGOGeT2BFkIDfR\nlH4YVTajovRF24nYO7yeO8vcrE8HvPYO64IXBAzpRwCZmUBFRccytKyIx8lu3iCVvhdaWsRq1rjB\nL5Arq/Td8vRljmF0I/0wNmdFydNntTjsr1ukfr/qwKx9jES2dwzpRwA9ewKDB4sFc0+fJkQSxAeK\nRenTzVKqir8FofS9CFrkdTiRfnMzWUh41F5UsndUbc46c4bd3tFN+vZ6/7wVQI29YyANUYvnxAn9\nxdYoBg70J32V1g4QXhkG2cNZ7KRPidrt0A3WfoBoKH2RCp2sT0520meZr70Nb+kGFgvJ+npE7B1D\n+gYdIEr6x48TeygIsOTqqyb9vn29yz/oCuTKkL5TeWWRw17c5sZbZVOHp8+i2O1ZOKLlnFkI0/46\neQ9eYVX6dGHhtXeMp2/QCTKkn5Ghfj5OCEPp+9X80RXI1aX0ZefW0kK+WDf6OC1AsoFg1tfipPRZ\nz+UVsXfsSp9loaBteA9757V3jKdv0AmJQPphKP3+/d33Bpw9S+wSmZspKNJXpfQpcbLaRE4xC1l7\nSJT0WdupsHdYlLV1QeN9mjD2joE0EoH0o6b0ZVU+4B4zkCV9UaK0wo30efpxyk6SUfp0gxLrASxW\n4tOp9EXtHavSV529Q1+736lcQcOQfkSQCKTPkr2jmvS9qnuqOKHLLSU0qkqfp8Km21x4SN/eni46\nLE8aovaOiKdvfyLRofR5ArnWnH5a4oEniK8ThvQjgkQgfZY8/SDtHRVKv29f0o8dOjx9XtLv1Yso\nROv+DR7Cts6Ftz69vT0F725gFZ4+S2aNUxuWcsy0jUj2DqvSj5K1AxjSjwwShfTDsHfCUvqiC0pK\nSmfLiHdjFkCUoQzpAiQfPTlZjHwB5/FFM39k7B0WT593LHsgV3X2jpX0o2LtAIb0I4P0dODkyc7n\ng/qhOwRydXr6OuwdpyJxIvYO0NniEY0N2C0aHtIXHV9VIFfE3mF5jXblzrOw8Ng7RukbOKJHD0Le\nDmfWeKKrK32ap+90Zo8Kpa/D3nEKDouQNdCZdBsaxA52sfbBQ/pOC4Zue0c0T18m40fE02dV+lFK\n1wQM6UcKQ4fyWTwtLaTuTlA7cqnS9zo0TTXpJycTknFS47K7cQF9St/epyqlX18vFhCWUfqJ4unz\njiWyOUske8cofQNX8Pr6VVWEiIM6kYdmbbgdBwiQJwFVB6hQuFk8soeiA4Sgo6z07YQteoSjqNIP\nm/RbWkjNIr/PuNXeiceDUfqsB6kbT9/AFbykH6S1QzFwIIk9uEFHxU+3YK4Kpd+3b2IpfdHUT5VK\nXzSQK+LpU0Xtl+5obdPcTArl0aJqXm3o/Fizd1gDudYducbeMXBFIpD+kCGkfr8bqqpIxVCVcMvV\nV6X06+o6W1Y6lL4qe0f2sPaoK31rO5EDW3h2DOv09OlGNmPvGLhi+HDg0CH2648fJ1k/QSItjVT2\ndIMO0ndT+iqyd5KTyZfdslKt9Ovrxe0d2UCuzMJBa/fQRZEnkCtacI23Jo69ja5xeLJ36ElbLS3G\n3jHwwMiRQHk5+/WHD5Pgb5DwUvotLcR7D8rTV3UAu5PFo1rpi2YaqQjk2tU6z8KRnEysEupPB+3p\nNzbyH7wi8kShOpALtFs8RukbuGLkSOCf/2S//vBh8nQQJNLS3En/5ElCwqoOUKFwU/rV1WpI302Z\nq1T6ovEHFfaObB/WmEDQefqstpjdEhJR+irtHaA9g8d4+gauyM4m9k5rK9v133wTPOkPGeJu7+iw\ndgB3T19VeqhTBk9dnVrSF40/qAjk2pU+79OCtT1vIFek4JqVXFlfb9BKn8WyodcbpW/gitRUkh3D\nukErLNJ3U/q6SN/N3qmuVkP6/fp1Jv2aGvJzEbjZOyJK395XGErfmvLJq/R5N0wBYkpf1tNXnb0D\ntFdbNZ6+gSdGjQIOHmS7NgzS9wrk6jqg3c3eUeXp9+vXeVGRIX03e0dE6dv7Et2RK+rp29vzkL5o\n1pCVjFlrFonaO6JKn2WRoK/f2DsGnhg5ko3043FC+sOG6Z+TFWEpfTdPX4XSd+pfxjpyUvqimUb2\nMhGyO3LjcTl7hyd7x/4+sJKx9clExN5htaDsKZs82Tss86Lvm7F3DDwxahRbMPfUKfJBks1T54VX\nIDcMT1+F0ncifRmlT29waxBT1N6xK31Re4eS75kzxGrw27hkhajS7927nbzpMY8sNoe1nUjwl+cA\ndhGPns6Lh/SNvWPgClZ7JwxrBwgnkOuVsqlD6be0kJtVZg9A794dyVrU3rGnk4rYO9aFQ3ZzF0+J\naKvSp+OyHCRiXaRYlX6PHuQpprmZL5BrfTpgqb9vVfp+1xvSN2ACa9pmWKTvpfQrK4Ozd86cITe5\nyIYnv/5ppo3MSUf2hUrU3rFnFonYO1aLSHZzF88TC1XSLS18i411sWAl/Vis3cYSiR2wzE9U6Yvu\nxtYFQ/oRA6u9ExbpDxxIyIxu1rFCp9K31/FXWc3TTvqnT4tbOxT24LAqpS9C+nalz9veSsI8pE+J\nuG4FGoIAAA1qSURBVKGB71Aa6yLDayfV1+tLDT3nHL4nHkr6onWXdMGQfsQwZgywf793+WIgPNJP\nSgIGDSIEb4cu0h80qHORN1VBXKAz6cv4+U59UrtI5Ma3K32RxcOq9EXsHeuiwRuboESsW+lb27GS\nvtW2YpkfjTXQejqG9A2UYOBAoiiOH/e+LizSB9wzeHSR/uDBnRcZlemhdlVeUyO/oFhJn6pcEbvI\nHsgVeQqR9fSti4YI6Tc08G12ozZNPM5P+g0N7KTPu7jQ/mlpCL+/pyF9A2bk5AB793pf889/Ev8/\nDLgFc3Xl6Q8YQEjHaimpXGB02zsyJaDt9o7IgmR9WpANBMsofdZ2SUntVoqIvcOaskmvb2khufR+\nbaz9s8zJkL4BM1hIv6wMGD8+mPnY4bZBS5fST0rqfFSjTtJXbe/IVAO1EnY8Tv7POzfrwiEbCOYl\nfZqJI1Lvp6FBzN5hbUPPMqbX+yl33v5phVJD+ga+8CP95mZSjXPMmODmZEVGRmf7qamJkNzAgXrG\nHDy4o6WkmvStgWIVSt9K+tXV4u+LlbAbGkjqH+9JabL2jgqlz1vLyEqwvEq/ro7t70fTallJmS5g\nRukbKIcf6ZeXA5mZ7IWvVGPYMODIkY4/o7X9eTb98MDu66tMD7U/RZw8Kd+31d45dUqc9K2EK7oY\nWZW6yFOHrKfPa+/QdtQ/51X6rK+RV7nzXm9I34AZfqS/bx8wblxw87HD6QD3o0eBrCx9Yw4Z0pH0\nVSp9HX1blb4M6dOgJj2rQIT07QsH7y5mFYFcEXuHh2DpWJT0WTKc6PvCOjcZT1+0YqsOGNKPIHJy\niGfvlrZZVhY+6duVvm7Styt91fZOQ0N7zraKgLQq0o/F2p8aRLOKaFwgHhc7g8B6pKQoefO24yVY\naxvWtFZe5c67EBmlb8CM/v3JjWYnVop9+8IL4gLO9s6RI3pP8bJnDKkk/Vis494DFX2rsneA9n0K\novYOrbVz9qwY6VOl39BALEUeC89KxLwBYNFALo+9Q9NJWcZITibvZXU1n9IXCZ7rhCH9iGLyZGDX\nLuffdUd7JzOz4zkDJ06oTQ+1WjwqSH/AgPY4gSrSly33XFsrtqmNKn2R1FORzVnWdjyvmVfpJyWR\nRezkSb6NY5WVRukbaEB+PvDpp86/C9veycwkpGs9FenIEb2kP3RoR9JXPZ41O0hFkNia1hoF0qdP\nHjJKX4T06WIjmrLJ897xevq0zYkT7KScmkpEgcneMVCO/Hzgk086/7y5mSj9nJzg50TRsych4UOH\n2n928KDezWJZWe2kH48Dx46ptZNUK33VpF9VJbdTmO6iFgnkyij9QYPI6xdR+nV14qTPOs8+ffhI\n3yh9A22YNs1Z6e/dSzz1oOvo2zF6NKkRRHHggN59A1lZ7XGEykpys6qosElhVfoqSD89HaioIP+X\nJf3Bg4nSP3lSvB9aHVVU6dfUiI1PA/C88Qj6dCNC+jz1iajS57F3WJW+SAZSEDCkH1Gcey5Rtvbq\nkjt3AuefH86crBgzhhA9QJT3/v2kQqguWO0dHUFjqsybmghpyB7O0r8/CZw2NhLykumPEuCxY8Ra\nEwENhIuQPh2f7sXgASX9igq+tmlp5O985gy7aqeBWV57h1W50+uPHmVbwOhibUjfgAk9egDnnQd8\n9lnHn3/2WTRI36r0KytJrRQVp1i5IS2N3EBNTXpIf8QIYld98w3pO0nyzojF2heSI0fkjrVURfqi\nSj8lhZBWWRk/6VPbjJf0hwwBvv6azJW1UN2AAeR94rV3Dh/mCxYfPMj2WtLSyOvmOWIyCBjSjzCm\nTwe2b+/4s/ffB2bNCmc+Vowb176BbP9+sgjoRI8ehDjLy/WQPj2bWGVsIi2NqGPZiqjU05chfboA\niZakzsgAdu8m/fCAKv0TJ/jaDhlCYlc8dlJWFvn7xePsZ9L27k3GYf089e5NnnAzMvyvTUsjQqJX\nL3kRoRIRmoqBHZddBrz1Vvv3jY3E57/wwvDmRHH++cRqAkhq6eTJ+secMAH4xz+Ar75Sn71ESb+8\nHMjOVtNnejpQWkqsBpnHe2rNyCr9/fuJahYp/paZCXzxhZi9c+IEecoIgvT37eMrY52RQZ5gWEk/\nI4O8Hpb3YeBAovLDKoHuBmHS//Of/4xJkyahR48e+MQpzeRbFBcXY+LEicjJycGTTz4pOly3QlFR\nEQBg7lzggw/aa35v3UrINewgLgDk5pLyzvX1ZCGaOlXPOPS9ANpJf88eYNIktePQs4lVKv3hw8nf\nb8QIuX7GjydPVYcOFUmR/vbtZLEUqeufmUmUvgjpHzlCPrM858SmpZHgsRvpWz8XFFlZpA3Poj12\nLNDayk76Y8eSf1mUfo8e5PXrfgrmhTDpn3feeXjllVcwZ84cz+tWrFiBtWvXYsuWLXjqqadwwu1U\nbYM20A/0wIHAxRcDGzeSn69fD/zgB+HNy4pzziEk/NlnhPTz8/WM40T6u3erJ/20NLKA7dmjjvSn\nTAHeeEOe9M89l7zu6uoibnuFIj2dPCGJ7uTOyCCqlZf06RMOr1ChG+/c4g9OpJ+SQqywvDz2cSiJ\n6yB9gHyuugzp5+bm4txzz/W8pvrb1JM5c+Zg1KhRmD9/PrbbTWoDTyxZAjz+OHm0X78euPHGsGfU\nju9+F3jqKWJhzJihf7zp04FNm4hPqroMRSxGXsOf/gTMnKmmz6lTif8ra0X16UMC2LScgggKCsi/\nvKRNQRcb3oA0faqw7ulgASX9iy/ma5eVxScIaJoxL+mzvo9divRZsGPHDuTm5rZ9n5eXh23btukc\nssvh+uuJWpo0CVi6VG9aJC8WLwZefBG44YZgLKeCAhJI+9GP2AN1PFi0iKj86dPV9Ectr5/+VL6v\n5GS5xYgGbwcNEmu/eDGwYQN5euHF/v3A3/7G16Z3b+D554EVK/jaZWeTrDdWjBtHPrus2TvjxpFr\nWT/vWVnh7p53RNwD8+bNi0+ePLnT16uvvtp2TWFhYfzjjz92bL958+b4TTfd1Pb9mjVr4g888IDj\ntQDMl/kyX+bLfAl88cDzDJ7Nmzd7/doXM2bMwL333tv2/e7du3HFFVc4Xht3qyNsYGBgYKAMSuwd\nN8Ie8G0Upri4GAcOHMDmzZtRQM1FAwMDA4PAIUz6r7zyCrKzs7Ft2zZcddVVuPLKKwEAhw8fxlVX\nXdV23eOPP45ly5Zh3rx5+PGPf4w00fQDAwMDAwN5cJlBGvDuu+/Gc3Nz4+PHj4//z//8T9jTCQ0H\nDx6MFxYWxvPy8uKXXnpp/IUXXgh7SqGiubk5PnXq1PjVV18d9lRCR21tbfyWW26J5+TkxCdOnBj/\n8MMPw55SaPj9738fnzVrVnzatGnxFStWhD2dQHHbbbfFMzIy4pMnT2772enTp+MLFy6MZ2dnx6+9\n9tp4TU2Nbz+h78g1efwEPXv2xOrVq7F7926sX78eDzzwAGro0UvdEE888QTy8vIQE9lJ1MXw4IMP\nYuTIkdi1axd27dqFiRMnhj2lUFBVVYWHH34Ymzdvxo4dO/DVV19h06ZNYU8rMNx22234my0Nas2a\nNRg5ciT27t2LESNG4He/+51vP6GSvsnjb0dWVhamfpvjl5aWhkmTJuGjjz4KeVbh4NChQ3jjjTfw\nox/9yAT4AWzZsgX//u//jpSUFCQnJ7fFyrobUlNTEY/HUV1djYaGBtTX12OQaA5qAmL27NmdXm9J\nSQmWLl2KXr16YcmSJUz8GSrpmzx+Z5SVlWH37t2YqWqXUILhX//1X/Hoo48iKUpVqkLCoUOH0NjY\niOXLl6OgoAC/+c1v0NjYGPa0QkFqairWrFmD0aNHIysrCxdffHG3vUcorByam5uLkpIS3zbmrooY\nampqcOONN2L16tXoI1IZK8Hx17/+FRkZGcjPzzcqH0BjYyO++uorXHfddSgqKsLu3bvx0ksvhT2t\nUFBRUYHly5djz549OHDgAD788EO8/vrrYU8rVIjcI6GS/owZM/Dll1+2fb97925cGIUSkiGhqakJ\n1113HRYvXoxrr7027OmEgg8++ACvvvoqxowZg0WLFuHtt9/GLbfcEva0QsP48eMxYcIEXHPNNUhN\nTcWiRYvw5ptvhj2tUFBSUoILL7wQ48ePx5AhQ/DDH/4QxcXFYU8rVMyYMQOlpaUAgNLSUsxgqIcS\nKumbPP52xONxLF26FJMnT8bPfvazsKcTGh5++GGUl5dj//79+OMf/4jLLrsM69atC3taoSInJwfb\nt29Ha2srXn/9dcybNy/sKYWC2bNn46OPPkJVVRXOnDmDN998E/Pnzw97WqGioKAATz/9NBoaGvD0\n008ziebQ7R2Tx0/w/vvv4/nnn8fbb7+N/Px85Ofnd4rUd0eY7B3gt7/9LVasWIFp06YhJSUFN910\nU9hTCgX9+/fHAw88gO9///u45JJLcP7552Pu3LlhTyswLFq0CBdddBG++uorZGdn4//+7/+wfPly\nHDx4EBMmTMA333yDO+64w7efWNwYpwYGBgbdBqErfQMDAwOD4GBI38DAwKAbwZC+gYGBQTeCIX0D\nAwODbgRD+gYGBgbdCIb0DQwMDLoR/j8U8QHdaUyIsAAAAABJRU5ErkJggg==\n"
111 111 }
112 112 ],
113 113 "prompt_number": 4
114 114 },
115 115 {
116 116 "cell_type": "markdown",
117 117 "source": [
118 118 "You can paste blocks of input with prompt markers, such as those from",
119 119 "[the official Python tutorial](http://docs.python.org/tutorial/interpreter.html#interactive-mode)"
120 120 ]
121 121 },
122 122 {
123 123 "cell_type": "code",
124 124 "collapsed": false,
125 125 "input": [
126 126 ">>> the_world_is_flat = 1",
127 127 ">>> if the_world_is_flat:",
128 128 "... print \"Be careful not to fall off!\""
129 129 ],
130 130 "language": "python",
131 131 "outputs": [
132 132 {
133 133 "output_type": "stream",
134 134 "stream": "stdout",
135 135 "text": [
136 136 "Be careful not to fall off!"
137 137 ]
138 138 }
139 139 ],
140 140 "prompt_number": 5
141 141 },
142 142 {
143 143 "cell_type": "markdown",
144 144 "source": [
145 145 "Errors are shown in informative ways:"
146 146 ]
147 147 },
148 148 {
149 149 "cell_type": "code",
150 150 "collapsed": false,
151 151 "input": [
152 152 "%run non_existent_file"
153 153 ],
154 154 "language": "python",
155 155 "outputs": [
156 156 {
157 157 "output_type": "stream",
158 158 "stream": "stderr",
159 159 "text": [
160 160 "ERROR: File &#96;non_existent_file.py&#96; not found."
161 161 ]
162 162 }
163 163 ],
164 164 "prompt_number": 6
165 165 },
166 166 {
167 167 "cell_type": "code",
168 168 "collapsed": false,
169 169 "input": [
170 170 "x = 1",
171 171 "y = 4",
172 172 "z = y/(1-x)"
173 173 ],
174 174 "language": "python",
175 175 "outputs": [
176 176 {
177 177 "ename": "ZeroDivisionError",
178 178 "evalue": "integer division or modulo by zero",
179 179 "output_type": "pyerr",
180 180 "traceback": [
181 181 "<span class=\"ansired\">---------------------------------------------------------------------------</span>\n<span class=\"ansired\">ZeroDivisionError</span> Traceback (most recent call last)",
182 182 "<span class=\"ansigreen\">/home/fperez/ipython/ipython/docs/examples/notebooks/&lt;ipython-input-7-dc39888fd1d2&gt;</span> in <span class=\"ansicyan\">&lt;module&gt;</span><span class=\"ansiblue\">()</span>\n<span class=\"ansigreen\"> 1</span> x <span class=\"ansiyellow\">=</span> <span class=\"ansicyan\">1</span><span class=\"ansiyellow\"></span>\n<span class=\"ansigreen\"> 2</span> y <span class=\"ansiyellow\">=</span> <span class=\"ansicyan\">4</span><span class=\"ansiyellow\"></span>\n<span class=\"ansigreen\">----&gt; 3</span><span class=\"ansiyellow\"> </span>z <span class=\"ansiyellow\">=</span> y<span class=\"ansiyellow\">/</span><span class=\"ansiyellow\">(</span><span class=\"ansicyan\">1</span><span class=\"ansiyellow\">-</span>x<span class=\"ansiyellow\">)</span><span class=\"ansiyellow\"></span>\n",
183 183 "<span class=\"ansired\">ZeroDivisionError</span>: integer division or modulo by zero"
184 184 ]
185 185 }
186 186 ],
187 187 "prompt_number": 7
188 188 },
189 189 {
190 190 "cell_type": "markdown",
191 191 "source": [
192 192 "When IPython needs to display additional information (such as providing details on an object via `x?`",
193 193 "it will automatically invoke a pager at the bottom of the screen:"
194 194 ]
195 195 },
196 196 {
197 197 "cell_type": "code",
198 198 "collapsed": true,
199 199 "input": [
200 200 "magic"
201 201 ],
202 202 "language": "python",
203 203 "outputs": [],
204 204 "prompt_number": 8
205 205 },
206 206 {
207 207 "cell_type": "markdown",
208 208 "source": [
209 209 "## Non-blocking output of kernel",
210 210 "",
211 211 "If you execute the next cell, you will see the output arriving as it is generated, not all at the end."
212 212 ]
213 213 },
214 214 {
215 215 "cell_type": "code",
216 216 "collapsed": false,
217 217 "input": [
218 218 "import time, sys",
219 219 "for i in range(8):",
220 220 " print i,",
221 221 " time.sleep(0.5)"
222 222 ],
223 223 "language": "python",
224 224 "outputs": [
225 225 {
226 226 "output_type": "stream",
227 227 "stream": "stdout",
228 228 "text": [
229 229 "0 "
230 230 ]
231 231 },
232 232 {
233 233 "output_type": "stream",
234 234 "stream": "stdout",
235 235 "text": [
236 236 "1 "
237 237 ]
238 238 },
239 239 {
240 240 "output_type": "stream",
241 241 "stream": "stdout",
242 242 "text": [
243 243 "2 "
244 244 ]
245 245 },
246 246 {
247 247 "output_type": "stream",
248 248 "stream": "stdout",
249 249 "text": [
250 250 "3 "
251 251 ]
252 252 },
253 253 {
254 254 "output_type": "stream",
255 255 "stream": "stdout",
256 256 "text": [
257 257 "4 "
258 258 ]
259 259 },
260 260 {
261 261 "output_type": "stream",
262 262 "stream": "stdout",
263 263 "text": [
264 264 "5 "
265 265 ]
266 266 },
267 267 {
268 268 "output_type": "stream",
269 269 "stream": "stdout",
270 270 "text": [
271 271 "6 "
272 272 ]
273 273 },
274 274 {
275 275 "output_type": "stream",
276 276 "stream": "stdout",
277 277 "text": [
278 278 "7"
279 279 ]
280 280 }
281 281 ],
282 282 "prompt_number": 9
283 283 },
284 284 {
285 285 "cell_type": "markdown",
286 286 "source": [
287 287 "## Clean crash and restart",
288 288 "",
289 289 "We call the low-level system libc.time routine with the wrong argument via",
290 290 "ctypes to segfault the Python interpreter:"
291 291 ]
292 292 },
293 293 {
294 294 "cell_type": "code",
295 295 "collapsed": true,
296 296 "input": [
297 297 "from ctypes import CDLL",
298 298 "# This will crash a linux system; equivalent calls can be made on Windows or Mac",
299 299 "libc = CDLL(\"libc.so.6\") ",
300 300 "libc.time(-1) # BOOM!!"
301 301 ],
302 302 "language": "python",
303 303 "outputs": [],
304 304 "prompt_number": "*"
305 305 },
306 306 {
307 307 "cell_type": "markdown",
308 308 "source": [
309 309 "## Markdown cells can contain formatted text and code",
310 310 "",
311 311 "You can *italicize*, **boldface**",
312 312 "",
313 313 "* build",
314 314 "* lists",
315 315 "",
316 316 "and embed code meant for illustration instead of execution in Python:",
317 317 "",
318 318 " def f(x):",
319 319 " \"\"\"a docstring\"\"\"",
320 320 " return x**2",
321 321 "",
322 322 "or other languages:",
323 323 "",
324 324 " if (i=0; i<n; i++) {",
325 325 " printf(\"hello %d\\n\", i);",
326 326 " x += 4;",
327 327 " }"
328 328 ]
329 329 },
330 330 {
331 331 "cell_type": "markdown",
332 332 "source": [
333 333 "Courtesy of MathJax, you can include mathematical expressions both inline: ",
334 334 "$e^{i\\pi} + 1 = 0$ and displayed:",
335 335 "",
336 336 "$$e^x=\\sum_{i=0}^\\infty \\frac{1}{i!}x^i$$"
337 337 ]
338 338 },
339 339 {
340 340 "cell_type": "markdown",
341 341 "source": [
342 342 "## Rich displays: include anyting a browser can show",
343 343 "",
344 344 "Note that we have an actual protocol for this, see the `display_protocol` notebook for further details.",
345 345 "",
346 346 "### Images"
347 347 ]
348 348 },
349 349 {
350 350 "cell_type": "code",
351 351 "collapsed": false,
352 352 "input": [
353 353 "from IPython.core.display import Image",
354 354 "Image(filename='../../source/_static/logo.png')"
355 355 ],
356 356 "language": "python",
357 357 "outputs": [
358 358 {
359 359 "output_type": "pyout",
360 360 "png": "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\n",
361 361 "prompt_number": 1,
362 362 "text": [
363 363 "&lt;IPython.core.display.Image at 0x41d4690&gt;"
364 364 ]
365 365 }
366 366 ],
367 367 "prompt_number": 1
368 368 },
369 369 {
370 370 "cell_type": "markdown",
371 371 "source": [
372 372 "An image can also be displayed from raw data or a url"
373 373 ]
374 374 },
375 375 {
376 376 "cell_type": "code",
377 377 "collapsed": false,
378 378 "input": [
379 379 "Image('http://python.org/images/python-logo.gif')"
380 380 ],
381 381 "language": "python",
382 382 "outputs": [
383 383 {
384 384 "html": [
385 385 "<img src=\"http://python.org/images/python-logo.gif\" />"
386 386 ],
387 387 "output_type": "pyout",
388 388 "prompt_number": 2,
389 389 "text": [
390 390 "&lt;IPython.core.display.Image at 0x41d4550&gt;"
391 391 ]
392 392 }
393 393 ],
394 394 "prompt_number": 2
395 395 },
396 396 {
397 397 "cell_type": "markdown",
398 398 "source": [
399 399 "SVG images are also supported out of the box (since modern browsers do a good job of rendering them):"
400 400 ]
401 401 },
402 402 {
403 403 "cell_type": "code",
404 404 "collapsed": false,
405 405 "input": [
406 406 "from IPython.core.display import SVG",
407 407 "SVG(filename='python-logo.svg')"
408 408 ],
409 409 "language": "python",
410 410 "outputs": [
411 411 {
412 412 "output_type": "pyout",
413 413 "prompt_number": 3,
414 414 "svg": [
415 415 "<svg height=\"115.02pt\" id=\"svg2\" inkscape:version=\"0.43\" sodipodi:docbase=\"/home/sdeibel\" sodipodi:docname=\"logo-python-generic.svg\" sodipodi:version=\"0.32\" version=\"1.0\" width=\"388.84pt\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:cc=\"http://web.resource.org/cc/\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:inkscape=\"http://www.inkscape.org/namespaces/inkscape\" xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\" xmlns:sodipodi=\"http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd\" xmlns:svg=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">",
416 416 " <metadata id=\"metadata2193\">",
417 417 " <rdf:RDF>",
418 418 " <cc:Work rdf:about=\"\">",
419 419 " <dc:format>image/svg+xml</dc:format>",
420 420 " <dc:type rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\"/>",
421 421 " </cc:Work>",
422 422 " </rdf:RDF>",
423 423 " </metadata>",
424 424 " <sodipodi:namedview bordercolor=\"#666666\" borderopacity=\"1.0\" id=\"base\" inkscape:current-layer=\"svg2\" inkscape:cx=\"243.02499\" inkscape:cy=\"71.887497\" inkscape:pageopacity=\"0.0\" inkscape:pageshadow=\"2\" inkscape:window-height=\"543\" inkscape:window-width=\"791\" inkscape:window-x=\"0\" inkscape:window-y=\"0\" inkscape:zoom=\"1.4340089\" pagecolor=\"#ffffff\"/>",
425 425 " <defs id=\"defs4\">",
426 426 " <linearGradient id=\"linearGradient2795\">",
427 427 " <stop id=\"stop2797\" offset=\"0\" style=\"stop-color:#b8b8b8;stop-opacity:0.49803922\"/>",
428 428 " <stop id=\"stop2799\" offset=\"1\" style=\"stop-color:#7f7f7f;stop-opacity:0\"/>",
429 429 " </linearGradient>",
430 430 " <linearGradient id=\"linearGradient2787\">",
431 431 " <stop id=\"stop2789\" offset=\"0\" style=\"stop-color:#7f7f7f;stop-opacity:0.5\"/>",
432 432 " <stop id=\"stop2791\" offset=\"1\" style=\"stop-color:#7f7f7f;stop-opacity:0\"/>",
433 433 " </linearGradient>",
434 434 " <linearGradient id=\"linearGradient3676\">",
435 435 " <stop id=\"stop3678\" offset=\"0\" style=\"stop-color:#b2b2b2;stop-opacity:0.5\"/>",
436 436 " <stop id=\"stop3680\" offset=\"1\" style=\"stop-color:#b3b3b3;stop-opacity:0\"/>",
437 437 " </linearGradient>",
438 438 " <linearGradient id=\"linearGradient3236\">",
439 439 " <stop id=\"stop3244\" offset=\"0\" style=\"stop-color:#f4f4f4;stop-opacity:1\"/>",
440 440 " <stop id=\"stop3240\" offset=\"1\" style=\"stop-color:#ffffff;stop-opacity:1\"/>",
441 441 " </linearGradient>",
442 442 " <linearGradient id=\"linearGradient4671\">",
443 443 " <stop id=\"stop4673\" offset=\"0\" style=\"stop-color:#ffd43b;stop-opacity:1\"/>",
444 444 " <stop id=\"stop4675\" offset=\"1\" style=\"stop-color:#ffe873;stop-opacity:1\"/>",
445 445 " </linearGradient>",
446 446 " <linearGradient id=\"linearGradient4689\">",
447 447 " <stop id=\"stop4691\" offset=\"0\" style=\"stop-color:#5a9fd4;stop-opacity:1\"/>",
448 448 " <stop id=\"stop4693\" offset=\"1\" style=\"stop-color:#306998;stop-opacity:1\"/>",
449 449 " </linearGradient>",
450 450 " <linearGradient gradientTransform=\"translate(100.2702,99.61116)\" gradientUnits=\"userSpaceOnUse\" id=\"linearGradient2987\" x1=\"224.23996\" x2=\"-65.308502\" xlink:href=\"#linearGradient4671\" y1=\"144.75717\" y2=\"144.75717\"/>",
451 451 " <linearGradient gradientTransform=\"translate(100.2702,99.61116)\" gradientUnits=\"userSpaceOnUse\" id=\"linearGradient2990\" x1=\"172.94208\" x2=\"26.670298\" xlink:href=\"#linearGradient4689\" y1=\"77.475983\" y2=\"76.313133\"/>",
452 452 " <linearGradient gradientTransform=\"translate(100.2702,99.61116)\" gradientUnits=\"userSpaceOnUse\" id=\"linearGradient2587\" x1=\"172.94208\" x2=\"26.670298\" xlink:href=\"#linearGradient4689\" y1=\"77.475983\" y2=\"76.313133\"/>",
453 453 " <linearGradient gradientTransform=\"translate(100.2702,99.61116)\" gradientUnits=\"userSpaceOnUse\" id=\"linearGradient2589\" x1=\"224.23996\" x2=\"-65.308502\" xlink:href=\"#linearGradient4671\" y1=\"144.75717\" y2=\"144.75717\"/>",
454 454 " <linearGradient gradientTransform=\"translate(100.2702,99.61116)\" gradientUnits=\"userSpaceOnUse\" id=\"linearGradient2248\" x1=\"172.94208\" x2=\"26.670298\" xlink:href=\"#linearGradient4689\" y1=\"77.475983\" y2=\"76.313133\"/>",
455 455 " <linearGradient gradientTransform=\"translate(100.2702,99.61116)\" gradientUnits=\"userSpaceOnUse\" id=\"linearGradient2250\" x1=\"224.23996\" x2=\"-65.308502\" xlink:href=\"#linearGradient4671\" y1=\"144.75717\" y2=\"144.75717\"/>",
456 456 " <linearGradient gradientTransform=\"matrix(0.562541,0,0,0.567972,-11.5974,-7.60954)\" gradientUnits=\"userSpaceOnUse\" id=\"linearGradient2255\" x1=\"224.23996\" x2=\"-65.308502\" xlink:href=\"#linearGradient4671\" y1=\"144.75717\" y2=\"144.75717\"/>",
457 457 " <linearGradient gradientTransform=\"matrix(0.562541,0,0,0.567972,-11.5974,-7.60954)\" gradientUnits=\"userSpaceOnUse\" id=\"linearGradient2258\" x1=\"172.94208\" x2=\"26.670298\" xlink:href=\"#linearGradient4689\" y1=\"76.176224\" y2=\"76.313133\"/>",
458 458 " <radialGradient cx=\"61.518883\" cy=\"132.28575\" fx=\"61.518883\" fy=\"132.28575\" gradientTransform=\"matrix(1,0,0,0.177966,0,108.7434)\" gradientUnits=\"userSpaceOnUse\" id=\"radialGradient2801\" r=\"29.036913\" xlink:href=\"#linearGradient2795\"/>",
459 459 " <linearGradient gradientTransform=\"matrix(0.562541,0,0,0.567972,-9.399749,-5.305317)\" gradientUnits=\"userSpaceOnUse\" id=\"linearGradient1475\" x1=\"150.96111\" x2=\"112.03144\" xlink:href=\"#linearGradient4671\" y1=\"192.35176\" y2=\"137.27299\"/>",
460 460 " <linearGradient gradientTransform=\"matrix(0.562541,0,0,0.567972,-9.399749,-5.305317)\" gradientUnits=\"userSpaceOnUse\" id=\"linearGradient1478\" x1=\"26.648937\" x2=\"135.66525\" xlink:href=\"#linearGradient4689\" y1=\"20.603781\" y2=\"114.39767\"/>",
461 461 " <radialGradient cx=\"61.518883\" cy=\"132.28575\" fx=\"61.518883\" fy=\"132.28575\" gradientTransform=\"matrix(2.382716e-8,-0.296405,1.43676,4.683673e-7,-128.544,150.5202)\" gradientUnits=\"userSpaceOnUse\" id=\"radialGradient1480\" r=\"29.036913\" xlink:href=\"#linearGradient2795\"/>",
462 462 " </defs>",
463 463 " <g id=\"g2303\">",
464 464 " <path d=\"M 184.61344,61.929363 C 184.61344,47.367213 180.46118,39.891193 172.15666,39.481813 C 168.85239,39.325863 165.62611,39.852203 162.48754,41.070593 C 159.98254,41.967323 158.2963,42.854313 157.40931,43.751043 L 157.40931,78.509163 C 162.72147,81.842673 167.43907,83.392453 171.55234,83.148783 C 180.25649,82.573703 184.61344,75.507063 184.61344,61.929363 z M 194.85763,62.533683 C 194.85763,69.931723 193.12265,76.072393 189.63319,80.955683 C 185.7441,86.482283 180.35396,89.328433 173.46277,89.484393 C 168.26757,89.650093 162.91642,88.022323 157.40931,84.610843 L 157.40931,116.20116 L 148.50047,113.02361 L 148.50047,42.903043 C 149.96253,41.109583 151.84372,39.569543 154.12454,38.263433 C 159.42696,35.173603 165.86978,33.584823 173.45302,33.506853 L 173.57973,33.633563 C 180.50991,33.545833 185.85132,36.391993 189.60395,42.162263 C 193.10315,47.454933 194.85763,54.238913 194.85763,62.533683 z \" id=\"path46\" style=\"fill:#646464;fill-opacity:1\"/>",
465 465 " <path d=\"M 249.30487,83.265743 C 249.30487,93.188283 248.31067,100.05998 246.32227,103.88084 C 244.32411,107.7017 240.52275,110.75254 234.90842,113.02361 C 230.35653,114.81707 225.43425,115.79178 220.15133,115.95748 L 218.67952,110.34316 C 224.05016,109.61213 227.83204,108.88109 230.02513,108.15006 C 234.34309,106.688 237.30621,104.44617 238.93397,101.44406 C 240.24008,98.997543 240.88339,94.328693 240.88339,87.418003 L 240.88339,85.098203 C 234.79146,87.866373 228.40711,89.240713 221.73036,89.240713 C 217.34417,89.240713 213.47457,87.866373 210.14107,85.098203 C 206.39818,82.086343 204.52674,78.265483 204.52674,73.635623 L 204.52674,36.557693 L 213.43558,33.506853 L 213.43558,70.828453 C 213.43558,74.815013 214.7222,77.885353 217.29543,80.039463 C 219.86866,82.193563 223.20217,83.226753 227.2862,83.148783 C 231.37023,83.061053 235.74667,81.482023 240.39603,78.392203 L 240.39603,34.851953 L 249.30487,34.851953 L 249.30487,83.265743 z \" id=\"path48\" style=\"fill:#646464;fill-opacity:1\"/>",
466 466 " <path d=\"M 284.08249,88.997033 C 283.02006,89.084753 282.04535,89.123743 281.14862,89.123743 C 276.10937,89.123743 272.18129,87.924853 269.37413,85.517323 C 266.57671,83.109793 265.17314,79.786033 265.17314,75.546053 L 265.17314,40.456523 L 259.07146,40.456523 L 259.07146,34.851953 L 265.17314,34.851953 L 265.17314,19.968143 L 274.07223,16.800333 L 274.07223,34.851953 L 284.08249,34.851953 L 284.08249,40.456523 L 274.07223,40.456523 L 274.07223,75.302373 C 274.07223,78.645623 274.96896,81.014163 276.76243,82.398253 C 278.30247,83.538663 280.74899,84.191723 284.08249,84.357423 L 284.08249,88.997033 z \" id=\"path50\" style=\"fill:#646464;fill-opacity:1\"/>",
467 467 " <path d=\"M 338.02288,88.266003 L 329.11404,88.266003 L 329.11404,53.878273 C 329.11404,50.379063 328.29528,47.367213 326.66753,44.852463 C 324.78634,42.006313 322.17411,40.583233 318.82112,40.583233 C 314.73708,40.583233 309.6296,42.737343 303.4987,47.045563 L 303.4987,88.266003 L 294.58985,88.266003 L 294.58985,6.0687929 L 303.4987,3.2616329 L 303.4987,40.700203 C 309.191,36.557693 315.40963,34.481563 322.16436,34.481563 C 326.88196,34.481563 330.70282,36.070333 333.62694,39.238143 C 336.56082,42.405943 338.02288,46.353513 338.02288,51.071103 L 338.02288,88.266003 L 338.02288,88.266003 z \" id=\"path52\" style=\"fill:#646464;fill-opacity:1\"/>",
468 468 " <path d=\"M 385.37424,60.525783 C 385.37424,54.930953 384.31182,50.310833 382.19669,46.655673 C 379.68195,42.201253 375.77337,39.852203 370.49044,39.608523 C 360.72386,40.173863 355.85032,47.172273 355.85032,60.584263 C 355.85032,66.734683 356.86401,71.871393 358.91089,75.994413 C 361.52312,81.248093 365.44145,83.840823 370.66589,83.753103 C 380.47146,83.675123 385.37424,75.935933 385.37424,60.525783 z M 395.13109,60.584263 C 395.13109,68.547643 393.09395,75.175663 389.02941,80.468333 C 384.5555,86.394563 378.37584,89.367423 370.49044,89.367423 C 362.67328,89.367423 356.58135,86.394563 352.18541,80.468333 C 348.19885,75.175663 346.21044,68.547643 346.21044,60.584263 C 346.21044,53.098503 348.36455,46.801883 352.67276,41.674913 C 357.22466,36.236033 363.20937,33.506853 370.6074,33.506853 C 378.00545,33.506853 384.02914,36.236033 388.66877,41.674913 C 392.97697,46.801883 395.13109,53.098503 395.13109,60.584263 z \" id=\"path54\" style=\"fill:#646464;fill-opacity:1\"/>",
469 469 " <path d=\"M 446.20583,88.266003 L 437.29699,88.266003 L 437.29699,51.928853 C 437.29699,47.942293 436.0981,44.832973 433.70032,42.591133 C 431.30253,40.359053 428.10549,39.277123 424.11893,39.364853 C 419.8887,39.442833 415.86314,40.826913 412.04229,43.507363 L 412.04229,88.266003 L 403.13345,88.266003 L 403.13345,42.405943 C 408.26042,38.672813 412.97801,36.236033 417.28621,35.095623 C 421.35076,34.033193 424.93769,33.506853 428.02752,33.506853 C 430.14264,33.506853 432.13104,33.711543 434.00248,34.120913 C 437.50169,34.929923 440.34783,36.430973 442.54093,38.633823 C 444.98744,41.070593 446.20583,43.994723 446.20583,47.415943 L 446.20583,88.266003 z \" id=\"path56\" style=\"fill:#646464;fill-opacity:1\"/>",
470 470 " <path d=\"M 60.510156,6.3979729 C 55.926503,6.4192712 51.549217,6.8101906 47.697656,7.4917229 C 36.35144,9.4962267 34.291407,13.691825 34.291406,21.429223 L 34.291406,31.647973 L 61.103906,31.647973 L 61.103906,35.054223 L 34.291406,35.054223 L 24.228906,35.054223 C 16.436447,35.054223 9.6131468,39.73794 7.4789058,48.647973 C 5.0170858,58.860939 4.9078907,65.233996 7.4789058,75.897973 C 9.3848341,83.835825 13.936449,89.491721 21.728906,89.491723 L 30.947656,89.491723 L 30.947656,77.241723 C 30.947656,68.391821 38.6048,60.585475 47.697656,60.585473 L 74.478906,60.585473 C 81.933857,60.585473 87.885159,54.447309 87.885156,46.960473 L 87.885156,21.429223 C 87.885156,14.162884 81.755176,8.7044455 74.478906,7.4917229 C 69.872919,6.7249976 65.093809,6.3766746 60.510156,6.3979729 z M 46.010156,14.616723 C 48.779703,14.616723 51.041406,16.915369 51.041406,19.741723 C 51.041404,22.558059 48.779703,24.835473 46.010156,24.835473 C 43.23068,24.835472 40.978906,22.558058 40.978906,19.741723 C 40.978905,16.91537 43.23068,14.616723 46.010156,14.616723 z \" id=\"path1948\" style=\"fill:url(#linearGradient1478);fill-opacity:1\"/>",
471 471 " <path d=\"M 91.228906,35.054223 L 91.228906,46.960473 C 91.228906,56.191228 83.403011,63.960472 74.478906,63.960473 L 47.697656,63.960473 C 40.361823,63.960473 34.291407,70.238956 34.291406,77.585473 L 34.291406,103.11672 C 34.291406,110.38306 40.609994,114.65704 47.697656,116.74172 C 56.184987,119.23733 64.323893,119.68835 74.478906,116.74172 C 81.229061,114.78733 87.885159,110.85411 87.885156,103.11672 L 87.885156,92.897973 L 61.103906,92.897973 L 61.103906,89.491723 L 87.885156,89.491723 L 101.29141,89.491723 C 109.08387,89.491723 111.98766,84.056315 114.69765,75.897973 C 117.49698,67.499087 117.37787,59.422197 114.69765,48.647973 C 112.77187,40.890532 109.09378,35.054223 101.29141,35.054223 L 91.228906,35.054223 z M 76.166406,99.710473 C 78.945884,99.710476 81.197656,101.98789 81.197656,104.80422 C 81.197654,107.63057 78.945881,109.92922 76.166406,109.92922 C 73.396856,109.92922 71.135156,107.63057 71.135156,104.80422 C 71.135158,101.98789 73.396853,99.710473 76.166406,99.710473 z \" id=\"path1950\" style=\"fill:url(#linearGradient1475);fill-opacity:1\"/>",
472 472 " <path d=\"M 463.5544,26.909383 L 465.11635,26.909383 L 465.11635,17.113143 L 468.81648,17.113143 L 468.81648,15.945483 L 459.85427,15.945483 L 459.85427,17.113143 L 463.5544,17.113143 L 463.5544,26.909383 M 470.20142,26.909383 L 471.53589,26.909383 L 471.53589,17.962353 L 474.4323,26.908259 L 475.91799,26.908259 L 478.93615,17.992683 L 478.93615,26.909383 L 480.39194,26.909383 L 480.39194,15.945483 L 478.46605,15.945483 L 475.16774,25.33834 L 472.35477,15.945483 L 470.20142,15.945483 L 470.20142,26.909383\" id=\"text3004\" style=\"font-size:15.16445827px;font-style:normal;font-weight:normal;line-height:125%;fill:#646464;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans\"/>",
473 473 " <path d=\"M 110.46717 132.28575 A 48.948284 8.6066771 0 1 1 12.570599,132.28575 A 48.948284 8.6066771 0 1 1 110.46717 132.28575 z\" id=\"path1894\" style=\"opacity:0.44382019;fill:url(#radialGradient1480);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:20;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1\" transform=\"matrix(0.73406,0,0,0.809524,16.24958,27.00935)\"/>",
474 474 " </g>",
475 475 "</svg>"
476 476 ],
477 477 "text": [
478 478 "&lt;IPython.core.display.SVG at 0x41d4910&gt;"
479 479 ]
480 480 }
481 481 ],
482 482 "prompt_number": 3
483 483 },
484 484 {
485 485 "cell_type": "markdown",
486 486 "source": [
487 487 "### Video"
488 488 ]
489 489 },
490 490 {
491 491 "cell_type": "markdown",
492 492 "source": [
493 493 "And more exotic objects can also be displayed, as long as their representation supports ",
494 494 "the IPython display protocol.",
495 495 "",
496 496 "For example, videos hosted externally on YouTube are easy to load (and writing a similar wrapper for other",
497 497 "hosted content is trivial):"
498 498 ]
499 499 },
500 500 {
501 501 "cell_type": "code",
502 502 "collapsed": false,
503 503 "input": [
504 504 "from IPython.lib.display import YouTubeVideo",
505 505 "# a talk about IPython at Sage Days at U. Washington, Seattle.",
506 506 "# Video credit: William Stein.",
507 507 "YouTubeVideo('1j_HxD4iLn8')"
508 508 ],
509 509 "language": "python",
510 510 "outputs": [
511 511 {
512 512 "html": [
513 513 "",
514 514 " <iframe",
515 515 " width=\"400\"",
516 516 " height=\"300\"",
517 517 " src=\"http://www.youtube.com/embed/1j_HxD4iLn8\"",
518 518 " frameborder=\"0\"",
519 519 " allowfullscreen",
520 520 " ></iframe>",
521 521 " "
522 522 ],
523 523 "output_type": "pyout",
524 524 "prompt_number": 4,
525 525 "text": [
526 526 "&lt;IPython.lib.display.YouTubeVideo at 0x41d4310&gt;"
527 527 ]
528 528 }
529 529 ],
530 530 "prompt_number": 4
531 531 },
532 532 {
533 533 "cell_type": "markdown",
534 534 "source": [
535 535 "Using the nascent video capabilities of modern browsers, you may also be able to display local",
536 536 "videos. At the moment this doesn't work very well in all browsers, so it may or may not work for you;",
537 537 "we will continue testing this and looking for ways to make it more robust. ",
538 538 "",
539 539 "The following cell loads a local file called `animation.m4v`, encodes the raw video as base64 for http",
540 540 "transport, and uses the HTML5 video tag to load it. On Chrome 15 it works correctly, displaying a control",
541 541 "bar at the bottom with a play/pause button and a location slider."
542 542 ]
543 543 },
544 544 {
545 545 "cell_type": "code",
546 546 "collapsed": false,
547 547 "input": [
548 548 "from IPython.core.display import HTML",
549 549 "video = open(\"animation.m4v\", \"rb\").read()",
550 550 "video_encoded = video.encode(\"base64\")",
551 551 "video_tag = '<video controls alt=\"test\" src=\"data:video/x-m4v;base64,{0}\">'.format(video_encoded)",
552 552 "HTML(data=video_tag)"
553 553 ],
554 554 "language": "python",
555 555 "outputs": [
556 556 {
557 557 "html": [
558 558 "<video controls alt=\"test\" src=\"data:video/x-m4v;base64,AAAAHGZ0eXBNNFYgAAACAGlzb21pc28yYXZjMQAAAAhmcmVlAAAqiW1kYXQAAAKMBgX//4jcRem9",
559 559 "5tlIt5Ys2CDZI+7veDI2NCAtIGNvcmUgMTE4IC0gSC4yNjQvTVBFRy00IEFWQyBjb2RlYyAtIENv",
560 560 "cHlsZWZ0IDIwMDMtMjAxMSAtIGh0dHA6Ly93d3cudmlkZW9sYW4ub3JnL3gyNjQuaHRtbCAtIG9w",
561 561 "dGlvbnM6IGNhYmFjPTEgcmVmPTMgZGVibG9jaz0xOjA6MCBhbmFseXNlPTB4MzoweDExMyBtZT1o",
562 562 "ZXggc3VibWU9NyBwc3k9MSBwc3lfcmQ9MS4wMDowLjAwIG1peGVkX3JlZj0xIG1lX3JhbmdlPTE2",
563 563 "IGNocm9tYV9tZT0xIHRyZWxsaXM9MSA4eDhkY3Q9MSBjcW09MCBkZWFkem9uZT0yMSwxMSBmYXN0",
564 564 "X3Bza2lwPTEgY2hyb21hX3FwX29mZnNldD0tMiB0aHJlYWRzPTEgc2xpY2VkX3RocmVhZHM9MCBu",
565 565 "cj0wIGRlY2ltYXRlPTEgaW50ZXJsYWNlZD0wIGJsdXJheV9jb21wYXQ9MCBjb25zdHJhaW5lZF9p",
566 566 "bnRyYT0wIGJmcmFtZXM9MyBiX3B5cmFtaWQ9MiBiX2FkYXB0PTEgYl9iaWFzPTAgZGlyZWN0PTEg",
567 567 "d2VpZ2h0Yj0xIG9wZW5fZ29wPTAgd2VpZ2h0cD0yIGtleWludD0yNTAga2V5aW50X21pbj0yNSBz",
568 568 "Y2VuZWN1dD00MCBpbnRyYV9yZWZyZXNoPTAgcmNfbG9va2FoZWFkPTQwIHJjPWNyZiBtYnRyZWU9",
569 569 "MSBjcmY9MjMuMCBxY29tcD0wLjYwIHFwbWluPTAgcXBtYXg9NjkgcXBzdGVwPTQgaXBfcmF0aW89",
570 570 "MS40MCBhcT0xOjEuMDAAgAAACqVliIQAV/0TAAI/3gU2tIW7KawwaCmQGTGHKmuYAAADACBcshU+",
571 571 "yICkgAA14AHowiEeT6ei7v7h3Hu0i2fpUBLGBIkbCMP3Vfz+9BVGCDXnw9Uv5o3iN030tb7eq6rs",
572 572 "EEhHs2azbdTiE9Csz5Zm6SiUWRdmB43hbD5i6syATuODUJd7LM3d9cbFpc7zFlu5y3vUmNGd6urp",
573 573 "vKKT9iyleIyTuR1sVS431DhevGfkUllVeIznYUe2USoMW1tufETjyRdmGldN6eNlhAOsGAH4z+Hk",
574 574 "rwKecPPU7Q5T4gDAIxj9hW84jVExMTSTHxkPTq1I4OotgUxURCGTsw60k/ezPNmNg38j1bqaGmPc",
575 575 "ruDKEIBDsK5qEytFB90Q68s0h2wmlf2KXd5bleBefiK+/p47ZsyUO4IdlW25rRy+HLjt6wQXfYee",
576 576 "3IkiQOoOK+U7u/lxcl78zfxwIoEMjUUSKNZjkp8clnmecDDJ3Kz+viF7bPklk7N6QRyizAKPIIpn",
577 577 "NJUuMWQmqeL2Or6cr4D0/0tOym+4tficxmhuEONKUtO2pPn3hRjMllkd12tXp70fLTfxy0dwB70M",
578 578 "L9iLEcItHb7zVupHlP5RxdvecpREw+OsIPr9KWilIesNE19jgIbT+TkiRBjOoKvUuwcQnKg7fOTH",
579 579 "VoLvnKuAfea+oujEdm1Rwd2tEOnkF+ZC11WaNQsiNR/eJ9EnUXjXDYGfhB+Oe7qj8nYTT+eOXg1c",
580 580 "uJNgLXEs4vOheWEjQOqfIWMQc3DmTof5s0ksBmUQ3PQ+UHPxZSnmOEZB+j6xT3wbm7HGzDjWtSg1",
581 581 "SjTxd1EiJ8xA4SIxxR8WIKLg+TwFxJNS7Laxq7Uglu3AkXe82P1JCdJX5PsbFbxuDbuJgakzRcTw",
582 582 "MLLSKCiizS/eCW0uJed/lev9yb80kKlVET4S219cn/zhkpeDV83cHYOr+sJQKDRk/Wh2c7fsuxfx",
583 583 "aEH/6reSmvFDsAnXAyPXliJ3G4VG3OkEM5K5WyGGrBizZbTrdGsBnzj5VSGGOJdCKuRrUluw/8es",
584 584 "2vYRPs9BcTqAqvHk9M52SSIf+1T6L53EZP8VbtXB+G29CMW4xVCK/B/YDjaNmqMwJ61dapugjnWJ",
585 585 "fqeXlGGa3Ch3aA7gi30T8PucNRBjLK3lF67ZDDvkWXRQXd+VMnKWHkBbCkQ/F/fMuNpHO3C00Y2p",
586 586 "ljna1qImBhVMvPe0F7Qx7G/YyxLRzhyUU8e23HGzp0agtNJRbydbrPV+TqJMSifJMNcZIf8wkdnC",
587 587 "3/xdpcXnLf2Ye3Kbd0o7utciTG+q5h6WTEk+PaNbXLLA0YyZ2VnLTcyV1QTS76aNCbV9Q1/OQ7QU",
588 588 "81Gg0hPa9aSiscGary6jLVwDQaik4zLsi7jPqgPVdup7pwx7uJDqRCVcVi5QoZFp/GHdex5sJTF6",
589 589 "9A6sja69/NLkFIWNSIeRcuGahXpF+wZeYIrqJv975s1TKYKAvp1WtzgtgWNkcbzCtROqf8rPtlAI",
590 590 "xkX8GLcEo9zfExyfimeXQ64qfFxEy0IMy2Hsxau9fSMqUnIjntuVVjCQtBL+94gx1RZLndE6wROV",
591 591 "Tq/wHwHrQzo9QL9cpPqPFJjiZ/NGZIFuudS+wsBFe6Hu8Oitf5zToLqLdtU4Smwh4ne3JsiT9lOz",
592 592 "N+4PPw3VSx9l5FppVwdKUWELw1dYpCOppyVWlJ3YQ8H4FQQM8EcYMG9N3Bxu79y1J1ikuvuhMmLQ",
593 593 "lehLTbguhbix74hd1VIQC8EjHmOZSSWbssulYwPbr6FF49tifk6PymJvulR9/u+2585HkRfbxveG",
594 594 "eWCz0ix1pIVfaNpESKmtLy/0mcbMg9hYDz2werz9oe0lT2BiMV6uAin6RaQcT8Vk9MPctfwae+gk",
595 595 "vtnZA/sOBk8MbpylaHqc0KIVHhhLFMNnkOFiucjtGo/JWTa/F6g8wWeow5ZuIJUORaYHWqegZbTg",
596 596 "M9dCsYYsfZGjjVMuSlDIvpYvIvFFooGPC7Ye2Jfawmq4Ut7EL/nv/dyAd2HRc5msmUhzeu/XpX3r",
597 597 "VlzRmf9/Qan8Dbve3QfW1Ym0o5J/KAc3z1VBho7JBr5PgCL68RiD9jZHN0VvsT4gzsEjNlW3D91U",
598 598 "y4RduaodBFoNTzXwlfUYULBzdiTbH75l/UmVMC4TKeTWhNzw2UezaqeGd8at3WSY7W/VR3+hvZHD",
599 599 "pkIjgKuNNH0DsCRa/Kk56XQoHIyvvUH/eNekNvziReqS4qgLnXUT4BRGt2BOtCifI6+X/DGHUOmW",
600 600 "lX7TN5b4pw5U7jwfwshtbhGZM49T8JMk15Mzrc7tM6J11TYxb5R3mQhZ8TZumJ0bMJXPM69HFyih",
601 601 "r5dJSEJMycxJVUh6NTQALUOoRTHIOwE+FpWI6feTv1SiZ0YpYe5DbkYJJbN7zAHbAKw25XvqR2mA",
602 602 "jQmOlsfX/tK8DPjP/8h5/xgAF4EUbj1tOnQCBQL8jk9vHtfsXncsprww4Z+P/Z/UrKifuFyEpBWN",
603 603 "8kLpF7yywE2iYdDruV9+/qKR8rC9ozNKyqQNIwtxrzYkWpE5t8K7gG4JFnrHona/Rp8dOX6VW41+",
604 604 "jb5LB1LEtE8MwjLp3RCUOq/+6yLzaOEgBTqzvEjDeFpg/u9DMHMr4/2TOchfjg7dl+uQ6Gsx+4Ia",
605 605 "9W7vivG95027p25eKL0nHvx/OqmAQEZYJL/JO58lOj0zPdJxrQ5dZksjMISzVZNn7DsxqE3zgBBu",
606 606 "Nzk50R8lTK3U8P12QiOAQYSTeGlYlkvfeofrfO1AitEj02m9aUkxTFd1ZZJoLQT2d3zEU5PmE4lx",
607 607 "MVfL5ttNnIbqfcIU2RJKNWqdw77xfjfrNc/eNpRKPZ/6z50LzBprgjzBHRfKgSWWkDxHrX0aTbgw",
608 608 "QFwd51+PoUWH4DkQg26uGslF5Hn3hB58+fkeLTosTANOIBNAeFZtTc4PIaLHw759zae7scY55xcT",
609 609 "abzlilYIftst2RZ6ntsRC3zFxduCKvL6wLfYT+TiIWJn5P7sTwZwXuSzXY+9Q3xMZ5o4Xcpz6vD9",
610 610 "FtTjzS69iefEYt4pXiDrZUo4ePGiLeoIFIwYB/v6GXdmG5VLLk+eKbOc9AmsX2zmvqtcvDRGQbzu",
611 611 "gXbH/kTH/lkNPBTmqN3ZJODUEXVohPEJ6th0xna0EVleB73Q3eNvaVUvhlJbjs3D/T17FRCebN7A",
612 612 "OXvzzbLE/I5kNfEmJcv4dxtIeo2uQ/z9ohSpiZzbDj1u40nJRyJxUK60wEv0nA9f/NuJ6/PEyU0b",
613 613 "kK16z2KH12k3Lc4+1f5fawIzkK2qJRB4wnj8VHhUW9mbJhs9vgfFmU3xrXSShY67Ygb+gYNPxxtn",
614 614 "4K/9eTSwIA9fv/nR33lA2lZoXALRUTmOZIl3R0gAM5h6oX1y1thIyqViBK95VZc8Pvy7G3O90M9S",
615 615 "4zkpyFQ36jrMazvMveMA4d39fvoaC7p90quiJfjI4yrl+ECVkCJL5MxRSa+iVcIL7Xbl0jVaGhZI",
616 616 "cMYmcGOBbLzhJgloM1x1zFnnj3ggJRFAM8yNnXxhavk+mA18JC+y3lqGsp6vPReRxGlGHMou17L4",
617 617 "It070LzkoeCzarpv8Apw59smdS5KN9qVN1WgeL7OSN8BHg94ubCvS7DW6H3/PbtRB62jFLsBhUV5",
618 618 "YqCIbIN5VZ81AAACpUGaIWxFfwAru8x8uT3FuOjrAeSWXmAWqq9jCNGE+N5AOv//9//xjk4uBAcA",
619 619 "DN96c97AVGmzRtnWwPsgcCbLrVdQJgbKp4QSmPwQnVhv0hXyBjeFWWlcvx70urEN3FK6/lvk2tQe",
620 620 "ZgbtlbzXluvTfnSj/Ctz7vZ+O1FjhDzzdpL7uLzewzCIW5VWLAEKUVuS2J6wNk6MR7UblcEd4EtO",
621 621 "Y+R4/qJgfojCsfRvA0oC5dc41Vd0erZbSkrmPTjLCn815bxlchUJMS8gQD5hJNwoKHvNLNwn7XKu",
622 622 "TtYIhH2wVNZvDWgzCjlPeQajnrcMsb6bZYJvNJU8HuGHvm50r7VG8qifEwmuyegAZXojh5Ul5Vvj",
623 623 "DW7kSAZyw8a7I6mHY3FZHd+OA3V4JZMbNliI3Tj1L6+MKTmilVialmyZagRtEMeKRdtxUPd3vVEt",
624 624 "rOBVIVYWdgAGA7HmZiHQUQNxLkWxbLyWVlrh5EM0Do2NdbclHxxArz90d+MSVeUOIXQ/4V9quq8C",
625 625 "8qVflo1gPtPMkjO2/UrdOYqhY404ReObOu/fdp4hAEDq6jhy64vOeT7XUK/Onq0rXTldtA6kvgQa",
626 626 "Jg+mgYSR9hfXtMbOUSLgLj/RmBSO8aAMHuJJZqf1tCM5pZ9eYUsrHmy+/z2NGalon0//uF6+33bQ",
627 627 "zT/RLRfBbYTjy9QrJqHLlw46lggWPGkHuPKSqk/CB7U4pNPXUbR0DdcJy9Db00wCzVzxVc6h7jfC",
628 628 "FgiL2Y0HVqd6bgIaVUqn/gJCEyCDVplnzebv0gg3XwMJAGu639lHu7rEvxTp1smIYjWp9R5L4Ssp",
629 629 "VvS07Nb+Smk1FgsMp1K3EMUT8X2Fty4VG54/Ec6bE8tNVw4/QV1VzBw7Px2/2eEhhUS+FMfbHAlD",
630 630 "28x00jRgAAACW0GaQjwhkymEVwArOUkEOhoFqiELtH8wgecFLiUq6WqmwAP7iGEwbYzfnHacfqUN",
631 631 "XAfD+CGR2ap0lAHL25ipuYtd5j2O0PU/MpaWPG/n2y5OkfTzaOpotaR5tWjN55B2XblVVqsFfBC/",
632 632 "mvsiPvCBWUHFChacdY5whj5mP5rqQ0dqLJCsWjrs4TWnIbL2V/Iwfj3hwI35jfo1JkTOeR+8GhOd",
633 633 "ma9rgiKWafCbQyhYMTDmVdvhND60Flm97EDSTjF0OC+0gD9b8Yn4tNeHipCa/aWyt0n79bMmjfcj",
634 634 "ntBCPjrcB5ecRTpfGHbEHy1IRj2cjkGXKC+VYoYJXBp4rd4cMd8ygLCk5nBSd8/cTaKNRjdBscOe",
635 635 "TXG6QEjSxj9/2pVwx9DMRVtWQR0BSaAcQcZ8W2KPSaeRC4QwmNMu2xx25CSyrDiq2rFSK/JJtmvo",
636 636 "IjAKq0ciEXoOgw+Ke+Ylb7ULKCS3k1p/613UNRp450uSq5b7CAHo7S0b7fBMLfNmwSjRYEhLlo0H",
637 637 "UaRe/I+IX2Z6XdZH9Hty/399ZA1PwZGC6EfvUJIf7CBeaxv7cu6IT2/s0zPRGthpvXpYw6A7P4Ww",
638 638 "z5C4V98KnIUNUanadqabKP6eXWhvbvcQHxAjiOOiKZgXZplZW2g+B2NNyJSLiR+g48DqvWR6t9S2",
639 639 "aGfFjdOW1Gi6oTtZ1d4p5XIslAr8mryeZ6+htSSQe4AcfVt7k+V6mOthBCYtr/LEU4ZHtl0mW987",
640 640 "6PK8mRFAaT8DJOUFVz1lPfzRApuPggkkyq+UMvyfKTUbCk7/DpfX8Y4s4QAAAg9BmmNJ4Q8mUwIr",
641 641 "/wAsWUPjZw3ksgRsxZ6n4fQjprPbkj2aUh30y0bZJnLmiXnWskvOGnCPwBnG9dEhatwX3hoxk7BN",
642 642 "yG+wQ4emZUpcVzcWl2T9nKQB1euucuZWHTg7TCtM/iHyfPO2vbmGsfzs70b/egIbywUH4y4BQSL1",
643 643 "nWc1SmpHm2zHMBcUjYLDZ5gL5vdfxn0V8FFw66G88c/LN4I5icUa7xf4fcSBKywU0ajbp1P+aJYj",
644 644 "BgWT6Ggu0MDLDNl54tfqd42lKosQtM1aif4WXAZFP5Ww3vrQ1rH9+utSYxqZd6N6gGtNbSNMcVia",
645 645 "Kn5LcnjsbBi3T3EmGqshEbcme8VHKwR3kSfBOAprrIsv6K8R+X6az+MD23rWka/2v64m1qM69D7X",
646 646 "a+Kcs/n0KLCJdTilyaGadopLeaAn3eYvWTeHcucMM1Fp1KgHD1tiFeO6HvobLkZlRximsA3/7Mio",
647 647 "hYklLIcJrZL22BH+6W9d6kZsYIsej9RM681nU6mWNjepBAfAfTbrGRrVB/h2DxC5B8YyRjgSIzQj",
648 648 "NYrse0rzChqbrsLl7mQ7W+1bsNKze5//9ZIa8rSsF+BXh/vgoRTDkPW/ws95B7VPCZEFChfX0icw",
649 649 "+tpcpN/q7NY87tUn4vESdSiMMlyhKklMjQu/G51J69ZRQLs2oUO6YfoJFqliy4qCFCrf8SZE9Fc6",
650 650 "DcCagAAAAodBmoRJ4Q8mUwIr/wArPWF/KOw78THwadfPqhJO0CnmR/M74/XYZLqVYKlNcEaYauf+",
651 651 "vrRUDJPmu75sMKy2Y+Bnslc/iAISSyWtw/h/3CF8fE5ZrbrwSNst+MSyCoNWP+8imtoX2eyojpdC",
652 652 "k8YP5K+cbK4SJPCkZXbYqSXYk7hO8AdSemBHgXKWiZ+UOr802aJo+98ZOIjX9hWL9bo31Gqx7cy4",
653 653 "ZG+W/ar/WGlzDa1xPWnPRsEdrIcZlEVGV/jGmbirkxw1lyUYoqj8Vv7Bxube9XPQlBkXOV6Lc1LT",
654 654 "2IzNq0V7WwVhF0kA6yxfAsFxc9krNEH8vGGntTWI608ovjatXc/CKKXw7AjJSftlTcLI0hIIGXbR",
655 655 "Ur0NCYNp7M4cVd/n73Rjetnixz4SAKpcz/P47UsijZG7T3SxzK2D79WS42aEalc12hQwCZ01LfmF",
656 656 "/H2mmGEvOzPBie1D0YT7Jh19vxa4Dd3SQ1FrDfmSUpvv4DjbYcZ2PrPpFpWtMjWqHBeoyMiZf6RP",
657 657 "3EfYR6z9jsVNIIHxM0bzzBQF8eeYkPgDySydxPXv9Izo+QUY94N8kWi16fI6eZSDc1G0Yo0L91jc",
658 658 "RQuDMGGS7B2zuf/0GbJyRhUO48UbMrqnILMrbQg1LF00Q3pH9nbGEK/RRQpRN3T/J/4IZQjwW2Ft",
659 659 "2ipWGztg1Jn9I4DmffKS60QC+JQcyakdVON6zDcKttIKlqeTcmAi4xzmo4QXa2dRKleS+fs3EtTd",
660 660 "BBtony2wK9T2Imj+NCziOSEL7Q7VuIU8kclUHrJJsSneFcxGRgIgGGUEQM8/pklwTOqab7mMmJeR",
661 661 "iaBrjJDEnDpkR4Vz3qXxgyn4/5x24FuTMNVPwQAAAhtBmqVJ4Q8mUwIr/wApcLwPT0/Xh9UdWqWX",
662 662 "Is8Wbj5K1hivmN6qIQnq+aolcegdlM/63MbHsdC6xYZC1e/Q8UjQCt9N/Ejqwms8DzeWv2qxskel",
663 663 "iZH0kt1QWkErWSEodq7V0ZNksctLkMGWayX33gBT368EehfIeGDolBZoqIbJfb4nqcfU+ev4OzVv",
664 664 "9zVqWyLck315GFmXxQKIM8pICQc8Q5es34LH1+DmnMnW8kQpVGrztQcDXhjCU3F0fOgoSsXSVWCj",
665 665 "c6XKqGbCwQDfJUxCfXfIT6YmQoPpVp1mpGy1wQypXus9z0bScDpyDu23hViYDntdj1O45ea0znKZ",
666 666 "kj1+tLHbBtqAGJ1WTcbGlF6Vya6hQhEsiiZUIC2fRxIj8/wEXCICIbr0gZ/m6gcOhE10tenvE7iy",
667 667 "+BKY81wLWrnzos3S6FWxYtmCRes+LLhNGOKWRuQo6SyePH2OZ90xZm8oA1MuTe3V59euVNxjAt0F",
668 668 "LkAc9TEiFhP/8CB+gA8mF+A8h1U01f4DVX55GzCH51jHI2xUS0L9GtsHoBxLPLK/NNel8zcnwG4X",
669 669 "+UusfcfEb5hh+ffnXteCE9vRGbs2n9wYW0xA3ZicklfadmWKUtMiHYBfkMSULWnkBQr4CXxjpYOs",
670 670 "6ygeEoA5+5B0B1SZObgZ42wWqddyyYE0NfwQAl75tfdJGqOa7OMHwBYNeatJaJK0zT2+bFaw2qWC",
671 671 "WwAAAitBmsZJ4Q8mUwIr/wAstkdsayRXchoFk703izqzduZ5WsyXriI9cfUdMUWvm0iGHwYIrUuj",
672 672 "vz3Yjou+JLwv9df2kt7MJo8u+3P5CjEKbwlz4vkE5AHTAbgXn3+Xc/MMJLgW5cm7iX3KiGNnBpbp",
673 673 "hhwJRlb3u91NRDr0d1IR2up/z7lKxE7XPAPFe0siPMYVlIqWNSn5KqLABPeuxxbOsvMEb27/nH1L",
674 674 "UVM8I2F95c1I3Lv1SpkhZXjs1JsmS9X7gsoTxkXyShGC2+zRJSGUbhCPo/q1XSFMHQyMWJ79FKPQ",
675 675 "SL/RpVsacN2bYwdKo4TFBw1SsKq/L1iOmqMI+4Gxnbbjojdk0ek0JIcDb4bHv1czxchF7FX1Ym8H",
676 676 "6IpPuE8CeNKjzQ1a1wqhEu+wl1N0x3Y37ZryCCKJRkxj0FT7bOoH3L38/yMUuh/v3aCmxY4eCkyk",
677 677 "b2p6ZrYMFE044anM/nMjmbErMibfRFuCz58Io1rBlF7JfkIz0R2/5vjUMVskcdbX2mm7DntncOsW",
678 678 "DIdg/XVmgsC9CzVzUyq4VsS/sk97lJggcddpWLNw/29egz8iLyzWHOAXCvl2fTIPkviYAOQXfVhZ",
679 679 "UQdxsyJUNFMTiALrZCmoQLMp2LmDbfbW8JQriDeR3fVz6P1sjT8C2yEDvzkCn7sh0aTBK+sx7BKH",
680 680 "1nb4320+caQepQj4TCJtCeNXjdrVcNEnjvwlcRJwFT1pT+Y7HREbHnT71XYNh4EAAAGEQZrnSeEP",
681 681 "JlMCK/8AKIjxcI58rm/ML255fOJW1zbznFna7lfgMQrka7OTPPsvVAV4EJXye/Uxiu9dlftmRypJ",
682 682 "qfDot3xwDe8lX/qAVf6pBkSlUsaLyBYtww/SUSa1bGl1JvrJCN7FXCCXbLd5R4PoYlPiDIm/DQH2",
683 683 "puO0StIWmrR77Isc/J1pRvdu5+mQa/n0SEHUeM2KkoRzCznfD9zaaRO7BDtvC9SYIT0uYZxrwTjx",
684 684 "Q7N7UERTrYG0P+vRLAhxkfohFIYl3HXyjPOvnlbUFP2oiiy6nkUFuaIyQcJawJv3GU8k4ObcKsC1",
685 685 "cNDXjSpsyQRrxLFaCCjke4mikyt7vs0iN0bnrNWv9HXruG9zOFEOer1ggIFTsT1Eos5CXRkgja5H",
686 686 "N4QUM6MhWpc5du/HgBIH8ANFcoo2kJpqcadw9r/0qk25X91MQSDJQiH8Hny2dQhqR+LFWEawiW75",
687 687 "3SJhn0ngZcv/mPj3mwcHv1SL9ErBqAjm4JGiDetPKYtFwANYY11OyQAAAVdBmwhJ4Q8mUwIr/wAr",
688 688 "Ox5HV2505jRePGgMxptW4PGIHEszV1xGZS+flSkF+aq30AaqO7u6XK9jJsuWXTfYCRQTn1bZfFQ2",
689 689 "2DbO5DXAxK/TUmbQleCflFzeS6/czxkL4PJ8AwOs2U+oehekgCZC8gZyHHaQSaKbNJ46gTjNsLy8",
690 690 "4ACQ5uNt11TPuCPqPTuh+schdw9S+/lU/6m+EyaqGZ49wDFPiBFBYXglQQBjyP9k/rqq0xL7SiLj",
691 691 "pe4riYg8SFUuUtOzPdWHyvxnI7Ug/0VLPGAAhgMISUnqe01d5QFf36yHpwMAHexjAZFIGQHAFaut",
692 692 "uMuEw6HzUZVzNdeHYxvEYOGkTo007bLwbuf/nxzrywGOxlRTYJLRdYI0mk0SdN3+LeTv1RIJwv21",
693 693 "+e9rT5iFOTCgzeQoekEWXLYz0X8YLq5bVCtijP7/T7w1Ck71j0aqfrEn6wtIAAABNUGbKUnhDyZT",
694 694 "Aiv/ACcySi7VBgOid6qZNXvhh/JsllHkMLLq0yNbQTqv/Wk2EBoSKICZwFwAD0WRzhvvReCGirep",
695 695 "1Fe4bxjm49/UR+OYrXRmHR18T0C83AUVeBk7KvDZmb/eHzuzEN4yfXucr/NWFJl+USVMY4r4UQ9C",
696 696 "ayrfEY9v6AQ6mzAdLy2UMfFxrRJ99g/Rfl8qx+m4jIZNjlrTaThzJ/3OpVmAliDfxVyg8+CVIlI3",
697 697 "1IykiwQrXcebgajG+av8XU1SfyAG5ibvwbtdSAxkGBcJWL387V+uTdY56w3KN2vBtoQpVKD2zb3y",
698 698 "azIcATZ02upwIytNcM/rpaLCdMb1myWcikE25agzLhDhOS+4zwjYz2DnW6VY0gFBAPsphhsUMnau",
699 699 "VVdUVHzCTSdvzEve/H8q4AAAAVdBm0pJ4Q8mUwIr/wAo+x5XKuiN1am7SkJKSMonFZDPU3f5XFcD",
700 700 "QSs0FLVq2idfsKwuIkt1mxIq8NgMHpzofTnDHqs/WedvAmhBgL0N5azdQa5MNKG2rJ4IAvGQY/uF",
701 701 "m3jKQAKzvhSS01gO1oIfizF817z9IShS4QK2WT0PeFPELqLSpED8eNOpVTR96vmwpk/WBKRVJdTQ",
702 702 "JzjiCQ5pgEwjtvk7KqoS0+lwXSbvIrXkYm8DignEts3DLNoLHrPjXlQmbIop76JZSyJEtB+91GrL",
703 703 "wo6Km5GeebyA2E6qGL3xSkpppej/ruoFprSKrH60UMbrq/SK7eCo+1QFoySPQmqDFsMGiQFqvtld",
704 704 "5BXDYdVI4yRaoyN7Y7wi83HRC6eVazuHU9OtIY3xJJApBWq1aJOsYwc38aTC3ee863Aa/4n9Lk4D",
705 705 "AtyFYHNZjB5m2e2vk8G2Gny9YFlBAAABQEGba0nhDyZTAiv/ACoZSZQfHxhfQxEqOBQrP+L3Dmgv",
706 706 "HSJQtB1iVkcLTxm+vagLHBLG91OGnopwrr7gT/loDypIhoRxjcwAAOeg/jN4WBbXzCJtnWGGllUC",
707 707 "SdtUZQzKOSp9iM4yX18C6jrY4Sq6R9PUV/lEGNveJR4gw4FMve7110XdEPL1O2VTdHvdqeANyaq0",
708 708 "nLdEmtXnrzvdrFlBaUvmaR4EdlkqGkvkZKWJej8Vq+msbKa7JdbxjwZtRufiyGfD/NVqMgSrYRzw",
709 709 "9z/a8Zwbr+9+19CxlWD5bCuAEfPmjY6kZJE2L/CQI6+tnCBTXOmWZtZMBoCLGOf7G2uAC3+kFlbo",
710 710 "h9as5WCkO6+iqXq29dyhKnsHInorRYsPlgxIXyU1Om/Kyhj1DJV0Am9WJK3Dln0zNUH0q6ZTOnZc",
711 711 "FD36AAABYkGbjEnhDyZTAiv/ACcwdIOLRFfoGK2ZkKsvgMwG0m0qsY0vMLPSzefc+ebp/aztyF7M",
712 712 "lsBz/fBeNtxFBcsKgR4pf65GvdfOMHah0ltZ918sMDmXUEZMeRHy/xpnWpTLeGz6uTs/7MATPmU5",
713 713 "BgHbT/DkD8QeaZnFAzidyFCXDz2l/jaKhEdgqipbB2pH0+fQ039r05z9axxEWGmaLQjg6x9+po1o",
714 714 "24yhkVO7m03YwWmPyCgy8cOwrvRyJkXJpRN4m8ZBS1zwY80HeN/VyMQQJSMwsTo7R1XMerSFuyx0",
715 715 "nz+8qOuhiqykc2ohCCsXia/+kIKbJ5Vs+cbWtvkqBKIDSfU7FhAd3GjcY/xar0EVmi6wWFTugAog",
716 716 "R3I7mTrQDdlTAqYgqO7Gn5NMXQVHu2i1zhFSdo9GjMbeGnbkJwsFbQ2XkoKRIDpuW7AewC9AEBt0",
717 717 "Ox/Ah6dGXfXO1jl8pEApj2RFmgAAAPlBm61J4Q8mUwIr/wAlR+eW/VZ7bSrmwwMA62G05DZ7p/5F",
718 718 "UugsSsQdonUq6abtbU5hjFr+I1lPgoiV5c3CkTQZS+K5zivdo+Ti2P4K90xXANp8dSMAu85uJIOC",
719 719 "Qn2TXbEnNDifLB+3V84ht5tj4lvTaZx317BcliV8D5v2zZQW8RO1mUbuJEBItst8E7hfE+ZXj7tf",
720 720 "DxNZPTvtpFyUv0fH1cTg1pr2VLy0d0zQLiA58dg+GkRvR1/hs2LyifBgHcj6eTWz0vsypVn9iPXR",
721 721 "H/unJ6i8cfFL69NO24tQ9QQB+nDFhoP2cRhkAvhHwn56n5PppBD/oxni2f8AAAE9QZvOSeEPJlMC",
722 722 "K/8AJjAXVGf+Kj2XNJnFeKC/gr7dJDTC2ngpd4WeAHlg04GuJKnn9hAmiECxxo9qM1IYMRiB85t6",
723 723 "gALnlm9sRqGmioyzAm18RJndc9Ah8RlpGzr+44a6ntRaPx0cIwNIWAA8buL2JP00dmfjNqEiAlCa",
724 724 "8OdV8FQxjp1vDXsGcAGF3Qbd62KEpkimeI3wH2nuXpbDHm8/ZKOR49s5ifUCkxCoJpfp43aC0lTz",
725 725 "h2NXpcfVw6h0QnK8G60R4ZAxOxaJB7c0nn8ixXSU2JVY24EtGMF53nxJnHfzUheewUfBOGYSxeo8",
726 726 "oK7oUCqX4rztzDwoc2QywNqQUJUkFrqIN+sb5ecYvX24Zujn+ZzTW6UDAF3R6WdNyJyRAremgC8s",
727 727 "pSflTqygQNGfHyGkfIEEJJaFo/pBCBkAAAEWQZvvSeEPJlMCK/8AKI41fuekXG59Knbw4Y6YJrit",
728 728 "sh9VtQgc3QKvVmxrzzo7f4aXn8N74eyP4b2lV1Z2Q+rohxps7EHTkOY9jLdqxI3MXe7je4g2qepz",
729 729 "71+hY+jYdX+9LO0kA0Zg3NfyAlIRX7k6c/YHAZNtNaGZgTBMqiPgmEjiJH9Luk7shbgr+srfwiYw",
730 730 "BX9rdS3fQNNFwcT8orQC+F60LAY9+GbFo2Sw3Ld4Tw9jq9yJtrY8RtHAdzytyek/mv2+j2TbTvAQ",
731 731 "KbbCYtdC8E/KtR4V5ZTSScr5Wb63vmbw7UpddEXYvl55pARyyvMxWNSh3Li4GF8Jk5JBi5B5ASQw",
732 732 "xCMYpX5hkAMc+d8tl2bT+IEvUTsAAAElQZoQSeEPJlMCK/8AJIAzFZs00JJ0yfm8CZiew4xWdArL",
733 733 "klEvBVXo/+ukPLu3XP9HFOfsme3T6BJEKmPPgZw/Lxnraq6Sl2kLVW19YU1qmqgfv+80LkZaWU5g",
734 734 "RAH4hqyo3bFYcbuY2SC3IW5Wm69gtYyAXOdbAYSEHA16fvCeRQjHEsxKVndJdrRAlrGHsKgUBQ3U",
735 735 "p/ZXIy1vkdFOfKSjpuZnswkuqr8NZI5tJ/dnBSErBTNWPaNwWV7nNomC0EYVGo+geGBhLXzaLw0U",
736 736 "AOCYGjiPc3803BDw1GLoLIXjrIFJxwRfBNIAXYZAglu30oYzhpAfRWSprkeULMWYJTlWvbUQ5CNe",
737 737 "wSZssuDWIRAc3w8AcFaywwn+YSGhtR8VI1OGjYkfBbcAAAD8QZoxSeEPJlMCK/8AJdokjCUETRw/",
738 738 "nciVPtaZQSBP/VxAQSITASEzlJBl9Na1r0DJhLOz279+KQLtl/xHZ8vAKc528mTMTqtWs4sFbeVg",
739 739 "HWyBpHcHEtgTzjIqEinp/MPuUXF5poo8YLSSMFn9Ozx2FbU5/Kh9A39oN9NHQflVxV1NA6yT/84H",
740 740 "HyfMtfdSMS8KTvAEE2lDs14VQayNs5ctjXboQT7xMBf5OLj6thhPvgaDrFB2o/PV9ouK147lruWT",
741 741 "P2mkoA9oDIMYW1pcBx4yyV/t9GOPZ3aXneMUb2fFmUCX43BjXfUDMaa4GO2/Ankj3UEQwDxA7ZlN",
742 742 "UQK2AAAA4UGaUknhDyZTAiv/ACJHv33I08bkhybYiJ/JiiheW5zMPBu4n5CxGr3frhE7TkLh0vPk",
743 743 "tM8m/AhaDiJisdk5QXNe/4WmxEDSAyaVi4eUVu0iHT2ly/KNTGqiORqA2oKpTjh84nYbrpXwnGv9",
744 744 "SOf/34Z06xN6Yo3t35UZrP8nlcs/63GtnEmnUwVZHBYfPM6bs5M5AeBfAQ/9mIqu7vnEst+5O2wp",
745 745 "PjzdItjwGCZ2ApHVjGnYYFomlA9nm6AXnxNIWHIsDgxCk3zx+6QbXipu/CWLG1Wf0WIbt4C0JPVl",
746 746 "3TEb0QAAAMlBmnNJ4Q8mUwIr/wAVV64OfTKmlktYOqZHH1W1DhPy/X/6sD4T6hRdzfOgNtTOX2Ic",
747 747 "kRJHshfBQVkJIzns079io6kpJFCcS3VD4zrWCn/dNaGV0kWTpFBRuusfn8F0C0R/EhsQeyTsdZft",
748 748 "EkLGb5tq+nrir3vfmeb7rjmWJRXkIrTEKu8pIuAd+4FBGp8ARgGe80Jqpp//s1433HqBFqXsIFJT",
749 749 "mU8j/toF9HyueI1Ea4uvsQ6NANGcYCbOAKCmbNiwABMCFaiUTMAAAAPSbW9vdgAAAGxtdmhkAAAA",
750 750 "AHwlsIB8JbCAAAAD6AAAAyAAAQAAAQAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAA",
751 751 "AAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAv10cmFrAAAAXHRraGQA",
752 752 "AAAPfCWwgHwlsIAAAAABAAAAAAAAAyAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAB",
753 753 "AAAAAAAAAAAAAAAAAABAAAAAAY4AAAGGAAAAAAAkZWR0cwAAABxlbHN0AAAAAAAAAAEAAAMgAAAA",
754 754 "AgABAAAAAAJ1bWRpYQAAACBtZGhkAAAAAHwlsIB8JbCAAAAAGQAAABRVxAAAAAAALWhkbHIAAAAA",
755 755 "AAAAAHZpZGUAAAAAAAAAAAAAAABWaWRlb0hhbmRsZXIAAAACIG1pbmYAAAAUdm1oZAAAAAEAAAAA",
756 756 "AAAAAAAAACRkaW5mAAAAHGRyZWYAAAAAAAAAAQAAAAx1cmwgAAAAAQAAAeBzdGJsAAAAtHN0c2QA",
757 757 "AAAAAAAAAQAAAKRhdmMxAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAY4BhgBIAAAASAAAAAAAAAAB",
758 758 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGP//AAAAMmF2Y0MBZAAV/+EAGWdkABWs",
759 759 "2UGQz6mhAAADAAEAAAMAMg8WLZYBAAZo6+PLIsAAAAAcdXVpZGtoQPJfJE/FujmlG88DI/MAAAAA",
760 760 "AAAAGHN0dHMAAAAAAAAAAQAAABQAAAABAAAAFHN0c3MAAAAAAAAAAQAAAAEAAAAYY3R0cwAAAAAA",
761 761 "AAABAAAAFAAAAAIAAAAcc3RzYwAAAAAAAAABAAAAAQAAAAEAAAABAAAAZHN0c3oAAAAAAAAAAAAA",
762 762 "ABQAAA05AAACqQAAAl8AAAITAAACiwAAAh8AAAIvAAABiAAAAVsAAAE5AAABWwAAAUQAAAFmAAAA",
763 763 "/QAAAUEAAAEaAAABKQAAAQAAAADlAAAAzQAAAGBzdGNvAAAAAAAAABQAAAAsAAANZQAAEA4AABJt",
764 764 "AAAUgAAAFwsAABkqAAAbWQAAHOEAAB48AAAfdQAAINAAACIUAAAjegAAJHcAACW4AAAm0gAAJ/sA",
765 765 "ACj7AAAp4AAAAGF1ZHRhAAAAWW1ldGEAAAAAAAAAIWhkbHIAAAAAAAAAAG1kaXJhcHBsAAAAAAAA",
766 766 "AAAAAAAALGlsc3QAAAAkqXRvbwAAABxkYXRhAAAAAQAAAABMYXZmNTIuMTExLjA=",
767 767 "\">"
768 768 ],
769 769 "output_type": "pyout",
770 770 "prompt_number": 5,
771 771 "text": [
772 772 "&lt;IPython.core.display.HTML at 0x423a550&gt;"
773 773 ]
774 774 }
775 775 ],
776 776 "prompt_number": 5
777 777 },
778 778 {
779 779 "cell_type": "markdown",
780 780 "source": [
781 "## Local Files",
782 "",
783 "The above examples embed images and video from the notebook filesystem in the output",
784 "areas of code cells. It is also possible to request these files directly in markdown cells",
785 "if they reside in the notebook directory via relative urls prefixed with `files/`:",
786 "",
787 " files/[subdirectory/]<filename>",
788 "",
789 "",
790 "For example, in the example notebook folder, we have the Python logo, addressed as:",
791 "",
792 " <img src=\"files/python-logo.svg\" />",
793 "",
794 "<img src=\"files/python-logo.svg\" />",
795 "",
796 "and a video with the HTML5 video tag:",
797 "",
798 " <video controls src=\"files/animation.m4v\" />",
799 "",
800 "<video controls src=\"files/animation.m4v\" />",
801 "",
802 "These do not embed the data into the notebook file,",
803 "and require that the files exist when you are viewing the notebook.",
804 "",
805 "### Security of local files",
806 "",
807 "Note that this means that the IPython notebook server also acts as a generic file server",
808 "for files inside the same tree as your notebooks. Access is not granted outside the",
809 "notebook folder so you have strict control over what files are visible, but for this",
810 "reason it is highly recommended that you do not run the notebook server with a notebook",
811 "directory at a high level in your filesystem (e.g. your home directory).",
812 "",
813 "When you run the notebook in a password-protected manner, local file access is restricted",
814 "to authenticated users unless read-only views are active."
815 ]
816 },
817 {
818 "cell_type": "markdown",
819 "source": [
781 820 "### External sites",
782 821 "",
783 822 "You can even embed an entire page from another site in an iframe; for example this is today's Wikipedia",
784 823 "page for mobile users:"
785 824 ]
786 825 },
787 826 {
788 827 "cell_type": "code",
789 828 "collapsed": false,
790 829 "input": [
791 830 "HTML('<iframe src=http://en.mobile.wikipedia.org/?useformat=mobile width=700 height=350>')"
792 831 ],
793 832 "language": "python",
794 833 "outputs": [
795 834 {
796 835 "html": [
797 836 "<iframe src=http://en.mobile.wikipedia.org/?useformat=mobile width=700 height=350>"
798 837 ],
799 838 "output_type": "pyout",
800 839 "prompt_number": 6,
801 840 "text": [
802 841 "&lt;IPython.core.display.HTML at 0x41d4710&gt;"
803 842 ]
804 843 }
805 844 ],
806 845 "prompt_number": 6
807 846 },
808 847 {
809 848 "cell_type": "markdown",
810 849 "source": [
811 850 "### Mathematics",
812 851 "",
813 852 "And we also support the display of mathematical expressions typeset in LaTeX, which is rendered",
814 853 "in the browser thanks to the [MathJax library](http://mathjax.org). ",
815 854 "",
816 855 "Note that this is *different* from the above examples. Above we were typing mathematical expressions",
817 856 "in Markdown cells (along with normal text) and letting the browser render them; now we are displaying",
818 857 "the output of a Python computation as a LaTeX expression wrapped by the `Math()` object so the browser",
819 858 "renders it:"
820 859 ]
821 860 },
822 861 {
823 862 "cell_type": "code",
824 863 "collapsed": false,
825 864 "input": [
826 865 "from IPython.core.display import Math",
827 866 "Math(r'$F(k) = \\int_{-\\infty}^{\\infty} f(x) e^{2\\pi i k} dx$')"
828 867 ],
829 868 "language": "python",
830 869 "outputs": [
831 870 {
832 871 "latex": [
833 872 "$F(k) = \\int_{-\\infty}^{\\infty} f(x) e^{2\\pi i k} dx$"
834 873 ],
835 874 "output_type": "pyout",
836 875 "prompt_number": 8,
837 876 "text": [
838 877 "&lt;IPython.core.display.Math at 0x45840d0&gt;"
839 878 ]
840 879 }
841 880 ],
842 881 "prompt_number": 8
843 882 },
844 883 {
845 884 "cell_type": "markdown",
846 885 "source": [
847 886 "# Loading external codes",
848 887 "* Drag and drop a ``.py`` in the dashboard",
849 888 "* Use ``%loadpy`` with any local or remote url: [the Matplotlib Gallery!](http://matplotlib.sourceforge.net/gallery.html)",
850 889 "",
851 890 "In this notebook we've kept the output saved so you can see the result, but you should run the next",
852 891 "cell yourself (with an active internet connection)."
853 892 ]
854 893 },
855 894 {
856 895 "cell_type": "code",
857 896 "collapsed": true,
858 897 "input": [
859 898 "%loadpy http://matplotlib.sourceforge.net/mpl_examples/pylab_examples/integral_demo.py"
860 899 ],
861 900 "language": "python",
862 901 "outputs": [],
863 902 "prompt_number": 8
864 903 },
865 904 {
866 905 "cell_type": "code",
867 906 "collapsed": false,
868 907 "input": [
869 908 "#!/usr/bin/env python",
870 909 "",
871 910 "# implement the example graphs/integral from pyx",
872 911 "from pylab import *",
873 912 "from matplotlib.patches import Polygon",
874 913 "",
875 914 "def func(x):",
876 915 " return (x-3)*(x-5)*(x-7)+85",
877 916 "",
878 917 "ax = subplot(111)",
879 918 "",
880 919 "a, b = 2, 9 # integral area",
881 920 "x = arange(0, 10, 0.01)",
882 921 "y = func(x)",
883 922 "plot(x, y, linewidth=1)",
884 923 "",
885 924 "# make the shaded region",
886 925 "ix = arange(a, b, 0.01)",
887 926 "iy = func(ix)",
888 927 "verts = [(a,0)] + zip(ix,iy) + [(b,0)]",
889 928 "poly = Polygon(verts, facecolor='0.8', edgecolor='k')",
890 929 "ax.add_patch(poly)",
891 930 "",
892 931 "text(0.5 * (a + b), 30,",
893 932 " r\"$\\int_a^b f(x)\\mathrm{d}x$\", horizontalalignment='center',",
894 933 " fontsize=20)",
895 934 "",
896 935 "axis([0,10, 0, 180])",
897 936 "figtext(0.9, 0.05, 'x')",
898 937 "figtext(0.1, 0.9, 'y')",
899 938 "ax.set_xticks((a,b))",
900 939 "ax.set_xticklabels(('a','b'))",
901 940 "ax.set_yticks([])",
902 941 "show()"
903 942 ],
904 943 "language": "python",
905 944 "outputs": [
906 945 {
907 946 "output_type": "display_data",
908 947 "png": "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\nSUVORK5CYII=\n"
909 948 }
910 949 ],
911 950 "prompt_number": 9
912 951 },
913 952 {
914 953 "cell_type": "code",
915 954 "collapsed": true,
916 955 "input": [],
917 956 "language": "python",
918 957 "outputs": [],
919 958 "prompt_number": "&nbsp;"
920 959 }
921 960 ]
922 961 }
923 962 ]
924 963 } No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now