├── .devcontainer └── devcontainer.json ├── .gitignore ├── Dockerfile ├── README.md ├── notebook.ipynb ├── requirements.txt ├── setup-fte.R └── setup.R /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | // For format details, see https://aka.ms/devcontainer.json. For config options, see the 2 | // README at: https://github.com/devcontainers/templates/tree/main/src/python 3 | { 4 | "name": "Python 3", 5 | // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile 6 | "image": "mcr.microsoft.com/devcontainers/python:1-3.11-bullseye", 7 | "customizations": { 8 | "vscode": { 9 | "extensions": [ 10 | "GitHub.copilot", 11 | "ms-python.python", 12 | "ms-python.vscode-pylance", 13 | "cweijan.vscode-office", 14 | "ms-toolsai.jupyter" 15 | ] 16 | } 17 | }, 18 | 19 | // Features to add to the dev container. More info: https://containers.dev/features. 20 | // "features": {}, 21 | 22 | // Use 'forwardPorts' to make a list of ports inside the container available locally. 23 | // "forwardPorts": [], 24 | 25 | // Use 'onCreateCommand' to run commands when the container is created. 26 | "onCreateCommand": "sh setup.sh", 27 | 28 | // Configure tool-specific properties. 29 | // "customizations": {}, 30 | 31 | // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. 32 | // "remoteUser": "root", 33 | 34 | // Minimum requriements for machine 35 | "hostRequirements": { 36 | "cpus": 4 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .venv 2 | .DS_Store 3 | .ipynb_checkpoints/ 4 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # syntax=docker/dockerfile:1 2 | 3 | FROM python:bullseye 4 | ENV DEBIAN_FRONTEND noninteractive 5 | 6 | COPY . . 7 | 8 | RUN apt-get update 9 | 10 | RUN apt-get install -y r-base \ 11 | libharfbuzz-dev \ 12 | libfribidi-dev \ 13 | libfreetype6-dev \ 14 | libpng-dev \ 15 | libtiff5-dev \ 16 | libjpeg-dev 17 | 18 | RUN Rscript setup.R 19 | 20 | RUN pip install -r requirements.txt 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Jupyter Quickstart 2 | 3 | A Jupyter notebook that mixes Python3 and R. 4 | 5 | ## Example Notebook 6 | 7 | https://nbviewer.jupyter.org/github/dmil/jupyter-quickstart/blob/master/notebook.ipynb 8 | 9 | ## Requirements 10 | 11 | * Homebrew 12 | * Python 3 13 | 14 | ## Quickstart 15 | 16 | 1. Install some packages with [HomeBrew](https://brew.sh/) 17 | 18 | ```bash 19 | brew install r 20 | brew install libgit2 21 | ``` 22 | 23 | 2. Clone the repo and `cd` into the folder you cloned 24 | 25 | 3. Install R and python packages 26 | 27 | ```bash 28 | RScript setup.R 29 | pip3 install -r requirements.txt 30 | ``` 31 | 32 | 4. Open the jupyter notebook 33 | 34 | ```bash 35 | jupyter notebook notebook.ipynb 36 | ``` 37 | 38 | ## Additional steps for FiveThirtyEight Writers 39 | 40 | See additional setup instructions inside `setup-fte.R`. 41 | -------------------------------------------------------------------------------- /notebook.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Python and R\n", 8 | "\n", 9 | "This setup allows you to use *Python* and *R* in the same notebook.\n", 10 | "\n", 11 | "To set up a similar notebook, see quickstart instructions here:\n", 12 | "\n", 13 | "https://github.com/dmil/jupyter-quickstart\n", 14 | "\n", 15 | "Some thoughts on why I like this setup and how I use it at the [end](notebook.ipynb#Thoughts) of this notebook." 16 | ] 17 | }, 18 | { 19 | "cell_type": "code", 20 | "execution_count": 1, 21 | "metadata": {}, 22 | "outputs": [], 23 | "source": [ 24 | "%load_ext rpy2.ipython\n", 25 | "%load_ext autoreload\n", 26 | "%autoreload 2\n", 27 | "\n", 28 | "%matplotlib inline \n", 29 | "from matplotlib import rcParams\n", 30 | "rcParams['figure.figsize'] = (16, 100)\n", 31 | "\n", 32 | "import warnings\n", 33 | "from rpy2.rinterface import RRuntimeWarning\n", 34 | "warnings.filterwarnings(\"ignore\") # Ignore all warnings\n", 35 | "# warnings.filterwarnings(\"ignore\", category=RRuntimeWarning) # Show some warnings\n", 36 | "\n", 37 | "import pandas as pd\n", 38 | "import numpy as np\n", 39 | "import matplotlib.pyplot as plt\n", 40 | "from IPython.display import display, HTML" 41 | ] 42 | }, 43 | { 44 | "cell_type": "code", 45 | "execution_count": 2, 46 | "metadata": {}, 47 | "outputs": [ 48 | { 49 | "data": { 50 | "application/javascript": [ 51 | "// Disable auto-scrolling\n", 52 | "IPython.OutputArea.prototype._should_scroll = function(lines) {\n", 53 | " return false;\n", 54 | "}\n" 55 | ], 56 | "text/plain": [ 57 | "" 58 | ] 59 | }, 60 | "metadata": {}, 61 | "output_type": "display_data" 62 | } 63 | ], 64 | "source": [ 65 | "%%javascript\n", 66 | "// Disable auto-scrolling\n", 67 | "IPython.OutputArea.prototype._should_scroll = function(lines) {\n", 68 | " return false;\n", 69 | "}" 70 | ] 71 | }, 72 | { 73 | "cell_type": "markdown", 74 | "metadata": {}, 75 | "source": [ 76 | "This is a Python notebook, but below is an R cell. The `%%R` at the top of the cell indicates that the code in this cell will be R code." 77 | ] 78 | }, 79 | { 80 | "cell_type": "code", 81 | "execution_count": 3, 82 | "metadata": {}, 83 | "outputs": [ 84 | { 85 | "name": "stderr", 86 | "output_type": "stream", 87 | "text": [ 88 | "R[write to console]: Loading required package: tidyverse\n", 89 | "\n" 90 | ] 91 | }, 92 | { 93 | "name": "stdout", 94 | "output_type": "stream", 95 | "text": [ 96 | "── Attaching packages ─────────────────────────────────────── tidyverse 1.3.2 ──\n", 97 | "✔ ggplot2 3.4.1 ✔ purrr 1.0.1\n", 98 | "✔ tibble 3.1.8 ✔ dplyr 1.1.0\n", 99 | "✔ tidyr 1.3.0 ✔ stringr 1.5.0\n", 100 | "✔ readr 2.1.3 ✔ forcats 0.5.1\n", 101 | "── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──\n", 102 | "✖ dplyr::filter() masks stats::filter()\n", 103 | "✖ dplyr::lag() masks stats::lag()\n" 104 | ] 105 | } 106 | ], 107 | "source": [ 108 | "%%R\n", 109 | "\n", 110 | "# My commonly used R imports\n", 111 | "\n", 112 | "require('tidyverse')" 113 | ] 114 | }, 115 | { 116 | "cell_type": "markdown", 117 | "metadata": {}, 118 | "source": [ 119 | "Below is a Python cell, there is nothing at the top of the cell because it is python by default." 120 | ] 121 | }, 122 | { 123 | "cell_type": "code", 124 | "execution_count": 4, 125 | "metadata": {}, 126 | "outputs": [ 127 | { 128 | "data": { 129 | "text/html": [ 130 | "
\n", 131 | "\n", 144 | "\n", 145 | " \n", 146 | " \n", 147 | " \n", 148 | " \n", 149 | " \n", 150 | " \n", 151 | " \n", 152 | " \n", 153 | " \n", 154 | " \n", 155 | " \n", 156 | " \n", 157 | " \n", 158 | " \n", 159 | " \n", 160 | " \n", 161 | " \n", 162 | " \n", 163 | " \n", 164 | " \n", 165 | " \n", 166 | " \n", 167 | " \n", 168 | " \n", 169 | " \n", 170 | " \n", 171 | " \n", 172 | " \n", 173 | " \n", 174 | " \n", 175 | " \n", 176 | " \n", 177 | " \n", 178 | " \n", 179 | "
AB
017
11041
2361
3797
48040
\n", 180 | "
" 181 | ], 182 | "text/plain": [ 183 | " A B\n", 184 | "0 1 7\n", 185 | "1 10 41\n", 186 | "2 36 1\n", 187 | "3 79 7\n", 188 | "4 80 40" 189 | ] 190 | }, 191 | "execution_count": 4, 192 | "metadata": {}, 193 | "output_type": "execute_result" 194 | } 195 | ], 196 | "source": [ 197 | "# EXAMPLE PYTHON CELL\n", 198 | "\n", 199 | "# create a dataframe of random numbers with two columns, A and B\n", 200 | "df = pd.DataFrame(\n", 201 | " np.random.randint(0,100,size=(100, 2)), columns=list('AB'))\n", 202 | "\n", 203 | "# display first 5 rows\n", 204 | "df.head(5)" 205 | ] 206 | }, 207 | { 208 | "cell_type": "markdown", 209 | "metadata": {}, 210 | "source": [ 211 | "Now another R cell, `%%R -i df` indicates that this is an R cell and imports the dataframe from Python. This is one way to pass data back and forth from R to Python. Another is to write a CSV file in Python and read it in R (or vice versa)" 212 | ] 213 | }, 214 | { 215 | "cell_type": "code", 216 | "execution_count": 5, 217 | "metadata": {}, 218 | "outputs": [ 219 | { 220 | "data": { 221 | "image/png": "iVBORw0KGgoAAAANSUhEUgAAAeAAAAHgCAYAAAB91L6VAAAEDmlDQ1BrQ0dDb2xvclNwYWNlR2VuZXJpY1JHQgAAOI2NVV1oHFUUPpu5syskzoPUpqaSDv41lLRsUtGE2uj+ZbNt3CyTbLRBkMns3Z1pJjPj/KRpKT4UQRDBqOCT4P9bwSchaqvtiy2itFCiBIMo+ND6R6HSFwnruTOzu5O4a73L3PnmnO9+595z7t4LkLgsW5beJQIsGq4t5dPis8fmxMQ6dMF90A190C0rjpUqlSYBG+PCv9rt7yDG3tf2t/f/Z+uuUEcBiN2F2Kw4yiLiZQD+FcWyXYAEQfvICddi+AnEO2ycIOISw7UAVxieD/Cyz5mRMohfRSwoqoz+xNuIB+cj9loEB3Pw2448NaitKSLLRck2q5pOI9O9g/t/tkXda8Tbg0+PszB9FN8DuPaXKnKW4YcQn1Xk3HSIry5ps8UQ/2W5aQnxIwBdu7yFcgrxPsRjVXu8HOh0qao30cArp9SZZxDfg3h1wTzKxu5E/LUxX5wKdX5SnAzmDx4A4OIqLbB69yMesE1pKojLjVdoNsfyiPi45hZmAn3uLWdpOtfQOaVmikEs7ovj8hFWpz7EV6mel0L9Xy23FMYlPYZenAx0yDB1/PX6dledmQjikjkXCxqMJS9WtfFCyH9XtSekEF+2dH+P4tzITduTygGfv58a5VCTH5PtXD7EFZiNyUDBhHnsFTBgE0SQIA9pfFtgo6cKGuhooeilaKH41eDs38Ip+f4At1Rq/sjr6NEwQqb/I/DQqsLvaFUjvAx+eWirddAJZnAj1DFJL0mSg/gcIpPkMBkhoyCSJ8lTZIxk0TpKDjXHliJzZPO50dR5ASNSnzeLvIvod0HG/mdkmOC0z8VKnzcQ2M/Yz2vKldduXjp9bleLu0ZWn7vWc+l0JGcaai10yNrUnXLP/8Jf59ewX+c3Wgz+B34Df+vbVrc16zTMVgp9um9bxEfzPU5kPqUtVWxhs6OiWTVW+gIfywB9uXi7CGcGW/zk98k/kmvJ95IfJn/j3uQ+4c5zn3Kfcd+AyF3gLnJfcl9xH3OfR2rUee80a+6vo7EK5mmXUdyfQlrYLTwoZIU9wsPCZEtP6BWGhAlhL3p2N6sTjRdduwbHsG9kq32sgBepc+xurLPW4T9URpYGJ3ym4+8zA05u44QjST8ZIoVtu3qE7fWmdn5LPdqvgcZz8Ww8BWJ8X3w0PhQ/wnCDGd+LvlHs8dRy6bLLDuKMaZ20tZrqisPJ5ONiCq8yKhYM5cCgKOu66Lsc0aYOtZdo5QCwezI4wm9J/v0X23mlZXOfBjj8Jzv3WrY5D+CsA9D7aMs2gGfjve8ArD6mePZSeCfEYt8CONWDw8FXTxrPqx/r9Vt4biXeANh8vV7/+/16ffMD1N8AuKD/A/8leAvFY9bLAAAAOGVYSWZNTQAqAAAACAABh2kABAAAAAEAAAAaAAAAAAACoAIABAAAAAEAAAHgoAMABAAAAAEAAAHgAAAAAKWfY0oAAEAASURBVHgB7Z0HeBRV18cPnRBKqKFX6V26SEdABAsgRQVBFBVfRRRQEVEEERUbih1B5QWR3ouAiCgiVUDpvYQWkAQSQiif//s+s98mbMiWmdkp//s8yc7Mztx7zu/Mzpnbzs1w/d8kTCRAAiRAAiRAAqYSyGhqaSyMBEiABEiABEhAEaAD5o1AAiRAAiRAAmEgQAccBugskgRIgARIgATogHkPkAAJkAAJkEAYCGQOQ5l+FRkfH+/Xeb5Oypgxo2BsmRPGl2XIkMExesBWtImvOzZ8x/BbuXbtWvgE0Klkp/xOgCNTpkxy9epVnciENxun2CXU30nWrFklW7ZsNxjDsg74woULNwjr74F8+fJJQkKCXLp0yd9LLHterly5JBQWVlEsZ86cgps4lBcrq+jiFJvgoZA7d245c+aMVdAGLUdERIRcvnzZEY6rSJEiEhMTEzQLq1yIFwncY4mJiVYRKWg5ChQoIHFxceoeCyYTPP98OWA2QQdDk9eQAAmQAAmQQIgE6IBDBMjLSYAESIAESCAYAnTAwVDjNSRAAiRAAiQQIgE64BAB8nISIAESIAESCIYAHXAw1HgNCZAACZAACYRIgA44RIC8nARIgARIgASCIUAHHAw1XkMCJEACJEACIRKgAw4RIC8nARIgARIggWAI0AEHQ43XkAAJkAAJkECIBOiAQwTIy0mABEiABEggGAJ0wMFQ4zUkQAIkQAIkECIB3R1wUlKSHDhwwCPWlStX5M8//5RTp055jl28eFE2btwo+GQiARIgARIgATcS0NUBYwGEkSNHytKlSxVLrHwzbNgw2b59u4wYMUL27dsnZ8+elSFDhsiuXbtk8ODBAofNRAIkQAIkQAJuI6DrakiffPKJlClTRpKTkxVHOFms7PHggw9KrVq1ZMGCBVKoUCHp1q2bNG3aVC2Dtm7dOrXtNvDUlwRIgARIwN0EdHXAgwYNki1btsjvv/+uqGJJLThgpOjoaDl58qRaLqxu3bopjqmdf//169dPfvnlF7WLZussWbJoXwX8iWWwnJIiIyOdoorkyJHDEbo4ySaFCxd2hE2cpISTbJInTx5HmAbL3Aab0lqSUVcHnFo470WMscA01kP0dUy77t133/XUntFUjcWcg0lRUVFqDUonNG/jQe+EvnLo4ZT1gJ1iE7ykYp1S/NbsnrJnz67War127ZrdVVGVFe8xM3ZVCL933GNOWJcdzhfrsmPN6WBSWhUPQx1wqVKl5LffflPyHjx4UEqWLClwjhikVbFiRcGxhg0bevTBQudaQu0ZfcjBJlzrhB8j9HeCHrCHXjaJj4+XMWPGyI4dO6RLly7ywAMPBHubBH2dE2yi6aB9Bg3DAhfqcX8dPXpU3nnnHTl8+LC89NJLUr9+/bBpFi6b4Hn99ddfy7lz5+Tjjz/2tGAGAwIVKL1+88GUr/c1sInedjHUAZcuXVoKFCigBmCdOXNGRo8eLZkyZZKxY8fK2rVrVY0YfcNMJOAvAfwAbr/9domNjVU/hs2bNwte3Dp27OhvFjyPBG4ggJc6b4fbo0cPmTNnjlSvXv2Gc516YO/eveqFVtPvrrvukuXLl0soTa9aXvz0TUB3BwyH6u1UH3vsMVVt9+6THT58+A3HfIvHoySQksDx48clIiLC8yaKbgY8JOiAU3LiXmAE/vrrLzVAVGv6RZ/dpk2bXOWAtdZKjRxqrxhI26hRI+0QP3UmoOs0pLRk83a+2jm+jmnf8ZME0iKAt3Hv/hQM1MufP39ap/M4CfhFAINEvcecoKWuRIkSfl3rlJOKFy+uWpM0fTBo1kmDwTS9rPRpigO2ksKUxd4E4HzRR4XP8uXLq/5fzDVnIoFQCGD6JLrGMGIX41NefPFFadmyZShZBnwtulcmTpwonTt3FgxIRQ3UzAR9+/btq7oN0fQ+bdo0Na3UTBncVlaGf41srpX9JIxBWMEm1JIQFMQJo+/Qv4n+KbsnjLbFqMi4uDi7q6JqCU6wCVqhcufOLRifYfeEbgmMUMVsC7umoUOHyvfff6+eW7DNs88+q/7sqg9aEaBHWlNw7KQXxjLh2RXsKGg8/7wHGWu6swaskeAnCZAACYSRAGIgaJUGPOgXL14cRmlYtBkE6IDNoMwySIAESCAdApUrV05xBuadMjmbAB2ws+1L7UiABGxC4M033/SMbahXr57Mnz/fJpJTzGAJ6D4NKVhBeB0JkAAJuJkARvNjLi7C94YyBsbNDO2mO2vAdrMY5SUBEiABEnAEATpgR5iRSpAACZAACdiNAJug7WYxymsLArt375Zly5apqF19+vRRU7BsITiFJAESMI0AHbBpqFmQWwggmD/WwD527JhywFjz+rPPPqMTdssNQD1JwE8CbIL2ExRPIwF/CSBSF5wvEoIQbNu2Ta385e/1PI8ESMAdBOiA3WFnamkiAcTPRYxqLZ04cULVhLV9fpIACZAACNAB8z4gAZ0JPPzww1KsWDEVyB4B7jG/E1NLmEjAbgSwLvCUKVNkxowZtg7zaVXu7AO2qmUol20JIC7xmjVr1FJuWDSiVKlSttWFgruXAMJiIiBIcnKyGr/wzjvvyOrVq9U67u6loq/mrAHry5O5kYAigIUnEFqQzpc3hF0JLF26VK27DQeMdbcxnuGPP/6wqzqWlJsO2JJmoVAkQAIkEF4CGMfgPZYBTpjruOtrEzZB68uTuZEACZCAIwi0adNGKlSoIAcOHFCOt1GjRtKgQQNH6GYVJeiArWIJykECJEACFiKQOXNmmTdvnmzatEmwXbNmTQtJ5wxR6ICdYUdqQQIkQAK6E8iQIYPUqVNH93yZ4f8IsA+YdwIJkAAJkAAJhIEAHXAYoLNIEiABEiABEqAD5j1AAiRAAiRAAmEgQAccBugskgRIgARIgATogHkPkAAJkAAJkEAYCNABhwE6iyQBEiCBYAicPn1afvvtNzU3N5jreY21CHAakrXsQWlIgARIwCeBI0eOyN13362+O3nypEyfPl0aN27s81wetAcB1oDtYSdKSQIk4HICTz/9tMDx4g9p5MiRLidif/XpgO1vQ2pAAiTgAgJ58+ZNoWVMTEyKfe7Yj4DrHPD169fl77//lj179tjPWpSYBEjAtQQeeeQRpTuiU+XOnVv69u3rWhZOUdx1fcDdunVTAxji4uKke/fuMmLECKfYknqQAAk4mECTJk3k559/lnXr1knx4sWlefPmDtbWHaq5ygEvXLhQNmzYIFhoGmn+/PnSqVMnBhl3x71OLUnA9gTKly8v+GNyBgFXNUFfvHhRrl696rEcFprGItNMJEACJEACJGA2AVc54GbNmknJkiUlY8aMaqFpLC5dt25ds5mzPBIgARIgARIQVzVBR0dHy6JFi2Ty5MkSGRkpnTt3Vutc8j4gARIgARIgAbMJuMoBA26uXLnkySefNJszyyMBEiABEiCBFARc1QSdQnPukAAJkAAJkEAYCdABhxE+iyYBEiABEnAvATpg99qempMACZAACYSRAB1wGOGzaBIgARIgAfcSoAN2r+2pOQmQAAmQQBgJ0AGHET6LJgESIAEScC8BOmD32p6akwAJkAAJhJEAHXAY4bNoEiABEiAB9xKgA3av7ak5CZAACZBAGAnQAYcRPosmARIgARJwLwHLhqLMmTOnYOHpYFKmTJkkIiJCLbgQzPVWugYLRiB8pt1TlixZlD2doItTbILfCRYmcYJNMmfOrH7v169ft/tPRcnvBJvg+Y17DLaxe8LvJEeOHJItWzZdVbEsmQsXLgStKB72WGZQW/c36IwscCF+iPHx8RaQJDQR8EKFm9gJujjFJniRwMPRCTbBC/fly5dTLDca2h0bvqvxW3GCTeB8cY85YclXON6EhAR1jwVzZ8CmvhKboH1R4TESIAESIAESMJgAHbDBgJk9CZAACZAACfgiQAfsiwqPkQAJkAAJkIDBBOiADQbM7EmABEiABEjAFwE6YF9UeIwESIAESIAEDCZAB2wwYGZPAiRAAiRAAr4I0AH7osJjJEACJEACARPYt2+fPPbYY9K2bVv5+eefA74+1AuSk5Nl1KhR0rFjR3nqqafkypUroWZp6PWWnQdsqNbMnARIgARIQFcCsbGx0qRJE0+effr0kfnz50ulSpU8x4ze6NWrl/z666/K8W7dulUKFy4sr7zyitHFBp0/a8BBo+OFJEACJEACGoGdO3dKwYIFtV0VgGPbtm2efTM2jh496qn1ojb8yy+/mFFs0GXQAQeNjheSAAmQAAloBIoXL65tej7Lli3r2TZjo0aNGp4Qxoi8h2hcVk50wFa2DmUjARIgAZsQKFWqlHz88ceSP39+qVq1qowZM0Zuv/12U6V/++23pWTJkgLHf/fdd8usWbNMLT/QwtgHHCgxnk8CJEACJOCTAPqAtWbncNQ+IyMjZe3atT5ls+JB1oCtaBXKRAIkQAIk4HgCdMCONzEVJAESIAESsCIBNkFb0SoGy7R8+XJZuHChZM+eXUaOHOmI9ToNRsbsScCVBPbs2SPffPONxMXFyauvvqr6d10JwiCl6YANAmvVbOF8+/btKxiij7VgT548KRMmTPCMHLSq3JSLBEjAXAKY19usWTNPoatWrVLBNfLmzes5xo3QCLAJOjR+trt6+vTpyvlCcESJ2b17t5w+fdp2elBgEiABYwmsXr1asmbN6ink+vXrguAWTPoRoAPWj6UtcqpQoYJkyZLFI+uhQ4ckR44cnn1ukAAJkAAIREVFpXg2oBmatV997w02QevL0/K5IT4q+n8vXLigflzjxo2TnDlzWl5upwm4d+9emTlzply7dk0GDhyo+uOdpiP1SZ8A5qlu3rxZGjZsKHfddVf6F5h4RosWLaRTp04yZ84c5YwR4xmBLsxMV69elSlTpqiWOsR3rl+/vpnFG14WHbDhiK1VAAZerVy5UmJiYpTjzZUrl7UEdIE06Ft74IEHBGHz0BqBeYvTpk2TiIgIF2hPFTUCGAA5adIkFbJx9uzZaqBTjx49tK8t8YmFDZ599lk1RgQBNsxOGK+CpvBLly7JvHnz5P3335eWLVuaLYZh5bEJ2jC01s64SJEiQucbHhstWrRIjh07pgrHYDhsI44uk7sIYKGCxMREpfTZs2dlxowZlgRQoECBsI1+Rp8znC8SxqpYlVGwhqMDDpYcryOBIAnkyZMnRd8aHr7shw8Spo0vK126dArpz58/n2KfOyL58uXzYEBsZ7ywOinRATvJmtTFFgTQ11evXj21cgzi1g4bNkwqVqwYkuyoSaGv7NNPPxWrPsg3bNgg48ePV0vUhaSsQy5G3GIkxFAuX768TJ061SGa6afGW2+9pTIDo2rVqskHH3ygX+YWyIl9wBYwAkVwFwHEyIWz3L9/v2TLlk2KFSsWEgAM5GrdurUcP35cLl++LN99951gulmo+YYkVKqLMYf0kUceUc2JaAHA9Lfnn38+1Vnu2kUNeNeuXXLixAllK7aC3Gj/OnXqqNjSaCWCE/aeFnXj2fY7whqw/WxGiR1CACu26OEk//zzT4mPj5ekpCTBXM3Dhw/LihUrLEUJo+21vjzU0BcsWGAp+cIlDMZhoPZL55u2BTD4C4yc5nyhMR1w2nbnNyRgCwKoRXvP7cZoaqtNLStTpkwKltogtBQHuUMCLiNAB+wyg1Nd5xGoUqWK3H///YKl2FCjbtSokdx3330hK/rTTz+pfsmDBw+GnNfgwYMFg2gw+r5o0aJq+k3ImTIDErA5AfYB29yAFJ8EQODFF1+Uzp07qz7gSpUqhRzb+5133lExwhGwBX3MmINZt27doGEXLlxY9fui77dQoULKCQedGS8kAYcQoAN2iCGpBgmgn0yvhIFcCD2opS+//DIkB4x80M9Zq1YtLUt+koDrCbAJ2vW3AAGQwI0EoqOjUxz8559/UuxzhwRIIHQCdMChM7whh59//lkWL14sFy9evOE7HiABOxB44YUXlJhoLsYfQgAykQAJ6EuATdD68pQBAwaoKSCYEoI/BB/AA4yJBOxEAPOK8SJ56tQpQZ9yOOIA24kXZSWBYAiwBhwMtTSuwWhRLHiPSeOo/WIlDwTZZyIBOxJAn3Ljxo3pfO1oPMpsCwJ0wDqbyXv+ZYYMGTzBB3QuhtmRAAmQAAnYnAAdsI4GRGi5Nm3aqGXlEG4PTXdPPvmkjiUwKxIgATsR2L59u2A+9blz5+wkNmU1iQD7gHUGjTU+27dvLwkJCYI4pt41Yp2LYnYkQAIWJvD999/L6NGj1TxqdEth3WfEM2YiAY0Aa8AaCR0/EYmoVatWEhUVpWOuzIoESMBOBF599VU5c+aMGhMCuREPm4kEvAnQAXvT4DYJkAAJ6EQAYTe9U0xMjPcut0mAizHwHiABEiABjcDWrVtl06ZNqtlYOxbs5wMPPCBYehKr+CBON2rEZid0hW3cuFGFATW7bJaXPgH2AafPiGeQAAm4gMDQoUNl6dKlKp42IoEtWrQopCXw+vXrJ1WrVlVzqRGCM/WKUEYjhfPFfG4sAxkbGytvvPGGPPTQQ0YXy/wDIEAHHAAsnkoCJOBMAqj5zpgxQ7D4BFJiYqIsXLgw5FWlMI86XAkDwLA2NBbTQBo/fryapcHAQOGyyI3lsg/4RiY8QgIk4DICqCV6z1i4fPmycsJ2xoCmb835Qg/UiKEXk3UI0AFbxxaUhARIIEwEateuLYj8FRERIZkz/69h8J577gmTNPoU261bN7U+NAIC4eUCy0kWL15cn8yZiy4E2AStC0ZmQgIkYGcCWbJkkalTp8rs2bNVzRcBdTBwys6pYsWKalEYLAyTN29eFZ/Azvo4UXY6YCdalTqRAAkETCBjxozSuXPngK+z8gUFChSQnj17WllEV8vGJmhXm5/KkwAJkAAJhIuAoTXguLg4OXLkiEc3NOkgXvLu3bvlypUr6jj2c+TI4TmHG+4ggGXuMCCEfVLB2/vkyZOSnJxMhsEj5JUkEFYChjpghGFbs2aNUhBOt2DBgjJw4EB5/fXXpUmTJuo4wjXSAYf1HjC98AkTJshXX32llmy8/fbb1fQIDBRh8p/AF198IRMnTlTTZlq2bCkffvih/xfzTBIgAUsQyHD932S0JJhTN3jwYHnzzTfl6NGjsmrVKunevbsaGOBd9l9//eWJm1q5cmUJ9qGcK1cuSUpKcsSQe7ycYPqA3RNGl8Ke69evlzvuuMNjG9gK8xOxgIVdUrht8ueff8qdd97pYYiVtz755BNp27ZtQAgx2hetUufPnw/oOiuenC1bNtWqhjW47Z7y58+vAmfYXQ9EAcM9hmex3RN+Y1jjXWu5DVQfTAnDsy51MrQGrBX2ww8/qAcGBNizZ49s27ZNvbkfP35cRo0a5RltOGfOHNm8ebO67Ntvv/VMB9Dy8fcTRseACvwo7Z5wE+PP7gn2gAPGDZwvXz45ceKEUgkvF5iD6evmtKrO4bYJnAxajtCMj4QHA5rzA2UIe8AugV5nRbtAD9QlTKhPmKK+E2yC+wt/cD52T7i/8OId7P2FriJfyfAaMCaCIyQbajlwiBAESsAo06dPl+zZs0vHjh1vkC2UwOV4wGsP9hsyttkB/BDj4+NtJvWN4mIeIm5i2LVZs2bKAWtBAvBChrd+u6Rw2wT3AxiiD1h7IGDdWdz3gST8BnPnzq1W7AnkOiueixYWvIQ4oQaMRRxCef5ZxT54UcU9hhZQuyeMJseYpmADmeD55+ulyvAaMPp+McFdq43++uuvguo8Jr6j5oN+YSb3EECTJxYoR3cE3igRLMBOztcKlsIP+eeff5YxY8aowBEI+h+o87WCHpSBBEIlgFagPn36yLlz51RLEMYc+XJ0oZZj1PWGO+ADBw5IuXLlPPJXq1ZNxo4dK8uWLVNNz127dvV8xw13EMAPBHFqmYInAIYIrs9EAm4mgAGIZ8+eVQjQ3D1ixAjlX+zCxHAHjMEi3glVeby5oyrvhL4Bb924TQIkQAIkYB4BtKBqDhjdMRjIa6cUtkAcdL52uk0oKwmQAAlYjwDGQiCMKBK6OTHDwk4pbA7YTpBCkXXv3r2CoO4IhP7kk0+mWJ0klHzddC1GzmOgHhg+/fTTZOgm44egK2I7t2rVSqpUqaJiPIeQFS+1KIHhw4fLww8/LHfddZeMHDlSnnvuOYtK6lssw5ugfRfrjqMYrdq0aVOPsljsG9Orevfu7TnGjZsT0Eb8amdhkfQGDRpwYXENCD99Eli3bp0MGjTIM0ocD+oKFSpI1apVfZ7Pg/YkgJkVCOxk18QasIGWi42NlTJlynhKwKhvTLlh8p8ARjmW/jdcqZYwpQFTbphI4GYEMI3Hu5sLU960uec3u47fkYCZBOiADaRdtGhRNeUKo/OQECCkRYsWBpbovKwRKxpz6DSGmFuIkY9MJHAzAphtofUN4jxMU6lZs+bNLuF3JGA6ATpgA5HjDXzatGmCeMfoixo3bpx06NDBwBKdlzUGVsyYMUNuu+02ad26tXz88ceCtVqZSOBmBG655RaZOXOm6q6477771LxpzMC4WdqyZYvg3Hr16smkSZNudiq/IwFdCBgeCStYKUOJBMNIWMFSN+46LRIWosnYPWEOrhOik+EFkZGw/nc3IiwuBvlpCTbGoiF4eTY7MRKW2cTTL8+oSFisAafPnmeQAAk4nMDhw4clOjraoyVesDCDgYkEjCRAB2wkXeZNAiRgCwJly5b1jJjWBL711lu1TX6SgCEEXOeAlyxZIl26dFHTg3bs2GEIVGZqLwJYoem1115Tk/g7derkiOXT7GWB8EtbqFAhtThMxYoVpXHjxqr5uUaNGuEXjBI4moCr5gFv3bpVHnnkEY9BsSYx5pUWK1bMc4wb7iPw6KOPysqVK9VSiRhlPXToUHn33XfdB8LlGmPRGCwUwkQCZhFwVQ0Y80cxcVtLmNqyf/9+bZefLiVw7Ngxz0LbWM5u/fr1LiVBtUmABMwk8P/eyMxSw1QW+nmwHJ6WEOTBO1CGdpyf7iJQv359Qc0XCS9lmK/NRAIkQAJGE3CVA27YsKEKW4bgDo0aNZIFCxYItpncTQBhCrE+NeaOdu7cWd0X7iZC7e1C4Ouvv1ZramNdbUTaY7IXAde96uNGxR8TCWgEEOxj3rx52i4/ScAWBD766CM1VgFLu6JrrX///gKHzGQfAq6qAdvHLJSUBEiABG5O4Pfff1frquMsxLrGqmFM9iJAB2wve1FaEiABElAEME/ZO9710aNHScZmBOiAbWYwihs6AdQWPv/8c+n977KQY8aM4frCoSNlDmEggLWx69SpIyVLllQhM7EEI5O9CLiuD9he5qG0RhDAot1z585VATdWrVol6AMeOHCgEUUxTxIwjABiec+aNcuw/Jmx8QRYAzaeMUuwGIENGzZ4ol1hAMvSpUstJiHFIQEScAMBOmA3WJk6piBQqVKlFPuJiYkp9rlDAiRAAmYQcJ0DxkhBxP0dMmSIOGFpPDNuEqeV8fbbbwuWR0RgFsT9nT9/vtNUpD4kQAI2IOCqPuDY2Fhp1qyZMgsiHq1YsUIt1I2HMZN7CGC96N27d7tHYWpKAiRgSQKuqgEvX77cE3Lw+vXrgri/iA/NRAIkQAIkQAJmE3CVA86bN2+KWNDnzp2T3Llzm82c5ZEACZAACZCAuMoB33HHHdK2bVvJnz+/lC5dWsWFrlKlCm8DEiABEiABEjCdgKv6gNHv++GHH0pMTIyKIFOgQAHTgbNAEiABEiABEgABVzlgzeRFihTRNvlJAiRAAiRAAmEh4Kom6LAQZqEkQAIkQAIk4IOAK2vAPjikeSghIUEtVZeUlCRdu3aViIiINM/lFyRAAiRAAiTgLwE64JuQunLligpyfvbsWRWwf9KkSTJz5kzBPFImEiABEiABEgiFAJugb0IP622i5ot4wXDGhw4dktWrV9/kCn5FAiRAAiRAAv4RoAO+CSesNuK93iZGUeMYEwmQAAmQAAmESoAO+CYE69evL82bN1fBOooWLSq1a9eWO++88yZX8CsSIAESSJvA2rVrZcaMGXLw4MG0T+I3riHAPuB0TP3BBx+ocJUIW1m9enVBLZiJBEiABAIl8OWXX8p7770nGNiZnJwsc+bMEbzkM7mXAGvAfti+WrVqUrNmTcmYkbj8wMVTSIAEfBD46KOP5Pz588r54uvPPvvMx1k85CYC9ChusjZ1JQESCBuB1AGAsDobk7sJ0AG72/7UngTCRuD48eOyePFi2bBhQ9hkMLNgrEGOhFj0+ENYXCZ3E2AfsLvtT+1JICwEDh8+LG3atFFlX7x4UUaNGiUPP/xwWGQxq9BWrVqp9cfx4lGpUiWJjo42q2iWY1ECrAFb1DAUiwScTGD48OESFxen/jDAccKECU5W16Nb+fLlpVmzZnS+HiLu3qADdrf9qT0JhIVAwYIFU5R75syZFPvcIQE3EKADdoOVddYRkcF+++031/Td6YyP2f1L4IknnlAcIiMjVWjXp59+mlxIwHUE2AfsOpOHpvC1a9ekZcuWEh8fL5cuXZK2bdvKuHHjQsuUV7uOQLly5WTr1q2yfv16wbrc9erVcx0DKkwCdMC8BwIiMHfuXDl27JiKkY0L16xZI1u2bJFatWoFlA9PJgE4XkaW433gZgJsgnaz9YPQHc3PqAVrCfsYRMNEAiRAAiQQGAHL1oAzZcoUmCapzkbUqlDzSJVlWHYR+tJKerRr106GDh2qQnJiYYoSJUqo5sP0QnTie6vpEqxBnaKHFtnNSvdXsDZxyu9d098JNoEOTrKLEbpY1gFjFaL0HurazZr6E6AyZ84s169fT/2V7fZxE1tpBabChQvLvn37ZP78+ZItWzZp3759ihWj0gKs/RitpEtasqZ33Go2SU/etL7HbwS/MSfYBLogwTZOSE6wifYcdoIu+J2E4pPS8mWWdcAY4BNsioiIUGv4hpJHsGXrfR0eLImJiXpnG3J+HTt2VHlgnWT8pZc0B2xFXdKTPfX3VrVJajnT28eDES9RTrAJdHVKd0hUVJQjbKK9qDrh/sJofW1t+PR+V76+z5kzp6/Dwj5gn1h4kARIgARIgASMJUAHbCxf5k4CJEACJEACPgnQAfvEwoMkQAIkQAIkYCwBOmBj+TJ3EiABEiABEvBJgA7YJxYeJAESIAESIAFjCdABG8s3LLknJyfL0aNHJSEhISzls1ASIAH7EDhx4oScPXvWPgI7SFI6YAcZE6pcuHBBOnfuLN26dZNbbrlFDh065DANqQ4JkIBeBAYNGqSeF3Xq1JE5c+bolS3z8ZMAHbCfoOxyWp8+fWTjxo1y4MABJfKzzz5rF9EpJwmQgIkEpk2bJvPmzVPPCsxxHTVqlBw+fNhECVgUHbDD7gFEa/GOAIamaCYSIAESSE3g3LlzqsVMO44Y7//884+2y08TCNABmwDZzCLuvfdeT2hIRDmqXbu2mcWzLBIgAZsQaNasmedZgbCRiCRWuXJlm0jvDDEtG4rSGXjN16Jr164qAPrq1aulZs2a0rt3b/OFYIkkQAKWJwBni/EiCxcuVKEvx4wZ43HIlhfeIQLSATvEkN5qdOnSRfDHRAIkQAJpEZg1a5YsXrxY4uPj1SmvvfaaWte7ePHiaV3C4zoTYBO0zkCZHQmQAAnYgUBMTIycP3/eIyrGjsTGxnr2uWE8ATpg4xmzBBIgARKwHIHGjRur1bA0wTAoq2LFitouP00gQAdsAmQWQQIkQAJWI1CrVi3BVKTmzZursSLr16+X7NmzW01MR8vDPmBHm5fKkQAJkEDaBOrXry9TpkxJ+wR+YygB1oANxcvMSYAESIAESMA3ATpg31x4lARIgARIgAQMJUAHbCheZk4CJEACJEACvgnQAfvmwqMkQAIkQAIkYCgBOmBD8TJzEiABEiABEvBNgA7YNxceJQESIAESIAFDCdABG4qXmZMACZAACZCAbwJ0wL658CgJkAAJkAAJGEqADthQvMycBEiABEiABHwToAP2zYVHSYAESIAESMBQAgxFaShea2b+ww8/yLx585RwX3zxheTIkcOaglIqEiABEnAwATpgBxvXl2oIvj5kyBBJTk6WjBkzSp8+fVQs2EyZMvk6ncdIgARIgAQMIsAmaIPAWjXblStXKucL+a5duybHjh2TU6dOWVVcykUCJEACjiVAB+xY0/pWrGbNmpI1a1bPl/v375eoqCjPPjdIgARIgATMIcAmaHM4h7WUuXPnytKlSyUyMlJGjhwpq1evln379knRokXl448/loiIiLDKx8JJgARIwI0E6IAdbnX0+b7wwgty+fJlyZw5s1y6dEm+//57h2tN9UiABEjA+gTYBG19G4Uk4Zw5c5TzRSZXrlyRP//8M6T8eDEJkAAJkIA+BOiA9eFo2VyqVq2qar6agIcOHdI2+UkCJEACJBBGAnTAYYRvRtHPPfeclCxZUkqUKCFwxhgFzUQCJEACJBB+AuwDDr8NDJUAQTbWrFljaBnMnARIgARIIHACrAEHzoxXkAAJkAAJkEDIBOiAQ0bIDEiABEiABEggcAJsgg6cWUhXIPrUzJkz5fDhw9KhQwepWLFiSPnxYmsQ+Pvvv2X58uWSO3du6d27tzWEohQkkA6BAwcOyIIFC1Rwnr59+6YYsJnOpfxaBwJ0wDpADCSLxx57TFatWiWJiYny3//+Vz7//HOpV69eIFnwXIsR2Llzp7Rt21auXr2qgp1s3rxZPvzwQ4tJSXFIICWB2NhY6d69uxw5ckSyZ8+unkvfffcdnXBKTIbusQnaULwpMz9z5oxs2rRJOV98c+LECQbFSInIlnt4iYLzRbp48aJs2LBBjh8/bktdKLR7CGBVNDhfJATo2bt3r+zYscM9ACygKR2wiUZADGY0UWoJqxFhVSImexMoVqyYeK8mBeebLVs2eytF6R1PIE+ePKrmqyl69uxZLk2qwTDpkw7YJNAoBs731VdfVSViXm758uXlzTffNFECFmUEgSeeeEIKFiwoRYoUkeLFi6vm5/z58xtRFPN0GYGNGzfKt99+K7/99pvumnfp0kU9gwoVKqTu20GDBkm5cuV0L4cZpk2AfcBpszHkm5YtW6omynPnzqmbHX0vTPYmkDNnTvnjjz9k9+7d6iULTpiJBEIlsGTJEnn66adVt0aGDBlkzJgx0rNnz1Cz9VyPFjmUgWZnPIfKli3r+Y4b5hBgDdgczilKwSpEiEpF55sCi613sNBFlSpVVE3C1opQeMsQePvtt5XzhUDXr1+XyZMn6y4bHDvuWzpf3dH6lSEdsF+YeBIJkAAJmEugVKlSKQo8efJkin3u2J+A4Q742LFjgjmS+Dt9+rQihpGi6NvAJxMJkAAJkMCNBIYNG6YORkdHC/6+/PLLG0/iEVsTMLwPGM0oaOJAqlu3rhot+sorr0jjxo1lwoQJ8v7773PEqK1vIQpPAiRgBAEMiNq+fbvs2rVLLabCsQVGUA5vnmk6YEylQECBpk2bqprrW2+9peaKDRkyRPVf+iM2oj4h9ejRQwUowFSNqVOnSrdu3VS++H7dunVqG+fhO8xFQxowYECKqR3qoJ//UE5ERISK7uLnJZY9LUuWLCmmLllW0HQEgx7ob/KehpXOJZb92ik2wTQ4/DnBJuiDx6Ai9JU6IWk2wWfp0qVtqRJ+73gW4/di94TfCRa2CXbcTlr3pU8H/Ndff0mrVq2kZs2aapoMHGX79u1VsIF27drJvn37/HJuR48eFTRBT5w4UTlWTNeIiYlRNWEYBM0q3v0aGE2aN29eZSuUCQMGm6Cw9gIQbB5WuM5JeoAnbWKFu+p/Mmi/LyfYBDrgL60HnXWo+yeJE2yC+wt/TtAFVgvlWaz91lJb36cDnj59ugwePFief/55QRMy1pDV+iN++ukn1SRSvXr11HndsI8mE8xhw5sDarZTpkxRb9uaQRA9yDtgQceOHT15wFEHm/AmjMgu+LN7ypUrl1y4cMHuaghervAW6QRdnGIT/E5QO3GCTdDidfnyZU9EMjv/YJxyf6H2i3sMYXftnlDzhR64x4JJeP75Sj4HYWGhgDJlyqjz0Q+BaTNaypcvnyBiij8JNWDMM0OCM8SNhZF9CACOdPDgQbVYvNrhPxIgARIgARJwEQGfNWBUtdGngoS3GO/qs/d2epwQ7Qk1YAQoQO3nwQcfVE3MY8eOlbVr16rab61atdLLht+TAAmQAAmQgOMI+HTA0LJ///6qGRrNU5gutGbNGqU8Bmc988wzfoGAs0bTNartaIrQ0vDhw284pn3HTxIgARIgARJwAwGfDnjEiBE3dbKIYRxI8na+2nW+jmnf8ZMEjCaA7hF0geBexmBApvATwMs+pt1gICbXyQ6/PSiB8QR8OuCSJUuyb9Z49iwhTAT+/PNP6dWrl+oWwSj8FStWSOXKlcMkDYsFgfPnz6uZFxiYiXVq33nnHTVdkXRIwMkEfA7CcrLC1I0EHnvsMTW3XZsCN2rUKEIJMwGsEoaZD7DJlStX5KOPPvJ7sGeYRWfxJBA0ATrgoNHxQrsSSN3kfOjQIbuq4hi5MU3Dew5vXFyccsSOUZCKkIAPAnTAPqDwUOAEEOsbo93tkHr37q3ExCBBPPgR3Y0pvAQwQwIJsyUwXbF169aCdWrNTnv27BEEImIiATMI+OwDNqNgluEcAg8//LBaUxS1lvvuu09FT7Oydp07d1bz0Xfu3KkG+9SrV8/K4rpCNvTBI/QtAv1ERUUJIu6ZnbDe7syZMyUpKUnFQcC2Nh3TbFlYnjsI0AG7w86Gabl06VI1RU2LdrN48WLp1KmTWN2pYWEQ/DFZhwC6Brp37x4WgbZt2yZfffWVJCQkqPJxPy9cuFDuueeesMjDQt1BgE3Q7rCzYVrigeXdd5ecnOx5iBlWKDMmAZ0JIFKftgACssY+l0vVGTKzu4EAHfANSHggEAJYLQsRz9B3h7jC+LztttsCyYLnkkDYCdSoUUM1OyM2PcYGYDqUd2z6sAtIARxJgE3QjjSreUrlz59fFi1aJN98841aArJLly6OWH7MPIIsyQoE4HinTZsmkyZNUs63Q4cOajCYFWSjDM4lQAfsXNuapllkZKQKXWpagSyIBAwggAFXjz76qAE5M0sS8E2ATdC+ufAoCZAACZAACRhKgA7YULzMnARIgARIIBQCGAx34sSJFIM9Q8nPSteyCdpK1qAsJEACJEACHgIIjPLEE08IFurAAj6Y9pgjRw7P93bfYA3Y7hak/CRAAiTgUAKtWrVSQX6OHDkiCBn7wQcfOEpTOmBHmZPKkAAJkIBzCJQqVcqjDBbp2LFjh2ffCRt0wE6wInUgARIgAQcSqF69uiccKJqgEUbWSYl9wE6yJnUhARIgAQcRGDdunIpQhoh7iA/evn17B2knQgfsKHNSGRIgARJwDgHMzcYiGU5NbIJ2qmWpFwmQAAmQgKUJ0AFb2jwUjgRIgARIwKkE6ICdalnqRQIWJnDt2jV59dVXpXnz5oKBNmfOnLGwtBSNBIwhQAdsDFfmSgIkcBMCr7zyilr4YPfu3RIbGyuPPPLITc7mVyTgTAJ0wM60K7UiAUsTOH78uGDtaC2xBqyR4KebCNABu8na1JUELEKgRYsWkj17diUN1t9NTEy0iGQUgwTMI0AHbB5rlqQTAdSWsGxckyZNZOTIkQEHab906ZIMGTJEWrZsKVi/OCkpSSfJmI2/BHr27Cn9+vVT/b89evSQ1atX+3spzyMBxxDgPGDHmNIdily+fFnq1q0r+ESaOHGilC1bVh588EG/Adx///2yZcsWtfB6pkyZZMSIETJ69Gi/r+eJoRNArffFF19Uf6HnxhxIwJ4EWAO2p91cK/WpU6ekaNGiHv1Rm127dq1n35+NuLg45Xxx7tWrV2XdunX+XMZzSIAESEBXAnTAuuJkZkYTKFiwoApNp5WTJUsWqVy5srbr12e9evUkY8b/3fqoAUdFRfl1HU8iARIgAT0JsAlaT5p+5IXa1+uvvy5//fWXdOjQQZ566ik/ruIpGoFs2bLJ5MmTFTs4TsSG7d+/v/a1X5+jRo2SnTt3Chb6btCggWqC9utCnkQCJEACOhKgA9YRZnpZobnztttuk3PnzqmBQ7t27ZICBQpIt27d0ruU33sRALPff//d60hgmxh9u2DBgsAu4tkkQAIkoDMBNkHrDPRm2Z0+fVpy5crlGbWL/stVq1bd7BJ+RwIkQAIk4FACdMAmGhZNprlz5/aUiP7LIkWKePa5QQIkQAIk4B4CbII20dZo+pw0aZK0bt1aMJgIcXCHDRtmogQsigTMIXD9+nU1Reynn36S6OhotaQclpZjMpfA4sWLZdasWXLlyhUZP3685MiRw1wBWNpNCfAXcVM8+n+JGi8GYDGRgJMJvPHGGzJhwgQV5ASON2vWrJxrbbLBV6xYoYKdYOwJRv1jrMns2bOFL0ImG+ImxbEJ+iZw+BUJkEBwBH799VdPhDHUvn777bfgMuJVQRNA7RfOFwmrT509e1aOHDkSdH68UH8CdMD6M2WOJOB6AlhiUJtrDRhY8YjJXAJVqlQRTNvT0oEDByR//vzaLj8tQIAO2AJGoAgk4DQCWOsXEctKly6tpt5xtL/5Fu7Vq5c0bdpU2aFmzZqCJmnvQaDmS2SPEpctWybPPvusGp+D1hsjE/uAjaTLvEnApQQiIyPljz/+cKn21lAbfb3ffPONNYSxiRSLFi1SgX0Qax78sPDLZ599Zpj0rAEbhpYZkwAJkAAJ2InAjBkzPAu9oPZr9IBZOmA73R2UlQRIgARIwDACFSpUSDFK/ODBg4aVhYzpgA3Fy8xJgARIgATsQmDAgAFSqlQpKV68uMAZL1261FDR2QdsKF5mTgIkQAIkYBcCERERsnr1aomJiVFhgxE62MhEB2wkXeZNAiRAAiRgKwIZMmRIsea4kcKzCdpIusybBEiABEiABNIgYNkaMGKW4k0kmIRF1jEBHZ92T1iwAVM67J6gBwIzOEUXJ+iB34eTbIJpI4j45ITkhPsL95Z2j9ndJtAFsfzxHAsmpeXLLOuAExMTg9FTXQPni3lcWO7P7gmGT0hIsLsa6mXKKbo4RQ/EZ8afE+4v9N3hN6+FXrTzDwbBMpxgEzhf3F+hPMutYkfcX0lJSZ4pSoHKldYLlWUdMFZTCSXh+lDzCKV8Pa91ih5g4hRdnKCHpoP2qec9a3Ze0EH7M7tsI8qjTYygGlqeRtxf7AMOzSa8mgRIgARIgASCIkAHHBQ2XkQCJEACJEACoRGgAw6NH68mARIgARIggaAI0AEHhY0XkQAJkAAJkEBoBOiAQ+PHq0mABEiABEggKAJ0wEFh40UkQAIkQAIkEBoBOuDQ+PFqEiABEiABEgiKAB1wUNh4EQmQAAmQAAmERoAOODR+vJoESIAESIAEgiJABxwUNl5EAiRAAiRAAqERoAMOjR+vJgESIAESIIGgCNABB4WNF5EACZAACZBAaATogEPjx6tJgARIgARIICgCdMBBYeNFJGB9Ajt27JCNGzc6Yok+69OmhCQQOAHLLkcYuCq8ggRIQCMwduxYmTp1qly5ckWwPvaqVaskR44c2tf8JAESsAAB1oAtYASKQAJ6Eti3b598/vnnEhMTI6dPn5aTJ0/KDz/8oGcRzIsESEAHAnTAOkBkFiRgJQKXL1+WvHnzekRKTk6W8+fPe/a5QQIkYA0CdMDWsAOlMJnAP//8I9u3b5f4+HiTSza+uIoVK0r16tUlMjJSMmbMKKVLl5aHHnrI+IJZgisJoMVlz549Ht2xv2vXLs8+N9ImwD7gtNnwG4cSOHDggPTo0UOuX78uR44ckXXr1kmJEiUcoy2c7ldffSWzZ8+WhIQEad68ueTPn98x+lER6xAYPny4LFmyRN1nt912m5QrV05mzZoliYmJUrVqVbVtHWmtJwkdsPVsQokMJtCtWzc5evSop5Rhw4bJN99849l3wkaGDBmkU6dOTlCFOliUAF5cp0yZopwvRMRAvx9//FGSkpKUxJs2bZL58+dLmzZtLKpB+MViE3T4bUAJTCZQoECBFCWiRsxEAiQQGAHUcrNnz+65CGMNMOJeS/j+woUL2i4/fRCgA/YBhYecTaBLly6SL18+pSSm5vTu3dvZClM7EjCAQJ06daRYsWKSKVMmQYvL1atXpWzZspIlSxZVGqbAdejQwYCSnZMlm6CdY0tq4ieBRx55RKKjo9UgrFtvvVXuuOMOP6/kaSRAAhqBXLlyqXEGX375pWTNmlU6d+4sUVFR8sUXX6hTsJ8nTx7VH6xdw8+UBDL8OxDlespD1tjDHMZgE2o3GHxy6dKlYLOwzHW4yZ0wUjdnzpxqRG5cXJxl2AYriFNsgodm7ty55cyZM8GisMx1ERERgulXqIXZPRUpUkTN4ba7HqgZ4x5DU7TdE7qt8OzCPRZMwvMPz43UiU3QqYlwnwRIgARIgARMIEAHbAJkFkECJEACJEACqQm4zgGPGTNGmjRpIhUqVJAZM2ak5hH2/ePHj0v79u2lUaNGUq9ePY4iDLtFKAAJkAAJGEPAVQ54xYoV8umnnwoitWB4/KhRoywXsaVFixayZcsWOXTokOoHeuWVV4yxPHMlARIgARIIKwFXOWAEpvcepHHt2jXLDUDBAAwtQb6tW7dqu/wkARIgARJwEAFXOWDMW8OoPC2dO3dOatWqpe1a4rNhw4aeeXSY1N6xY0dLyEUhSIAESIAE9CXgqnnA5cuXl8WLFwv6gTGB/D//+Y8KWK8v0tBye+ONN1SM4rNnz0qrVq3ksccec8Q0pNCo8GoSsD+B2NhY9cw5ePCgmpIyd+5cwfQpfxNCPA4aNEh1UaE179dff2WMb3/hWfQ8zgO2qGE0sZwy55TzgDWLWueT84DNtUWlSpXUXFKUijmyffv2lddee+0GIdKaB4wVrX7++WdPNxoW2UAsZqsmzgP+f8twHvD/s+AWCZAACZhOoFChQp4yMRZl8+bNnn1/NlAD9h7Dsn//fn8u4zkWJuCqPmAL24GikQAJOJwAwp6iVoiE8R0NGjQISOPWrVt7xrBkzpzZE888oEx4sqUIuKoP2FLkKQwJhJEA5pu/8MILakoemjIx9gAB9ZmMI/D222/LP//8o8LkwplifEcgqV+/foJ+5A0bNqjBo0OGDAnkckeeizC9gwcPVnHdEd8dTfLeKzJZXWn2AVvcQuwDtp6B7G4TNGVi1RotDDyWlBsxYoT07NnTerD9lIixoP0EZeJpZvQBY9bI4cOHlVZoFcBCK7761UNVm7GgQyXI60mABBSBkydPSqlSpTw0sGgJalVMJGA3AtrSh5Abyx/+8ccftlKBfcC2MheFJYHQCaCpDqsgaQkPsbp162q7/CQB2xBAv3rGjP9zY7iP0bJjp8Q+YDtZi7KSgA4E0EeGvrKuXbuq9VsRe9zOzc86IGEWNiXw1ltvqSZotOI0bdpU7NYvTgds0xuPYpNAKASwZvbq1asdsx5wKCx4rX0JYPzC7NmzbasAm6BtazoKTgIkQAIkYGcCdMB2th5lJwESIAESsC0BOmDbmo6CkwAJkAAJ2JkAHbCdrUfZSYAESIAEbEuADti2pqPgJEACJEACdiZg+ChoBA//+++/1cR/be7h7t271aRpgCtdurTkyJHDzgwpOwmQAAmQAAkETMDQGjCc78CBAwUO980331TRdhAG7/XXX5dffvlF/SE2KhMJkAAJmE3g6NGjKh72ww8/LHv27DG7eJZHAmJoDfjMmTPSpUsXNUG6QoUKsmTJEomMjJTGjRurIAB58+alCUiABEjAdAJxcXFSv359T7lY3P7HH3+UMmXKeI5xgwSMJmCoA0bIO/yhJjxt2jS566671Jvmtm3b5MKFC4IVWUaNGqWcMhR98cUXZf369UrnBQsWiHecz0BAIDQZmrsRNN/uCbpgsrndE1bawZ+dVipJi7mTbAJdChYsmJaqtjmureSkLTCRnuBbtmwRBNhHJQEJcYT37t2bwimnl4eR3zvJJliM3u4JC0tERUV5FjAJVJ/Lly/7vMRQB4wScWOjyRmxZhs1aiTJycnSrl07ta7l9OnTZeXKldKxY0clXP/+/QXLSyHBQQeb8uTJIwhNhuZuuye0GFy8eNHuaqh+fjzsQ7GrVSA4xSZ4wYUuTugGwksqni3eC9bf7H7B+ZrTxnlw3GBx7ty5m11myndwvlaQI1Rl4bRwj+FZbPcE54vnMO6xYFJalShDHfC1a9dk+PDhcscdd0iLFi2U3GjqgYOsXbu2Moz3m17JkiU9usXExHi2A93Ajwk/RDh/uycwTE8PhGJbs2aNaj576qmnUjxYrKI/9EBKTxeryHszOfyxyc2ut8p3eCFCcoJNtN+7vw64UqVKqv8XS9cVLlxY7r//frntttssw8IJNsFzGPeYE3TB70S7x7CtVzLUAa9YsUK2bt2qaj1wEjVr1pR77rlHxo4dK8uWLVNvnAgIzxQ8gU8//VTeeecd9TKDt03U+p9//vngM+SVJOASAg888IDgj4kEwkXAUAeMmi/+UqcxY8YI2sSzZs2a+ivuB0hg5syZniYeNI8sWrSIDjhAhjydBEiABMJBwNBpSDdTiM73ZnT8/65ixYopTtYGlaQ4yB0SIAESIAHLEQibA7YcCZsKhAFuERERKtAJnPHChQttqgnFJgESIAF3ETC0CdpdKMOjbf78+WXnzp1qShcGtDGqWHjswFJJgARIIFACdMCBErPg+Rh8VapUKQtKRpFIgARIgATSIsAm6LTI8DgJkAAJkAAJGEiANWAD4Tola8TMxZQy9DVjvqR3AAOn6Eg9SIAESMBsAnTAZhO3WXmIktStWzc5dOiQComJEKETJ04URLlhIgESIAESCJ4Am6CDZ+eKK6dOnSoHDx4URH9KSEiQHTt2qOUlXaE8lSQBEiABAwnQARsI1wlZI2yo95xt1IjTimvqBH2pAwmQAAmYRYAO2CzSFi7n2LFjMmvWLFm+fPkNUt53331SrFgxtWJOkSJFpF+/flK+fPkbzuMBEiABEiCBwAiwDzgwXo47+8SJE9KkSRPVxIzBVejvRahQLWHg1erVq1VMbywlWLlyZe0rfpIACZAACYRAgA44BHhOuPT999/3xJKGPj///LNg1HPx4sU96mFFk1q1ann2uUECJEACJBA6ATZBh87Q1jkgepb3tKKzZ89K5sx8L7O1USk8CZCALQjQAdvCTMYJ2adPHzWoKl++fFKoUCHp37+/Wh81kBITExPVPOFVq1aphc0DuZbnGkfgl19+Uct+OmFBdOMoMWcSCB8BVnXCx94SJSOW9Pbt22XDhg2SO3dutWZzIIJhse0WLVpIXFycWrC6SpUqMmPGDM4TDgSiAec+88wz8tNPP6llP7GQ+B9//CF4yWIiARKwDgHWgK1ji7BJgoFWGIhVs2bNgGVYunSpnD59WjA9KT4+Xvbt26ce9gFnxAt0I7B79241oj02NlbZJCkpSY1y160AZkQCJKALATpgXTC6NxP0H2OQlpaSk5O1TX6GkUDOnDlTlH758uUU+9whARIIPwE2QYffBraWoHnz5hIVFaUGcmHwVrly5aRhw4a21snuwleoUEEaNGggGFCHkKElSpSQ3r17210tyh8EAbRKbdu2TfBCVqNGjSBy4CVGEqADNpKuC/LG+sNr164VDMBCbbhZs2YpRlW7AIElVfzoo4/UlDIMwIIz5jrRljSToULB+eL3iDEA58+fl6FDh6pAOoYWyswDIkAHHBAunuyLAGq+rVu39vUVj4WRAB6+TO4l8NZbb8nJkyc9MxOwiMo999wj0dHR7oViMc3/v/POYoJRHBIgARIggeAJIGb79evXPRlcuHBBMGuByToE6ID2GV35AAAYdElEQVStYwtKQgIkQAK6EXjggQdUXmihwhTDli1bqrjuuhXAjEImwCbokBEyAxIgARKwHoGyZcuqOf6YD54rVy5p06aN9YR0uUR0wC6/Aag+CZCAcwkg+Ernzp2dq6DNNWMTtM0NSPFJgARIgATsSYAO2AZ2wxSCHTt2SEJCgg2kpYgkQAIkQAL+EGATtD+UwnjOnj17pFOnTmq93iNHjsjGjRsDXiwhjOKzaBIgARIggTQIsAacBhirHG7fvr0cPHhQDh8+rKYUvPrqq1YRjXKQAAmQAAmEQIAOOAR4ZlyK9Xq9ExY7YCIBEiABErA/ATpgi9uwS5cukidPHiUlVi3q1auXxSWmeCTgHwGESDx27Jhascm/K0I/68yZM4I/JhKwAgH2AVvBCjeR4bnnnlNz+LDEHBY54Fy+m8DiV7YhgBjVeJk8fvy47N+/X1asWCGVK1c2VP5x48bJ999/r5bO7Nmzp7z00kuGlsfMSSA9AnTA6RGywPfdu3e3gBQUgQT0IzBw4EC1iAdqwUgDBgyQZcuW6VdAqpzWrVsn7733nmjLMv73v/+VFi1acOWuVJy4ay4BNkGby5ulkQAJ/EsAMYo15wsg586dM5QLpvIhNrKWkpKSDC9TK4ufJJAWATrgtMjwOAmQgGEEsCoPYhQjZc2aVUqWLGlYWcj41ltvTbFM5sWLF+W2224ztExmTgLpEWATdHqE+D0JkIDuBO6880758ssvZcGCBVKlShV59NFHdS/DO8MCBQrI6tWrZfTo0ZI3b17p06ePZ3Cj93ncJgEzCdABm0mbZZEACXgItG3bVvBnVsKUvvfff9+s4lgOCaRLgE3Q6SLiCSRAAiRAAiSgPwE6YP2ZMkcSIAESIAESSJcAHXC6iHgCCVifwIYNG6RDhw5Su3Zt+fDDD60vsA0l3LVrl9x7771Sp04deeWVV9RIbj3VwMCwxx9/XCpWrKgGiMXGxspTTz0lTZo0UWXGxcXpWRzzsgAB9gFbwAgUgQRCIYBoUnfffbcni/Hjx0v16tWlZcuWnmPcCI0Apklh3rCWpk6dql52sFCKXqljx44CJ48pWhkyZJDmzZurqVLXrl1TRSAoz1dffaVXcczHAgRYA7aAESgCCYRC4OjRo1KkSBFPFhcuXJADBw549rkROoGTJ09KqVKlPBlhadDt27d79vXYgNOF80XCJ2rEmvPFMSxJyuQsAnTAzrIntXEhgVtuuSWF1tHR0dKoUaMUx7gTGgHMU86SJYsnE0xrQtOwngn5aWXgs1ixYp59zJkuXLiwnsUxLwsQYBO0BYxAEfQlgL6yIUOGqBoK+tM+//xzT9AHfUuyRm758+eXuXPnyhNPPCH58uVTMZYxt9bpacqUKYKQkqdPn1YxnsuXL2+Yyjly5JDZs2dL7969VWz2rl27pmiS1qPgYcOGyalTp5Q+devWFYTrHDp0qCAOfL169eSFF14IuJhPPvlE3RtoQsc94t1SEnBmvEB3Ahn+ber4X5uH7lmHlmFMTEzQGeAhhCYiBHy3e8qVK5epq8UYxStnzpySMWNGMWMgCQYiockQCVGWEGcYDzO9klNsAja5c+e25epAa9askf79+3tkL1q0qCxZskRQM7V7gpMM5fmn6T9x4kR57bXXJDk5WR2qVKmSCnyClwkzUqZMmdTvLzEx0YziDC0D9xWeXVos8UALw/MPz43UiU3QqYlw3/YEvB8w+MH8+uuvtteJCqQkgP5X72UF0X96+PDhlCe5fO/vv//2OF+gQIXkxIkTLqdiLfXpgK1lD0qjAwE0O+OBjIS+tLJly+qQK7OwEoGqVatKZGSkRySMBC9XrpxnnxuipjJhDXEtYbAe+pWZrEPAsk3Q8fHxnodooLiw6smVK1fUX6DXWu18NBMG2+xhJV3gCOEUzdAFo4Bbt26t+n2xfjL61tD8rVdyik3s3kQ4efJktcQgXrDefvtt5YAt2qMW0K2H5krcw3qkMWPGyIwZM9Tc4nfffdfUgVz4veMew7PY7gkvMnh2ea/gFahOsGvqZFkHHEofCPuAU5s5/Ptm9gEbrS37gI0mHHj+ejwgAy/VmCv06gM2Rjr/c7X7C563puwD9qbBbRIgARIgARKwOQH92uVsDoLikwAJkAAJkICZBOiAzaTNshSBI0eOqKlBnTt3lo0bN5IKCZAACbiSAANxuNLs4VP6/Pnz0qBBA48A3bp1k3nz5qlF2T0HuUECJEACLiDAGrALjGwlFf/66y/BwuhawtzELVu2aLv8JAESIAHXEKADdo2praEo4hRrc3QhEbYZHs8atqEUJEAC5hKgAzaXt+tLQ7AEzE1ECESExsMcXe9l3uwCaPHixWqt1kGDBjlinmNq7ghfOG7cOOnbt6+Ks5z6e+6bQwCxrhHje9SoUSlWRjKndJZiNAH2ARtNmPnfQKBdu3ayc+fOG47b5QCC8j/55JNqYj5Wqfnnn38ct05rjx49ZMOGDUrH5cuXq6AmXbp0sYuJHCEngot89tlnKoSkFsjm5ZdfdoRuVOJ/BFgD5p1AAgES+OGHHzwRvRDlB4uoOy0hrrIWtQy1YQyUYzKXwLJlyzwLysAGK1asMFcAlmY4ATpgwxGzAKcRqFatWorlDQ8ePOg0FVOELEQYT+9+e8cpa1GFEO/aO2FJQSZnEaADdpY9qY0JBJ577jm55ZZbpHjx4lK5cmVBE63T0vjx45VKiLPctGlT1RTqNB2trs+IESMkT548Urp0aalVq5agRszkLALsA3aWPamNCQQQd3jlypUmlBS+IkqUKCHHjx8PnwAsWaKiomTHjh0k4WACrAE72LhUjQRIgARIwLoE6ICtaxtKRgIkQAIk4GACbIJ2sHGpGgnoSWDhwoXy999/S5MmTaRhw4Z6Zs28SMCVBOiAXWl2Kk0CgRF44403ZOLEiZKQkCDfffedjB49Wjp06BBYJjybBEggBQE2QafAwR0SIAFfBGbNmqWcL747c+aMTJkyxddpPEYCJBAAATrgAGDxVBJwK4FixYqlUB2rWjGRAAmERsDxTdAnT55UEWQwdeTee+91RUCBrVu3qhWGSpYsKc2bNw/tDuHVJPAvATQ5t2nTRjA9CUE5vv76a3KxIIE9e/bIunXrpECBAoKQr0zWJuBoB3zx4kVB/NpDhw5JpkyZVLze+fPnCyL7ODX99ttv0qtXL9VcCJ2x2MHjjz/uVHWpl0kEEP3rzz//lJiYGClTpozkypXLpJJZjL8E4HzxkoSwlYhR3rNnTxk5cqS/l/O8MBBwrif6F+a0adPkwIEDarWapKQkQW0YtUMnpzfffNPTV3f16lXFwMn6UjfzCGAd5xo1atD5moc8oJLGjh0reM5du3ZNxfH+6aefJDY2NqA8eLK5BBztgCMjIyVr1qweovHx8Sn2PV84aKNUqVIptEGNhYkESMD5BIoWLZqii+3EiRMpYpY7n4D9NHS0A7777rvVYu/58+dXweW7d+8uVapUsZ+VApB4yJAh6uxChQpJdHS0fPrppwFczVNJgATsSuCpp55SFQy0VOC3j9YwxJK2W1q9erWgq9ANtXdH9wFj4NUvv/wimzZtUjcmms+cnjDwCvFj8Ve4cGEVyN3pOlM/EiABUQOvECgF3Wz58uWT8uXL2w7La6+9JtOnT5fExES1FOOaNWsEC4I4NTm6BgyjYcBV3bp1Vd+VU42YWi+89SJSEVZRYSIBEnAPAVQ6GjRoYEvnixovnC+WXbx06ZIy2qRJkxxtPMc7YEdbj8qRAAmQgIMIpG4y/+effxyk3Y2q0AHfyIRHSIAESIAETCaAsTq9e/eWLFmySN68edXf8OHDdZfi6NGjam3lXbt26Z53oBk6ug84UBg8nwRIgARIIHwE+vXrJ/Xq1RPUfDFmB05ZzwSne99996ksUQaauDF3OlyJDjhc5FkuCZAACZDADQRq1659wzG9DgwcOFA5dy2/9957L6wOmE3QmiX4SQIkQAIk4GgCmJ7lnY4fP+69a/o2HbDpyFkgCZAACZBAOAhgrjQSRotHRUXJyy+/HA4xPGWyCdqDghskQAIkQAJOJoApqWvXrlWL1RQvXlzq1KkTVnXpgMOKn4WTAAmQAAmYSQDhelOH7DWzfO+y2ATtTYPbJEACJEACJGASATpgk0CzGBIgARIgARLwJkAH7E2D2yRAAiRAAiRgEgE6YJNAsxgSIAESIAES8CZAB+xNg9skQAIkQAIkYBIBOmCTQLMYEiABEiABEvAmQAfsTYPbJEACJEACJGASATpgk0CzGBIgARIgARLwJkAH7E2D2yRAAiRAAiRgEgE6YJNAsxh7Ebhy5YrExMTIpUuX7CW4y6Q9c+ZMitVtXKY+1bU5ATpgmxuQ4utP4OLFi9KtWze5//775ZZbbpFjx47pXwhzDJnAsGHD5N5771XxfGfPnh1yfsyABMwmQAdsNnGWZ3kCDz30kPz++++yf/9+uXbtmmANUSZrEZg7d67MmDFD2SgxMVHgjA8ePGgtISkNCaRDgA44HUD82n0EsmTJItevX/cozge7B4VlNk6fPi1xcXEeeWCv2NhYzz43SMAOBMLigNHEt3HjRsEnEwlYjUCHDh0EThgpa9asUqNGDauJ6Hp5GjdurGwDEBkyZFDOuFq1aq7nQgD2ImC6Az579qwMGTJEdu3aJYMHD5akpCR7EbOYtAkJCdK3b1+5/fbbpXLlygK+TKER6NWrl7z++uvSsWNHefHFF+Wzzz4LLUNerTsB3OuLFy9WNnr88cdl69atki1btoDKwfWtW7eW6tWry8cffxzQtTyZBPQgkOHfppv/b2vTI8d08pg6daoUK1ZMmjZtKpMnT5aSJUuqbVyGUadwKEi5cuVSb7ZqJ8B/efLkUaNXneDcc+TI4WHiC0O7du1k8+bNniZT7H/77be+Tg3rMeiRMWNGuXDhQljl0KPw9GyiRxlm5IFafmRkpCNGEcP5Jicnqz57f9jt2LFDmjVr5jk1KipKvv76a/Ui6zkYpo2CBQsKmtjtnvB7xz3mhOcw7g+02OIeCyZlz55d+bTU12ZOfcDofTjZunXrqmKio6Pl5MmTniLHjh2rBr/gwIoVKzzNgJ4T/NyA4TNnzqweLn5eYtnT0LwG46WV0ETq/Q61Z88eyZcvX1qnh+049ECCvHZP6dnETvrht2LF+yVQhrCJ9+8gvevxMPV2dNjHy6FVWFhFjvQ4pvc97IKXPLsn/E5QKQw2pfUSYroDhiIYWYp09erVFM1G7777rkc/OOpgE25e1KSdMIcTRo+Pj08TRfPmzWXTpk1y+fJl9cJSqlQpOXXqVJrnh+uLnDlzqhqw98CZcMkSarnp2STU/M26Hi9DuXPnFsyltXuKiIhQvwE8U/xJRYsWVc8f7VzUbCpVqmSJ306RIkUsIYfGJtjPTJkyqRdujFK3eypQoIAaZ4DnbDAJzz9fyXQHDAdx4MABqVixohz8d9pAw4YNfcnFY34S+M9//qNuDPSBNWjQQAYMGODnlTyNBNxLoFChQrJo0SIZNGiQ5M+fX9CPXLx4cfcCoeZhIWC6A27btq2gqXnt2rWq9lurVq2wKO6UQtGigDmQTCRAAoERwPiTH374IbCLeDYJ6EjAdAeMASzDhw9XzUVO6A/U0RbMigRIgARIwEUETJ+GpLGl89VI8JMESIAESMCNBMLmgN0ImzqTAAmQAAmQgEaADlgjwU8SIAESIAESMJEAHbCJsFkUCZAACZAACWgE6IA1EvwkARIgARIgARMJ0AGbCJtFkQAJkAAJkIBGgA5YI8FPEiABEiABEjCRAB2wibBZFAmQAAmQAAloBOiANRL8JAESIAESIAETCdABmwibRZEACZAACZCARoAOWCPBTxIgARIgARIwkQAdsImwWRQJkAAJkAAJaATogDUS/CQBEiABEiABEwnQAZsIm0WRAAmQAAmQgEaADlgjwU8SIAESIAESMJFAhuv/JhPL87uo+Ph4v89NfeLSpUulfPnyUrZs2dRf2W4/Q4YMYlETBcRy8+bNcunSJWnUqFFA11nxZKfY5Pjx47J+/Xq55557rIg5IJmcYpOrV6/KpEmTpHfv3pIpU6aAGFjxZKfYZe7cuVKvXj0pWrRoUJix/G62bNluuDbzDUcsciBXrlxBS7J48WKJiIiQmjVrBp0HL9SXwLZt2yQ2NlbatGmjb8bMLWgCsMeMGTPkoYceCjoPXqgvgaSkJPn000/lySef9PnA1rc05uYvgZkzZ6oKXcWKFf29xK/z2ATtFyaeRAIkQAIkQAL6ErBsE3Qoau7atUsKFiwo+fLlCyUbXqsjATR3JicnS6lSpXTMlVmFQiAuLk6OHDkiVatWDSUbXqsjAXQ3oVsAzZ1ovmWyBoG//vpLSpQoIblz59ZVIEc6YF0JMTMSIAESIAESMICAZfuAg9X1ypUrgreVIkWKSKFChYLNhtfpQCAhIUH27NkjVapUkSxZsqgcd+/eLbARUunSpSVHjhxqm//MIXDs2DE5f/68KgytRPjjb8Yc9r5KAXu02HkntEicO3dOYmJi1OHIyEi2HHkDMngb/fBosStTpowqydfv4+LFi7Jz506pVKmSwD7Bpkyv/ZuCvdhq16H55uWXX1ZNN5MnT1Zw2AwdHiuhafP111+XvHnzyvjx46Vp06ZKkOeff159Hj58WD1UQhlsFx7N7F3qK6+8IomJiQL+eHDgRZW/mfDZFA/7+fPnK3ts375dpk6dKvfff7989913smXLFjl16pTgRVbvwT/h09jaJYP1G2+8IadPn5a6deuqGSipfx/QYOjQoaryMGHCBGndurVkzhxcXTa4qyzKEG+SeKA8+OCDUqtWLVmwYIEMGDDAotI6W6wzZ84o9uXKlRP0Nf7+++9SvHhxady4sXTt2lU5ZmcTsJ52165dU0L16NFDOV9Mc8FbPH8z4bMVZms8/vjjSgC8sOIFCWnfvn3y0ksvCaavsJVIITHl3yeffKJqvhivguTLp6BltVu3bqpSgd/UunXrPBWMQIV01ChoNNngYYIUHR0tJ0+eDJQHz9eJQO3atQXOF01pv/zyi2AfzdGYjvTVV1/JwIEDBc04TOYROHr0qKAJeuLEifLss8+qrhr+Zszjf7OStm7dKhkzZpRq1aqp0/bv3y/ffPONDB8+XDAHlckcAoMGDZI6dep4CvP1+/B1zHNBgBuOqgHjBtbe8jGh3dfE5wD58PQQCKAWjAcIHvYFChSQO++8U9q1a6fe6qdPny4rV66Ujh07hlACLw2EAFogvv32W1Wj2rt3r0yZMkWaNWvG30wgEA06d968edK5c2dP7gjGgS4C9D/269dP7r77bo6K9tAxb8OXT/F1LFiJHFUDxhSXAwcOKBYHDx6UkiVLBsuF14VIAM4XwwsGDx7smeby66+/qloXskZULPb/hgg5wMtRA16yZIm6SuPP30yAEA04HWNXUOOtXLmyyh1O9+uvv1bbWkWCU5IMAO9Hlr5+H76O+ZGVz1McVQPGqFrUtEaMGCFwAKNHj/apNA8aTwAPENjg/fffV4V16dJFNa+NHTtWli1bpt7u0RfMZB4BzGNEDRgj0fEWj7ESxYoV42/GPBP4LAldZVrXGU7AgB4MHh01apSyU58+fXxex4PGE/DlUzB2As+xtWvXqlZWjDcKNjlyHvDly5dVM2ewUHidsQRoH2P5ppe7L/6+jqWXD783lgAGAmnT94wtibmnR8DX78PXsfTySf29Ix1waiW5TwIkQAIkQAJWI+CoPmCrwaU8JEACJEACJJAWATrgtMjwOAmQAAmQAAkYSIAO2EC4zJoESIAESIAE0iJAB5wWGR4nAYcT6NSpk9SoUcPhWlI9ErAuATpg69qGkpGAYQQwRQzTkYoWLSpr1qwxrBxmTAIkkDYBjoJOmw2/IQHHEvjwww8FgTmqV68uP/74owr+71hlqRgJWJQAHbBFDUOxSMBIAggegFjDiNeNyD6I082Vw4wkzrxJ4EYCbIK+kQmPkICjCWzevFmtd4pwrStWrJCyZcsqZ+xopakcCViQAGvAFjQKRSIBIwk888wzsmPHDqlSpYoqJjY2VjZu3KiOGVku8yYBEkhJgA44JQ/ukYCjCSB8HuI/r1+/XhDnFgkriKEZevLkyWp1JHWQ/0iABAwnwCZowxGzABKwDoH58+dLxYoVPc4XkmFhhl69esnnn39uHUEpCQm4gABrwC4wMlUkARIgARKwHgHWgK1nE0pEAiRAAiTgAgJ0wC4wMlUkARIgARKwHgE6YOvZhBKRAAmQAAm4gAAdsAuMTBVJgARIgASsR4AO2Ho2oUQkQAIkQAIuIEAH7AIjU0USIAESIAHrEfg/g/oU8a+9H/EAAAAASUVORK5CYII=\n" 222 | }, 223 | "metadata": {}, 224 | "output_type": "display_data" 225 | } 226 | ], 227 | "source": [ 228 | "%%R -i df\n", 229 | "\n", 230 | "# Plotting using R\n", 231 | "plt <- ggplot(df) +\n", 232 | " geom_point(aes(A,B))\n", 233 | "\n", 234 | "plt" 235 | ] 236 | }, 237 | { 238 | "cell_type": "markdown", 239 | "metadata": {}, 240 | "source": [ 241 | "## Thoughts\n", 242 | "\n", 243 | "#### Why I like this setup\n", 244 | "- It lets me do some things in Python (hitting APIs, scraping, etc)\n", 245 | "- It lets do other things in R (statistical calculations, visualization, etc)\n", 246 | "\n", 247 | "#### How I use this setup\n", 248 | "- If things start to get complicated, I move Python functions into `.py` files in the repo and then call those functions from the notebook. This keeps the notebook clean.\n", 249 | "- While you can read the pandas dataframe directly into R by putting `%%R -i df` at the top of the cell, I prefer to save human-readable CSV files at the end of the python cells (usually _wide_ format), and then read those CSV files into the R cells and convert it to whatever format I need to visualize it (usually _long_ format). This allows me to:\n", 250 | " - send the CSV data files along with the article to my editor\n", 251 | " - file the R code + CSV files to the charts team and they can just run it and modify as needed\n", 252 | "\n", 253 | "#### Other thoughts about ths setup\n", 254 | "- I have found it useful to learn R (or Python) while on deadline. When I was learning R it allowed me to switch back to Python if I was stuck on a step and the deadline was approaching, and then switch back to R to finish up.\n", 255 | "- Storing code away in functions in separate files let me keep the notebooks very clean and readable and proved to be a good way to annotate my process for the quantitative edit.\n", 256 | "- One-click pipeline, I could quickly change a variable and re-run an analysis with new data or a different query.\n", 257 | "\n" 258 | ] 259 | }, 260 | { 261 | "cell_type": "code", 262 | "execution_count": null, 263 | "metadata": {}, 264 | "outputs": [], 265 | "source": [] 266 | } 267 | ], 268 | "metadata": { 269 | "kernelspec": { 270 | "display_name": "Python 3 (ipykernel)", 271 | "language": "python", 272 | "name": "python3" 273 | }, 274 | "language_info": { 275 | "codemirror_mode": { 276 | "name": "ipython", 277 | "version": 3 278 | }, 279 | "file_extension": ".py", 280 | "mimetype": "text/x-python", 281 | "name": "python", 282 | "nbconvert_exporter": "python", 283 | "pygments_lexer": "ipython3", 284 | "version": "3.9.7" 285 | } 286 | }, 287 | "nbformat": 4, 288 | "nbformat_minor": 4 289 | } 290 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | jupyter 2 | pandas 3 | scikit-learn 4 | rpy2 5 | tzlocal 6 | matplotlib 7 | -------------------------------------------------------------------------------- /setup-fte.R: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env RScript 2 | 3 | # Step 1: Make sure your computer has the FiveThirtyEight fonts installed 4 | # (ask someone on viz team for the fonts or find them inside our Google Drive) 5 | 6 | # Step 2: Make a GitHub personal access token 7 | # https://github.com/settings/tokens 8 | # make sure all boxes in the repo scope are checked. 9 | 10 | # Step 3: Insert the auth token below in place of **** and then run this script 11 | require('extrafont') 12 | require('devtools') 13 | install_github("fivethirtyeight/theme538", auth_token = "****") 14 | font_import(prompt=FALSE) 15 | -------------------------------------------------------------------------------- /setup.R: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env RScript 2 | 3 | # A function that installs packages 4 | installPackage <- function(pkg) { 5 | install.packages(pkg, repos='http://cran.us.r-project.org', verbose = TRUE) 6 | } 7 | 8 | # A list of packages to install, including tidyverse 9 | # (this includes ggplot2, dplyr, and several others...) 10 | # https://www.tidyverse.org/packages/ 11 | libs <- c("tidyverse", "extrafont", "Cairo", "devtools","gridExtra") 12 | 13 | # Apply the function above to the list of packages 14 | lapply(libs, installPackage) 15 | 16 | # Print successful completion message 17 | sprintf("Successfully loaded: %s", libs) 18 | --------------------------------------------------------------------------------