From fff9444da55d046fb33d6caaac6bf9b9048cf2a2 Mon Sep 17 00:00:00 2001
From: Jelle Treep <40466121+jelletreep@users.noreply.github.com>
Date: Wed, 27 Sep 2023 17:50:29 +0200
Subject: [PATCH] last minor revisions from pilot (#79)
---
book/Introduction_to_python_1.ipynb | 2 +-
book/Introduction_to_python_2.ipynb | 4 +-
book/Introduction_to_python_3.ipynb | 12 +-
book/Introduction_to_python_4.ipynb | 2 +-
book/_quarto.yml | 4 +
book/data-science-with-pandas-1.ipynb | 43 +-
book/data-science-with-pandas-2.ipynb | 14 +-
book/data-science-with-pandas-3.ipynb | 17 +-
book/data-science-with-pandas-4.ipynb | 10 +-
book/installation-and-setup.qmd | 19 +-
.../afternoon_exercises_solutions.ipynb | 1337 +++++++++++++++++
.../morning_exercises_solutions.ipynb | 301 +++-
course_materials/afternoon_exercises.ipynb | 174 ++-
.../empty_notebook_for_coding_along.ipynb | 92 ++
course_materials/morning_exercises.ipynb | 45 +-
.../afternoon_exercises_solutions.ipynb | 425 ------
16 files changed, 1887 insertions(+), 614 deletions(-)
create mode 100644 book/solutions/afternoon_exercises_solutions.ipynb
rename {course_materials => book}/solutions/morning_exercises_solutions.ipynb (62%)
create mode 100644 course_materials/empty_notebook_for_coding_along.ipynb
delete mode 100644 course_materials/solutions/afternoon_exercises_solutions.ipynb
diff --git a/book/Introduction_to_python_1.ipynb b/book/Introduction_to_python_1.ipynb
index 4b2f6ef..bb93656 100644
--- a/book/Introduction_to_python_1.ipynb
+++ b/book/Introduction_to_python_1.ipynb
@@ -273,7 +273,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.11.0"
+ "version": "3.8.10"
}
},
"nbformat": 4,
diff --git a/book/Introduction_to_python_2.ipynb b/book/Introduction_to_python_2.ipynb
index fca6fd1..3ecbe26 100644
--- a/book/Introduction_to_python_2.ipynb
+++ b/book/Introduction_to_python_2.ipynb
@@ -76,7 +76,7 @@
"When we want to make use of a function (referred to as calling the function), we type the name of the function followed by parentheses. Between the parentheses we can pass arguments.\n",
"\n",
"**Arguments**\n",
- "We typically provide a function with 'arguments' to tell python which values or variables are used to perform the body of the function. In the example below `type` is the function name and `pi_value` is the argument."
+ "Arguments are used by a function to perform the body of the function with the value of this argument. In the example below `type` is the function name and `pi_value` is the argument."
]
},
{
@@ -397,7 +397,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.11.0"
+ "version": "3.8.10"
}
},
"nbformat": 4,
diff --git a/book/Introduction_to_python_3.ipynb b/book/Introduction_to_python_3.ipynb
index 118aca0..a585a31 100644
--- a/book/Introduction_to_python_3.ipynb
+++ b/book/Introduction_to_python_3.ipynb
@@ -522,7 +522,7 @@
"source": [
"## Dictionaries\n",
"\n",
- "A dictionary is another way to store multiple items into one object. In dictionaries, however, this is done with keys and values. This can be useful for several reasons, one example is to store model settings, parameters or variable values for multiple scenarios."
+ "A dictionary is another way to store multiple items into one object. In dictionaries, however, this is done with keys and values. In dictionaries, keys are typically use to look up values. A good analogy may be the contact list in your phone where you use a name (key) to lookup a phone number (value). This can be useful for several reasons, one example is to store model settings, parameters or variable values for multiple scenarios. "
]
},
{
@@ -532,7 +532,7 @@
"metadata": {},
"outputs": [],
"source": [
- "my_dict = {'one': 'first', 'two': 'second'}\n",
+ "my_dict = {'one': 1, 'two': 2}\n",
"my_dict"
]
},
@@ -569,7 +569,7 @@
"metadata": {},
"outputs": [],
"source": [
- "my_dict['third'] = 'three'\n",
+ "my_dict['three'] = 3\n",
"my_dict"
]
},
@@ -578,7 +578,7 @@
"id": "1043ec01",
"metadata": {},
"source": [
- "Dictionary items are key-value pairs. The keys are changeable and unique. The values are changable, but not necessarily unique."
+ "Dictionary items are key-value pairs. The keys are changeable and always have to be unique (within a dictionary object). The values within a dictionary are changable, and don't have to be unique."
]
},
{
@@ -588,7 +588,7 @@
"metadata": {},
"outputs": [],
"source": [
- "my_dict['two'] = 'three'\n",
+ "my_dict['two'] = 5\n",
"my_dict"
]
},
@@ -738,7 +738,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.11.0"
+ "version": "3.8.10"
}
},
"nbformat": 4,
diff --git a/book/Introduction_to_python_4.ipynb b/book/Introduction_to_python_4.ipynb
index 603ecc1..f3ac93f 100644
--- a/book/Introduction_to_python_4.ipynb
+++ b/book/Introduction_to_python_4.ipynb
@@ -168,7 +168,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.11.0"
+ "version": "3.8.10"
}
},
"nbformat": 4,
diff --git a/book/_quarto.yml b/book/_quarto.yml
index 69525cf..0a3b4cf 100644
--- a/book/_quarto.yml
+++ b/book/_quarto.yml
@@ -28,6 +28,10 @@ book:
- data-science-with-pandas-2.ipynb
- data-science-with-pandas-3.ipynb
- data-science-with-pandas-4.ipynb
+ - part: "Exercises solutions"
+ chapters:
+ - solutions/morning_exercises_solutions.ipynb
+ - solutions/afternoon_exercises_solutions.ipynb
- what-next.qmd
- references.qmd
repo-url: https://github.com/UtrechtUniversity/workshop-introduction-to-python
diff --git a/book/data-science-with-pandas-1.ipynb b/book/data-science-with-pandas-1.ipynb
index 800957c..3d1cdc8 100644
--- a/book/data-science-with-pandas-1.ipynb
+++ b/book/data-science-with-pandas-1.ipynb
@@ -25,7 +25,7 @@
"\n",
"A library (aka package) is a collection of files (aka python scripts) that contains **functions** that can be used to perform specific tasks. A library may also contain data. The functions in a library are typically related and used for a specific purpose, e.g. there are libraries for plotting, handling audio data and machine learning and many many more. Some libraries are built into python, but most packages need to be installed before you can use it.\n",
"\n",
- "Important to add: libraries are developed and maintained by other Python users. A popular library like Pandas has a large user base and the maintainers are supported by several funders, which makes it a reliable library that is updated very frequently. But this is not always the case, on the other side of the spectrum, a library can also be published once and not maintained at all.\n",
+ "Libraries are developed and maintained by other Python users. That is why there are so many packages and this is great: there is a huge variety of functions available that you can use instead of programming them yourself. But it is important to be aware that the quality can differ. A popular library like Pandas has a large user base and the maintainers are supported by several funders, which makes it a reliable library that is updated very frequently. But this is not always the case, on the other side of the spectrum, a library can also be published once, badly designed/documented and/or not maintained at all. To check the quality of a library, you can check e.g. the number of downloads, the number of contributors, the number of open issues, the date of the last update and the number of stars on GitHub.\n",
"\n",
"## Pandas\n",
"The python library [**Pandas**](https://pandas.pydata.org/about/) is a popular open-source data analysis and data manipulation library for Python which was developed in 2008. The library has some similarities with R, mainly related to the DataFrame data type that is used to handle table like datasets.\n",
@@ -212,29 +212,6 @@
"It is, however, enough for a quick exploration of how the dataset looks like in terms of columns names, values, and potential reading errors."
]
},
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "
\n",
- "Exercise 1\n",
- " \n",
- "Now go to the Jupyter Dashboard in your internet browser and open the notebook `afternoon_exercises.ipynb` and do exercise 1.\n",
- "
"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "::: {.callout-note}\n",
- "As you can see in this exercise a DataFrame object comes with several methods that can be applied to the DataFrame. A method is similar to a function, but it can only be applied to the object it belongs to and has a different notation than a function.\n",
- "\n",
- "Compare the notation of the function `len`: `len(surveys_df)` \n",
- "with the DataFrame specific method `shape`: `surveys_df.shape`\n",
- ":::"
- ]
- },
{
"cell_type": "markdown",
"metadata": {},
@@ -356,12 +333,24 @@
"metadata": {},
"source": [
"
\n",
- "Exercise 2\n",
+ "Exercises 0 and 1\n",
" \n",
- "Now go to the Jupyter Dashboard in your internet browser and continue with exercise 2.\n",
+ "Now go to the Jupyter Dashboard in your internet browser and continue with exercises 0 and 1.\n",
"
"
]
},
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "::: {.callout-note}\n",
+ "As you can see in this exercise a DataFrame object comes with several methods that can be applied to the DataFrame. A method is similar to a function, but it can only be applied to the object it belongs to and has a different notation than a function.\n",
+ "\n",
+ "Compare the notation of the function `len`: `len(surveys_df)` \n",
+ "with the DataFrame specific method `shape`: `surveys_df.shape`\n",
+ ":::"
+ ]
+ },
{
"cell_type": "markdown",
"metadata": {},
@@ -439,7 +428,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.11.0"
+ "version": "3.8.10"
},
"vscode": {
"interpreter": {
diff --git a/book/data-science-with-pandas-2.ipynb b/book/data-science-with-pandas-2.ipynb
index 3aa722a..6f5bc4e 100644
--- a/book/data-science-with-pandas-2.ipynb
+++ b/book/data-science-with-pandas-2.ipynb
@@ -353,9 +353,9 @@
"metadata": {},
"source": [
"
\n",
- "Exercise 3 to 5\n",
+ "Exercise 2 to 4\n",
" \n",
- "Now go to the Jupyter Dashboard in your internet browser and continue with the afternoon exercises 3 to 5."
+ "Now go to the Jupyter Dashboard in your internet browser and continue with the afternoon exercises 2 to 4."
]
},
{
@@ -669,9 +669,9 @@
"metadata": {},
"source": [
"
\n",
- "Exercise 6 and 7\n",
+ "Exercise 5 and 6\n",
"\n",
- "Now go to the Jupyter Dashboard in your internet browser and continue with the afternoon exercises 6 and 7."
+ "Now go to the Jupyter Dashboard in your internet browser and continue with the afternoon exercises 5 and 6."
]
},
{
@@ -869,9 +869,9 @@
"metadata": {},
"source": [
"
\n",
- "Exercise 8 to 10\n",
+ "Exercise 7 to 9\n",
" \n",
- "Now go to the Jupyter Dashboard in your internet browser and continue with the afternoon exercises 8 to 10."
+ "Now go to the Jupyter Dashboard in your internet browser and continue with the afternoon exercises 7 to 9."
]
},
{
@@ -899,7 +899,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.11.0"
+ "version": "3.8.10"
}
},
"nbformat": 4,
diff --git a/book/data-science-with-pandas-3.ipynb b/book/data-science-with-pandas-3.ipynb
index e7400c7..d3bf853 100644
--- a/book/data-science-with-pandas-3.ipynb
+++ b/book/data-science-with-pandas-3.ipynb
@@ -193,17 +193,6 @@
"vertical_stack.reset_index()"
]
},
- {
- "cell_type": "markdown",
- "id": "f1db04a6-8ae2-44e4-9798-adc1b108c9d8",
- "metadata": {},
- "source": [
- "
\n",
- "Exercise 11\n",
- " \n",
- "Now go to the Jupyter Dashboard in your internet browser and continue with exercise 11.\n"
- ]
- },
{
"cell_type": "markdown",
"id": "7bc415a6",
@@ -315,9 +304,9 @@
"metadata": {},
"source": [
"
\n",
- "Exercise 12\n",
+ "Exercise 10 and 11\n",
" \n",
- "Now go to the Jupyter Dashboard in your internet browser and continue with exercise 12.\n"
+ "Now go to the Jupyter Dashboard in your internet browser and continue with exercise 10 and 11.\n"
]
},
{
@@ -508,7 +497,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.11.0"
+ "version": "3.8.10"
}
},
"nbformat": 4,
diff --git a/book/data-science-with-pandas-4.ipynb b/book/data-science-with-pandas-4.ipynb
index a4a9abe..99aced6 100644
--- a/book/data-science-with-pandas-4.ipynb
+++ b/book/data-science-with-pandas-4.ipynb
@@ -439,9 +439,9 @@
"metadata": {},
"source": [
"
\n",
- "Exercise 13\n",
+ "Exercise 12\n",
" \n",
- "Now go to the Jupyter Dashboard in your internet browser and continue with exercise 13.\n",
+ "Now go to the Jupyter Dashboard in your internet browser and continue with exercise 12.\n",
"
\n",
- "Exercise 14\n",
+ "Exercise 13\n",
" \n",
- "Now go to the Jupyter Dashboard in your internet browser and continue with exercise 14.\n",
+ "Now go to the Jupyter Dashboard in your internet browser and continue with exercise 13.\n",
"
"
]
},
@@ -564,7 +564,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.11.0"
+ "version": "3.8.10"
},
"toc": {
"base_numbering": 1,
diff --git a/book/installation-and-setup.qmd b/book/installation-and-setup.qmd
index 08be8bf..6a0ace9 100644
--- a/book/installation-and-setup.qmd
+++ b/book/installation-and-setup.qmd
@@ -72,7 +72,7 @@ version 9 and below, are not).
3. Move the downloaded zip to the folder where you want to store these course materials.
4. Unzip the zip file.
-In your `python-workshop` you will see two folders called `data` and `solutions` and the following files:
+In your `python-workshop` you will see a folders called `data` and the following files:
```
python-workshop
@@ -82,11 +82,9 @@ python-workshop
│ ├── species.csv
│ ├── surveys.csv
│ └── plots.csv
-├── solutions
-│ ├── morning_exercises_solutions.ipynb
-│ └── afternoon_exercises_solutions.ipynb
├── morning_exercises.ipynb
-└── afternoon_exercises.ipynb
+├── afternoon_exercises.ipynb
+└── empty_notebook_for_code_along.ipynb
```
## Launch Python interface
@@ -139,9 +137,12 @@ Make your choice and click "Ok, and don't show again" button.
2. Find the "Notebook" tab and click on the "Launch" button.
Anaconda will open a new browser window or tab with a Notebook Dashboard showing you the
contents of your Home (or User) folder.
-3. Navigate to the `python-workshop` directory by clicking on the directory names leading to it.
-`Desktop` and then `python-workshop`:
-4. Launch the notebook by clicking on the "New" button and then selecting "Python 3".
+3. Navigate to the `data` directory by clicking on the directory names leading to it.
+`Desktop`, `python-workshop`, then `data`:
+4. Launch the notebook called `empty_notebook_for_code_along.ipynb` by clicking on it.
+5. Run the first code cell just below "Test installation" by clicking on it and then click on the 'play button'.
+If the output of the cell displays 4 version numbers and the words "No errors! Ready to code!" instead of an error message, your installation is successful. If not, contact us at [RDM walk in hours][walk-in-hours] or reply to the welcome email.
+
:::
### Option B: IPython interpreter
@@ -176,7 +177,7 @@ This workshop will make use of the following Python packages:
- `matplotlib`
- `numpy`
-Anaconda Navigator comes with these packages, so you are ready to go. If you are using another option to work with Python, you need to install these packages. If you need help with this, please ask the internet, your colleagues or us (see welcome email).
+Anaconda Navigator comes with these packages, so you are ready to go. If you are using another option to work with Python, you need to install these packages. We then assume that you know how to install packages, otherwise we recommend using Anaconda instead. If for some reason you cannot work with Anaconda and you need help with installing packages, we are happy to help during the [RDM walk in hours](https://www.uu.nl/en/research/research-data-management/workshops/walk-in-hours-research-data-and-software), or email us by replying to the welcome email.
## References {.unnumbered}
diff --git a/book/solutions/afternoon_exercises_solutions.ipynb b/book/solutions/afternoon_exercises_solutions.ipynb
new file mode 100644
index 0000000..7c53bbe
--- /dev/null
+++ b/book/solutions/afternoon_exercises_solutions.ipynb
@@ -0,0 +1,1337 @@
+{
+ "cells": [
+ {
+ "cell_type": "raw",
+ "id": "14f401b8-2d1d-4a01-a3c8-ed2c59e66d29",
+ "metadata": {},
+ "source": [
+ "---\n",
+ "format: html\n",
+ "execute: \n",
+ " enabled: true\n",
+ " error: true\n",
+ "---"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "67d94b6e",
+ "metadata": {},
+ "source": [
+ "# Afternoon Exercises: Working with data {.unnumbered}"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "id": "2c6372a4",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import pandas as pd\n",
+ "surveys_df = pd.read_csv('../../course_materials/data/surveys.csv') # in your notebook the path should be 'data/surveys.csv'"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "507d1c2c-98b8-4a67-b2e5-b3a3031a5b5f",
+ "metadata": {},
+ "source": [
+ "### Exercise 0\n",
+ "\n",
+ "Type the following commands and check the outputs. Can you tell what each command does? What is the difference between commands with and without parenthesis?\n",
+ "\n",
+ "```python\n",
+ "surveys_df.shape # Answer: the dimensions of the dataframe\n",
+ "surveys_df.columns # Answer: the column names of the dataframe\n",
+ "surveys_df.index # Answer: the index (row labels) of the dataframe\n",
+ "surveys_df.dtypes # Answer: the data types of each column\n",
+ "surveys_df.head() # Answer: the first n rows of the dataframe\n",
+ "surveys_df.tail() # Answer: the last n rows of the dataframe\n",
+ "```"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "0514bad4-1266-4553-9752-29dcf3166d21",
+ "metadata": {},
+ "source": [
+ "### Exercise 1\n",
+ "Perform some basic statistics on the weight column. For practical reasons, it can be useful to first create a variable `weight` that contains the just the weight column. It will make the code look a bit cleaner. Can you tell what each method listed below does? Look at our explorative plot, do the statistics make sense?\n",
+ "\n",
+ "```python\n",
+ "weight=surveys_df['weight'] # Answer: creates a new variable that contains the weight column\n",
+ "weight.min() # Answer: the minimum value of the weight column\n",
+ "weight.max() # Answer: the maximum value of the weight column\n",
+ "weight.mean() # Answer: the mean value of the weight column\n",
+ "weight.std() # Answer: the standard deviation of the weight column\n",
+ "weight.count() # Answer: the number of non-NaN values in the weight column\n",
+ "```"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "2bcb581f",
+ "metadata": {},
+ "source": [
+ "### Exercise 2\n",
+ "- Swap the order of column names in `surveys_df[['plot_id', 'species_id']]`\n",
+ "- Repeat one of the column names like `surveys_df[['plot_id', 'plot_id', 'species_id']]`.\n",
+ "What do the results look like and why? \n",
+ "\n",
+ "> Answer: the column names are repeated and the data is displayed twice. Column names do not have to be unique.\n",
+ "\n",
+ "- Which error occurs in `surveys_df['plot_id', 'species_id']` and why? \n",
+ "\n",
+ "> Answer: KeyError: ('plot_id', 'species_id'). The column names are not in a list. We need double square brackets to select multiple columns.\n",
+ "\n",
+ "- Which error occurs in `surveys_df['speciess']`? \n",
+ "\n",
+ "> Answer: KeyError: 'speciess'. The column name does not exist. Typo."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "3731f5fd",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " species_id plot_id\n",
+ "0 NL 2\n",
+ "1 NL 3\n",
+ "2 DM 2\n",
+ "3 DM 7\n",
+ "4 DM 3\n",
+ "... ... ...\n",
+ "35544 AH 15\n",
+ "35545 AH 15\n",
+ "35546 RM 10\n",
+ "35547 DO 7\n",
+ "35548 NaN 5\n",
+ "\n",
+ "[35549 rows x 2 columns]\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(surveys_df[['species_id', 'plot_id']])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "b71788b1",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "
\n",
+ "\n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
\n",
+ "
plot_id
\n",
+ "
plot_id
\n",
+ "
species_id
\n",
+ "
\n",
+ " \n",
+ " \n",
+ "
\n",
+ "
0
\n",
+ "
2
\n",
+ "
2
\n",
+ "
NL
\n",
+ "
\n",
+ "
\n",
+ "
1
\n",
+ "
3
\n",
+ "
3
\n",
+ "
NL
\n",
+ "
\n",
+ "
\n",
+ "
2
\n",
+ "
2
\n",
+ "
2
\n",
+ "
DM
\n",
+ "
\n",
+ "
\n",
+ "
3
\n",
+ "
7
\n",
+ "
7
\n",
+ "
DM
\n",
+ "
\n",
+ "
\n",
+ "
4
\n",
+ "
3
\n",
+ "
3
\n",
+ "
DM
\n",
+ "
\n",
+ "
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
\n",
+ "
\n",
+ "
35544
\n",
+ "
15
\n",
+ "
15
\n",
+ "
AH
\n",
+ "
\n",
+ "
\n",
+ "
35545
\n",
+ "
15
\n",
+ "
15
\n",
+ "
AH
\n",
+ "
\n",
+ "
\n",
+ "
35546
\n",
+ "
10
\n",
+ "
10
\n",
+ "
RM
\n",
+ "
\n",
+ "
\n",
+ "
35547
\n",
+ "
7
\n",
+ "
7
\n",
+ "
DO
\n",
+ "
\n",
+ "
\n",
+ "
35548
\n",
+ "
5
\n",
+ "
5
\n",
+ "
NaN
\n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
35549 rows × 3 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " plot_id plot_id species_id\n",
+ "0 2 2 NL\n",
+ "1 3 3 NL\n",
+ "2 2 2 DM\n",
+ "3 7 7 DM\n",
+ "4 3 3 DM\n",
+ "... ... ... ...\n",
+ "35544 15 15 AH\n",
+ "35545 15 15 AH\n",
+ "35546 10 10 RM\n",
+ "35547 7 7 DO\n",
+ "35548 5 5 NaN\n",
+ "\n",
+ "[35549 rows x 3 columns]"
+ ]
+ },
+ "execution_count": 7,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "surveys_df[['plot_id', 'plot_id', 'species_id']]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "bb68a995",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Unexpected exception formatting exception. Falling back to standard exception\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Traceback (most recent call last):\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/pandas/core/indexes/base.py\", line 3802, in get_loc\n",
+ " return self._engine.get_loc(casted_key)\n",
+ " File \"pandas/_libs/index.pyx\", line 138, in pandas._libs.index.IndexEngine.get_loc\n",
+ " File \"pandas/_libs/index.pyx\", line 165, in pandas._libs.index.IndexEngine.get_loc\n",
+ " File \"pandas/_libs/hashtable_class_helper.pxi\", line 5745, in pandas._libs.hashtable.PyObjectHashTable.get_item\n",
+ " File \"pandas/_libs/hashtable_class_helper.pxi\", line 5753, in pandas._libs.hashtable.PyObjectHashTable.get_item\n",
+ "KeyError: ('plot_id', 'species_id')\n",
+ "\n",
+ "The above exception was the direct cause of the following exception:\n",
+ "\n",
+ "Traceback (most recent call last):\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/IPython/core/interactiveshell.py\", line 3460, in run_code\n",
+ " exec(code_obj, self.user_global_ns, self.user_ns)\n",
+ " File \"/tmp/ipykernel_16478/997369930.py\", line 1, in \n",
+ " surveys_df['plot_id', 'species_id']\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/pandas/core/frame.py\", line 3807, in __getitem__\n",
+ " indexer = self.columns.get_loc(key)\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/pandas/core/indexes/base.py\", line 3804, in get_loc\n",
+ " raise KeyError(key) from err\n",
+ "KeyError: ('plot_id', 'species_id')\n",
+ "\n",
+ "During handling of the above exception, another exception occurred:\n",
+ "\n",
+ "Traceback (most recent call last):\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/IPython/core/interactiveshell.py\", line 2057, in showtraceback\n",
+ " stb = self.InteractiveTB.structured_traceback(\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/IPython/core/ultratb.py\", line 1288, in structured_traceback\n",
+ " return FormattedTB.structured_traceback(\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/IPython/core/ultratb.py\", line 1177, in structured_traceback\n",
+ " return VerboseTB.structured_traceback(\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/IPython/core/ultratb.py\", line 1030, in structured_traceback\n",
+ " formatted_exception = self.format_exception_as_a_whole(etype, evalue, etb, number_of_lines_of_context,\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/IPython/core/ultratb.py\", line 935, in format_exception_as_a_whole\n",
+ " self.get_records(etb, number_of_lines_of_context, tb_offset) if etb else []\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/IPython/core/ultratb.py\", line 987, in get_records\n",
+ " style = stack_data.style_with_executing_node(style, self._tb_highlight)\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/stack_data/core.py\", line 455, in style_with_executing_node\n",
+ " class NewStyle(style):\n",
+ " File \"/usr/lib/python3/dist-packages/pygments/style.py\", line 91, in __new__\n",
+ " ndef[4] = colorformat(styledef[3:])\n",
+ " File \"/usr/lib/python3/dist-packages/pygments/style.py\", line 58, in colorformat\n",
+ " assert False, \"wrong color format %r\" % text\n",
+ "AssertionError: wrong color format 'ansiyellow'\n"
+ ]
+ }
+ ],
+ "source": [
+ "surveys_df['plot_id', 'species_id'] "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "b74edc72",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Unexpected exception formatting exception. Falling back to standard exception\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Traceback (most recent call last):\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/pandas/core/indexes/base.py\", line 3802, in get_loc\n",
+ " return self._engine.get_loc(casted_key)\n",
+ " File \"pandas/_libs/index.pyx\", line 138, in pandas._libs.index.IndexEngine.get_loc\n",
+ " File \"pandas/_libs/index.pyx\", line 165, in pandas._libs.index.IndexEngine.get_loc\n",
+ " File \"pandas/_libs/hashtable_class_helper.pxi\", line 5745, in pandas._libs.hashtable.PyObjectHashTable.get_item\n",
+ " File \"pandas/_libs/hashtable_class_helper.pxi\", line 5753, in pandas._libs.hashtable.PyObjectHashTable.get_item\n",
+ "KeyError: 'speciess'\n",
+ "\n",
+ "The above exception was the direct cause of the following exception:\n",
+ "\n",
+ "Traceback (most recent call last):\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/IPython/core/interactiveshell.py\", line 3460, in run_code\n",
+ " exec(code_obj, self.user_global_ns, self.user_ns)\n",
+ " File \"/tmp/ipykernel_16478/158671928.py\", line 1, in \n",
+ " surveys_df['speciess']\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/pandas/core/frame.py\", line 3807, in __getitem__\n",
+ " indexer = self.columns.get_loc(key)\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/pandas/core/indexes/base.py\", line 3804, in get_loc\n",
+ " raise KeyError(key) from err\n",
+ "KeyError: 'speciess'\n",
+ "\n",
+ "During handling of the above exception, another exception occurred:\n",
+ "\n",
+ "Traceback (most recent call last):\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/IPython/core/interactiveshell.py\", line 2057, in showtraceback\n",
+ " stb = self.InteractiveTB.structured_traceback(\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/IPython/core/ultratb.py\", line 1288, in structured_traceback\n",
+ " return FormattedTB.structured_traceback(\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/IPython/core/ultratb.py\", line 1177, in structured_traceback\n",
+ " return VerboseTB.structured_traceback(\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/IPython/core/ultratb.py\", line 1030, in structured_traceback\n",
+ " formatted_exception = self.format_exception_as_a_whole(etype, evalue, etb, number_of_lines_of_context,\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/IPython/core/ultratb.py\", line 935, in format_exception_as_a_whole\n",
+ " self.get_records(etb, number_of_lines_of_context, tb_offset) if etb else []\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/IPython/core/ultratb.py\", line 987, in get_records\n",
+ " style = stack_data.style_with_executing_node(style, self._tb_highlight)\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/stack_data/core.py\", line 455, in style_with_executing_node\n",
+ " class NewStyle(style):\n",
+ " File \"/usr/lib/python3/dist-packages/pygments/style.py\", line 91, in __new__\n",
+ " ndef[4] = colorformat(styledef[3:])\n",
+ " File \"/usr/lib/python3/dist-packages/pygments/style.py\", line 58, in colorformat\n",
+ " assert False, \"wrong color format %r\" % text\n",
+ "AssertionError: wrong color format 'ansiyellow'\n"
+ ]
+ }
+ ],
+ "source": [
+ "surveys_df['speciess']"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "119b576b",
+ "metadata": {},
+ "source": [
+ "### Exercise 3\n",
+ "What happens when you call:\n",
+ "\n",
+ "- `surveys_df[0:1]` Answer: shows the first row of the dataframe\n",
+ "- `surveys_df[:4]` Answer: shows the first 4 rows of the dataframe from index 0 to index 3\n",
+ "- `surveys_df[:-1]` Answer: shows all rows of the dataframe except the last row"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "id": "bd3b4c74",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "
\n",
+ "\n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
\n",
+ "
record_id
\n",
+ "
month
\n",
+ "
day
\n",
+ "
year
\n",
+ "
plot_id
\n",
+ "
species_id
\n",
+ "
sex
\n",
+ "
hindfoot_length
\n",
+ "
weight
\n",
+ "
\n",
+ " \n",
+ " \n",
+ "
\n",
+ "
0
\n",
+ "
1
\n",
+ "
7
\n",
+ "
16
\n",
+ "
1977
\n",
+ "
2
\n",
+ "
NL
\n",
+ "
M
\n",
+ "
32.0
\n",
+ "
NaN
\n",
+ "
\n",
+ "
\n",
+ "
1
\n",
+ "
2
\n",
+ "
7
\n",
+ "
16
\n",
+ "
1977
\n",
+ "
3
\n",
+ "
NL
\n",
+ "
M
\n",
+ "
33.0
\n",
+ "
NaN
\n",
+ "
\n",
+ "
\n",
+ "
2
\n",
+ "
3
\n",
+ "
7
\n",
+ "
16
\n",
+ "
1977
\n",
+ "
2
\n",
+ "
DM
\n",
+ "
F
\n",
+ "
37.0
\n",
+ "
NaN
\n",
+ "
\n",
+ "
\n",
+ "
3
\n",
+ "
4
\n",
+ "
7
\n",
+ "
16
\n",
+ "
1977
\n",
+ "
7
\n",
+ "
DM
\n",
+ "
M
\n",
+ "
36.0
\n",
+ "
NaN
\n",
+ "
\n",
+ "
\n",
+ "
4
\n",
+ "
5
\n",
+ "
7
\n",
+ "
16
\n",
+ "
1977
\n",
+ "
3
\n",
+ "
DM
\n",
+ "
M
\n",
+ "
35.0
\n",
+ "
NaN
\n",
+ "
\n",
+ "
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
\n",
+ "
\n",
+ "
35543
\n",
+ "
35544
\n",
+ "
12
\n",
+ "
31
\n",
+ "
2002
\n",
+ "
15
\n",
+ "
US
\n",
+ "
NaN
\n",
+ "
NaN
\n",
+ "
NaN
\n",
+ "
\n",
+ "
\n",
+ "
35544
\n",
+ "
35545
\n",
+ "
12
\n",
+ "
31
\n",
+ "
2002
\n",
+ "
15
\n",
+ "
AH
\n",
+ "
NaN
\n",
+ "
NaN
\n",
+ "
NaN
\n",
+ "
\n",
+ "
\n",
+ "
35545
\n",
+ "
35546
\n",
+ "
12
\n",
+ "
31
\n",
+ "
2002
\n",
+ "
15
\n",
+ "
AH
\n",
+ "
NaN
\n",
+ "
NaN
\n",
+ "
NaN
\n",
+ "
\n",
+ "
\n",
+ "
35546
\n",
+ "
35547
\n",
+ "
12
\n",
+ "
31
\n",
+ "
2002
\n",
+ "
10
\n",
+ "
RM
\n",
+ "
F
\n",
+ "
15.0
\n",
+ "
14.0
\n",
+ "
\n",
+ "
\n",
+ "
35547
\n",
+ "
35548
\n",
+ "
12
\n",
+ "
31
\n",
+ "
2002
\n",
+ "
7
\n",
+ "
DO
\n",
+ "
M
\n",
+ "
36.0
\n",
+ "
51.0
\n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
35548 rows × 9 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " record_id month day year plot_id species_id sex hindfoot_length \\\n",
+ "0 1 7 16 1977 2 NL M 32.0 \n",
+ "1 2 7 16 1977 3 NL M 33.0 \n",
+ "2 3 7 16 1977 2 DM F 37.0 \n",
+ "3 4 7 16 1977 7 DM M 36.0 \n",
+ "4 5 7 16 1977 3 DM M 35.0 \n",
+ "... ... ... ... ... ... ... ... ... \n",
+ "35543 35544 12 31 2002 15 US NaN NaN \n",
+ "35544 35545 12 31 2002 15 AH NaN NaN \n",
+ "35545 35546 12 31 2002 15 AH NaN NaN \n",
+ "35546 35547 12 31 2002 10 RM F 15.0 \n",
+ "35547 35548 12 31 2002 7 DO M 36.0 \n",
+ "\n",
+ " weight \n",
+ "0 NaN \n",
+ "1 NaN \n",
+ "2 NaN \n",
+ "3 NaN \n",
+ "4 NaN \n",
+ "... ... \n",
+ "35543 NaN \n",
+ "35544 NaN \n",
+ "35545 NaN \n",
+ "35546 14.0 \n",
+ "35547 51.0 \n",
+ "\n",
+ "[35548 rows x 9 columns]"
+ ]
+ },
+ "execution_count": 10,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "surveys_df[0:1]\n",
+ "surveys_df[:4] \n",
+ "surveys_df[:-1] "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "4fc54c12",
+ "metadata": {},
+ "source": [
+ "### Exercise 4\n",
+ "What happens in the following two examples?\n",
+ "\n",
+ "- ```surveys_df.iloc[0:4, 1:4]```;\n",
+ "- ```surveys_df.loc[0:4, 1:4]```.\n",
+ "\n",
+ "How are the two commands different? \n",
+ "\n",
+ "> Answer: iloc uses integer indices, loc uses labels. The first command will return the first 4 rows and the columns with integer indices 1, 2 and 3. The second command will return the first 4 rows and the columns with labels 1, 2 and 3. Since there are no columns with these labels, the second command will return an error."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "id": "6680a6fe",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " month day year\n",
+ "0 7 16 1977\n",
+ "1 7 16 1977\n",
+ "2 7 16 1977\n",
+ "3 7 16 1977\n",
+ "Unexpected exception formatting exception. Falling back to standard exception\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Traceback (most recent call last):\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/IPython/core/interactiveshell.py\", line 3460, in run_code\n",
+ " exec(code_obj, self.user_global_ns, self.user_ns)\n",
+ " File \"/tmp/ipykernel_16478/1314140639.py\", line 2, in \n",
+ " surveys_df.loc[0:4, 1:4] # the function loc works with indices for rows (0:4),\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/pandas/core/indexing.py\", line 1067, in __getitem__\n",
+ " return self._getitem_tuple(key)\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/pandas/core/indexing.py\", line 1256, in _getitem_tuple\n",
+ " return self._getitem_tuple_same_dim(tup)\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/pandas/core/indexing.py\", line 924, in _getitem_tuple_same_dim\n",
+ " retval = getattr(retval, self.name)._getitem_axis(key, axis=i)\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/pandas/core/indexing.py\", line 1290, in _getitem_axis\n",
+ " return self._get_slice_axis(key, axis=axis)\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/pandas/core/indexing.py\", line 1324, in _get_slice_axis\n",
+ " indexer = labels.slice_indexer(slice_obj.start, slice_obj.stop, slice_obj.step)\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/pandas/core/indexes/base.py\", line 6559, in slice_indexer\n",
+ " start_slice, end_slice = self.slice_locs(start, end, step=step)\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/pandas/core/indexes/base.py\", line 6767, in slice_locs\n",
+ " start_slice = self.get_slice_bound(start, \"left\")\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/pandas/core/indexes/base.py\", line 6676, in get_slice_bound\n",
+ " label = self._maybe_cast_slice_bound(label, side)\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/pandas/core/indexes/base.py\", line 6623, in _maybe_cast_slice_bound\n",
+ " raise self._invalid_indexer(\"slice\", label)\n",
+ "TypeError: cannot do slice indexing on Index with these indexers [1] of type int\n",
+ "\n",
+ "During handling of the above exception, another exception occurred:\n",
+ "\n",
+ "Traceback (most recent call last):\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/IPython/core/interactiveshell.py\", line 2057, in showtraceback\n",
+ " stb = self.InteractiveTB.structured_traceback(\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/IPython/core/ultratb.py\", line 1288, in structured_traceback\n",
+ " return FormattedTB.structured_traceback(\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/IPython/core/ultratb.py\", line 1177, in structured_traceback\n",
+ " return VerboseTB.structured_traceback(\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/IPython/core/ultratb.py\", line 1030, in structured_traceback\n",
+ " formatted_exception = self.format_exception_as_a_whole(etype, evalue, etb, number_of_lines_of_context,\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/IPython/core/ultratb.py\", line 935, in format_exception_as_a_whole\n",
+ " self.get_records(etb, number_of_lines_of_context, tb_offset) if etb else []\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/IPython/core/ultratb.py\", line 987, in get_records\n",
+ " style = stack_data.style_with_executing_node(style, self._tb_highlight)\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/stack_data/core.py\", line 455, in style_with_executing_node\n",
+ " class NewStyle(style):\n",
+ " File \"/usr/lib/python3/dist-packages/pygments/style.py\", line 91, in __new__\n",
+ " ndef[4] = colorformat(styledef[3:])\n",
+ " File \"/usr/lib/python3/dist-packages/pygments/style.py\", line 58, in colorformat\n",
+ " assert False, \"wrong color format %r\" % text\n",
+ "AssertionError: wrong color format 'ansiyellow'\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(surveys_df.iloc[0:4, 1:4])\n",
+ "surveys_df.loc[0:4, 1:4] "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "7b12cdaf",
+ "metadata": {},
+ "source": [
+ "### Exercise 5\n",
+ "- Create a new DataFrame that only contains observations from the original with sex values that are not female or male. Print the number of rows in this new DataFrame. Verify the result by comparing the number of rows in the new DataFrame with the number of rows in the surveys DataFrame where sex is NaN (hint: there is a function `isnull`)."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "id": "53f7777a",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Number of rows: 2511\n",
+ "Unique values in column 'sex': [nan]\n"
+ ]
+ }
+ ],
+ "source": [
+ "df = surveys_df[(surveys_df['sex'] != 'M') & (surveys_df['sex'] != 'F')]\n",
+ "print(\"Number of rows not female or male:\", len(df))\n",
+ "print(\"Number of rows NaN:\", len(surveys_df['sex'].isnull()))\n",
+ "print(\"Unique values in column 'sex':\", df['sex'].unique())"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "b34b321b",
+ "metadata": {},
+ "source": [
+ "### Exercise 6: Putting it all together \n",
+ "1. Clean the column *sex* (leave out samples of which we do not know whether they are male or female) and save the result as a new dataframe `clean_df`.\n",
+ "2. Fill undefined *weight* values with the mean of all valid weights in `surveys_df`.\n",
+ "3. Calculate the average weight of that new DataFrame `clean_df`"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "id": "570cbd6c",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Average weight of surveys_df: 42.672428212991356\n",
+ "Average weight of clean_df: 42.60316325896464\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Step 1\n",
+ "# sex is 'F' or 'M'. The `|` means or.\n",
+ "clean_df = surveys_df[(surveys_df['sex']=='F') | (surveys_df['sex']=='M')]\n",
+ "# Alternative solution: select columns where 'not' sex is null. The `~` means not.\n",
+ "clean_df = surveys_df[~(surveys_df['sex'].isnull())]\n",
+ "\n",
+ "# Step 2\n",
+ "clean_df.weight.fillna(surveys_df.weight.mean())\n",
+ "\n",
+ "# Step 3\n",
+ "print(\"Average weight of surveys_df:\", surveys_df.weight.mean())\n",
+ "print(\"Average weight of clean_df:\", clean_df.weight.mean())"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "ccb33c2e",
+ "metadata": {},
+ "source": [
+ "### Exercise 7\n",
+ "Let's see in which plots animals get more food. Calculate the average weight per plot! Complete the code below."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "733aba46",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "plot_id\n",
+ "1 51.822911\n",
+ "2 52.251688\n",
+ "3 32.654386\n",
+ "4 47.928189\n",
+ "5 40.947802\n",
+ "6 36.738893\n",
+ "7 20.663009\n",
+ "8 47.758001\n",
+ "9 51.432358\n",
+ "10 18.541219\n",
+ "11 43.451757\n",
+ "12 49.496169\n",
+ "13 40.445660\n",
+ "14 46.277199\n",
+ "15 27.042578\n",
+ "16 24.585417\n",
+ "17 47.889593\n",
+ "18 40.005922\n",
+ "19 21.105166\n",
+ "20 48.665303\n",
+ "21 24.627794\n",
+ "22 54.146379\n",
+ "23 19.634146\n",
+ "24 43.679167\n",
+ "Name: weight, dtype: float64"
+ ]
+ },
+ "execution_count": 2,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "grouped_data = surveys_df.groupby(\"plot_id\")\n",
+ "grouped_data['weight'].mean()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "2bccb9da",
+ "metadata": {},
+ "source": [
+ "### Exercise 8\n",
+ "See below a more complex grouping example. Investigate the group keys and row indexes for this more complex grouping example. \n",
+ "Why are there more than 48 groups? Answer: nan values are not ignored when grouping.\n",
+ "Calculate the average weight per group.\n",
+ "What happened to the third group and why does it not turn up in our statistics? Answer: the third group contains only nan values and is therefore not included in the statistics."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "ee674ae9",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "72\n"
+ ]
+ },
+ {
+ "data": {
+ "text/plain": [
+ "dict_keys([('F', 1), ('F', 2), ('F', 3), ('F', 4), ('F', 5), ('F', 6), ('F', 7), ('F', 8), ('F', 9), ('F', 10), ('F', 11), ('F', 12), ('F', 13), ('F', 14), ('F', 15), ('F', 16), ('F', 17), ('F', 18), ('F', 19), ('F', 20), ('F', 21), ('F', 22), ('F', 23), ('F', 24), ('M', 1), ('M', 2), ('M', 3), ('M', 4), ('M', 5), ('M', 6), ('M', 7), ('M', 8), ('M', 9), ('M', 10), ('M', 11), ('M', 12), ('M', 13), ('M', 14), ('M', 15), ('M', 16), ('M', 17), ('M', 18), ('M', 19), ('M', 20), ('M', 21), ('M', 22), ('M', 23), ('M', 24), (nan, 1), (nan, 2), (nan, 3), (nan, 4), (nan, 5), (nan, 6), (nan, 7), (nan, 8), (nan, 9), (nan, 10), (nan, 11), (nan, 12), (nan, 13), (nan, 14), (nan, 15), (nan, 16), (nan, 17), (nan, 18), (nan, 19), (nan, 20), (nan, 21), (nan, 22), (nan, 23), (nan, 24)])"
+ ]
+ },
+ "execution_count": 3,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "grouped_data = surveys_df.groupby(['sex', 'plot_id'])\n",
+ "print(len(grouped_data.groups))\n",
+ "grouped_data.groups.keys()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "3d9b5ba0",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "sex plot_id\n",
+ "F 1 46.311138\n",
+ " 2 52.561845\n",
+ " 3 31.215349\n",
+ " 4 46.818824\n",
+ " 5 40.974806\n",
+ " 6 36.352288\n",
+ " 7 20.006135\n",
+ " 8 45.623011\n",
+ " 9 53.618469\n",
+ " 10 17.094203\n",
+ " 11 43.515075\n",
+ " 12 49.831731\n",
+ " 13 40.524590\n",
+ " 14 47.355491\n",
+ " 15 26.670236\n",
+ " 16 25.810427\n",
+ " 17 48.176201\n",
+ " 18 36.963514\n",
+ " 19 21.978599\n",
+ " 20 52.624406\n",
+ " 21 25.974832\n",
+ " 22 53.647059\n",
+ " 23 20.564417\n",
+ " 24 47.914405\n",
+ "M 1 55.950560\n",
+ " 2 51.391382\n",
+ " 3 34.163241\n",
+ " 4 48.888119\n",
+ " 5 40.708551\n",
+ " 6 36.867388\n",
+ " 7 21.194719\n",
+ " 8 49.641372\n",
+ " 9 49.519309\n",
+ " 10 19.971223\n",
+ " 11 43.366197\n",
+ " 12 48.909710\n",
+ " 13 40.097754\n",
+ " 14 45.159378\n",
+ " 15 27.523691\n",
+ " 16 23.811321\n",
+ " 17 47.558853\n",
+ " 18 43.546952\n",
+ " 19 20.306878\n",
+ " 20 44.197279\n",
+ " 21 22.772622\n",
+ " 22 54.572531\n",
+ " 23 18.941463\n",
+ " 24 39.321503\n",
+ "Name: weight, dtype: float64"
+ ]
+ },
+ "execution_count": 4,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "grouped_data['weight'].mean()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "2336ac85",
+ "metadata": {},
+ "source": []
+ },
+ {
+ "cell_type": "markdown",
+ "id": "b0f1ab75",
+ "metadata": {},
+ "source": [
+ "### Exercise 9\n",
+ "Would it make sense to group our data frame by the column *weight*? Why or why not?"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "bbff11b3",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Number of rows: 35549\n",
+ "256\n",
+ "255\n"
+ ]
+ }
+ ],
+ "source": [
+ "# In real life nearly every sample has a unique value. So nearly every sample would \n",
+ "# be placed in an own group.\n",
+ "# In our training data you can see that there are quite some values for weight. So\n",
+ "# usually it is not a good idea to categorise (group) data on such values.\n",
+ "print(\"Number of rows:\", len(surveys_df))\n",
+ "print(len(surveys_df['weight'].unique())) #includes nan\n",
+ "print(len(surveys_df.groupby(['weight']).groups)) #does not include nan"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "79ae54cf",
+ "metadata": {},
+ "source": [
+ "### Exercise 10\n",
+ "In the given example of vertical concatenation, you concatenated two DataFrames with the same columns. What would happen if the two DataFrames to concatenate have different column number and names?\n",
+ "\n",
+ " 1. Create a new DataFrame using the last 10 rows of the species DataFrame (`species_df`);\n",
+ " 2. Concatenate vertically `surveys_df_sub_first10` and your just created DataFrame;\n",
+ " 3. Print the concatenated DataFrame info on the screen. How may rows does it have? What happened to the columns? Explain why you get this result."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "18b13126",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Unexpected exception formatting exception. Falling back to standard exception\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Traceback (most recent call last):\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/IPython/core/interactiveshell.py\", line 3460, in run_code\n",
+ " exec(code_obj, self.user_global_ns, self.user_ns)\n",
+ " File \"/tmp/ipykernel_16478/1143081575.py\", line 1, in \n",
+ " species_df = pd.read_csv(\"../data/species.csv\")\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/pandas/util/_decorators.py\", line 211, in wrapper\n",
+ " return func(*args, **kwargs)\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/pandas/util/_decorators.py\", line 331, in wrapper\n",
+ " return func(*args, **kwargs)\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/pandas/io/parsers/readers.py\", line 950, in read_csv\n",
+ " return _read(filepath_or_buffer, kwds)\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/pandas/io/parsers/readers.py\", line 605, in _read\n",
+ " parser = TextFileReader(filepath_or_buffer, **kwds)\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/pandas/io/parsers/readers.py\", line 1442, in __init__\n",
+ " self._engine = self._make_engine(f, self.engine)\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/pandas/io/parsers/readers.py\", line 1735, in _make_engine\n",
+ " self.handles = get_handle(\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/pandas/io/common.py\", line 856, in get_handle\n",
+ " handle = open(\n",
+ "FileNotFoundError: [Errno 2] No such file or directory: '../data/species.csv'\n",
+ "\n",
+ "During handling of the above exception, another exception occurred:\n",
+ "\n",
+ "Traceback (most recent call last):\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/IPython/core/interactiveshell.py\", line 2057, in showtraceback\n",
+ " stb = self.InteractiveTB.structured_traceback(\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/IPython/core/ultratb.py\", line 1288, in structured_traceback\n",
+ " return FormattedTB.structured_traceback(\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/IPython/core/ultratb.py\", line 1177, in structured_traceback\n",
+ " return VerboseTB.structured_traceback(\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/IPython/core/ultratb.py\", line 1030, in structured_traceback\n",
+ " formatted_exception = self.format_exception_as_a_whole(etype, evalue, etb, number_of_lines_of_context,\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/IPython/core/ultratb.py\", line 935, in format_exception_as_a_whole\n",
+ " self.get_records(etb, number_of_lines_of_context, tb_offset) if etb else []\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/IPython/core/ultratb.py\", line 987, in get_records\n",
+ " style = stack_data.style_with_executing_node(style, self._tb_highlight)\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/stack_data/core.py\", line 455, in style_with_executing_node\n",
+ " class NewStyle(style):\n",
+ " File \"/usr/lib/python3/dist-packages/pygments/style.py\", line 91, in __new__\n",
+ " ndef[4] = colorformat(styledef[3:])\n",
+ " File \"/usr/lib/python3/dist-packages/pygments/style.py\", line 58, in colorformat\n",
+ " assert False, \"wrong color format %r\" % text\n",
+ "AssertionError: wrong color format 'ansiyellow'\n"
+ ]
+ }
+ ],
+ "source": [
+ "species_df = pd.read_csv(\"../../course_materials/data/species.csv\")\n",
+ "species_df_sub_last10 = species_df.tail(10)\n",
+ "\n",
+ "surveys_df_sub_first10 = surveys_df.head(10)\n",
+ "vert_concat = pd.concat([surveys_df_sub_first10, species_df_sub_last10], axis=0)\n",
+ "\n",
+ "vert_concat"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "aa6d4ee8",
+ "metadata": {},
+ "source": [
+ "We get a total of 20 rows and 12 columns. The original dataframes together had a total of 13 columns. As they both have a column `species_id`, this one is collapsed. All other columns are padded with `NaN` values.\n",
+ "We expect 20 rows, as we are putting two DataFrames of 10 rows one after the other. The padding of the columns happens because these two DataFrames do not have the same column names. To keep all the information that was in the original DataFrames, the padding of columns that occur in only one of the two is necessary."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "9478026d",
+ "metadata": {},
+ "source": [
+ "### Exercise 11\n",
+ "In the given example of horizontal concatenation, you first concatenated two DataFrame with different indices, then reset the indices of the second one. Based on the outcome of these two cases, try to answer the following questions:\n",
+ " 1. What happens when you concatenate horizontally two DataFrames with different indexing?\n",
+ " 2. What happens when you concatenate horizontally two DataFrames with the same columns?\n",
+ " 3. What happens when you try to select a column of the `horizontal_stack` DataFrame we just created?\n",
+ " 4. How can you select a specific column, when multiple columns share a name?"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "b5b01c88",
+ "metadata": {},
+ "source": [
+ "1. The columns of both DataFrames are kept, duplicates are not merged, and the rows of both DataFrames are kept as well, no merging there either. This results in the two original DataFrames appearing in a checker-pattern in the resulting DataFrames, with the empty spaces padded out with `NaN` values.\n",
+ "2. Columns still are not merged, but now, rows with a common index are merged. This means that the information of both rows is put into a single row in the resulting DataFrame. If no corresponding row exists in the other DataFrame, the row is still padded with `NaN`'s in the result. But if a corresponding row (with the same index) *does* exists, this is no longer necessary."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "0faee1fd",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Unexpected exception formatting exception. Falling back to standard exception\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Traceback (most recent call last):\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/IPython/core/interactiveshell.py\", line 3460, in run_code\n",
+ " exec(code_obj, self.user_global_ns, self.user_ns)\n",
+ " File \"/tmp/ipykernel_16478/3936511566.py\", line 4, in \n",
+ " horizontal_stack = pd.concat([surveys_df_sub_first10, surveys_df_sub_last10], axis=1)\n",
+ "NameError: name 'surveys_df_sub_first10' is not defined\n",
+ "\n",
+ "During handling of the above exception, another exception occurred:\n",
+ "\n",
+ "Traceback (most recent call last):\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/IPython/core/interactiveshell.py\", line 2057, in showtraceback\n",
+ " stb = self.InteractiveTB.structured_traceback(\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/IPython/core/ultratb.py\", line 1288, in structured_traceback\n",
+ " return FormattedTB.structured_traceback(\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/IPython/core/ultratb.py\", line 1177, in structured_traceback\n",
+ " return VerboseTB.structured_traceback(\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/IPython/core/ultratb.py\", line 1030, in structured_traceback\n",
+ " formatted_exception = self.format_exception_as_a_whole(etype, evalue, etb, number_of_lines_of_context,\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/IPython/core/ultratb.py\", line 935, in format_exception_as_a_whole\n",
+ " self.get_records(etb, number_of_lines_of_context, tb_offset) if etb else []\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/IPython/core/ultratb.py\", line 987, in get_records\n",
+ " style = stack_data.style_with_executing_node(style, self._tb_highlight)\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/stack_data/core.py\", line 455, in style_with_executing_node\n",
+ " class NewStyle(style):\n",
+ " File \"/usr/lib/python3/dist-packages/pygments/style.py\", line 91, in __new__\n",
+ " ndef[4] = colorformat(styledef[3:])\n",
+ " File \"/usr/lib/python3/dist-packages/pygments/style.py\", line 58, in colorformat\n",
+ " assert False, \"wrong color format %r\" % text\n",
+ "AssertionError: wrong color format 'ansiyellow'\n"
+ ]
+ }
+ ],
+ "source": [
+ "# 3.\n",
+ "surveys_df_sub_last10 = surveys_df.tail(10)\n",
+ "surveys_df_sub_last10 = surveys_df_sub_last10.reset_index(drop=True)\n",
+ "horizontal_stack = pd.concat([surveys_df_sub_first10, surveys_df_sub_last10], axis=1)\n",
+ "horizontal_stack['species_id']"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "4f860304",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Unexpected exception formatting exception. Falling back to standard exception\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Traceback (most recent call last):\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/IPython/core/interactiveshell.py\", line 3460, in run_code\n",
+ " exec(code_obj, self.user_global_ns, self.user_ns)\n",
+ " File \"/tmp/ipykernel_16478/4095435365.py\", line 2, in \n",
+ " horizontal_stack.iloc[:,5]\n",
+ "NameError: name 'horizontal_stack' is not defined\n",
+ "\n",
+ "During handling of the above exception, another exception occurred:\n",
+ "\n",
+ "Traceback (most recent call last):\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/IPython/core/interactiveshell.py\", line 2057, in showtraceback\n",
+ " stb = self.InteractiveTB.structured_traceback(\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/IPython/core/ultratb.py\", line 1288, in structured_traceback\n",
+ " return FormattedTB.structured_traceback(\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/IPython/core/ultratb.py\", line 1177, in structured_traceback\n",
+ " return VerboseTB.structured_traceback(\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/IPython/core/ultratb.py\", line 1030, in structured_traceback\n",
+ " formatted_exception = self.format_exception_as_a_whole(etype, evalue, etb, number_of_lines_of_context,\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/IPython/core/ultratb.py\", line 935, in format_exception_as_a_whole\n",
+ " self.get_records(etb, number_of_lines_of_context, tb_offset) if etb else []\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/IPython/core/ultratb.py\", line 987, in get_records\n",
+ " style = stack_data.style_with_executing_node(style, self._tb_highlight)\n",
+ " File \"/home/jelle/.local/lib/python3.8/site-packages/stack_data/core.py\", line 455, in style_with_executing_node\n",
+ " class NewStyle(style):\n",
+ " File \"/usr/lib/python3/dist-packages/pygments/style.py\", line 91, in __new__\n",
+ " ndef[4] = colorformat(styledef[3:])\n",
+ " File \"/usr/lib/python3/dist-packages/pygments/style.py\", line 58, in colorformat\n",
+ " assert False, \"wrong color format %r\" % text\n",
+ "AssertionError: wrong color format 'ansiyellow'\n"
+ ]
+ }
+ ],
+ "source": [
+ "# 4.\n",
+ "horizontal_stack.iloc[:,5]"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "d6382b5f-9c13-4ceb-88f6-f7ba13f797f7",
+ "metadata": {
+ "tags": []
+ },
+ "source": [
+ "### Exercise 12\n",
+ "Time to play with plots! Look at the pandas.DataFrame.plot() documentation [here](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.plot.html) and change your data visualization swapping the DataFrame columns, and changing the axes labels.\n",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "id": "1896c89b-f2c2-41ae-9a18-9b9fb8a87648",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "Text(0.5, 0.98, 'Scatter plot of weight versus hindfoot length')"
+ ]
+ },
+ "execution_count": 7,
+ "metadata": {},
+ "output_type": "execute_result"
+ },
+ {
+ "data": {
+ "image/png": "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fvhB7xix68/lf//7n8E3/6amJqZSqVjv3r0ZAPbCCy/o9pWXlzMnJyfWu3dvvfM8/vjjDACbNm0aKy8v122vrKxkY8eOZQDYypUr9Y7h6pGqqKjQ9Thu2LBB7/EvvfQS77dy7bm8vLzY4cOHddtramrY0KFDGQCDb6xi72c+Bw4cYADYHXfcYbCvubmZRUREMCcnJ71eyq+//poBYH369GG5ubl6j3/55Zd1146rfQDY5s2bDZ5Le9wTTzxhsK+goIBduHBB938pPVLtOb+Q1n/DH3zwgd4+7d/Ogw8+qLddrEeqPefavHkzA8AiIiL03ms3btxgffr04e2JFOoxvffeexkANmPGDFZXV6fbfuDAAebl5cWcnZ31esyrq6tZ586dGQD28ccf653r3XffZQBYWFgYq62tFb0GxuD77PnHP/7BALDU1FR27do13fa6ujqWnp7OALC//e1vnNehPX9b2nONHz9e7zWdPHlS16vaukdKqM1arT/Pp0+fzm7duqXbt3XrVt3v2FZQIGUDdu/ezcLDww26Of39/dljjz3GioqK9B5/9OhRBoB16tRJ78YrxWeffcYAsA8//FBvu6mB1P33388ZAGiNHz+eAWCZmZkG5+zbt69B0CdG+4fn5OTEOQzxt7/9jQFg6enpetu5AintTSUtLc3gPLdu3WKhoaEMADt48KBuu9RAqrq6mnl6ejInJyd27tw5g/0ffvghA8BGjRqlt11KIFVbW8vc3d31PtQyMzN1gWu3bt1YcnKybt/27dsZAPb444/rtt24cYO5urqy8PBwptFoDJ7j2rVrzM3Njd1+++1627luVNr33p133mlwnoaGBt3vhi+Qah30aX377becNySpgVRzc7Puy0bbId2MjAzO9vfr148BYGfOnOE8X//+/ZmzszNTq9UG7Rs3bhxnOx577DEGgG3btk20zVICqfacX4j2fdn6faRVXFzMeVMVC6Tac67hw4czAOyLL74wOOann35qdyB18eJFBoD5+PiwkpISg3P+9a9/ZQDYvHnzdNu++OILBoANGTLE4PGMMTZgwAAGgK1fv170GhiD67OnoaGBBQUFMW9vb3b9+nWDYzQaDQsJCWEqlYo1NTXptrf3b6uqqop5eHgwZ2dnziD0hRdeMCmQ8vPz4xwK1wbFQkPzlkTlD2zAnXfeiQsXLmDLli2YP38+EhIS4OLigvLycqxcuRL9+/dHTk6O7vG7d+8GAKSlpcHX19fo5zl48CCWLVuGxx57DHPnzsWcOXPwzTffAABnF6xUzc3N2LNnD7y8vHD33XdzPkbbrX3s2DGDfffee6/kmkj9+/fnHIJIS0sDABw4cED0HNrHPPDAAwb73N3dMWXKFKPPJebkyZOora1FQkICZ8Ltgw8+CAA4dOgQmpubTXouDw8PJCUloaCgQFdHR1sOIDU1FampqTh+/Dg0Go3BPq19+/ahoaEBY8aM4RwSCAkJQUxMDM6cOYPa2lrB9hw6dAgAdNezNRcXF0yePFnw+NGjRxts0w5nX7t2TfBYYykUCsyYMQPNzc3YvHmz3j6uYb2bN2/i9OnTiImJ4Ry+UigUSE5ORlNTE06ePGmwf/z48ZztGDBgAADg+eefx48//ohbt25Jfk2WOD/X7yYwMBABAQHt/t0Ye66Ghgb8+uuvAIBp06YZHDNmzBioVKp2PffBgwd1xwYEBBjs1/59tv4sEPr8AP58v5jj84NPZmambsiNawjZ09MTAwYMQFlZGednv7F/WydPnsStW7eQmJiIyMhIg2O4fg/tMWDAAAQGBhrVFmuiQMpGuLm5YeLEiVi5ciVOnjwJtVqNlStXQqVS4ebNm3jiiSd0jy0sLAQAREdHG3XuiooK3HnnnRg2bBheeuklfPrpp1izZg3Wrl2LnTt3AmjJ0zGX4uJiVFdXQ6PRwM3NTVcssvXPs88+q3tsW6bM8OrWrRvndu0feVFRkeg5tI/h+mBovf3q1avtbl97n8vf3x9KpRK1tbUoKysz+fm0QZE2SNq3bx/8/PwwYMAApKam6vKkWj+mdX6UNgD77LPPOH+vCoUCv//+OxhjKC0tFWyL9kNQmyfYltj7ICwszGCb9otFXV2d4LHtob0hagMnoCWf7JtvvoGHhwcmTZqk2669Prm5ubzX55NPPgHQvvf+nDlzMHXqVJw9exb33XcfVCoVhg8fjuXLl+P69esmv0Zzn5/rdwO0/H7q6+tlOVdJSQnq6+sRHBwMLy8vzmP4Ph/4SPkssOTnBx/t+3DXrl2878MdO3YA4H4fGvu3ZerfsBih333btlgTJZvbKH9/f8yfPx+hoaG4//77sXfvXmg0Gt4PCCF/+9vf8L///Q8jRozAa6+9hj59+sDf3x/Ozs7YuXMn7r77bjDGzNZ2bc+Jj4+PaK9C7969DbZ5eHiYrS1ysHQFcXM+X2pqKt544w3s27cPs2bNwoEDB5CSkgJnZ2e9ICsxMRGnTp3CbbfdpjcBQvu77d+/P/r16yf4XO7u7mZrNxdjJyCYqlevXoiPj0dmZiZycnIQFxeHn376CWVlZZgyZQr8/Px0j9Ven5CQEN7eWC2umzrfe9/Z2RlfffUVlixZgu+//x7/+9//cPToURw4cABvvfUWfv75ZwwdOtSo18PVs2nO8wPm/d1Y6vcshZS/TUt8fmh/xz169EBycrLgY7l6fGzlmttKO8RQIGXjtMXhmpqaUF5eDi8vL130f/HiRaPOsXXrVjg7O2P79u16H/oAkJeXZ94GAwgKCoKHhwecnJywevVqiwYeBQUFgttDQ0NFzxEaGoqcnBwUFBRwBnrab3vmKC6pbQ9fuysqKlBeXg5PT892D0twGTJkCNzc3LBv3z6cPn0aZWVlugAqMjIS3bp1w759+zBo0CA0NzcbLJOh/YaYkpKCjz76yKS2dOnSBcCfPaxt8W23hgceeABZWVnYsGEDXn/9dd7ZetrrExQUJEvV//j4eMTHx+PVV19FZWUlXn31Vbz33nt4+umndcPkbm5uAIDq6mrOcwhdV2POb6sCAwPh5uYGtVqN2tpazqHny5cvt+ucYn+fXJ8FUo4xN+37sGfPnrKuPmFPf8Nyso9wrwMT6wm6cOECgJYPx6CgIADQTU/ftGkT74dla2VlZfDz8zMIogDg66+/5jxG+2Hc2NjY7v0uLi5ITU1FZWUl9uzZI9o+czp16hTnmL82v6X11GI+2vytTZs2GezTDum0fhwgfr34DBgwAJ6enjh58iRnu9evXw8ASE5ONsu3M09PT12elPYDduTIkbr92jyp//73v7r/tzZy5Eg4Ozvjxx9/RENDg0lt0X5T/u677wz2NTU1YcuWLSadvzWpvx+ttLQ0ODk5YdOmTaisrMQPP/yAgIAA3HPPPXqPCwsLQ8+ePXH27FmcP3/e5HYL8fPzw5tvvgmFQoHs7Gzddu3Njev5S0tLkZmZadL5bZWrqysGDRoEgPtzbefOnaLDzW1pPy9+/vlnlJeXG+zX/n22/iwQ+vzgO8bU92dbiYmJUCqVyMjIaPdrbo8BAwbAw8MDJ06c4AxSpd5f7A0FUlb20ksv4dlnn+XsXbp69SoeffRRAC1JqNo3X1JSEkaOHImbN2/ikUceQU1Njd5x+fn5OHPmjO7/sbGxKCsrw1dffaX3uPfee09XQ6gt7beq1knu7dn/wgsvwMnJCXPnzuVc36y6uhpffPGFaEJyezU3N2PhwoW6hGmgJSHy448/hkKhwGOPPSZ6jvT0dHh6emLz5s26PALtuZ9//nlcvXoVAwYM0OsyF7sefLy9vfHQQw+hubkZCxYs0Ptdnj9/HsuWLQMAPPnkk+06rxBtcPSf//wHSqUS8fHxevvq6+t1QVbr/Cig5Vv0Qw89hPz8fKSlpeHGjRsG579w4QJncNTWlClTEBAQgF27dhkkci9btgyXLl1q5yvjJ/X30/r4kSNH4sKFC/jb3/6GW7duYcqUKQZ1iYCWv+nm5mZMnjwZp06dMthfUlKCzz77rF3P/+WXX3IGMz/99BMYY3o5Kt27d0dERATOnDmD77//Xre9pqYGjzzyCCorK006vy3T/n2/8sorejf24uJiXV5me0RFRWHcuHGoqqrCU089pffl4ciRI1i5ciWcnZ2xYMEC3fapU6eic+fOOHjwIP7zn//one/DDz/EiRMn0LVrV720B1Pfn225u7vjueeeQ1VVFSZNmsQ58nD16lV8+eWXJj2Pj48PHnjgATQ2NuKpp57Sy1k6ffo0b6+1uV+v1Vl1ziBhTz31lG5KbmxsLJswYQKbPn06S0lJYa6urgwA69GjB7ty5YrecVeuXGFxcXEMAAsICGDjx49nU6ZMYQkJCczJyYm99957useuX79e9xzDhg1jaWlprFevXszJyYktWrSIc9rtiRMnmEKhYB4eHuz+++9n6enpLD09XTcV9erVq7ppr2PGjGEPPfQQS09P1ys9sHLlSubs7KyrqTNp0iQ2bdo0NmjQIObu7s4A6FWMljKlX0s7Xfbee+9l4eHhLCQkhE2dOpXdfffduuv44osvGhzHV9l83bp1zMnJiSkUCpaSksLS0tJ017tz584GpQpqa2t1NZ9GjBjB5s6dy9LT03mrL7dWWVmpmxLdqVMnNmXKFDZ27Fjm4eHBALAnn3zS4BhTrtWuXbt074e20+0vXbqk29ezZ0/O4zUaDbvrrrsYAObt7c2Sk5NZWloaGz9+POvRowcDwO6//369Y/iml3/33Xe698iQIUNYWloa69OnD3Nzc2OPPPIIA8D+/ve/G3Wu1u0fMWKE3nax97MxtNPatT8HDhzgfezzzz+vK8eRkJDApkyZwv7yl7+w+Ph45uzszJRKpd7jxcozaMuJREdHswkTJrC0tDQ2ePBgplAomJOTE/v666/1Hr9q1SoGgDk7O7ORI0ey++67j3Xu3JnFxMToztX6udp7fj5i70uuvzdjKpsbey7GGJsyZYruvTl+/Hg2adIk5u/vzxISEtjgwYPbXUfqypUrrHv37rpp/NOnT2d33nmn7n27YsUKg2N2796tqw84YMAAlpaWxuLj43WlFPbv329wzO23384AsMTERDZnzhyWnp6uV8eOD18pgaamJvbggw8yoGXVgkGDBrHp06ezSZMmsd69ezOFQsH69etn9HXg+9tSq9W6v/uuXbuyadOm6T53tTXyYmJi9I4R+7yUWp3fWiiQsjK1Ws2+/PJLNnPmTNa3b18WGBjIXFxcWEBAAEtOTmb/+Mc/9IpLtlZZWclef/11dvvttzNPT0/m4+PDevbsyZ544gm9QoCMMbZjxw7dch7+/v5s1KhRbN++fYJv2A0bNrCEhATdB0LbP7BffvmFJScnMx8fH93+tm/srKwsNnv2bNatWzfm5ubG/P39We/evdlDDz3EfvzxR716UeYIpGbPns2uXr3KZs6cyYKDg5m7uzvr169fuz+MGWPs0KFD7L777mOBgYHM1dWVRUREsMcee8wgqNU6fvw4u+uuu5hSqWQKhaJdr6W6upq99tprrFevXszd3Z35+vqylJQUtnHjRs7Hm3KtampqmJubGwPA/vnPfxrs116T+fPn856jsbGRrV27lt1xxx0sICBAtwTGkCFD2Guvvaa3RBFjwh/Qe/fuZampqczb25v5+fmx0aNHs6NHj7Jly5YxAOzTTz81+lx8H/aMib+fxVRUVOiC227duonWOsvIyGBTpkxhoaGhzNXVlQUGBrLbb7+dPfHEEywjI0PvsWI3hoyMDLZgwQLWv39/FhgYyDw8PFhUVBSbPn06O378OOcxq1ev1gWlnTt3ZvPmzWPFxcWczyXl/FxsIZBqaGhgb7/9NouNjWVubm4sNDSUPf7446y8vJz3vSP0nmKspW7V4sWLWXR0tO5zbPTo0YJLxGRnZ7O0tDTWuXNn5urqyrp06cJmzpzJu9xObm4umzBhAgsMDGROTk6CdZZaE6vJ9P3337Nx48axTp06MVdXV9apUyc2YMAA9txzzxkUKJb6t3Xz5k326KOPspCQEObu7s5uu+029v7777PLly8zAGzw4MEGxwh9XtpbIKVgzIzTtQixkn379mHkyJGYPXu2rMmVxHLGjBmDX375Bb/++qsu94UQYj82b96MtLQ0zJ8/HytXrrR2c2RDOVKEEKu5evWqQZ5Vc3Mz3nvvPfzyyy+IjY1FUlKSlVpHCDEGV3HZU6dO6fLS2s5u7Wio/AEhxGoOHDiAmTNnIj4+Ht26dUNdXR2ys7ORn58PLy8vfP755xav20UIaZ/k5GSEhITgtttug5+fHy5duoSTJ0+iubkZTzzxhGgtK3tHgRQhxGoGDBigKwyak5ODW7duISQkBA8++CCWLFmCXr16WbuJhBARS5cuxX//+1+cOHEC5eXl8PHxwfDhwzFv3jzepXI6EsqRIoQQQgiRiHKkCCGEEEIkokCKEEIIIUQiCqQIIYQQQiSiQIoQQgghRCIKpAghhBBCJKJAihBCCCFEIgqkCCGEEEIkokCKEEIIIUQiCqQIIYQQQiSiQIoQQgghRCIKpAghhBBCJKJAihBCCCFEIgqkCCGEEEIkokCKEEIIIUQiCqQIIYQQQiSiQIoQQgghRCIKpAghhBBCJKJAihBCCCFEIgqkCCGEEEIkokCKEEIIIUQiCqQIIYQQQiSiQIoQQgghRCIKpAghhBBCJKJAihBCCCFEIgqkCCGEEEIkokCKEEIIIUQiF2s3oCNrbm5GUVERfH19oVAorN0cQgghhBiBMYaqqiqEhobCyUm4z4kCKRkVFRUhPDzc2s0ghBBCiASFhYUICwsTfAwFUjLy9fUF0PKL8PPzs3JrCCGEEGKMyspKhIeH6+7jQiiQkpF2OM/Pz48CKUIIIcTOGJOWQ8nmhBBCCCESUSBFCCGEECIRBVKEEEIIIRJRIEUIIYQQIhEFUoQQQgghElEgRQghhBAiEQVShBBCCCESUSBFCCGEECIRBVKEEEIIIRJRIEUIIYQQIhEtEUMIIRLkqatRUKpBZKA3ugd5W7s5hBAroUCKEELaoVxTjyc3ncL+XLVu2/CYYHyUFg+ll6sVW0YIsQYa2iOEEB556mrszbmJS8U1um1PbjqFQxeK9R536EIxFm7KsnTzCCE2gHqkCCGkDb5ep8WjY/W2aTUxhv25alwqrqFhPkIcDAVShBDSBl+vU2lNneBx+SUUSBHiaCiQIoSQVvLU1by9TtlFlYLHRgZSEEWIo6EcKUIIaaWgVCO4v09XPzgrFHrbnBUKDI8JNktvFFdeFiHEdlGPFCGEtNItwEtw//KJffHOL+f1eq2SewTho7R4k56XZgMSYp+oR4oQQlqJCvbB8Jhg3l6nCJFASyqaDUiIfaJAihBC2vgoLR7JPYL0tml7neQIeLR5WU2M6W1vPRuQEGKbaGiPEELaUHq5Yl16Ei4V1yC/pEZXvVwoEd2U8gdieVk0G5AQ20WBFCGE8OgepL/8i1wBj1heFs0GJMR20dAeIYTwaDuDTq6ARywvi3qjCLFd1CNFCCFtCM2gGx4TjEMXivXymZwVCiT3CDIp4PkoLR4LN2WZfTYgIUReCsbaZDcSs6msrIRSqURFRQX8/Pys3RxCiJFmrTrGGyxxBTzmLFPQNi+LEGJ57bl/U48UIYS0IpZQXqqp50xEN5e2eVmEENtGgRQhhLRibEI5BTyEEICSzQkhRA/NoCOEtAcFUoQQ0oo5ZtDRenmEOA4a2iOEkDakzqCj9fIIcTw0a09GNGuPEPvW3oRyodl+69KT5GwqIcSMaNYeIYSYQXsSyuVaPoYQYtsoR4oQQszAmNl+hJCOhwIpQggxA5rtR4hjokCKEEIkaDszj9bLI8QxUY4UIYS0g9DMvGUTeuP+Tw6hTNOg2+fn6YK/T+hjjaYSQiyAAilCCGmHR9adwLH8Mr1t+3PVeHjdCXi4OqOytlFvX2VtI17Ylk2z9gjpoCiQIoQQI+Wpqw2CKK1j+aWc22nWHiEdG+VIEUKIkX78rUjysTRrj5COiQIpQggxUmlNveRjadYeIR0TBVKEEGKkkXGdBPf36uLLuX1odCAN6xHSQVEgRQghRhoR1wlKT+7UUqWnC5Sebpz7aCEuQjouqwZSDQ0N2LNnD5599lkkJibC398frq6uCAkJwfjx47Fjxw7O41599VUoFArBnz/++IP3eS9cuIA5c+YgLCwM7u7uCAsLw5w5c5CXlyfXSyWEdBA/PjEMqjYLEKu8XPGvGQk4klfCecyRvBJdvSlCSMdi1Vl7GRkZuOuuuwAAISEhSElJgbe3N86ePYsffvgBP/zwAx555BF8+umnULQpcgcA/fr1Q//+/TnPrVQqObcfOnQIo0ePhkajQe/evZGSkoLs7GysXbsW3377LXbv3o3Bgweb7TUSQuxXnroaBaUavUWLwwO9kPXyaBzIVSPzchkSIlQYFhOMvTk3Bc+VX0Kz9gjpiKwaSDk5OWHy5Ml46qmnMGzYML19X331FR544AH85z//QXJyMmbNmmVw/IQJE/Dqq68a/XwajQZTp06FRqPB0qVLsXz5ct2+559/Hm+++SamTp2KnJwceHp6Sn5dhBD7JlR0U/n/vVHDYoIxLCZYt5+WiCHEMVl1aO+OO+7At99+axBEAcC0adMwZ84cAMC6devM8nxr1qxBUVERYmNjsWzZMr19y5YtQ2xsLAoLC832fIQQ+/TY+ky9IApoKbo5f/1J3f+5logZGh3IeT5KNiek47LpZPP4+HgAQGFhoVnOt3XrVgDA9OnT4eSk/9KdnJwwbdo0AMCWLVvM8nyEEPuTp64WzHU6XViGWauO4Y4VGZi7+jhGvrMPs1YdQ4WmgTepnJLNCem4bLqyeW5uLgCgS5cunPszMzOxZMkSlJaWQqlUIj4+Hvfddx98fbmnIGdlZQEABg4cyLlfu137OEKI4zl6ibtCudYz35xGnlqjt+3QhWKkrz2OEwXcVc+1yebUK0VIx2OzgdT169exZs0aAMDkyZM5H6NNSG9NqVTiww8/NMipqqqqQklJy7fMiIgIzvOFh4cDANRqNWpqauDtTR96hDge4e6j3JuGs++aGOMNorQo2ZyQjskmh/YaGxsxc+ZMVFRUoG/fvnj00Uf19kdHR2P58uXIyspCaWkpSktLcfDgQdx7772oqKjA7NmzsWHDBr1jqqqqdP/mC5B8fHx0/66srGx3u+vq6lBZWan3QwixL4O6c+c5mcrF6c+Zx23zq1oT2kcIsT022SM1f/587NmzB4GBgfj222/h5qZf5O7BBx80OCY5ORk//PADnnzySXz00UdYtGgRpkyZYnCsnN5880289tprFns+Qoj5RQX7IClSxbk48e1d/fDbVWlfkK6U1QrOBmRgojMFCSG2x+Z6pJ566imsWrUKKpUKu3btQmxsbLuOf/XVV+Hs7Ay1Wo2jR4/qtrfOm6qp4f6mV11drfu3n59fO1sOLF26FBUVFbofcyXJE0Isiy853N3F2aAYp5aXm7PgORUAntx0CocuFOttP3ShGAs3ZQnuI4TYLpsKpBYvXowPP/wQ/v7+2Llzp27WXnsEBASgU6eW9bCuXLmi2+7r64uAgAAAwOXLlzmP1QY+QUFBkvKj3N3d4efnp/dDCLEveepqHOfJdzpeUIYyTQPnPk19k+B5Q/09sD9XjaY2UVoTY9ifqxbcR8N8hNgumwmknnvuObz77rtQKpXYuXMn78w6MU1NTaioqAAAg9l7CQkJAIATJ05wHqvdrn0cIcTxiM3aE3JbCP+ixU0mlEDIL6FAihBbZROB1JIlS/DPf/4TSqUSu3btQmJiouRzbd++HRqNBgqFwiAYmzhxIgBg8+bNaG5u1tvX3NyMr776CgAwadIkyc9PCLF30iOetyffjuGtqp0DLXlOKx8YIFr5XAhVRSfEdlk9kHrxxRfx9ttvw9/f36gg6vLly1i/fj1u3bplsG/btm2YN28eAOCBBx5ASEiI3v45c+YgNDQU58+fx0svvaS376WXXsL58+cRFhbGuRwNIcQxiM3aS4xUwbnN2p/OCgWGxwTj9nB/rEtPwrqHkrDorhh8mZ6EdelJUHq5IirYB8NjgnmPFdpHZRMIsV0KxqxXc3f79u24//77AbQUw+zduzfn44KCgvDOO+8AAE6dOoX4+Hj4+PggPj4eXbt2RW1tLc6ePasr4Dly5Ehs375dr5yBVutFi/v06YM+ffogOzsb2dnZ8Pb2NuuixZWVlVAqlaioqKB8KULsyIzPfsXhi4bVzYdGB2LlAwOwcFOWpJl3FZoG3mMB8O6jWXuEWFZ77t9WDaTWrFmDuXPnij6uW7duyM/PBwCUlJTgn//8J44fP44LFy6gpKQE9fX1CAoKwoABAzBjxgxMmzbNYAmY1i5cuIA33ngDu3fvhlqtRnBwMEaNGoWXX34Z0dHR5np5FEgRYqeEAh6hYGnhpiwculCslzTurFAguUcQ1qUn6bZ9dewyjlwqQXJ0EKYMDNd77v3n1cgqLENChEpvUWRCiOXYTSDV0VEgRYh9u1Rcg/ySGkQGeuuG12atOsYZLMVH+AtWN9/7TCqcFMCETw7pzfxTebli+4IU+Hq6UB0pQmwEBVI2ggIpQjqWPHU17liRIenY1XMT8devTnGWT1B5uaJvV3+jerMIIfJrz/3b6snmhBBiqzJybuKDPedx4P97iQpKNSJH8LtZcYu3BlWZpoHqSBFip2xyiRhCCLGUPHU1Cko1esN3BSU1nENwH6dJrzF39JJh8rqxaMFjQmwXBVKEEIcktO5d2yAKaOk1emJTJoZEBeJInmFQFKbyxJWyWt7nMyWHgupIEWK7aGiPEOKQ+Na2e2DVr4JDcBW13PvcXYQ/TnsEG5ZjaU2oPhX1RhFiuyiQIoQ4nDx1NW9OUvbVSsFjz17j3n9RLZzH1Cgyr2f20Egk9wjS25bcI0hXY4oQYptoaI8Q4nBMSRqXKj7cX3B/71Al1qWHcpZcIITYLgqkCCEOR2zdO2cFOBcZ5ttujOGxnTA8Jpi3xIE2aOoeRAEUIfaEhvYIIQ5HaN27xEgVb7AkNYgCgG9OFOKjtHgaviOkg6EeKUKIQ1o2oTfubzM7z8/TBVMGhuF4Pn+FcqkOXSzGlIHhWJeeRMN3hHQg1CNFCHFIL277HZW1jXrbKmsb8c2JK7I8X2wnX92/aUEJQjoO6pEihDgc7ay9tpoYw/H8Mt5cKBcnBYZGB3HmOUUFeyP3ZjXvcwZ4uwnWrqL19AixT9QjRQhxOGKz9vhyoRqbGWYMCufMc0pLDBc8JwN/7aqFm7JE20wIsU3UI0UIcThis/aE5Nyo4sxzysi5KXics0LB2wumXU+P8qUIsT/UI0UIcThCs/b6dBVe6T0hQgWgpUzByLhOuuCnWeQ5r1XyLx8DtKynRwixPxRIEUIcEl8pgg3pg+Hnwd1Z7+fhgmExwZz7xD5Mu/h5Cu6n9fQIsU80tEcIcUhKL1eTShHkqatRUKrRHSfWIxXs547ESBVnaYWkSJXuuduelxBi2yiQIoQ4tLaVxDNybqLyViPnYytvNeKnM9ew6Vihwcy7xaNjBZ8nMtAb529wz+rLuVFNM/oIsVMUSBFCSCunrpQL7n/r53O4UnpLb9uhC8UorakTPO6/vxWhoraBc19FbQMeXHUUZ4uqDM67cFMW1qUniTecEGIVlCNFCCGtOEMhuL+gpFavhhTQMvMuu6hS8Lgff7smuP/M1UrO82pn9BFCbBMFUoQQ0koT5Kk6rvKWPjxHM/oIsV0USBFCSCv9w/xlOe+E+K6Sj6UZfYTYLgqkCCEOLU9djb05N3XDZ+EmFOvkGxR0VgBNzcI9XZ6u3B/HKi9Xmr1HiA2jZHNCiEPimyWXGhckcJQwvlCpiQHqqnrBY2sbuAsolGkaqOo5ITaMAilCiEPiW/fuWoXwOnzSSc+9yi9pCaSoxhQhtocCKUKIw8lTV/Oue5d7U57E7mBfD8nHBni5YdaqY1RjihAbRDlShBCHU1Aq3OskXACBn4dAntOg7gGCx/ItS6PycsWKnec5e88WbsqS1lBCiNlQIEUIcThiH3xSB+FuCeQ5XSkTDt74qqmXaRqwP1dNNaYIsVEUSBFCHI7YunhyyCosl+W8VGOKEOuiQIoQ4nC6mVDiQKoQE3KkhFCNKUKsiwIpQojDiQr2wfCYYDgr9LOhnBUK9OnqJ/m87i7cH6n9wpTopBQOpPp09eNsz/CYYN62Do8Jptl7hFgZBVKEkA6tbcFNrY/S4pHcQ79mVHKPIPx9Qh/Jz1XXyD1oePpKhWgv2PKJfTnb81FaPG9bP0qLl9xWQoh5KBhj8iwsRVBZWQmlUomKigr4+Un/lksIaT++gpttSwZcKq5BfkmNXm2mGZ/9isMXSwzOGRXkjTyJyd3P3R2HX/NKcehCsV7iuLNCgeQeQViXnsTbHqG2EkLMrz33b+qRIoR0SHwFN9uWDOD6LlnP07MU6O0muT07z143qmdJ6Ltt9yBvjIzrREEUITaECnISQjocoYKb2pIBKi9Xzh6rxaNjcKKgjPO8x3m2G6OzrweYQGEFY3vQCCG2hQIpQkiHI1ZwM7+kBq98n2/RJWJSe3YS7SXj26cd9iOE2B4KpAghHY5YzoK68pbFl4gpra4T7CXj0roHjYbzCLFNlCNFCOlwxApuXqu8ZZF2tJarrpZ8LBXdJMR2USBFCOlwxEoNxIf7W6YhrQR6Sk9Up6KbhNguCqQIIR2OUMHN4THBGB7biXd/TCd5gpay2gbB/d0CvajoJiF2iAIpQkiHJFZqgG//6F6dZWmP0Iw9AFh6T08qukmIHaJkc0JIh6T0csW69CTeIpZ8+z/ckytLewK93aHyckWZxrBnSuXlijF9umBMny5UdJMQO0M9UoSQDk1s8Ya2+4N9pecyCSmuqcP6hwbBxUl/+M7FSYEN6YN0/6eim4TYF+qRIoR0SGIFLvn2h6uEFxeWKjk6CG//koO2cR1jwFs/51CtKELslFV7pBoaGrBnzx48++yzSExMhL+/P1xdXRESEoLx48djx44dgsfv3r0bY8eORVBQEDw9PdGzZ0+88MILqK4WnmZ84cIFzJkzB2FhYXB3d0dYWBjmzJmDvLw8c748QogVPb4h06A+0/5cNR7bcBIA/xIy35++Jkt7Ovt5YH+uWm+dPUC/VhQhxP5YNZDKyMjAqFGj8M477+DKlStISUnBpEmTEBwcjB9++AH33nsvHn30Uc6u+ffeew933XUXfv75Z/Tu3Rv33XcfKioqsHz5cgwcOBDFxcUczwgcOnQI/fr1w9q1a+Hv74+JEyfC398fa9euxe23345ff/1V7pdNCJFZnrqac9FhADh8sQT7z9/kDWqq6xpladO2rKuC+6lWFCH2yaqBlJOTEyZPnoz9+/fj2rVr+PHHH/HVV1/hzJkz2Lx5M5ydnfGf//wHX375pd5xWVlZWLx4MZydnbFjxw5kZGTg66+/xsWLF3HnnXciJycH8+fPN3g+jUaDqVOnQqPRYOnSpcjOzsbmzZuRnZ2NpUuXoqamBlOnTkVtba2lLgEhRAZHL3EHUVr/+4O7kricblQIFwGlWlGE2CerBlJ33HEHvv32WwwbNsxg37Rp0zBnzhwAwLp16/T2vfnmm2CMYe7cubjnnnt02728vLBq1So4OTnhu+++wx9//KF33Jo1a1BUVITY2FgsW7ZMb9+yZcsQGxuLwsJCg+cjhNgbhfBehXACuhy83V0Ea1tRcjkh9smmZ+3Fx7fUTyksLNRtq6+v1+VOzZgxw+CYbt26ITk5GQCwdetWvX3a/0+fPh1OTvov3cnJCdOmTQMAbNmyxUyvgBBiCXnqauzNuanLMxrUPUDw8XGd/SzRLD23hytFa1sRQuyPTc/ay81tqefSpUsX3bbz589Do2lZnX3gwIGcxw0cOBAHDhxAVlaW3nbt/4WOa/04QohtE5qZN7CbCicKygyOSeymQpJIoCWHzn4eorWtCCH2x2Z7pK5fv441a9YAACZPnqzbfunSJQCAv78/fH19OY8NDw/XeywAVFVVoaSkJW8iIiJC8Di1Wo2aGkr8JMTW8c28W7gpC048o3sKhUJwCZk+XeXprSqq+DP3kmpFEdJx2GQg1djYiJkzZ6KiogJ9+/bFo48+qttXVVUFAPD25v8A8vHxAQBUVlYaHCd0rPa4tscaq66uDpWVlXo/hBB55KmrBcsJHMs37I0CgGP5pbhUXINlE3rDz1O/U97P0wVLx/SUpb2uTjb5cUsIMZFN/mXPnz8fe/bsQWBgIL799lu4uclTadjc3nzzTSiVSt2PtoeLEGJ+BaUayccezSvBi9t+R2WtfqmDytpGvC/TEjEXbgrXtyOE2CebC6SeeuoprFq1CiqVCrt27UJsbKzefu1wntDQm7Ygp5/fn130rYcB+Y5tXciz9bHGWrp0KSoqKnQ/rZPkCSGmaZtQ3i3AS/K51NW3eHuzjvP0ZJnqRqVw+QNCiH2yqWTzxYsX48MPP4S/vz927typm7XXWmRkJACgvLwcVVVVnHlS2gBG+1igJZAKCAhAaWkpLl++jH79+vEeFxQUJDh0yMfd3R3u7u7tPo4Qwk8ooXx4TDAOXSjWC4icFQokdPMXDIiCfORZBkZIZz/LPychRH420yP13HPP4d1334VSqcTOnTt5Z9bFxcXBy6vlm+iJEyc4H6PdnpCQoLdd+//2HkcIsR6hhHK+cgIvjusleE5rfPBNTOhqhWclhMjNJgKpJUuW4J///CeUSiV27dqFxMRE3se6ublh3LhxAICNGzca7C8oKMDhw4cBABMnTtTbp/3/5s2b0dzcrLevubkZX331FQBg0qRJ0l8MIcRsxBLKSzX1WJeehL3PpGL13ETsfSYV69KTUKqpFzzvryKVz+UwLCbY4s9JCJGf1QOpF198EW+//Tb8/f1FgyitJUuWQKFQYPXq1fj555912zUaDdLT09HU1ITJkyejZ0/92Tdz5sxBaGgozp8/j5deeklv30svvYTz588jLCwMs2bNMs+LI4SYRCyhXLs+XdtyAmIfbDW35FlPT8iBXMsvS0MIkZ9Vc6S2b9+Ov//97wCAHj164JNPPuF8XFBQEN555x3d/xMSErBixQr89a9/xdixYzFixAh06tQJBw4cwLVr1xAXF4dPP/3U4DxeXl74+uuvMXr0aCxfvhzbt29Hnz59kJ2djezsbHh7e+Obb76Bp6enPC+YENIuYgGRC0+xqGbOrX/qE6bEznM3JbVJqj3nblKvFCEdkFUDqdLSUt2/T5w4wZu71K1bN71ACgAWLVqEvn37YsWKFTh27BhqamoQERGBpUuXYunSpbzFOpOTk3H69Gm88cYb2L17N7777jsEBwdj1qxZePnllxEdHW2+F0gIMYlYQNTYzL1mntiMvvv6dcUHu3PRZMEl94J87KOMCyGkfawaSM2ZM0e3MLEUo0aNwqhRo9p9XI8ePbB27VrJz0sIsQyxgCgysGUoL09djYJSjW7JlahgH6i8XFGmaTA4RuXlCsaYRYMoQH/WXtv2GkvqcURe9HtxbDZV/oAQQloTC4hUXq6YteqYQWmExaNjOI8BgDJNA45eKuXcJ6ffiypxl0ApB6WXK++xQiUghI4j8qLfCwFsINmcEEL45KmrBQOih9ee4CyN8MK2bJEzW7g7CoCzAnh8Q6beTRcA9ueq8diGk4LHCpWAINZDvxcCUCBFCLFhYrP2jheUcZZGyL4qvM7l4Kgg3kWLPWTqpy8sq8Xhi9xlFw5fLNFVbG9bwV2sBIT2ccSy6PdCtGhojxBis0xZBqZniC/+uF5lsH1IVCC6B3lj2YQ+uP+Tg3o9Xn6eLmhqasatxibJz8vnskhQuPePG3glp9hgmGhqYpjgcfklNZSXYwXGlOag34tjoB4pQojNigr24e05SoxUCR7r6erMuV17qiVbfjMYNizTNPDOBDRV7y7C63duOHqZc9hv1YFLgsdpE+6JZRk7EYJ0fBRIEUJsGt8yMJ/PShQMsrIKyznPd/hiCfafV/MOs2kaxIouSHNTZNHii2ruoaCswnIkdlNxvs7hMcHU62ElQkE+/V4cCw3tEUJsmtLLFevSk3CpuAb5JTV6U8z5huemDAwTXLT4f39YthgnABwr4G+PmLF9u8DTzUWvxyq5RxA+SjNc2J1Yzkdp8Vi4KYt+Lw6OAilCiF3oHmRYo+fFbdmorNVf7qWythHrjhQInounILqsnBXShww93Jx5g0liPUJBPnEcFEgRQuySdtZUW8bM2vP3snyV8dtClDjJM9woZnBUIADuYJJYH/1eHBvlSBFC7JLYrCkhnXzdzdgS4/QNV8KPp7aCn4cLhvx/sNSWdpYhIcQ2USBFCLFLYrOmhBK0rTCyh96hSvQM4V4DtGeILz6dOQDD2yxqPDwmGJ/OHGCJ5hFCJKKhPUKIXdLOmjp0oVivKKKzQqFL+OVLBF5zRLikgBwamxmO8STAH8svQ6mmnvJtCLFD1CNFCLFbfKURPkqLBxNYBibE14N3n1xKqusE9+eXtJQ/6B7kjZFxnSiIIsROUI8UIcRuCc2amrXqGO86aAMj/S3e1kAf4bwsKuBIiH2iQIoQYvfazpoSmtG3P1cNdxfLZ0m5OCkwNDqQsxDo0Og/E8rz1NUoKNXQ0J4V0LUnUlAgRQixe21vgGIz+nzkWplYQFFFLRjPaCNjQLmmHk9uOmWw1t5HafFQerlaqJWOia49MQXlSBFC7Fa5ph6zVh3DHSsyMHf1cYx8Zx9mrTqGAJE6URPju1qohX/q4ueBI3ncy9IcySvBw+tO8A5FGitPXY29OTdxqZh7uRnC7clNp0y+9sRxUY8UIcRu8d0ANfWNPEdoWX5oL+d6leB+riVttEORl4prBIeaqEdFOrFhYLFrTwj1SBFC7JL2BtjUZrysiTGcEFnX7stf82VsGbe9OYY3a2NpZ/TxoR4V6cSGgcWuPSEUSBFC7JIplc3/uCbcOySHhqYmyce6CCwOKBRQantUCD+xwq40m5KIoUCKEGKXxG6AQupNCGqkChYpfyCksZm/Jhb1qJhGW9iVrwo+DesRMRRIEULsktANMKaT8M2vRxD3Ui1yCjAhkBLqFaEeFdMJFXa1Jpo8YB8o2ZwQYrf4loGZnhSOxzdk8h7Xs4svDvHMoJOL0PAcAMR28sZFtYZzuRuhXhGxpXKoR0WcUGFXa6DJA/ZFwRhfZRNiqsrKSiiVSlRUVMDPz8/azSGkw2p7A1z0VRa2ZhXxPj4qyAt5xdJzrKToGeKDP65X8+5PilTBw9VF0s2zQtNgEFDSjdd+aavycwXG69KTrNgyx9Ge+zf1SBFC7F7byuZVt4TLH5TV1MvdJANiBRf8PV3xn9mJknpFbK1HhfxJrFp62/1UjsH+UCBFCDErW1hm4/YwJXafu8m7X+XlhrJasVpT5qXyFi4SelfvEACGQWF7mHIsMS+x4Tm+/VMTwwTPm19CgZStoUCKEGIWtpTXce/toXh3Vy7v/v4RKuSVWHZoL8TPU3B/kK/0ZHRie4Rqe61LT+LdX9sgHOBrJw/YwhcW0oICKUKIWYjdOCwpKtgHfUN9cabIsF7U7V394O9p+bwhlUgwWVxVZ6GWELmJDc/tP6/m3X88vwx+Hi6o5BieVnm5QuXlilmrjtnEFxbSgsofEEJMZotFIQvLbnFuv1xai8tllu2NAsTrPRVV1FqoJcTc2pYpEPtdZxUKV97nCqIAoEzTgIfXmr4mIzEv6pEihJjMmKKQlhx+yMi5ifLaBs595bUNqK2zfEHO8yJr7YUqhYf+iO3hG86eLpLn1EXpIfk5j3Msf0SJ6NZFPVKEEJPZWlHIU1fKBfc3w/JVX6pucQd2WtocKSrCaD3tvfZ8w9nv7ebPzwOApmbwFpMd2E3Vvka3QlXsrYN6pAghJrO1opD9w/wF99/WxRdH8kot05j/FxXsg5OXy3n336pvpNwXKzFmokR7yhTk3uSvFwYAJdV1WDahN+7/5BDKNH8G2H6eLlg0KhYPrDoq6XVQFXvroB4pQohZ2NIyGyPiOvFWEndxUmDm4EjLNgjA8Lhgwf2f7L1IuS9WIjRRolxTj1mrjuGOFRmYu/o4Rr6zD7NWHcO5okrJzxfo444Xt/2OyjYlOCprG/HmT+cEj+0T6kfrAtoY6pEihJiFLRWFzFNX8y7029jM8N/frlm4ReJ5MdkcN2bKfZGf2Ay7h9edQGZBud6+QxeKUaaRPsvSWaHgfU6u90Fryyf2xTs7zxssi2TtdQEdGQVShBCzsoWikGLJ7z/+xr98jFyamoGh0YE4fNFwjb/bQnxxTiAZnYowykfsvXI8nzu5+8xV6T1SZ69VSD7W19N2vrCQFhRIEUI6HLHkd083Zwu15E8l1XXgW9nU3UU4y4JyX+Qj9l6Rg0J0wSB+2qDaFr6wkBaUI0WIg+rIs8MKRXoZgq1QRfzIxRIcyTPsjQKAU1cqkBipotwXOxMfpuTc3p9nu1ZciK/k52xd2byj/v3aG+qRIsTB2NJSLu3RniUxRMsfWL76Aa6JFNycPTQSnq5XKPfFwsSG9m7r4otz1wyHXYdGB/Ie4+UufGtN6h4guL9/uD9OFZYbbB8SFUiVzW0QBVKEOBhbWsrFGFKmpouVP4gPVwkuaiyHAC835IH/pt07VIl16aGCuS+0vpppuK6f2NCeB8+wq6auiTdg58qDa+0kR1HN1lyduYf+mpqb7e7v1xFQIEWIAxGboWSLs8OEbhwfpvXnDbJUXq56NXq0VF6uCPBxk73dbd0wci09rtwXe+1FtBVC109MViF3YrhYr6eQt0VKHHAluAPAMZ7ttvz36wgk5Ui9/vrr0GgMv1nV1tbi9ddfN7lRhBB5GLOUiy0RW8NPaN2x7QtSDBYKVnm5YvuCFMAKlc3FnlPo2gsFk0Sc0PUT+5uQQylHgG8Otvb36ygkBVKvvfYaqqsNK7dqNBq89tprJjeKECIPW1vKRYzo1PSCMt4gq5ExZL08Gl+mJ2HRXTH4Mj0JWS+PRnigF5xMmDUlVe9Q4QRkvmtviwtC2xOx69c2wd8S3HmG7kxl7N8vJaqbl6ShPcYYFBxvvtOnTyMgQDiJjhBiPba2lIsYU6ama6eJD4sJxrAY/ari16tumdq0dmtqZpKuva0tCG1vxK5fExP+vQDg3Ofp5oRqiYtfe7g6o7axUfyBHGI7e+PiTY2kv18aIpZHu3qkVCoVAgICoFAoEBsbi4CAAN2PUqnEXXfdhalTp8rVVkKIGdjSUi5itIEfV1mAxEjhxV2Fvp2LJaPLITzAS9K1t7deRFtjzPUT+r3w7ZszJFJym5pMGFlO7hEMP0/9PhA/Txf8fUIf0WNpiFge7eqRev/998EYw0MPPYTXXnsNSuWfXdVubm6IjIzEkCFD2tWAnJwc7Ny5EydPnsTJkydx7tw5NDU14Y033sCLL77Iecyrr74qOoR47tw59OzZk3PfhQsXsGzZMuzevRtqtRrBwcEYNWoUXn75ZURFRbWr/YTYG1taysUYH6XFY+GmLM6yAPPXn+SszTQkKlDwNYVboQjjg0MiwSTkZtlbL6KtMeb6lWvqeY/X/r3sP38TWYXlSIhQYVhMMPLU1fh430VJbfL3dEHlLWk9Ur9eLDGYRFGmacDftvyGjQ8P5j3OHiea2It2BVKzZ88GAHTv3h1Dhw6Fq6vpXYErV67EBx98IOnYfv36oX///pz7Wgd5rR06dAijR4+GRqNB7969kZKSguzsbKxduxbffvstdu/ejcGD+d+MhHQU9lIZWSjw40tvEUt7+dEKa+0B0ktPCAWTRJzY9ZMyM9TPQ3o9a029tCFBALxLCR2+WCIYDNEQsXwk5UiNGDECzc3NOH/+PG7evInm5ma9/cOHDzf6XH369MEzzzyD+Ph4JCQkYPny5fjyyy+NOnbChAl49dVXjX4ujUaDqVOnQqPRYOnSpVi+fLlu3/PPP48333wTU6dORU5ODjw9PY0+LyFEfm0Dvzx1NW+9HrGbSmmN9AVnpfo1r0Ryj4C99SLaGqHrJ7po8doTyLxcrrfv0IViOCmkj8/dapAeSAk5mlfC+76gIWL5SAqkfv31V8yYMQMFBQVgbWZCKBQKNDUZ/yaZN2+e3v+dnORbtWbNmjUoKipCbGwsli1bprdv2bJl+O6773D+/HmsW7cOjz76qGztIISYzpRv2EHell8ipqRaOHjTtleo6Ka99CJaU3uvnzEzQ9tqYsykPKfa+mbxB0kg1CQaIpaPpEBq/vz5GDhwIHbs2IEuXbpwzuCzRVu3bgUATJ8+3SBgc3JywrRp0/DGG29gy5YtFEgRYuOM/YbNdWO9WGxYvkVuzXwrFv+/W/WNtPSHCaTOSLPGgrPy9EcBg6P4l60BaIhYLpICqdzcXHz77bfo0aOHudvTLpmZmViyZAlKS0uhVCoRHx+P++67D76+3AtCZmW1zEwYOHAg537tdu3jCCG2S+wbttCaZLBCHalgXw/B/Z/svWiwphst/WG8xzdkGgz17s9V47ENJwWTsOXpG5JPVJA38jjqP4lNsABoiFgukgKpQYMG4cKFC1YPpH744Qf88MMPetuUSiU+/PBDzJo1S297VVUVSkpa/sgiIiI4zxceHg4AUKvVqKmpgbc3vcEIsWVC37DT1x7HiTbDMvtz1Zi39jhGxAa3PZXsxGowZhdVGmyjGVXGMSVfzpRaZVIFeLqgtFbarL3n7o7DxmOFkpa70aIhYvMyOpD67bffdP9euHAhFi9ejOvXr6Nv374Gs/duv/1287WQQ3R0NJYvX4577rkH3bp1AwCcPXsWb731Fn788UfMnj0bzs7OeOCBB3THVFX9+U2PL0Dy8fHR/buysrLdgVRdXR3q6v7Mg6isNPxgJISYD185gfySaoMgSut4QZlVhsrOXpP+eUAzqoQdvSS8SLBQErY1lEsMogDgv2eKzNgSYg5GB1L9+/eHQqHQSy5/6KGHdP/W7mtvsrkUDz74oMG25ORk/PDDD3jyySfx0UcfYdGiRZgyZQrc3Cy3OOmbb75JS+QQYkF809YLSoWXvshTWz5HKshHeoI7zagSI9zdJ5Sd9uNvlg9MTBlO3H3uJuoa9V8RDQFbl9GB1KVLl+Rsh9m8+uqr+Ne//gW1Wo2jR49i2LBhAKCXN1VTw/0h23r9QD8/v3Y/99KlS/HXv/5V9//KykrdcCEhRHhGlZRz8U1bLygRnonl7mL5FONOfsKBVGI3FTIvl9OMKgkGdRdemkwoCfu3KxXmbo6sNA2GYRgNAVuX0YGUdgjN1gUEBKBTp064du0arly5otvu6+uLgIAAlJaW4vLly+jXr5/BsYWFhQCAoKAgSflR7u7ucHe3/LRqQmydHGt8iU1bFzIkOgjnrlu2V+paxS3B5HiaUSVdVLAPlJ6uqKhtMNin9HTVqxnVNpD39ZCUKmwSFycFGptNqJ/Ag4aArUPSO2j79u2c2xUKBTw8PNCjRw90797dpIZJ1dTUhIqKlm8YbWfvJSQkYPfu3Thx4gTuu+8+g2NPnDihexwhxHykVvQWYkqS8MzB3fDFoXzJx0vh6uQkGCzRjCrp8tTVnEEUAFTUNuB0YTlW7DzPGcirPC2X/qHVPdALuWrh4WcpaAjYOiQFUhMmTDDIlwL086RSUlKwbds2qFTCC4ua2/bt26HRaKBQKAzKHEycOBG7d+/G5s2b8corr+jVkmpubsZXX30FAJg0aZJF20xIR2aLa3ydyC+16PMBgLqqzqhgiWZUtZ9Y7+QL287gXBF3aQk3F8uXwigTWNtPTFSwF/LUhq+3dfkDcw6hE3GSEgV27dqFxMRE7Nq1CxUVFaioqMCuXbswaNAg/Pjjj9i/fz9KSkrwzDPPmLu9uHz5MtavX49bt24Z7Nu2bZuuUvoDDzyAkJAQvf1z5sxBaGgozp8/j5deeklv30svvYTz588jLCzMoHQCIUQ6YyqQSyE2U0vIrrM3JB8rlVOr+3X3IG+MjOtENzkzEbuRZV+t1BtOBf4M5J2sUFOstIa798wYVTw9bwpFyxD6rFXHcMeKDMxdfRwj39mHWauOoUIj/fmIOEk9Uk899RT+85//YOjQobptd955Jzw8PPDII4/g999/x/vvv683q49PZmYmHn/8cd3/L15sWU373//+N3788Ufd9q1bt6JLly4oLS3Fgw8+iMceewzx8fHo2rUramtrcfbsWeTm5gIARo4ciZUrVxo8l5eXF77++muMHj0ay5cvx/bt29GnTx9kZ2cjOzsb3t7e+Oabb2idPULMSL41vqTfAP08LV/+wN/b8kNIHVXbHhdTZsFV11k+yDClvepq7vYevliCh9edQGZBud52mtEnP0mB1MWLFzlntfn5+SEvLw8AEBMTg+LiYoPHtFVZWYmjR48abL9y5Ypesri2PlN4eDj+9re/4fjx47hw4QIyMzNRX1+PoKAg3HvvvZgxYwamTZvGu2ZfcnIyTp8+jTfeeAO7d+/Gd999h+DgYMyaNQsvv/wyoqOjjboGhBDjyLXGl9hMLUHmz/MVFWxC+QPSgm/SwuLRsZLPyTULzl4dz+deF5Bm9MlLUiA1YMAAPPvss1i3bh2Cg1sqBKvVajz33HNITEwE0LKMjDFT/1NTUw1yrYQEBgbirbfektJsnR49emDt2rUmnYMQYjxjZ6S1J7cjKtgHQ6ICcSTPcIjvthBfnLtexXFUi4pblu+FGCSyDhoRxzdpAQBUXq4o4xjC4tuuFR+uxKnCcrO20xbRjD75SAqkVq1ahfvvvx9hYWG6YKmwsBBRUVH4/vvvAbTUZHrxxRfN11JCiN0SS7KWWh7h05kDDAK04THBGNkzGK/9cJb3OJUVhvaIacQmLfARCqIAoLpO3gLSXLr4ueNaZZ34A82IZvTJR1IgFRcXh7Nnz2Lnzp04f/68bttdd92lG1KbMGGC2RpJCOkY+GakSS2PwBegfbDnvGA7yngSduW047ciPHFHjMWft6MwpW6YkL05lp94UFojTxDVLdALV0prqairhUmuRObk5IQxY8ZgzJgx5mwPIcTBmKM8QtsArX+Yv+DjlZ6WL8KY16pukNTp6Y48rV2uxYVrrdAjJddTPpQciT3n1FTU1cKM/jT58MMP8cgjj8DDwwMffvih4GOffPJJkxtGCHEMxpRHaG/QEC5y02XM8lPeVV6ukocw5agMT1rIUWHcWiICvbEuvTsVdbUwowOp9957Dw888AA8PDzw3nvv8T5OoVBQIEUIMZoc5RHEgrNKKySb9+jsi8fWZxokx+/PVWP++pPY9Mhg3mPlqAxvb+Qa2nNSKGDpaZxB3q4oNqGWFB/t34pYUVdH7tmUg6RFi+1lAWNCiO2TozzCzQrDgr2tWSPZ3FkBzhmGQMt2viFMW6wMbw1yDe35uDujttGyJRCaTOgFiw7ywsVi4crmfKhnUx4mLYFeX1+PnJwcNDY2mqs9hBAH9FFaPJJ7BOltMyW341eRqudXy4UDLTn8mie8LM2vPEGWXJXhSYuKW5a/f5XVSn/O+ibuIExhxGi1UM8mkU5SxqVGo8HChQt1tZjOnz+PqKgoLFy4EF27dsWSJUvM2khCSMdm7gV780UWhC0ss3zwUSVywy6p5p7JJV9lePsi19AeX2BiqwrLajm3H77I36sJUM+mnCT1SC1duhSnT5/Gvn374OHhods+atQo3cK/hBDSXu0pzivkVqPwtKjSaumLxkp1e5hScH8gT+Vz7dCnc5suB2eFAsNjgh3m5ifX0F5HItQ7ST2b8pEUSG3btg0ff/wxUlJSoGj1x927d2/dWnmEEGIsUxdbzVNXY2/OTVwqbrkZ+HtZZ107d54+/iFRgRh3exfBYwcLVD4399CnPRIKKAMovweAcO8k9WzKR9LQnlqtRqdOnQy219TU6AVWhBBiDKmz0viSZ+Mj/HFEICcptrMfsq6Um9zutqYkhONy2S3eZF6+JW3EEoXNPfRpr/iWGiqtqUOpkUG3vfNxd0ZtfXO7J2bIteYlkRhIDRw4EDt27MDChQsBQBc8ff755xgyZIj5WkcIMYk9THM2JXeDLwCrbRDOR1o0OgazvjguvdE87u7bBcNignkDHr4lbYztWRKb1t5R8L1v+QLK17f/juyiSknP5QTA0ssWuyqABomj2IO6B6ChCZKKbhq75iVpH0mB1PLly3HPPffg7NmzaGxsxAcffICzZ8/i8OHDyMjIMHcbCSHtZE/TnKUW5BQKwI7nlwme85pMs/ZOF5Zj2P/nLXG1mVm4XpG9MfZ92/b6xoT4Sn5OSwdRgPQgCgB8PV3x/rR4Sb2T1LMpD0k5UikpKTh9+jQaGxvRt29f7Ny5E506dcKRI0cwYMAAc7eRENJO9jTNWWruhimzuLaduir5WCG/FVYI7ren34s1PLzuhEFwvD9XjYfXifUeOk6AmhzdkivXPcgbI+M6SQqETDmWGJLUIzVr1iyMHDkSS5YsQXR0tLnbRAgxgb1Nc5aau2HKLC7ZUjkVLe3PyLmJU1fKkRChwrCYYAD293uxtDx1NW9P4rH8MsHrk3u9Ws6m2ZSBkQEA7GPY3lFICqTc3Nzw5ptvYt68eQgNDcWIESOQmpqKESNGICaGVjcnxJrkWLtOblJyN4QCsNtCfZF9lT9nJq6zHw5fFC6QKYWfpyviX9+JslaJzyovV2xfkGKXvxdL+vG3IsH9O34rwhN3tNxf2gaq+3JuWqKJNuHbE5dx5mqVXQzbOwpJgdTnn38OALh69Sr279+PjIwMrFixAo8++ii6dOmCK1eumLWRhBDj2eM0Z6m5G3wB2OLRMbj/k8O8x8WZkFMj5L+/XYOmQT/rpkzTgPGfHMR3jw0VPNYWfy+WVCqy9lxxdT0KSmow4ZNDBoGqvZU/CPZ2hVriWntbs67iRqV+HTRHW3fR1kgKpLRUKhUCAwOhUqng7+8PFxcXBAcHm6tthBAJ7Hmac3tnpQkFYH1DfXGmqMrgmNu7+iGpe4DZ2txa2yBKq0zTgKvltXb7e7GEkXHBWHM4n3f/nbd1MgiigJZrW9sgXIDV1ni5uQASA6miCsMK+DQ8bF2Sks2ff/55DB06FIGBgViyZAlu3bqFJUuW4Pr168jKoqRJQqzN0Qo4ciXPcgVRAPDb1UoUyrTciJDMy2UO93tpjxFxnaDkWUxa6emK5mZmEERp3eIJYG1VAc8yL6ai6uTWIalH6q233kJwcDBeeeUVTJo0CbGxseZuFyHEBI4+zfnjPbmC+z/YLbxfDqFKT4f/vYj58YkUjP/kIGeO2ZZTlDIixtGHh61FUiCVlZWFjIwM7Nu3DytWrICbm5su4Tw1NZUCK0JshKMWcDx0sVjw8Ter5akjJSTI98+19Bzl99Je4YFeyHp5NA7kqpF5uUxv1mP/MH/rNs5G9An1w7lrVbIND9NswPaTFEj169cP/fr1w5NPPgkAOH36NN577z0sWLAAzc3NaGqyr/FqQoh94ivgOCBCJbhEzJheXfD5oUuWaKIO9RYYr6u/JxqbGcJUf06cGBHXCS5OCjQ2O07NKC7LJ/bFOzvPm706uT0V8bU1kgIpxhiysrKwb98+7Nu3DwcPHkRlZSVuv/12jBgxwtxtJIQQTlKXiInp7CNns0TRt35uQjfzkpq6DhNEdfJ2xU2BZPPESBUyC8o5e51uD/eXZXhY6nqXRGIgFRAQgOrqavTr1w8jRozAww8/jGHDhsHf39/MzSOEEG6mLBEjV2VzIfklNVB5uVrtW789BG9CN/O5KZHWaZQMbjUKJ8ff06cLPF1dBHudzDk8TMViTSMpkFq/fj2GDRsGPz8/c7eHEEKMYsoSMQrIVdqcn4uTwirf+u1lyEbsZj6ub4gVWiWPyjrh9Jdfsq/B3dWk6kTtQsViTSOp/MG4ceMoiCKEWJVY4dHEbio4t1kLxlmhwPCYYAyODpSzaZyulGmwP1etN1wD6H/rl4O9rO8ndjM/d52/Un1Hc+pKhUV/Z/ZYxNeWSAqkCCH2IU9djb05N2W7SVuTtvAoX7C0Ymo/+Hnqf6v383TB3yf0sdIHn3AvmBw1gLS9PJYO3qQQu5lboxfRWuoamy36OxP7W6LeKGEUSBHSAZVr6jFr1THcsSIDc1cfx8h39mHWqmOo4CloaK+WTejNGyz97bsznFWwn/vuN1wolmeRW3cX7o/UodGBGCRSTV2Ob/3GDNnYiqhgH6h4hhpVXq6IDbHuBAFz8uR5nxhDrt8ZFYuVznKDsIQQi3GUGTh8wdKTmzORVVjBecyRvBJMTugqS3v8PVxwo7reYHtDY7NVlu6xpyGbPHU1b+XyMk0Duvp7WrhF8unk6y65urlcvzMqFisd9UgR0sHY03COKfLU1TiSV8K5jy+I0rpWLk9BTq4gCgCOF5ThUnGNxb/129OQjVjv2VWZfmfWUHFLuGc4MsDTar8zruWWiDDqkSKkg3GUGThHL/EX3BTj7e5sxpYY59e8EqQlRVj8W/9HafFYuCnL7AUczU08R6rjqK0XnrU3NDoIV8pv2fzvjLSgQIqQDsaehnNMI704o6ZeuGCnHFoHApZcIsbUIRtL1Z+KCvbB0OhAHL5o2Ms4NDoQSSI5ZvbEy80ZdbX878H4biosnxyO/efVyCrUXyqH2B4KpAjpYKyRi2MNg7pLL2FgSg0qqQZFWb7kQmvtDd6MrT9lzkCL8cTGjLW8r+VYIsZJAVi6YHqvUCUOcQSMWh5uzpi16pjN1/4iLShHipAOyBFm4Gh7MLjcFuIreGyvLlQHT4xY/SlzzwwVynk7kleCr45flmWJGB83yw/z+ngI92H8J+OiXdT+Ii0okCKkA9IO5+x9JhWr5yZi7zOpWJee1OG+za58YACGtxnyGB4TjM2PDIGLE3dWjYuTAiN7drJE8/TYUqkBMcZMWDB3oU+xXsJdZ29IOq+YKpEq43I4mS+c33fmamWHnyzSkdDQHiEdmCVzcayB8eRJ5ZfU8PZeNDYznL9eJWezONlTbppYUPNrXrHZ12YTTTaXKdvcGssgV92SnqPXUSaLdCQUSBHSgdnDQrWm4OsVKa2pEzyuUGINH0chFtQYU6W9ve83sdy+jlRHykmhgNQQjq+nlVgPDe0R0gE5QmVzoeGn7CLhddn8PCw/xGlPQ3ti9afkqtIulNs3Ms7yw7FyCTUhKJQjT4yYhgIpQjoge1motq32rA0oNvzk7cb98ab0dMH9/UMFj+X7zm9KX4A9De0BwkGNXIU+hXL7RsgUSFnjJjghoSvvcjh+Iono9vY+cgQ0tEdIB6PtqWnLlPwVuRk71b41sRtgTX0z5/aK2kZcrxSuks33nd+R+gLE6k/JWeiTK7fvq2OXTT4vlyBvV9yssWxPrbNCgfXpSbj/k8N6PUwuTgo8OzoOL23/nffYK2Uam/v7dXQUSBHSwdhjZXNj1gZsm+9VVCE9z2mTTDdlIbZ43Y3BN2HB0muzHbnEX3fJFJYOogDgYK4av+aVGtTNYgz4/GCe4LGZl8uoOKeNoUCKkA7G3iqbi/WgnS4sw4qduQa9VamxQQbHGKuy1vI3T1u77uZiqZmhPYJ8ZH8OS7nV0ITMPMMSCE2MoaBU+AuCqxNl5Nga+o0Q0sHY00K1gHgP2gtbszl7q/6bfV3yc0YHy3NT7tvVz26uu73pHaaU5bzOVpgEZ8oQcUMz95A1sR4KpAjpgOypsrlYD1p2EXdxwhMFZYLH9erCXd08IcIf/cL829VGYz06Itpurru9uVkhnNcmVZOdJb4lRKgAtG9iBpGX1Yf2cnJysHPnTpw8eRInT57EuXPn0NTUhDfeeAMvvvii4LG7d+/Gu+++i2PHjqGmpgbdunXD5MmTsXTpUvj48H/jvHDhApYtW4bdu3dDrVYjODgYo0aNwssvv4yoqChzv0RCLM7S+SumiAr2gcrLFWUcpRl83J1RLbHydAFPuYGL6mqMiJMnx6R3qBLr0kNt8rrbe02x61XyBFLSKzpJFx+hQn6JhvM9r53Nx7evb1clrcNnY6weSK1cuRIffPBBu49777338Ne//hUKhQLDhg1D586dceDAASxfvhzfffcdDh48iKAgwxyKQ4cOYfTo0dBoNOjduzdSUlKQnZ2NtWvX4ttvv8Xu3bsxePBgc7w0QqzOHiqb56mrOW8aACQHUYDwrL1KjfTK0sawpesuZUakLeovUy+ir7szKi28TIyTQsH7ni/TNGDjvEFYsDFT7zEqL1dsX5Bi1MQMYllWH9rr06cPnnnmGWzYsAHnzp3Dgw8+KHpMVlYWFi9eDGdnZ+zYsQMZGRn4+uuvcfHiRdx5553IycnB/PnzDY7TaDSYOnUqNBoNli5diuzsbGzevBnZ2dlYunQpampqMHXqVNTWUtVjQixFLEeqTyh/3hFfLR4PV+GPtrPXKtrXSCP9yrPorjXZa02xtsJFq61L4ybyXpHDiQLhtfbqmpqR9fJofJmehEV3xeDL9CRkvTwaDc3NomsgEsuzeiA1b948/POf/8SMGTPQs2dPOBkxI+HNN98EYwxz587FPffco9vu5eWFVatWwcnJCd999x3++OMPvePWrFmDoqIixMbGYtmyZXr7li1bhtjYWBQWFmLdunXmeXGEEFFiOVLLJ/blzDtaPDqW91v9rQbhhNw6kf1SlVQLL01jacYsPmwvxAJuqWpMWPdOqs6+HoL7tTM8u/p74vYwf4SpWv5GjCltQizP6oFUe9XX12PHjh0AgBkzZhjs79atG5KTkwEAW7du1dun/f/06dMNAjYnJydMmzYNALBlyxazt5sQwp0gKzbLMCKQO9AqLJN+Yw3wcZN8rJBAH3ejHmepROGOdOOVK9m8ttHy2eYje3YSfM+rvFw5l3gK8BJ+33bUEhu2zuo5Uu11/vx5aDQtHw4DBw7kfMzAgQNx4MABZGXpd11r/y90XOvHEULMQyxPR6hK9mMbTuLwRf0hs/25alTdkl4Lql+YErvP3ZR8PJ/BUYGC+y2dr2RvNcWEyJVsbg2DogJxT58uvO/5+etP4kie4Xu+oalZcGFnW8nLczR2F0hdunQJAODv7w9fX+7pzeHh4XqPBYCqqiqUlLS8MSMiIgSPU6vVqKmpgbc3vSkJMQexBFntLMOvjl3GkUslSI4OwpSB4chTVxsEUVpZheVwVnBPX3dxUsDTzRlVHMM2fh4uUJiwap63mxNnIrvS00X0RmbpRGFtb19HuPHKlWwe7O0KtYWrm/905hoeH9mDc2ZtnrraIIjSOpJXgu1PtIy4yLE0D5HG7gKpqqoqABAMcrSlDyor/1wBXnuc0LGtSyZUVla2O5Cqq6tDXd2fORKtn58QR2XM2n9OCmDCJ4d0OU/bsoqw/L/nMC9FuBwJXw2gxmbGGUQBQOWtRt7gzBhCswGF1jG01hqIcq6JZ0kj4jrBxQloNHN6m5Oz5TNcfjhdhMdH9gAAXC6pwW9XyuHipED3IG8cvSSciP57UaXdlDZxFHYXSNmyN998E6+99pq1m0GITTEmT+evX50ySBwv0zTgk725srTphsiixVIJradnrTUQ7ammmJA8dbXZgygAqDZhiFgqT1cnFJTU6H15AFpKHEyMDxU8VjuhwZZKbDg6u0s21w7n1dTwJ0lWV1cDAPz8/AyOEzpWe1zbY421dOlSVFRU6H4KCwvbfQ5COhqxPJ2bFbd4Z99pZJpdV10vz81TKOfI2vlK3YO8MTKuk93efMV6aqRys0KPVHyEyiCIAlq+PGw+fkXwWGMnNBDLsbtAKjIyEgBQXl6uN1zXmjaA0T4WaAmkAgICAACXL3Ov/K49LigoSFJ+lLu7O/z8/PR+CHF0UcE+GBrNnYQ9NDpQNIk4TOXJuX1IVCBvHSkfd2fBc3q7ydsZzzc7cQhPMvqQqEC7DXAsR57ZdT4elh+YuVLGXdUcADT1wsVBxSY0EMuzu0AqLi4OXl4t3+xOnDjB+Rjt9oSEBL3t2v+39zhCiGkYzz2QMfEk4qdHxRgETCovV/xj8u3YviCFc99PTw6Hvyd3kOXv6YoRsZ2Mbnt7ZBdVcE5br/j/m6aCJ8edb7uj4gpEB3WXJ4BIjAyQ5bxCblQJ1xsT+vJAAbftsbtAys3NDePGjQMAbNy40WB/QUEBDh8+DACYOHGi3j7t/zdv3ozmNitoNzc346uvvgIATJo0yeztJsRRic1Cigj05u1ZUnm5Yvupa6is1U8cr6xtxAvbshEe6MVZATo80Asb5iXBxUk/QnFxUmDjvEF4cEg387y4NtYdzuedlSc0A/HwxRKz1JSy94VsyzX1goGoHJwUlr8NDuymEtz/4tjbMDxGfz3I4THB+HTmADmbRSSyu0AKAJYsWQKFQoHVq1fj559/1m3XaDRIT09HU1MTJk+ejJ49e+odN2fOHISGhuL8+fN46aWX9Pa99NJLOH/+PMLCwjBr1iyLvA5CHIExSdZ8PUsfpyUYVZl7WEwwnrozFsNa3XyW7fgDjc36xzU2M7yx45wpLwfdAj05CykO7KbC8fwy3rYeE8nxMaU4pjUCEDkIlYeQq7L5jjNXZTmvED+e3lItbw8XrEtPwt5nUrF6biL2PpOqKxNCbI/VA6nMzEwMHjxY96OtWv7vf/9bb/u1a9d0xyQkJGDFihVoamrC2LFjMXLkSEybNg09evTAnj17EBcXh08//dTguby8vPD111/Dy8sLy5cvR9++fZGWloa+ffti+fLl8Pb2xjfffANPT+5uVUKIuLa9IsYkWWt7lp69OxZDogLw3N1xyHp5NOqbhZPN+YIPsV6wj/93wYhXwm1ETDDnkjVzh0YKHieW4WNKsnlHWE9PbDkb2SqbN1i+svm+PwzLYLSWebkMgP1PEHAUVi9/UFlZiaNHjxpsv3LlCq5c+XP2Quv6TACwaNEi9O3bFytWrMCxY8dQU1ODiIgILF26FEuXLuUt1pmcnIzTp0/jjTfewO7du/Hdd98hODgYs2bNwssvv4zo6GjzvkBCHIRQ1W6xopBtp4IfySvFZwfy8LFIrSNt8JGnrkZBqUY3tV9shte5a9JrvBVV3OIsJ5CRI1wpPUzlKUtxTGvVpzI3sR6njlTZvLy2XnB/QoTw0B+xLVYPpFJTU8H4MlFFjBo1CqNGjWr3cT169MDatWslPSchhJtQr4hYUUi+qeBPbMoSDD60a5K1Dd5S4/R7jNq6rYsfzl3nnvUrRtvD1vZzS6xQQ2Mzk6U4prXqU5mbWM9lfLi/LM/r7gzUCU+UM7uECBUul9YaDD0DLXl8w9rkRxHbZvVAihBi/8R6RUo19bxFITNybvJOBS/TNOD+/l1w5mq53mP8PF3w9wl98Nj6TM41yapuCX/jX3hnDL4/dZWzMroCwsNwEQFenMHb9KRwwed0cVLIUhzT2vWpzEVsOZswlfDrlOqBQZH44nC+LOfmk9Q9EN9mcudmNTYzu+lFJC2sniNFCLF/xvSKANw5H6eulAse++GeXM5Ze3/95hRvHlRWYYVomz1duT/+XEQ+Fb84fImz5+29XecFj7taVqv7tzlzX7QBCFcC/PCYYLu6IX+UFs+Zf/ZRWrxsyeY9Q7nTQOR0rbJWcL8pEw+I5VGPFCHEZKb0iojVkSooNbzpNDGG4/llRrWNy0d7clHNs2aeWDH1ghLu9uTerOZ49J/kTGnuKOvpCfXYyZVsvvP3G7KcV0h8uHAOlL30IpIWFEgRQkwmNiwj1CsyIq4TVF6unMN7Pu7OqJYhgeVUYbnZzylGzorUHWU9PS2udeTkSja/JVJJXCp/TxdU3Wri/HsYHhssy8QDYh00tEcIMQuhYRkxfHWk/i1TAUKFTP1DvUK4h4ksVZG6I0+XF+u5lKptuQVzeWBQN8G/B1P+XohtoR4pQohZmNIroq0jdSBXjczLZUiIUOlmLg2JCuTMhYoPVxqVC8Wls9IDF4vNn3OzYGQPfHXiCmcJCGK8tuUsgJaeS6WnKypqDXsu+bYbo1cXPxzJM/+CyH8ZGI5nx3hj/3k1sgr139NAx+tFdGQUSBFCzIprWMZYw2KCDaZ+861D5+nmAqWnCyraJKIDgK+7M6oEhgSHRgXh8EXz3zx7dVViXb9QujlKJFSLTOnliqggL87gOTrICzk3qlHDMUzn4gQ0CuS9XSkTTvyWav/5m3jlezXva9Ey5e+F2AYa2iOE2Cyx9em4gigAgkEUAJRqhBeNFeLFM9tP5eWquyF25CE2OT2+IdOgjMb+XDUe23ASeepq3h7IzMIKziAKEA6iAOBwXrHwAyR6b1eu3VebJ8ahQIoQYrPkmvJ+xITeKA3PtL4yTYPdLhZsC8SC5h1nrnHuM5W7szy3wfLaBtE1IknHQIEUIcRmZOTcxAd7zuPA//dKiJVVkE6eBGOq/yPd0UvcQZTWbzLNtOzs6y7LeYXQ+6RjoRwpQojFZOTcxKkr5QaJt23X2gNahsq2L0jhnSZ+W6gvsq/yr5nn5eYMDcdwj5+HC1ReboLt5Mu9ig/3R5bADZ3q/5iCJxnu//l6yHO7KuGpqi8nep90LNQjRQiRXUFJDeJf34nZq4/jvV25eHDVMcS/vhOFJS1Dd3xr7Y3/5CDvNPG/T+gj+JxCH25e7sI35f7hSgxvk/Q+PCYYa+YmdZgq4rZmUPcAwf0T4rvK8rxRMv3OfNydObe3zqUjHQP1SBFCzIpr6rpQoPT+tP6Ca+19f+oKDl/UT9o9fLEY/c/5Cbajmif5uPJWI1Serpz7tAZ1D8LjI3twzr5bNqE37m/zerRr/xHpooJ9eHsClZ4uGB7bibcUxm0hvpIXoU6JCcZhieUPXBRAI8cosbcbfyFZbS4dBVMdBwVShBCz4Ju6Pj0xTCRQKhI87yvbzxpkNDU2M3z4v4uS23qlXLhKtnYYkWtq+ovbfudc+++FbdlYl54kuU2OLk9dzTsLs6K2EZeKa/D25Ntx/ycHDYaAh0YHSg6k1h25JOk4AC21OTgKeopl4OWXUCDVkVAgRQgxiyc3neKc7l1QKpxYK3bTkSMt/EqZcJtKq+sBGPau5amrDabnA/qzsegGKY0xC1+vPpjPGcQe4PidGKusRnqOVGMz97uTKzevNcqR6lgokCLEQXENwZlyLr4Ao6BE+AY5KaEr/vfHTc7K1GLFFKWqruPu+dBKigrArFXHDHrXpiaGCR5HPQ3Sic3QdFYoeN9j529KnwWn8nbF9cp6ycfzCVd5opCj2OfQaMssF0QshwIpQhyMWPVoKcR6E/gWH1Z5uWJYTDDiOvvgWH6Zwf4AbzfcrDL/TS7Ayx1NzS35Um35ebjgyyMFBjWN9ueqUXVLuPfCHD0N5gxw7YnYwtdyrYk3JDoIW7OEh5el4Es2l+llECuiWXuEOBi+IThTKi6L9Sa8O6U/XJz0Z7q5OCmwIX0Q8tTVnEEUANEgiu9m5eEiPJV+8oAwRAZyt7mLnztvYUih0gemKtfUY9aqY7hjRQbmrj6Oke/sw6xVx1Bhhen51vLc3XEGSwIpFMCSMXGy3ayc+NYgMtG569Wc24/klVBBzg6GAilCbECeuhp7c27K/gGrHYIzd8XlqGAfDI0O5Nw3NDoQ649eNvgmzhjw1s85JlUv55sZdYtrKlUrKm83/MZTgyrHhGEiUwotyhHg2psHvzhqkHfU2MzwwKqjkGGEFwBwUc0d8MiJCnJ2LDS0R4gVyTHMJsSYhF6pw0n1PMlMlbUNyC4yDFq0wdu8YZGSns8U56/zF/I0RdteN2NREntLsVah2Z3qSuGZllJ5u3H3aspJ6vuE2CbqkSLEiizdCyE2BCc1xydPXY0TBdzDc1xBVGtXyw0TcltL7KbiLIAZqpS+tEcOz7CLqfhmcYkxJsAFgK+OXcbTX2XhmxOF7X4OS/V6SnXqSrng/muVt3iLoQZ4m9AnwKQHNS48d1C+IWctqe8TYpuoR4oQK+lIvRBHL0lfBFhsaZA5QyPh6XZF71ol9wiCpqERRRV1kp6RiRRVCPByQanGMBG9b1c/nBFYlkZqICoW4NY3NKHH8//V3YC3ZRVh6ZYz2L4gGb26KgWPtXSvp1T9w/wF9ydEqHBnXCdMuFisVxNDoQBSegRh++nrkp63VCPtPQTwzyjlG3LWoh6pjoV6pAixEmN7IezjOYUDk5hOPrzLqogtDRIW4Mm5fXCkqn1NbEVsuZEQP+7n9HF3lWWJGO2MNb7zLtiYxZk7NP6TQ6LntpfcqxFxnaDiCey0szsf/OIY53XYfU56Hakw2RbG5kc9Uh0LBVKEWIlcw2zWeM5B3bkTzbVeHd8Lfp76HeDGLquy7MdznIHAb1elVbIGgKTugfDjWQTXx80ZZ3mqZB/JK8Ezd8dyrv33UVq85PYA4F1TcGRcMO+Nt7GZCQ7zyTW5QC7r05N4Z3cK5VCJFcAUYo3OISrI2bFQIEWIlYj1QsgxrGeN5wSA93fl8i6rcvQSd6kBreMFZbyBgFTrj+Rj07zBnDftZ8bECR5bUlOPdelJ2PtMKlbPTcTeZ1KxLj3J5GEyvuHG4wXCw6aH2qxD2Jo1ej1N8fbP53lnd4rlUEl1ViSHT6o+Xf1ocWsHQYEUIVbE1wthau+GpZ9T7IYtFAypZSi4KaagVIO3f8nhvGlv/PWy4LHFVS05Nd2DvDEyrpOkmyJX4jffEFzuDeGet+ToIN591uj1lEqs96xStnpa8nRJPTGyh8X/tol1ULI5IVak9HLFuvQkXCquQX5JjUWqWcvxnDcrTJmabvl8EZWXG745ecVge8tyI8Iz+n4vqsQUic/Ll/i9eHQs78SDXJG6VgMj+XPMxKqF21LPiFgwXqKRJ+AO9HHjXMrFVOWaBov/bRProB4pQmyAKb0btvCc16ukB1KdfD0E9/cM8eXcflsX7u3GaGiWXt4xyMdN8rGPb8g0CJj256qx5LvfJJ+z9fAcV0+XNXo9pRDrPRsikocn1YAI6ZMWhGjDVmv8bRPLoh4pQojJxKauOykArnxpFycFkkRm7Xm6ctfkMWVAJshbeg2qcbeHij6Ga728PHU179Iz53iS240RGegtWuLAHnpGxHrPQpTCAbdUw2ODsepQvtnPOzhKnsCP2B7qkSKEmExo6rq3mzNnEAW0zDr76cw1wXPzrW939pr04MPX00VwSRu+GX1+Hi6CQYjQenliSfVSncgv5e3pemzDSd3/7aFnRKj3bG/OTVme87crFZKPjeK5lkOiAm36OhPzokCKEGIW2xekGARTKi9XTEsMFzxu17kbcjaLU0KEyiDRXEtT14jKW4bFOAGg8lajYMkA4ZpN8iQ1b828ytvTdfiifS2Qq+0945oRqZDp+u39Q/r778HBERgeE6y3bXhMMD6dOcDUZhE7QkN7hBCzCA/0QtbLo3EgV43My2VIiFBhWEwwMnJu4guBoZNOPtKH2aS6Vn4LR/K4g49TIj0UfOsRilWql2tNwdoG7qBP62heCboHeXMON9qq7kGGbYzlyZUzVW2D9Hy51J6dMTclyuaHTYm8KJAihJjVsJhgDGv1LV077MdVTFHl5Yo+Yf7YeU6eYRs+h/P4ay+J0ZYMaBuYiM06E1tTUKo6kUCgpr4Rs1Yds7klYtob2IlVwJcqOTpQMEetf7g/TnEML7cevmN83ZvEIVAgRQiR3fYFKRj/yUG9YErl5YrtC1Jw8KL0wppSDY0KwrasIt79iZEqZBaUcyY9q7xcOQOTxaNjRZ5VnqEpsXUDfzxdhKxC/V62/blqzF9/EpseGSxLm7S4giWpa/9FBftA6emCilrDHjhPVwVqG6QFM8mxwTh7vYpzeHRodCDemtQX939yyOC9+4/Jt9vNOoZEXhRIEUJkpx32+/p4IQ7nFSM5OghTBrbkTg1qtvzspi7+HhgSFcg5vDckKhBvTza8eWqXtOHLgyoTWfz2gkhhTam6BXrj3HX+2ldtgyitI3klsi2MLRRgCOWRrUtPAsA/65EriAIgOYgCWgqsrnxgABZuyuJs78JNWbxV+bVtF3otpOOjQIoQIru2N9ZtWUX44fQ1fJQWj6hgH7g4KTjXk1NAnnKdWzOvoolnKmFTM8OL237nvHn+9ZtTOJ5fZngMYzhzVXipkR0isxOlOlVo2B5j/fr/+VPmxhcspa89jhMF3Ndvf64apwvLsWLnec6ARmzoVKrfiyoxZWA4Z4kIsbw3Lq3XMaR8KcdAs/YIIbIT6oXIyLnJuyivXJkn1ytv4Vg+9xp2x/JLeZcq4QqijHWzUrjHSqrrldIrfssx2Ci01AtXENXaC9vO8L5PxAp2SuXc6iK0LRFhSvBma+sYEvlQjxQhRFZi3+qjguW5QQrxcbP8R5/0uWHyGfT/RSPNOaPPlOAjm6NXT/s+USgUvJMWXJ0VaGiSFnb36PznbMCMnJs4daVcN+PUlODNltYxJPKiQIoQYlbtns0mss5ZF6U7rlUY9uYE+7hBXS2tNyYswFPScR3NH9cq8cr3v5s1WVos+OBL5L+tiy+yi/iHR3/NK+YMogBIDqKAlgrkBSU1mMCRUL59QQpvtfWEbv4m9VCSjoOG9gixc1zrq1kDX1XvAC/htenEboHxESrOoodJJqy9FtNZuCaRM88nI992e7Xsx7OcFdEfXndC8jm1S704K/QHDp0VCgyPCcbnsxI5q5f/fWJfkTNLH4h04jnUxallOG/8x4cMgrQyTQPu/fggb7X12UMjBZ+ThvYcB/VIEWKnbG3qNV8eFADBOlL9w/yxW6COVJ9QJR4f2cMgETgj56bkBO7BUYG8s/Z6dvbBHze4Z8E12eL4nAmuVnAvNn0sv9SkZGntbLfW703tUi98a//lqflnHgJAabX0HDP+JYqAT/6Xi4pa7p6uitoG/Ha1XFJ7aWjPcVAgRYidenxDpkHtG+36ahsflrc+UFtSZjcBLd/6g3yFK5vfFuoHwLDadbgJ+StXyjT4dCb3lPc+ob68gZQj2fFbEZ64I0bSscYslNz293n0EnfyvxbfmoumEluiaM+5mxgWE2zQXrFFlmnGnuOgQIoQO5SnrhZdX82SH+SmJBjnCFSVBlrq/ACGicBiN14hWzOvYlhMMOfN/qtjlyWftyMpNqEHSItrqRd+woO84Sp5JiV08vEAwL8sUJAP/9C0UM8bcRwUSBFih45e4g6idPtNXF+tvcfJNTUdAM4WVSL+9Z0GicCT4rua5fxtb/bNshVdsC+9Q5Wynr/te2yQSM7brKGR2HbqKucQsZ+HC+9C02J8PYVvg+NuD+XdZ0zPG+n47DZ1cs6cOVAoFII/t25xj/+fPHkSU6ZMQefOneHh4YHu3btj4cKFuHnTsut9ESKdcOKtdn21tonfFTyznrT4EsbbHtc2wT0q2AdDorhvhEP+Px+Jb19qXDDnPq2vTxRyJgJvOl4oeJyQiQlCQZg8S7nYG7EhV6n43mOB3u4YGs39Phka3bKu3fqHBsGlTea4i5MCmx8ezPseU4kESpW1DUiKVHHuS4pUGRUYta0/RRyL3fdIJScno0ePHpz7nJ2dDbZ9++23SEtLQ2NjIxITE9G9e3ecOHECH3/8Mb755hscPHiQ93yE2AqxBVx/zr6OzIJyvW3GLF0htnyHUIK7gif+UCiABp4s7abmZtFcp5r6Js7tGp7t7dV2yFCuxXHtjXZI1dyE3mNCS7UAwNu/5KDt+sCMAW/9nMNbqV7p6YYynqVlAGB07xCM7hUi+LyECLH7QGrevHmYM2eOUY8tKirC7Nmz0djYiH//+9945JFHAABNTU2YM2cO1q9fjxkzZuDo0aNQ8N0VCLEB2h4grlln/cOUvMuYCC1dIZYwfqm4Bq98/3u7lv4AwJvLBQDH8suw4zd5lk4Rknm5DBEBXpy1gz5OS7B4e2zRrt9v6NZDNBex91ipph7r0pOw/7waWYVluuDWmGP55Ivk74UoPXRDdFzP62jMWZzVUdh9INUe77//PjQaDUaNGqULooCWnquVK1fihx9+wPHjx7Fz507cfffdVmwpIeL4Zp1NGxiGBZuyeI/LL+EOpMQSxn/NK+a9kYkt/SHkUrHlZ8iFKj0NgiigZcjwobXHLd4eW6Q2Q7J5W2LvseyiCt4CoXKttZd5uQx9uyptqpSINdhaORV7Yrc5UlJs3boVADBjxgyDfT4+Phg/fjwAYMuWLRZtFyFSaL9F730mFavnJmLvM6lYl56kKxfAh6++jXjCuDy9tEqRgp1yOFtUyVslu66xgxWLksjb3TA1wlRi77F1h/MtvtZeQoRKcLjRUdA1kM7ue6T27t2LM2fOoKqqCoGBgUhKSsLYsWPh7q6fKFlVVYULFy4AAAYOHMh5roEDB+LLL79EVha9cQg3W+z2Zm2TRiQSq4sjV+7Q7rPXZTmvkJwb/EuRkBbXyoWX7pGD0JD0lTLpPVK+7s6oqjPMqVN6uqCrv6fokLat/K3LxZhh/Y5+DUxh94HUunXrDLZ16dIFX3zxBcaMGaPblp+fr/t3REQE57nCw1vyAS5dumTeRhK7Z4vd3nxtmpoYJngc39AeIF6Rmi/QElsnTYhapqRmIXGdfXH4ovQ6VI5AjiIQpgzPiRXk9HZz5pyYoPR0RVxnXxzLN/x9x3X2E22T0N9LR0HXwDR2O7TXr18/fPDBB8jOzkZlZSVu3LiBnTt3YujQobh27RrGjx+Pffv26R5fVfVn0T9vb+43hI+PDwCgslLaDaGurg6VlZV6P6RjsMVu70fWneBcJ+0/GRcFjxNauoJvuFAbLPKtO/b4SOkzXduuyWYJs4Z2t/hz2psB3czfA2nK8FxljXDpDr7ZnRW1DZxBFNCyFI6zyNvPEZZ6Efu9OMI1MIXd9kgtWrRI7/++vr646667MGrUKEycOBHff/89nn76aZw6dcpibXrzzTfx2muvWez5iGXYYrd3nroax3hWnv/taiWcFUATR5eCdpFWMXwVqfkKEO7NkV6DrabB8jlJx0QKmhIgLMDT7OcUGj4W69UsMGFoT0gTg8Mv9ULL3ZjGbnuk+CgUCl0wc/r0aRQWthTt8/X9c7X3mhruVbmrq1tmD/n5CSfr8lm6dCkqKip0P9rnJvbNmG5vOWXk3MQHe87jQKtg7sffigSP4QqigJZFWrXn4TqvsdoWIPz9Cv8SG7aIq2wE0Xel1LgcqbbFWcX28fVq/n1iX8HnCZchsANaelv42uRIdaToGkhntz1SQm677Tbdv69cuYLw8HB069ZNt+3y5cvo29fwj1Yb+ERGRkp6Xnd3d4Mkd2L/rNXtXVBSw1nnaPuCFJTW1Es+77bMq3hyUxbnecMDpQ297D5nX6sC9AjysXYTbJ5YcrdQ3iADE8wp5OrVzBDp1QzyFv5s7dvVD2eLqgx6VOIj/EXLc1hzqRdbmcBCy91I1+F6pACgpOTPb5vanig/Pz9dxfITJ05wHqfdnpBABfnIn7Td3m1zeZwVCgz//1Xh5cBX52j8JwcxMq6T5PP++FsR53nv/fiA0ecw6GlQ2N76dK48s/eVnq7oHSbvOnIdgVhBSqG8wcfWZ3Lm781ff1L3/7a9mqeulAs+X65auN7YoyOiOXtU5g6NFDyudY+yJZd6MXY5Jkuj5W7ar0MGUps3bwbQEjzFxcXptk+cOBEAsHHjRoNjqqur8cMPPwAAJk2aZIFWEnti6W7vjJybvHWOyjQNyL4qfSitjmfcr6K2UXSYj+/D//7+/Au7WksDzwoyFbUNOGvC9XMU9/TtwrtPmzfY1Kb0hjZvkG/o9EheCecQIAD0D/MXbA/fOnxa4Sru3tQwG02ktsUJLEQauxzaO3XqFC5fvoyxY8fCxeXPl9Dc3IzVq1fj+eefBwA8+eSTcHX9c2r6008/jU8++QS7d+/GZ599hocffhhAyxIxjz/+OMrLy5GYmIjRo0db9gURmyd3t3fb7n2xb+frjuSb7blb23PuBobFBPMON/B9+BeUWL46uSnEcsyI8JR3U8oY/JpXwnneEXGd4OKkQCPHmnkuTgoMFJlFuGzHWc71JQHbSya3xQksRDq7DKTy8/MxceJEqFQqJCQkoHPnzigvL0d2djYuX74MAEhLS8Mrr7yid1xoaCjWrFmDtLQ0PPLII1i1ahUiIyNx/Phx5OXloXPnzti4cSOts0d48c1mk4ovz2R6knAtKLmqb5dWt/Q4ceW2lNTU8X74FxiZmGwr+Hr7yJ+EempMKWPA9+map67mDKIAoLGZ4dgl4bpfQsU8tz+RDACc9dGsgeo2dSx2GUj169cPTz/9NE6cOIE//vgDhw4dAmMMnTt3xl/+8hfMnTsXY8eO5Tx2ypQpiIqKwvLly3HgwAFkZWWhS5cuWLBgAV566SV07tzZwq+GODK+Hh4Agt/Ouyg9UF5r/l6gXeduoL5R/zm1ww1zUyLN/nzWEhXkjeuVli8Eai9cnBSCN3Kh6fIJ3fw5gxqtQVHcQ3RiwcXNqlsireZXUlNvU4nUVLepY7HLQKp79+547733JB8/YMAAfPfdd2ZsESHtJ3U1+8ZmhqpbjbK0qZajppO2PfOGRcrynNbg62GXH30W09jMcCBXLZhwLlQF/7ENJ3H4omGe1NDoQN4ARiy4CPb1MLL1hrSBibl7lKWiuk0dS4dMNifEHpiSZ8I3BCKnJgYM4elNEKsObWtMufaOIvOycSUDuKrgr3xgAIa3CcKGxwRj5QMDdP9vO/NTbHas2FqP8eH+nNuFgjdrorpNHQd9LSPESkzJM4m2wtBUcVUd+NIHvd1dUClTL5kc+oQq8cd1+0qQt7SECJVRj+Pq5RGanCFUf0rqWo/JPYJQW8/9/mswUz6hues9Ud2mjoMCKUKsRKh7P1zliXyBXpOcG1W8++Ry+GIJ53ANALsKogCgG92wBKm8XEXrSBmDK8gSmva/Lj1JMLjgC7QWj47F/Z8c4mzD8YIyk2bByb1gua0MNxLpaGiPECvi6953dREeKysWWcBVDjV2FiwJKa2uR+9QaUtBdTSqNsGAtsq9HMTqT2mH+fiKQvINJ569JrxA/K8mLAlE9Z6IGOqRIsRCuIYGtDeG/edvIquwHAkRKgyLCcag5bus3FpDYkuG2JPbuvhh9eF8azfD6tycFch6eTQO5KqReblM9/6Ti7mm/Rv24gjnDEpN4aN6T8QYFEgRYkZcwZKUNcnKrdDjJMbeAilfdxdU1Rn2ovl7uqKJyVOHy9509mtZv25YTLCsAZSWXNP+B3UXrnrOV3JBDNV7sn22sFYhBVKEmIFQsPTY+kyDJTO06465OjtxDhu0HfqwBUovV1TW8ay7YmP8PFywY+EwjP/kIOfizAcvFgsc7ThG9wqx6POZa9p/25tnVLAPhkYHtrvkghiq92S75M5daw/KkSLEDPgWaZ39xVHBdcf48kVskdi3fltSeasRpZp69O3qr7e9b1d/+Hm6IlQpvSZRRzJzSKTFn9OUaf9CC/0aU3Khvay1YDkRZ0u5awrGbPRTuwOorKyEUqlERUUF/PwosbWjylNX444VGdZuhuyGRAXgSJ7wMh22JDLQC4WltZw9H/f0DcHSLWes2Drr8/NwwW+v3m2155cy7X/WqmO8vVnr0pMkn1dIhabBYKagtXo+SAuxz9y9z6Sa/Ltvz/2bhvYIMdFRkTXAOorsqxXWbkK75JcY5rdok4Sjg6XX8OooKm81WjVZur3T/o1N/DZ3OQGq92R7bC13jYb2CDGR2oQ1wOLDlGZsibyq7CQ/yhhM8jyujiW/pMbaTTCaMTdPOfGVZCCWZ2u5axRI2am2yysQy8jIuYkP9pzHgVbfjMXWAIvm+eAdGh3IWyncFrl0oE+LO3rKP0PNHthTsrSt3TyJ9dha7hoN7dkZW5qp4EgKSmow4ZNDnDPAxNYAe25MHBZszNJbH8/FSYE5QyLxyPqTsrXZ3EKVHrhcJr33jVhH365+OFtURYvjkg5FaDkhS6NAys6ILa9A5HH/x4dQXqtf26lM04D7Pj6IU6+Mhq+HC6o4Kn/7ebhgyZYzBosMNzYzPPmVfVVGvmJHQVRsZx+cv8G/lt7WrCILtsa6JiWEQeWltokbjilsLS+GWJct5a5RIGVHqMqudWTk3DQIorTKaxvw9YnLnEEUILwG3a0G+yoKaU+tdXESHjPNL3acBYtr6hpt5oZjChraI1xsYa3CDpT10PFZO9nSUe3NuSm4f1vmVQu1hBjr7DXhRZ0dqeiL9qXae7K0sXkxlD9KLI16pOwIfSMzn/YsK6AQmeFV29BxZrM5ivgIFU5dsa9yDnx83J1RLTCjMtjH3YKtkZdQXgzljxJroUDKjphreQVHJuXDNjbER/Cc3YN8kFXYMW7KHQlfgKH0dMGDQ7p1mEWLpyeG4/OD+bz7pa4zZ4uE8mK0xTpbs4X8UVtYC47Ii4b27IwpyysQacsKiC2NMiG+q1naZuucrd0ADrGdvTmHehIjVby9NBW1jVAoFPBx535FPJttVoB3x+lxMlbbYUpt/ijXckva/FFLE1rOhnQs1CNlZ2xppoK9kZqsHxXsg8RIFY7nlxnsS4pUwVFWWbLFAcy7eoUgxK/SYKgnNS6Y8/el9eNvV3kDLXurO/rFoUuC+x1hNpstzuijGdaOgwIpO2ULMxVsGVd3urEftlzHujpzd966ODuJJqMT+eRer+b8YrHpWIHgcZfUwu8Fe1JTJ9zD4Qi5k5bIH23PEB3NsHYsFEiRDkUoB0psHPtWfRNmrTpmcOzi0bE4fLGE85jDF0ugcIwOKZtUU99SXqJtr2Co0lPwOH/PjpN8HOzjgcggH9HcyY6cqyNn/qiUvEpb7CEj8qFAinQoQt3pc1MiBY/9cE8uzl3Xnza/P1ctupZeTQN/rSgiL5WXK2fwOzUxTPC4mBBfuZtmMQMjA/DKfb0dfjabXJWupQzR0Qxrx0KBFOkwxLrT5w3rLnh82yBKbLuWEy2AazXnb1bh4k39b/+HLhSjViS4HRwViKHRgZw9jfHh/sgqLDdnM2U1JDrQLmezmZsc+aOm5FXSDGvHQbP2iE1rT3E9se70JsZ4C/rFdBIucSCkXFMv+VhimvM3ajhnagklmms9f09PgwroLk4K9O1qX71VTa2WH7KH2WxyM2fhUVOKINMMa8dBPVLEJkkZjjCmO52v+79vVz/k3pS2bIjSyxXgTqEiNiq/pAZPbszkXAPxy18LrdQqaYRS9ChXxzSmDNHRDGvHQYEUsUlS8hKM7U6XMstLiKebnRUeIrhZeQtVPHUO7G3uwGCBgpuUq2MacwzR0Qzrjo+G9ojVtR2+M2U4wtju9Lbd/6bkOZXV0NCenPh+M94ilTP7hPrxrsu26+wNM7XOMvx4XuuQqEDBm7Sx69MRfjRER8RQIEWMJnUxUL7j+Cr/niuqFDyfNi+B67xMYn/CdZGZeULCVMLf+olp7u7dCao2w7kqL1f8Z+YAweOWju0JP0/9Tnc/Txf8fUIf1NRZfqalswlzEtbPG4zhMcF624bHBONTkWsAUCBgKu0Q3d5nUrF6biL2PpOKdelJHWrGIzENDe0RUVKnT4sdxzd8p6kXvskFeLlxTnn/KC1ecjVhZxN6pCJEhk+Iaf52Ty90D/LGgVw1Mi+XISFChWExwchTC+e0vb8rF5W1+u+lytpGvLAtGxP6d8WRvFI5m22gk687rlXWSTrW11N6vo2puToduf5Ue9AQHeFDgRQRJTU4eWx9Jo7k6Wdh789VY/76k/j7xD6804pPFJQhMVKFzIJyzryEFTvPc7Zn3rrjnLO1uKYqt705NJmQGbPjt2uSjyUtfNycUF3fzLld+zsbFhOMYa16ZcQSqY8X8L8Xxt0eYmKL28/ZhC4pbVK4KTfz9h7rKPWnCDEVBVJEkNQ6KnnqaoMgSutIXgmOXRLuDZg9NBKerlcMZtctHh2L+z85xNkesSnv+SU1UP1/T1jbm8PIuGCBI4Vdr5LWy0D+xBVEabfzvcfEEqmFWCNHqk8XJa6USRtCtkZSOK0VR4hxKJAigqROnz4qEijdFAk+eocqsS491GA4wpR17VycFLw3h2sVtZLPS+TF9x4TmlGV0M1fMLAOVwkvISOHaYMi8LNAANcn1A/nrlXZRAFHWiuOEONRsjkRJH36tPBQWSdfd6NmE7WdXWdKL8S2rKu8swGl1pAipuslslyLUG8MXyL157MSBd9fDw6JlNxeIff368K5fdWsgaLv3aX38CfHW5ophSgdkdSJOKRjoECKCDJ2+nTbD5JB3flr2wDAoKhASbOJooJ9MDSa+9xtZ3a1JZacTKxjUFSg5Cn6QrM0hd5fUcE+SIpUcR7Xt6tfO1qv7+m74pD/1jjMS+mOniE+mJfSHflvjcOdvTqL/i39e/8l3uR4S6P6U8bhm3lcoWmwdtOIBSlY22XTidlUVlZCqVSioqICfn7SP5ytrULTYFANXJt0ysB4E1If23CScy2zodGB2PjwYN3/hWYTcc0YmvjJQWQVVhicN8jHFcXV/B9gUwaE4ZuTV4x/4cQivkxPwu1d/XnfY0KJzdp15LiGw7R5PHzvL6H39fB//g8VtYazR5WeLojr7ItjHMOGSZEqfD1/qOBr5XtOvtw/rb3PpFp8KM2Ya+vo6Bp1XO25f1OOFBEldUHUlQ8M4L1RtcY1m4hvxtDi0bGcQRQAwSAKAC7eoB4pWxSm8pJU/8vYPB6+2Wp87+s8dTVnEAUAFbWNeHFcL7yz87zo+5oL33OK5f5ZYykXvuWUqP5UC8ojI1oUSBGjtb0hiX2QlGrqJdev4UsKLzAhN+PcDeFCn8Q68ktq8Mr3+e2eIWaudeTavq/Fzltiwvua7znNNZRmzppPtFacMFrHkGhRIEWM1vZD2tgPErHR47bnFQrQxJ5TSF0D9xR7Yl3OCkj6Zi9XHo+x5zVngUZT13STs+YTFaLkRnlkRIsCKSKKf5gtRvA4oQrkSi9X3vNOTQwz/4sA4OGqgKaBUgKlCld5oFCgDlKvUD+c5VjeJyHcHz4errxBQpPIr0RK+QNTSgbIdV4xpgylUc0ny7PW+4TYHpq1R0TxfUiv2JkrOAuJrwL5wk1Zguddezjf/C8CwC0KokySltSNd6ZbUqQKm3jWg1s9N0lwBp0p3+zlWkfOGuvTSV3TzZRFvolpaB1DAlCPFBEhlge1IT0JZ66Wo6zVdF8/Txc8OjwKD6w6ynvc/vNq3vMezy9D/3B/nCosN9jvpACaJcZDNLBnmttC/fDAoG6Cs+uEcmr49im9XCV/s5crj8ea+UHtHUqjXB3roTwyAlAgRUSIfUi/+fMfnLVv3vzpnOBxWYXCy7nUNTRxbndxBkTWNCYyiQz0NurGIRQI8O0zdYaYXHk89pAfRLk61mcP7xMiHwqkiCCxD+nsq4Y5MU2MIZsjV6a1ED8Pwf3nrldxbqcgqoW3qxNqZEieN3aZEnPfOOibvXSUq0OIdTlsjtQ333yD1NRUqFQqeHt7o1+/fvjHP/6BhgaqSNuaUDXmPqHCRcr6dPXjzZ/qJBJIyaEjvdmnJ0XIct7lE/taNeej7ZJAxDiUq0OI9ThkZfOnn34aH3zwAVxcXHDHHXfAx8cH//vf/1BeXo6UlBTs3LkTnp6mL2ra0Subi1Vj3v5EMt75hbtwYUlNHe5YkSFru9tKjgrEoTzDSuu2KszfA1fKDWfJ3R7mh+1PDEPkkh2Sztunqx/OFXH3OolVAye2jX5vhJhHe+7fDhdIbdu2DRMnToSPjw8yMjKQkJAAACguLsYdd9yBM2fOYPHixXjnnXdMfq6OEkhpCVU2l3JTFjoWgKR9Jy+XoqbOML/K290Z/5qRgNmrj5vjUliEUCCq9HLF0YslmPbZrwbHLR3TE2/+/AfveT+dmYCNRwtlqTlECCEdAQVSApKSknD8+HEsW7YML7zwgt6+gwcPYtiwYXB3d8eNGzegVCpNeq6OFkhxEVqvTOymLHQsAEn7KmsbMP6Tg3qzCFVerti+IAUXiqsxV4ZAysUJaJSYrnRbF1+cu2aYD9Z6PUKxXoZ/7b2AA7lqDIsJxuMje2Bvzk3B17l6biJGxnWi3gtCCOFBgRSPq1evIiyspdhjXl4eunfvbvCYiIgIFBYWYuPGjUhLSzPp+RwhkNIy5aYsdKzUfQdy1ci8XIaECBWG/X9tozx1tSzDidFBXrhYLK3iulivkxRir9MaC+ASQog9oUWLeWRltRSCDAgI4AyiAGDgwIEoLCxEVlaWyYGUIzFlFpeU6fJi+4bFBOsCKC2x2U0A/5Bh21pZWiovV+x5ZqRgvpLQc94e5m/22Wo0i4sQQiynI01kEnXp0iUALb1OfMLDw/UeSzoWodlNQvu2L0iBqk0PkXbIEACeHR3L+XzPjo41akaVuWer0SwuQgixDIfqkaqqaslF8fbmv1n5+PgAaOnWa6+6ujrU1dXp/i/lHEReplTfznp5NOeQIQAsuCMGC+6IwV/+dQi/X6tE7y5++PbxZNHzWut1EkIIMQ+HCqTk9uabb+K1116zdjOIEcw5ZNha6+CpPeeVC1VcJoQQeTnU0J6vry8AoKaGfxHP6upqAJCUHL506VJUVFTofgoLC6U1lBBCCCF2waF6pCIjIwFAMMDR7tM+tj3c3d3h7u4upWmEEEIIsUMO1SMVH9+SaFtSUsKbTH7ixAkA0BXqJIQQQgjh41CBVFhYGBITEwEAGzduNNh/8OBBFBYWwt3dHWPHjrV08wghhBBiZxwqkAKA559/HgDw1ltvITMzU7e9pKQEjz/+OADgiSeeMLmqOSGEEEI6PoeqbK711FNP4cMPP4SrqyvuvPNOeHt7Y8+ePSgvL0dycjJ27dpFixYTQgghDoqWiDHC119/jU8++QSnTp1CQ0MDoqOjMXPmTCxatAhubm5meQ4KpAghhBD7Q4GUjaBAihBCCLE/7bl/O1yOFCGEEEKIuThUHSlL03b20VIxhBBCiP3Q3reNGbSjQEpG2rX9tAshE0IIIcR+VFVVic7ipxwpGTU3N6OoqAi+vr5QKBQG+ysrKxEeHo7CwkLKoeJB10gcXSNhdH3E0TUSR9dIXEe6RowxVFVVITQ0FE5OwllQ1CMlIycnJ4SFhYk+zs/Pz+7fdHKjaySOrpEwuj7i6BqJo2skrqNcI2PrSVKyOSGEEEKIRBRIEUIIIYRIRIGUFbm7u+OVV16Bu7u7tZtis+gaiaNrJIyujzi6RuLoGolz1GtEyeaEEEIIIRJRjxQhhBBCiEQUSBFCCCGESESBFCGEEEKIRBRIEUIIIYRIRIEUIYQQQohEFEgRQgghhEhEgRQhhBBCiEQUSBFCCCGESESBFCGEEEKIRBRIEUIIIYRIRIGUlXzzzTdITU2FSqWCt7c3+vXrh3/84x9oaGiwdtNkl5OTg48++ghz5sxB37594eLiAoVCgWXLlokeu3v3bowdOxZBQUHw9PREz5498cILL6C6utoCLbeMhoYG7NmzB88++ywSExPh7+8PV1dXhISEYPz48dixY4fg8Y5wjQBgw4YNmDVrFvr164dOnTrB1dUVSqUSSUlJePPNNwVfr6Nco7aee+45KBQK0b83R7k+c+bM0V0Pvp9bt25xHnvy5ElMmTIFnTt3hoeHB7p3746FCxfi5s2bFn4VllFfX48PP/wQKSkpCAgIgIeHB8LCwnDPPffgq6++4jzGUd5HYMTinnrqKQaAubi4sNGjR7NJkyYxf39/BoClpKQwjUZj7SbKSvv62/688cYbgse9++67DABTKBRs+PDhbMqUKSwkJIQBYHFxcUytVlvoFchr165dumsSEhLCxo0bx6ZOncr69Omj2/7II4+w5uZmg2Md5RoxxlhycjJTKBSsV69e7O6772ZpaWnsjjvuYJ6engwA69GjB7t69arBcY50jVo7dOgQc3JyYgqFQvDvzZGuz+zZsxkAlpyczGbPns35U19fb3DcN998w1xcXBgAlpiYyKZOncqioqIYANa5c2eWm5trhVcjn8LCQtarVy8GgAUFBbF7772XTZs2jQ0dOpR5eXmxyZMnGxzjSO8jCqQsbOvWrQwA8/HxYSdPntRtV6vVrG/fvgwAW7x4sRVbKL/PPvuMPfPMM2zDhg3s3Llz7MEHHxQNpDIzM5lCoWDOzs7sv//9r257TU0Nu/POOxkAzj9me7Rnzx42efJktn//foN9mzdvZs7OzgwAW7t2rd4+R7pGjDH266+/spKSEoPtxcXFLCUlhQFg06dP19vnaNdIq6amhsXExLCuXbuyCRMm8P69Odr10QZSq1evNvqYq1evMi8vLwaA/fvf/9Ztb2xsZDNnztQFV1xfdOyRRqNhPXv2ZADYq6++ahBY1tTUsKysLL1tjvY+okDKwhITExkAtmzZMoN9Bw4cYACYu7s7Ky8vt0LrrEP7YSYUSE2ZMoUBYPPmzTPYl5+fz5ycnBgAdu7cOTmbahPS09MZAHbnnXfqbadr9Kf9+/czACwgIEBvu6NeoyeffJIBYDt27BD8e3O06yMlkHr22WcZADZq1CiDfVVVVUypVDIA7OeffzZjS63npZde0vWCG8vR3keUI2VBV69exfHjxwEAM2bMMNifkpKC8PBw1NXV4b///a+lm2ez6uvrdXlBXNetW7duSE5OBgBs3brVom2zhvj4eABAYWGhbhtdI30uLi4AAHd3d902R71G+/btw0cffYRZs2Zh7NixvI9z1OvTXtrXznWNfHx8MH78eADAli1bLNouOTQ0NGDlypUAgGeffdaoYxzxfUSBlAVlZWUBAAICAtC9e3fOxwwcOFDvsQQ4f/48NBoNgD+vT1uOdN1yc3MBAF26dNFto2v0p6qqKrz66qsAoLupAY55jaqrq/HQQw+hc+fOeP/99wUf64jXR2vv3r1YvHgxHnnkESxduhRbt25FXV2dweOqqqpw4cIFAI5xjTIzM1FcXIzQ0FD06NEDZ86cwWuvvYZHH30US5YswY4dO9Dc3Kx3jCO+j1ys3QBHcunSJQBAREQE72PCw8P1Hkv+vBb+/v7w9fXlfIyjXLfr169jzZo1AIDJkyfrtjvyNdq5cyc2btyI5uZm3LhxA0eOHEFVVRXGjBmDt99+W/c4R7xGzzzzDC5duoStW7dCpVIJPtYRr4/WunXrDLZ16dIFX3zxBcaMGaPblp+fr/s33+d4R7pGv/32GwAgLCwMS5YswT/+8Q8wxnT73377bcTHx2Pbtm266+GI7yPqkbKgqqoqAIC3tzfvY3x8fAAAlZWVFmmTPaDr1qKxsREzZ85ERUUF+vbti0cffVS3z5Gv0dmzZ7F27Vp8+eWX2LlzJ6qqqjBjxgysWbMGSqVS9zhHu0Y7d+7Ev//9b0yfPh0TJkwQfbyjXR8A6NevHz744ANkZ2ejsrISN27cwM6dOzF06FBcu3YN48ePx759+3SP114jgP86daRrVFJSAqCl5+jtt9/G448/jpycHFRUVGDXrl2IjY1FVlYWxo0bpyvd44jvIwqkCLET8+fPx549exAYGIhvv/0Wbm5u1m6STXj66afBGEN9fT0uXLiAFStW4KeffkKvXr2wf/9+azfPKioqKpCeno7g4GB89NFH1m6OzVq0aBGefPJJ9O7dG76+vujUqRPuuusuHDx4EPfffz8aGhrw9NNPW7uZVqPtfWpoaEBaWho+/vhjxMbGws/PD6NGjcKuXbvg4eGB7OxsbN682cqttR4KpCxI281ZU1PD+xhtoTI/Pz+LtMke0HUDnnrqKaxatQoqlUr3TbA1ukaAq6sroqOj8de//hU//fQTysrKMHPmTNTW1gJwrGv09NNP48qVK/j4448RFBRk1DGOdH3EKBQKvPbaawCA06dP6yZ2tB6q4rtOHekatX69rXvAtSIiIjBu3DgALcU3Wx/jSO8jCqQsKDIyEoD+bKu2tPu0jyV/Xovy8nK9rvXWOvJ1W7x4MT788EP4+/tj586dull7rTn6NWpr0KBB6NWrFwoLC3HixAkAjnWNtm7dChcXF/zrX/9Camqq3s/PP/8MAFi1ahVSU1Mxffp0AI51fYxx22236f595coVAC0zzrQuX77MeVxHukZRUVGc/+Z6zLVr1wA45vuIAikL0t4AS0pKeJPstB/6CQkJFmuXrYuLi4OXlxeAP69PWx31uj333HN49913oVQqsXPnTt5ZMI58jfhoczS0S3Y42jVqbGxERkaGwc+NGzcAtCROZ2Rk4NdffwXgeNdHjDY/CPizl8XPzw89evQA4BjXKCEhAQqFAgBQXFzM+Rjtdm3ekyO+jyiQsqCwsDAkJiYCADZu3Giw/+DBgygsLIS7u7tgvRdH4+bmpus+5rpuBQUFOHz4MABg4sSJFm2bnJYsWYJ//vOfUCqV2LVrl+69w8VRrxGf4uJinD59GgB0w6COdI3Ky8vBWgouG/zMnj0bAPDGG2+AMaabieZI18cY2pwfPz8/xMXF6bZrXzvXNaqursYPP/wAAJg0aZIFWimvkJAQpKSkAPhz6K61hoYGZGRkAACSkpIAOOj7yFqVQB0V3xIxxcXFDrNETFvGVDY/efKkbsmBn376Sbe9oy458MILLzAAzN/fnx07dsyoYxzpGv3+++9s/fr1rLa21mBfTk4OS01NZQDY4MGD9fY50jXiI/T35kjXJysri33//fesoaFBb3tTUxP7/PPPmYeHBwPAXnzxRb39rZeI+c9//qPb3tjYqFvuqiMtEbN7924GgKlUKnbkyBHd9oaGBrZw4UIGgPn6+rLr16/r9jnS+4gxWiLGKrTLNbi6urIxY8awyZMn6xYtTk5O7vCLFp88eZINGjRI9xMUFMQAsLCwML3tRUVFese1XgQzNTWVTZ06lXXp0qXDLYL5/fff6xYnHjhwIO9iqlwBt6Nco7179zIAzNvbm6WkpLDp06ezSZMmsYEDB+qWn7jttttYQUGBwbGOco34iH1xcZTro/1Sq1Kp2J133slmzJjBxo4dyyIiInR/f2lpaQaBFmOMff3117o1LwcNGsSmTZvWoRctfuONNxgA5uLiwoYOHcomTZrEIiMjGQDm6enJfvzxR4NjHOV9xBgFUlbz1VdfseHDhzM/Pz/m6enJ+vTpw9566y1WV1dn7abJTnsTFPu5dOmSwbG7du1iY8aMYQEBAczd3Z3FxMSwpUuXssrKSsu/EJmsXr3aqOvTrVs3zuMd4RrdvHmT/f3vf2djxoxhkZGRzNvbm7m5ubGQkBB21113sZUrV7Jbt27xHu8I14iPMT3AjnB98vLy2NNPP81SUlJY165dmYeHB3N3d2cRERHsL3/5C9uxY4fg8SdOnGCTJk1iwcHBzM3NjXXr1o0tWLBAr2emI/nll1/YPffcwwICApirqysLDw9nc+bMEVwvzxHeR4wxpmCsVZlSQgghhBBiNEo2J4QQQgiRiAIpQgghhBCJKJAihBBCCJGIAilCCCGEEIkokCKEEEIIkYgCKUIIIYQQiSiQIoQQQgiRiAIpQgghhBCJKJAihNiUNWvWwN/f3+TzpKam4umnn9b9X6PRYPLkyfDz84NCoUB5ebnJz9EeCoUC27Zts+hz8nn11VfRv39/azeDkA6BAilCiEXMmTMHEyZMMNi+b98+vcBm2rRpOH/+vNmff+3atThw4AAOHz6Ma9euQalUmuW8kZGReP/9981yLjnYUgBHSEfkYu0GEEJIa56envD09DT7eS9evIjbbrsNffr0Mfu5CSGOi3qkCCE2pe3QnnYY6ssvv0RkZCSUSiWmT5+Oqqoq3WNqamowa9Ys+Pj4oEuXLlixYoXeOVNTU7FixQrs378fCoUCqampAICysjLMmjULKpUKXl5euOeee5Cbm6t37HfffYfevXvD3d0dkZGReudOTU1FQUEBFi1aBIVCAYVCYfTrLCwsxNSpU+Hv74+AgADcf//9yM/P1+3X9uC988476NKlCwIDA7FgwQI0NDToHnPt2jWMGzcOnp6e6N69OzZu3KjXQxYZGQkAmDhxIhQKhe7/WkLXlBBiHAqkCCE27+LFi9i2bRt+/PFH/Pjjj8jIyMBbb72l2//ss88iIyMD33//PXbu3Il9+/YhMzNTt3/Lli14+OGHMeT/2rmXkKj2OA7gX9MRR+cU2UOi1AHHxkctmlmI2YNQMSIZFFKpKEF0mYuaFkEPxqVEm1YRjBZCCBW4CCJfaEP4QsVgcMapFtoJUQbKheno7y4u9889dK8zd7op3vv9wIH5P8///18MP35z5hQXQ9d1vHjxAsDvwcro6Ci6urrw7t07iAjOnTungpWxsTHU1NSgrq4OU1NTuHfvHm7fvo22tjY176FDh+DxeKDrOnRdj2k/q6urqKiogKZpGBwchM/ng8ViwdmzZ7GysqL69fX1IRQKoa+vD+3t7Whra1P3BoArV67g8+fP6O/vx/Pnz/Ho0SPMz8+r9pGREQCA1+uFruuqHMuZElGMhIhoE1y9elUSExMlLS3NcKWkpAgACYfDIiLi9Xpl165datzdu3clNTVVvn79qurcbrcUFRWJiMi3b98kOTlZOjs7Vfvi4qKYzWZpbm5Wdc3NzXL69GlVDgQCAkB8Pp+qW1hYELPZrOa6ePGilJeXG/bhdruloKBAlbOzs+XBgwdR9w9AXr58KSIiT58+FbvdLuvr66r9+/fvYjab5fXr1+q8srOzJRKJqD4XLlyQ2tpaERHx+/0CQEZGRlR7MBgUAIb1/Pm+f4h2pkQUO2akiGjTnDlzBhMTE4br8ePHUcdZrVZomqbKBw4cUJmXUCiElZUVFBUVqfb09HTY7fYN5/T7/UhKSjKM27NnD+x2O/x+v+pTUlJiGFdSUoJgMIi1tbXoG/4bk5OTmJmZgaZpsFgssFgsSE9Px/LyMkKhkOpXWFiIxMTEv9z39PQ0kpKS4HA4VLvNZsPu3btjWsNGZ0pEsePD5kS0adLS0mCz2Qx1s7OzUceZTCZDOSEhAevr6//q2jbT0tISnE4nOjo6fmjbt2+f+vwr9/1fO1OircKMFBFtazk5OTCZTBgaGlJ14XA46isU8vPzEYlEDOMWFxcxPT2NgoIC1cfn8xnG+Xw+HD58WGWKkpOT/3F2yuFwIBgMYv/+/bDZbIYr1tcy2O12RCIRjI+Pq7qZmRmEw2FDP5PJ9FPZMyLaGAMpItrWLBYLGhoa4Ha70dvbi/fv36O+vh47dmz89ZabmwuXy4XGxka8ffsWk5OTuHz5Mg4ePAiXywUAuH79Onp6etDS0oJAIID29nY8fPgQN27cUPNYrVYMDAxgbm4OCwsLMa350qVL2Lt3L1wuFwYHB/Hx40f09/fj2rVrMWXoACAvLw9lZWVoamrC8PAwxsfH0dTUBLPZbPj3oNVqRU9PD758+fJDkEVEP4+BFBFte62trTh58iQqKytRVlaGEydOwOl0Rh3n9XrhdDpx/vx5FBcXQ0Tw6tUr9bOXw+FAZ2cnnj17hiNHjuDOnTvweDyor69Xc3g8Hnz69Ak5OTmGn+U2kpqaioGBAWRlZaG6uhr5+floaGjA8vIydu7cGfO+nzx5goyMDJw6dQpVVVVobGyEpmlISUlRfe7fv483b94gMzMTx44di3luIopNgojIVi+CiIh+3uzsLDIzM9Hd3Y3S0tKtXg7R/wIDKSKibaq3txdLS0s4evQodF3HzZs3MTc3h0Ag8MPD5ET0a/Bfe0RE29Tq6ipu3bqFDx8+QNM0HD9+HB0dHQyiiDYRM1JEREREceLD5kRERERxYiBFREREFCcGUkRERERxYiBFREREFCcGUkRERERxYiBFREREFCcGUkRERERxYiBFREREFCcGUkRERERx+g3K0pU0MzqouwAAAABJRU5ErkJggg==",
+ "text/plain": [
+ "