Skip to content

Instantly share code, notes, and snippets.

@clayadavis
Created September 23, 2013 23:45
Show Gist options
  • Save clayadavis/6678534 to your computer and use it in GitHub Desktop.
Save clayadavis/6678534 to your computer and use it in GitHub Desktop.
{
"metadata": {
"name": ""
},
"nbformat": 3,
"nbformat_minor": 0,
"worksheets": [
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"How to Python Like a Boss\n",
"=============\n",
"## Anaconda & Scipy for data analysis\n",
"\n",
"![](files/likeaboss.jpg)\n",
"\n",
"## Clayton Davis\n",
"## NaN, 23 Sep 2013"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# Why Python?\n",
"\n",
"* It's the best thing ever"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"#No, seriously\n",
"\n",
"* Expressive language with easy-to-read syntax makes it easier to share and reuse code\n",
"* Large ecosystem of high-quality modules makes it easy to not reinvent the wheel"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"#So how do I Python Like a Boss?\n",
"\n",
"1. Use a Python distribution\n",
"2. Use IPython + notebook\n",
"3. Use the Scipy stack"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# 1. Use a Python Distribution"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"No, scratch that..."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# 1. Use *Anaconda* Python Distribution\n",
"\n",
"[http://continuum.io/downloads](http://continuum.io/downloads)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Convenience\n",
"\n",
"* Many popular packages for science and data analysis preinstalled"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Portability\n",
"\n",
"* Use *your* version and *your* packages on any campus machine\n",
" * The Simpsons (CNetS)\n",
" * FutureGrid\n",
" * Big Red II\n",
"* Default Python installs on these machines are out of date"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Compatibility\n",
"* Fix the \"Python Packaging Problem\" with dependency resolution\n",
"* Anaconda uses **`conda`** as its package manager, instead of `pip` or `easy_install`\n",
"* Use separate environments for incompatible packages"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Shareability\n",
"\n",
"* Freeze the requirements for a particular package or script\n",
" * Share the requirements as dependencies\n",
" * If using Anaconda, share the entire environment"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"#DEMOS\n",
"\n",
"\n",
"* Installing and updating Anaconda\n",
"* Installing packages with `conda` and `pip`\n",
"* Using `conda` for package environments\n",
"\n",
"Docs can be found [online](http://docs.continuum.io/conda/index.html).\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"# Installing and updating Anaconda\n",
"**This works on campus machines**\n",
"\n",
"Find the correct link at [http://continuum.io/downloads](http://continuum.io/downloads) then type something like the following in your command shell:\n",
"<pre>\n",
" wget &lt;copy-paste that link&gt;\n",
" bash Anaconda-&lt;your version&gt;.sh\n",
"</pre>\n",
" \n",
"Answer yes at the prompts. At the end, the installer asks if you want to add Anaconda to your `PATH`, say yes if this will be your primary Python install.\n",
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"To update all of anaconda's packages at once:\n",
"\n",
" conda update anaconda"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"# Installing packages with `conda` and `pip`\n",
"\n",
"Conda is preferable since it does dependency resolution:\n",
"\n",
" conda install pymc"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"But not all packages are in the conda repositories\n",
" \n",
" conda install geopy\n",
"\n",
"In that case, use `pip`\n",
"\n",
" pip install geopy"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"# Using `conda` for package environments\n",
"\n",
"The current version of NetworkX is 1.8.1, but suppose I have a script that is dependent on NetworkX 1.7 for now. This calls for package environments!"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"* Create a new environment named \"nx1.7\", and link all the Anaconda packages\n",
"\n",
" conda create -n nx1.7 anaconda\n",
" \n",
"* List all currently-defined environments:\n",
"\n",
" conda info -e\n",
" \n",
"* Activate our new environment:\n",
"\n",
" source activate nx1.7\n",
" \n",
"* Replace NetworkX 1.8 with 1.7:\n",
" \n",
" conda install networkx=1.7\n",
" \n",
"* Deactivate our new environment, returning to the base Anaconda env:\n",
"\n",
" source deactivate nx1.7"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"Environments are also a great way to have Python 2.7 and 3.3 side-by-side:\n",
"\n",
" conda create -n py3.3 python=3.3 anaconda\n",
" \n",
"Then, like before, I can just switch to py3k with a\n",
"\n",
" source activate py3.3\n",
" \n",
"and switch back with\n",
"\n",
" source deactivate py3.3"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"#2. Use IPython"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
" \n",
"## IPython shell\n",
"\n",
"## IPython notebook"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"#IPython shell\n",
"\n",
"* Enhanced Python shell\n",
"* Comes in console and Qt versions\n",
"* Awesome features\n",
" * Tab-completion\n",
" * Magic (special %-prefixed commands)\n",
" * Inline plots in Qt console"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"#IPython magic"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"import random as rd\n",
"import numpy as np"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"prompt_number": 1
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%timeit a = [rd.random() for x in range(1000)]"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"10000 loops, best of 3: 102 \u00b5s per loop\n"
]
}
],
"prompt_number": 2
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%timeit a = [np.random.random() for x in range(1000)]"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"10000 loops, best of 3: 182 \u00b5s per loop\n"
]
}
],
"prompt_number": 3
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%timeit a = np.random.random(1000)"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"100000 loops, best of 3: 14 \u00b5s per loop\n"
]
}
],
"prompt_number": 4
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"There are also cell magics for use in IPython notebook"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%time\n",
"# This is a terrible way to do this\n",
"fib = [0, 1]\n",
"for i in range(10**5):\n",
" fib.append(fib[-1] + fib[-2])"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"CPU times: user 208 ms, sys: 24 ms, total: 232 ms\n",
"Wall time: 210 ms\n"
]
}
],
"prompt_number": 15
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"#DEMO Qt console\n",
"\n",
"Run the following:\n",
"<pre>\n",
" ipython qtconsole --pylab inline\n",
"</pre>\n",
" \n",
"then paste this in the Qt console:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"from scipy.special import jn\n",
"x = linspace(0, 4*pi)\n",
"for i in range(6):\n",
" plot(x, jn(i, x))"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"metadata": {},
"output_type": "display_data",
"png": "iVBORw0KGgoAAAANSUhEUgAAAX0AAAD7CAYAAACG50QgAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzsnXd4FFUXxt9QBaQnhJDQO0IoKqCI8GEDsYHYBcQCqAgq\nYldAEVAQEFC6AqIUKQIKCAiB7KYX0kN6771tn/f7YwAhdWsSyP09T55kd+/cc2aze+bOuafYkSQE\nAoFA0CBoVNcKCAQCgaD2EEZfIBAIGhDC6AsEAkEDQhh9gUAgaEAIoy8QCAQNCGH0BQKBoAHRpK4V\nuMqwYcMQFBRU12oIBALBTcPQoUNx6dIlk46pNyv9oKAgkLwpfxYvXlznOgj9614Pof/N+XMz62/O\nQrneGH2BQCAQ2B5h9AUCgaABIYy+FRg/fnxdq2ARQv+6Rehft9zs+puKHcl6UXvHzs4O9UQVgUAg\nuCkwx26Klb5AIBA0IITRFwgEggaEMPoCgUDQgBBGXyAQCBoQwugLBAJBA0IYfYFAIGhACKMvEAgE\nDQhh9AUCgaABIYy+QCAQNCCE0RcIBIIGhDD6AoFA0IAQRl8gEAgaEMLoCwQCQQNCGH2BQCBoQFhk\n9F999VU4OjpiyJAhVY6ZP38++vbti6FDhyIwMNAScQKBQCCwEIuM/qxZs3Dq1KkqXz9x4gRiYmIQ\nHR2NrVu34s0337REnEAgEAgsxCKjP3bsWLRv377K148dO4aZM2cCAEaNGoWCggJkZmZaIlIgEAgE\nFmBTn35qaiq6du167bGLiwtSUlJsKVIgEAgE1dDE1gLKt/Kys7Orcuz48UswaBDQqZPct7Kh9a4U\nCASC6nBzc4Obm5tFc9jU6Ds7OyM5Ofna45SUFDg7O1c5fvjwJTh4EGjdGiABe3tg8GBbaigQCAQ3\nD+UXw0uXLjV5Dpu6d5544gns3r0bAODl5YV27drB0dGxyvFr1wKJicDPPwMlJcDDDwNffCFfAAQC\ngUBgOXY0tZX6dbzwwgu4cOECcnJy4OjoiKVLl0Kn0wEA5syZAwCYN28eTp06hVatWuGXX37BiBEj\nKlekkq7u2dnAgw8CkyYBK1YA1XiGBAKBoMFRmd2s8RhLjL41qUr53FzgoYeA8eOB778Xhl8gEAiu\nYo7Rr/cZuR07Av/+CygUwDvvAJJU1xoJBALBzUu9N/oA0L49cOYMEBAAvPmmMPwCgUBgLjeF0QeA\ntm2Bf/4BIiKA114DDIa61kggEAhuPm4aow/IoZwnTwJxccCyZXWtjUAgENx81PuN3MpISQGGDwcu\nXgQGDrSxYgKBQFBPuSU3civDxQVYsgSYPVv49wUCgcAUbkqjDwBz5wJ6PbB9e11rIhAIBDcPN6V7\n5yqhocD//gcEBwNOTjZSTCAQCOopt2RyVk18/jkQGQkcPGgDpQQCgaAe02B8+tfz+efySv/o0brW\nRCAQCOo/N/1KHwDc3IDp04GwMKBNG+vqJRAIBPWVBuneucrrrwMtWgAbNlhRKYFAIKjHNGijn5cn\n194/fBgYPdqKigkEAkE9pUH69K/SoQOwfDnw6ad1rYlAIBDUX24Zow8AL70kl2jw9KxrTQQCgaB+\ncksZ/aZNgQ8/lBuuCAQCgaAit4xP/yoqFdCrl1yR09XVCooJBAJBPaVB+/Sv0qIF8N57wMqVda2J\nQCAQ1D9uuZU+ABQXy6t9T0+gTx+rTCkQCAT1DrHSv0Lr1sBbbwHfflvXmggEAkH94pZc6QNyQ/W+\nfeUSDS4uVptWIBAI6g1ipX8dHTsCs2YB339f15oIBAJB/eGWXekDQGoqMGQIcPky4OBg1akFAoGg\nzhEr/XI4OwPPPAOsX1/XmggEAkH94JZe6QNyhu7IkfJvUYFTIBDcSoiVfiX06gVMnAhs2lTXmggE\nAkHdc8uv9AEgIACYOhWIjQUaN7aJCIFAIKh1xEq/CkaMAOztgTNn6loTgUAgqFsahNEHgNmzga1b\n61oLgUAgqFsahHsHkEszdOsGhIcDTk42EyMQCAS1hnDvVEPr1sC0acDOnXWtiUAgENQdDWalDwC+\nvsBzzwExMUCjBnO5EwgEtypipV8Dd90FtG0LnDtX15oIBAJB3dCgjL6dndjQFQgEDZsG5d4BgMJC\noEcPIDIScHS0uTiBQCCwGcK9YwRt2wJTpgC7dtW1JgKBQFD7NLiVPgB4eQHTpwNRUbLLRyAQCG5G\nxErfSEaNknvpurnVtSYCgUBQuzRIoy82dAUCQUOlQbp3ACA/H+jZU47Zt7evNbECgUBgNYR7xwTa\ntweefBLYvbuuNREIBILao8EafQB44w1gxw6gftzrCAQCge1p0EZ/zBigrAwICqprTQQCgaB2aNBG\n384OePFF4Lff6loTgUAgqB0a7EbuVcLDgYcfBhITRVctgUBwcyE2cs1g0CDAwQG4eLGuNREIBALb\n0+CNPgC89JJxLh6SiMqNQom2xPZKCQQCgQ1o8O4dAEhNBVxd5d+33Vbx9cSCRPwa/Ct2B+1Gqa4U\n+ap8dL69M4Y4DsFgh8EY3GkwhnYeioH2A2En6joIBIJawhy7KYz+FSZMAObNA6ZOlR+XaEtwKPwQ\ndgXtQnBmMJ6941nMHDoTI51HQqKEmLwYhGaFIiQrBKFZofBK8cKYbmOwafImdGjRoc7OQyAQNByE\n0beA7duBkyeBQ4eAo5FHMevoLIzpNgYzh87E4/0eR/Mmzas9XqVT4ZN/P8GhiEP4+Ymf8VDvh2pJ\nc4FA0FARRt8CCgqA7t2BZX/vwHLvz3H8heO4q8tdJs9zJvYMXj32KqYOmIqVD65Ei6YtbKCtQCAQ\nCKNvESQx+M2VyHLZCuWb/6Bfx35mz5WnysNbf7+FoMwg/Db1N4xwGmFFTQUCgUBGhGyaiUQJ7556\nFyU99qKfQmmRwQeADi06YN+0ffji/i8wcc9E/BH2h5U0FQgEAsuw2OifOnUKAwYMQN++ffHtt99W\neN3NzQ1t27bF8OHDMXz4cCxbtsxSkVZFa9DipcMvITAjEN5zLyLCpwtSU60z94tDXsTp6afx1om3\n4JXiZZ1JBQKBwAIsMvoGgwHz5s3DqVOnEB4ejr179yIiIqLCuHHjxiEwMBCBgYH4/PPPLRFpVUq1\npXjs98eg0qnwz8v/oHO7dpgyBdi713oyhnUehp1P7sTU/VORUJBgvYkFAoHADCwy+j4+PujTpw96\n9OiBpk2b4vnnn8fRo0crjKsn2wYVePfUu2jfoj0OPnvw2oarsYlapjC532R8fN/HmPz7ZBSqC607\nuUAgEJiARUY/NTUVXbt2vfbYxcUFqeV8I3Z2dvDw8MDQoUPx6KOPIjw83BKRVuNIxBGcSziHbY9v\nQ5NGTa49P24ckJUl1+SxJvNHzceEHhPwzB/PQGfQWXdygUAgMJImNQ+pGmOyT0eMGIHk5GS0bNkS\nJ0+exFNPPYWoqKhKxy5ZsuTa3+PHj8f48eMtUa9K0orTMPfvufjzuT/RpnmbG15r3Bh44QV5tf/N\nN9aVu3biWjyx9wnMOzEPmx/bLLJ3BQKBSbi5ucHNwubeFoVsenl5YcmSJTh16hQAYMWKFWjUqBE+\n+uijKo/p2bMn/P390aHDjVmrtRWyKVHCxD0TMabrGCwev7jSMYGBcmZuXJxcftmaFGuKMeZnOelr\n4b0Laz5ApQJiY4GoKPnvkSOBPn2sr5hAILjpMMduWrTSv+uuuxAdHY2EhAR06dIF+/fvx95yu6CZ\nmZno1KkT7Ozs4OPjA5IVDH5t8oPXDyjRluCz+z+rcsywYUCzZoCfH3D33daV37p5a/z14l+4Z8c9\nGOgwEI/2ffS/F0k5LfjECdnIR0UBGRlAr15Av35AkybAJ5/InV9GjwbuuUf+PXIk0Lq1dRUVCAS3\nJBYZ/SZNmmDjxo145JFHYDAY8Nprr2HgwIHYsmULAGDOnDk4ePAgNm3ahCZNmqBly5bYt2+fVRQ3\nh+DMYCxXLIf36943+PHLY2cHPPsscOCA9Y0+AHRr2w2/Tf0NLx9+GeFvh6NNs9bA8ePAV18BGg0w\naxYwebJs6Lt3l4399aSmAl5egKcnsHgxEBEBfPopMH8+0LSp9RUWCAS3DA0mI1elU+HubXfjwzEf\nYsbQGTWODw4GHn8cSEiwnSfljT9fw92+qZh9IlNe5X/5JfDUU0AjE/fXL18GFiyQO8GsXw88JOr+\nCAQNAVGGoRoWnFyAjNIM7Ht6n1EbqCQwcCCwaxcwapQNFDp9GvqF7yE8PwpNly7DwFc/tOzqQgLH\njgHvvQcMHw6sWSPfJQgEglsWUYahCs7GncWRyCPYPNn4iJnrXTxWRZJkN86rr6LJ8pWIPLUH0zS7\noZUsDOO0swOefBIICwOGDgVGjJDDjyTJOnoLBIJbglt+pW+QDBi+ZTiWjl+KKQOnmHRsaCjw6KOy\ni8dUj0ulFBYCM2YAOTnAwYOAkxNI4ol9T2Bkl5H4YtwXVhByhYQE4OWXgd69gR07Ku4LCASCmx7h\n3qmE3UG7scV/CxSzFCbHxZPAHXfINvOeeyxUJCJC9tc/+CCwdq0cHnSFpMIkjNgyAopXFRhgP8BC\nQddRVgZMmQLcfjvw++9A84o9ATK1WrgXFMC9sBCeRUXQSBJaNGqE2xo1QovGjdGiUSO0aNQII1q3\nxtP29ujRQpSKFgjqC8Lol0OtV6P/xv74bepvuK/bfWbNsWSJvEBfu9YCRQ4fBubMAb77To7MqYT1\n3utxMPwg3F5xQyM7K3rdNBrgxReBkhLg8GFoW7TAoexs/JufD/fCQmTpdLi3TRuMbdsWY9q2RevG\njaGSJKgkCeorv0sNBrgXFuJoTg66NW+Opx0c8LSDA/q1bGk9PQUCgckIo1+ONZ5rcCHxAo4+X7Ee\nkLGEhQETJ8qBMSa7eEjg66/lW4WDB6uN/zRIBoz5eQxeG/4a3rjzDbP1rRS9HqrZs7G9QwesmjIF\n/W+/HU927Iix7dphcKtWaGzkHZBeknCxsBCHsrNxJCcHHZs2xTxnZ7zh5IRGIllMIKh1hNG/jgJ1\nAfpt6Ae3V9wwyGGQRXMNHgxs3Qrce6+JBy5dKhv7f/8FOnWqcXhwZjAe2P0AgucGw6m1k3nKlqNY\nr8emtDSsTUnBqPh4fPbHH7h72zbAwcGieSUSysJCfBIXBz2Jzf36YZhIEBMIahVh9K/jk7OfILss\nG9uf2G7xXF99BeTlAevWmXDQt98Cv/wCXLgAODoafdgnZz9BanEqdk/Zbbqi16EyGLA6ORnrU1Px\nYPv2+LRbNwxp1Qr47DPgzz8Bd3egY0eLZACy8d+ZkYFP4uLwkqMjlvbogdZVbBprUjUoDiyGocgA\nfZEehmKD/HexHjAALQe2xO1Db0erIa3QpI3YeBYIakIY/SukFKVg6OahCJ4bDOc2zhbPFxEh778m\nJxvp4vnhB2DDBtngO5smv1hTjL4b+uL09NNwdXQ1S1+/oiLMiIzEoJYt8U2vXuhf3ve+cCEQEiKX\nfGjc2CwZ5cnRavFhXBzO5OdjXZ8+mGpvD0OxAQUXCpB/Jh/5Z/OhzdSi9d2t0bR9UzRu0xiNWzdG\nkzZN0LiNrENZeBlKgkpQGlaKZp2aoZVrK7Qe0RqOLzuiRS+xgSwQlEcY/Su8fux1OLR0wIoHV1hl\nPgBwdQV++gm4r6b94M2b5VX+hQtAt25myfrB6wecjT+L4y8cN+k4nSRhWWIiNqel4Yc+ffB8VXcY\nej3wyCPyHsPKlWbpWBUXUnOxf10kxp4lnKMltBndBu0fbI8OD3XA7cNuh11jIxLjDIQqVoWS4BIU\nKgqRuScTbe9tC+d3nNH+wfaiOqlAcAVh9AGEZ4dj/M7xiHonCu1ua2cFzWSWLZPr7K9fX82gX36R\nSym4ucnx8Wai0WvQf2N/7Jm6x+ioo7DSUsyIiIBjs2bY3r8/ulQSnnkDOTnAXXfJEUXPPmu2rtd0\nztAgdWMq0reko/V9bbBnoh6+rsThu4agvYX1gAxlBmT+nonUDamQNBKc5zmj88zOaNK6chcQSej1\nhdBq06/7yQDQGM2bO6FZs/9+mjS53SLdBIK6RBh9AE/uexLjuo/D+/e8bwWt/uPyZeB//5NdPJV6\nRPbuld0m588D/ftbLG/XpV3YFrAN7rPcq13ZSiTWJCfj2+RkLO/ZE687ORm/Eg4IkFf8584BQ4aY\npWdpWCmS1yQj53AOOr3QCS7vuaBl35aQSCyKjcWpvDycdHVFt9tuM2v+6yGJQkUhUjekIv/ffPRY\n0gPObztDYhkKCi4gP/8M8vPPQqWKgZ1d02uGXTb0nUEaoNWmQ6ORLwJabToAO9x++xB07Pg4OnZ8\nAq1a3SHuJAQ3DQ3e6CuSFHj58Mu4PO8ymjepYaVrBsOGySv9++8v94KbG/Dcc3KUzuDBVpFlkAxw\n3eyK7x78DpP7Ta50TIlej+mRkcjSarFn4ED0NCdx6tdf5SgjX1+gfXujD1MnqRG7MBYF7gVwftsZ\nXd7sgmb2zSqMW5OcjLUpKTgxZAiG3G69VXVOmBei9+yBvp832CsSrdvciQ4dHkb79g+hVatBaNy4\nVY1zkITBUIziYl/k5BxDbu4xAEDHjk+gY8fH0a7d/WjUqOI5CQT1hQZv9B/Z8wieu+M5vDr8VStp\ndSPLlwNpacDGjdc9GRsLjBkD7Nkj7/ZakaORR/HF+S9wae6lCglbSWo1nggJwZ2tW2NTv35oZkmd\niAULgOhoubxzDRu7klZC8ppkJK9Ohss7Luj6YVc0blH9MfsyM7EgJgb7Bw3CeBMuLBVkSxpkZR1A\nauqP0GrTYd/xSRjcRyB7cRf0/HAQnOc5w66R+at0kigtDUVu7nHk5ByDRpOEbt0+QZcus9GokfUX\nEQKBpZhlN1lPsFSVS+mX2OX7LtToNVbSqCJRUaSjI6nXX3mioIAcOJD86SebyJMkiaO3j+aeoD03\nPO9ZUMAuSiW/T0qiJEmWC9JqyfvvJz/7rNphuadz6dXfi8GPBbMstswkEf/m5dFBoeAfmZkmq6dS\nJTI29hMqFJ146dLDzM4+SknSX3u9NKqU/mP8GTA2gKXRpSbPXxVFRf4MCppMD4+uTE3dQoNBa7W5\nBQJrYI7dvGWM/vTD07nSfaWVtKmaYcPI8+dJ6nTkxInk22/bVJ5bvBt7rut57WL2W0YGHRQKHs/O\ntq6gzEyya1fy5MkKL6mSVQx9JpSePT2Zfcx8uZeKi+moUPB0bq5R44uLgxgSMpXu7h0YFbWApaWX\nqxwr6SUmrU2ie0d3ZvyeYbaOlVFQ4MlLlx6kp2dPpqX9QoNBZ9X5BQJzMcdu3hLunatx+bHzY60a\nsVMZy5fLjat+bPaeXIbz5EmbV7Cc9NskTOozGZkOj2JvVhaODR6MwVb0j1/jzBngtdfkGP62bQEA\nmXszEbMgBl3e7IJuH3er0ZVTE+4FBXg6LAxnhg7F0CrOQaVKQELCl8jL+wfdun0CJ6fXjY6yKQkp\nQcjkELgscIHL+y5W3ZQtKLiI+PjPodPlYeDAPWjdepjV5hYIzKHB+vQXnV4EAw1Y88gaK2tVkeho\nYPOd27C6y/ew8/Q0afPTXHzSAjDO8wSG9ZiIY0Nc4dDMhpuLs2cDAPSrfkLU21Eo9ivGoN8HofUI\n65VYOJCVhYWxsfAYPhxdr4vq0WpzkJT0DTIydsPZeR66dl2IJk3amDy/OlmN4EnBaP9ge/RZ08ci\nP395SCIz8zfExr6Hbt0+gYvLu7CzZoE8gcAEGqTRL1QXotf6XgiYHYDu7WqhU5SbG3Ifeg6xOxUY\n+VJfm4tTGQx4JiwMgRmBeL15KpaO+9S2AgsLUdDvaUTafYYOU53Re3VvNG5pnazd6/k+ORk7MzKg\nGD4ct9vpkJKyBsnJa9Gp03Po3v0LNG/e2aL5dQU6hD4ZimaOzTBg9wA0vs2656BSxSEi4iU0btwG\nAwbsRPPm1qmVJBCYQoPsnLU9YDse6f1I7Rj8hATg+edxasZe7PKwvcEv1OvxSHAw2jVpgtMjRuMn\nn7Uo1hTbTJ6kkxC/Og/hus/QR/oB/b51sonBB4D3XVwwvl07fBC4Hb6+Q1BcHIARI7zQr9+PFht8\nAGjarilc/5HLWAQ/EgxdvmmdyTQaOTArKwtQqyu+3qJFLwwb5o42bUbD338EcnL+slhngaA2uKlX\n+jqDDr3W98LR549ihNMIG2l2BZVKrsEwYwaiH12AsWNl376VStdUIEurxcTgYNzbpg3W9+2LRnZ2\neP7g8xjhNAIfjvnQ6vLUyWqEPxuOJu2aoP8v/dH80zeB226Ta0/YAI0mAzGx7yMm5yK823yOb4bO\nsUlSFCUidmEs8s7kwfWUK25zqTpJTK+Xc+v27ZNr0rVuDZSWyv0U7OyANm3kn+7d5fYITz8tb+cU\nFCgQEfEyOnZ8DH36rEWjRpZlIAsExtLgQjZ/DfqVE3ZNsIE25ZAkctYs8vnn5b9JDh1KurnZRlyi\nSsV+Xl78Ii7uhpDMoIwgdl7dmWVa08IlayL3TC6VnZVM/C7xP3n5+aSLC/nvv1aVJUkGpqRsokJh\nz5iYD1mkKeRof39+FhtrVTnlSViRQO8B3tRk3xjSazCQFy+Sb71FdupE3n03+f33ZFLSjcerVHKA\nU1QUefAgOXasHOz07bdkXh6p1eYzKOhRBgVNol5fYtNzEQiuYo7dvGmNviRJdN3kyhNRJ2yk0XVs\n3UrecQdZXHztqWXLbBOtGVlaym4eHlxb3upc4fHfH+cG7w1WkSUZJCYsS6DSScm883kVB/z1F9mz\n5w3nbQklJWH097+H/v73sLg4+NrzWRoNu3t48Ki1w1DLEftJLP3u9qOuSA65TE6WjfegQeQ335Ax\nMabN5+dHvvwy2a6dfNGIjNQyImIW/fzupkaTZYMzEAhuxByjf9O6d87EnsH7p99H8Nxg29ZK8fUF\nJk8GFAqgX79rT0dFyeUYrOniCS0pwcPBwfimZ0/Mcqp8Y9A7xRvP/PEMYubHoFlj86N4dPk6RM6I\nhC5fhzsO3IHmXarIOJ05U/ZpbNhgtizSgOTk1UhKWoWePb9Gly5zKkS8eBYW4qnQUPjceSe6W6FO\nT+V6EFFzoqCKUyH5LVe88VYjLFgAfPSRZY3v09KATZvkAqtffEE89tjnyM4+CFfXU2jRoqdFOhsk\nA3zTfHEy+iROxZ5CTlkOOrboiI4tO8K+pT06tpB/uzq64tG+j6JJI9GHoCHRoKJ3HtnzCF4Y/AJe\nGfaK7ZTKzpYrUa5bJzcYL8ewYXLp/HHjLBcVWFyMScHBWNunD16ooenKg7sfxItDXjS73ERxYDHC\npoXB/gl79PquFxo1rcbi5eXJxdj27zeirnRFysouIzLyFTRq1AL9+/+MFi16VDl2VVISDufk4OKw\nYWhqiRWuBnUZcXhoGFJS7XDvqUG4737rLRji4mQ//6BBwNdfb0BGxkoMGfK3yfH8OWU5+CvqL5yK\nOYUzcWfg3NoZE/tMxKQ+k9C1bVfkluUipywHuSr5d05ZDi4kXkByYTLm3jUXr494HZ1a1dypTXDz\n02B8+ldLLqh1atsppNeTDzxAfvxxlUOs5eLxLixkJ4WCh7KMcwmcizvHvuv7Um/Q1zy4HOm/plNh\nr2DmPhPKIezfT7q6ylnIRiJJeiYlraG7e0empGykJBlqPMYgSXw0KIiLTPWzGEl0NHnnneTTjxvo\ne38gI2dHWqeMxXWUlZEzZ5KDB5NBQQeoUDgwL8+4fRGDZOAm3020/86eT+9/mtv9tzOlMMVo2QFp\nAXzt6Gtst7IdXz78Mr2Svax7fqWlZHi4nLW9eTP5ySeyf+uDD8h9++Q32Mrvp6B6zDHhN6XRn3lk\nJle4r7ChNpQ/0A88UK2hu3yZ7Nz5ulo8ZqAoKDC5rIIkSbxn+z3cG7LX6GMMOgOj342mZ29PFoeY\n6KOXJPJ//yM3GLeXUFYWw4CA+xgQMJZlZaYZ8GyNhl09PPhXTo5pOtbAn3+S9vbyKUgSqSvS0e8u\nP8Z+av0NZEmSbaKDA3n8+HkqFA7MzT1V7TFhWWEcs2MM79l+D0MzQy2Sn1uWy9XK1ez1Qy+O/Xks\n4/LiLJgsl1yxguzRg2zenOzbl3zwQfL118mvvyZ/+UVe/UyZIu9st21LTphALlpE+vhYdB6CmmkQ\nRj+nNIftVrZjTql1jcINHDlCdutGGrHytiSK59yVImT/GFmL5nr+uvwXh/w0hAYjVtCaLA0D/xfI\nS49cojbPzKJhoaGy1azmPZEkiampW6hQ2DMpaY1Rq/vKcM/PZyeFgkkqlXm6luP0aTkyx9f3xuc1\n2Rp69fdi8vpkq8gpj7f31QgfBRUKe+bnX6wwRqVT8ctzX9L+O3v+5POTUf9PYzFIBn7v8T3tv7Pn\nvpB9ph0cFSXfxrZrR86YQfr7y6FONZGZSZ44QS5ZIkd/TZ5c8Y03k0Kdjmdyc/l1fDwfDQpidw8P\nDvbx4fjAQD4dEsI5kZH8LDaW65OTGVtm3Qi3+kqDMPqrlas5/fB02ykSGSkv0YxcpZjr4vknN5cO\nCgXP51USNWMEkiRx2OZhPBp5tNpxRf5F9OjuwdhPYinpLbz1fvddeYVXCWp1OoOCJtPXdwRLSsIs\nk0NyeUICx/j7U2uMoakGX1/533mxor0lSZbFl1HhqGDev+b9H2oiK4u8917yq69OU6FwYFGR37XX\n3BPd2X9Df07ZN8UkN46p+KX6se/6vnz1z1dZoqkhnNTdnXzySfkC/+mnZGqq+YLVanLjRtLZmXzs\nMTncyUT8ioo4OzKSg3182OrCBd4XEMAPYmJ4KCuL0aWlvFRczH/z8rg/M5M/paTwq/h4vh4ZSQeF\ngmP8/bk5NZV5WutVR9WX6Zl3No/5F/KtNqcl3PJG3yAZ2Gd9H3okedhGiaIiOX5v61ajDzHHxfNn\ndjY7KRRUFhSYoeR/HAg9wJHbRlbpt83YkyH77/8wvZxxpRQUkE5OFS6IWVkHqVA4Mi7ucxoM1ilt\nbZAkPnLpEj+2IH7/6v/maPXXReb9m0eFo4Jl8bZZHRYUkMOHk+vWHaFC4ciSkjAeCD3ATqs68XD4\nYZvILE+RGyPBAAAgAElEQVSxppgzj8xk/w39GZgeWHGAWk3Omyff4W7aJPvvrYVKJfvVnJ3JJ54g\nw2peFAQVF/PJ4GB2USr5bWIifQsLqTFhAaA1GHgsO5vPhIayzcWLnBoSwiNZWdSbuOdg0BlY4FnA\nhGUJDJwQyIu3X6T/aH+m70w3aR5bccsb/TOxZ+i6ydXqm28kZUfstGnka6+ZfKirK3nhgnFjf8/I\nYGelkv5FRSbLKY/eoGf/Df15JvbMDc8btAZGLYgyz39fE7/8Qo4cSRoM1OkKGB4+g15efVhQYP0L\ncZZGwy5KJd3yTV9VpabKbujt240bn7wumT5DfagvtWCDphqyssgBA8gdO37lGbf2dF1vz0vpl2wi\nqzr2BO2h/Xf23Oi98b8no6PJESNkv7wZ77XRqFTkunXyXcTOnZUOCSsp4TOhoeysVHJtUhLLLNkw\nu0K+Vsttqakc6efHu/38GGDEd0+VoGLEqxG82PYifVx9GP1uNLOPZ1NXWL/Kat/yRn/q/qnc5LvJ\nNgqsWkXedZf8wTSRr7+WF0k1sT0tjV2USoZYKdmJJHcG7uT4neOvPVanqxlwfwCDHg0y339fHQYD\nOXo0837/gB4e3RgZOcemGajHs7PZ09OTxSZEDuXnk0OGkMuXGy9HkiSGzwhn2PNhtllUUE4G6/DI\nJj6/rR0vKlyoVtvOpVMdMbkxHLhxIBefX0xp3z7ZCK9fX3uRN6GhZP/+sqvwyvctWaXii2Fh7KRQ\n8LvERJZYwdiXxyBJ3JGWxk4KBd+Ljq70M6VOVzPqnSi6d3Bn3Bdx1GTYrimTNbiljX5KYQrbr2zP\nIrXlK+QKnDsnt8RKSDDr8MjIml08PyQns5uHB6OsedtMUqvXsuuarvRO8WaBRwE9XDwYtziOksE2\nX2C9vpRRimfpcbARcxMP2kRGeV6JiOCbl6tuoHI9ZWVylu2CBabbMH2Znr53+jLxu0QztKyZ7z2+\np8vqnuzUP5ZHj35Lb+8B1Ghsm4VcFZk5idw7tgNznNpRstJGq0kUFZHPPksOH84zYWHsrFTyi7g4\nFplwcTeXLI2GM8PD2c3Dg39eiZrT5mkZ+0ks3Tu4M/q9aGoy67exv8otbfSXnF/CucfnWl9wUpJs\nsc+cqXlsNbi6Vh3Fszwhgb09PZlgpWiU8qz1WMvFry+mwkFhUWermigo8KSXV1+Ghb1E7dszZcta\nC+Rrtezq4cEzNUQ5SRL5zDPkiy8aF2hSGaokFZVOSuaeMj2iqmq9JC51W8p+G/oxqSCJISFyNNGp\nUx8yIOA+Ggw2zDepjNRUctgwqqc8zjFrBnPR6UU2u7upDoPBwGV799Lp0CGe++uvWpd/Li+P/T08\nuXSRDy/auzPy9UiqkmzzHbUVt6zR1xl0dP7emUEZQdYVqlbL/umVlrdZXL6cnFvumiRJEj+JjeUg\nb2+mqW3zxdaX6Rk8M5i7HHcx3CfcJjIMBvWVHrWOzMz8Q34yO1sOiwkOrv5gK3EqN5fdPDxYUM1K\ncOtWuZ2lpW91/oV8KjopWBZjnY3dj898zME/DWZG8X9tHH18SAcHA93cpjI8fHrtGd20NNm1smwZ\nKUnMLcvliC0j+O7Jd2vV8OdptXw8OJj3+vszxcNDjm394otaTe7S5mp5aXIQjwxXcuReBQOtsM9W\n29yyRv9IxBHeu+Ne6wqUJHL6dPLpp63yQYuLk12jV6PDtAYDX4mI4Eg/P2ZpbHOrWBJRQp8hPgx7\nPoyL/1pskzuhwkIf+vgMYXDwE9RoyvWe3bBBTtSppS/q7MhIvhYRUelrkZHy+x9upeteysYU+rj6\nUF9mmW/5J5+fOHDjwErzSo4fJ3v0KKWHx51MSFhmkRyjSE+Xd5OX3SgrryyPd2+9m/P+nlcrhj+w\nqIi9PD25ICrqv5DcrCw5xOm992rl81ToU0jPHp6MfjeaBo2BBzIzaa9QXHP33Czcskb/4V8f5u5L\nu60r8Jtv5Jz8EuttQo4eLWeoF+t0nBgUxMlBQTbZkCLJ9N1yOYXULamUJImZJZlst7LdDatJS9Dr\nSxkdvZAKhSMzMn6r3BhotfKq8e+/rSKzJop0Ovbw9OTf5bJ1NRr5X/nTT9aTJUkSQ58N5eU3jdtL\nqAy3eDd2WtWJ0bnRVY5ZvJicODGVSmVXZmbuN1tWjWRkyOHIS5dW+nKBqoCjt4/m3ONzbWr4910x\nrvsyKwkjzsuTgynmzbOZ4ZckickbkqlwUDDr0I2Jhj6FhXS+EiJaF+4uc7gljX50bjTtv7OnSmdF\nX9uBA3K2oCWJJ5Wwbh35zGwN7/Lz42sREdRZmFhUGfoSPSNeiaBXfy8WB90YBTT3+Fx+/u/nFsvI\nyztHT8/eDAt7seYSwcePkwMHmlSXxxLO5eXRWam8IeHmo4/Ixx+3vp3QFejo2cvTrDyH+Px4Oq5y\n5OmY09WOMxjkvKXPP79EhcKBhYVe5qpbNZmZcmnwxYurHVakLuLIbSO55PwS6+tA8rcr4cpB1UWv\nFRTIq6c5c8zfmKkCXZGOoc+G0ne4b5Wuu2SVisN9fTkrIqLKvICTJ+Wcs/rALWn0F51exA/++cB6\ngry9ZT9AQID15ryCMqGUjX735KdRcTZZKZSEltB7kDfDp4dTV1zRyF69QBZrzAsJ1ekKGBk5mx4e\nLszOPm7cQZIk11qx5jK7BuZFRXH6FT/OuXNkly5GVcwwi0KfQiocFCyLM96/X6IpoesmV671XGvU\n+Px8sk8f8sCBY1Qqu1ClMi+KrFKys+X41c8/N+qqmFGcwR7revDXoF+tpwP/M/hGhSsXFpJjxsg5\nM1Yy/OoUNb0HejNydiT1qurvvkv0ej4VEsL7AwKYXc41u3u3HOjnYaP8UFO55Yy+Sqeiw3cO1d4e\nm0RiomwhakrRNAOfwkJ2VirZf2EqDx2y7tySQWLKjylU2CuY9ktatWOnHZjGdZ7rTJtfkpiRsYdK\nZRdevjyXOp2JmcKBgfI3wcIMY2Mp0evZ29OTv8Vn08WFPFV9LTOLSVqTRL+RfjRoajZAkiRx2oFp\nfOXPV0y68AcHy2sRT8819PEZQp2u0BKVZXJz5bCyTz816TYoNDOUDt858EKCkRmHNbAnI4NOpuan\nFBeT48bJdX8sdJGWxZfRs5cnE781PhTXIElcFBPDwT4+1/bkVq+WE5aNSCiuNW45o/9r0K98aPdD\n1hFQVCR/AVavts5817EnI4P2CgWPZmdz61Y5bNBalMWXMXBCIP1G+bEkoub9B58UH3Zb241avXGJ\nWcXFQQwIGEtf3xEsKPA0X9FZs2Q/Sy1xNjePLY558M0PbO9WkiSJwY8FM3phzYuPr9y+4qhto8xy\nR+7dS/bsKTEoaDZDQp4yu2AdSXm/ZcIE8xIWKGe/d1rViZdzzN/TIP8z+KHm7J2VlsqVbl96yewV\nf+nlUnp082DyBtOL6kmSxM/j4jjY24dvfarhoEEV22jWNbec0R+zY4x1apPo9XK1vzfesKrjV2sw\ncEFUFHt7el7zU+bkkG3ayNcYS5AkialbU6mwVzBxZSINOuM/9P/b+b8ab8+12nxGRb1DhcKBKSmb\nKEkWbjinppIdOpDx8ZbNYyQ7dpDtV0RwTrhlRslYtDlaenT1YM5fVVd3PRJxhC5rXJhWVP3dWHW8\n/z45aZKG/v73Mj7+a7Pn4TvvkBMnWrRK3ua/jX3W92F2qXkRLRYZ/KtczbZ7/32TDy0OKaayi5Jp\nO8z/f2g0EgevjWXLvT68XA8Ttm4pox+eFc7OqzsbvWKtEoNBTveeMOG/eEorkKHRcFxAACcFBVWo\n4jd5Mrlnj/lzq5JUvPTIJfre6cuSUNO/MCejT3LIT0MqdS9Ikp5paTuoVHZmZORs62aELl4sN4+3\nMSkpZMeOpCJISyelkopacivlu+dT4aigKrniKj4qJ4r239nTO8XbIhk6HTl+PLliRRqVSmfm5JiR\ntLR1qxxVZYU6Oh+d+Yhjdowx+c5lrzUM/lVyc+VggbXG7ZGQZJFfERWOCmb8bn40W3GxfN2c/JjE\nRZGxHOLjU8HHX9fcUkb/g38+4EdnLHQXGAzk7NnkffdZrbk3SXoVFtLFw4Ofx8VVWrXv119lw28q\nkl5i6uZUKhwUjP86ngatebe0kiRxyE9DeDL65A3PZWUdprf3IPr7j2FhoQ1S70tK5D0TLxtEoFzH\nM8/I+5Ik+UdmJgd6e1Ntg0ipykhYlsCA+wNuKFOtM+g4atso/uD1g1VkpKbKWyQXLyqpUDiwtDTK\n+IMvXpTTfY0sW1ETBsnAaQem8YWDLxi9R+GWn08HhcKqNaaYmChX6dxfc1hrgaJAzk7/0/wFTVkZ\nef/95CuvyBfiq4mWrvXM8N8yRl+j11juT5QkOUX23nst97Vcm1Li1tRUOtSQxFFUJLt4TOmNku+e\nT99hvgwYG1AhFNMcfg369Vohtry8f+nnN5I+Pq7MyfnLtjHIP/8sv+c2knHqFNmrl/ylJOX/yZPB\nwfwyzoLuUCYg6SUGjg9kwjf/RdgsOb+ED//6sFUboBw7RnbvTkZHb6K39x3U6Yz4TCQkyCVFrLyz\nXaYt48htI43qVhdZWspOCkWNJTPM4tIlOQu8mq5FhT6FVNgrLCqjodXKYbTly3nUR8N/yxj9Q+GH\neP8v95s/mSSRb70lx/sWWiEKgmSqWs3Hg4M5xMeHkUYUTZs2zbiy/KpkFcNeCKNHVw9m7M2wmkHW\n6rUct9mRF7xG0tOz95UEq1pYDev1cjuxAwesPnVZGdm7t9yY6XpS1GraW3tlWQ2qJBUVnRQs9C6k\nV7IXO63qxNQi6+Z8kHJznmeflRgR8RpDQ6dV/9koKZHf9zVrrK4HSSYXJrPz6s4VynhfT7ZGw96e\nntxm5fyXGzh7Vr6TCQmp8FLp5VIqOyuZfdT8Fb7BIO8bT55cuTdYkiR+HBvLd6OtFFFoIbeM0Z+0\nZ5L5GbiSJG9ijRxplRBCSZK4Kz2dDgoFv4iLM7qRw6FD8jZCVehVeiYsS6B7R3fGfR5HfYl1Mncl\nSWJu7j+8dOkhnj7fll8eHUaDwQYllqvj7Fl5OW7lekNffilXzaiMTSkpHOXnZ3KTDHPJPJBJj94e\nvGPVHfwj7A+byCgrkxus//yzin5+I5mYWEWNKINBfmNmzbJpCYNzcefouMqRCfkV8whUej3H+Pvz\nIxs1tb+BPXvkWj3J/0XkqFPV9OzhybTt5m/aSpKcDDx2bPU9ZCRJsrijm7W4JYx+UkES269sz1Kt\nGSWIJUkOUbv7bqtsYqWo1ZwcFERXHx+jGi9cT1mZ3F40rdxnUF+mZ/L6ZHq4eDBkSohJST/VYTBo\nmJ6+kz4+Q+jjM5jp6TtZpMqjw3cOjMiuvF6NTZk82arhsZcvy5u3yVVE3hkkiWMDAri+qgE2YPsD\n27nlgS02lRESIp93WFgylUon5ub+U3HQ8uXkPfdY/SJbGauVq3nnljtv2NiVJIkvhIVxWmgoDbVV\nvuDbb+Wks8JCavO19Bniw4TlliW1ffmlXLCvluICrMItYfS/cvuKb/71pukTqNVySOZdd1ls8CVJ\n4s9paXRQKLjYhNV9eWbMkEszkKSuWMfE7xKp7Kxk8JPBLPS1jttJo8liYuJKKpVdeOnSQ8zNPXWD\nG2Cp21K++uerVpFlEuHhcrZRjuUN7CVJruv2/ffVj4ssLWVHd3eblbC+nqORRzng2wH06O1hvXaU\nVfDjj3ItsqysC1QoHFlWFv/fiwqFvOtbSxc7SZL47B/P8tU/X732OfsiLo6j/Pys0uXKBEXIOXOo\nn/QUA+7zZ9T8KItco2vXkv36yRUrbiZueqNvkAzssa4H/VJNbKCckCAb+ylTLLpMS5LEEzk5HOHr\nyzt9fS0utXriBDnuLh0TliVQ4aBg6LOhVtmkNRg0zMo6wuDgJ3nxYluGh89kcXHlrfdySnPYfmV7\nJhfW3gr4Gm++Sc6fb/E0e/fKeXXGlPdZlpDASUFBNt2szijOYOfVneme6M5C70IqOilsWoddkuRe\n5QsXkklJ39PX907q9So5UqBbN7n+US1SrCnmoB8HcYvfFu5KT2cPT09m1MHGpqFMwxD7TQwbsMei\npkG7dsneIjN7KNUpN73RPxN7hsM2DzPtC3vypLyxs2qVRf5Mt/x8jvH350Bvb/6RmWnRbaokScx3\nz2fYjAj+ZXeRPlPCjcqmrWnOoqIARkXNp0LhwICA+5mW9jN1upovTO+deo/vnzI9ucViMjNl30SU\nCSGH5SgokKNAlUrjxmsMBg7x8eHvGdapNloeSZI4+bfJ/PTsp9eeS/gmgQHjbgzjtDbZ2bxSckJi\naOg0Rka+Tj71lFyKuA6IzI5kux9Hs93F89aJxTcRSZIY+UYkL433paF3fzlqzAzOnZPNhyklufX6\nsoplxuuIm97oP3/weW7w3mDcAQYDuWSJbBGM7UpeCT6FhXzo0iX29PTkrvR0izYC1WlqJq5MpFc/\nL3oP8GbiqkS+94qGX31l3nwGg4Z5eWcZHf0uPT1708OjO+PivmRZmWmbZcmFyWy/sj1zy2wQRlcT\nK1bId2BmMn++nFtnCt6FhXRUKGwSVrcjYAeHbx5Ojf6/uSW9xICxAUxYYdul4r//yh/39PQiep90\nZNrc7rXix6+MLI2GDhf+ZccdU5hZUvs+kYQVCfQd4UtdkY6MiJAt98WLJs1x+bJ82L//Gn+MwaBj\ncPCTjI5eaKLGtuGmN/ptV7RlXllezYNzcuRUubFjK+6UGkGhTsdtqakc4+9PZ6WSm1JSzPbbqxJU\nTNmUwqBHg+jeTm65VuBRcO1uxcdHDmQxdnq1Oo3p6bsYGvoM3d3b0c9vJOPjv2ZRUaBFLotZf87i\nV25mXn0sQaWSA87NuDAHB8tfSnO2Bd6NjuYMa3VUuUJqUSrtv7PnpfSKrjRVoooKBwULfayzV1MV\nixaR743zZ/HQdlRcaM+iIn+byqsMncHACYGB/Dg2lp+e/ZQP7HqAekPt+fOzDmXRw8WD6pTrLnj/\n/CPnKBiZr5GTI1c23bbNeLmSJDEycjYvXXqQBkMDjtM/efIk+/fvzz59+nBlFW0H33nnHfbp04eu\nrq4MqKKkMQC+eOjF6oXl58tNIOztyQ8+MKmsgkGSeDYvjy+Hh7PtxYucEhLCo9nZJodeGTQG5p3L\nY8wHMfS+w5sKBwXDp4cz4/eMSssdS5JcyrwymydJehYVBTIl5UeGhb1ET8+edHdvz5CQp5iWtoNq\ndbpJulVHeFY4O63qZF5UlKX89pu852LCe31183aDkTd+5SnW6djdw4P/WDFJaMq+Kfzs38+qfD1z\nfya9+nhV+jmwFursIiY078uzr+9lZuYBenr2oFZbu3dwi2Ji+OClS9RLEvUGPSfsmlDt+2JNivyK\nqLBXsMi/Erfmhg3yl62G3ByNRs62XbTINNnx8Uvo6zvCKJdqbVHrRl+v17N3796Mj4+nVqvl0KFD\nGV5udfX3339z0qRJJEkvLy+OGjWqckUAnos7V7mgrCy5PGyHDnJetJEp5mlqNfdnZnJeVBS7eXhw\nuK8vf0hONrp9oWSQWBpVyozfMxj9fjQD7g/gxdYX6Xe3H+MWx7HQu9AoP+6qVeTcuZnMyzvPlJSN\nvHz5LQYEjOPFi63p5dWfERGzmJa2nSUl4TZNoJqyb4rx7jNrYjDIYbQmFCQ6flzu7GdJuaSTOTns\n4elple5lB8MOcsDGATXWoImYFcGIWTYKkZUk8qWXmDftdXbsKH8NoqPfZ1DQxNpJvCN5IDOTPTw9\nb3CdZZZk0mWNC/+6bNvm5uoUNZXOSmYdrqJ5giTJwQOPPlploTlJImfOlLdDTFnvpaZuoadn73rj\ny79KrRt9Dw8PPvLII9cer1ixgitW3JiqPWfOHO7bt+/a4/79+zOjkk22q9E7N5CUJFfXa99eLqlQ\nza1bkU7HoOJi/pKWxlcjItjHy4vt3d35eHAwVyUmVtmtR5IkanO0LPQpZOb+TCauTGTk7EgGjg/k\nxbYX6dHdgyFPhzBheQJzT+dSm1vRCkmSnhpNFouKApmdfZQpKRsZE/MRw8JeoL//GF68aM/jx9vR\n13cMIyPfYHLyOubmnrZusTMj8Er2Yve13S0vYmcO7u5ypElZzXkJ1uzC+HJ4ON+3MHsytyyXTqud\nqEhU1DhWV6yjV18vZu63gZ/7l1/klWxpKX/8UW4RqVJpGRBwP+PivrS+vHKElZTQXqGgfyVRbcok\nJTut6sS4PNuUw9CX6Ok73JeJK2uoia/VyuWYq6jKuXw5OWKEaV1Ss7KOUKl0Ymlp/cjCvR5zjH4T\nWEBqaiq6du167bGLiwu8vb1rHJOSkgJHR8cK88WuWQMmJ0JKTgaTU2EAoH7gAZT9+SfK2rRGWW4e\nVFk5KDPoka3RIUOlRqZKgyyVFnqdBKcmTdGrcXOMb3Ib5to1hyObgXGlkNRFMJTGIaJAA32BFvoi\nLfSF8m9dvhpopkezbnZo5myHpk52aHqfHVpPk9ChmwF2LTUwGEqgN5Qix1CKzMxi6FLyoNfnQqfL\nhU6XA72+CE2atEHz5i5o3rwrmjfvittu64ZWrSahefOuaNmyP555pjOmTrXDK69Y8o5bxiiXUejV\nvhf2h+3Hy64v167w++4D7roLWLcO+OSTaodu2gT06AFMmmS52LW9e2Owry+e79QJd7dpY9YcC08v\nxLRB0zCm25gaxza5vQkG/jYQIZND0GZUG9zW/TazZFYgJgZYtAg4fx5o2RJvvgmcOAF89VVTLF68\nHwEBd6N16zthb/+EdeSVo1Cvx5TQUKzu3RsjWreu8Pq9Xe/Fp/d9iml/TIPyVSVua2Kl8wZAiYh4\nOQK3D70dXT/sWv3gpk2BP/4ARo8GBg4EXn/92ksHD8qfLS8voFUr42QXFCgQFfUGhgw5iZYt+1hw\nFvUHi4y+nZ2dUePkC1LNxy3z+fKaVkMfa4phg5sC2A7kbEezHKAZgHZXDu1DO8AOsGsEoJXddXPa\nAXZ2UNnZIcHODnYt5Md2do1g16gJ7Bo3vvbTuEkTNG3aBI2a3oZGjZrBzq4Z0Kg5DI2aQbJrBj1u\nR2NNKzRu3ApNm3ZE8+bd0Ljx7WjatAOaNu2Ipk3t0aRJRzRt2h52do2rfQ9eeQVYvx51avQB4OP7\nPsb7/7yPF4e8iEZ2jWpX+Lffyl/GmTOBLl0qHZKXByxbJts2Iz9e1WLfrBm+79MHr1++DL8770TT\nRqad8+nY0zgffx6hb4UafUybu9ug68KuiJgegWHnh8GusYUnotMBL78MfP45MHgwAPm92bEDGD4c\nmDixM4YO/QOhoU+gZUt3tGzZ3zJ55ZBIzIyIwIPt22Nm585Vjps/aj48Ujww/+R8bH18q9Xkx30a\nB12eDoP2DzLO5rRvDxw/DowdC/TpA4wfD39/4M03gdOnq/zoVaC0NAxhYU9j4MDf0KbNXZadhJVw\nc3ODm5ubZZNYcmvh6el5g3tn+fLlFTZz58yZw7179157XJ1751ZGo5H3n2Nj61YPSZJ455Y7rdOc\nxhw+/picPr3Kl+fPl92y1kSSJE4MCuLXJjZ4KdYUs/va7jwVbXrVSskgMXBCIOO/Nk1mpXz5Jfnw\nw5U6of/+Ww6Oys8nU1O30tt7gHVaLV7HysREjvb3NyrCrUhdxP4b+vOXwF+sIjt9Zzo9e3tSk21G\ntMzZs6SjIzMU0XRxoUltTNXqFHp4dGN6upk1wGoJc+ymRZZWp9OxV69ejI+Pp0ajqXEj19PTs9qN\n3Fud+fPl729dcyzyGF03uVq1FLDRFBfLddErybaKiJAvjLZocp6kUtFeoahyb6cy5p+YzxlHZpgt\nU52ipqKTggUeFhRzUSrlMgvVhCa//Tb53HPyJmVk5GyGhEyx2sbu+bw8dlYqmWRCaYvQzNAqQ1tN\n4Wpd/JJw85O/ND9sYtxtA7jqM+NLs+h0BfTxGcKEhJpLSdc1tW70SfLEiRPs168fe/fuzeXLl5Mk\nN2/ezM2bN18b8/bbb7N37950dXWlv3/lccUNwegHBsqrsrou0Hd1tX8w7GDdKLBnj7wLWS7Cwso1\n2iqwIy2Nw319jQrT9UjyYOfVnZlTalntoKzDWfTs6UldgRlhnIWFZM+e5J9/VjusrEwuU7F1K2kw\nqOnvP5oJCd+YqfF/pKrVdFIqedqMsNe9IXvZc11Ps1stlsWXUdlZyZyT5r//kkS+8AJ5su87lB5+\n2Kg6HgaDhoGBE3j58lu27TthJerE6FuLhmD0SbmK39mzda0FefzycQ7+aXDdrPYlSW60cl1mzOnT\ncq18WyaYSpLESUFBXFqDm0ej13DQj4O4L2RfteOM5fJblxkyNcR0IzJjhlxE0Aiu3iUFB5NqdSqV\nyi7MyTlR84FVoDUYeF9AAL+yoOfxh6c/5IRdE6gzmHbB0xXr6DPEh0lrLetC/s03cnpIWZFOdo+9\n80614yXJwLCwF680pa/F4nEWIIz+TcC6deTLL9e1FrIBvHvr3TarBV8j/v6y2yI/nzqdXDf+cC1s\nMyRfcfNUV0xvqdtSPv7741Zb6RnUBvre6cvkdSYUvdu/n+zb16TYwt275dyGkhIyP9/9SqtF88IM\nF0ZHc1JQkEU1qPQGPSfumcgFJxcYfYxkkBj8ZDAjXouw6P0/fFj2Il7r55KfL785V8veVkJMzIf0\n97+Xer11yp3XBsLo3wRkZ5Nt29aPmt1/R/1dd6t9kpwzh1ywgFu2kOPG2bT/xw3sTE+nq49PpRuT\n4Vnh7PhtRyYVWLbKLE9ZbBkVDgoWeBrxj09KktsC+viYLOeVV+QfkkxJ+fFKq0XTPmwHs7LYw9OT\nuZZkxl0hX5XPvuv7cmfgTqPGx34cy4D7A2jQmP+ZDAyU73oqvH3x8VX22U1O3kAvr/7Uai0vBV6b\nCKN/kzBlimk1P2yFJEkcuW0k94fW3GzaJmRn02DvwHEdQ1jFVo9NkCSJj1XSV9cgGThmxxhu9N5o\nExjMEBEAACAASURBVLlZR7Lo0c2D2pxqjKleT44fTy5bZpaMkhJ5Qbtrl3yely+/xUuXHqHBSBfL\n5dJSOigU9LVSm1FSvpA6fOdA7xTvasel706nZ08zI3WukJYm5wDuq8ozFxgoX1DPn7/2VFbWISqV\nXVhWVjt9lq2JMPo3CceOyS7t+sCJqBMc9OOgOlvtH3t4A0M7T6i9Zf4VUtVqdiqXXfqTz0+8Z/s9\nNn0vot+PZtCjQVXXf//mG/m2x4LSEcHB8ko3IkKuCnnp0iNGbUyW6PUc7OPDzTbocXs08ihd1rgw\nrajyKKQCZQEV9goWh5jfb6KkRI4PqLGq7b//yoY/OJh5eeeoUDjUSeE6ayCM/k2CViu7s40sIWRT\nJEniqG2jrLZpaQqJiaRDex21/QeTB2s/kujX9HQO9vGh2mBgcmEy7b+zZ1hWmE1lGrQG+t/jX3k5\nAU9PuaxokuWupa1b5YiesjI5BNHb+w4mJ/9Q5XhJkvhsaChfibDMl14dX7l9xdHbR1Otu3G3vjS6\nlApHBXP+Nt+1oteTjz8uu7aMUn/vXhaO7UTFhY7Myztvtty6Rhj9m4hFi+ROSPWBU9GnOHDjwFot\nj0uSL71EfvEF5U4W3bqRFnYqMxVJkvhkcDAXxcTwib1PcPH5xbUiV5WkosJRwfwL18WOFxTI4Zmm\nZBBVgySRzz8v9yKQJLKsLJ5KpRNzciovivZtYiLv8vOjyoYtDw2SgU/vf5rTD0+/djelzdHSq68X\nUzalmD3v1YbmDzwgJ0EaQ2lpJJWnWzP7ORe5A9lNijD6NxHx8XJTKRNyhWyGJEkcvX00fw/+vdZk\nenvLDUGunf/MmfI3t5bJ1GjY4cJZdv1laoUVqC3JOZFDpbOS6nS1bLVefJGcPduqMgoL5fpsV8tT\nFxR4UqFwqNBa85/cXDqZmIBlLqXaUt6z/R4uOr2IepWeAfcFMGaRaU2ByrN2rXyexrbGVqmS6OHR\njWlpP8uF2caMMaoQYH1EGP2bjKlT5abX9YF/Yv7hgI0DamW1L0nkffeR27df92RuLunkJFfjrEXy\nyvLYccsD7HjxPNNquQtV/JJ4+o3yo377r+TAgWSp9XsdxMbKvUX++Ud+nJm5jx4e3ahWy7712LIy\ndlIoeMFYi2kFcstyeceGO3jowUMMnRZqUX/bI0fkgBxj+9tqNNn09h7ApKQrWYAGg3zL+eCDNnn/\nbY05drOWK24JrmfBAuCHHwBJqmtNgId6PQT7lvbYFbTL5rKOHAGKisoVn+vQAdi4EXjtNUCttrkO\nV1l4eiGede6Hd7r2wEsRETCUKw5oS7p/2R232etx+a0E8PffgZYtrS6jVy/gwAG5XltkJNCp03Nw\ncnoDISGPo0iTjymhofi8e3fc366d1WVXRYcWHfBb/G/IjclFwAcBsGtkXkE6Hx/gjTeAo0eB7t1r\nHq/XFyMk5FHY2z+Frl0Xyk82agTs3Ak4OQGTJwMlJWbpclNhg4uPWdQjVWoNSSKHDydPmJ84aVV8\nUnzotNqJRWrb+dY1Gjnz9syZKgZMmyYXZasF/rr8F3us68EidRH1ksTxgYE1ZutaFY2G+jvvoV/3\nvxm/xLZyd+yQ2wPm5l4N5ZzL3xR38rUwv1ovN5C6NZWevT0ZGh5Kx1WO/DvK9MYJly/LN4bHjhk3\nXq8vZWDg/xgZ+Ubl56vXk6++Krt6rBiuamvMsZv1xtI2RKNPkjt3yhni9YUZR2bw4zO2M7pr1sg1\ndqokI0OOYLFx4H5eWR6dv3e+oVtbqlrNzkolz+cZ0afZGnz0ETl5MtVpanp082DGXtt2ZVq4kJww\nQY4eW5UQz1XujzEg8EHq9bb35V8l52QOFY4Kll6WXSmeyZ50+M6BnsmeRs8RE0N27SpfyIxBpytm\nQMA4hofPqL68gsEgl3gdOZKsrc+AhQijfxOiVsvhm2G2jRQ0mtSiVHb8tiNj86xfAzonR44fr7Ff\n+a5d5NChlvVKrIHph6dz3t8VN45P5ebSWak0uqWm2fz5p2y5MuUOW8VBxVTYK1joZbtVpl4vX3An\nLs2mk1LJxLJihoY+w+Dgx2kw2L6bWt75PCrsFSxQ3pghfCLqBB1XORoVLpuQIBct3LTJOJk6XRED\nAu5jRMSrxtXTkSTy3XflW/Cc+p+dK4z+TcrixXJFgvrCsgvLOHX/VKvP+9ZbchngGpEkcuJEs7NS\na+LPiD/Z+4feLNFUXtfm49hYTrSw7ky1XL4sJwd5ed3wdPaxbCq7KKlKtN3K+1xaIRsfU/D9rfLF\nxWDQMDj4MYaGPmfTImMFHnKZ5Lxzla+gfw36lU6rneifVvUdXnIy2asX+UPV6QY3oNMV0N9/NCMj\n55hWalqS5LuwIUPkO896jDD6Nynp6WS7dvUnXLhMW8bua7vzfPx5q80ZGCh7bYw+x8RE+bbAyrdA\nOaU5dFrtxIsJF6scozUYeK+/P1cYGxJiCsXF5KBB5HWlx68naXUSfVx9qCsyoxRzDUSXlrKzUslt\nodl0dv4vekqvVzEw8AFGRLxikwbrRX5FVDgoaiyTfCj8EB2+c+DpmNMVXktLI/v1I1etMk6mVptH\nP7+7efny2+btWUgSuXSpnD9S7uJMypVY6wPC6N/EzJhBlms6VqfsD93PoZuGWiWE82qI5pYtJh74\n00/k6NFG1UH/f3t3HhdVuf8B/DPIIG6AEQzoqKBAiKJompWSoGLXvLilplaSlllW1917u+Yv7ea+\nW7Zc06TcKishRXILFRBRWUwEAQUEgUHEYZuRWc7398eTlleWmWHgAPO8X695IcM5c76i853nPMv3\nMdTUg1NpfuT8Oo+7qVZT55gYOmjOHV0EgWjyZKIZM2pcNioIAl176xolPJdA2nLz/b2LqqrIIy7u\nQYmF9HTWu3S/m0Snq6BLlwb/Ua7BfIm//PdyipZFU9HPhv0ez2SfIef1zrQnec+D5xQKNqPV0Bs/\njaaYLlzoTxkZ8+o/SB0Wxu7Ktm0jEgRSa9X0Rtgb9I+If9Tvdc2EJ/1m7NIl9iZswG5sowiCQP67\n/OnLi8Zm6kft2UPUv78J5WT0ejbKvWRJvWMgIjqYcpC8PvGiSo1h87ETysrIKTqaYsxVEnXjRlYc\npo6FQIJeoNSZqWZL/JU6HQ26eJGW/s9enZmZrH982zb2PesOeZZSUqaYZXC3Mq2SYlxjSHFAYdR5\nVxRXqMumLrQhZgMVFrJelmXLDDtXrb5J8fF9KDNzsflmJWVmEvn5UfmEYBqy1Y8mfT+pQWe4GYMn\n/WbO37/aqq+iuZR/iWTrZaRUm570ysrY4pnYWBNf4PZtdotdz2L7RRVF5LLBhWJvGhfI0eJikkVH\n07X6Ltz57Tc2Ym9gl5G5Er9Wr6fgy5dp+tWr1SbBrCxW/WHjRva9TqeiK1cmUULCkHqVGVZdV1Fs\nl1gq2F1g0vk3lTep+0Yf6jBxPv3fcr1B9XSUyhiKiXGlnJx1Zp+G+uvvh2jPU7ZU3M2ZhCtXzPra\n9cGTfjN38GDTqb5538xDM2nRr4tMPn/JEtZ1VS/x8ewW28QKdYIg0Nj9Y2nxscUmnf9Vfj51P3eO\nFKbO6MnNZctijz3aV12b+iZ+QRBodloaBSUl1bqp+c2bbA7/6tX3z9NTZuYSiovzNGkTlrJLZRTT\nOYZufWF6tc6ffiJ6rHMJea/1pxe/e7HObSvz87+m6GgnKi42fs5/bfSCnpb/tpw6bexEp7NPE+3a\nxcaamkjrjCf9Zk6rZY1aE/bOaDAF5QXkuNaRrhUbn3DT0lh9oQLTGnsP++ILtr2WETtJ3bchZgM9\nteOpeg2+Lbtxg566eJEqje2jqqxk875Xm7bJtqmJXxAEWpiRQX4XLlCpAWMieXlsoHT58j+HG/Ly\nPqfoaBkplY9uYl+T27/cpminaCr6ybSxEEFgffdyOdGFC0RqrZrmHp1LsvUy2nd53yMteEHQUUbG\nQjp3rgdVVJh/0H/UnlE0ZNeQh0tCJyUZviqsgfGk3wJs3Mhq8jQlW85toae/etqovU7vz7o020bn\ngsCKsk2bZlTt/eicaHJe70zZd+s3E0cQBHr16lUae/ky6Qy9flUV0ahR7FanHt0NxiZ+nSDQrLQ0\nevrSJSoxYpCooICNvQQHP1g+QMXFRyg6+nFSKL6v8/zcT3IpxjWGSs+bttZApWKVQQcO/Ms2h3+I\ny42j3p/1ptF7R1OOkpWl1mqVlJz8N0pMHGbWHa/UWjVtiNlATuucaEHkAtLomshAWzV40m8BVCrW\nB37O8AWKDU4v6CnomyCjSg+HhbEdnMy6xqmyki3aul82sg5FFUUk3ySnw9eqLydsrCq9noYnJtJb\n167VPYdfp2MZbMwYs8w+EvQCpc1Ko/i+8VSZUfP4gkavp5euXKFhiYlUbsJ1q6rYFHVXV6LDf/za\nysoSKDa2C1279g5ptY8OYAo6gTLmZdB57/OkumFatcobN9gm5tOm1TzOXaWroo+iPiLHtY70VexC\niot7gtLT3zXbwjKdXke7E3dT181dacz+MXRF0XT67mvCk34L8dVXbFC3kUui1OpW2S2SrZdRzM26\nb/XVaraIxsgubMNkZrL+/TpGhnV6HQV9E2T2khJKrZaGJCTQS1eu1Fx7XhDYcv6AAPbLMBNBECjv\nszzWffLjo90nKp2ORicnU/Dly/Wui3/6NJvZ89ZbrEdNoymh1NQZFBvblYqLjz44Tleho9/H/U6J\nAYmkKTE++ZaVsVJLjo7srrCu//NarZLikqZS+HEpzdrXnXYl7KrXRAMi9nv95dov1Puz3jR452CK\nzomu1+s1Jp70Wwitls1LPmyeBqrZ/Jz6M7lvcafSe7Xfvn/wQQN3UYWHs07f3NwaD1kRtYKGfj3U\nqC4pQ6l1Opp05Qo9l5BQ/ebhS5eyqZkNVLirNL6UYrvFUsaCDNJr2ABtqVZLQxMSaFpKCmlqGbQ1\nhlJJ9OqrrK//wgX23J07x+jcOTe6enU6lVzIovg+8XT11atGb2Su07HaOa6urNeurh0aBUEgheI7\nionpRGlpb9K9qmI6mHKQxh8YT3ar7WjCdxPoYMpBUmsN+5Atu1dGEekRtOjXRdTn8z7ks92HwtLC\nGr34XH2Zkjclf5woOolEgiYSSpMQHg4sXQokJQGtWokdzZ/e/OVNaPQa7B63u9qfX7oEvPACi9vV\ntQED2bQJ2L4dOHXqkbq6J26cQMihEFycdRGuHRomCIEIi69fx9GSEhzt0wfdbG3ZDzZvBr78Ejh7\nFnByapBrA4D2jhap01OhU+rguscTY0vS8WSHDtju6QkriWmlimvy3XfAe+8BQ4awyteBz5bi6qG5\nqHA4jE661fB48XVYWRlepf3MGWDePFZJevNmYODA2o9Xq7OQkTEHVVV58PL6Avb2gx/6ufKeEj+l\n/oR9v+9DQkECRnuNRhe7LmgnbYd2Nu3Q3qY92knbobV1ayQWJOJU9ikkFyZjYOeBGOY2DIHugXhG\n/gxaWTWhN5qBTMmbPOk3UUSAvz+rFx4SInY0f6rUVKLfl/3w8bCPMbnX5Id+VlUFPPkk8O9/A9Om\nNUIwW7cCW7awxO/uDgC4VXYLA3YMwL4J+xDoHtjgIWzLy8O6mzcR7uuL/j/+CHz4IUv4Xbs2+LVJ\nIJz4MA0Vnytwc5UT3nujp1HJ1xhlZcCBA8DpTSUYk5kOwdsOvjtuQ9VqDqysWqNTp9lwdp4Ga+sO\nj5yr1QJxccDx4+yRnw+sWwdMngzU9PlERCgrO4/Cwp24fftndO26GHL5AlhZSWuNM788H4fTD6NY\nVYxKTSUqNBWo1LKvKq0Kvs6+GOY+DM92eRZtpG3M8asRFU/6LUxMDDB1KpCeDtxvSDYFF25dwOh9\no3HpzUvoYt/lwfP//jfbqOPHH2t+M5vdZ58Ba9cCJ0+ioqsLRnwzAn/3+js+eO6DRgoA+KmoCG8l\nJyN00yaM2rwZ8PZu8GtW6vVYfP06jty5g9235Wi/tBBWtlbo9mE3OI52hMTM/wDaO1pcX3Qdd0/d\nRet/euHbDEfs2QP4+goYMeI4PD2/RMeOUaisnAxBmI22bfshPR04doy17D08gKAg9hgyBGjduvrr\naDRFUCi+RUHBLhBp4eIyEy4uIWjduiFvG5svnvRboHHj2Jtk0SKxI3nYqrOrcPzGcZx49QRaWbVC\nfDwwZgyQnAzIZI0czFdfQVixHDPekcPGxxf/Df6v2ZNeje7dA2bPRmxpKSYuXIi/OTlhlbs7XGrK\namZwvqwMr6am4mk7O2zz8ICDVAoSCLd/uo2cj3IgsZHA7f/c4Bhcv+RPRCi/WI7C3YUoOlAE2csy\nuK90h3UHawDszi4iAsjKAkpLAY0mHzLZTvTosQNlZa64c+dv6NatB/r184CLiwekUqeH4tHpKnDv\nXtaDh1J5BnfvnsTjj4+Dq+vrsLcf0nj/js0UT/otUGoq8NxzrLXfsaPY0fxJL+gx7JthGNJlCJYN\nXon+/YHly9kte2PT6DX49J2BeO2HDNifPo9WvX0b58L5+cD48YCbG7BrF0pbt8bHOTn4uqAAS7p2\nxVy5HK3N2N2iFQSszMnB5/n5+NTTE5OcnR85hgRC8aFiZH+UDYlEAvkCOewH28PW3dbgBFpVWAXF\nHgUKdxdCUAtwec0FLtNdYNvNsNtNIj1KSn5FWdl5qNWZfzyug6gKbdp4QCKxhlqdBUFQwdbWDba2\n7rC1dUf79n5wdp4Ea2t7o34vlown/RZq1izA0RFYs0bsSB6mqFAgMDQQjvnT4JrxAb7/vvFj0Ak6\nTP1xKrR6LQ5qx8N6yb+A/fuBgICGvXBcHDBxIjBnDvD++w/1Z2WoVFh4/TquVlZik4cHgh3r1+Iu\nrKrCrsJC7CgogHfbttj5xBPoVMedBAmE4vBiFO4uRPmFcghVAjoM6IAOAzrAbqAd2nq3hfauFlqF\nFhqF5sFDnalG+flyPD7+cbi85gJ7f3uztba12rt/JH8d2rRxh1TqzFvy9cSTfgt16xbQpw/rOpHL\nxY7mYYejCjHuUADeH/Ua/vP8vxr12gIJmBE2A4UVhQifEo7W1q2Bo0eB2bOBESOA9evZp6W5hYYC\nixcDO3cCwcE1HvZrSQnmZ2aik40Npjg7I7BjR3S3NazFLRDh5N27+DI/HyeVSkx0csJsV1cMsLMz\nKeSq/CqUXyxH+YVylF0ogzpDDamjFDYyG0hl7KuNzAat5a3RcWRHWLe3Nuk6XOPiSb8Fe/99IDcX\n2LNH7Ej+pFYDfn7AohX5WH87ALP6z8LiwYsb5dpEhHci3sGVoiuIfCUSbaVt//xheTmwbBmbbrJu\nHfDqq+YZWT5zBvjPf4CbN4GffwZ8fOo8RSsI2F9UhF9LSvCbUolWEgkCHRwQ4OAAf3t7WEskuK3V\nsodGg2KtFoUaDQ4VF6N9q1aY3akTXpbJYGfNkzD3KJ70W7CKCjYdctky4JVXxI6GTSl9+202gLd/\nP5sqOXT3ULwz8B3Mf2Z+g15bL+ix6NgiROdG4+T0k7BrXUPr9+JF1uq3twe++ALw8jL+YkRAVBSw\nYgX71F26lH2ISGufOlj9SxEy1WpEKZX4TalEdGkprAA42djgcakUTn95BHbsiKc6dODdH1yteNJv\n4ZKTWa/F2bONMiuwVlu2sN6NmBjgfo9Dbmkuhu4eivlPz8d7g95rkOtmK7Pxyk+vwKaVDX6Y9AMc\n29bRfaPTAZ9+Cnz8MfD886yvPyCAzSGsLaEKAnDyJPDRR4BCAXzwAVt8wFvcXBPCk74F+PJLNjU9\nLg5oI9Lakl9+YQ3oc+ceWQyLHGUOAkID8Hq/17Fk8BLYtLIx23X3Xt6Leb/Owz8H/xMLnlkAK4kR\nM2MKCoAjR4DTp1nLXa8Hhg5lHwDOzmze4Y0b7JGVBWRnAz16sMUHL73UtJZFc9wfeNK3AERswZaD\nA+uxaGxJScDIkSzxDxpU/TE5yhy8deQtZN3NwubnN2OU56h6XVN5T4k5R+YgqTAJeyfsRT/XfvV6\nPRCxxB4VxR5KJdC9O3u4u7Ovbm5Au3b1uw7HNTCe9C1EWRnr3//4Y9YIbSz5+cDTTwMbNwKTJtV+\nLBEhIiMC83+dD09HT2wauQlPPP6E0deMyo5CyKEQBHsFY13QuocHbDnOwvGkb0ESE1kXdWws655u\naJWVrDdkwgTW42EojV6DT85/gtXRqxHSNwTLhi6Dg61DjcfrBT3O3zqPsLQwhF0Lg0qrwuejP8do\nr9Fm+FtwXMvCk76F2b6dDaaeO1dzLRNzEAS2DsnODvj6a9NmPyoqFFh6aim+vfwtZO1k6N6xO9w7\nusPdgT3aSNsgMjMSv6T/Aud2zhj7xFiMfWIsnuz0pHF99xxnQXjStzBELBk7OrL+/YYosKjVAnPn\nAikprHhWfT9ctHot8srycOPuDWQps5B1NwtZyiyUVpVihPsIjPUei+4du5sneI5r4XjSt0BKJSt0\nZmfHFm451NxzYrSCAjZm0K4dsG9f06r9w3GcaXmT3zc3cw4ObDp59+5sM4qUFPO87unTbLB4xAg2\n05EnfI5rGXhLvwX59ltgwQLg889Zt48piIANG9gMndBQNljMcVzTxLt3OCQksBk2U6YAK1cat6ao\ntBR47TU2NfOHHxpl8yeO4+qBd+9w6N+flZy5eBEIDGQreFNTWQu+OqWlwMGDwMyZgKcn0KkTqyvG\nEz7HtUy8pd9C6XTA3r3Ab7+xJF5ezvbc9fcH+vVjHwpHjrCvgwcDo0ezDc179BA7co7jDMW7d7ga\n5eWxQm1nzrAuoP79WZIfNoxXG+C45oonfY7jOAvC+/Q5juO4WvGkz3EcZ0F40uc4jrMgPOlzHMdZ\nEJ70OY7jLAhP+hzHcRbE5F2eS0pK8NJLLyEnJwdubm74/vvv4VBNiUc3NzfY2dmhVatWkEqliI+P\nr1fAHMdxnOlMbumvWbMGQUFBSE9Px/Dhw7FmzZpqj5NIJIiKikJiYiJP+BzHcSIzOemHh4cjJCQE\nABASEoJDhw7VeCxfdMVxHNc0mJz0FQoFZDIZAEAmk0GhUFR7nEQiwYgRIzBgwADs2LHD1MtxHMdx\nZlBrn35QUBAKCwsfeX7lypUPfS+RSCCpYePUmJgYuLq64vbt2wgKCoK3tzf8/f2rPXb58uUP/hwQ\nEICAgIA6wuc4jrMcUVFRiIqKqtdrmFx7x9vbG1FRUXBxcUFBQQECAwORlpZW6zkrVqxA+/btsXDh\nwkcD4bV3OI7jjNKotXfGjBmD0NBQAEBoaCjGjRv3yDEqlQrl5eUAgMrKShw7dgy+vr6mXpLjOI6r\nJ5Nb+iUlJZg8eTJu3rz50JTN/Px8zJo1C0eOHMGNGzcwYcIEAIBOp8PLL7+M999/v/pAeEuf4zjO\nKLy0MsdxnAXhpZU5juO4WvGkz3EcZ0F40uc4jrMgPOlzHMdZEJ70zaC+iyXExuMXF49fXM09fmPx\npG8Gzf0/DY9fXDx+cTX3+I3Fkz7HcZwF4Umf4zjOgjSZxVl+fn5ITk4WOwyO47hmo2/fvkhKSjLq\nnCaT9DmO47iGx7t3OI7jLAhP+hzHcRZE9KQfGRkJb29veHp6Yu3atWKHY5Tc3FwEBgaiV69e6N27\nN7Zt2yZ2SCbR6/Xo168fgoODxQ7FaEqlEhMnTkTPnj3h4+ODuLg4sUMy2OrVq9GrVy/4+vpi2rRp\nqKqqEjukWs2cORMymeyh8uglJSUICgqCl5cXRo4cCaVSKWKEtasu/sWLF6Nnz57o27cvJkyYgNLS\nUhEjrF118d+3ceNGWFlZoaSkpM7XETXp6/V6vPvuu4iMjMTVq1exf/9+pKamihmSUaRSKTZv3oyU\nlBTExcVh+/btzSr++7Zu3QofH58adz9ryubOnYsXXngBqampuHz5Mnr27Cl2SAbJzs7Gjh07kJCQ\ngN9//x16vR4HDhwQO6xazZgxA5GRkQ89t2bNGgQFBSE9PR3Dhw/HmjVrRIqubtXFP3LkSKSkpCA5\nORleXl5YvXq1SNHVrbr4Adb4PH78OLp162bQ64ia9OPj4+Hh4QE3NzdIpVJMmTIFYWFhYoZkFBcX\nF/j5+QEA2rdvj549eyI/P1/kqIyTl5eHiIgIvPHGG82utHVpaSnOnj2LmTNnAgCsra1hb28vclSG\nsbOzg1QqhUqlgk6ng0qlQufOncUOq1b+/v7o2LHjQ8+Fh4cjJCQEABASEoJDhw6JEZpBqos/KCgI\nVlYsDQ4aNAh5eXlihGaQ6uIHgAULFmDdunUGv46oSf/WrVvo0qXLg+/lcjlu3bolYkSmy87ORmJi\nIgYNGiR2KEaZP38+1q9f/+A/fnOSlZUFJycnzJgxA/3798esWbOgUqnEDssgjz32GBYuXIiuXbui\nU6dOcHBwwIgRI8QOy2gKhQIymQwAIJPJoFAoRI7IdLt27cILL7wgdhhGCQsLg1wuR58+fQw+R9R3\nenPsTqhORUUFJk6ciK1bt6J9+/Zih2Oww4cPw9nZGf369Wt2rXyA7caWkJCAOXPmICEhAe3atWvS\n3Qt/df36dWzZsgXZ2dnIz89HRUUF9u7dK3ZY9SKRSJrte3rlypWwsbHBtGnTxA7FYCqVCqtWrcKK\nFSsePGfI+1jUpN+5c2fk5uY++D43NxdyuVzEiIyn1Wrx4osv4pVXXql2n+CmLDY2FuHh4XB3d8fU\nqVNx6tQpTJ8+XeywDCaXyyGXyzFw4EAAwMSJE5GQkCByVIa5ePEinn32WTg6OsLa2hoTJkxAbGys\n2GEZTSaTobCwEABQUFAAZ2dnkSMy3u7duxEREdHsPnSvX7+O7Oxs9O3bF+7u7sjLy8OTTz6JoqKi\nWs8TNekPGDAAGRkZyM7OhkajwXfffYcxY8aIGZJRiAivv/46fHx8MG/ePLHDMdqqVauQm5uLrKws\nHDhwAMOGDcM333wjdlgGc3FxQZcuXZCeng4AOHHiBHr16iVyVIbx9vZGXFwc1Go1iAgnTpyAps2I\nnQAAATpJREFUj4+P2GEZbcyYMQgNDQUAhIaGNruGT2RkJNavX4+wsDDY2tqKHY5RfH19oVAokJWV\nhaysLMjlciQkJNT9wUsii4iIIC8vL+rRowetWrVK7HCMcvbsWZJIJNS3b1/y8/MjPz8/Onr0qNhh\nmSQqKoqCg4PFDsNoSUlJNGDAAOrTpw+NHz+elEql2CEZbO3ateTj40O9e/em6dOnk0ajETukWk2Z\nMoVcXV1JKpWSXC6nXbt20Z07d2j48OHk6elJQUFBdPfuXbHDrNH/xr9z507y8PCgrl27Pnj/vv32\n22KHWaP78dvY2Dz4/f+Vu7s73blzp87X4WUYOI7jLEjzm7LBcRzHmYwnfY7jOAvCkz7HcZwF4Umf\n4zjOgvCkz3EcZ0F40uc4jrMgPOlzHMdZEJ70OY7jLMj/AxuJHYQL90OPAAAAAElFTkSuQmCC\n",
"text": [
"<matplotlib.figure.Figure at 0x5311950>"
]
}
],
"prompt_number": 95
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# IPython notebook\n",
"\n",
"Locally, you can run\n",
"<pre>\n",
" ipython notebook --pylab inline\n",
"</pre>\n",
"\n",
"* Evaluate and edit code by the chunk (cell) instead of by line\n",
"* Keep images/plots/calculations inline with code\n",
"* Excellent for interactive/iterative data exploration\n",
"* Use markdown instead of comments for literate programming"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"#DEMO IPython Notebook\n",
"\n",
"If you're reading this, you're seeing my slides online. It's hard for me to demo this for you, but luckily there are many writeups out there of how awesome IPython notebook is.\n",
"\n",
"![](files/likeaboss2.jpg)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"# Bonus: NBconvert\n",
"\n",
"* Converts notebooks into a variety of formats\n",
" * LaTeX/pdf\n",
" * HTML\n",
" * **Reveal.js**\n",
" * This presentation was made entirely in IPython notebook\n",
"* Notebooks can then be hosted/shared with [NBviewier](http://nbviewer.ipython.org/urls/raw.github.com/jrjohansson/qutip-lectures/master/Lecture-1-Jaynes-Cumming-model.ipynb) or [Wakari](https://www.wakari.io/sharing/bundle/wakari_demo/realtime_twitter_analysis)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"# Extra Bonus: Python + JavaScript in the notebook\n",
"\n",
"Run [this notebook](https://www.wakari.io/sharing/bundle/wakari_demo/realtime_twitter_analysis) in Wakari to see Python + JavaScript in action\n",
"\n",
"[![](files/like-a-boss1.jpg)](https://www.wakari.io/sharing/bundle/wakari_demo/realtime_twitter_analysis)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"#3. Use the SciPy stack"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"Actually..."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"#3. Use *the rest of* the SciPy stack\n",
"\n",
"![](files/scipy.png)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# 3.1 Numpy\n",
"\n",
"* Used for n-dimensional arrays\n",
"* C code under the hood, so it's *really* fast when used correctly\n",
"* Use it to replace **MATLAB/Octave**\n",
"\n",
"[Link](http://www.numpy.org/)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"# Example\n",
"The \"native\" Python solution for matrices is often to use a list of lists, but this can be really awful. \n",
"\n",
"For example, let's look at column-wise operations on a list of lists."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"import random as rd\n",
"N = 4\n",
"\n",
"lol = [[rd.random() for c in range(N)] for r in range(N)]\n",
"# OR\n",
"lol = []\n",
"for r in range(N):\n",
" row = []\n",
" for c in range(N):\n",
" row.append(rd.random())\n",
" lol.append(row)\n",
"lol"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 53,
"text": [
"[[0.9937229473980533,\n",
" 0.995334868014186,\n",
" 0.5942674962738761,\n",
" 0.5154385022192677],\n",
" [0.422784005229769,\n",
" 0.7807343114323023,\n",
" 0.09179473422846407,\n",
" 0.609573372880339],\n",
" [0.4972764651566518,\n",
" 0.13311678867268917,\n",
" 0.12249203373176598,\n",
" 0.8453804747179231],\n",
" [0.15205034547325147,\n",
" 0.6133030575174816,\n",
" 0.9485418183964225,\n",
" 0.8287048466130321]]"
]
}
],
"prompt_number": 53
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"List slicing: Can we get the first column of this \"matrix?\"?"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"lol[:,0]"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"ename": "TypeError",
"evalue": "list indices must be integers, not tuple",
"output_type": "pyerr",
"traceback": [
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)",
"\u001b[1;32m<ipython-input-55-fb5f0d5bbc73>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mlol\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[1;31mTypeError\u001b[0m: list indices must be integers, not tuple"
]
}
],
"prompt_number": 55
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"Try again."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"How about this?"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"lol[:][0]"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 56,
"text": [
"[0.9937229473980533, 0.995334868014186, 0.5942674962738761, 0.5154385022192677]"
]
}
],
"prompt_number": 56
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"This is actually the first *row*. Seriously, go back and check."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"Surely a list comprehension can save us:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"[x[0] for x in lol]"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 57,
"text": [
"[0.9937229473980533,\n",
" 0.422784005229769,\n",
" 0.4972764651566518,\n",
" 0.15205034547325147]"
]
}
],
"prompt_number": 57
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"That works, but... ugh.\n",
"\n",
"Do you want to write a column-wise sum?"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"This isn't FORTRAN. I shouldn't have to think about which way my matrix is laid out, row- or column-major. Try again with Numpy:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"import numpy as np\n",
"\n",
"npm = np.random.random((N, N))\n",
"npm"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 62,
"text": [
"array([[ 0.15602394, 0.98540191, 0.13926817, 0.23745073],\n",
" [ 0.51627372, 0.53242708, 0.27257836, 0.30676598],\n",
" [ 0.04349275, 0.16361163, 0.3415986 , 0.49103593],\n",
" [ 0.33081051, 0.99886844, 0.76993015, 0.55732118]])"
]
}
],
"prompt_number": 62
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"npm[:,0]"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 63,
"text": [
"array([ 0.15602394, 0.51627372, 0.04349275, 0.33081051])"
]
}
],
"prompt_number": 63
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"Nice. And that column-wise sum?"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"npm.sum(0)"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 67,
"text": [
"array([ 1.04660092, 2.68030907, 1.52337528, 1.59257382])"
]
}
],
"prompt_number": 67
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"Like a boss."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"# Bonus Example: Conway's Game of Life\n",
"\n",
"Uses Numpy's image convolution for a really fast, really elegant Game of Life implementation.\n",
"\n",
"Source: [\"Think Complexity\", Allen B. Downey](http://www.greenteapress.com/compmod/html/book008.html)"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"import numpy\n",
"import scipy.ndimage\n",
"import Image\n",
"\n",
"class Life(object):\n",
"\n",
" def __init__(self, n, p=0.5, mode='wrap'):\n",
" self.n = n\n",
" self.mode = mode\n",
" self.array = numpy.uint8(numpy.random.random((n, n)) < p)\n",
" self.weights = numpy.array([[1,1,1],\n",
" [1,10,1],\n",
" [1,1,1]], dtype=numpy.uint8)\n",
"\n",
" def step(self):\n",
" con = scipy.ndimage.filters.convolve(self.array,\n",
" self.weights,\n",
" mode=self.mode)\n",
"\n",
" boolean = (con==3) | (con==12) | (con==13)\n",
" self.array = numpy.int8(boolean)\n",
" \n",
" def run(self, N):\n",
" for _ in range(N):\n",
" self.step()\n",
" \n",
" def draw(self, scale):\n",
" im = Image.fromarray(numpy.uint8(self.array)*255)\n",
" z = int(scale*self.n)\n",
" return im.resize((z,z))"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"prompt_number": 98
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"l = Life(50)\n",
"imshow(l.draw(15))"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 99,
"text": [
"<matplotlib.image.AxesImage at 0x547cf10>"
]
},
{
"metadata": {},
"output_type": "display_data",
"png": "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\n",
"text": [
"<matplotlib.figure.Figure at 0x54d0b90>"
]
}
],
"prompt_number": 99
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"l.run(10)\n",
"imshow(l.draw(15))"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 100,
"text": [
"<matplotlib.image.AxesImage at 0x55d0210>"
]
},
{
"metadata": {},
"output_type": "display_data",
"png": "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\n",
"text": [
"<matplotlib.figure.Figure at 0x549e210>"
]
}
],
"prompt_number": 100
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# 3.2 Scipy library\n",
"\n",
"* Higher-level interface for numeric computation with Numpy\n",
"* Many submodules for common computational tasks\n",
" * `scipy.stats`\n",
" * `scipy.optimize`\n",
" * `scipy.linalg`\n",
" * `scipy.signal`\n",
" * `scipy.sparse.csgraph` (compressed sparse graph)\n",
" * and much more\n",
"* Use it to replace **R** and **MATLAB/Octave**\n",
"\n",
"[Link](http://www.scipy.org/scipylib/index.html)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"# Example: Linear Regression"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"from scipy import stats\n",
"import numpy as np\n",
"\n",
"x = np.random.random(10)\n",
"y = np.random.random(10)\n",
"slope, intercept, r_value, p_value, std_err = stats.linregress(x,y)\n",
"\n",
"print \"r-squared:\", r_value**2"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"r-squared: 0.109819072488\n"
]
}
],
"prompt_number": 2
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"We'll come back to this in a minute."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# 3.3 Matplotlib\n",
"\n",
"* Comprehensive 2D plotting library\n",
"* Incredibly flexible and powerful\n",
"* Steep learning curve, similar to native MATLAB and R plotting\n",
"\n",
"[Link](http://matplotlib.org/)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"# Example: Linear Regression, continued\n",
"\n",
"From before, we have the following:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"from scipy import stats\n",
"import numpy as np\n",
"\n",
"x = np.random.random(10)\n",
"y = np.random.random(10)\n",
"slope, intercept, r_value, p_value, std_err = stats.linregress(x,y)\n",
"\n",
"print \"r-squared:\", r_value**2"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"import matplotlib.pyplot as plt\n",
"\n",
"sizes = 1000* np.random.random(10)\n",
"colors = np.random.random(10)\n",
"\n",
"fit_x = np.linspace(0,1,100)\n",
"fit_y = slope * xx + intercept\n",
"\n",
"plt.scatter(x,y, sizes, colors, alpha=0.5)\n",
"plt.plot(fit_x, fit_y, '--r')\n",
"\n",
"plt.title(\"Fit line to random junk\", fontsize=16)\n",
"plt.show()"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"outputs": [
{
"metadata": {},
"output_type": "display_data",
"png": "iVBORw0KGgoAAAANSUhEUgAAAXYAAAEMCAYAAADQ553CAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzt3Xl4VOXZ+PHvTGayJ5AFsk0gZCELSwiyKxoQCItQKloR\nVAREakstWltbW2uwbvxsa6m8KlVcUAhYUcIiQVkCyi5LUAIIgawkIRvZt5k5vz/ykteQkEySmSyT\n+3Ndc12Zmec85z6TnDtnnvMsKkVRFIQQQlgNdWcHIIQQwrwksQshhJWRxC6EEFZGErsQQlgZSexC\nCGFlJLELIYSVkcTexX344Yeo1eomH3v27Kl/Pz09vX6b2NhY9u3bZ1L9sbGxqNUN/wzUajUvvvii\nWY+jJadPnyY2NpaioqIO3a+lNfX5dpaOiOXGPoxGo0X3I5qn6ewAhGk+++wzdDpdg9fCw8OJjIzk\nyJEjeHt717/+4osv8pe//IUJEyaYVLdKpWrw/MiRI432ZWmnT5/mxRdf5JFHHsHNza1D921pN3++\nnWXJkiVMnz7d4vvpKsfbk0li7yaGDRtGYGBgo9ddXFzw9PRs9Hprxp3dXHbUqFGtD9BMLD1erra2\nFq1Wa9F93KyrjAH08/PDz8/P4vvpKsfbk3WN74iizW5uirnxVfvll1+ub7JpbbOKWq1mxYoV9c9v\nfL2+dOkSM2bMwMXFhYCAAP72t781Oonz8vL45S9/iU6nw97envDwcN59990Wj2HRokUAhISE1Md9\n45hKSkpYtmwZvr6+2NvbExYWxr/+9a8WjyM1NRW1Ws3bb7/NH/7wh/rti4uLycvLY+nSpYSGhuLk\n5ES/fv2YP38+V69ebVBHa4791KlTjB8/HgcHB3Q6HS+99FKTSc6U40lMTEStVhMfH8/jjz+Oh4cH\n7u7uPPXUUxiNRg4fPszYsWNxcnJi8ODBfPXVVy1+Hjc3xdz4fD766KMm933gwIH616Kjoxk/fjy7\nd+9m+PDhODk5MWTIELZs2dLifhMSEnB2dubJJ5+UpN9B5Iq9m9Dr9ej1+vrnKpUKGxubRuVunPAL\nFy5k6dKlAG1qVmnq6/TPf/5zFi1axO9+9zu2bt3KCy+8gL+/P48++ihQl7DuuOMOqqurWbFiBQMG\nDCAhIYEnnniC6upqli1b1uS+7rnnHv7yl7/w0ksvNWhy8vb2xmg0MmPGDE6dOsXf/vY3hgwZwvbt\n23n66afJy8vj5ZdfbvFYXn75ZUaNGsV7772HwWDAzs6O3Nxc7OzsePnll/Hy8iI7O5u///3v3H77\n7Zw/fx47O7tWHXt+fj4TJ07E19eXdevWYWtry+uvv05aWlqDz7K1x7N8+XLmzJnDp59+yv79+3np\npZeorKxk3759/OlPf8LX15eXXnqJe++9l7S0NDw8PJr9LJr6vZrSdKJSqUhJSWH58uU899xzeHh4\n8I9//IP777+f8+fPExQU1OR269atY8mSJbzwwgs899xzLe5HmIkiurQPPvhAUalUjR7jx49v8H5a\nWlr9NiqVSnn++edNqv+FF15QVCpVg9dUKpWyYsWKRmU+/PDDBuWGDBmiTJkypf75iy++qNjb2yuX\nLl1qUG7JkiWKp6enYjAYWjzOlJSUBq9v27ZNUalUykcffdTg9ccee0yxs7NT8vPzb1nnlStXFJVK\npdx22223LHODXq9X0tPTFZVKpXzxxRf1r5t67M8995xiZ2enZGZm1r9WXl6ueHh4KGq1utXHs2/f\nPkWlUimLFy9uUG748OGKSqVSDh48WP/amTNnmqzzZjf/rm98Pjdvd2Pf+/fvr3/trrvuUmxtbRv8\nbq9du6bY2Ngor7zySqN96PV6ZeXKlYpWq1XWrl3bbFzC/KQpppvYsmUL3333Xf1j7dq1HR7DjBkz\nGjwfNGhQg944CQkJjBkzhoCAgPpvGHq9nilTplBQUEBycnKr93ngwAHUajXz5s1r8Pr8+fOpqanh\nyJEjLdYxe/bsJl9/++23iYyMxMXFBa1WS//+/QH48ccfG5Vt6dgPHz7MmDFjGrRhOzo6MnPmzAbN\nD609nmnTpjV4HhoairOzM+PGjWvwGkBmZmaTx2kuISEhDa7M+/TpQ9++fcnIyGhUdvny5cTGxrJ5\n8+b6ZjbRcaQpppsYPHhwkzdPO5K7u3uD53Z2dlRVVdU/v3btGikpKU3enFSpVBQUFLR6n4WFhbi7\nu6PRNPxTvdELqLCwsMU6fHx8Gr325ptv8tvf/pbf/e53xMTE4ObmhsFgYMyYMQ2O6YaWjj07O5uh\nQ4c22s7Ly6tdx3NzDyFbW1t69+7d6DWgybjN6ebPABp/Djds3LiRIUOGcPfdd1s0JtE0SezCbDw9\nPfH29mbVqlVNvj9w4MBW1+nu7k5hYSF6vb5BMszJyal/vyVNtSFv3LiRSZMm8frrr9e/duXKlVbH\nd4Ovr299TD+Vm5vb4Lk5jkcx0w1Ie3t7AGpqahq83pZ/wDfbu3cvkydPZtq0aXz55Zc4OTm1u05h\nOmmKsUK2trZUVlZ2+H6nTp3KuXPn8Pf3Z/jw4Y0ezs7Ot9z2xs3KioqKBq9HR0djNBr59NNPG7y+\nfv167OzsGDt2bJtiraysbHTV/MEHH7SpLoCxY8dy5MiRBs0h5eXlbNu2rcE/FnMcj7n6iXt5eWFn\nZ8f333/f4PUdO3a0u+5BgwaRmJjIxYsXmTZtGuXl5e2uU5hOrtitUEREBNu3bycmJobevXvj5+fX\nZHOEuT311FNs2rSJ8ePH89RTTzFw4EDKy8s5f/483377bbNd4wYNGgTA//zP//DII4+g1WqJjIxk\n2rRp3HHHHfzyl78kLy+PiIgIvvzyS9auXctzzz1n0hVuU6ZOncrKlSt59dVXGTlyJHv37mXz5s1t\nqgvqjv2tt95iypQpxMbG1veKcXR0bNC8Yo7jMdcVu0ql4oEHHmDt2rUMHDiQgQMHsmPHDvbv32/y\nfpuLJSwsjMTERCZMmEBMTEx9t0dheXLF3g20dIV28/urV6/GycmJmTNnMmrUqGb7katUKpPqv1U3\nuZ++7urqyqFDh5g+fTorV65k6tSpLF68mG3btjFx4sRm9zF06FBiY2PZtm0b48ePZ/To0WRnZ6NS\nqdixYwcLFixg5cqV3HPPPezcuZM33niDl156qdk6m/PXv/6VpUuX8sYbb3Dvvffyww8/sGvXrjYf\nu4eHB3v27MHT05MFCxbwm9/8hunTp7No0aIG5VpzPKbst71WrVrFvffeS2xsLHPnzqWmpoY333yz\n0T6a+xyaKzdw4ED2799PWloaMTExlJaWmi12cWsqpYV//4sWLWLHjh307du30Ve2G5588kl27tyJ\no6MjH374IVFRURYJVgjRdk8//TSffPIJ165d6+xQhIW1eMW+cOFCEhISbvn+l19+yaVLl7h48SL/\n+c9/eOKJJ8waoBCifYqKiti2bRtffPEFY8aM6exwRAdoMbGPHz++2UmZtm7dyoIFCwAYPXo0169f\nb9QTQAjRefbv38+DDz5IYGCgSVMxiO6v3TdPs7Ky8Pf3r3+u0+nIzMxs1H9XCNE5Zs+eTVlZWWeH\nITqQWW6e3txML9N2CiFE52n3Fbufn1+DIcWZmZlNTg0aHBxMSkpKe3cnhBA9SlBQEJcuXWrVNu2+\nYp81axbr1q0D6hZo6N27d5PNMCkpKSiK0m0fL7zwQqfH0FPj786xS/yd/+ju8bflgrjFK/YHH3yQ\n/fv3k5+fj7+/PytWrKC2thaApUuXMn36dL788kuCg4NxcnJq1+g9IYQQ7ddiYo+Li2uxktWrV5sl\nGCGEEO0nI09NFB0d3dkhtEt3jr87xw4Sf2fr7vG3RYsjT822I5WKDtqVEEJYjbbkTrliF0IIKyOJ\nXQghrIwkdiGEsDKS2IUQwspIYhdCCCsjiV0IIayMJHYhhLAyktiFEMLKSGIXQggr0+5pe0XXZjQa\nKS4upra2FrVajYuLC3Z2dp0dlhDCgiSxW6Hi4mKOHj3ByZNXuHIll9paB1QqW8CI0ViCr28vIiL8\nGDduGAEBAbIwihBWRuaKsSLXr19n8+ZdHDyYiqIMxdU1DBcXHzQa+/oyRqOBiop8iotTqa39jn79\nFObNm0RYWFgnRi6EuJW25E5J7FZAURSOHz/BBx/spbZ2LD4+o7GxsTVpu6Kiy1y/voPJk/24777p\nODg4dEDEQghTSWLvgRRFIT4+gc2bU/H2noOTU99W12Ew1JKR8TUDBlzhqacextXV1QKRCiHaQhJ7\nD7R9+1ds2pRO//4PNWhyaYvMzG/Q6ZL4wx8W4ejoaKYIhRDtIdP29jA//vgj//3vOfr1m9/upA6g\n040nLS2Izz770gzRCSE6i/SK6aaqqqr4z3+24+Z2L1qt+drFdbpJ7N79DiNGJBMREWG2eoXl1NbW\nkpWVRXZ2NldTfqQ4LwdDbS02Gi1Ovd3wCRyIr06HTqfD3r79FwCi62uxKSYhIYHly5djMBh47LHH\nePbZZxu8X1RUxKJFi7h8+TL29va8//77DBo0qPGOpCnGrPbtO8CHHxYyYMBss9ddVHQFF5ft/O1v\ny6QrZBdWWFjId0cOcXrfLtwM5fjZKfg42+Lm5IBGrcagGCmtrOFqSSVXa1Tk6LWEj5vAyDvuxNfX\nt7PDFyYyexu7wWAgNDSU3bt34+fnx8iRI4mLiyM8PLy+zO9//3tcXV15/vnnuXDhAr/+9a/ZvXu3\nWYITTTMajfzhD/8C5uHs7G32+hVFIS3tHf761xgCAwPNXr9on+rqar7esZ3kfduJclVxW78+uDu3\n/K2tvKqGU+nX+K7IQN/Isdxz/1y5Ud4NmL2N/dixYwQHBxMQEIBWq2Xu3LnEx8c3KHPu3DkmTJgA\nQGhoKKmpqeTl5bUydNEaly9fpqDA1SJJHer+kGxtR/Dtt6csUr9ouytXrvD2K7EYjm7jyeF+TI7o\nZ1JSB3Cyt+WOgTp+M9If37SjrPnbcySdPm3hiEVnaDaxZ2Vl4e/vX/9cp9ORlZXVoExkZCSff/45\nUPePIC0tjczMTAuEKm5IT88EBlh0H716BXD2rPweu5IzSUlsfuMlZriW8bOhAdjbtu0WmY1aTXSo\nPw8H2HNg7T/Y+9Uu+TZtZZr9yzClffWPf/wjv/3tb4mKimLIkCFERUVhY2PTZNnY2Nj6n6Ojo4mO\njm5VsKLO+fNXcXQcZtF9ODp6kJ5eTmVlpQxa6gJ++P57vn7vDR4J70PfXk5mqdO7tzOLhtny8fZP\nUKvVRE+abJZ6RfskJiaSmJjYrjqaTex+fn5kZGTUP8/IyECn0zUo4+Liwvvvv1//fMCAAbdsl/1p\nYhdtd+1aCfb2bhbdh0qlRq3uTUlJiST2Tpabm8uX7/2bBeGeZkvqNzjZ2/JwpD9r4z+mr6+f9ITq\nAm6+6F2xYkWr62i2KWbEiBFcvHiR1NRUampq2LRpE7NmzWpQpri4mJqaGgDeffdd7rrrLpydnVsd\niDCdXm9ArW76W5F5qTEajR2wH3ErBoOBLR+/z2QvG7x6Wea8crK35echHny57j+Ul5dbZB+iYzWb\n2DUaDatXryYmJoaIiAgeeOABwsPDWbNmDWvWrAEgOTmZIUOGEBYWxq5du1i1alWHBN6T2dlpMRhq\nOmBPtWg0MtShMx365gDOV88xrJ+XRffj79GLoTYlJGzZbNH9iI4hUwp0Qx9//DnffhuAj89wi+3D\nYKglJ+f/8fbbz0py7yS1tbW88dzTPBbsaHLPl3btT2/gje8yeWzFP3B3d7f4/oRp2pI75YzthkJC\nfNm79ypgucReVpZDv359JKl3ouTkZPyUUtydPTpkf1qNDcNcVZw4eoTJ06abvJ3BYCA7O5vs7Gxy\nsq5QXVUGqHB06o2PLgAfHx+8vLxksFsHkrO2GxowYACKcghFMaJSWWa6n+Li89x9d4BF6u6K9Ho9\nBoMBW1vbLpOATuz7itu9OvZ+1Yh+fXhvXwJ3x0xFrW7+b6ukpITvjh3h5NEvcdKU4Oep4O2uwaFX\nXVopK6/hynGFb/IUsPVhxLjpRA2/TW7GdwBJ7N2Ql5cXERG9SE//EU9P8y+QYTTqgdOMG7fY7HV3\nJXl5eRw6dJTduw9TWloBqFGrFSIjBzJ58p2Ehobesuuupen1erJTLhA4wqdD9+vu7IBDTR55eXl4\neTXdrm80Gjly+CDf7l7PkP41LJjiQR+PfresU1EUMrNLOP7De/zPvs+YOvsxBg0a1GX+gVojSezd\n1LRpo3j99W/w8Bho9qv27OzvGDHCx2rbWUtLS1m3bhPfffcjKpUvffuOxd3dCZVKhdFo4MKFdE6d\n2oSHh4pHH53DkCFDOjzG3Nxc3DVGtJqO/8fiawfZ2dlNJvby8nI2ffIfVGWneGymD+69W776VqlU\n+Pv2wt+3F5nZJcRv/X+cPzuJ2XPmSVOfhci0vd3U4MGDGTFCS1bWYbPWW1lZiFp9gAcemGbWeruK\nwsJCXnrpX5w8WYG/fwz9+g3D3t65/upRrbahb98BBARMQFEG8fe/f8I33xzs8DhzcnLwseuczgY+\n9iqy09MavV5eXs4Ha/5Of+cfeHT2AJOS+s10Pq4svS8ACnezYd0a9Hq9GSIWN5PE3k2pVCoefvhn\n2NkdpLg4o+UNTGAw1HD16mYefng8Hh4dc8OuI1VUVPDGG2u4fr0v/v5DWxwL4OraB1/fO3n33XiS\nkpI6KMo6lZWVOKk7J7E72WmpLL3e4DWDwcD6D1czyCeDu8f6t6sZRaNRc+/kAThWH2XL5g3SW84C\nJLF3Y25ubjz11L2Ulm5sd3LX66tJTd3APff05fbbx5gpwq5l//5vSE9X4+MTavI2dnZO9Okzmvff\n/6xDry6NRmOnnZw2ajWGm471m/37cDKcJXqUn1n2oVarmH13ALkpe0hOTjZLneL/SGLv5oKDg/nj\nH39OdXUcWVl1PWVaq7g4g/T0d5k925P7759plTe19Ho9CQnf4uXV+pvNLi4eFBdrOjQB2djYoKdz\nfg+1BgMarV3987y8PI4f2MjMu/zM+reh0aj52V0e7PziXSorK81Wr5Cbp1YhODiYl19ewrp18Zw4\nkYyr63g8PEJavKlaUZHPtWtH6d37HM8+O63JBVKsRXJyMiUlWvr379Wm7Z2cAti1az/9+vXjdFIS\n57MyScnOoqSiAgAXR0eCvH0J1/kTOXQobm7tm8vH3d2dNH3nJPaCihrcff7vyvzIwURGhRlxdbFr\nZqu20fm4MsAzlaTTpxgzdpzZ6++pJLFbCTc3N558cgHff/89O3d+w/nzO4FQ7Ox8cHLqi42NHYpi\noLKyiPLybCCVXr3yefDBKO644wmcnMw7uVRXc/bsj2i1bR+W7+DgzBdff855/XU0Q8NxGhqCS8wd\nuP3vvEjVZWVczM7ldHoG6//zFiN0/Zk9afItuwy2xMfHhx2VndP2fLVGxRi/usReVVXF2VO7WXaf\nZeb+Bxg52I34g18yesxYq/y22BkksVsRlUrF0KFDGTp0KNnZ2Vy+fIWLF1O4cuUw1dW1aDQ26HSu\nhIf70q/fGIKDg3tMd7OSkjK02tav96koRtIyfuBs+UWq7x6D/68W4ODUeNCQo5sbjm5uEBGG4e5o\nfkg6w8kP32PumDu4a/z4Fgf73KxXr14YHVworqiil2PHrVNqNCpkVyr1S+elpKTQz7MWZydbi+3T\n38cVpTqda9eutfkfoWioZ5zVPZCPjw8+Pj7cfntnR9I12NioURRDq7YxGg18f/Fb0r0U3H4+lwp9\nDhq7lpsjbLRadCNuoyokmI+37CAtJ5uH77u/VYOdVCoVYSNv58wPXzF+oH/LG5jJxZwCPALD6mdo\nvZqZjl8fy+5TpVLh56ni6tWrktjNRG6eih7Bw6M31dVlJpdXFIXklMNk6DR43jMLGwdH1DagaUVy\ntu/Vi+D5v+AbfQUbt3zR6m59I++4k+8KDRiNHdckczy3jJF3T61/np15AZ8+lm+m83FXkZOVbvH9\n9BSS2EWPcNttwzAYrpqcXK/lpXLFsRSPKVNR22goLy+kfz+fVo/ytdFoCLrvZ+zJyeDMmTOt2tbH\nxweXwAjOZl1r1XZtlXO9jGyb3g1uoleWF+PsaLlmmBucnWypKC+y+H56Cknsokfw9/cnKMiT69ez\nWyxbW1vF6dyTuE6ehFqjBQUMxhL6B7StScRGq8XnZ9P5YNeXrV7IYur989h1tZryKsvOv28wGtly\n4RqTHnikwX0XRQG5n9n9SGIXPYJKpWL69GgKC5MxGptva8/Kvoh+cCD2ferae8vKC/H0cKKXq2ub\n9+/q60NFaCDHT5xo1XY6nY7IaXPYcS7LoiM0v7mYhcvQcQyLimrwur2DE5VVlh+YVVlVi529i8X3\n01NIYhc9xvDhw5k0KYLU1EO3TO6KYiSl5BLOg+sm/qqoKMbG5jrDbxsK7Rww1GdEFDu/O9bq5Qaj\nJ02hyCecxB+z2rX/W/kh8xonDL2Z+Yt5jbobevmGkJ1n+r2JtsopNOLt19/i++kpJLGLHkOlUjF/\n/i+4++5ArlxJ5Pr1nEZXweXl16lysUXr5k5xcQ42NkXcccdIHB0c271/Vx9vCrVqrl1rXZu5Vqvl\noV/+hrP2/uw9n2HWK/czGbkkFNny0JN/wLWJbyS+/gFczbf8zdurBXX3FIR5SGIXPYpGo+GRR+ax\nbNk9uLikkpa2m8zMZAoKMikqukp6+veUu0JlRSohwb24664xuDibr4lA7evF1atXW72dk5MTC3/7\nDJfcBrLh5BVKKqrbFUd1rZ5t36eyp7IXC37351t2MwwMDCQlW01VteWaY67ll1Nh6I23t+UGQfU0\nLa55mpCQwPLlyzEYDDz22GM8++yzDd7Pz8/noYceIicnB71ezzPPPMOjjz7aeEey5qnoYhRFITU1\nlaNHT3DtWhG1tXrSMq+QdfsQhv9sBhob8w/zSD14hBnlRu6ZOrXlwk0wGAx8k7iPY/FxTOhjw7B+\nXq2as91oVLiQnc+ujDIC75rBlHtmYW/f/ACo/8Z9SH+Hg4waap4JwG62Y38aTv0fInri3Rapv7tr\nS+5sNrEbDAZCQ0PZvXs3fn5+jBw5kri4OMLDw+vLxMbGUl1dzauvvkp+fj6hoaHk5uY2GtEoiV10\nB5/v2M4ed0f6jR5hkfozjp/grmul3D9zVrvqycnJYe/2LWQmHSPSRWGwjxtevZzR2DT+Em40KuSX\nVnA+p5AT1w24Dojgrpn3EhwcbFrMGRl89sFfeeJ+P+ztzPvPrqCogrXbS3ji6ddxcZGbp00x+2LW\nx44dIzg4mICAAADmzp1LfHx8g8Tu4+NT3z+3pKQEDw+PHjNMXVgfrdoGxdC6EaqtoRiMaM3wTcDb\n25t5j/2SoqIHOHH0CFtPHqXwQgaettBbCxqVgkFRUapXyK0GF08vAiKnMnfcHa1uy/b39yck8h6+\nOriNWRMD2h37DYqiEJ+Yw51TlkpSN7Nm/8KysrLw9/+/vrs6nY6jR482KLNkyRImTpyIr68vpaWl\nfPrpp5aJVIgO4OXhgT4n1WL11xYU4N3n1uuDtpabmxuTpk5j0tRp1NbWkpubS3FxMQaDARsbG5yc\nnPD29m6xuaUlk6fewzv/Psnpc7kMCzfPsP89hzNRuQ5n9BiZ1dHcmk3spsy09sorrzBs2DASExNJ\nSUlh8uTJJCUlNfkfODY2tv7n6OhooqOjWx2wEJbk6+sLJ4+2XLCNVNl5+EZaZiETrVaLTqdDp9OZ\nvW47OzvmL3yKj/7zCtC+5K4oCvuOZnIhrz8Llz5uuRkda2rgxAkYO9Yy9VtIYmIiiYmJ7aqj2cTu\n5+dHRsb/rcyTkZHR6I/m0KFD/PnPfwYgKCiIAQMGcOHCBUaMaNxG+dPELkRX5O3tjX1xKZXXr+PQ\nu7dZ664qLkZbeL3bduvz9PRkwePPsf6DN0i7mkrMHbpWt7kXl1axbX82lZrBPPr4r3B0bH830lta\nsABycuDrr6EbNQ/ffNG7YsWKVtfRbHfHESNGcPHiRVJTU6mpqWHTpk3MmtXwpk9YWBi7d+8G6lZW\nv3DhAoGBga0ORIiuQKPRMGloFDknzb/Gac7JJCYNjUKr1Zq97o7i6enJL5/8KzZ9Z/L2f7M4mpRl\nUlfI0rJq9h/LYM3n+fQb+iiLlj5t+TUA1q2Dffu6VVI3lxa7O+7cubO+u+PixYv505/+xJo1awBY\nunQp+fn5LFy4kPT0dIxGI3/605+YN29e4x1JrxjRTRQUFPDce+/gu3QB9u2YRuCnqktLyVzzEa8s\nehxPT0+z1NnZMjIyOHpwL5eSvyHQ24CvpwqfPs442GtRFIXyylquXisjK19FZoEdg4dPZvS4O813\n/GlpEBcHFRXw4ovmqbMLMnt3R3OSxC66kz2JiWzIuETIvPvb3QasKAqXNm7mAZ8AJk+caKYIu46y\nsjIuX77M1cw0cq9epKqyDJVKhYOjKz66MHx1/gQFBWFnwlz2LSoogP/+F9avh3Pn4L774JFHYJz1\n3oCVxC6EmRgMBt5Y+x4pgb70n3Bnu5J72r4DDLiUydOPLWnVYhviJlVVEBAA0dEwfz7ExICt5acU\n7myS2IUwo/Lycv714fukB/oRMGkC6lYmZaPBQNqeRPwuZfD0wsVWv65sh6ip6RHJ/KcksQthZpWV\nlXzy+WYOF+fjM2sarr6m9Wgpyc4he+tOxri489C9cyzb+8NaKAocPgwbNsD06XUPIYldCEtQFIWk\npCTW7/6KIo9euAwfSu/+/ti5uNQ30SiKQnVpKdfTMyk9eYZeeYU8NCmGYcOGWa6ftrVITq5L5hs2\ngL09zJtX11XRv+PWeu3KJLELYUEGg4Hz589z4PQpLmRlUKYCG+e65hVDWTlORoVQP3/uHBZFeHi4\ntKebYudOeOwxePDBunbzYcNkyaabSGIXooMoikJpaSkVFRUoioKjoyOurq5WdXVuMBjIy8sjOzub\nyspKoG4Eqre3N15eXuaZE0qvr0vk8k/wliSxCyHaRVEULl++zPF9e0n57hi9FQM+anCi7tytBHIU\nFQWKGv+Oeo6UAAAgAElEQVTBQxk5aTKhoaGo1bcY61hZCdu3w6efwtq1YKZxAT2JJHYhRJtlZmay\n9cP3UaddZqSzHYO9+2B3i6vyWoOB89fyOV5SSYmnNzMWLiYkJKTuTb2+bsTn+vUQHw8jRtQ1szzw\nADg4dOARWQdJ7EKIVjMajezZuZOkLZ8xrbcDEV59WtWkdLmgiK251xkQM53pP78X7W9+AydP1t0E\nfeAB6KZz43QVktiFEK1iMBj4bN1H1Bzcx72B/jjZta2PeLVez/aUdIoHRTF/0WPYyfzqZtOW3Clr\nngrRQymKwpa4DRgO7mNe6ADTk3pJKRw4DNu+qn/JTqPh3oED8DyXxMZ1H2Kw4GIlomWS2IXooZJO\nn+bavq/4xcAB2Nzq5ucNlVVw7BSsWQevvwVXr0FYw6X1VCoV9wT1R336OAcPHLBg5KIlPW8+SyEE\npaWlfP3hWh7WeTW5TmoDRiP8cw34ecOYERARAreYelitVjGrvy9rNq0nNCICLy/zrLYkWkfa2IXo\ngRK2bkWd8AVTgvqbtoHeABrT+5ofSc8kPXIcv1i0qI0RihukjV0I0aKamhqSvt7FKN//vZpWFMjM\nhq27IOls0xu1IqkDRPl6c+XoQUpKStoZrWgLaYoRooc5f/48/jUV9C63gW+PwqkfwGCAYYPBzzxd\nE+00GgapDCSdOsX4u+4yS53CdJLYhehhMi5dYkhBHqz/FIYNgl/Mgv46s8/REujiRNK5ZJDE3uEk\nsQvRw1y9cI7BIYEwKsqic7T4uDqzM+WixeoXtyZt7EJYo5oa2LoV5s6F3NwGbxXl5ODp4mzxibd6\nO9hTUVhIbW2tRfcjGmsxsSckJBAWFkZISAgrV65s9P7f//53oqKiiIqKYsiQIWg0Gq5fv26RYIUQ\nzTAa4cABWLoUfH3h73+HCRPgpkU+9LU1LXdxNAOVSoVGrZLBSp2g2aYYg8HAsmXL2L17N35+fowc\nOZJZs2YRHh5eX+aZZ57hmWeeAWD79u3861//onfv3paNWgjR2J/+BAkJdXObnzgB/Zvuymij1WIw\nWr7rsaIoGBRF5qXvBM0m9mPHjhEcHExAQAAAc+fOJT4+vkFi/6kNGzbw4IMPmj1IIYQJXnwRmvhW\nfbPefbworCjC0bbpQUbmUlpdg51LL/PM2y5apdnvY1lZWfj/ZHkqnU5HVlZWk2UrKirYtWsXc+bM\nMW+EQog6eXnw1lvwm980/b6dnUnV+IaFcbWk1IyBNe1qSSm+wSFWtfhId9Hsv9LW/EK2bdvGHXfc\n0WwzTGxsbP3P0dHRREdHm1y/ED1SeXndnObr18PBgzBtGjz0ULuq9AsM4tJuPaPMFOKtpJWW4xfW\n9Ld7cWuJiYkkJia2q45mE7ufnx8ZGRn1zzMyMtDpdE2W3bhxY4vNMD9N7EKIFigKjB5dt6jz/Pmw\naRM4O7e72oiICL6ysaWsugbnNk7T25Jag4GkWngsKsoi9Vuzmy96V6xY0eo6mp0rRq/XExoayp49\ne/D19WXUqFHExcU1amMvLi4mMDCQzMxMHG6xQorMFSNEG1RXm9zE0hrbPvsvLokJRA/wb7lwG5zM\nzOZcaCTzf/kri9Tfk5h9rhiNRsPq1auJiYkhIiKCBx54gPDwcNasWcOaNWvqy23ZsoWYmJhbJnUh\nxC2cPQt//jN89FHT71sgqQPcPvFujikaCsorzF53eXUNe8tquHPGTLPXLUwjszsK0dEyMiAurq7d\nvKCgrnviwoUQEdGhYRw5eJDkD9bwaOgA1Grz3OBUFIXPLqbSa+b9TLnnHrPU2dPJ7I5CdHXJyTBs\nGFy6BKtWQXo6vP56hyd1gNHjxmE7YixbL6Wa5aJLURT2pWZSGBjOhJgYM0Qo2kqu2IXoSIpSN9zf\nQk0srVVTU8P6d97G9YeTzAzqh20rp+e9wWA08vXlDC7rgliw/CmcnJzMHGnPJVfsQnQ2vR6++goW\nLICUlMbvq1RdJqkD2Nra8tATv0IdHcPbP6aRWtj66UBySsp493wqBcNGs/Dp30lS7wLkil2I9lIU\nOHYMNmyo65LYrx/Mm1eX3N3cOjs6k124cIEd779H36I8Rro5E+Lpccu2d0VRSC28zvGCYlIdXJiy\nYBGRw4bJYCQLaEvulMQuRHu99hq8/35dX/MHH4SBAzs7ojbT6/WcPXuW418lkP/jeXw0Knww4mij\nRgVUGhRyUHFVr+Ds35+RU6czNDISuy70LcTaSGIXojNUV4OtrdkXquhs5eXlXL16lZzsbKrKy1GM\nRuycnPD28cHHxwcXFxe5Qu8AktiFsITiYti8GY4cgf/8p7OjET2M3DwVwlyqquDzz2HOnLo28+3b\nISamrj1diC5OrtiFaMq4cWBvX9duPmcOyBoDopNIU4wQ5lJVVZfYhehkktiFMNWlS3XdE/v0gSee\n6OxohLglaWMXojk5OfDvf9dNhXv77ZCfD2PGdHZUQpidXLGLniEzE4YMgZkz6wYPTZoEsmSb6Aak\nKUaI5ki7ueiGpClG9FxGI+zfD48/DmfONF1GkrroIeS7qOi+FKUuia9fXze/ubt7XTOLt3dnRyZE\np5LELrqvNWvq5mmZNw927oTBgzs7IiG6BGljF91XdTVotaCWFkVhvaSNXViXsrK6ZpZHH61rQ7+Z\nnZ0kdSGa0OJZkZCQQFhYGCEhIaxcubLJMomJiURFRTF48GCio6PNHaPoSWprYceOuuYVna5uENGU\nKU0ndiFEk5ptijEYDISGhrJ79278/PwYOXIkcXFxhIeH15e5fv06t99+O7t27UKn05Gfn4+np2fj\nHUlTjDDFtGl1synOnw+/+EXdyFAherC25M5mb54eO3aM4OBgAgICAJg7dy7x8fENEvuGDRuYM2cO\nOp0OoMmkLoTJPv8cHBw6OwohurVmE3tWVhb+/v71z3U6HUePHm1Q5uLFi9TW1jJhwgRKS0v57W9/\ny8MPP2yZaEX3l54OGzfW3fR86qnG70tS71LKy8s5lXSavMJrVFRXYae1xc2lN8OGDsPDw6OzwxO3\n0GxiN2V1lNraWk6ePMmePXuoqKhg7NixjBkzhpCQkEZlY2Nj63+Ojo6W9vieoqAAPvus7kbo2bNw\n332wcGFnRyWakZGRwbfHD3Lix1P0DvfExbcXtna26GvLuViQzpfvf8VAryDuHDme0NBQ1HIT22wS\nExNJTExsVx3NJnY/Pz8yMjLqn2dkZNQ3udzg7++Pp6cnDg4OODg4cOedd5KUlNRiYhc9RFERhITU\nzc3yu9/B1Kl1vVlEl6QoCrv37earpL34junP+GmTsXNo/PsyTNSTnpzGRwc2EJEUwoNzHkSr1XZC\nxNbn5oveFStWtLqOZm+e6vV6QkND2bNnD76+vowaNarRzdPz58+zbNkydu3aRXV1NaNHj2bTpk1E\nREQ03JHcPO25KiuliaUbUBSFbQnbOZR5nDHz7sDeqeXfmcFg4MTWo/S53oslDz+GRiZWMzuz92PX\naDSsXr2amJgYIiIieOCBBwgPD2fNmjWsWbMGgLCwMKZOncrQoUMZPXo0S5YsaZTUhRVTFDh6FJ58\nEg4darqMJPVu4ejxo3xz5QjjHr7TpKQOYGNjw8jZY8l1LmLzts8tHKEwlYw8FW1z/nxdm/mGDXXT\n386bB4sX1/U9F92OXq/nhTdeZMijI+ndp/XLAOpr9SSu2sUfH31GesaZmYw8FR1j40aYOBHKy+HT\nT+uS/AsvSFLvxpKTk1F7a9uU1AE0Wg19h/tx+PgRM0cm2kISu2i9n/8cMjLgn/+E224DE3pPia4t\n8fgB+o0c0K46gm4L5uCZQ9TU1JgpKtFWkthFY1VVsHkzPPJI3RD/m9nZgY1Nx8clLKKqqooruan4\nDfRvuXAznHo5o/WyJz093UyRibaSxC7qGAywe3dd/3IfH3jrLYiOljlaeoCKigpsnezM0hfd1tmO\nyspKM0Ql2kP6Jok68+fDpUvw4IPw0kvg59fZEYkOYjQawUytaSq1qq4+0akksYs6H3wg3RJ7KAcH\nB2ora1AUxaTR5s2prdTjIH9HnU6aYnqKnBxYtQpeeaXp9+Vk7LEcHR1xd3AjPyuvXfXUVNdQlnEd\nHx8fM0Um2koSuzUrKYGPPqqbzzw8HE6ehLFjOzsq0cWoVCqiR9xF6vGUdtVzJSmFqKBIXFxczBSZ\naCtpirEieXl5XLt2jaqqKrQGAxHTpqG+/XbUjz0GW7aAo2Nnhyi6qOHDooj/91aqKqqwd7Rv9faK\nonD1eDo/m/GYBaITrSWJvZszGAycP3+eA199ReqZM/RSq7FRFBRg64wZVLu5cYeLC6NraugtiV3c\ngqOjI3cMHcfJ7ccZc/8drW5rP3fwB3xtvejfv7+FIhStIVMKdFeKQsHevfz45z9z0dUVQ3Aw/Tw9\nsbmpy1pxRQWX8vPJVamYdN99TJ46td03yIR10uv1vPfJWvI9Shg+Y5TJ3R8vfneBwm9yeGrxk7i6\nulo4yp6nLblTEnt3c/kybNhA7UcfUZqbS0ZwMJXjx1Pl5tbsZlW1tRxMT2fo9OncN3euJHfRpOrq\naj7+9BOukEX4xMF4+t16acLSolIuHEzG5oqBpfOX4O7u3oGR9hyS2K3dzp3wyCNUzZrFJ6Wl2Pft\ni64VEy7pDQb2p6Uxft48pkydasFARXdmMBg4fPQI+44nUuFQjd+Ifnj49UFrp0Vfa6C0oJiME6nU\nZlUxPnIc0eOjcZRmPouRxG7tampApWLDhg0UHDjAEP/WDwGvqq1lb3Y2z/3zn/Tu3bYJn0TPYDQa\nSUlJ4eCJQ+QU5lJZXYmt1g53l96MjRzDoEGDZHGNDmD2xaxFB6utha++qpsx8a23wMmp4fu2tpSV\nlXH6m2+Y1Ma+wvZaLV7A0cOHiZk2rf0xC6ulVqsJCQlpcjU00bVJP/bOZjTCt9/CE0+Ar2/dAKLR\no29Z/Lvjx/EwGLBtx0o1wZ6efJuQgF6vb3MdQoiuS67YO9uvfw0HDtTN1XL8OAQENFv8+P79BLZw\no7QlvRwdUeflkZqaSnBwcLvqEkJ0PZLYO9s//lE3nN/EXiolRUU439xE0wYOKhXl5eXtrkcI0fVI\nU4ylFRTAO+/AX//a9PuOjq1aqKK2pqZRX/W2UAG1Tc21LoTo9lrMEAkJCYSFhRESEsLKlSsbvZ+Y\nmEivXr2IiooiKiqKl156ySKBdisVFXXLx82aBUFBkJgIY8aYpWoHJydqzNA2blCpsLdv/dBxIUTX\n12xTjMFgYNmyZezevRs/Pz9GjhzJrFmzCA8Pb1DurrvuYuvWrRYNtNswGOom3AoLq2s3X78ezDgp\nUr/gYHJOnybY27vtIRqNFBuNeHl5mS0uIUTX0WxiP3bsGMHBwQT87w29uXPnEh8f3yixS//0n7Cx\ngeTkxl0VzeT2iRP5+MgR2nPLM6OggP5DhtCnz61HFQohuq9mm2KysrLw/8kgGJ1OR1ZWVoMyKpWK\nQ4cOERkZyfTp00lOTrZMpF3JuXPw/PMQH9/0+xZK6gDBwcHYenmRX1ra5jrSKiq4c8oUM0YlhOhK\nmr1iN2U+keHDh5ORkYGjoyM7d+5k9uzZ/Pjjj02WjY2Nrf85Ojqa6OjoVgXbqbKyIC4ONmyA3FyY\nOxdCQzs8DLVazcSZM0lYs4ZoJ6dW30i9kpeHjY9Po29dQoiuITExkcTExHbV0eyUAkeOHCE2NpaE\nhAQAXn31VdRqNc8+++wtKxwwYAAnTpxoNCFQt55S4PBhmDEDfv7zunbzu+6qa3LpJIqiELduHSl7\n9jAuIMDk5J5VWMhZg4Enn38e73a00QshOo7ZpxQYMWIEFy9eJDU1FV9fXzZt2kRcXFyDMrm5ufTt\n2xeVSsWxY8dQFMX6ZnkbORKuXoUu0otEpVLxi/nz+RRI3L2byL598WzmBm2NXs+F7GzynJ355bPP\nSlIXwso1m9g1Gg2rV68mJiYGg8HA4sWLCQ8PZ82aNQAsXbqUzz77jLfffhuNRoOjoyMbN27skMA7\nlEZT9+hCNBoNDz7yCIeCgti7bRs1qan0t7fHu3dvbDUaDEYjZVVVXC4spECjIXL8eObNnImHh0dn\nhy6EsDCZ3dEKGI1GLl26xLe7d5ORkkJFRQVarRbX3r0ZGR3NiJEjZR1KIbopmbZXCCGsTFtyp0wp\nIIQQVkYSuxBCWBlJ7EIIYWUksQshhJWRxC6EEFZGErsQQlgZSexCCGFlJLELIYSVkcQuhBBWRhK7\nEEJYGUnsQghhZSSxCyGElZHELoQQVkYSuxBCWBlJ7EIIYWUksQshhJWRxC6EEFZGErsQQliZFhN7\nQkICYWFhhISEsHLlyluWO378OBqNhs8//9ysAQohhGidZhO7wWBg2bJlJCQkkJycTFxcHOfOnWuy\n3LPPPsvUqVNlXVMhhOhkzSb2Y8eOERwcTEBAAFqtlrlz5xIfH9+o3Jtvvsl9991Hnz59LBaoEEII\n0zSb2LOysvD3969/rtPpyMrKalQmPj6eJ554AqhbUVsIIUTn0TT3pilJevny5bz22muoVCoURWm2\nKSY2Nrb+5+joaKKjo00OVAgheoLExEQSExPbVYdKaSYTHzlyhNjYWBISEgB49dVXUavVPPvss/Vl\nAgMD65N5fn4+jo6OvPvuu8yaNavhjv438QshhDBdW3Jns4ldr9cTGhrKnj178PX1ZdSoUcTFxREe\nHt5k+YULFzJz5kzuvfdeswQnhBA9XVtyZ7NNMRqNhtWrVxMTE4PBYGDx4sWEh4ezZs0aAJYuXdr2\naIUQQlhEs1fsZt2RXLELIUSrtSV3yshTIYSwMpLYhRDCykhiF0IIKyOJXQghrIwkdiGEsDKS2IUQ\nwspIYhdCCCsjiV0IIayMJHYhhLAyktiFEMLKNDtXjBA9TW5uLhcuXCD1xx/JunKFmupqNDY29PH1\nZUB4OIFBQQQGBsq6A6JLk7lihAAuXrzIV/HxpJ89S1/Azd4eN2dntDY2GIxGiisqKCwvJ19RcPT1\nZeLMmYwaPRq1Wr70Cssy+7S95iSJXXRFlZWVbPviC04kJBDu4oK/hwc2zSRrRVHILy3lh7w8PIcO\nZe6jj8qSkMKiJLEL0QrFxcW8889/okpPJ0qnQ2tjY/K2iqLwY04OaRoNS555hgEDBlgwUtGTSWIX\nwkQVFRX8e+VKXK5eZZCfX5vryS4qIqm6mmV/+Qs6nc6MEQpRR6btFcJE8Z99hk1aWruSOoCPmxth\nNjZ8/M471NTUmCk6IdpHErvocc6dO0fS7t1E+fubpb6APn1QMjP5audOs9QnRHtJYhc9iqIo7Ny8\nmcG9eqFpRZt6S4b7+XFg+3YqKirMVqcQbdViYk9ISCAsLIyQkBBWrlzZ6P34+HgiIyOJioritttu\nY+/evRYJVAhzyMrKIu/SJfzc3c1ar71Wi7tez4nvvjNrvUK0RbOJ3WAwsGzZMhISEkhOTiYuLo5z\n5841KDNp0iSSkpI4deoUH374IY8//rhFAxaiPc7+8ANeKpVFBhj1d3Xl5KFDZq9XiNZqNrEfO3aM\n4OBgAgIC0Gq1zJ07l/j4+AZlnJyc6n8uKyvD09PTMpEKYQap58/j4exskbo9XFzIvHwZo9FokfqF\nMFWziT0rKwv/n9xg0ul0ZGVlNSq3ZcsWwsPDmTZtGv/+97/NH6UQZpKVmoq7hRK7rUaDVq+nqKjI\nIvULYapmE7upX1dnz57NuXPn2LZtGw8//LBZAhPCEqqrqlo1EKm1bFQqqqurLVa/EKZodhIwPz8/\nMjIy6p9nZGQ0Owhj/Pjx6PV6CgoK8PDwaPR+bGxs/c/R0dFER0e3PmIh2kFtY4PRwgPlbCz4j0NY\nv8TERBITE9tVR7MjT/V6PaGhoezZswdfX19GjRpFXFwc4eHh9WVSUlLqZ7s7efIk999/PykpKY13\nJCNPRRfw9xUr6F9cTB9XV7PXbVQUdmRk8PJbb2Fvb2/2+kXP1Jbc2ewVu0ajYfXq1cTExGAwGFi8\neDHh4eGsWbMGgKVLl7J582bWrVuHVqvF2dmZjRs3tv0IhLCwgNBQ8vfssUhiL66owN3LS5K66HQy\nV4zoUZKSktj6xhuMDwgwe90/ZGbiPWkS982da/a6Rc8lc8UI0YKIiAiqXFworaw0a71GRSHTYGDs\n+PFmrVeItpDELnoUrVbL+KlTOZuba9Z6U3Jz8YuIwNfX16z1CtEWsjReD1JTU0PSmSQyr6ZSXlmC\nWm2Dk4MLQQGhhIeH95jeHBMnT+bEwYNkFBTg30TvrdYqr67mYm0tTz/8sCyZJ7oEaWPvAfLy8jhy\n/BAnvt+PR4AKv2BX7B20GI0KVRU1pCUXU1lgz9jhkxh52yhcLXBjsatJTU3l7RdfZKyHB71/Mnq6\ntWr0eg6kpXH3woVMmDjRjBEKUUcW2hCNfHfiONv2fkzwCBcihutw6eXYZLnCvBLOHs8k86yBh+59\ngqCgoA6OtOOdPn2auFWrGOHm1qZeMpU1NRzMyGDE7Nn87N575WpdWIQkdtHAt4e+Ye93m4iZH46b\nh2nD6K+mF5D4aSpz7/kVYWFhFo6w8507d471b7+NZ3k5Q/z8ml3v9AZFUbh87RoXqquJefBBJk6a\nJEldWIwkdlHvh7M/sPmrd5i5eDDOrg6t2jb3ahG7P7nC4/P/gF87VxjqDsrKyvhi0ya+//ZbfFQq\nAjw86OXoiPonyVpRFMqrq8koKCCjthbPkBDmLlwoN0uFxUliFwAYjUZWrvor4+5zx8e/bTcHk0+l\nUfhDHxY9/ISZo+u68vPzOXroEKcOHqTo2jWcVCq0ajUGRaHCaMTO1ZXwqCjGRUfTv39/uUoXHcLs\nI09F93Tx4kVsXMrw8Q9pcx0Dh+jYuPvkLef9sUaenp7MmDWLGbNmUVlZSV5eHrW1tdjY2ODu7o6L\ni4skc9EtSGK3QoeOJxI2sn3JWKOxISjKlaPfHWZ6zD1miqz7cHBwoF+/fp0dhhBtIgOUrEx5eTmX\nM78neFD728YjbtNx4sw3ZohKCNGRJLFbmbKyMhxcNWg07R9s5NrbkfLKElkRSIhuRhK7lampqUGj\nNc+vVaVSYaNVUVNTY5b6hBAdQxK7lbGzs0NfY54rbEVR0Nco2NramqU+IUTHkMRuZVxcXKgo0VNT\no293XUX5pbg690ZtwqAdIUTXIWeslXFwcCA88DYunMlsd13JJ7IYHSXznwjR3Uhit0JjR97FheMF\n7RoQVlOj50pSGSNvG2XGyIQQHUESuxUaMGAAtnpPMi7ntbmO5JNphPYfTq9evcwYmRCiI0hit0Iq\nlYqfT5/PN1+kU5hf2urtM67kce6bCmLunmmB6IQQlmZSYk9ISCAsLIyQkBBWrlzZ6P3169cTGRnJ\n0KFDuf322zlz5ozZAxWtExQUxOxJC0n46Dy5V4tM3u7yhWwO/DeTBfcvo0+fPhaMUAhhKS0mdoPB\nwLJly0hISCA5OZm4uDjOnTvXoExgYCAHDhzgzJkzPP/88zz++OMWC7izJCYmdnYIrRY1bDgPTP81\nez5JZ80rO8nLud5kOUVRyEzN4+v/fs+J7SU8Pv/3BFhgsee26o6f/U9J/J2ru8ffFi0m9mPHjhEc\nHExAQABarZa5c+cSHx/foMzYsWPr22JHjx5NZmb7e2R0Nd31jyM8PJxnfvUiBRftOBCXx5a1pzi2\n/zxnjl3m9JFLHN57js/eOsnpHVWMDPgFzyx7octN1dtdP/sbJP7O1d3jb4sWJwHLysrC39+//rlO\np+Po0aO3LL927VqmT59unuiEWTg7OxPQfwDP/vav/Pjjj2RmZVCRV4pKZYOngwt3zQiUaWiFsCIt\nJvbWnOz79u3j/fff5+DBg+0KSliGWq0mLCysR6yMJESPprTg8OHDSkxMTP3zV155RXnttdcalUtK\nSlKCgoKUixcvNllPUFCQAshDHvKQhzxa8QgKCmopTTfS4gpKer2e0NBQ9uzZg6+vL6NGjSIuLo7w\n8PD6Munp6UycOJFPPvmEMWPGNFedEEIIC2uxKUaj0bB69WpiYmIwGAwsXryY8PBw1qxZA8DSpUt5\n8cUXKSoq4okn6pZR02q1HDt2zLKRCyGEaFKHrXkqhBCiY1hs5GlhYSGTJ09m4MCBTJkyhevXG/eh\nzsjIYMKECQwaNIjBgwfz73//21LhmKSlgVgATz75JCEhIURGRnLq1KkOjrB53X0gmSmfP8Dx48fR\naDR8/vnnHRhdy0yJPzExkaioKAYPHkx0dHTHBtiCluLPz89n6tSpDBs2jMGDB/Phhx92fJC3sGjR\nIry8vBgyZMgty3Tlc7el+Ft97ra6Vd5Ev//975WVK1cqiqIor732mvLss882KpOdna2cOnVKURRF\nKS0tVQYOHKgkJydbKqRm6fV6JSgoSLly5YpSU1OjREZGNoplx44dyrRp0xRFUZQjR44oo0eP7oxQ\nm2RK/IcOHVKuX7+uKIqi7Ny5s9vFf6PchAkTlBkzZiifffZZJ0TaNFPiLyoqUiIiIpSMjAxFURQl\nLy+vM0Jtkinxv/DCC8of//hHRVHqYnd3d1dqa2s7I9xGDhw4oJw8eVIZPHhwk+935XNXUVqOv7Xn\nrsWu2Ldu3cqCBQsAWLBgAVu2bGlUxtvbm2HDhgF1fa3Dw8O5evWqpUJqlikDsX56TKNHj+b69evk\n5uZ2RriNdPeBZKbED/Dmm29y3333dbnpDkyJf8OGDcyZMwedTgeAp6dnZ4TaJFPi9/HxoaSkBICS\nkhI8PDzQaFq8Tdchxo8fj5ub2y3f78rnLrQcf2vPXYsl9tzcXLy8vADw8vJq8UNMTU3l1KlTjB49\n2lIhNaupgVhZWVktlukqydGU+H+qqw0kM/Xzj4+Pr79J35UGVJkS/8WLFyksLGTChAmMGDGCjz/+\nuKPDvCVT4l+yZAlnz57F19eXyMhIVq1a1dFhtllXPndby5Rzt13/bidPnkxOTk6j119++eUGz1Uq\nVTsh/fAAAALzSURBVLMnYVlZGffddx+rVq3C2dm5PSG1malJQrnpXnNXSS7dfSCZKfEvX76c1157\nDZVKhaIo7Zpv3txMib+2tpaTJ0+yZ88eKioqGDt2LGPGjCEkJKQDImyeKfG/8sorDBs2jMTERFJS\nUpg8eTJJSUm4uLh0QITt11XP3dYw9dxtV2L/+uuvb/mel5cXOTk5eHt7k52dTd++fZssV1tby5w5\nc3jooYeYPXt2e8JpFz8/PzIyMuqfZ2Rk1H9lvlWZzMzMLjOviinxA5w5c4YlS5aQkJDQ7Fe/jmZK\n/CdOnGDu3LlA3Y28nTt3otVqmTVrVofG2hRT4vf398fT0xMHBwccHBy48847SUpK6hKJ3ZT4Dx06\nxJ///GegbvbQAQMGcOHCBUaMGNGhsbZFVz53TdWqc9esdwB+4ve//339CNVXX321yZunRqNRefjh\nh5Xly5dbKgyT1dbWKoGBgcqVK1eU6urqFm+eHj58uEvdgDEl/rS0NCUoKEg5fPhwJ0V5a6bE/1OP\nPvqosnnz5g6MsHmmxH/u3Dnl7rvvVvR6vVJeXq4MHjxYOXv2bCdF3JAp8T/11FNKbGysoiiKkpOT\no/j5+SkFBQWdEW6Trly5YtLN06527t7QXPytPXctltgLCgqUu+++WwkJCVEmT56sFBUVKYqiKFlZ\nWcr06dMVRVGUb775RlGpVEpkZKQybNgwZdiwYcrOnTstFVKLvvzyS2XgwIFKUFCQ8sorryiKoijv\nvPOO8s4779SX+fWvf60EBQUpQ4cOVU6cONFZoTappfgXL16suLu713/WI0eO7MxwGzHl87+hqyV2\nRTEt/tdff12JiIhQBg8erKxataqzQm1SS/Hn5eUp99xzjzJ06FBl8ODByvr16zsz3Abmzp2r+Pj4\nKFqtVtHpdMratWu71bnbUvytPXdlgJIQQlgZWRpPCCGsjCR2IYSwMpLYhRDCykhiF0IIKyOJXQgh\nrIwkdiGEsDKS2IUQwspIYhdCCCvz/wHy0On2yaynVwAAAABJRU5ErkJggg==\n",
"text": [
"<matplotlib.figure.Figure at 0x39a6c90>"
]
}
],
"prompt_number": 48
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# 3.4 Pandas\n",
"\n",
"* Used for manipulating tabular data \n",
" * SQL query output\n",
" * CSV\n",
"* Has many features for time series\n",
"* Allows very expressive syntax\n",
"* Provides a Data Frame structure similar to that in **R**\n",
"* Has NumPy at the core, so can be very fast\n",
"\n",
"[Link](http://pandas.pydata.org/)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"# Example: Kinsey Reporter's timelines\n",
"\n",
"**TASK**: Calculate how many responses [Kinsey Reporter](https://kinseyreporter.org) received, with *weekly* resolution, for a given tag.\n",
"\n",
"* Reports come in, and each report has one or more tags associated with it.\n",
"* First, we need to do a SQL query to get all the reports associated with a specific tag (don't worry if you're not familiar with SQL)\n",
"\n",
" SELECT `option`, \n",
" DATE(timestamp) as datestamp, \n",
" count(1) as num_answers\n",
" FROM survey_event, survey_answer, survey_option\n",
" WHERE event_id = survey_event.id\n",
" AND option_id = survey_option.id\n",
" GROUP BY datestamp"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"The results come to Python looking like this:\n",
"\n",
"\n",
" [\n",
" ...\n",
" ('smile flirt', datetime.date(2013,5,23), 12),\n",
" ('smile flirt', datetime.date(2013,5,24), 9),\n",
" ...\n",
" ]"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"To calculate the weekly timeline with native Python would be... uncomfortable. One must:\n",
"\n",
"1. Fill in any missing days with zeros\n",
"2. Sort the list by date, go through and sum up every set of seven counts"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"With Pandas, it's as simple as:\n",
" \n",
" import pandas as pd\n",
" \n",
" df = pd.DataFrame.from_records(kr_rows, index=datestamp)\n",
" timeline = df['num_answers'].asfreq('D').resample('W', how=sum).fillna(0)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"#Example: Auto MPG analysis\n",
"\n",
"In addition to making time series easier, Pandas makes plotting a snap too.\n",
"\n",
"This is a notebook where I slice and dice some automobile gas mileage data: [https://www.wakari.io/sharing/bundle/clayadavis/mpg](https://www.wakari.io/sharing/bundle/clayadavis/mpg)\n",
"\n",
"Key concepts used in the MPG analysis:\n",
"\n",
"* `DataFrame.group_by()`\n",
"* `Series.describe()`\n",
"* `Series.plot()`\n",
"* `DataFrame.boxplot()`\n",
"* `DataFrame.hist()`\n",
"* `Series.rolling_mean()`\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# 3.5 Sympy\n",
"\n",
"* Symbolic math library\n",
"* Do all that algebra/calculus you're terrible at!\n",
" * Simplification\n",
" * Expansion\n",
" * Integration\n",
" * Differentiation\n",
" * etc.\n",
"* If output supports it (e.g. IPython notebook), prints LaTeX or unicode output\n",
"* Use it to replace **Mathematica**\n",
"\n",
"[Link](http://sympy.org/en/index.html)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"# Example: Differentiation"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"import sympy\n",
"sympy.init_printing(use_latex=True) ##or use_unicode=True in a console\n",
"x, y = sympy.symbols('x y')"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"prompt_number": 93
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"We differentiate and get an answer..."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"sympy.diff(sympy.exp(x**2), x)"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"latex": [
"$$2 x e^{x^{2}}$$"
],
"metadata": {},
"output_type": "pyout",
"prompt_number": 74,
"text": [
" \u239b 2\u239e\n",
" \u239dx \u23a0\n",
"2\u22c5x\u22c5\u212f "
]
}
],
"prompt_number": 74
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"...or we can create an unevaluated expression for further manipulation..."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"my_deriv = sympy.Derivative(sympy.exp(x**2), x, x)\n",
"my_deriv"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"latex": [
"$$\\frac{d^{2}}{d x^{2}} e^{x^{2}}$$"
],
"metadata": {},
"output_type": "pyout",
"prompt_number": 75,
"text": [
" 2\u239b \u239b 2\u239e\u239e\n",
" d \u239c \u239dx \u23a0\u239f\n",
"\u2500\u2500\u2500\u239d\u212f \u23a0\n",
" 2 \n",
"dx "
]
}
],
"prompt_number": 75
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"...which we can evaluate later."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"my_deriv.doit()"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"latex": [
"$$2 \\left(2 x^{2} + 1\\right) e^{x^{2}}$$"
],
"metadata": {},
"output_type": "pyout",
"prompt_number": 76,
"text": [
" \u239b 2\u239e\n",
" \u239b 2 \u239e \u239dx \u23a0\n",
"2\u22c5\u239d2\u22c5x + 1\u23a0\u22c5\u212f "
]
}
],
"prompt_number": 76
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"# More Sympy examples"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"sympy.Integral(sympy.exp(-x**2 - y**2), x, y)"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"latex": [
"$$\\iint e^{- x^{2} - y^{2}}\\, dx\\, dy$$"
],
"metadata": {},
"output_type": "pyout",
"prompt_number": 82,
"text": [
"\u2320 \u2320 \n",
"\u23ae \u23ae 2 2 \n",
"\u23ae \u23ae - x - y \n",
"\u23ae \u23ae \u212f dx dy\n",
"\u2321 \u2321 "
]
}
],
"prompt_number": 82
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"from sympy import oo\n",
"sympy.integrate(sympy.exp(-x**2 - y**2), (x, -oo, oo), (y, -oo, oo))"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"latex": [
"$$\\pi$$"
],
"metadata": {},
"output_type": "pyout",
"prompt_number": 84,
"text": [
"\u03c0"
]
}
],
"prompt_number": 84
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"sympy.solve([x*y - 7, x + y - 6], [x, y])"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"latex": [
"$$\\begin{bmatrix}\\begin{pmatrix}- \\sqrt{2} + 3, & \\sqrt{2} + 3\\end{pmatrix}, & \\begin{pmatrix}\\sqrt{2} + 3, & - \\sqrt{2} + 3\\end{pmatrix}\\end{bmatrix}$$"
],
"metadata": {},
"output_type": "pyout",
"prompt_number": 83,
"text": [
"\u23a1\u239b ___ ___ \u239e \u239b ___ ___ \u239e\u23a4\n",
"\u23a3\u239d- \u2572\u2571 2 + 3, \u2572\u2571 2 + 3\u23a0, \u239d\u2572\u2571 2 + 3, - \u2572\u2571 2 + 3\u23a0\u23a6"
]
}
],
"prompt_number": 83
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"#OMFG Example: [Sympy Gamma](http://www.sympygamma.com/input/?i=integrate%28exp%28x%29*cos%28x%29%2C+x%29)\n",
"\n",
"* Use it to replace Wolfram Alpha **PRO**"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"![](files/patrick.jpg)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# 3.x Honorable SciPy mention: scikit-learn\n",
" \n",
"Mature and featureful library for machine learning. [Link](http://scikit-learn.org/stable/)\n",
"\n",
"![](files/sklearn.png)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "skip"
}
},
"source": [
"# 4. Make web GUIs\n",
"\n",
"* As a community, we've focused on creating awesome tools for data analysis\n",
"* Less attention has been paid to sharing workflows once created\n",
" * IPython notebook is a huge step in the right direction\n",
"* GUIs are cool, they lower the barrier of entry"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "skip"
}
},
"source": [
"Some truths about GUIs\n",
"\n",
"* GUIs suck to program\n",
"* For 90% of use cases, a web GUI on a modern browser is as good as native\n",
"* 90% of (data) scientists want the same thing from a GUI:\n",
" * Give me knobs to twiddle\n",
" * Let me see how it affects the output"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "skip"
}
},
"source": [
"# A modest proposal\n",
"\n",
"### Comprehensive GUI frameworks exist already. \n",
"\n",
"### There is room for domain-specific GUI frameworks that sacrifice generality for speed and ease of use."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "skip"
}
},
"source": [
"# Enter Ashiba\n",
"\n",
"* A framework for making webapps with Python at their core\n",
" * GUI elements defined in HTML or Enaml\n",
" * No JavaScript needed\n",
"* (almost) free software\n",
"* Backed by Continuum Analytics"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "skip"
}
},
"source": [
"Why it rocks:\n",
" \n",
"* Uses familiar Python libraries on the backend\n",
" * Pandas\n",
" * Numpy\n",
" * Matplotlib\n",
"* Allows rapid development of web applications from existing Python code\n",
"* Moves beyond \"open data\" -- share both the data and a framework to analyze it\n",
"* Useful at every stage of te research process\n",
" * Exploring data and forming hypotheses\n",
" * Eliciting collaboration and feedback from peers\n",
" * Enabling wide dialog and evaluation of the finished product"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "skip"
}
},
"source": [
"#DEMOS\n",
"\n",
"![](files/spongebob.gif)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"#Fin\n",
"\n",
"Thanks for your time. Hit me up on [Twitter](https://twitter.com/clayadavis) or email if you have any questions."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "skip"
}
},
"source": [
"# 5. Profile and Compile\n",
"\n",
"Rule 1: \"Premature optimization is the root of all evil\" $-$ Knuth\n",
"\n",
"Rule 2: Post-hoc optimization is fucking rad"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "skip"
}
},
"source": [
"## The broad view\n",
"\n",
"* My time is more valuable than CPU time.\n",
"* Optimization is only useful when it lets me do something otherwise impossible with the resources I have."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "skip"
}
},
"source": [
"# 5.1: Profile to find hot loops"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "skip"
}
},
"source": [
"# 5.2 Use Numba to compile hot loops"
]
}
],
"metadata": {}
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment