From 585ddc110a05fe512aaced76e5ffcd40c012af70 Mon Sep 17 00:00:00 2001 From: cmalzer <claudia.malzer@geo.uni-goettingen.de> Date: Wed, 4 Sep 2019 21:06:10 +0200 Subject: [PATCH] update --- Aufgabe/Geocoding.ipynb | 357 ++++++++++++ .../R\303\244umliche Verschneidung.ipynb" | 450 +++++++++++++++ Aufgabe/Versorgungsgrad berechnen.ipynb | 537 ++++++++++++++++++ ...en 1 - if-Anweisungen und Vergleiche.ipynb | 12 +- ... 2 - Schleifen, Listen, Dictionaries.ipynb | 64 +-- Tutorials/Grundlagen 3 - Funktionen.ipynb | 157 +++++ ...=> Grundlagen 4 - Pandas DataFrames.ipynb} | 241 +++++--- 7 files changed, 1693 insertions(+), 125 deletions(-) create mode 100644 Aufgabe/Geocoding.ipynb create mode 100644 "Aufgabe/R\303\244umliche Verschneidung.ipynb" create mode 100644 Aufgabe/Versorgungsgrad berechnen.ipynb create mode 100644 Tutorials/Grundlagen 3 - Funktionen.ipynb rename Tutorials/{Grundlagen 3 - Pandas DataFrames.ipynb => Grundlagen 4 - Pandas DataFrames.ipynb} (67%) diff --git a/Aufgabe/Geocoding.ipynb b/Aufgabe/Geocoding.ipynb new file mode 100644 index 0000000..68e4d22 --- /dev/null +++ b/Aufgabe/Geocoding.ipynb @@ -0,0 +1,357 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Geokodierung von Adressdaten" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Genau wie in der originalen Aufgabenstellung sollen zunächst die Adressdaten der Ärzte aus dem Excel-File <b>Ärztedaten_Hamburg.xls</b> (hier in Jupyter im Ordner <b>Daten</b> zu finden) mithilfe eines externen Adress-Geocoders gekodiert werden. Lesen Sie in der untenstehenden Code-Zelle nun die Datei als Excel-File ein. Als Orientierung kann das 3. Tutorial dienen. Lassen Sie sich die ersten paar Zeilen ausgeben." + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " ID Fachgebiet1 Adresse PLZ \\\n", + "0 2 Hals-Nasen-Ohrenheilkunde Waitzstr. 7 22607 \n", + "1 52 Hals-Nasen-Ohrenheilkunde Neuer Wall 43 20354 \n", + "2 102 Hals-Nasen-Ohrenheilkunde Möllner Landstr. 26 a 22111 \n", + "3 125 Hals-Nasen-Ohrenheilkunde Wandsbeker Marktstr. 73 22041 \n", + "4 148 Hals-Nasen-Ohrenheilkunde Sand 35 21073 \n", + ".. ... ... ... ... \n", + "131 3947 Hals-Nasen-Ohrenheilkunde Tangstedter Landstr. 77 22415 \n", + "132 3971 Hals-Nasen-Ohrenheilkunde Spitalerstr. 32 20095 \n", + "133 4030 Hals-Nasen-Ohrenheilkunde Erdkampsweg 55 22335 \n", + "134 4042 Hals-Nasen-Ohrenheilkunde Bismarckstr. 115 20253 \n", + "135 4057 Hals-Nasen-Ohrenheilkunde Wandsbeker Marktstr. 8 22041 \n", + "\n", + " Privatarzt Stadt Land \n", + "0 NaN Hamburg Germany \n", + "1 NaN Hamburg Germany \n", + "2 NaN Hamburg Germany \n", + "3 NaN Hamburg Germany \n", + "4 NaN Hamburg Germany \n", + ".. ... ... ... \n", + "131 NaN Hamburg Germany \n", + "132 NaN Hamburg Germany \n", + "133 NaN Hamburg Germany \n", + "134 NaN Hamburg Germany \n", + "135 NaN Hamburg Germany \n", + "\n", + "[136 rows x 7 columns]\n" + ] + } + ], + "source": [ + "import pandas as pd\n", + "aerzte = pd.read_excel(open(\"../Daten/Ärztedaten_Hamburg.xls\",'rb'), sheet_name='HNO')\n", + "print(aerzte)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Filtern Sie nun alle Privatärzte aus der Ärzte-Tabelle raus. Selektieren Sie dazu alle Ärzte, die keine Privatärzte sind, und überschreiben Sie den bisherigen DataFrame mit dem neuen Ergebnis. Um herauszufinden, wie Privatärzte gekennzeichnet sind, ist es ggf. nötig, sich die komplette Excel-Tabelle nochmal genauer anzusehen." + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [], + "source": [ + " aerzte = aerzte[aerzte.Privatarzt != 'P']" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " NAME Einwohner geometry\n", + "0 Barmbek-Süd 31360 POLYGON ((568738.5000999998 5936170.3463, 5687...\n", + "1 Duvenstedt 6220 POLYGON ((574154.1001000004 5950369.9463, 5740...\n", + "2 Rissen 14763 POLYGON ((552240.9001000002 5939762.5463, 5522...\n", + "3 Blankenese 12807 POLYGON ((551279.1001000004 5934212.5463, 5507...\n", + "4 Volksdorf 19989 POLYGON ((578633.7001 5943958.3463, 578496.300...\n", + ".. ... ... ...\n", + "95 St. Georg 10279 POLYGON ((568009.5000999998 5934687.146299999,...\n", + "96 Hohenfelde 8904 POLYGON ((566795.1001000004 5935675.9463, 5669...\n", + "97 Altona-Nord 33052 POLYGON ((563605.9812000003 5935419.763699999,...\n", + "98 Sternschanze 7723 POLYGON ((564561.5401999997 5935584.9878, 5644...\n", + "99 Hafen-City 1097 POLYGON ((566813.6781000001 5933346.6083, 5669...\n", + "\n", + "[100 rows x 3 columns]\n" + ] + } + ], + "source": [ + "selected_cols = ['NAME', 'Einwohner', 'geometry']\n", + "stadtteile = stadtteile[selected_cols]\n", + "print(stadtteile)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Die Adressen in der Ärztetabelle sollen nun geokodiert werden, denn wir brauchen die Koordinaten, um sie später als Punkte auf der Karte darzustellen sowie räumliche Verschneidungen durchzuführen. Lassen Sie sich zur Übersicht erstmal die Datentypen der Spalten in der Ärztetabelle anzeigen." + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "ID int64\n", + "Fachgebiet1 object\n", + "Adresse object\n", + "PLZ int64\n", + "Privatarzt object\n", + "Stadt object\n", + "Land object\n", + "dtype: object\n" + ] + } + ], + "source": [ + "print(aerzte.dtypes)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Geokodiert werden kann nur ein einziges Feld, in dem die komplette Adresse steht. Die einzelnen Bestandteile der Adresse werden kommagetrennt. Wir brauchen also eine neue Spalte, die sich aus den Werten der Spalten \"Adresse\", \"PLZ\", \"Stadt\" und \"Land\" zusammensetzt. Das bedeutet, dass 4 Strings miteinander verknüpft werden müssen. Da die Ausgabe der Datentypen aber ergeben hat, dass \"PLZ\" als Zahl gespeichert wird, ändern Sie die komplette Spalte zunächst in den Typ \"String\" um:" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [], + "source": [ + "aerzte['PLZ'] = aerzte['PLZ'].astype(str)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Legen Sie nun eine neue Spalte \"Adresse_kombiniert\" an. Hinweis: Dies kann in einer Zeile Code erfolgen, es ist keine Schleife nötig! Die neue Spalte soll einen kommagetrennten String aus Teilstrings von \"Adresse\", \"PLZ\", \"Stadt\" und \"Land\" enthalten. Lassen Sie sich diese Spalte ausgeben." + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 Waitzstr. 7,22607,Hamburg,Germany\n", + "1 Neuer Wall 43,20354,Hamburg,Germany\n", + "2 Möllner Landstr. 26 a,22111,Hamburg,Germany\n", + "3 Wandsbeker Marktstr. 73,22041,Hamburg,Germany\n", + "4 Sand 35,21073,Hamburg,Germany\n", + " ... \n", + "131 Tangstedter Landstr. 77,22415,Hamburg,Germany\n", + "132 Spitalerstr. 32,20095,Hamburg,Germany\n", + "133 Erdkampsweg 55,22335,Hamburg,Germany\n", + "134 Bismarckstr. 115,20253,Hamburg,Germany\n", + "135 Wandsbeker Marktstr. 8,22041,Hamburg,Germany\n", + "Name: Adresse_kombiniert, Length: 120, dtype: object\n" + ] + } + ], + "source": [ + "aerzte[\"Adresse_kombiniert\"] = aerzte[\"Adresse\"] + \",\" + aerzte[\"PLZ\"] + \",\" + aerzte[\"Stadt\"] + \",\" + aerzte[\"Land\"]\n", + "print(aerzte['Adresse_kombiniert'])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Als nächstes können wir diese Spalte geokodieren. Die GIS-Bibliothek <b>geopy</b> unterstützt eine Vielzahl an Geocodern, unter anderem auch den Esri-Geocoder. Zur API-Referenz siehe hier: https://geopy.readthedocs.io/en/stable/#module-geopy.geocoders \n", + "\n", + "Da wir einen offenen Geocoder verwenden wollen, wählen wir für diese Aufgabe <b>Nominatim</b>, der seine Daten aus OpenStreetMap bezieht. Es ist möglich, mit wenigen Zeilen Code ein komplettes Pandas-DataFrame zu geokodieren. Informationen Sie sich hierzu unter https://geopy.readthedocs.io/en/stable/#usage-with-pandas. (Die Verwendung des <i>RateLimiters</i> ist optional.) Geokodieren Sie nun also die Spalte \"Adresse_kombiniert\" in eine neue Spalte namens \"Geocoded\", und vergessen Sie vorher nicht den Nominatim-Geocoder korrekt einzubinden. Lassen Sie sich danach die neue Spalte ausgeben. Der Geokodierungsprozess wird ca. eine Minute dauern, erst dann wird das Ergebnis angezeigt.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " ID Fachgebiet1 Adresse PLZ \\\n", + "0 2 Hals-Nasen-Ohrenheilkunde Waitzstr. 7 22607 \n", + "1 52 Hals-Nasen-Ohrenheilkunde Neuer Wall 43 20354 \n", + "2 102 Hals-Nasen-Ohrenheilkunde Möllner Landstr. 26 a 22111 \n", + "3 125 Hals-Nasen-Ohrenheilkunde Wandsbeker Marktstr. 73 22041 \n", + "4 148 Hals-Nasen-Ohrenheilkunde Sand 35 21073 \n", + ".. ... ... ... ... \n", + "131 3947 Hals-Nasen-Ohrenheilkunde Tangstedter Landstr. 77 22415 \n", + "132 3971 Hals-Nasen-Ohrenheilkunde Spitalerstr. 32 20095 \n", + "133 4030 Hals-Nasen-Ohrenheilkunde Erdkampsweg 55 22335 \n", + "134 4042 Hals-Nasen-Ohrenheilkunde Bismarckstr. 115 20253 \n", + "135 4057 Hals-Nasen-Ohrenheilkunde Wandsbeker Marktstr. 8 22041 \n", + "\n", + " Privatarzt Stadt Land \\\n", + "0 NaN Hamburg Germany \n", + "1 NaN Hamburg Germany \n", + "2 NaN Hamburg Germany \n", + "3 NaN Hamburg Germany \n", + "4 NaN Hamburg Germany \n", + ".. ... ... ... \n", + "131 NaN Hamburg Germany \n", + "132 NaN Hamburg Germany \n", + "133 NaN Hamburg Germany \n", + "134 NaN Hamburg Germany \n", + "135 NaN Hamburg Germany \n", + "\n", + " Adresse_kombiniert \\\n", + "0 Waitzstr. 7,22607,Hamburg,Germany \n", + "1 Neuer Wall 43,20354,Hamburg,Germany \n", + "2 Möllner Landstr. 26 a,22111,Hamburg,Germany \n", + "3 Wandsbeker Marktstr. 73,22041,Hamburg,Germany \n", + "4 Sand 35,21073,Hamburg,Germany \n", + ".. ... \n", + "131 Tangstedter Landstr. 77,22415,Hamburg,Germany \n", + "132 Spitalerstr. 32,20095,Hamburg,Germany \n", + "133 Erdkampsweg 55,22335,Hamburg,Germany \n", + "134 Bismarckstr. 115,20253,Hamburg,Germany \n", + "135 Wandsbeker Marktstr. 8,22041,Hamburg,Germany \n", + "\n", + " Geocoded \n", + "0 (Änderungsschneiderei, 7, Waitzstraße, Groß Fl... \n", + "1 (van Laack, 43, Neuer Wall, Neustadt, Hamburg-... \n", + "2 (Möllner Landstraße, Billstedt, Hamburg-Mitte,... \n", + "3 (Adler-Apotheke, 73, Wandsbeker Marktstraße, W... \n", + "4 (Damian Apotheke, 35, Sand, Harburg, Hamburg, ... \n", + ".. ... \n", + "131 (Ärztehaus Langenhorn, 77, Tangstedter Landstr... \n", + "132 (Praxis Forster & Team, 32, Spitalerstraße, Al... \n", + "133 (55, Erdkampsweg, Fuhlsbüttel, Hamburg-Nord, H... \n", + "134 (Fachärzte für HNO, 115, Bismarckstraße, Hohel... \n", + "135 (First Cut, 8, Wandsbeker Marktstraße, Marient... \n", + "\n", + "[120 rows x 9 columns]\n" + ] + } + ], + "source": [ + "from geopy.geocoders import Nominatim \n", + "nom = Nominatim(user_agent=\"unigoe1\")\n", + "aerzte[\"Geocoded\"] = aerzte[\"Adresse_kombiniert\"].apply(nom.geocode)\n", + "print(aerzte['Geocoded'])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Um aus dem Ergebnis Längen-und Breitengrad zu extrahieren und in neuen Spalten zu speichern, gibt es eine Syntax, die Ihnen im Folgenden vorgegeben wird, da sogenannte <i>lambda-Funktionen</i> noch nicht behandelt wurden. Sie müssen in der folgenden Code-Zelle ggf. nur noch den Namen Ihres DataFrames entsprechend anpassen. " + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " ID Fachgebiet1 Adresse PLZ Privatarzt \\\n", + "0 2 Hals-Nasen-Ohrenheilkunde Waitzstr. 7 22607 NaN \n", + "1 52 Hals-Nasen-Ohrenheilkunde Neuer Wall 43 20354 NaN \n", + "2 102 Hals-Nasen-Ohrenheilkunde Möllner Landstr. 26 a 22111 NaN \n", + "3 125 Hals-Nasen-Ohrenheilkunde Wandsbeker Marktstr. 73 22041 NaN \n", + "4 148 Hals-Nasen-Ohrenheilkunde Sand 35 21073 NaN \n", + "\n", + " Stadt Land Adresse_kombiniert \\\n", + "0 Hamburg Germany Waitzstr. 7,22607,Hamburg,Germany \n", + "1 Hamburg Germany Neuer Wall 43,20354,Hamburg,Germany \n", + "2 Hamburg Germany Möllner Landstr. 26 a,22111,Hamburg,Germany \n", + "3 Hamburg Germany Wandsbeker Marktstr. 73,22041,Hamburg,Germany \n", + "4 Hamburg Germany Sand 35,21073,Hamburg,Germany \n", + "\n", + " Geocoded latitude longitude \n", + "0 (Änderungsschneiderei, 7, Waitzstraße, Groß Fl... 53.559497 9.885421 \n", + "1 (van Laack, 43, Neuer Wall, Neustadt, Hamburg-... 53.551104 9.989545 \n", + "2 (Möllner Landstraße, Billstedt, Hamburg-Mitte,... 53.539653 10.103738 \n", + "3 (Adler-Apotheke, 73, Wandsbeker Marktstraße, W... 53.572075 10.066240 \n", + "4 (Damian Apotheke, 35, Sand, Harburg, Hamburg, ... 53.461323 9.979341 \n" + ] + } + ], + "source": [ + "aerzte[\"latitude\"]=aerzte[\"Geocoded\"].apply(lambda x: x.latitude if x != None else None)\n", + "aerzte[\"longitude\"]=aerzte[\"Geocoded\"].apply(lambda x: x.longitude if x != None else None)\n", + "print(aerzte.head())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Die ausgegebene Tabelle sollte nun die Arztdaten zusammen mit den neuen Feldern \"Geocoded\", \"latitude\" und \"longitude\" enthalten. Speichern Sie das Ergebnis nun unbedingt im Ordner \"Daten\" ab, damit Sie später den Geokodierungsprozess nicht neu durchführen müssen, sondern einfach das fertige Teilergebnis einlesen können. Verwenden Sie hierfür einfach die <b>to_csv</b>-Funktion; ein Abspeichern im Excel-Format ist nicht nötig." + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": {}, + "outputs": [], + "source": [ + "aerzte.to_csv(\"../Daten/geocoded.csv\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.7" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git "a/Aufgabe/R\303\244umliche Verschneidung.ipynb" "b/Aufgabe/R\303\244umliche Verschneidung.ipynb" new file mode 100644 index 0000000..09e83f1 --- /dev/null +++ "b/Aufgabe/R\303\244umliche Verschneidung.ipynb" @@ -0,0 +1,450 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Räumliche Verschneidung" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Um dort zu starten, wo im letzten Arbeitsschritt aufgehört wurde, lesen Sie zunächst Ihre <b>geokodierte</b> Ärzte-Tabelle in ein DataFrame namens <b>\"aerzte\"</b> ein. Da diese im CSV-Format gespeichert wurde, kann die Pandas-Funktion <b>read_csv</b> verwendet werden. Vergessen Sie nicht, Pandas vorher wieder einzubinden." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " Unnamed: 0 ID Fachgebiet1 Adresse PLZ \\\n", + "0 0 2 Hals-Nasen-Ohrenheilkunde Waitzstr. 7 22607 \n", + "1 1 52 Hals-Nasen-Ohrenheilkunde Neuer Wall 43 20354 \n", + "2 2 102 Hals-Nasen-Ohrenheilkunde Möllner Landstr. 26 a 22111 \n", + "3 3 125 Hals-Nasen-Ohrenheilkunde Wandsbeker Marktstr. 73 22041 \n", + "4 4 148 Hals-Nasen-Ohrenheilkunde Sand 35 21073 \n", + "\n", + " Privatarzt Stadt Land \\\n", + "0 NaN Hamburg Germany \n", + "1 NaN Hamburg Germany \n", + "2 NaN Hamburg Germany \n", + "3 NaN Hamburg Germany \n", + "4 NaN Hamburg Germany \n", + "\n", + " Adresse_kombiniert \\\n", + "0 Waitzstr. 7,22607,Hamburg,Germany \n", + "1 Neuer Wall 43,20354,Hamburg,Germany \n", + "2 Möllner Landstr. 26 a,22111,Hamburg,Germany \n", + "3 Wandsbeker Marktstr. 73,22041,Hamburg,Germany \n", + "4 Sand 35,21073,Hamburg,Germany \n", + "\n", + " Geocoded latitude longitude \n", + "0 Änderungsschneiderei, 7, Waitzstraße, Groß Flo... 53.559497 9.885421 \n", + "1 van Laack, 43, Neuer Wall, Neustadt, Hamburg-M... 53.551104 9.989545 \n", + "2 Möllner Landstraße, Billstedt, Hamburg-Mitte, ... 53.539653 10.103738 \n", + "3 Adler-Apotheke, 73, Wandsbeker Marktstraße, Wa... 53.572075 10.066240 \n", + "4 Damian Apotheke, 35, Sand, Harburg, Hamburg, 2... 53.461323 9.979341 \n" + ] + } + ], + "source": [ + "import pandas as pd\n", + "aerzte = pd.DataFrame(pd.read_csv(\"../Daten/geocoded.csv\", sep=',', encoding = \"utf-8\"))\n", + "print(aerzte.head())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Lesen Sie nun auch das Shapefile <b>shapefile.shp</b> mit Stadtteilinformationen ein, das im gleichen Ordner zu finden ist. Nennen Sie Ihre Variable <b>stadtteile</b> und lassen Sie sich die ersten paar Zeilen ausgeben. Beachten Sie zur Lösung dieser Aufgabe folgende Hinweise:\n", + "- Die Bibliothek <b>Geopandas</b> (eine Erweiterung von Pandas um räumliche Funktionen) bietet die Funktion <b>read_file</b> an, mit der man Shapefiles einlesen kann\n", + "- Die eingelesenen Daten werden in ein <b>GeoDataframe</b> geschrieben, das genauso behandelt werden kann wie ein normales DataFrame, aber noch zusätzliche Funktionen unterstützt\n", + "- Mehr Infos zu Einlesen und Abspeichern von Dateien mit Geopandas hier: http://geopandas.org/io.html" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " OBJECTID NAME code Shape_Leng xlsID Bezirk Einwohner \\\n", + "0 1 Barmbek-Süd 3 7442.385726 49 Hamburg-Nord 31360 \n", + "1 3 Duvenstedt 0 13986.241699 68 Wandsbek 6220 \n", + "2 7 Rissen 0 26714.578295 32 Altona 14763 \n", + "3 8 Blankenese 0 13233.990172 29 Altona 12807 \n", + "4 10 Volksdorf 0 17677.783156 71 Wandsbek 19989 \n", + "\n", + " Einw_u18 Anteil_u18 ü65 ... Gewaltdeli Gew_Dichte Diebstahl \\\n", + "0 2895 9.2 5099 ... 65 2 1654 \n", + "1 1573 25.3 1103 ... 6 1 137 \n", + "2 2542 17.2 4398 ... 19 1 439 \n", + "3 2243 17.5 3541 ... 28 2 472 \n", + "4 4100 20.5 5038 ... 35 2 572 \n", + "\n", + " Die_Dichte Shape_Le_1 Shape_Area OBJECTID_1 FREQUENCY NAME_1 \\\n", + "0 53 7442.385726 3121774.74 3 1 Barmbek-Süd \n", + "1 22 13986.241699 6700717.44 8 1 Duvenstedt \n", + "2 30 26714.578295 16812700.56 33 1 Rissen \n", + "3 37 13233.990172 7839792.18 6 3 Blankenese \n", + "4 29 17677.783156 11311905.78 39 2 Volksdorf \n", + "\n", + " geometry \n", + "0 POLYGON ((568738.5000999998 5936170.3463, 5687... \n", + "1 POLYGON ((574154.1001000004 5950369.9463, 5740... \n", + "2 POLYGON ((552240.9001000002 5939762.5463, 5522... \n", + "3 POLYGON ((551279.1001000004 5934212.5463, 5507... \n", + "4 POLYGON ((578633.7001 5943958.3463, 578496.300... \n", + "\n", + "[5 rows x 88 columns]\n" + ] + } + ], + "source": [ + "import geopandas as gp\n", + "stadtteile = gp.read_file(\"../Daten/shapefile.shp\")\n", + "print(stadtteile.head())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Filtern Sie jetzt das Stadtteil-GeoDataframe so, dass nur noch die drei Spalten \"NAME\", \"Einwohner\" und \"geometry\" übrig bleiben. Lassen Sie sich das Ergebnis ausgeben und <b>speichern</b> Sie es anschließend mithilfe der <b>to_file</b>-Funktion (driver = 'ESRI_Shapefile') unter dem Namen <b>\"stadtteile_gefiltert.shp\"</b> im Daten-Ordner." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " NAME Einwohner geometry\n", + "0 Barmbek-Süd 31360 POLYGON ((568738.5000999998 5936170.3463, 5687...\n", + "1 Duvenstedt 6220 POLYGON ((574154.1001000004 5950369.9463, 5740...\n", + "2 Rissen 14763 POLYGON ((552240.9001000002 5939762.5463, 5522...\n", + "3 Blankenese 12807 POLYGON ((551279.1001000004 5934212.5463, 5507...\n", + "4 Volksdorf 19989 POLYGON ((578633.7001 5943958.3463, 578496.300...\n", + ".. ... ... ...\n", + "95 St. Georg 10279 POLYGON ((568009.5000999998 5934687.146299999,...\n", + "96 Hohenfelde 8904 POLYGON ((566795.1001000004 5935675.9463, 5669...\n", + "97 Altona-Nord 33052 POLYGON ((563605.9812000003 5935419.763699999,...\n", + "98 Sternschanze 7723 POLYGON ((564561.5401999997 5935584.9878, 5644...\n", + "99 Hafen-City 1097 POLYGON ((566813.6781000001 5933346.6083, 5669...\n", + "\n", + "[100 rows x 3 columns]\n" + ] + } + ], + "source": [ + "selected_cols = ['NAME', 'Einwohner', 'geometry']\n", + "stadtteile = stadtteile[selected_cols]\n", + "print(stadtteile)\n", + "stadtteile.to_file(driver='ESRI Shapefile', filename='../Daten/stadtteile_gefiltert.shp')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Da wir räumliche Funktionen ausführen wollen, die das normale DataFrame nicht unterstützt, müssen wir nun auch unsere Ärzte-Tabelle in ein GeoDataframe umwandeln. Der Unterschied besteht hier nur darin, dass das GeoDataframe eine Spalte namens \"geometry\" besitzt (wie im Stadtteil-GeoDataframe zu sehen), in der die räumlichen Geometrien in einem bestimmten Format gespeichert werden. Zusätzlich kann ein Koordinatensystem angegeben werden, das wir fürs Erste auf das geographische Koordinatensystem WGS1984 mit dem Code <i>epsg:4325</i> setzen.\n", + "\n", + "Die Erstellung der Geometrie wird im Folgenden aufgrund der noch nicht behandelten Syntax vorgeben. Beachten Sie, dass wir mit <b>Point()</b> eine Datenstruktur aus der externen Bibliothek <b>shapely</b> importieren, die GeoPandas wiederum für das Speichern seiner Geometrien verwendet. " + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "from shapely.geometry import Point #dieses Format kann von einem GeoDataframe verstanden werden\n", + "geometry = [Point(xy) for xy in zip(aerzte[\"longitude\"], aerzte[\"latitude\"])] #erstelle Punktgeometrie aus Koordinaten\n", + "crs = {'init' :'epsg:4326'} #erstmal verwenden wir WGS1984 als Koordinatensystem" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Legen Sie auf Basis dieser Vorarbeit nun ein GeodataFrame namens <b>aerzteGDF</b> an. Zur Syntax siehe hier: http://geopandas.org/reference/geopandas.GeoDataFrame.html. Die eben erstellten Variablen <i>geometry</i> und <i>crs</i> müssen also nur noch hinter den gleichnamigen Parameternamen (<i>crs=...</i>) eingesetzt werden; als Ausgangs-DataFrame dient das DataFrame <i>aerzte</i>." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " Unnamed: 0 ID Fachgebiet1 Adresse \\\n", + "0 0 2 Hals-Nasen-Ohrenheilkunde Waitzstr. 7 \n", + "1 1 52 Hals-Nasen-Ohrenheilkunde Neuer Wall 43 \n", + "2 2 102 Hals-Nasen-Ohrenheilkunde Möllner Landstr. 26 a \n", + "3 3 125 Hals-Nasen-Ohrenheilkunde Wandsbeker Marktstr. 73 \n", + "4 4 148 Hals-Nasen-Ohrenheilkunde Sand 35 \n", + ".. ... ... ... ... \n", + "115 131 3947 Hals-Nasen-Ohrenheilkunde Tangstedter Landstr. 77 \n", + "116 132 3971 Hals-Nasen-Ohrenheilkunde Spitalerstr. 32 \n", + "117 133 4030 Hals-Nasen-Ohrenheilkunde Erdkampsweg 55 \n", + "118 134 4042 Hals-Nasen-Ohrenheilkunde Bismarckstr. 115 \n", + "119 135 4057 Hals-Nasen-Ohrenheilkunde Wandsbeker Marktstr. 8 \n", + "\n", + " PLZ Privatarzt Stadt Land \\\n", + "0 22607 NaN Hamburg Germany \n", + "1 20354 NaN Hamburg Germany \n", + "2 22111 NaN Hamburg Germany \n", + "3 22041 NaN Hamburg Germany \n", + "4 21073 NaN Hamburg Germany \n", + ".. ... ... ... ... \n", + "115 22415 NaN Hamburg Germany \n", + "116 20095 NaN Hamburg Germany \n", + "117 22335 NaN Hamburg Germany \n", + "118 20253 NaN Hamburg Germany \n", + "119 22041 NaN Hamburg Germany \n", + "\n", + " Adresse_kombiniert \\\n", + "0 Waitzstr. 7,22607,Hamburg,Germany \n", + "1 Neuer Wall 43,20354,Hamburg,Germany \n", + "2 Möllner Landstr. 26 a,22111,Hamburg,Germany \n", + "3 Wandsbeker Marktstr. 73,22041,Hamburg,Germany \n", + "4 Sand 35,21073,Hamburg,Germany \n", + ".. ... \n", + "115 Tangstedter Landstr. 77,22415,Hamburg,Germany \n", + "116 Spitalerstr. 32,20095,Hamburg,Germany \n", + "117 Erdkampsweg 55,22335,Hamburg,Germany \n", + "118 Bismarckstr. 115,20253,Hamburg,Germany \n", + "119 Wandsbeker Marktstr. 8,22041,Hamburg,Germany \n", + "\n", + " Geocoded latitude longitude \\\n", + "0 Änderungsschneiderei, 7, Waitzstraße, Groß Flo... 53.559497 9.885421 \n", + "1 van Laack, 43, Neuer Wall, Neustadt, Hamburg-M... 53.551104 9.989545 \n", + "2 Möllner Landstraße, Billstedt, Hamburg-Mitte, ... 53.539653 10.103738 \n", + "3 Adler-Apotheke, 73, Wandsbeker Marktstraße, Wa... 53.572075 10.066240 \n", + "4 Damian Apotheke, 35, Sand, Harburg, Hamburg, 2... 53.461323 9.979341 \n", + ".. ... ... ... \n", + "115 Ärztehaus Langenhorn, 77, Tangstedter Landstra... 53.651396 10.017983 \n", + "116 Praxis Forster & Team, 32, Spitalerstraße, Alt... 53.551292 10.000149 \n", + "117 55, Erdkampsweg, Fuhlsbüttel, Hamburg-Nord, Ha... 53.629615 10.022251 \n", + "118 Fachärzte für HNO, 115, Bismarckstraße, Hohelu... 53.577285 9.971537 \n", + "119 First Cut, 8, Wandsbeker Marktstraße, Marienth... 53.570492 10.061576 \n", + "\n", + " geometry \n", + "0 POINT (9.8854209 53.5594975) \n", + "1 POINT (9.989545 53.5511039) \n", + "2 POINT (10.1037383 53.5396527) \n", + "3 POINT (10.0662405 53.572075) \n", + "4 POINT (9.9793412 53.4613231) \n", + ".. ... \n", + "115 POINT (10.0179825746869 53.65139605) \n", + "116 POINT (10.0001492 53.5512924) \n", + "117 POINT (10.0222513142276 53.62961545) \n", + "118 POINT (9.9715366 53.57728520000001) \n", + "119 POINT (10.0615756 53.570492) \n", + "\n", + "[120 rows x 13 columns]\n" + ] + } + ], + "source": [ + "aerzteGDF = gp.GeoDataFrame(aerzte,crs=crs,geometry=geometry)\n", + "print(aerzteGDF)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Um eine räumliche Verschneidung zwischen zwei räumlichen Objekten durchzuführen, müssen jedoch beide im gleichen Koordinatensystem liegen. Überprüfen Sie zunächst, in welchem Koordinatensystem die Stadtteile liegen. Auf diese Information greifen Sie mithilfe von <b>stadtteile.crs</b> zu. Lassen Sie sich dieses ausgeben:" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'init': 'epsg:32632'}\n" + ] + } + ], + "source": [ + "print(stadtteile.crs)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Wir könnten nun entweder dieses Koordinatensystem in das der Ärztedaten umwandeln, oder umgekehrt. In unserem Fall wollen wir das der Ärztedaten in das der Stadtteile umwandeln. Überschreiben Sie hierzu Ihre Variable <i>aerzteGDF</i> mit dem Ergebnis der Funktion <b>aerzteGDF.to_crs()</b>, welcher Sie das Koordinatensystem der Stadtteil-GDF übergeben. Damit erhalten Sie ein GeoDataframe im gleichen Koordinatensystem wie die Stadtteile." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "aerzteGDF = aerzteGDF.to_crs(stadtteile.crs) " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Als nächstes können wir einen <b>Spatial Join</b> durchführen, d.h. eine räumliche Verschneidung, mit der ermittelt wird, in welchen Stadtteilen die Punkt-Koordinaten der Ärzte liegen, sodass die passenden Stadtteil-Informationen (in unserem Fall Name und Einwohner) der Ärzte-Tabelle zugeordnet werden kann. Verwenden Sie hierfür Geopandas' <b>sjoin</b>-Funktion: http://geopandas.org/reference/geopandas.sjoin.html, der Sie Ihre Geodataframes <i>aerzteGDF</i> und <i>stadtteile</i> übergeben, und speichern Sie das Ergebnis in einer neuen Variablen namens <b>aerzte_mit_stadtteil</b>. Lassen Sie sich diese Variable ausgeben. Sie sollte nicht leer sein! Anderenfalls hat vermutlich etwas mit dem Gleichsetzen der Koordinatensysteme nicht geklappt." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " Unnamed: 0 ID Fachgebiet1 Adresse \\\n", + "0 0 2 Hals-Nasen-Ohrenheilkunde Waitzstr. 7 \n", + "19 19 592 Hals-Nasen-Ohrenheilkunde Waitzstr. 7 \n", + "33 34 995 Hals-Nasen-Ohrenheilkunde Waitzstr. 14 \n", + "87 99 2870 Hals-Nasen-Ohrenheilkunde Beselerplatz 11 \n", + "107 122 3722 Hals-Nasen-Ohrenheilkunde Waitzstr. 14 \n", + ".. ... ... ... ... \n", + "99 114 3387 Hals-Nasen-Ohrenheilkunde Bornheide 11 \n", + "94 108 3148 Hals-Nasen-Ohrenheilkunde Wolffstr. 9 \n", + "106 121 3693 Hals-Nasen-Ohrenheilkunde Marktpassage 6 \n", + "115 131 3947 Hals-Nasen-Ohrenheilkunde Tangstedter Landstr. 77 \n", + "119 135 4057 Hals-Nasen-Ohrenheilkunde Wandsbeker Marktstr. 8 \n", + "\n", + " PLZ Privatarzt Stadt Land \\\n", + "0 22607 NaN Hamburg Germany \n", + "19 22607 NaN Hamburg Germany \n", + "33 22607 NaN Hamburg Germany \n", + "87 22607 NaN Hamburg Germany \n", + "107 22607 NaN Hamburg Germany \n", + ".. ... ... ... ... \n", + "99 22549 NaN Hamburg Germany \n", + "94 22525 NaN Hamburg Germany \n", + "106 21149 NaN Hamburg Germany \n", + "115 22415 NaN Hamburg Germany \n", + "119 22041 NaN Hamburg Germany \n", + "\n", + " Adresse_kombiniert \\\n", + "0 Waitzstr. 7,22607,Hamburg,Germany \n", + "19 Waitzstr. 7,22607,Hamburg,Germany \n", + "33 Waitzstr. 14,22607,Hamburg,Germany \n", + "87 Beselerplatz 11,22607,Hamburg,Germany \n", + "107 Waitzstr. 14,22607,Hamburg,Germany \n", + ".. ... \n", + "99 Bornheide 11,22549,Hamburg,Germany \n", + "94 Wolffstr. 9,22525,Hamburg,Germany \n", + "106 Marktpassage 6,21149,Hamburg,Germany \n", + "115 Tangstedter Landstr. 77,22415,Hamburg,Germany \n", + "119 Wandsbeker Marktstr. 8,22041,Hamburg,Germany \n", + "\n", + " Geocoded latitude longitude \\\n", + "0 Änderungsschneiderei, 7, Waitzstraße, Groß Flo... 53.559497 9.885421 \n", + "19 Änderungsschneiderei, 7, Waitzstraße, Groß Flo... 53.559497 9.885421 \n", + "33 Volksbank, 14, Waitzstraße, Groß Flottbek, Alt... 53.559661 9.884339 \n", + "87 Köpi-Bar, 11, Beselerplatz, Groß Flottbek, Alt... 53.559699 9.887951 \n", + "107 Volksbank, 14, Waitzstraße, Groß Flottbek, Alt... 53.559661 9.884339 \n", + ".. ... ... ... \n", + "99 Deesmoor-Apotheke, 11, Bornheide, Osdorf, Alto... 53.582789 9.855380 \n", + "94 Ärztehaus, 9, Wolffstraße, Stellingen, Eimsbüt... 53.579169 9.933645 \n", + "106 6, Marktpassage, Neugraben, Neugraben-Fischbek... 53.470557 9.853249 \n", + "115 Ärztehaus Langenhorn, 77, Tangstedter Landstra... 53.651396 10.017983 \n", + "119 First Cut, 8, Wandsbeker Marktstraße, Marienth... 53.570492 10.061576 \n", + "\n", + " geometry index_right \\\n", + "0 POINT (558649.2475721425 5934877.526663299) 22 \n", + "19 POINT (558649.2475721425 5934877.526663299) 22 \n", + "33 POINT (558577.3466108972 5934894.802930685) 22 \n", + "87 POINT (558816.5614957435 5934902.040986323) 22 \n", + "107 POINT (558577.3466108972 5934894.802930685) 22 \n", + ".. ... ... \n", + "99 POINT (556628.3174588972 5937444.31490787) 11 \n", + "94 POINT (561814.8077995365 5937106.683680706) 31 \n", + "106 POINT (556636.7223994726 5924957.048849167) 21 \n", + "115 POINT (567283.4957914886 5945218.391117038) 10 \n", + "119 POINT (570298.9358385277 5936260.128897806) 27 \n", + "\n", + " NAME Einwohner \n", + "0 Othmarschen 12335 \n", + "19 Othmarschen 12335 \n", + "33 Othmarschen 12335 \n", + "87 Othmarschen 12335 \n", + "107 Othmarschen 12335 \n", + ".. ... ... \n", + "99 Osdorf 25203 \n", + "94 Stellingen 23037 \n", + "106 Neugraben-Fischbek 26782 \n", + "115 Langenhorn 41459 \n", + "119 Marienthal 12239 \n", + "\n", + "[120 rows x 16 columns]\n" + ] + } + ], + "source": [ + "aerzte_mit_stadtteil = gp.sjoin(aerzteGDF, stadtteile)\n", + "print(aerzte_mit_stadtteil)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Speichern Sie dieses Ergebnis als Shapefile mit dem Namen \"Aerzte_mit_Stadtteil.shp\" im Daten-Ordner ab." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "aerzte_mit_stadtteil.to_file(driver='ESRI Shapefile', filename='../Daten/Aerzte_mit_Stadtteil.shp')" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.7" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Aufgabe/Versorgungsgrad berechnen.ipynb b/Aufgabe/Versorgungsgrad berechnen.ipynb new file mode 100644 index 0000000..c5e372f --- /dev/null +++ b/Aufgabe/Versorgungsgrad berechnen.ipynb @@ -0,0 +1,537 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Berechnung und Darstellung des Versorgungsgrads" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Um dort anzuknüpfen, wo wir im letzten Teil aufgehört haben, lesen Sie zunächst \"Aerzte_mit_Stadtteilen.shp\" in einen GeoDataframe mit Namen \"aerzte_mit_stadtteil\" und die gefilterten Stadtteile (\"stadtteile_gefiltert.shp\") in einen GeoDataframe mit Namen \"stadtteile\" ein. " + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "import geopandas as gp\n", + "import pandas as pd\n", + "\n", + "aerzte_mit_stadtteil = gp.read_file(\"../Daten/Aerzte_mit_Stadtteil.shp\")\n", + "stadtteile = gp.read_file(\"../Daten/stadtteile_gefiltert.shp\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Wir wollen nun zunächst berechnen, wie viele Ärzte es pro Stadtteil gibt. Zum Glück bietet Pandas hierfür bereits eine einfache Funktion an: <b>aerzte_mit_stadtteil[\"NAME\"].value_counts()</b>. Alternativ können Sie zuvor die Spalte \"NAME\" zur besseren Verständlichkeit auch gerne in \"Stadtteilname\" o.ä. umbenennen. Speichern Sie das Ergebnis dieses Funktionsaufrufs in einer Variablen namens <b>anzahl_aerzte</b> und lassen Sie diese ausgeben." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Harburg 8\n", + "Neustadt 7\n", + "Bergedorf 6\n", + "Poppenbüttel 6\n", + "Othmarschen 6\n", + "Altona-Altstadt 5\n", + "Hamburg-Altstadt 5\n", + "Eimsbüttel 4\n", + "Winterhude 4\n", + "Ottensen 4\n", + "Barmbek-Nord 4\n", + "Eppendorf 4\n", + "Eidelstedt 4\n", + "Billstedt 4\n", + "Wandsbek 3\n", + "Uhlenhorst 3\n", + "Bramfeld 3\n", + "Niendorf 3\n", + "Hoheluft-West 3\n", + "Blankenese 3\n", + "Volksdorf 2\n", + "Fuhlsbüttel 2\n", + "Osdorf 2\n", + "Rahlstedt 2\n", + "Wilhelmsburg 2\n", + "Horn 2\n", + "Tonndorf 2\n", + "Hausbruch 2\n", + "Schnelsen 2\n", + "Barmbek-Süd 1\n", + "Farmsen-Berne 1\n", + "Hamm-Nord 1\n", + "Langenhorn 1\n", + "Duvenstedt 1\n", + "Marienthal 1\n", + "Rissen 1\n", + "Neugraben-Fischbek 1\n", + "Stellingen 1\n", + "Hamm-Mitte 1\n", + "Rotherbaum 1\n", + "Harvestehude 1\n", + "Lohbrügge 1\n", + "Name: NAME, dtype: int64\n" + ] + } + ], + "source": [ + "anzahl_aerzte = aerzte_mit_stadtteil[\"NAME\"].value_counts()\n", + "print(anzahl_aerzte)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Die aufgelisteten Zahlen würden wir dem bestehenden DataFrame nun gerne als neue Spalte namens \"ANZAHL_AERZTE\" hinzufügen. Verwenden Sie hierfür die im DataFrame-Tutorial gelernte Vorgehensweise mit der Schleife, d.h.:\n", + "\n", + "- Legen Sie eine leere Liste an\n", + "- Iterieren Sie durch den Ärzte-DataFrame und greifen Sie pro Durchlauf auf den Namen (\"NAME\") des Stadtteils aus den im Format \"Series\" gegebenen Zeilen-Daten zu\n", + "- Nutzen Sie diesen Namen als Schlüssel für die als Variable <i>anzahl_aerzte</i> gespeicherten Key-Value-Pairs, um die Anzahl an Ärzten zu erhalten\n", + "- Erstellen Sie ein neues, leeres Dictionary und fügen Sie einen neuen Eintrag \"NAME\" mit dem Stadtteilnamen hinzu\n", + "(alternativ können Sie auch auf die in ein Dictionary umgewandelte Series aufbauen - dann wird das Ergebnis eben deutlich mehr Daten erhalten)\n", + "- Fügen Sie Ihrem Dictionary außerdem einen neuen Eintrag \"ANZAHL_AERZTE\" mit der Anzahl der Ärzte hinzu.\n", + "- Hängen Sie das Dictionary an Ihre Liste an\n", + "- Nach der Schleife erstellen Sie ein neues DataFrame (oder GeoDataframe) aus der gefüllten Liste" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " NAME ANZAHL_AERZTE\n", + "0 Othmarschen 6\n", + "1 Othmarschen 6\n", + "2 Othmarschen 6\n", + "3 Othmarschen 6\n", + "4 Othmarschen 6\n", + ".. ... ...\n", + "115 Osdorf 2\n", + "116 Stellingen 1\n", + "117 Neugraben-Fischbek 1\n", + "118 Langenhorn 1\n", + "119 Marienthal 1\n", + "\n", + "[120 rows x 2 columns]\n" + ] + } + ], + "source": [ + "lines = []\n", + "for row, data in aerzte_mit_stadtteil.iterrows():\n", + " \n", + " name = data[\"NAME\"]\n", + " my_dict = {}\n", + " my_dict[\"NAME\"] = name\n", + " my_dict['ANZAHL_AERZTE'] = anzahl_aerzte[name]\n", + " lines.append(my_dict) \n", + " \n", + "result = gp.GeoDataFrame(lines) \n", + "print(result)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Als nächstes wollen wir die Information über die Anzahl an Ärzten in unser Stadtteil-GeoDataframe übertragen. Da das Stadtteil-GDF eine Spalte \"NAME\" enthält und unser DataFrame aus dem letzten Schritt ebenfalls eine Spalte \"NAME\" neben der Spalte \"ANZAHL_AERZTE\" enthält, können wir beide Tabellen über die gemeinsame Spalte \"NAME\" vereinigen. Verwenden Sie hierfür Pandas' <b>merge</b>-Funktion (https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.merge.html), der Sie erst die Stadtteile und dann den DataFrame des letzten Arbeitsschritts übergeben. \n", + "\n", + "Wichtig: Das Standard-Verhalten von <i>merge</i> ist ein sogenannter <i>innerer Join</i>, der nur übereinstimmende Tabelleneinträge beibehält und die anderen entfernt. Wir wollen aber auch diejenigen Stadtteile beibehalten, in denen es überhaupt keine Ärzte gibt. Verwenden Sie deshalb den Parameter <b>how='left'</b>. " + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " NAME Einwohner \\\n", + "0 Barmbek-Süd 31360 \n", + "1 Duvenstedt 6220 \n", + "2 Rissen 14763 \n", + "3 Blankenese 12807 \n", + "4 Blankenese 12807 \n", + ".. ... ... \n", + "173 St. Georg 10279 \n", + "174 Hohenfelde 8904 \n", + "175 Altona-Nord 33052 \n", + "176 Sternschanze 7723 \n", + "177 Hafen-City 1097 \n", + "\n", + " geometry ANZAHL_AERZTE \n", + "0 POLYGON ((568738.5000999998 5936170.3463, 5687... 1.0 \n", + "1 POLYGON ((574154.1001000004 5950369.9463, 5740... 1.0 \n", + "2 POLYGON ((552240.9001000002 5939762.5463, 5522... 1.0 \n", + "3 POLYGON ((551279.1001000004 5934212.5463, 5507... 3.0 \n", + "4 POLYGON ((551279.1001000004 5934212.5463, 5507... 3.0 \n", + ".. ... ... \n", + "173 POLYGON ((568009.5000999998 5934687.146299999,... NaN \n", + "174 POLYGON ((566795.1001000004 5935675.9463, 5669... NaN \n", + "175 POLYGON ((563605.9812000003 5935419.763699999,... NaN \n", + "176 POLYGON ((564561.5401999997 5935584.9878, 5644... NaN \n", + "177 POLYGON ((566813.6781000001 5933346.6083, 5669... NaN \n", + "\n", + "[178 rows x 4 columns]\n" + ] + } + ], + "source": [ + "merged = pd.merge(stadtteile, result, on=['NAME'], how='left')\n", + "print(merged)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Wenn Sie sich das Ergebnis ausgeben lassen, sehen Sie einige NaN-Einträge in der ANZAHL_AERZTE-Spalte. Dies sind die Stadtteile, wo keine Ärzte Eingetragen sind. Füllen Sie diese Werte mit Nullen auf, indem Sie die Funktion <b>fillna</b> (https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.fillna.html) auf ihr aktuelles DataFrame anwenden und das Ergebnis in einer Variablen namens <b>stadtteile_final</b> speichern." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "NAME object\n", + "Einwohner int64\n", + "geometry object\n", + "ANZAHL_AERZTE float64\n", + "dtype: object\n", + " NAME Einwohner \\\n", + "0 Barmbek-Süd 31360 \n", + "1 Duvenstedt 6220 \n", + "2 Rissen 14763 \n", + "3 Blankenese 12807 \n", + "4 Blankenese 12807 \n", + ".. ... ... \n", + "173 St. Georg 10279 \n", + "174 Hohenfelde 8904 \n", + "175 Altona-Nord 33052 \n", + "176 Sternschanze 7723 \n", + "177 Hafen-City 1097 \n", + "\n", + " geometry ANZAHL_AERZTE \n", + "0 POLYGON ((568738.5000999998 5936170.3463, 5687... 1.0 \n", + "1 POLYGON ((574154.1001000004 5950369.9463, 5740... 1.0 \n", + "2 POLYGON ((552240.9001000002 5939762.5463, 5522... 1.0 \n", + "3 POLYGON ((551279.1001000004 5934212.5463, 5507... 3.0 \n", + "4 POLYGON ((551279.1001000004 5934212.5463, 5507... 3.0 \n", + ".. ... ... \n", + "173 POLYGON ((568009.5000999998 5934687.146299999,... 0.0 \n", + "174 POLYGON ((566795.1001000004 5935675.9463, 5669... 0.0 \n", + "175 POLYGON ((563605.9812000003 5935419.763699999,... 0.0 \n", + "176 POLYGON ((564561.5401999997 5935584.9878, 5644... 0.0 \n", + "177 POLYGON ((566813.6781000001 5933346.6083, 5669... 0.0 \n", + "\n", + "[178 rows x 4 columns]\n" + ] + } + ], + "source": [ + "stadtteile_final = merged.fillna(0)\n", + "print(stadtteile_final.dtypes)\n", + "print(stadtteile_final)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Sollten Sie in der ANZAHL_AERZTE-Tabelle nun Gleitkommazahlen stehen haben, wandeln Sie die komplette Spalte mit dem bekannten <b>.astype()</b> in eine <b>int</b>-Spalte um." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [], + "source": [ + "stadtteile_final[\"ANZAHL_AERZTE\"] = stadtteile_final[\"ANZAHL_AERZTE\"].astype(int)" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " NAME Einwohner \\\n", + "0 Barmbek-Süd 31360 \n", + "1 Duvenstedt 6220 \n", + "2 Rissen 14763 \n", + "3 Blankenese 12807 \n", + "4 Blankenese 12807 \n", + ".. ... ... \n", + "173 St. Georg 10279 \n", + "174 Hohenfelde 8904 \n", + "175 Altona-Nord 33052 \n", + "176 Sternschanze 7723 \n", + "177 Hafen-City 1097 \n", + "\n", + " geometry ANZAHL_AERZTE \n", + "0 POLYGON ((568738.5000999998 5936170.3463, 5687... 1 \n", + "1 POLYGON ((574154.1001000004 5950369.9463, 5740... 1 \n", + "2 POLYGON ((552240.9001000002 5939762.5463, 5522... 1 \n", + "3 POLYGON ((551279.1001000004 5934212.5463, 5507... 3 \n", + "4 POLYGON ((551279.1001000004 5934212.5463, 5507... 3 \n", + ".. ... ... \n", + "173 POLYGON ((568009.5000999998 5934687.146299999,... 0 \n", + "174 POLYGON ((566795.1001000004 5935675.9463, 5669... 0 \n", + "175 POLYGON ((563605.9812000003 5935419.763699999,... 0 \n", + "176 POLYGON ((564561.5401999997 5935584.9878, 5644... 0 \n", + "177 POLYGON ((566813.6781000001 5933346.6083, 5669... 0 \n", + "\n", + "[178 rows x 4 columns]\n" + ] + } + ], + "source": [ + "print(stadtteile_final)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Legen Sie nun eine neue Spalte \"Verhaeltnis\" an, die das Ergebnis der Division von \"Einwohner\" und \"ANZAHL_Aerzte\" beinhaltet. (Tipp: Sie brauchen hierfür nur eine Zeile Code, keine Schleife.) Zum Glück wird eine Division durch 0 bereits automatisch so abgefangen, dass diese Felder den Wert <i>inf</i> erhalten." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " NAME Einwohner \\\n", + "0 Barmbek-Süd 31360 \n", + "1 Duvenstedt 6220 \n", + "2 Rissen 14763 \n", + "3 Blankenese 12807 \n", + "4 Blankenese 12807 \n", + ".. ... ... \n", + "173 St. Georg 10279 \n", + "174 Hohenfelde 8904 \n", + "175 Altona-Nord 33052 \n", + "176 Sternschanze 7723 \n", + "177 Hafen-City 1097 \n", + "\n", + " geometry ANZAHL_AERZTE \\\n", + "0 POLYGON ((568738.5000999998 5936170.3463, 5687... 1 \n", + "1 POLYGON ((574154.1001000004 5950369.9463, 5740... 1 \n", + "2 POLYGON ((552240.9001000002 5939762.5463, 5522... 1 \n", + "3 POLYGON ((551279.1001000004 5934212.5463, 5507... 3 \n", + "4 POLYGON ((551279.1001000004 5934212.5463, 5507... 3 \n", + ".. ... ... \n", + "173 POLYGON ((568009.5000999998 5934687.146299999,... 0 \n", + "174 POLYGON ((566795.1001000004 5935675.9463, 5669... 0 \n", + "175 POLYGON ((563605.9812000003 5935419.763699999,... 0 \n", + "176 POLYGON ((564561.5401999997 5935584.9878, 5644... 0 \n", + "177 POLYGON ((566813.6781000001 5933346.6083, 5669... 0 \n", + "\n", + " Verhaeltnis \n", + "0 31360.0 \n", + "1 6220.0 \n", + "2 14763.0 \n", + "3 4269.0 \n", + "4 4269.0 \n", + ".. ... \n", + "173 inf \n", + "174 inf \n", + "175 inf \n", + "176 inf \n", + "177 inf \n", + "\n", + "[178 rows x 5 columns]\n" + ] + } + ], + "source": [ + "stadtteile_final[\"Verhaeltnis\"] = stadtteile_final[\"Einwohner\"]/stadtteile_final[\"ANZAHL_AERZTE\"]\n", + "print(stadtteile_final)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Die planmäßige Verhältniszahl für HNO-Ärzte lautet 17675. Berechnen Sie den Verhältnisgrad in einer neuen Spalte \"VG\", indem Sie das prozentuale Verhältnis zwischen dieser Zahl und dem vorliegenden Wert in der Spalte \"Verhaeltnis\" berechnen." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " NAME Einwohner \\\n", + "0 Barmbek-Süd 31360 \n", + "1 Duvenstedt 6220 \n", + "2 Rissen 14763 \n", + "3 Blankenese 12807 \n", + "4 Blankenese 12807 \n", + ".. ... ... \n", + "173 St. Georg 10279 \n", + "174 Hohenfelde 8904 \n", + "175 Altona-Nord 33052 \n", + "176 Sternschanze 7723 \n", + "177 Hafen-City 1097 \n", + "\n", + " geometry ANZAHL_AERZTE \\\n", + "0 POLYGON ((568738.5000999998 5936170.3463, 5687... 1 \n", + "1 POLYGON ((574154.1001000004 5950369.9463, 5740... 1 \n", + "2 POLYGON ((552240.9001000002 5939762.5463, 5522... 1 \n", + "3 POLYGON ((551279.1001000004 5934212.5463, 5507... 3 \n", + "4 POLYGON ((551279.1001000004 5934212.5463, 5507... 3 \n", + ".. ... ... \n", + "173 POLYGON ((568009.5000999998 5934687.146299999,... 0 \n", + "174 POLYGON ((566795.1001000004 5935675.9463, 5669... 0 \n", + "175 POLYGON ((563605.9812000003 5935419.763699999,... 0 \n", + "176 POLYGON ((564561.5401999997 5935584.9878, 5644... 0 \n", + "177 POLYGON ((566813.6781000001 5933346.6083, 5669... 0 \n", + "\n", + " Verhaeltnis VG \n", + "0 31360.0 56.361607 \n", + "1 6220.0 284.163987 \n", + "2 14763.0 119.724988 \n", + "3 4269.0 414.031389 \n", + "4 4269.0 414.031389 \n", + ".. ... ... \n", + "173 inf 0.000000 \n", + "174 inf 0.000000 \n", + "175 inf 0.000000 \n", + "176 inf 0.000000 \n", + "177 inf 0.000000 \n", + "\n", + "[178 rows x 6 columns]\n" + ] + } + ], + "source": [ + "stadtteile_final['VG'] = 17675/stadtteile_final['Verhaeltnis']*100\n", + "print(stadtteile_final)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Speichern Sie das Ergebnis als Shapefile im Daten-Ordner unter dem Namen \"versorgungsgrad.shp\"." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [], + "source": [ + "stadtteile_final.to_file(driver='ESRI Shapefile', filename='../Daten/versorgungsgrad.shp')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Das Ergebnis plotten wir nun mithilfe der Bibliothek <b>matplotlib</b> und der Plotting-Funktionalität von GeoDataFrames. Der Code dafür ist unten vorgegeben, kann aber nach eigenen Ermessen von Ihnen erweitert oder verändert werden. Orientieren Sie sich hierfür an den Dokumentationen (http://geopandas.org/mapping.html bzw. https://matplotlib.org/api/pyplot_api.html). Für manche Funktionalitäten kann es aber sein, dass erst noch zusätzliche Module installiert werden müssen. " + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "<matplotlib.axes._subplots.AxesSubplot at 0x7f752fcd8358>" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAgQAAAHSCAYAAACTjdM5AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjEsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy8QZhcZAAAgAElEQVR4nOzdd3xUVfr48c+ZmUx6L7QAARJqIAQCqCAWpCgKsiJiRV12V3f3p+u6q2xBF8siu64rfi2sHVwrIEWU5iJSBFIg9BJKAgkBQnqfzMz5/TGTkJBJMpPMZFLO+/Xilcm955x7Iph55txzn0dIKVEURVEUpXPTuHsCiqIoiqK4nwoIFEVRFEVRAYGiKIqiKCogUBRFURQFFRAoiqIoioIKCBRFURRFAXTunkBrCgsLk1FRUe6ehqIoiqK4RUpKymUpZbitc50qIIiKiiI5Odnd01AURVEUtxBCZDR0Tt0yUBRFURRFBQSKoiiKoqiAQFEURVEUOtkeAkVRFAWqqqrIzMykoqLC3VNRXMTLy4vIyEg8PDzs7qMCAkVRlE4mMzMTf39/oqKiEEK4ezqKk0kpyc3NJTMzkz59+tjdT90yUBRF6WQqKioIDQ1VwUAHJYQgNDTU4RUgtUKgKIrSCdkbDGTklvLR1jRW782kyAQBWrhzRCSP3BhD71BfF89Saa7mBHtqhUBRFEWx6Yfjl7jj1f+R8c5n/Pztv7PgH3/k52//nYx3PuOOV//HD8cvNXvsDRs2MGDAAKKjo3nllVdstpFS8sQTTxAdHc2wYcPYu3evQ/0bc+bMGcaMGUNMTAz33HMPBoPBZrulS5cSExNDTEwMS5cudbh/e6ICAkVRFKWejNxSnvx4N/cte5OJ/1tDaEEuWmkmtCCXif9bw33L3uTJj3eTkVvq8Ngmk4nf/OY3rF+/niNHjvD5559z5MiReu3Wr19PWloaaWlpvPvuuzz++OMO9W/Ms88+y1NPPUVaWhrBwcF88MEH9drk5eWxYMEC9uzZQ2JiIgsWLCA/P9/u/u2NCggURVGUej7amsbIpB30Om87sV2v8xmMTN7Bxz+mOTx2YmIi0dHR9O3bF71ez+zZs1mzZk29dmvWrOGhhx5CCME111xDQUEB2dnZdvdviJSSLVu2MHPmTADmzJnD6tWr67XbuHEjEydOJCQkhODgYCZOnMiGDRvs7t/eqIBAURRFqWf13kxGpOxotM2I5B2sTsl0eOysrCx69uxZ831kZCRZWVl2t7O3f0Nyc3MJCgpCp9M16/r29m9vVECgKIqi1FNkgqDC/EbbBBXlU2hyfGwpZb1jtjbBNdTO3v5t9fptlQoIFEVRlHoCtFAQGNxom4KAYAK1jo8dGRnJuXPnar7PzMyke/fudrezp7/JZGL48OEMHz6c5557rs65sLAwCgoKMBqNzbq+vf3bGxUQKIqiKPXcOSKSvSPHNdpmb8I47hwZ6fDYo0aNIi0tjTNnzmAwGPjiiy+YNm1avXbTpk1j2bJlSCnZvXs3gYGBdOvWza7+Wq2W1NRUUlNTeeGFF+qcE0Jw0003sWLFCsDyJMH06dPrXX/y5Mls2rSJ/Px88vPz2bRpE5MnT7a7f3ujAgJFURSlnkdujCFl1DjOdu9t8/zZ7r1JSRjHwzfEODy2TqfjzTffZPLkyQwaNIhZs2YxZMgQAJYsWcKSJUsAuO222+jbty/R0dH84he/4O23326yv70WLVrEa6+9RnR0NLm5ufz85z8HIDk5mblz5wIQEhLC/PnzGTVqFKNGjeK5554jJCSk0f7tmbB1L6SjSkhIkMnJye6ehqIoilsdPXqUQYMGNdnuh+OXePLj3YxM3sGI5B0EFeVTEBDM3oRxpCSMY/HD13DTgIhWmLHSHLb+noUQKVLKBFvt7cpUKIRIB4oBE2CUUiYIIeKAJYAfkA7cL6UsEkJEAUeB49buu6WUj1nH2Qp0A8qt5yZJKS8JITyBZcBIIBe4R0qZbu0zB/irtf1LUsql1uN9gC+AEGAv8KCUsv1nhlAURWkjbhoQwTd/mMDHP/biw5TxFJogUAt3jozkbzeoTIUdjSOpi2+SUl6u9f37wB+klD8KIR4F/gjMt547JaUc3sA490spr/6Y/nMgX0oZLYSYDSwC7hFChADPAwmABFKEEGullPnWNv+WUn4hhFhiHeMdB34eRVGUDkWazWRv2oHW2wv/fr3wieza4jF7h/ry/M+G8/zPGvqVrnQULdlDMADYZn29GbirBWNNB6pzQq4AJgjLMxyTgc1SyjxrELAZmGI9d7O1Lda+d7bg+oqiKO2aNJtJfOx5tt76C/5344Os7nkDm8bO5tQHy6kqLnH39JR2wN6AQAKbhBApQohfWo8dAqq3dd4N9KzVvo8QYp8Q4kchxPVXjfWRECJVCDFfXHlwswdwDkBKaQQKgdDax60yrcdCgQJr29rH6xFC/FIIkSyESM7JybHzx1UURWlfzq3azKn3vqpz7PJP+9gz96+siZrA2ZUb3TQzpb2wNyAYK6UcAdwK/EYIMR541Po6BfAHqu/fZwO9pJTxwO+Bz4QQAdZz90sphwLXW/88aD1uK6ODbMbx+gelfFdKmSClTAgPD2/q51QURWmX0t75vMFzhrwCdsx8gl0Pz6OqSK0WKLbZtYdASnne+vWSEGIVMFpK+SowCUAI0R+Yam1TCVRaX6cIIU4B/YFkKWWW9XixEOIzYDSWzYSZWFYYMoUQOiAQyLMev7HWVCKBrcBlIEgIobOuEkQC55v530BRFKXdq8zJa7LNmaWrKM/Oodvrf7B73IzcUpZuP8ma1EzyKyTBXoLpwyOZc3202lTYwTS5QiCE8BVC+Fe/xhIEHBJCRFiPabA8BbDE+n24EEJrfd0XiAFOCyF0Qogw63EP4HYstx0A1gJzrK9nAluk5XnIjcAkIUSwECLYeu2N1nM/WNti7Wt/ZQtFUZQORhrtyyF8YdMOTJX2PZD1w/FLzFj8Ax6HN/Kl73IORXzMl77L8Ti8kRmLf2jX5Y/ffPNNoqOjEUJw+fKV/fItveaaNWsYNmwYw4cPJyEhgR07rtSDWLx4MbGxsQwZMoTXX3/d4Tm7mj23DLoAO4QQ+4FE4Fsp5QbgXiHECeAYlk/nH1nbjwcOWNuvAB6TUuYBnsBGIcQBIBXIAt6z9vkACBVCnMRym2EegLXfi0CS9c8L1mMAzwK/t/YJtY6hKIrSKZmNxqYbWRnyCjEbqhptk5FbytOfJvKO7zqe9tlDL10xOiHppSvmaZ89luOfJrbb8sdjx47l+++/p3fvuomXWnrNCRMmsH//flJTU/nwww9rkhwdOnSI9957j8TERPbv38+6detIS3O8UqQrNXnLQEp5GoizcXwxsNjG8ZXAShvHS7HkGbB1jQosGxNtnfsQ+LCBeY1uYvqKoigdnslgwFRWYXd7s8FAwaE0vLuH4xURitDU/2y4dPtJ7vY8Qrze9mbseH0OM41HWLajJ/On13uLaFTt8sVATfniwYMH12nXUPnj9PR0u/o3Jj4+3ubxll7Tz8+v5nVpaWlN0aOjR49yzTXX4OPjA8ANN9zAqlWreOaZZ+yes6up1MWKoijtlJSSc19v4tsht1OWecGxvmYzZZkXKTh4gqLjp6kqrvtJf01qJnfrG//UPUt/hDX72l/54+bMzZFrrlq1ioEDBzJ16lQ+/NDyeTY2NpZt27aRm5tLWVkZ3333XZ3CSW2BI4mJFEVRlDYiN+kAe3//Cjk7Ulo0jrnKiLnKCNmX0PlFIYTAXGUkv0LSPaDxJxK6aUvIr3Q8/X1bLj/sjGvOmDGDGTNmsG3bNubPn8/333/PoEGDePbZZ5k4cSJ+fn7ExcWh07Wtt2C1QqAoitKOlGZksfP+p9k4+u4WBwO1VRWVUrD/GMUnMyg8nEaQh+S8ya/RPtkmP4I9HX8jdnf54+bMzd451zZ+/HhOnTpVs2nx5z//OXv37mXbtm2EhIQQE+N4YShXUgGBoihKO2AoLCb1T//imwFTyPhsnUuuYTaaMBQUYzaamNLLj+WVjRdA+sowmOnx7a/8cWNack2AkydP1qwm7N27F4PBQGhoKACXLlmeyjh79ixff/019957r93zag1ta71CURRFqcNsNHLqva848Pz/2ZVrwFlmxQTxyNnB3OxxxubGwn2GcFZUDmbVuGiHx65dvthkMvHoo4/WKX8M8Nhjj3Hbbbfx3XffER0djY+PDx999FGT/e31xhtv8I9//IMLFy4wbNgwbrvtNt5///1mXbP2nFeuXMmyZcvw8PDA29ubL7/8subWwl133UVubi4eHh689dZbBAcHO/zfzpVU+WNFUZQ2qizzAj/e8Rj5qUedOm7/9W/RJ6zpwkdJlXr+vPEEMz2PMEt/hG7aErJNfnxlGMyKysH86/7RqvxxG+aS8seKoihK65JmM9t+9lunBwOOuGlgBKsG9mDZjp7M3jeE/EpJsKdgenwkq8apTIUdjQoIFEVR2qBTH6wgL+mgW+eg9fKkt68386fHOZxrQGl/1KZCRVGUNqL41FmklFTmFbD/T/9y93TQeundPQWlFakVAkVRFDeTUnLs3x+z7+lX8OnZDa+IECpzC9w6J43eA6HVunUOSutSAYGiKIoblaRnkvzbFzn/7VYAys5lU3Yu272TAjQe6u2hs1F/44qiKG5y/I1lpP7pNUxl5e6eSoMycktZ+tMZ1uzPIr/USLCvjulxPZhzXR+1qbCDUXsIFEVR3ODIP98n5cmX22wwoA8JtJQ/fns7Xh7ZrHxcx/GXvFn5uA4vj2xmvL29ReWPH330USIiIoiNja1zPC8vj4kTJxITE8PEiRPJz8+vObdw4UKio6MZMGAAGzdutDnu/Pnza8oPT5o0ifPnzwNgMBh45JFHGDp0KHFxcWzdutVpc96/fz/XXnstQ4cO5Y477qCoqMihOTfU/9NPP63Jtjh8+HA0Gg2pqakOz9teKiBQFEVpRaZKA0m//hupz/zT3VNpkNAILqDn6a/28t5DOv44RUfvUA06raB3qIY/TtHx3kM6nv5qb7PKHwM8/PDDbNiwod7xV155hQkTJpCWlsaECRN45ZVXADhy5AhffPEFhw8fZsOGDfz617/GZDLV6//HP/6RAwcOkJqayu23316TpfC9994D4ODBg2zevJmnn34as9nslDnPnTuXV155hYMHDzJjxgz++c9/OjTnhvrff//9NdkWP/nkE6Kiohg+fLhDc3aECggURVFaScnpc2weO5u0dz5391QapQ8J5JPEs8wepWVEb9sbC0f01nLPKC3Ldp1p1jXGjx9PSEhIveNr1qxhzpw5AMyZM4fVq1fXHJ89ezaenp706dOH6OhoEhMT6/UPCAioeV27/PCRI0eYMGECABEREQQFBeFoorqG5nz8+HHGjx8PwMSJE1m5cqVDc26of22ff/65y1Mdq4BAUZROw2Q2sjVzDftydpBRdIIiQ77NKnaucHHrHtaPmEFeyuFWuV5LeIWHsmZ/FrNGNf4Wcc8oDWtSnVN2uNrFixfp1q0bAN26davJ/+9I+eG//OUv9OzZk08//bRmhSAuLo41a9ZgNBo5c+YMKSkpTis/HBsby9q1awFYvnx5zbj2zrmh/rV9+eWXLg8I1KZCRVE6jUN5iezM/q7OMZ3GgxDPCIK9IgjxDKeLT08GhyQghPM+LxkKitg2/ddUFTVeTrgt0Pl6o/P1Jr/USI8gj0bbdg8S5JcZW2VejpQffvnll3n55ZdZuHAhb775JgsWLODRRx/l6NGjJCQk0Lt3b6677jqnlR/+8MMPeeKJJ3jhhReYNm0aer3eoTk31L/anj178PHxqbd3wdlUQKAoSqcgpZld2fU3dRnNVVwqz+JS+ZVPbvtytnN3zK/x1Ho75dqnPljRLoIBAK9wy5J4sK+OrAJJ79CGyxufL5AE+zj3baRLly5kZ2fTrVs3srOziYiw1EpoTvnh++67j6lTp7JgwQJ0Oh3//ve/a85dd9119coP79mzh1/96lcANW/O9hg4cCCbNm0C4MSJE3z77bcOzbmh/tW++OKLVqmMqG4ZKIrSKRzPTyW34oJdbTOKT/D1qfcwy/obwBxVfOosJ978b4vHaQ1Cp0UfEgjA9LgefJXU+Ka7L5PMTB/ew6lzmDZtGkuXLgVg6dKlTJ8+veb4F198QWVlJWfOnCEtLY3Ro0fX65+Wllbzeu3atQwcOBCAsrIySkstGyA3b96MTqdj8ODBdfqOGTOmZhOfvcEAXClrbDabeemll3jsscccmnND/auPLV++nNmzZ9s9n+ZSAYGiKB2elJKfsuvvDm/M6cLDfHP6Y5Iu/kBRZfPKDksp2T7jN5SmO/c+u6t4hQUjNJa3hTnX9eGLJBN7M2wHRXszTHyZZOKha/s061r33nsv1157LcePHycyMpIPPvgAgHnz5rF582ZiYmLYvHkz8+bNA2DIkCHMmjWLwYMHM2XKFN566y201kyKc+fOrdkgOG/ePGJjYxk2bBibNm1i8eLFgOVNd8SIEQwaNIhFixbxySefOG3On3/+Of3792fgwIF0796dRx55xKE5N9QfYNu2bURGRtK3b1+H5+soVf5YUZQO70zhUT478Xqz+4+KuJlJve9ptM2O89+RW57N7X3moNVYltEvbNnFlgkPN/u6rtJQ+eOg2Bi0Xp413/9w/BJPf7WXe0ZpuWeUhu5BgvMFki+TzHyZZOJfs0ao8sdtmCp/rCiKcpWfste3qP++y9sxmCvp6tOTrr69iPCORK+1vHFKKSk05LL9/DrM0kRX396M6XoLAKfeW97iubcWj0C/OsEAwE0DIlj16+tZtusMM9/JIr/MSLCPjunDe7Dq1ypTYUejAgJFUTq0rJIzpBcfb9EYRnMV+y/vZL/1e4Eg1KsrJmmiwliKSRpr9htklZzGLM0IBBe31n/mvK3yCg+1ebx3qC/zb49l/u2u3eGuuJ8KCBRF6dAO5e5x+pgSyeUK2wWIjuan4PVWFuKD/VRcyHH6tZvDMzSInndPIePzb6kqLK53Xqv3wCPQzw0zU9oSFRAoitKhlFYV4a3zQyM07M7eRPKlH1p9DkWaEsypR1v9urVpfbwJio0hMDaG3rOn0m3iWDQ6nc0nHjzDQxp8pl/pPFRAoChKh2Eym/j46CIqTeV08+nN6aIjbplHSVczPm65soVHUAAzc/fUPDFQLe7vT2G4aoVACIFnWHBrTk9po1RAoChKh5FTcZ7CyjwkZrcFAwB5ERVuDQiERsOpD1cSPffuOsc9/P24btk/OJiyF31gAIaCIvTBAWg8Gn4ryMgt5cOdp1idmklRuSTAW3Dn8EgeHdtPbSrsYFQeAkVROoyuPj15YOBTjO9+BxphuyhPazBpZL1P563JkFdA0uN/o+j4aZvndT7e+Ef3InBINF7dwhsc54fjl7j9/7ZyMO9Hply/mUfv/IYp12/mYN6P3P5/W11S/ritlxI2mUzEx8dz++231xxbvnw5Q4YMQaPR2CyYdPbsWfz8/Hj11VdtjtlQyefExMSa+cbFxbFq1SqH5+sIFRAoitKh9PLvT7h3d6dkGWyuiCxvpIOldZ1JaLUMePIhvHt0abSdztsLnbeXzXMZuaU88XkSN12znZFDDhHgV4ZGIwnwK2PkkEPcdM12nvg8yenlj9t6KeHFixfXe7Y/NjaWr7/+uqZi4dWeeuopbr311gbHbKjkc2xsLMnJyaSmprJhwwZ+9atfYTS6rnaECggURelQKoxlfJfh3lTB3oXu+9Uaes1wpqR8zYhXn8XDr/lL+h/uPEVM1Gm6hObbPN8lNJ/oqNN89NOpZo3fHksJZ2Zm8u233zJ37tw6xwcNGsSAAQNs9lm9ejV9+/ZlyJAhDY7bUMlnHx+fmgJMFRUVLt/4qQICRVE6lMSL/6Pc2LxPrQ0xm8wc257BDx/s5dj2DMymxj/9lwe1fgZYj6AARv/nBSbt/JzguIEtHm91aiYxvW3fcqjWv/dpVu/LbPG1amvLpYR/97vf8Y9//AONnbeDSktLWbRoEc8//3yj7Roq+QyWgktDhgxh6NChLFmyxGkVGm1RAYGiKB1GhbGcpItbnDqm2WTmq3nfkbrsf4wMSiZ12f/4at53jQYFugqnTqFJUQ9O5/Zj64n+5T1O27tQVC7x8ylvtI2fTzlF5c4Nfj788EPeeustRo4cSXFxcbNKCdvqX625pYTXrVtHREQEI0eOtLvP888/z1NPPYWfX/NzPIwZM4bDhw+TlJTEwoULqahw3T8u9ZSBoigdhqfWi1kxv+FA7i6O5iVTaWr5L88TP52DgkvsTTLi4QEvvWgkPuESJ346x8Dre9vsE7qngiKbZ5zLL7o3o/+zgK43X+v0sQO8BSVl3gT4lTXYpqTMmwBv5y5ju7OUcGPlj3fu3MnatWv57rvvqKiooKioiAceeID//rfh21N79uxhxYoVPPPMMxQUFKDRaPDy8uK3v/1tnXYNlXyubdCgQfj6+nLo0CESEmyWImgxtUKgKEqHIYSgp380U6Me5Mnh/+TOvj+nb8BgoPlvWtkncrltiiUYAPDwgKm3Gsk+kdtgH016/WyArjDsxSddEgwA3Dk8krSMxivsncjoy53xkU69rjtLCTdW/njhwoVkZmaSnp7OF198wc0339xoMACwfft20tPTSU9P53e/+x1//vOf6wUD1T+brZLPZ86cqdlEmJGRwfHjx4mKimr0mi2hAgJFUTokD42eIaGjuXfAk/y/uIUEezb8eF1juvUP5bsNOqqqLN9XVcG363V06287939rytnuuuqtj47tR1p6Xy7m2k5adDE3mJPpfXnkun7NGr8jlRJetWoVkZGR7Nq1i6lTpzJ58uQm+1xdstlWyecdO3YQFxfH8OHDmTFjBm+//TZhYWFOnXttqvyxoigd3uHcRFaf/qBZfav3EMj8S0y91ci363WI4AhmvXIbGq3tz1Txrxoo+OqnlkzZbuNWvEGvu5p+A6rNVllcW344foknPk8iOuo0/Xufxs+nnJIyb05k9OVkel/euHeUKn/chqnyx4qiKLWUVhWxIePzZvfXaDXMeuU2Tvx0jpQTucTPCaX/dT0bDAYADIMCmn09R+2Y+QRxLz/FkD8/1nRjB900IIJ1/+9GPvqpJ6u397uSqTA+ktfvUJkKOxoVECiK0qGdKDhAhanhjXH20Gg1DLy+d4ObCK92/JZKYpNHUfhtUouua6+LPya5JCAAS/njv90xjL/dMcwl4ytth9pDoChKhxbi2fpL2iatmaqj51vtel7hqjiR0nJqhUBRlA4t2CucLj49uVhWP0GNq0gNFP1tOKGb+4KXjvI1+zFcynPd9TrRXjDFdVRAoChKh3Qsfx+7sjdwvjS9Wf27nvWh6+ZyUh+WoIXYb7zQJeVgHhLCyVuhLKCq4c4awbmBpZwbqAUkQ7b6ujQgQMUDihOogEBRlA6nqDKPb05/hMFcafP8kO+80aw4jm5wVzLvDSSnR92MfOHnvQl8fBeFOfkMzx7N0d/7U/X2LkpzC2EDxJTdzP5HbA5Nn/1+eJRIfI6WUd7fh5PXlFGZmePsH7EuF64QZOSW8t62NFbty6TMAD56mBEfyS/Gx6hNhR2MXXsIhBDpQoiDQohUIUSy9VicEGKX9fg3QogA6/EoIUS5tW2qEGJJrXFGWtufFEK8Iax5J4UQnkKIL63H9wghomr1mSOESLP+mVPreB9r2zRr37r5KRVF6bT+l7mywWAAQH+ggJJDpyn46if8Zqxn+IJSup32ASDkohehv07GkGMp6lO4NpG+DxzCkFtY0784zrvemB6VGnoe9UX7xPdUPfUtRR9sw/T8FuIXlGIqd20uY//+US4Z94fjl5j8+hbe3bmSE7lvkV74Midy3+LdnSuZ/PqWFpU/hvZXSjgqKoqhQ4cyfPjwOtkC58+fz7Bhwxg+fDiTJk3i/HnL/pHNmzczcuRIhg4dysiRI9my5Upa7ZSUFIYOHUp0dDRPPPGEzds+6enpeHt718y7dpKlL7/8kmHDhjFkyBCeeeYZh38WW+zKQyCESAcSpJSXax1LAv4gpfxRCPEo0EdKOd/6Zr5OSlkvUbQQIhF4EtgNfAe8IaVcL4T4NTBMSvmYEGI2MENKeY8QIgRIBhKwLIqlACOllPlCiK+Ar6WUX1iDjv1Synca+zlUHgJF6djMJhP7//QvsiKLEOtOIiuMlk/PZgkmM9IsQUrKT2RhLCqp11/r44WprOk3b5++PRCeHsjKKkyl5RhLyjGV1l1lCB0zjPzUY/j1iaToWONFglrqpk0f0m3iWLvb25OHICO3lMmvb+FM/scYTPWLCOm1PegT/DAbf3dzs1cKXnvtNZKTkykqKmLdunU1c9NoNPzqV7/i1VdfrZem96677kKj0TBmzBj+8Ic/1BvzmWeeISQkhHnz5vHKK6+Qn5/PokWLKCsrQ6/Xo9PpyM7OJi4ujvPnzztULCgqKork5OR6yYGKiooICLA8avrGG29w5MgRlixZwr59++jSpQvdu3fn0KFDTJ48uaYg0+jRo1m8eDHXXHMNt912G0888US9Esnp6encfvvtHDp0qM7x3Nxc4uPjSUlJITw8nDlz5vDQQw8xYcKEOu0czUPQkqcMBgDbrK83A3c11lgI0Q0IkFLukpYoZBlwp/X0dGCp9fUKYIJ19WAysFlKmSelzLdeZ4r13M3Wtlj7Vo+lKEonlb1+G0f/+QFFTy6ncPM+irYfpGjHIYp+OkzRnqMUJx2jOPm4zWAAsCsYACg7nUXp0XTKTmdReTGvXjAQMKAPuXsOYK40uDwYAAiObzrJkKPe25ZGXnmizWAAwGDKIq88ife3n2zW+B2plHB1MACWCofVY8fHx9fUWxgyZAgVFRVUVlaSnZ1NUVER1157LUIIHnrooZp52uP06dP079+f8HBL9s1bbrnFZplnR9kbEEhgkxAiRQjxS+uxQ0B1sue7gZ612vcRQuwTQvwohLjeeqwHULtOZqb1WPW5cwBSSiNQCITWPn5Vn1CgwNr26rEURemEDPmF/DjtcXdPAwDPiNZNa6yxpvB1plX7Mskvb3xFNVPjjXIAACAASURBVL88ia/3Ne/pjfZYSlgIwaRJkxg5ciTvvvtunXN/+ctf6NmzJ59++ikvvPBCvb4rV64kPj4eT09PsrKyiIy8UgOioVLOYKlnEB8fzw033MD27dsBiI6O5tixY6Snp2M0Glm9erXNMs+OsjcgGCulHAHcCvxGCDEeeNT6OgXwBwzWttlALyllPPB74DPr/gJb4Vj1/YqGzjl6vB4hxC+FEMlCiOScHBdv7FEUxW2K0jJcurnOXt7dI8j5aV+rXtNsMjl9zDIDGM0FjbYxmgspa3irRoPaaynhnTt3snfvXtavX89bb73Ftm3bas69/PLLnDt3jvvvv58333yzTr/Dhw/z7LPP8p///Aewv5Rzt27dOHv2LPv27eO1117jvvvuo6ioiODgYN555x3uuecerr/+eqKiohwObmyxKyCQUp63fr0ErAJGSymPSSknSSlHAp8Dp6xtKqWUudbXKdbj/bF8iq9dFisSqM7ckYl1hUEIoQMCgbzax6/qcxkIsra9eqyr5/6ulDJBSplQvbyiKErHYzYYmm7UCvTBgXh1CSVs3EhCEuptpXIJaTI7fUwfPeg0QY220WkC8fF0fOzqUsJRUVHMnj2bLVu28MADDzTaZ8+ePTzzzDNERUXx+uuv8/e//73eGy9cKSUM2FVK+OprVG/gW7t2bb1+1cv/ERERzJgxg8TExHpt7rvvvjrL95mZmcyYMYNly5bRr5+lEFRkZCSZmZl12tgq5ezp6UloqGW1aeTIkfTr148TJ04AcMcdd7Bnzx527drFgAEDiImJqdffUU0GBEIIXyGEf/VrYBJwSAgRYT2mAf4KLLF+Hy6E0Fpf9wVigNNSymygWAhxjXUPwEPAGutl1gLVTxDMBLZY9xlsBCYJIYKFEMHWa2+0nvvB2hZr3+qxFEXphDJXfe/uKQBgLC2j4vwlLu9IabVrShesEMyIjyTY2+besxrB3qP4WXzPRtvY0lZLCTdW/ri0tJTi4uKa15s2bSI21hLwpaWl1bRbu3YtAwcOBKCgoICpU6eycOFCxo69sumzW7du+Pv7s3v3bqSULFu2rGaeteXk5GCy/t2ePn2atLS0mkqN1bdC8vPzefvtt+vtxWgOe1YIugA7hBD7gUTgWynlBuBeIcQJ4BiWT+cfWduPBw5Y268AHpNSVmfkeBx4HziJZeVgvfX4B0CoEOIkltsM8wCs/V4Ekqx/Xqg11rPA7619Qq1jKIrSCZWcPkf6Z+vcPQ0Ays5mo/G0PAVtLG1ZDQV7eAT6ow9yfjGlX4yPIcR7NHqt7e1Zem0PQrxHMff6aKdet62WEr548SLjxo0jLi6O0aNHM3XqVKZMmVJzzdjYWIYNG8amTZtYvHgxAG+++SYnT57kxRdfrFl5qH4jf+edd5g7dy7R0dH069ev5gmDtWvX8txzzwGWcs3Dhg0jLi6OmTNnsmTJEkJCQgB48sknGTx4MGPHjmXevHn079/f7p+lIar8saIo7d6ZT9ey64E/unsaAAitFs+IECqycxBaLQGD+lresAXkJh/G7MScBDd8+y7+Mb0JiIlyqJ8j5Y8f/+8e8sqTyC9PwmguRKcJJNh7FCHeo3jngTGq/HEbpsofK4rSqRjLyilNt71D2x3CxsaTs83ywUOaTBQeurKcHDRsAEVpGU4JCvr/9gF63HZDi8dpzE0DItj4u5t5f3svvt43mrJK8PGEn8X3ZO710SpTYQejAgJFUdqltCWfk/7pN5bn/asaqSvQysyVDc+l4MBx/Pr1QprNVF7Ox1hWAc24/+8b1YO4hb9vyTTt1jvUlxfvjOPFO+Na5XqK+6iAQFGUdqnw6ClyWnHjnr00Ho3/Wi05dbbmtW/fnpSedvz58dHvvoiHn/p0rjhXSzIVKoqiuE3XCde6ewq22ZlopyX8Y3q3eIzOtH+sM2rO368KCBRFaZe633YDd2Zt4/bjG5iydxVRD9Z/bMsdHMmIqw8OQB/a+LP+thQeOeVwn9q8vLzIzc1VQUEHJaUkNzcXLy8vh/qpWwaKorRLGp0On+5dAKjMzSd7/bYmerQOR95j81MOo/HUEzp6KKVnL1Bxwb5sqh5+Ps2cnUV1YhyVvbXj8vLyqpMe2R4qIFAUpd3zDA3Gv38UlZfz3T0VDPmFTTeqxVxpIDfxICGjYtHoPfDuHoFGrwMEOduS6rUPihtI+PWNJwxqioeHB3369GnRGErHowICRVE6hH5z7+ZyK9cQuJpHgB+FB080q29ekiWNbtlZaxZ2G/cefKN6MOb9l5xaqU9Rqqk9BIqitAlStiwff6+7p6Dzd+/Oe+NVZZBb5Kp7D71m3cqt+1YTmjDUeddQlFrUCoGiKHVIacZSoqSRNiYjVFWAoRyqKpBVFWCogKpypKHCcq6qAmk9j+Gq7619Za1zZr0fpQlPEjpqWLPm7eHnS+/ZUzn13lfN6t9SWi9PQkYPrUlK1FxeXcLQenvi3S2ciou5lGfnkPB/f6XvozPVyoDiUiogUBSlhizNx7hyAQR2RUT0gcpS5IWTYCizvnlb39BNRqdfO/2YJ/uffpDrPvsXPe+8pVlj9Jt7t1sCAp2/L379erU4GADoftt4rvlwIYAlgVFeAV5hIS0eV1GaomoZKIoCgDSUY/ziz8jcs003drKLeeH89NouTGUVIAQjXpvHwN89bHf/kpISfrviNb47uIOxO3MQUlKphUqd4MZMDX3PlLhs7kFxAynPvEhlrnM2NOr8fPjZhZ3ofFv2JIGi2KJqGSiK0iTTDx+4JRjIvBDBnte2Ia2laZGSvU8tpORMJiNe+xMarbZO+wPnTvDEV/8m5dwxSirr37NfHe9Z5/ufYiT/rPQn+HyxS+av9fFyWjAAYCwp49zXm+jz4J1OG1NR7KECAkVRMB3bjvnID61+3byiEBIX77gSDNRy4o1PKE3PYsATD9Fv5TOUyebVKyjXC/48UcOdqd5M3u/ETX9WWg8Pp495eulqAmP7ow8OwC/KsWfJFaW51FMGitLJyYILmP73n1a/bkWVNzvfOoi50tBgm6y1W9hyy8ME5bWsOmCRt4ZPxniCr2OZ25oSfn0Cl2zkCmipi1t28/3195P4i/nk7NqH+aqASWJC4li+A0VpigoIFKUTk6YqjN+9Ztks2MqOJHpQmWPfUvuEYy2vZig1gk+HCYS+5Z/ohU5H+PUJriuuJCXG0jIufP8Tm8feS+m51Uh2IDmI5BJQBJx0zbWVTksFBIrSmRVcRF5sWV785qio8uLM6j12t5+yv5wB2S0PCr6L8+LJmd4cim5+vgKvLmGWJwq2JzuWp7iZ9CGBeHcLAKqAy8BhIBXwbLSfojhKBQSK0olJU8PL9a5kNHsgTSaH+szZ75xr5wRoWXiLnhen+VHQzd/h/n79elJ8/LRzJmMHQ24BJ/9jK3gyIGnZrRRFqU0FBIrSicnMI+6egt16p5fQPd+xIKIxx7p7MH+CBvy86xzXhwYROmoooWOGofHU1+tXVeiapxUa493dVuBSCGQiaVmGR0WppgICRenEzGcPuHsKDvGtdO4SfZ6fhndG1c3+Fzgkhtykg+TuOYBv7+54BNZ9My48fBLfqB5OnUdjQkcPpOddjaUrTkGyE0nrrVooHZMKCBSlk5JmEzKr/awQAPy/JPAyODco2NFfT2Yvv1pHroxffCKdwNiY+p0keFtLL7tanzmjEZqGflWHIhgFDAYuI2leYSVFARUQKEqnZUlJ3PpPF7REaFYxM/dWOndQIVgx8EoQcHWBooqLl+t1Kc3Iwrd3N8LGjXTuXGzwCGrsUckzSC4Cp4BSIAvJIZfPSemYVECgKJ2UPHfQjRdvfteoYuf/2krqq2fFaMtegvyUwwQM7ldzzlRm2bjn06s7gUOi8YnsitbLk8u7Urm8I4WAQf3QBTi+OdFehxasJz81q4GzhcARoPa+hpx6OQokZiQX1X4DpVEqIFCUTsqd+weMpubnAhiUXkFUjvOLK60a4cXH47ypDPPjD9EX+Wq0N8Lbk8rcAsKuHY40Gik8fJKyzAuYKq6sUhQdPUVQbLTT51Ot+MQ5Dr3wvYO9DiC5jMSI5DKwE0vgkOb8CSodhkpdrCidVRMljl2pqqoF1zaZ+NkhE6/d5PxfX5tjvdg8RIIQHO/uwc4YE2+srODyrtRG+13elYo+NAhDboHT5wRwadtRpNncyF6CqxkBWytAF5DEINRnQcUG9a9CUTopTV+bBc9ahbFKNN2oESPOSzRmFyUFEnXnJkXTc9UHB6APCnDNfLDkIri8O8MJI7Xsv7vSsamAQFE6KXcGBFe/6TrcvbicvjnOy0lg8xpS8vfNEsqb3sSoDw6k5JRrK0VmrnLGEyF91OqA0iD1L0NROqvALqBzT/pbZ9yt8K1wbdrg0BIzvpeaTkIUMLify4MBgMxVe5EtTpV8DolrAyml/VIBgaJ0ViV5YHTyI3x2Ei15zMBqVKZr3tjCik2MO17JL/bYN75XeIhL5nG1klNZFBw838JRKoHdSK6unmhGUtrCsZX2Tm0qVJROSpbaV2nQFZwRENx0sJxNA3ScDXPur7GEM1U8+JMD+RkkeEd2pTzzglPnYUvW6qMED2tplkQDsAtJIJbHFk1UPwcqGYugfrpmpXNQKwSK0kkJ/zD3XVvjnM1tU484f5XA28Giipe2JaHzaSx5kPNc3OqsxwaNQK71a+3g7KiTxlfaIxUQKEpn5RMIHq3zRlafc+7/X3/KiF+5+5PtFJ9IJ3y86zdp5u4+jtnoyj0AeUjaV/ZKxXlUQKAonZQQAhHYOvn461/bOePISgM+Tqxt0KXAxJC85v1azNmWTPj4UQQM7Is++MojiOHjRxF+vXOCBVN5BcVpOU4Zq2Htq76F4jxqD4GidGZBXeGyM55vd4wQznsTl058tH70mSoGnSpH6HVIg+PZEHO2JdW89gjww6trWM2xwKH98QwJrNPeVGkgd/d+m2MNe3kW0Y+NwVhSScH+bLI3pqHRa512u6VhRUhKEPg13VTpUFRAoCidmPANdtLivaMXdt6b2riTVawaoXXKWMlRHkzM1PHyeEG/i0YmpQtiMirA5PgyfVVRCVVFJTXfFx6sX4nQPyYKz7AQKi/n1TsXPKI7niG+eIb44tsrhB53DHF4Ds2XByog6HRUQKAonVlF08/Zt3XXXdCxykljZQdreeIOy+uLgVp+6g8eRg/Cis2MPlPFrETn3l8vTksHIDh+EEVpGZhKygAY/Oc76XqLjbLLrUIDRLrp2oo7qT0EitKJyVLX5N5vSoBPIeP+fBMhcS1/0+txvgwPo+vWOap0guxgLUVerluqz993lICY3qC1rHSYK41odM5Z9XCcGShpspXS8aiAQFE6KfPJPchM92wg89BW0TUsB9+ugU03boI0muid6/rse/6Vrr25kr/vKKGjYhE6HVofd+cCSEGyHclRVTK5E1EBgaJ0QuYLaRjXv46zHv9zt1+mSLoWOCEoMJhgcxp8mmr5argy5mU/1/+6zN29n8Ah0fhFBbn8Wk0zAheAH63BwV4kBndPSnEhFRAoSicjCy9iXLMQjB3nl3vkRQP5vi38dWYw4b8ymYEeeTzzeCUDPfLwX5lcExSc6NI6S/gF+49RcsZ9WSRtM2LJapjt7okoLqQCAkVpJkv+90x3T8NhpsNboKzQ3dNwquM9PKj0aOE9/h9P070rHDgAixZZvnbvajkOUOTder8uyzLb6t+Pr7snoLiQCggUxQGSw0gKkeQAO6EdBgTCydkJTWbJt4ez+fumo3x7OBuTuenbEFJKLheGUXDSOfn/oy9LFn9jZPE3RkJKmnnP+2Ix06aBh4flWw8PmDbNchzAoAOhd/2DWf3m3sLwRVOa1ddkMrFu3S5efPET1q3bhakZj0s2zAuB+9JdK66nHjtUFIdcsv6pZkSSCAxA0PgGOYm5bdSi13s7bSiTWXL3JzvINucx8VYTL63X8kFyCMsfHIe2kQQ6Kdv8SV+z1Wnz0BSVEVZked210I+85tzvl/DNN/Dyy5ZgoKoK1q6lZpvF0EzHExU5KmBgbxKW/AyN1vH5m0wmfjbjGbKyjjFxUgV/e96L994dyNer/oFW64zbHRVI8hEEO2EspS2y61+dECJdCHFQCJEqhEi2HosTQuyyHv9GCBFwVZ9eQogSIcQfah3bKoQ4bh0nVQgRYT3uKYT4UghxUgixRwgRVavPHCFEmvXPnFrH+1jbpln7untbrtLBWFYC0pGUIMlAsqeBlqXAXuvGqx+R/IBkK5JUJGlIDEjOAmlIjEjykWRZzx1CtvZ9WSeuEGw4eoFscx67U0y8sgh2p5g4b8pjw9GGP/mXGXzJWJfU4PmWGp3RzE/FwpIvacwY+NOfLF811t+QT2ytZN63Jc3KXuiIPg9f26xgAGD9+kSyso6xe3c5ryyU7N5dTmbmUdavT3TiDE85cSylrXHkX95NUsrhUsrqpNzvA/OklEOBVcAfr2r/b2C9jXHut44zXEpZ/VHr50C+lDLa2m8RgBAiBHgeGAOMBp4XQlSHp4uAf0spY4B86xiK4hSSYmAvcAZIAk4DZU30MkLNI1oSyz/LTCy3Fk4B54HtQCpwwnouBziGpG6de4nr8gMIJ64Q7M8qYOKtpjrL7JNuM3HgfMP3wNNPeCOdupRtsa+/D/93iy+7+jTz03AXf8xmeO458PW1fDWZIM7sy5hjTf3dO4df3+Z/+t637yQTbiln40Z48UXYuBFumVhBaupJJ86wwoljKW1NS9YvBwDbrK83A3dVnxBC3InlN+hhO8eaDiy1vl4BTBBCCGAysFlKmSelzLdeZ4r13M3Wtlj73tmCn0VRrtLaVQCPI9ljXYlIBfYh+cn6HHhuoz0lDr65OjEgiOsRxOb1WqqsJYOrqmDTd1qGdbd9+8RsFpzZYO+vBfsJb09evdmT3dF6jnfzaN4gN/Tl/AWYNw+Kiy1fL2XD78pDnTvZRhQeudR0owYMG9aXZUs1PP88lJXB88/DsqWCoUP7OnGGVUja6oZHpaXsDQgksEkIkSKE+KX12CFgmvX13UBPACGEL/AssKCBsT6y3i6Yb31jB+gBnAOQUlY/3xJa+7hVpvVYKFBgbVv7uKI4SaobrlmOJY6ufuSsEstz4AeQ7ERyDkkykhTAEghIdgPb6tx2kFxq/OkHJ94ymDKoK900IYwZoWXeszBmhJbu2hCmDOpar62UkgOJAZSfd361vuIAJ9wx1GspviuB48YQFr+hJ/hkEP8u7oee1ssYmPFZIpV5pc3qK4CQENi9GxYutHwNCRE4P79i/ZoMSsdg76bCsVLK89Z7/puFEMeAR4E3hBDPAWuhJmPFAixL+SWifgGT+6WUWUIIf2Al8CCwDGz+m5XNOF6PNYD5JUCvXr0a+REVpTZ31IRvbHe+Abiy9GsJCkq4covimHUloT/VC3OVxrOsPZNKRnEaPf2iuaXXTEK9ulB14aTT3iS0GsHyB8ex4egFDhwsZP6YQKYM6mpzQ+HRw+Gc/Gqrk65c18ZeRpyxR7pLGXQZ0Jt5GRUuua3RlOIT5zj7xX5ifn2dw333HzjNtGnyqqckJAcOnmba9LFOnGUJkjIEPk4cU2kL7Po/SEp53vr1khBiFTBaSvkqMAlACNEfmGptPgaYKYT4BxAEmIUQFVLKN6WUWdZxioUQn2HZF7AMyyf8nkCmEEIHBGIpt5UJ3FhrKpHAVuAyECSE0FlXCSLhqpuwV+b+LvAuQEJCQsdIy6a4lCVVa+u/GTimyMaxHOsfCzPFnCiwlNY9WXiAkwcPoBMe9Knyder9Na1GMHVIN6YO6dZgm/M5ERz5cIsTr1rXzn4O3iaQkvBiM1VaQUGthEaxWUZ+kWJG+HhjLHJPPn/PiOZVGYyPj+Zvz3vx4ovlNU9JbNrkyYIXop08QwC1h7sjavKWgRDC1/qJvvp2wCTgUK0nBDTAX4ElAFLK66WUUVLKKOB14O9SyjeFEDohRJi1jwdwO5bbDmBZYah+gmAmsEVKKYGNwCQhRLB1M+EkYKP13A/Wtlj7rmnBfwdFqaV+Kdr2yEunx9+jbiIZo6zitK64VbPTlxt8SF6S7LLxi7v6czHI/mX9hDMGPl5u5PXPivj792Y8q658Tggrk5jKKggcHO3UEs2OyN9n87NNk269dTQ9egxkzBgv5v1JMGaMF5GRg7j11tFOnmEYQj2x3iHZs4egC7BDCLEfSAS+lVJuAO4VQpwAjmH5dP5RE+N4AhuFEAew3KDNAt6znvsACBVCnAR+D8wDkFLmAS9i2eadBLxgPQaWfQq/t/YJtY6hKE6Q5e4JOM3MmPpLzyZMbI3v1yrXl2ZIXleOId/WioZzbOzZ9KOA3QpMzE6sYHZiBU/uknjkWT79B2YX8+Q2A55Vkv7ZRm5PswQBubtTCRo6wGVzbkxpRvPSFmu1Wr5e9Q8WvDAfX9+HWfDCfCfmIKjNXWWZFVcTlg/bnUNCQoJMTnbdJxWlY7DkDGiN560FrVFcaNnRLWSW1N29LtDw2z15eFW59rn6I4fCOPLhVpdeY+lYbzYNrb9RUpglf9tcRfQlE6LK2HgOASHgqt+FYWNHcHnnXmdPt0ldJ47gxo2/wMYerDYgAMFId09CaQEhREqt9AF1tIG0aYrStgh6YXvfqnOv0lqVBh8YcCO+HnU3gEnMbBrRx6XXvZQXxpGPfnTpNQBmndAibKRL/tneSqLPlEJpRdMJhWx8MLq8cy+ho4fh1aX1HjsEuLB5L1tvfZ+Df9tM0fGLrXrtpqnVgY5MBQSKYpOr36xbb2VOo9EwMrz+s+gnPAoo9XLN5jApJQdWnbX5Ruts3jklXHOqqs6x649X8rPklj8pkpt4AGNpOeHjbX6gcpkLG1M4tGAlx17b0arXbVxXBAFNN1PaLRUQKEoncE23gVz9RLpE8v3w3i653qX8CAoOn3bJ2Lbce9qTsGITfuVmfrW9kse2Ou+xUWNJGTnbkgkcEo1PVHenjWsPz9C2Ul3QD8Egd09CcTG1VVRRbGq9Jf3WoNPo8NZ5Umasm3r2tK7Y6dcymrQcWnPW6ePaogvwI3j4IHT7jrD401KE3gNpqGq6YzMUHj6J1tuLsOviufzTPpdc42r60LbwrL8HqH0DnYJaIVCUq0gu4tpgwD2bxW6KHFbvmBEjR/pGNtrPiLD7MUWzWbBnHeQfbJ0iOAED+pCzLQljsSW7n6uCgWqm8gou70oldHT9/5aO0no3nTHSM9R5aaabRwAJbaNKp+JyaoVAUahORnQOOIulSJFrr+YOceF92X3hOLkVdXPRb+0hGNzA6n653oP/jAkjQHrx6I4zNtuUeuk53yWEnABv0suM+J10XSXD2oTewy3ZBJGS3MQDhI9PIGd7isP7JPyiujPyof4E+xewZ50k+8f9V04KgX/fHpirjBjLKvAMc/0tA7PZDBnnkEUlYDYjL+Uicy6DRoPw64IIyUJ06YvoNwqNRr1ldGTqb1fp9CzBwA7syU5oMBh4+aVP2bHzEOPGxvKXv96PXt8+srYtO7qlXjAAUCrL+de4CCQSgcBXeKFDQxkGKqUBZBUSzzp9jELDt2P6cVJXiBkzliCqGAJB8/4AQvb3Ify9TCpOuaa0s9DpCIqNIX/vEZeMb4+cbckEjxhM0Yl0TCX2V0Mc+VB/woMuA3DdHXC8/02UXCqn6wAfwkML8fSorGkrdM5JkmVOO435aBry8mWorLSUcTSb0M65D9PGHyDrnM1+8uJ55Cnr7RGNFu34OWjjp9psq7R/Kg+BogCS7TS1MmAwGOgfMxMfnxKmTYO1a6GszI8TaSvsDArcuy9hUfJyTLJ5n6j9hQ+PbbfsC9g3oBfbIqowyMaX572PleOZd+Xn9Sg2E/ZJNhUnWpb4yTM0GP8BUa12H78pfn17YjJUUZ55wa72wUP7cd39oXjr7QsiNNeNRzN6qF15CcwnTmLefwR58SIYDaDVWVYwTA382w6NgLwch1Y5RPQ1aGMnYEpPRR7ZAmYTePlDQDjCLxSZcwa0HmivuQdtzBi7x1VaR2N5CFRAoCiA5CCWEhkNe/65j1i+/BMOHKAmV/zQoTBr1oMseOGR1ploCyxM+hLZzIBEh45xeV4cDtGQY7OOgp2MZnp+VYrHW/uRDiZFCh+fQNm5C5SeaaSSo5voQ4Pw69uVvKRjdrWPnDiSa26tbLqhlWb4aDQ3jrIZFJgv5WDelYzMOAsm1+6hcJjeGzFwPNpxD6DxbAsbJJXGAgJ1y0BRAOyo3LZj5yGmTaNONbnp02HnT4ca71iHe1YJjGZjs4MBsGw+3BrihGI/Og3n7vPHL3Yk4XP3NNxOoyF83EiQElNFJaVnMi2P/rkpnXBjes68htjnJ+IfE0HiL74i/ZPtTfbJ+t8+yieMxFtv3+OR5tRE8PdDmzAY87E0TEmpUFYKlRUNf/pvCwzlyAMbMR7YBF36oRt3P5peLd+QqbiGCggUBYCKJluMGxvL8uX7eOmlKysEa9bArFmxrTC/ljmW17Y+VZcM86bnDQOo+PF4neNaH2/8+vVEHxxIzrb6mxP1wQGWzW46rcufKGiMZ1gQve4ZRd9HRxEy4kpZ9WuX3U/U/fHs/d1qio41/OilNJs5n+lPv77250sw7/wRWVyITE1p0dzdQ8LFkxhXLgDvQHQPvY7GRyU5amvULQOlU7NsKDwANF1QpnoPgbd3CdOnW4KB8nJH9hC4z7dnkth/uXUeBbRXr2VFaN+sVStAqyVgQBRFRxqZp7XmQMiooeQlHXTJvEJG9Wfo3ybh3SOIvJRznHp3N/mpZ0BKRi25j8DYbgTFRaLVN/x5qiwzn+9iX6aq8MqqSvDQfsTf1QOdzkxWuo7e0WX42LmPoIaXP1Q4P3dEa9KMn4Nu5DR3T6PTUrcMFKVBuwH77uXq9XpOpK3g5Zc+ZedPh5g1D99yKwAAIABJREFUq/08ZZBTXv/pAnerCtBQuw5f+LXDydnRxKdf6weYsrPNKxFcm8ZTT/jYAaCxPGMfNLQr3SYPoMstA9FoLceC4yLp9+i1mE1mDLkleEXY96nWJzKYaz95iG3T3wEpCYrty81zvBAay1MDAYObMWGtDiodDCDaEqFBe/sf0EarjYZtlQoIlE7O4FBrvV7fLjYQXq2gstTdU6ghKk2Eby0nZHMh+mED0Pl6c3lXqkNjVF4uwDMshMrL9j+W5xfdm5CESDzDfNAHe9Nv7jX49gqxq69Gq7E7GKjW445hJLx9P8mP/5eqojLs2afSKA/v9rs6ENwd3a1PoelSv6aG0naogEDp5DrHLbNKk2OBT3MZDUa2frSPs/sv0iuuCzc+Eo/uqqV1TbEJ/5cPUlZRSfXnXd++kRQds7/2gTSZ8IwIwTMsqNF+QqcjdMwwKi/lUpyWwXWfziZ0tGurPNYW89g4fHoEcPyNnVRJLXoHA9AagV2gsK1VPnSAoVwFA+2AykepKK3CvbXtzdLe5MPNZzQYeWvWf7mwcx8zbz7PhZ37eGvWfzFeVXrYFKZHzq5bKKf0dCaVl5vex1Fb0ZGTeAT62zwn9B6EjxuJZ3gwl3fupTgtAwCz0fX/Ha7W445h3LTpcfTaThoMgCUngtLmqYBA6ZQkZiTOyQJn7xXdJb+ipEWPHNpr60f7CA0wcOAALFoEBw5AiL+BrR/tQ5QZwWAGk0R3sRKzp3MCpKtvGfhEdSd8fAI6by9ydqRQkZ1T57x0Q0AAIPOa+chmQAcIBpR2Q90yUDodSTmQhD2pip3HfVkKt2Tub7qRE5zdf5GZNvI0rPj+Av03HMOQ1Xjip+YoOZ1J2HXxCJ0OQ14BhYfSKEtveMPh7jmfog/xQ+utR+ulI+bxa+l5V7zT51WHBNPGTY73C4iAog4SDFSWUrX1QzxufNTdM1EaoQICpVORlALJYHf9Pudd2R1BwenCCxzPt52n3tl6xXVh7drz9fI09LquK5q9fuCCgAApHUphXJp+gdL0K9+bDSaXBwRSAhfteyrCZJZsOHqB/VkFxPXOZUpMCFqNe283Ocv/Z++846Oq8v7/PnNnJr0XSAKB0HuHiBQ7gihYWXeRVddddVfdvpZHsVBWcd31UR9/a0esu6IgqIBgpZfQQzGkQSrpfSYzc+/5/TEJScgkmZnMJEHn/XrxIrlzT5nkZs7nfM+3yJxj3T0FHx3gOzLw8ZNBUo3dMtA9ZuPusBBkVnqnuJAjLr1zPKVVRkaPhocesqd1Lqs2culd4ym9KbrL5uEKlgovh/FJsH3+pVO3qprklne3s2zvXsxjT7Bs53ZueXc7qvYjcHzVG9Ff/uvunoWPDvAJAh8/CSTlwH5+KlEFAN/nHmXf2bQuG09v1HPfR7cRN308H38dT9/ho3n65vn02lFPdX/FnlSohxHcP8prfUsJ1u37IOOUU/dvOlFIgVbG7v0qzzwDu/er5KtlbDrhXNGkHkvvwejveQtdwvCO7/XRrfiODHowEhV7BT6JwL+7p3PBIrEBh+leMdB1xwU1FjPrMndzurrrFxK9Uc+V90xmyNxDWPdXAIcJAHpaktqQoX1JWjSJoX+6zHOdSpBWDVlrRtaZ0DZ8ATXOF4I6nFfBVXPUFj4Ys65ROXK0krkj4zw3T28SHmd3gmyIatFNuA79JXd075x8OI1PEPRAJBlALk2m7V6AO6nNfNhJo/stA10z/qbsFA4Up3fJWG3R67MarMUV3TqH9gjsG8vcE//jVDlhV9Bq6lHfeN3t9mMTwlm2Uc/SZbZzPhibNygsTg7z4Cy9hxhzNYYr7karLsW2dikiur9PDFxg+ARBj8RCy3PuoO6ayAWPzWbmHwdfYlBYPAB9gqO5KH5YN8zE+xaC3OrirhMDUqLPr8e/WMNQ0/S+grNV9C8eaKdh9yN0Oo+LAQB1v/POjY6YPX4gb6akkzyhjFnXqGzeoBCvRDJ7eG8PzdC7CL3dtKELicL4y//t5tn4cAefIOiRnB8O5xME7qLX+6PoDKRV2qv9pVXmougEk3u7V0Y3rSyXb3IP0yswghsGXezJqZ7DYrGwfNn7bN+RyvRpztVLKDVV8d9T270yn0Z0lVbCD1uIPGBB+S4Xo38gNZldE8HgSeJme8nalp3lfludgqKprF40nU0nCjlytJLFyWHMHt77gokykBdynQUfgK/aYY/B7i+QA5QA5+crn+rzIegENpuN5w79AVU2ZczToSMqIJRAxY9AvRGrVLGqKhbNhk2qqJoGSEw2CxbNitpOpj+BYHLsEK7s1174mnMWApPJxMABNxEWZmb+fFi/Hurq2q+oeLz0NOsyd3st+ZAx20zCpnp0HxxHM9sLQSn+fkRMGOFSyF9PIHnlHSTdnuwVC4H1rXeh0s0iUoFhUNfzClA5hRCIAZNQrv0rOp1vj9nT8VU7vCCoARztMBTAr4vn8uOi1FxAsCGMSkvpuWsaGsUmz5xzSyR7i35gX1EaNw2cxpDIPg7v6ghVVZk44VeEh5s5csTuVLZsGYweXcPyZe87LKr0acZujpdld/5NOMA/w0y/D2qwfJYKtDzEipwyBtVk8sq43iJy8hCviQGp4b4YCOsNlRdoJEHsAPQ3P4XOr5OFm3z0CHyCoMfQVmrTAEQ358G/UCmqzeetE8tbWAa8iUTyccZ2Rpb3Y/7AqS6337hxL2Vlxdx5Z+tsfzt2pra6f23GLk6UnXbYlzHXzMB/lFC4IILyac4fOekqLCSuMROwtxzzgaw2S/FIq42yfamEDh9I1YkMp/v3JDqDnqip46gvqUCzWtEHBaL4+9lLF+t02GrqKD943H6vn5FRi6/0jhiQYHvnQ/c7qPFCwqauIDAM/c+f9lkFfkT4fpM9hrbKmtYjkT5R4CKHirbzxel3u2XsY2WnubLvBIKMrll2Dh5MZ8YMjS1bYOnSpmx/n34KP/vZqHP3aZrGhuyUNsVAwIk6+v4lDXNJBeHDx1MxUUX6K003aBJ0An2xhfiNZnIWBCH9FQKPm+jz5xNYy6owdzBXS4U9nK6t4kKOCB02AHNRKZYyz5jGo5LHUry1/SPAsFGDCR0ez/jnrna61LErSAm2D9dAeWnHNzsiKAJqXSvq1CPwC0L/i3/4xMCPDN9vs8fQliCwAvXg8yFwisPFO/ki+11kt2UjtLPv7A9c2neMS23Gjx/Ep2v9iI+vJzkZZs2yi4GqKn8efWwhAGabhZXHv6K83kF8uyYJSDPT/5kCzCX24xDdB8fpv9JC0VuTqR0ZiKhXGfL3MoquCCT6qWPYqusY9F4wqBq26jqsTswzZuakcwtx+f5UjBGhWModx9uHjhiEEuBHXU4BVScziUoeS+ke12orxEyfCEJQeTwdS6n9fYUOG0Dx9v0dtq1MPUWfG4Z7RQwAaFn5Tqcl/tHQayD6BcvQ6dt3dPVx4eETBD0A++JV284d1fgEQcdsOb2avUVfdfc0AEivzHNZEMyZM4XXXxtBTs5xBg6sZ+VKHZGRMWRkvoXRaKTaUserRzdh0Rwb8uPX1OD37P4Wu/tGJ8A+j2YgRscijxRhKSglfKM95RWArcL5SnyxMydTtHVfU/9WG2GjhzjcqUdfPJ6ylFQ0i11mCL2emuw8p8cC8IuJpHTfUbR6CygKMTMmUXH45Lk+O0QIkhZNdGlMp5GgrVvjfvvw3lBxYfkOiLGzMVz+m+6ehg8v4RMEPYJa2nc6qwZiumguFyabsv/D/uJvu3sa54gPcj0lrqIorFn7LBs37uXQoXRuv2MQc+ZMQVEU6mz1vJ76pWMxICVx62rx/9fhNp8iS34p5Ltp1m4gZsakFmKgkfqiMpTAANQ6U+MbIWbquFY7+IDe0dTlurYAhg0f2DSmqlK8LQVDeKhT4Y4B8dEM+f0lhAzu5dKYziItnaiWGRR5YYkBoUO55k8oQ7wTauujZ+ATBD2Cto4LnH39p82GrPc5WLK1u6fRgln93NuVKorCtddO5dprm5wSaywmXk3dSL3q2DIw+F0Ttv9L8Wrao5jpEyne5vi8vupkJiGD+1OdmYMxLJjAPr0dmvPryytBUUB1biENHtCX4l2twxqtFR2nA45KHsoV39+P4mdwaix30PLcLE2sU8DsfErjbkfo0P98BbpeA7p7Jj68jK+4UY+gIyeraq/FmF/o9EQxAKAIz/1pZVedbSUGYgIiuDhuBH8efyO9crz7bATEx1Ka0jrKoTnVp7KJHD8czWKl4sgPDu9Ra03EXDzOqTF1fvbzaWl1L0Lkond+4V0xUGt1/7ggMAzUrol86TwC/Y2P+8TATwSfhaCbsfsPdORlbMWeztiXj6A5ewu/6ZFiwNP0D20yeeuEjunxI5keP/LcNUOod/1LAuJiMeUXdXhfWQeiAcBW11H8gp3QYQOoOHzSqXsdEZzkhXLLEqQqUTPOIDd85l4fF5jfgHLFb9Alju7uafjoInyCoBuxi4FD2KMIOuIYkiQg3BeCCGRVnmBLzn+7exptYtNUDIpn/ryCjQHcNfJqNKkR5R+G8bx+heK95yFm5mSKHfgNuEt9iXMhdobQYLfH8IuNQGdQWlxzJx10CyTYTp1BfrHe7XkBYLtQLAN2tPS9KGOu7u5p+OgifEcG3UoRHR8XNFKJXTwcRFL2kz5CUOstrP9oeXdPo13eTN2EJ9OC9wqMIC4oqpUYALxSM8m/VzSRk0d5VAwAmPI6tjR0luCk2BbfWywWhgy+mdWr32XypIOsXv0uQwbfjMXSVtqllkgJtgPHOi8GAHQX1keuPH0YreYCzJPgwy0urKfzR4R9Qc91o2UlcBg4gKTkJykMctZsptcDhzEe77mOWRbVCl1gyTEVVpL32SGP9ukXE4lqrqdsX8dHAK4ibTb8YzvOCeCsJcERSXdMbvH98mXvExhYw5EjsGIFHDkCAQH2dNBOYdGQWz0UweKFTIneRaJuebm7J+Gji/AJgm6jjs5FD1QBR4EUJMU/KWFQnZaNVm+h36PZGDKcj6HvShYOv6JLPvtTl2zGUuZZYRTULx5rpfciW/QdZDc0Roa5nQ458WdTGXzv9BbXtu9IZd4859JBO0JN70QVw1ZcaIIAZPYhrOuexvrtW909FR9exicIuglBEDCGzpc2rgFSgX1Iin4SwqA63Z6y15ZXRp+FBwje6H0ztCuMiUoi0j/U6+NITSN3jWerDcbMnOyUc6BTCEH/X05j+pp7uGr3QwTER5+73h4hQ5LcHjJhXuvSxtOnjWL9ensaaLD/v24dTLt4VKt7z0faJHLzRrfn04oLTw8AEpmZgjz6JZrWvRlAfXgXn1NhNyKIQhIBFGCvdOhk9jWH1ALHgMCGPoMRxHtglj2P6lPNcvhrGjFPnsCS6I9lZOcXYYvJwpplW8k7VkzCyBhufGwmxgDXUrTGBoR3iXWgdG825rNlHusvZGhSm7kGXCUwMZbJr/6M+NlN0RBXH3iQ3LWHSH91b7ttFaN74YKzDz1GxNjWlSYffWwhq1atZfToGubPt4sBkyn4XDro9lBPZbs1F4cER11QEQatUG1oKZ+im3Jjd8/Eh5fwWQi6GYEOQQKey0RYB+QBp5DnlaixOyN2IrtaD6GFIACQEmNW50vxmmvMPHfN2xQezOSyi6qxnsnkhetXYTE553zWSHZ113zoVxwp8Fhfir+fvRJgJxwhhU5H4q0XccXWvzAv68kWYgAgoFcog++dyeB7kwEI7BvLgF/NYOgfr2pxn2p1XRiHjxngUAwAGI1G0k59zIIFi0jZP54FCxaRdupj56IM3NwRq5rki2MF/H3zCb44VoCqSfBQ1InT43kBLaN9MefjwsZnIegxVHi4Pw04gWQcYALSgVKgDzDYw2N1DbVn8jn0yD+xlLX+WfV6Jh2dClXz3UtTq6kar/7yIxL72s+Xt2yBQYNASsmaZVu5dfmVTveVXlmAqmkI0RggKtq0GJSmnKbuTBmWCjNZq1KQ1paCzS86mJGLryRqcv9WbQPiPXcsET52KKV7jrjVVh8SyMC7pjHkgZkED+hY2A749TQSF0zAEB6IEAJrlYmsd/aQ+LOJ9Jk/iqz3DlC6y7U59J41tN3XjUYjTy2507VOAWE0unwIp2qSW97dToFWxlVzVJZtVHgzJZLV912P0nFzl2lzvEXTUXQeNlVpF/6GwkfbOCUIhBDZ2D3gVMAmpZwkhBgLvAIEA9nAQillVbM2icBx4Ekp5XMN1yYCbwMBwAbgD1JKKYTwA94BJmJftX4mpcxuaHM78FhDt8uklKsaricB/wEigQPAIimla1u5HoKkHvvO3tNUYA9VrKQpNi0XSSQC13PtdxfW6hqOP/M6J/+1EtXsOGeDZrEStfwExrMWSu7u6/IYaTtziAgyc+SI3els6VJIToZRo+DbPcUu97di/0fnvh4Q2psFg2ag1VvRrBJDiB8lu7NIe3E7Z/7b8cqX91kKCfMmMerJWUSOTzx3Pai/Zyr4Na9e6Ap+sREM/eOlDP7dTIxhAU630yk6jBFNvjOG0ADmnV6CIdieYKm+rI7T7+1wuj+hKAy+b5rzE3cB3aC+aNGxUOK8n8qmE4UUaGXs3q/an6VlKskTyti0J5W5EwZDvWcdYdsc70Qhc0fGeXQsnyD4cePKkcFlUspxUspJDd+/ATwspRwNrAX+dt79zwPne+P8G7gb+xZ1MDC74fpdQLmUclBDuxUAQohI4AkgGZgCPCGEiGhoswJ4Xko5GHuqv7tceC89DG/G+VbQOlC9ZznhtUfRthQ+GzKbY39/pU0x0JyQNzII/9D1crQFaaXMn9/SE33WLNi6FRJGdO44pzY/l7o336PiXx/zSfif+I/+Pr6a9g+nxEAjeetT+HLi0+z+1YfUl9gXlNBhvVH8O5e9MnRoEsU7XHNMNEaEMHbFjczLeoqRj1ztkhhoi0YxANDvZxPpdUXHDn+NDPn9lQT390JmQuz+j8rNN7jU5nBeBVfNUVs+S9eoHMmvBOn5BbXd8TyN7YLcc/lwks74EAwFGvPGbgFuanxBCHE9kIndy63xWhwQKqXcJe0ZW94Brm94eT6wquHrj4ErhBACuBrYIqUsk1KWN4wzu+G1yxvupaFtY18XIJ0XBEVb8zn5fAoH/rSZ7Td/yM6FH3Pin22d97m+g+4uMt9eg7nQtR16xPNpRK7Kc+k8PG5IFBu/1LfwRP/0U6gzwY2PzXRpfKQktsbGzDMWfnvEyi8PVeBXW01oYDmT/nQFgxdMQyhuGI+lJGvl92ya8CxHn9hA8bZ0wkb3c72fZiiBAU4XG4qeOpRJL/+c6zKfYsSDs9AHuuZs6SxCp+OiVQubohLaodcVYxj37DyvzOPcfPxdc3IcmxDOlo1Ki2dp8waFMfFhYDFBmGerL7Y7nqepdt1a5uPCwVkfAglsFkJI4FUp5WvYY93mAeuAW2hYZYQQQcBDwFXAX5v1kUDLTDy5DdcaX8sBkFLahBCVQFTz6+e1iQIqpJQ2B321QAhxN3arBImJiY5u6VbsYYLuC4KarGr23bOawi2tF//60mSG/2XKeVdjEbifFrarKfrevUx5YS+fwlCmcvYPfcGJc9QhF/fl0PpYxk8q4prZNtZ9CuV1/vz5swVORRn4WzWGllpJqtHRr0rDWNc6jl8IQf++Z6EvnD2QQNWpM269t7qcIlKXrIcl0HvWRW71AfZyxh1FFYQMSSBm+gD63jyW+DnO79o7S2BCBNekPsJ3s1+hdO8ph/dETBjEjDV3otN742TefWYP782bKZEkTyhj1jUqmzcoxCuRzB7e235D5VkIifHY4trheJ5EtaGV5aGLdPhx6+MCx1lBME1KmS+EiAW2CCFOAr8CXhRCPA6sx159B+Ap7Kb8GtHSk8rRp7Ls4DVXr7e+aBcvrwFMmjSpBwbpm3CuloFj/KL8qMlwbCIPTGg8Y44CooFIBN4thONJ8jdtpSbDvUUTIPDDTBKqVPL/1hcZ2P6jrlN0LHjmGtJ25nAgrZQp90Qx5OK+6JT2jWh6VXLFGRujC+sQqvPe8YFx4W4LguYUbt5NzIxJVGecwexEAaJGoi4a16EYCBuZyOXfPoB/TPuJhLyFMSKIS764h4y3dlK66zTFOzOpL7KL5+BBCVy66R4MoZ0/rvA0ik6wetF0Np0o5MjRShYnhzF7eO+WDn4e9CNwajwPoqV+jW7mL73St4/uxSlBIKXMb/i/SAixFpjS4Cg4C0AIMQSY23B7MnCzEOJZIBzQhBBm4BPsLu6N9AEaV7Jc7BaGXCGEHggDyhquX3pem++AEiBcCKFvsBI07+sCo3PHBYZQI0P/NJf9D7za6jW7yTUOGIjAe6VgvYGlspq9v1nc6X6MX5xm0O4yzt6dYI9AaOdDUqfoGDajH8NmOGeG97dq3JamEVHu+lmtf3gAOoMezc3yvs0p3pYCQhAxYSTmIJX68gpEwymAqKzHlt/yGQsfN5zSfUfb7C/2spEM/eNM4ueO7lAQeRu/6GBGPDgLgOqMYlJ+t5qKw7nMXP/rbhMqzqDoBHNHxrXt1Gcxgd4PbO5vBlwaz4Nopw97fQwf3UOHgqDhCEAnpaxu+HoWsEQIEdsgEHTYowBeAZBSzmjW9kmgRkr5fw3fVwshLgL2AL8EXmq4dT1wO7ALuBn4piH64Evg780cCWcBjzS89m3Dvf9paLuuMz+IrkCSjj0oIwJxrpRx58INazKr0Ac7NmmXH8xBMKxT/XcXB/+6grpcz8Tz20qriXr6JDGfV1IyJ5TKeb3A2PmFbl6WRkS5e7+/SZfW4hd6MT+856HyzVJSfuAYppuTKPxny9+5MKnoi+rR55iI2FqNpVg69BsIH5vE+Ofm0fvK4Z6Zk4cJGRjDZV/+DqlpiAusSJBDgsLtxwcXGpWey3/ho2fhjIWgF7C2wfyvBz6QUm4SQvxBCHFfwz1rgJVO9PVbmsION9IUhfAm8K4QIh27ZeBWACllmRBiKdB4kLxEStmYmu0h4D9CiGXAwYY+eiwSE83dISRBQASdtRCo9Sp77nzJ4WsFm7ZhLi7DP8Yz4WldhaWymow3Vnu8X+1oAZFHC4hdXcqZR/tSP8Z9p6vYGhv9ijon5iL7eD4NiGJpfSomAxSs/QKx9gvEND2KfEDURGPMrsOQZya+OoiZc2cSM2MQ4gIovtPlYsBbB42VZyG894WXvVC5sKyNPpynw08kKWUmMNbB9ReAFzpo++R536cArTyTpJRm7I6Jjvp4C2hVVaNhXud7zPVgSs/7vrbhX+cIGx7BsL/dwsl/tF5Apapy+j9fMPSBRZ0epyvRB3rXz8GWVULCveVUL+pP2U2xqLGuhe75WzVuzOz8KhES4hlzcXN0Zucy68lgPfWjQqkfFUpkr2HEJl6Yyaq6BG96HlUUkh4XwaCCC6fEsP7a8yPMffxY+BHY3Xo+9nTBnXcga4txKy5n9uHlDLr3ulavpS79f9SezvPa2N5AZzCgBHhXFEibSvDKDPpdvxe/I675APSvsBJS1fkYb3+D5wWBvkJ1Of1wldUbSbG8i6qqfP75LpYufZfPP9+F6mTopDsIBfR/vB8muR/R0R7fJXW2wFnXIYbPRNe366JNfHQtPkHQJeTSmUiCjhBCEDEmir43jWn1Wn1xGd/P+y3Wms5bI7qKmswcRBc5s0mbSuKyHERNa+e+MLPKxbkWZmVZuOWUjTuP27j3qJU5pz2z+BgUEzqDh48N9ubR58lsUJ0XBaV1ni2f7G1UVeXGGx7kySeWUVf3Nk8+sYwbb3jQu6JAgC6pv8f7NRkNlOvMnIzpedESrQiOQpn1QHfPwocX8QkCLyOxAKc7vM+bVBz5gV2/fAjZw0uXWsor2XXHw3w25GpsNV23a7VllzBo4TH8Drb0CRhcZmNadhVj86rof7aC6LIKQior0Zs9MzchBH4xER3f6CKGjafxP+C8f0Op2bOpdL3Nxo17ycs7ye7dJp55WrJ7t4nc3BNs3Ojlwjte8K/Ij7WnEN8wNBRzD/40Fn1GYvzNa+h+DM6cPtrEV9zI62RDF1QYlFJybNmGNl/PXbuFo0++xJglf/D6XFwh462PMYQGE5gYz77fPkn5gWMdN/ICtoJyQvZGUj8+/Ny12C74hPa4haABLdD5ZD3h/q13pxaLheXL3mf7jlSmTxvFo48tdK46YBdw8GA6V80yt0zVe3U9hw6lc+21U7t3cm2wZ2QSRyMldViwSBuNjgkSu2VKReWjSXH8cm/P9OCXtReOj4MP9/EJAq9T0iWjCCEo2ZXa7j2pS/8fYaMG02/BNV0yp7aoOHaKnE++JGfNFioOn+zWuTRHMbU0s9fremAeKyfRgp3/0w41tjzDtlgsDBl8M4GBNcybB6tXH2TVqrXOlwz2MuPHD+LJJ/xZusSEwdCQqvdLP55aMsir42pu6sMvJg/iuF9Fh86JZ41W9vcNYWJO6yyX3U55Ppq5Bp3/hZPl1Ifr+Ow/XqfrFhUlsONzyIN/WeFUkSBv8v3cezj6xEs9SgwA6Ewtj1S+6Wfg64EhaIbOFRDqcoRAC3VeEJis9S38EJcve5/AwBqOHIEVK+DIEQgIqGH5sve9MNmWWCwWnnh8JVdc8ReeeHwlFkvrYjpz5kwhIWEYycn+PPyIIDnZnz59hjNnjneDjjL8zLwyI5HDQ5xPgf7lpAYx4CTf9vOnygM5MryBtveT7p6CDy/TM5+8HxVd50GsD+rYM78ut5BPYqdy4l8r0azOp9rtDJJqJJlIspGcJmZma+fHnoBibinepBAciPPjdKT3Ih7CB3s2s5y+dzgFL49Bi3B+J19gKmd7fuo5UbB9Ryrz5rWs/Dh/PuzY2b4FqrM0WiZWr36XyZMOsnr1uwwZfHMrUaAoCmvWPstTSxYTFHQHTy1ZzJq1z6K4UzDKlflpNqplHZtj6/hw2kBsDjKo24TS67XkAAAgAElEQVSOM3HR7B2ZxCcXDeKIv2u5KiSS/0z0Qg0CD6Cd8FASLR89Fp8g8DpeqDjWBvog5zyVbdW1HPzLM3xz5Z2o9V1RzvQMdsfKLCATv6ie+djp6h1bc2q9eLA28rIAjyXa0S7pS8Y7IzBPct1RcVt+Kpuy9yGlZPq0UaxfT4vqeevWwbSLvRtu5oplQlEUrr12Ko89tohrr53qdTEAYG1WqyJXVPJF8kAAjg/sw8rpSfzvjDienxbJfwfC9xHVZOrdS1xVqVjYNNw75Zw7RV0FWnF2d8/Chxfx+RB4nb7Yyyx4d+G1Vlupy3EtDWrR1n3su/cJBt69gPDRQzAEe8uaEQk0Fd4J6NN1IgkgdNgA/GIikQ1haUKvBynRbDak1UZZin3nq7N0fRRGaEAl/ecnk7V2V6f6USKCyXo6CfQdiwubxcZ3Kw9y5vBZEsf24tI7x6M36jlYkoFE8j+PLmTVqrWMHl3D/Pl2MWAyBfPoYws7NceO8KRlQkrp8ayLfkpLq8tZo5VPpg4iU6kAzB49HTwaBWemxhNklSxM6TmOhrbPn8N45/919zR8eImeuVX7ESHQA97PApf7aTqqyexyu8y317Dl4lvZcvGtmEvKOm7gIpJKmosBgGF/nsGEF27DENo1DkqGsBCKt6VQsvMgJTsPUrx1H8XbUijddYiylFRChw0getoEzt7sYGctJQO8HKYfndT5GPTaS6OdFgMvL3iPwh0HufnyfAp3HOTlBe9hs9i93Q+VZCIVQdqpj1mwYBEp+8ezYMGiLnEo9IRlojq9iFP/3srXM19EupigqSPiglqmAK+UtQ1iwDtUKhbKepr7SkUB6uEvu3sWPryEz0LQJURjr9jsPQfD2qxShF6PtLlXPa/iaBqnXv6A0U/c77E5SaqBA62uCyEY+vvp9Pv5WNJe2kX2e7upzfJesUqdsf3c61UnMwGIP+jPmTf9sQ5sspQkVNsIrG7KSqhqOgQSnQcjEHr1qkIJ8HdL0DVSO9w5P4fvVh4kKtTCkSP2HfiyZTB6tIXvVh7kynsmA5BZUcCI6ESeWnKn2/Nxh0cf65xlwmaysDn5OSxldgX3xbDl53IHTH3nF0RNSerU/EKMnRdubVln2kIVGhYdGHtQChH1+5WIkZeh03d/xIkPz+KzEHQJtXg72mDU49O5oeAfTHzxbrf7OPrkS6R7tKhQbruv+seEMGbJLK7LWMxlX/2FhPkXeSX5i7Opm7U6M31ebGmelQdqOHogkhPHotm9yY+1fzvKV69VYrV5rsCLv8HMgPmTO9WHNapjbW+z2Di04RTXXdfaLH/mSNNxU63N1Km5uIvRaDxnmdi7byyxsaMZMGAgy5e97zDaoDlSSo7/ffM5MQBQnZZL9Q85VP+Qw+kPD3V6fgZd5/wUOrLOOMJqs7LR4PnkVZ1CtaJubLeMjY8LFJ8g6BK6Jq7YLzqAIQ9MIG6O+znX9969mIyVngovci7fvxCC3lcMZuand3Bd+lIG/242Oj/P7D78oiIwnz2/sFTb6GpaJpEyZ9Xyw3tbOfbmd+Ru3g9SUpV2hrx8z35IJ43q3BZQC2sSKMKsEvviGYxpTc9d42IUrNSwYUNrs3zimF7n7q2zdV9YqtFo5NHHFpKZkUFx8VGmTDncZrRBI+aiKrZe+yrHln3eZr/1pZ7JLnll3wlut21unWl0mowMsVtnzqfXhhqG35XFoFkpWO/fjqnKPcuft5Dpu30Ohj9CfIKgS+ja1LCWsk6MJyV77nqUzFVrPTAT5+O1GwkeEM2kl69nXvZShj80H0N4SKdmEDyoL5oLkRQipxrlbJPp/vxkRY1YPewjGhpYSVCi++FmUm+3rAiTSv+/ZhL0Xib9/pqBUmRf3BsXo1OnYMAASE6GBx+EUaOgrNrIpXeOP9dXpH/nfuadxZVog/LDuWwc+wz5G9q3AAgn/Cs6QgiY1Mt9f6Azh886dJo8Z52Rkvi11Qy7+ThBSw5gPnoataYOpCQvo+d9VNs+e7a7p+DDw/S8p+xHhCQNyRGg69J+Vh4vp/zAD53rREp23/kIWe+t6+Rs3HdRCegdxrhn5nBD4d+Zse4BEm+dieJiWeSo5LGU7jniUhu1ooakP2US/WoOwqyimBzv3M2Vns/hMObnIzp1ZKIrtZD05wzYaz8isRVWkPCC/evGxcjfH9auhSVLYNcuKKoO5r6Pbmtxjh0bGO6w/67C2WgDzaqy+/b3MRd27AxrCPVu9UxnSBzby6HTZOKYXog6G0OXluD39H7qzxS1qjtSeMq150254m6IG+KpqTum8izqwS+8O4aPLsUnCLyEpAJ7uGEp0HWFenb87A3PJBySkt23P0z2B5+53LTyeDrpb6zm0CP/7vQ0FD8DfeaNZNqHv+DGohX0unycU+2iksdStt+9ughqehEhb2YQ9HUJSrVjQVByosjh9c6Q0KuI8OH9XW4nYsOp/LiEAb84gtzf0jlT2XKGkM/PtliMFAWuvhqKi2HcNYNbObWF+3VB9Ids+bWUIG0aUnM+2uDY8k1UHM5yajj/mEAPTdx9Lr1zPKVVRkaPhocegtGj7daZK68ZwbDf52D5vO3ntfyUC89bSDTKmKsRigeO3YQO/IIgsg9iwCR0U26C3k1WEnXbu2hazzrO8OE+vigDLyCpB47RlWmLG6lJb9+RzxWkprFr0YOo5noG3HFjhwl0pJTkrt3CrjsexlZdS8J1ycBMj81HH+RH/NwRnP2mYwcxoejcjrhoJOapE22+VnYkA7N1PP4GzzrghSRGUXHcuUUOnY6scbE8P9xEmKmCEeWOj4pi/p7GrfP78HiFgdGjrec8+Ctr/Hl/yf0MiEqgor6ar3NSOFtXjlHnnY8FKUGarajHf4Ct34HBaN/+17Uszf3w737ebrSBtcpExlu7SF3Sts9Ac6KShzLk95d45D0IBFf1nciWnP0ut9Ub9dz30W18t/IgH397lgEjo3g0cAjG245gNrXvtyE15z9LdCMutbcpdvI5EjowBkBQBCK8NyIqEV3cEEgY7rB2gTb5Bmz/vgM0GyJuKDovPS8+uh7fb9LDSDQgFW8nInKEarZ5vE6B1DT23PUox55+jWF/up3+C+dhDGt5xqya6ynde4SjT77E2W/3nLtujPT8rkwJdG7XI7ycuU7abGSlBTF8pIc98p08MvhhYm9eHVLH2bB6QEdpCFj7x2LIbr2TlDaVkE9O86+QEbw9ycrGbWZuvmU6ixf/4lxugXC/KH41Yjbbco+Ag5S8nUFK0ApK0P77n5YvWC0OnTH0H37IiW2v8/QbG9i5I5UFC5qqLdbllbNl6vPU5Ti/Y57075swhHjmyEAI6BfSq+Mb20Bv1HPlPZPptaGGwCdTgKMeroUq0E26wT7WTY9j++BhQDZb9MMRYb0R0f0QvQch+oxA56LPiM4YgG76bWipX6Hc9IRHZ++je/EJAo9zCvByJhsHaDaVrHfb3tG6i87PSOSkUaBppNy/lEMPPsfopx5g6B9vR9pUdt/xMGc+/tLhbty/l2sfNJ4suVt28DjGyDAsZc5FOrhD2uoUkoYM97iVoCPWXRLJR8PrgZaiZ9kEM0tLA9GqHR9RiWoTfzWP5/Ktv2HTpj2sWPFfxo8fxJw5U1AUBSEkM/uOBzq2rDj7u5KaxPbya2Bz7RhL/8lqFkcAC8chps9ElNei2iopX73fJTEw8DeXETnededWbyLqbIS/muXalsHZJEtRfdEZ7eJH12sQ+ttfgMBQlxf9jtBPvA5t/Fx0Hkq77aNn4BMEHkRSgN1voOvJXZPBvrtf9mifugB/QocmUbKjKbmQrbaOg39dwbHlr+AfG0nVD22bJfvcMMLpsTxdcldabegjvCsIrFU1lJSG0qe35wRB0MAoIsYPwFRQ0aaz3JgqIx/R2hKUHqvwwgzBAxsc9x0xYRgz/ruIm278G3l5J7lqlpknn/Dn9deGNSsO5JwYaOt3ZZIWpIQwYxBaYWlrq4CrVFYiv/js3OFbjJREjB5I+dGMDpsGD4hn/L/md258B4T5dc7ylbSyBkuB86GwAJaKanattRASrWfUjLYXYWXyDS2+10UmuDVHZ/CJgR8fPkHgIexZ+dJcaqOqKhs37uXgwfQWOzV36HvzIPrfdhXZ721xq70jwkYMpLwNxzxLeSWWcseL7dA/zSVyUgLRF/V3eqzmoWZNGfTsoWbOZswTRgPRF43DUlpO1Q/Z1OV4Pwe8ixvfcyj3/RahE6in85BHj6GbPBERHMT40EAQdotP7tpDHFm8keofWvqFDDhjgmTHH8a7E3XcPKY3cUcKW1wPGz2ISzfew1c7D5GXd5Ldu00YDLB0iYnk5BNs3LiXa6+d2jg7aMeQ3dbvas7v/ocr7pnE5QUKEzNcq6uhapJNJwo5nFfB2IRwZg/vjaJrfXQhhGDo7P7sbkcQ+MVE0PvK4Qz5wwwMwZ6PLjAqekKNAVRZXBeCkVtrke8cdmvcvG32z5f+I4YSHNU6MZZy6V0owz3ns+Pjp4dPEHiMNMD55DKqqnLjDQ+2s1NzDaHTkfzWDVgq6sj/fIfL7R2hM7j3eIz8n8vwi3bNU93ZUDOdn56oKWMQBv15To6S+uJyirfuc2vO7lJXbrPXr2qDthY6YVAQAvQD+8KAvq2O7XV6hcRbJpIwfyxZb+8i7d39fKaVsj2mnsIOfrRvJ9XxSLNoy7jZFzHto4UYQgwcPJjOVbPMLX7Os66u59Ch9GaCQKU9UdDW7+rjb+0iZJwbYuCWd7dToJVx1RyVZRsV3kyJZPWi6Q5FQULvQqInD6dkn+MjstFL5jL43ukuzcEVhIC5/afyYdo3LrXzzzAT8ehhtE7WWMjLVBga1eyCTkE//3/Q9XcuAseHj7bw2Xw8RiKu/Dg3btx7bqf2zNOS3btN5Obad2ruUHWynMItZxhwx1T8YiM7btAB0RePp3S3ezsZnb/rQsLZUDOt3kbp3iOU7DhA8baUZv/2n6tJ0JUcf/t7ThyPdlhIp3GhW7Z3L+YxJ1i2dy+3fH4M7YabWt7Yjg+fYtQz6O4ZzNn6R379wb0ci1MoDWn/OUuNUzg8xe74Fj1tDNPX3IYhxL56jx8/iC2b/Vv8nDd/6ce4cYPOnz3n+yg00tbvKnFMLxR0bbRqm00nCinQyti9X+WZFbB7v0q+WsamE4UO7xdCED8xzuFrY5++if63TXJxBq7TJ8S18sS6MgtJzxW5lCSrLYqzm5mlDP7ob/unTwz48Ag+QeAhBDFAv4bvhgDt57pvb6fmDiW78/l+7jNsv/k56os6X7VQp3ffS1+tc/1D79HHFlJXF9wiRrsrSu56gmNvfMf+74PRtJYru8OFrvIMW1KzXc4/JARMSExg599+6/gGiwpbTsH7h2DLKZ4bVkfd7FHMXP8r9AFNAm3OnCkkJAwjOdmfhx8RJCf706fPcObMmeKgU8cWAke/q8Zsh8KNCIXDeRVcNUdt+bdwjcqR/Lb9P8JjWguwAb+6hBEPX+WVY4LzUZr9Av3TTQy79QeE+byfl1UjdlMNwxeeot/snZj3e0awlh7LtwtQnR79r19FF9WOicqHDxfwCQKP0hsIAqKA+HbvdH6n5hyxl3rWk7ozpWPTX91LXa5r2RmbF7bpypK7niJ7/R62faRSY26y5ztc6Ga1L/pqamq4ZOYfiIyYxyUz/0BNTVNuASEgOSmRfQ+fV5HSohLySQrDDGU8+Nt6hhnKCFq3n5s++jV+kS0XR0VRWLP2WZ5aspigoDt4aslil4+pGn9XQy67mI+/jSdu+vhz2Q51bgiCsQnhbNmotPxb2KAwJj6szTYB/k1OlYawYCa/uogpb9zq8tju0ih8jNlmEj+qpT6zgGH3naH/m5UkvVLBsAcLGHR1CkGPp2A+5VxxLWexVtVyOlWjSklymCfAhw93EZ6uGd6TmTRpkkxJSemSsSRmYFebrzf6EOTmnmDW1fVs/tKPPn2Gu+1DALC+/1PUnvaMI13o8IHUns5DrXOvJO/Mz35PwrXORxk4S9Y7+9l9++se79dTKAH+XLF4IqH+lXxxrIBle/eye79dFFitkDzRwFPLn+Ta66a2altTU0OfhHnEx8O8ebB+PeTnQ27eeoKDW37wN55Dl9XW0Xfyr0ni7DknP6vVvmsfN+4yPvzPYk+8K5pbC1RVZW3mLtIqWifBUtDx5+2uZXFsPFrJV8uYdY3K5g0K8UrbPgQAdfVBbHhkD/rgQK74/o9ETuja0EIp4a0n3iBwadd8njhi8v97gsG//UW3je/jwkQIsV9K6fBczWch8BICf6Dtc0ZP7NTOJ/bSMW63PZ+qExkE9e+DPiTIrfaWMu/E5uuDe7bFQDWZObC2DKlJZg/vTZwukuQJCg8/BMkTFOJ14cy+2nGp47nXPEp8PC2K+sTF2a+fj04IdEIQHRxEfL3OoZPf3n0nPfWuzn31WeZuVhxY7VAM2O/UePci1xZnRSdYvWg6i5OnEHB0BIuTp7QrBgCM+nomPP8Lrkl9tMvFAICtVutWMQAQ2NexH4UPH+7iEwQeRGJD8gOSQ0j2AO2f5SuKwrXXTuWxxxZx7bVTOyUGAEKGuF8tzxFVx9MJiI91y0mxdG+OR+fSSE8XBAAl+06QkdWrzYWOIscx6EePZjlc2I+mtp+CdsqUYQ6d/KZMHubJt8X/HlzL0dLsDu8r1NexYZxr59qKTjB3ZByPXDWMuSPj2hUDmibYtU4FnUZQv6g27/McArtPUOM/MATrMIR1b1XImizPpSn34QN8gsDDZGNPTFSOvaBR52rcu4o7znwdUf1DFjqDweXdSOFXxz0+FwBbTdenhHaHI29sp7w60uFCJzdvdljmYvToJIcL++hRSe2O9dbKv3L2rNLCya+oSOGtlX/16HuqszmfFvtYsIlPJ3p+515eE8nOdYKz249SsKmpqqeqqny6dhuXXfonxo79NYsfexOLxd1nRaH54m//ZVmb/bMTMqiPm/17hupTp7t1fB8/PnyCwKMUd+vo1hrP1jFoxJR3FludiZAh/Z1uU52W06qEqyf44fnvPd6nN9DqLXz39B5OHIumsCSG4opoSquiKauOpCJfoTw1j7q8lo6XX2xYTn4+LRb2ggL79fYICAggN28948ZdxuqP4xg37jJy874gICDA6fmqqsrnn+9i6dJ3+fzzXaiqAPwa/oUBzvfVyKmAOkwGx1av1MRop3L4W2xGSqujyDrTi71fBfL141sp3GZPslCw8SCle7NQVZXr5/+NRx55gilTDqOpmbz66vsMHnSTi6JAoclfouXi74jIKYPbfd3biHasKD58uIMvMZFHGYi9ymH3YKtxzwGwOUpwAHJib6pH+RO+tRrrUbtZ0lJaQcgAF8zAUrJ1/ttctHKBy0mK2sNUWOGxvryNaq7n2JvfOX5x8VYQgiH3X87EF28BIDg4mNy89cy95lFeez2L0aOS2JeyvJVDoSMCAgLccCA0AgGoqo0bb7ifvLzUZkmyhrNm7YqGYyy70AwxhFBtrXZphJVTevG7HU3pvFXgu1F9OBBu5svEWO46UEG4A8tWRW0Eu9/MoCa7/VTgZ9Yf48XPv2PfviO8+ipcdx0sXw7JyVBUVMvyZR/w1JK7sJv9JY5DKQV2IeBadczw0e1HEnmbvjfO6tbxffz48AkCj9K1RW6aY1GtHBpZSmRECLZy1z60G1Gm9yfrkTjUGD8Ayi4LIeRgGJZoPdZoPWcrVHq5kAhQ6HRoNs/WctMHeT/GvMuQkow3dzDhf2+iLqecwMRIgoOD+X7rCx4aoHGh8wcclUa2ABY2btxFXl7qeemMj5+XzhiuSpzImozvXJpBrbCwbkJf5h/I4YeEaNYnAdiFq4bG+xOiuW+7fdGXGpRWR3PmaD1Z63Yi1fafHQ3J799+j8qIMu64Q2PpUnjrLVi7Fq6+GrZvhx07j9JeGma7KLLgqhgAMIS7bjXxFOFjhhIzw/sJmHz8tPAJAo/iuB59V7Dq+PeUTg+g/MPRJL5UhPiiday7flIiOb+Nxjy8accZuLeShGXZlN2eQOktMdDMDGlLDKQ8samQiwUQVw5EftVxYRmAPjeOIqB327Hk7mDKK/Fof12OEBgjQtHpFXR+fvjFRJL++g5OvbSNMX+fS595Yz04mMR+Ktj+c+lcOmMYFtkbkSGQjhwg2iEt0MS3faN46LWvOXOsiISRMdz42EyMAUbqsPD9iATG7DWx/7+5VBz7zul+D1FLdVAJBw5oTWGdyfDZZ/Dll1BUBL/61ajzWumxL/467ILJfZ8Uv2jPl/d2lphpExCuZrfy4aMDfILAo3SPIDhemk+x2b5QapFGsp/og/HWMOI/qkRfaqN8aiCVU4OxJbb+AKu7OIJT68LA4Jw7Sc6vI+nzdaZT5VhTn/yCAbd7dhejBPjhHx+L4mdE8TMiDAb0gf7U5RZiynMth35XEjNtAqaCYkyFxS0qMNblFJByr/2Yaf/9nxA+JoHg/q6lxW2fjhe88eMH8eQT/ixdYjq3sG7+0o+nlrROkqUIBZt0bTdtMVn42d2riOsl+c1tsH59NS9cn8UfPr0dY4CRlCAzNa+cwJTvmg/OaeqZM19rIWSuugruuQc0DQICghxkumyce+f9W6Iv6o3OYECzulnhqhP4RUd0+Zg+fvz4BIGHkKjYIws6T0FNJRmVRRTUllFeX0WdzdRu5kCT2vqowjI0hOzFToZFOSkGAKwDgjAMj8N6vP2z3X4LL2HU4sud7tdZDGFBVKa2TgGrDwkiZvpEyg4cczuZkldRFGoy2w/FrMspYstF/6L/bZMY9pcrCIjrrHWlcTfcPnPmTOH114aRnNwySZajdMZ6nR6b6pogWLNsK3G95HnVESVrlm3l1uVXEvFpsctiAKAffmxcJ1i6XJ4TMuvX6wgMimHhL65k8eOLvJrp0hBiIOaScZz9qmsLasVdPZ1Ri3/XpWP6+GngEwQew3PWgZUnNnqsL29QPzgIXQdRhZrZSujQXh4fu9+tkzjyWGtBYKuupXj7fpTgQIIH9qUmwzt5ENzGyYyg5rNlnPznZqyVZqa83pksdM6JAWhKkrVx414OHUrnqSVtl+K+YcA0Pjz1tUszyTtWzG9ua51f4Y1VRSQ9lQsbnDuCOp9xBLE115+JI81cc4Nk8xZ/Bg/uXLZPV+n/i4tcFgQ6o4GAuEh0/gZ0Rj2Knx6dUUEoOkx5FdSeLmrTf8IQGsz01S+ga/xh+vDhQXyCwGN4ThD4K/6Y1R64y21AX612aHDN+WQnlvKbMEa4l+mwLfx7t+9xr9bUYRw+kPCQIEx5RdQXd77QkyfQrK7tqjNX7mDony8jbLg72eicFwONNCbJau4z4Iik8BiCDcHUWJ1/3hNGxrB+fTXLljWlVl63DoaW6sGBr4uz6BD8vq4Ph07VkvW8xpOf3M811yR3mRgA6HvTYFJ+54dqbgr5NUaEYAgPImRQDDEzBxAQH4Yh2Ig+NICQQTEEJUWjU9q2ymk2lZr0YjJX7SHjtR1YyqrOvRZ98XgMIb76BT68g08QeAzPCYLEkHjSKrq+lK+zKAXmDgVB2KgBHhcDADq/jh/Zsn1Hz32tDw0msE9vjBGhCL2CZqrHVFBEXY7j0rreQrooCKSqsv/+T5j52d3oA50ze5/99gdipg9GZ3DdY94VEkN6c7zM+YX8xsdm8sL1WYweLZk/3y4GzubDw7bOZxnUIZhAMFMjIpl7zUXtLrTewBBqJPHWmRRvTcUYGcSYZXOIu3pkp/rU6RVCh/Vm3NPzGbV4DlmrdvPD899TfSoPxclnwYcPd/AJAo/huQ/hGfHDeq4gkBItt+NcAOOeneeV4RU/13Z/tqoaqo63XrwiJ43CVlNH1cmu+Tm743h29ptUNo1bQfLKnxMzre0qmPVltRx59HPSX/mWmBnjmLb6lwT08p4HfKDeD1SJvqiekF3V+J9VUSwSpUbDL7MOLOfJxSoz/1s+gFfLz/L2s2YG4M8zk2dRty+1U/MwhAaTcNkoeg8NJKa/4kadRdfQNA1yitFOnEIWnYW6aqg3MfGKSAwrn/DKmPpAI4N/O5OBd0+n7kwZQf1cTyPuw4ez+ASBx/BcTHKvoFAErod3dQW6KhtqdfvOk6OevIn4OZ7No39ufCcsBM5QlpKKMBoIHzecikMnPNJne9hM7mWRrD6Vx1cz/smQ+y9nzN+vwxDcMg9D1ru7OfCHT7A05J4o3naILyfmM/2T+4hO9rwPB0Cv9yqZsLaE8v2tk3C1JXuMKDzQrCS4rrwa/7gYzAWuOxMKnY6+sycx5hINf0MNUANmkGlnEW4dsbSNZrPB6bOo+w5C4Rl7soTzqa5B0zR0Ou9ZJ3SKjuAke/SJZBcwBoHnLXA+ftr4BIHH8OyHQZAhyKVzWk9js9j4buVBzhw+S+LYXlx653j0Rj1aiJ4zn0/FkG/GL9+Kf6FKQnogumoban09QhEk3T7ea/Ny1ULQHtJipeLQCWJmTqZ4q3c9xc1nO5E/QUrSXvqa/C+OM2vPX/CLDqYmu4QTK74m/ZVvW91uyivClFcNeF4QlOwq5ORT/0GzqcRMn0jx9v1u9VOTfhqd0YAwGpAWxzJCKAr+sRH4R4cR3CeS2KGhREbXE+xfhaJrLUrVlD2IYfPdjs/XzBYoLLNbAM5kganaOWdQswlKyyGmKwotgT2x014kOmAQgoQuGtfHjx2fIPAYjivYuUt8UAxpFd0jCCwmCy/f8h4xkTZungfr1+fz8sZj3PfRbeiNetRYP9RYP8zjoBIIfvAM2p4m0/vGUcuJmTGS3rOGMvh3F6H4ec4j2lMWghY42vV5GFtVDcaocCyl7qdersksYO9vV2MINpD93m6kzQZCoA8ORB8UgFAUey4GIUj7v23svvNVbNWtnyFDaDDD/noDg+4ej3+s85aturxatt34f+ccJEt2H9yOL2cAACAASURBVCb64vGU7Dzo1vvRLFZiZkykeFuTqND5GZl0/3RiYmrx19cizulsEx1mAi3JRaYVIdqJbtE0DXksC3k6B1leBrXVYDGD2slcAgF+nWvvFhqQhiQNiAGGIXwf6T46gVNPjxAiG6jGngPUJqWcJIQYC7wCBGMv87dQSlklhJgCvNbYFHhSSrm2oZ/vgDia/rJnSSmLhBB+wDvAROwr68+klNkNbW4HHmu4f5mUclXD9STgP0AkcABYJKXsllJ4EjNQ1eF9rqCI7qk7paka/170MTGRtvPixi18t/IgV94zuVUbU6KB5h+HtloTBZtSKNiUQtbbu5n63kKP5H2XmkbxtuxO99OqX7VrqlKGDk1ye/EE0PWP5FhMKWH/bvKJiJk+keJtKdiqazFGhBIzczJafT1F3+5psx9rZTVHF79Dyc5TXLrhdqfGlprG3l+vxlzYZOmQNhslOw8SPm449UWlmPKLXH5PFUfSMEaFo5nrSbx6PAPGK4QHud5PI+qu7YghN7ayEti27EJmpdvP/b0hAP27O6V2MVCMRA/0RdC/m+fj40LElVXnMinlOCllY+q5N4CHpZSjgbXA3xqupwKTpJTjgNnAq0KI5sJjYUM/46SUjX/5dwHlUspBwPPACgAhRCTwBJAMTAGeEEI0puhaATwvpRyMvd7wXS68Fw/TvVUOPUnazhzqymqZN6913PiZI60zASpF9QRvbNtjv+JIBl9O/DvHln/TqboGtWfKWJ+0hKOPf+x2H21RX1qJ8OL5L4A+NKTd0EMlJpTcDyaRt3IC9VcnIAz2PxklJAAxLIaaBYmUTw0m45UjrKWUA9SgIak6mUnYqMH4x8VgKa+ieOs+SvcccWpOBRt3kfWec/4Tx5btpGDTboevVRw6gaWymuip4/CLdc3pzVpZTezUMVzx6DgmTK8iPKi840btUV6AzGgSLVp5Nda3P0Km7ofaSq9Zg+QPp7zSr+vYgN7dPQkfFyid+RQcCmxt+HoLcBOAlLJOynO5Tf1xWPm9FfOBVQ1ffwxcIewS/2pgi5SyTEpZ3jDO7IbXLm+4l4a213fivXSSH48gKEgrZcwYyfr19nhxaIobTxzT2hSbtKIQa3Flq+vN0aw2jjz2EVsueoHqdPd+VkqAgbozroUK2tD4L0XcSzq/4hQPksleqtDOeySrf8gkevpEt+blLKFD+7cIhzwftbiK2DcLsA4KIn/pYDK3TyN76wzSv5pC7sN9Cd5Xw8p1O9gyOI+Bfytly5ACXgzMxVRcSu3pfGy1rhXWqo0KZPswf+5643Vmv7iq3XuLt+eT+tQH7d6j1poo2XUIoVMIG+V8WeDoaRMo/H4/NTWec8pV9+9H3XoA27qvUFe9C+XuWxycRdvyjT0KoUfQLYZSHz8CnBUEEtgshNgvhLi74Voq0BhbdgtwrjauECJZCHEMOArc20wgAKwUQhwSQiwWTXa9BCAHoOHeSiCq+fUGchuuRQEVzfptvN7lSOqxT9fT/XYPcUOiqKzWUVsLo0fDQw/Z/y8p13PpnS2dBUWNDW3nGaf7LtufxteXvEhVmusf0H7RwSj+zp/T2tB4MCiDndEVJI7U+P3fJCHDbLwfXcj/BuS0EgXFW/cRO7P1cYjTCIESFoQ+JhTdeefJSnBgu2KgEePXeUS+euZcf9JfASGwjAjly7uCMQ+wkJIqeeZZSEmVmBPMHKIWY3ioUxYOGeTHNyP8eeL6EO6+2ci/Lw3gu+F+bD5xklU7HTsH1uXXsnX+C0gnFztzYTGVx9KJuaT9n2VQ/wSiLhpHyY4D2KprSfuqbbGnapIvjhXw980n+OJYAarWwV9HaT7a/p3IzJPe9w/x90eMG4NuxsVejTJwDe9Hzfj4ceKsB8o0KWW+ECIW2CKEOAn8CnhRCPE4sJ5mslRKuQcYKYQYDqwSQmyUUpqxHxfkCSFCgE+ARdh9Bxy5BUs3rreiQcDcDZCYmOjcu3UJ71Tfq++sk5ObDLm4L4fW9yZYFhIeqvHyy4LAqCDuW30zemPT4xLxaTExbxdi7aBE7fmY8ov55rKXuPzbBwgdEut0OyEEwYMSHNYxcMRayjCESxJ6we7d9mOP5cth4kQoLDXzYbSNvqFhaEJi08GZMEFm9AmqF4Y2jSlBr4JRlcybGEdir2CkXiAVAXqB1AtQBFqQHi1YD0qzx9KmoatTMabX0m9JDmqNc3UuwnfVUPr71tfzciqYM1dtcYxzzfWSjH/UM3tAH4q+bydKQqfj03FG1o33x2IQ5+bHwVworIHewdxp+wi9orAwedy5ZlJKUn63tkUxJqeQkuLv9xE9bQIlOw60erkxOqE2O+/ctYqTZ9C0JHS6ln/Gqia55d3tFGhlXDVHZdlGhTdTIlm9aDqKro1ognrP1BRxCr0e/WUzu248p3AvxNWHD6cEgZQyv+H/IiHEWmCKlPI5YBaAEGIIMNdBuxNCiFpgFJAipcxruF4thPgAu1/AO9h3+H2B3AZ/gzCgrOH6pc267AN8h30VDhdC6BusBH0Ah9V2pJSv0eDkOGnSJC9svL1zXFBndc0E7Cl0io4Fz1xD2s4cCtJKueGmKIZc3LdVBrjYT8ux5LsXWWHKL/7/7J13fBxnnf/fz2wv6tUqVrEtyd2SZTtxbCeB2ImTkAI5juNCCeX4HdzvCndHOeA4UjjgOA4OOPqFI/A7CJBGEqeQZie24265yEVyUbd6WW2fmd8fK6uutki72pU879dLlnZ25pnHq9HM9/mWz5dXbvwOJe+/nrSVeeRuKyVlaU7QfRWfTH9dG+7OYU4vNeN12DEqYJQFBgUGTCqdZoUus8qgCVwGcBsEx495WVsGW7ZMzIXYuRP27oXnPT5YH7nHwXp9Dh5rFNUSegklVcJdk87lL6gs/Y6d4XOXwx83zRW6qCKL53+h5+GH/KPyv88/JdiBKWxSZP1iE7/dOC7pza9gf+oIhdkyd/85PP3MIK1PXeEDwP/9zTO8+rcfZd3iQi7+z2lan34z8v/zJLrfOjKhpNOUk4mtpCBoqaJv0EHvUCbZaROvqRfqO2hXetl/OGAMPfSwzKaaXl6o7+COlSE0B4Q0J9UjTFMymVi0PgcaMyOsQSCEsAHSyEPcRsAIeFAIkTtiIEgEqgB+OLJ/GdCsqqpfCFFCINfg0siDPl1V1W4hhAG4E/jjyGmeAT4E7APuA15VVVUVQrwIfHVcIuEO4PMj7702su+vR459OgafR1SoeIGZl5GFwi0nLg4o6SSqtpZQtbUk+A6yiu/87OKy7o4ezn7r2dHXaavLSVmWj600k+Wf2YYlLxVPt4PnVn4VT+dIP4LFdr54e4Q3u8FULl5y4HTCgw+Oaejv2gXdvcCa6JT8wrqpQ+DekEHTvR6yvh5mx5W5XH64LOhbAc9NLutXd3D7XQrPPyVIdeSyDhu+EN6HN5abeWbtpM/saCuF2TInJlSRyJw92kr/hmJq/vV76GWVn+3SzbqIrWv3QTI3rMLT049/YJjeQ9OrE/a0S2RPavB4vLWf7TsnekZ23C5Td2IgtEFgMIE3tFEtKyov1HdwvLWftYXp3LY8f3qvw3T44ysTPTPmSg9BY6ERyd97HvDkSLhfD/w/VVVfEEL8jRDiUyP7PAE8OvLzFuBzQggfgULZT44YATbgxRFjQEfAGPjJyDE/Ax4TQjQQ8Ay8D0BV1V4hxEPAVX/og6qqXu1W81ng10KIh4GjI2PMMd3EK9rvSaBBEA7hkqPW5g/HwIkLDJwIhAMaf/wqOrMRT/dEY8vui+JmXV1I/xMdeJoUqqvh9tvhmWeguwecaXYoTo9qft9+vJ4vP7CWGWreMHxD+rS3aV1xBkM1drr+ajFKWnCDR9JJ/OkXd9C//WUa/83NDkxszCrGvjYPV8vU6g+AU2UWfrzNxJRJdzi4+8+nVpF841djmgV+neBjt8ncdNbKn543YOmYeZ5M78GTpFcvZ/hCS8j9+ludUJMGzpFz6QysLS/g4V3neejhMc/IS8/r+dKmiZbDlIf7+ip0IXQLpoQintfx9Tds7FhSQHVRRsTGgbR+Xdh95p54hEY1rgWEGmFb1oVAbW2teujQoZiNp9JJQDbBPfLlIVYGwjcO/x6/EsYd6Vco+nYHrmI9g5ts+EqsU2/+cUDX5WHxHfvifp7J9BSm8NfvimLN6lfgUDOc6Q78bDfAhmIoy4QoV4Jry9P5k5um8ZhEOJfyrW8FbWvb+9dLGbi/KOwQlv295P91ZCWFvXk2PnOHAZcxyP/zYDOVw22jHgKfD1atgnP2RbBx6sNEqCorW/x85JSOvEvRGwbGrHS8fYMQJjEx/9ZN3PzCA6MhEKGTkGWZd9/7GVpa6tlxq4eXXjRRWLicJ37+INKAC7WrD/+lS9z3tZ/RLvewfafMy7t0LDLk8tv3XzftQ/25U+08fODAaCjC5wskz65aCRfP61gkhclTGEH38Q8j2ZOp+2AJgvJET0IjiRFCHB4nHzABTdZqFghygbHEuEDvAQ9jxoFr3OurX5HFNcMaA8Cin3ZiePwcBiAVMBRl4dqUSd8GM851KSiZ8emMJpwz1xOYDf5obR29BNeVBL5myV03hH9gT2ay/PPHc+wwaaUtLc3Gsyyy8IX1UOTiV/+7iuDGAEB1Ia1PXmHVKpm774bnn4feXrAoQ7gUdYqxpArBmTwdv2nopphBSjCxDhtShO2E0lYupWt35Ia4GJevotPpeOLJb7Br1wGOHWvgKw8uZefOjYEWx1k2KM9mV1c37dIg+w+MyzNY3x0yzyBYKOKee8Buh//9dWR5CqK0JMmMgRzNGNCYFZpBEEMEgoD0QnDVsoDB4GOigTDZePBzuidofuQErAf6MT96dsI2X0sP+pYecn4feG0oy8WzJo3BVUYcq634Sq1Rr4yDYWpJTBazX0qcN8uoj66kzO/18/33/pKsVO+o/POnhyXeTx7NeCkz2cn+3kZ8azPCDzZC+ltDEZmTcoqFg2Uhci30Eo71ZThON2Czwde+Btu2QekSB67fnYCyDKguDBhUAIqKcc8ZXNIwS/5RYdfTgt0tZv7aWRSZUTBL1U2dTsedd17PnXdeH/T9o0cb2L7DMynPwE9d3fR5BmsL03l4l46HHh7zELz00li+Sdg8BSEhvWvnrP5fsWdJoiegMc9JlsLZawKBQGBEkIogF8FiBBUIViPYiGArsJUM0wYKbGUYpOBZ8FKvl6KHLoVtvOK72In09HnSHzlF0fsOsmznEZZ8pomcX1zBfGQA4Z7ZSr/wXyPIlo8DcvyjITHj9UePkpXqpa4Ovv51OHoUZJPCCxXtlP9jD0+XXOabX/kDboc7ovFMdQMojZFVdTy/VMWnD/Nh9bn5s/cFyjAPHoSqKsjLhs98zEXlcBvWJw7B203wh3p4pYFCg4NDJ5QpGgihSFlWEtAa2HeUrOvWYSsL7WVxtXYzkxBmdfVSXn7JPEFI66UXTawpSJv2mNuW57NIymRTjY7PjWhtFBQEqlACeQq6kMeL0mIkfTKtp65HxLDjqsa1STJd0RqAQE+BvYIHVnxuwnZZlhnw9tDjuUL7N35Py5W9UY/t7xuC14ewvx5oQCEMevSrFuFYbcVVbMCbrcOXo8e/yIySEmKFmWWFzvhUV4TCP4/M18vHOviTcfLPf/wj5OUFDAODAR5+BFavdvOtd/2Cf3j+wxgtocM7GU9HWN6q1/HiygjKKTPM/M/P4bVXAzL8aWmM9q74whegqEil0tnO3X8OTz0NOhWu6u6M10CoIbjLPHfbBjp3H4TzAeOxZ/8xhF4/rTaBMSsdv9PDya/sx9HYhrc/UDlhKcgg96ZlpCzNQG83YC20YUid+Fnt3LmRn/y4ik2bxuUZ5Fdy2/LpJXx1kuC3H9jCC/UdHKvrJ8XbSuslB1/4J4WXntdRoMuc/nghkG7bHuYDnkvWIabxSmpoRINmEMwTdDodmZZcMi259LSHlpGNFNXnx3e0GdNRJjQnQggMawoZ3GSnf6MV9wr7mPsYULIS0dkNeo3JIg0bHllWeOaZQEmfwQCHDgUqHSbHrH/2M3ji4d2875FbQo6nG45s5fzicgN99ggsp+5hsrICok233cZo7wpZhk2boLCQSc2t4A9/CMzZ54Pnn9Gxg6nXga20EENaSsAYmITq99Nz8MSUro9XjQdvTz9n/+P36O02XG1jlRONPx4bo/T+7Wz44V3obWMGa7A8g9tu3ID60x+G/Ah0kuCOlYu4Y+UiPndLFS/Ud1B3YoAvbUoLWWUgysuREt7M6CpLEEQedtLQCIVmEMxDhpvC5xjMClXFd7wFy3Gw/Bj06Xb8m/Lp22BmaJMdX4YuIbGmdtv8qYiRJEF3d+BBevfd8Ktfgc0WUEscH7Petg1eezuC1X+EH/iTNREaax0OVl4XyB/IyQn0qnj4YXjxxUCC4QMPTDRe7roLPvZx2LcXdj0lMLcauXnD9bgam/D2DiAZ9GRfX03X/mOo4xQIJ6N6fdjLiunrHyKjejnABOPBN+ggbXXFBINgPJd++TKXfvVHjJlp6G0W9DYz5vxM7GW5lCzOYrFvMcoeF+6V7iDmyvSMNw7CIb1jaxQjx5M8hFZiqBFDNINgHjLc1D6n5/P3O+DFBjJehAzAtrQY67YNuNo6cTTMXT6BJ6FXa3QJDKXVi2hzdPCe98Dbb8MHPgDf/37AQLjnnoAxUFAAJ09C4YrgKo3j8dslIqkZUSKZpqJilT2cPg3LlsH589DZGSg9zM0NqDu+/DI89NCY8fL009CTlsnpH1nYMaiyDhsDB08g9HpspYU42zqDegWCMXj2ApLFNK1IUe+BOnQ2C/J0DZtUFW9P/6iXYbD+Ip2vTdzl3HefYfunS7FnxfiisViTpLJAIFiR6EloLDDmUVRWAwL68s7muTUIJjPc0EzX7oM4Gi5jzEonbdUysm+oIfuGGiyFUzsixopEBgx+8MxZzjUPoqoqqho2n5ObHqimz2Hk978PJO49+SToLRLNLYEwQVlZ4EF8pUvw7i+G18J3roisNHFRfwSfUnM/RVl+6uoCHoL9+wOGQOMlePO0hROnYNGiQOjgc58LGDFtnRLcvITc8lxqsI9WF6h+P8OXWlGjkPD1Dw2H7O2g+Pykr1ga8XjBkF1ums7G/vYmliVLWV92oiegsQDRPATzDE9XL4oneVQMx6/UrmIpysdWUoAQAseFZlxtsWk/m8gqg7YeN794+eKEbf/yodXodcEfOnqjnk89fj+vP3qU3712hcVb8vizB6pRZIUnHt7Na293Ubgih7/5ybawCYUAju055PxbY1iFyM++qfDx96ihBaq6ndx9pzIxJHA3/NsrhbC+kNbXzqBeGGLNcpWf/gwcGPG8ew3oJX6xwcAt9UbUOF+DkztGzoQr55ys2BzL1bxAun5jDMebDVWJnoDGAkQzCOYZcc8fiAGulg5cLWPtbG1lRViL8/E7nAycapixQaMkmT9LVlT0uunf1xv13PKJqW2AwyUQBkO16ZHXZiEdCh5bv8q5NBlEGAMj28rTz0k88rAyGhJ46lkJSmwgCZw3V9HQ3E9DsxPjOguVBjuNqsBJQNLYlWHG3JE8RimAtTgfV2vnhDbNffUtyN4KdMbYXDi6v/xoEiUTHkBlI0K7hWvEEO1qmmc4m6fvG5+sDF9sYfhiQMdeGPSkrVyGMSsd2elioL5x+ljxJCKKjy9gLn+/CvPRRSz6P8em3ed8ZgQDFafT0mBn5ToH99yp8NSzEq2+cf0dBGzy2bhtIJXK4y5U7zBquo3HVqn0WsDS5YlTB48xwnVwTF2+BHNOJn6nm+HmdpzNHWRUr8DR2IRvMNCTQfH5cTkU7JmxMQiSxxiAgIjZHlS2akaBRszQrqR5xnzwEIRC9fkZOHV+wjZ9agq2kgKMaXaGzl/CfSW4AI+cJB6Cd1bnctO6/BFlyjlECDxVoV3g762TGbB4eH25EXW6sMGIF+B8cz//9poTSqwBY0AS5PXL/N0BQfGFgOjQ1Qe/6B/mg2+CvbwYqcrM4KTfYSwRkoTebiV7czWoKqqiBlb+V79LAkdjM4P1jROO6zt6GvuSxQiDfjSM5YuVqOYc9AiZGReAikRPQmOBoBkE8wznHFcYzAX+wSEGTozJMJvzc7CVLEJnNuHtH2LwzAUUjxclSW7KXr+KSPBcdFYzxsy0KZ0OVY+PPz9p4FShQmfa1HiG2auiCkh1KaSYUzDn2xEqiFY/S3oU/vSoP2R+gONCMwhB1qa19Lx9POb/LyFJZG5aQ8eLb87oeEdjE2mrlo0aBC7HLKr0CwuhdaSE0pQY7Y3wzL1AmMbCRTMI5hmJrjCYC9wdXbg7xmrzJbOJjPUrKR6+THGPn5ZM3fSr3zmgozeyEEcskAZ86Nvc6Hq86Lu8GNo9ZNSsZODUeVwtV5DMJvRWCzqLCVNmOsJk4B+WXA5qDEiKyldf8JHXNr3kcEShAFWl//gZzAW5uGeYMKqzWTBlZSDpdQiDHqHTIel16GwWevZNHxKJBG/fWBOo/i5BwbIZDKI3oLvvbugfaUZlDKHcmVC00kON2KEZBPOMudYgSAYUt4e+w6fYDmw/AlhNdGcaabXIdFpUuq3Qa5PotwoGLIHvwyYRNzfvB3fEt/RMuGX0rS7MxwfJ/W4TyvDEfgd9435W3B687oBf3NUa8Bb82xkzBwp8HFis4/jisRbI1ZdDGwPRILs92DPT8HT1hq18mIylMA//sAvnHIS/XI4ZZjv4fTA4iJQ51b/g9Xp55OFfsefNE+TlZlBZWUTthqqxLoxzSg9MIx+toREtmkEwj3B39aLKiWk9nFQ4PWQ7PaErsXU6VKsRr1mHyyBw6FUcBpVhvYovTC7CoQLBgfLgK0KzHoSsEmwtLQ360be7MbS5MbX58JvBn2NANUjoBv3oBuXR78ZuP6YOH1K7E9U77oGqguIaC3zPRHtBONxsOgebzgFmI0+ulPjDOjN3nomtksPAyfOkrliKpNfTX3cm5L45W9ajyDKSToe3f2jUeIk3fs8MDQJJF+iFPAmv10vFsvuwWh28610BOee6OvjDH0z85McreOLJb8yxUdCOSp7Wy0AjJmgGwTzA3dVL23Ovc/yfvoXrSg8pFaUMnbuU6GklN7KMGHJhGgr0aUiP4tDr6oFXQuzwg91RTUVI0oRyuKuoQNzNO7eXew/DnY2CvJXLcflaYqYLATB4ugEA86IcUpaV4O7onnJt5mzbQFeEKoaxwNM7QGplGYNnLyJ7wxtBQ10+3C5BWrbAaA08zKV1q4N2M3zk4V9htTpG+zw88khAwOmf/9nDgw/Ws2vXgWnbNMcHF3Ac2DSH59RYqGgGQZLT8swr7L7nUxOk8WSXh6zr1qH6/dPKv2okDzqbBf9QbFz1M8XQ76L3rSNIJiM5W9bT9ebhmI7vbu/C3R7I+7CVFWFbvAhn6xUsBXlzagwAKC43pvxsOHsR2RfcIFBklZ4WmdYGicYXGlBlGWNmKnlrFpFTncWyv9kc9Lg33zo52ggKAt9vvTUgQb3jVg/HjjXMsUEAAaNAQ2P2JEkhl8Z09B2tn6KT62xup2f/MXoPnQyUZmkkNRlrq8isXZXoaQCgeLx0vXmYlMoysjfXIBlivyYYvthC5xsHcTQ04enswVZeHPNzhGPgxDmyb6jBnD3VN+Qd9vPGY8O88Z0zNDx3ejQM5+0dpPn1sxz/0RH8QxPrFWWvn8u/PkhJd6CLpW9EqdnnCzSEWrUKXnrRxLp1s5NcnhnqyL9+VM6gsheVN1DZPfLzYVTqUalPwNw05hNCDSfKvoCora1VDx06lOhpRMXud/8VLU++PO37wmggY20lvQc1T0EyIwx67OXFDJ29GH7nOURnt5JWVY7OasbVciVQVhhj0tdU0l93NvyOcaJ85wrWbFPxuhSazuk490Iz3v6hkMcYM1IwpNvQ282ofpmh8+2ofj9+FD5rv0BaocJdd8Ezz4Akgclkorg4ETkEV8kHwouWCW6O/1Q0khohxGFVVWuDvqcZBMnNrpp76Tt6OvROkkTO5mqETkLx+hg43YhvIPQNT2PuiYerPtakVJVjzs3E2zuAY0RdUm8xI5mMs0oETK0qZ/DMhVhNM2rybt7AlddiE7rwo/AkvZzDRV5+FuvvqGHbPZsSVGUQHZpBoBHKINByCJIc//D0XeFGUZQJDxphNJCztZbeQyeRXe4QB2rMJb3H6pM+IXTozAWGJj24r0pL20oLsRbm4bjYgt/hHJUIjgRjVjRpnbFH8cdu4aNH4k+u1rh0gPifBiprqpPeGIi2hbfGtYeWQ5DkFL97R9THqF4fXXsOYc7NIqN6eRxmpTETZIcTb+8gxsy0RE9lRgxfaqXrrSO42jrxDTowZWeSu20DmetXYcoN3USh71g9ppxIGi3EASFiWlkxGdXv59Cn/pcjn/590GqSxKNHcDOCmxI9EY0kRzMIkpyyD90z42OHL7fSdzSwKs3fcUPibsgao3i6e0mtLEv0NGKCp7uXzt0H6T18Ek9nL+ZFOWRvriF9beWUfeVhF/alixMwS8i+fh2Oxqa4n+fsf7zMhUf3xf080aNpFGhEhmYQJDlpVUvIum7drMbwDQzR8dJb+F3usCs5jfjTve8Y5ryQskrzEnd7F917j9B//CypVeWkLl8y4f2efcdIrYqvymMw4ukdmEzz7+vm7FyRU5DoCWjMEzSDYB5Q/uF7p31Pn2Ijd9sGcm6owZCeGnSflIrAilR2OKfcpDUSQ8qykkRPIa4MnrmAzmYm98YNEySk59pLlbFuOcOXWufsfL7+ZMvZSUFQmOhJaMwTNINgHlDyp7ez6LatCGnir0syGkitKqdz90G63jqCzmwibdXETi7pqysYPD3WJrbnwAlyt21Y8A+kZEf1L3wJar3FQucbB0lZspjszdXYyovmvH23PnVudf6HVo7bLwAAIABJREFUGq7Q9WZD3MaXZZlnn93HQw89xrPP7kMOK2VeFbe5aCw8tLLDecQr7/wQV17dP/o6fd1y+o9NFRvJ3lyNZNAjuzz0HDwxRdjoKqlV5ZiyM+g9eno0k1xjbshYv4q+wwtXOyJYiaUwGsjdVkvvoVP4+genOTLG89haS9eeuf+bv+PMv5BamR/TMWVZ5t33fobW1jNs3+Hm5ZfMFBZWhdE+sCPYENN5aMxvQpUdah6CeUTJn9054bWnqzfoft17j9L5xkF6DtRNawxAwK3b9eZh9GYzWRvXxHSuGmFIymz02CG7PVO2qV4fV/64D0mnI2vT2rjPwVqUz1DD5bifJxiGVEvMx9y16wCtrWfYv9/F1/5VZf9+Fy0tgf4J03PtLPg0Zo+mQzCPmJydrl7VT50lnp4+PD19pFSWY8nLwtnagaMx9op1GmOo8sI1CDJqVjAwLkw1mavXW9rqCnyDDpyXYxNGsBblI4yBJgOSTofs9oz2V5hL9DYLppzYhyqOHm1g+w73hD4K4fonCDbGfB4aCxfNQzBPkD1eDn3qKxO2+RyxdfMPnb1A5+6DOBqbMaSnkrF+JTnbNmApzIvpeTQAdWEaBEKvZ+BUA7Iz/LU5cOIc7s5eMjeswr60BPuSmZclZtauwtnSwfCFZoYvNDN0/hLO5vYZjzcbcm+qQtLHXqSounopL79kntBHIXT/BG29pxEdmkEwT1A8XvpPnh99rbOYI7rpzhRf/yB9h0/Rtfsgxsx0sjfXkL25Gr3dOmXfeDTIWegoYZPB5ieZtStRPN6I91dcbnoPnsTRcBmfw0n6mqkaBpHg6enHUhTbmP1MyN+xhusfu392g0zj5d+5cyOFhVVs2mTmc58XbNpkpqhoOTt3TucFyJndPDSuObSkwnlE99vHOfDxL9J/4hxZG9cEcgTmmPR1y3G3d2FfUkxf3VlUnx/JaEh4e9/5RkplWdI1Opot1sWLcHf1ocxSLjt7czX9dWfxOyKQ7Z50fktBLqpfTlhb8J0nvkT6qpmX+al+Bf93/wvpz96PLi9zitqwLMvs2nWAY8caWLduaZj+CUUIlk3znsa1itbcaIT5bhAAKD4fh//2q1z+zfN4e/oTPZ1RdGZT0EQyjeDYK0pxxLmngTEzlZV3FuEagoaXLuKPcyVJxvqV9B0+FZOxbKWFqIqCsyk6t7+5IBd3W2cg/KCqceneGAyh15NzQzVDDZeo/LsbWf73t0Q/iAr+S62oTz0ZeF1Ugv49dyKkmfYgSEEQ9L6vcQ2jVRksICSDgRWf/XhSGQNAQnrea0zP4ndWcdNfFLBkncSqrRK3/G0JlvysuJ0vdcWSmBkDEOib4B8ajlpIS9LpMOfn4GhswlKQG7P5hCP7+nV0vnEQV2sXx/7hdzT9NvKulqoKctcAvjcPjBkDAC2X8X/n+8id/TMsFkg2kSSNZEczCOYhtsUFGOZYcCUcpuzEdrPTmIjPpZCaO5bbYc/SU7k9fsmhpuyMmI/p7RvE2dJB6orIjQJnc/uo6Nbg2YsY0lJiPq/JmPOyR1tFX2Xfnz/Ki7X/xv4Hfkn/iemVElUV/L/8DcovH4NDwcsHlV/9EmVgOFBBHIlhoILv6Gnkk4lJqtSYv2gGwTzl3vY3uadlNyJJWq4u5DK6+UhO6dREz7LV8I6/r8JeGvvku3g11vUPDTN8uS0q3QLV7wcCOh3WxYviKpdszs8OdFNs6ZiwXfH56T3cyMWfv8kbt/+QoYYg/RRU8D/7MnSHL42UH30U/7e/h6+uPpS0SGBYWYHXX0V54xmU1qnCZRoa06EZBPMUvdWCtTCPwjtvSvRUAKJOANMYQzIZYz5m0bKpBppOL5FZqKfqHbF9QKavraJr77GYjjkeedhFz9vHydlai9CHr2iRvWP6HAMnzgGQtnK60rzZYc7Lxt0R+oHubOni5c3fou/YuHwGFXwnzkDD2ehO+Oor+L/9PRSHe1pvgXq1HNnrxP/EQyiXj0d3Do1rFs0gmOeUf/S+RE8BAMfFFnQWrc1qKOzlxeRsqyVny3pSS/PIXldGyfbl1H4gtg2nUpcVYk2b/sFZukpizftXTOmNMRuursrjSdeeQ6QsXYytrCjkfop3omCXp6uXoQstZNSsiOl8crdtoP/4mYj29XT18/rOHzB8uScwR5cHXvnjjM8t/+Sn+C+2TDUKVJAf/+3Ya78H/9Nfxf/8t1DO7WUuk8hVRUZpeHvOzqcxe7Qqg3mO4vfz9OKbcCVAkW0ywfTrNQJkbVpL/8lzoz0jUpcUsP2TGcg+Fb1RovGoQt1vG2NSqVF+23JqdoQPJXU3+9j3WAee7oGQ++ntViy5aRhsJvwuH75hNwarCVOaGVOKkbb9FxCSQHbNTZWJMBqwlxYyNE2VhrU4H2dzx5TtQq8nfU0FfUdOz3oOWZvW0PN29GW/qcuLeecbf4Pulz+f9RwAKFuK/s4dIAlAoHT1ofy/X027u8hfhm7bh5EK49v0SFVk5Be/h9KwH8PHf4IwJ1fO07VMqCoDTVFmHuHq6MKYnorObBrdJun1lH3oXk5/7ccJnNkIIl6R5PlN9uZquvcenbBNkRWEEOiNgc9sSbVEfmkZ7RclOi/66ThwAcU3s1V3el5kv4fsYgM3fDif3T/wjpYkWgtzyFqWSUaBjvRshfQcMNqmv004B/x01pnZ/tcFGG0STfVwfs8A3sGxEJJvyBlTY0H1+gLeDSGC9upwNncELYFU/X6Gzl/GXl4883JEIcjZsn7GGiCD9c28dtP3ueGD2ViMMSgDvdiA/7uRd1dUO87jf/wLiGXXo99yPyI99vkkAWPguyhn9gCgnH4dXc2dYY7SSAY0D8E8Ys99f03b82+Qs7WWgtu2svQTf4reamHw/CWerbg10dMja3M1/cfOxFVB0bq4AEtBDpLBEMhkU9VAAteR06je2PR2iCWGtBQQYkp3P2tRDrd/evqsf49D5lK94NLbfQxdiC5bfPtnK0nLM0S8v+xTAkrKAvTG6MIIqqKCABHCGHT2+9j3Oxd9p5uiGjscuds20Ln7YND3bCWFONs7g14T5rws9HYbjsbo5iMZDWRUL5+RZ2Ay9vJC3vmXuRh0CbxmJT3Sup3oNt0XsxW8qsjIL3wH5exbYxszCzF88DshrxGNuUMTJhphPhsEXfuO8sdt90+I1drLi9n4owfJv2Uzf7zx/mlvjnNF2uqKQAdGIeLSVCZt1TIcDU1B3eqpVeXobBY8XX0osoy9pCAQL5UVPH2DOM5fivl8wiGMBrI3rQ3afteSn8Udn1kUdgxVVelpkbl8WnDlRBfOtu6Q+2esLOGdH41/qV20yH6Futeh8fnZu+vHk7VpLT1vB0+ay9lWS9fu4H/v+lQ7tsWLGBgnBx4KIUlkVK+gN4Ytq4tvq2XjdlfiH5SWVPQ7/xapZHYdKFXZj7zr2yjn9015T3/fvyAVr57V+BqxYdbCREKIS0KIE0KIY0KIQyPb1goh9o1s/4MQInVk+8aR/Y4JIY4LIe4dN876kf0bhBD/KUb+EoQQJiHEb0a2vy2EKB13zIeEEOdHvj40bnvZyL7nR46Nfap2EtH448enJG45LjTz6vYH2Pfhz1F0zwyU0WLM0PnLKCNSxua82IjgCIOenK3rSa0sY+Dk+Wlj7INnLtB3+BTOpjZSyoro3nuUnn3H6DlQh+r3k7a6AkthXkRZ6rEipbw4qDEARBwOEEKQXaxn/a06dv59Hrf+UxVr3r+CjBXBGwFll9tmPN94otNLVN8iseEjyynaVok5Jza6BaEWNN1vHiFlUofQq/gHHQw1NEWWaCgEWdeti6kxAND8wiFaO5KgcZhrEP8TDyHvexxVmVmPDVX245/GGABQTr02mxlqzBHR+AdvVlV13TjL4qfA51RVXQ08CfzjyPaTQK2qquuA24AfCSGu3oV/APwFsGzk67aR7R8F+lRVXQr8B/B1ACFEJvBlYBOwEfiyEOLqneTrwH+oqroM6BsZY0GiqipXXps+W/fi/zxJ3T9/Zw5nFBzF7SFtxdKRdraClIrSWY2XunwJ1oI8uvYcZjAK3f+B0w2kVpWPvh6+2MLAiXO4Wq+g+v2krlhC9vXVcc150KfYGGqY3iXtd7qR/dFpNwghSMnWU1Er8c6PpXLLZyop3b4caaTlr95mYVFZcutBlKzScd09BhZvDu8diYT+42em1RlQFQUUZVojUHF76K87R86W9SHPkXNDDd17j8x6rsE4+vOjeP2m8DvGHRV5/2/wP/UIqmsw/O7jj5T9+J//Fuo0xgCA6o2vbLZGbIgoZCCEuETgId89btsgkKaqqiqEKAZeVFV1xaTjyoD9QCGB1luvqapaNfLenwE3qar6CSHEi8C/qKq6b8R46BjZ/31X9xk55kfA68CvgS4gX1VVvxDi+pHjQwbS52vIoOutw7y85f2JnkZEpK+ppL8uUFstJAnzohzs5cWB6oMg15o5P2e0g6LQSRgz0/APDeMbcAQe4MrMH3A52zbQFSKMkrFuOY6LLfgGhmZ8jsnYyorQ260YM9JCnhtgy19VkV8+e4+F7FfwOhUkSWCyJ4dQVTgu1skc/nlsRHPC/Z4zN6ym98hpCNFhMndbLZ1BwgsZ1SvoOxrbMMdkyu69nvVbY3cNzhpbJvqbPoJYdt2EcIaqyDDUjdrXNvbV24ra2wLDfWGH1d3wfqTaexDS/LhGFyqxqDJQgZeEECrwI1VVf0zAE3AX8DTwJ8ComL0QYhPw30AJ8IGRh3YhMF7fs4WAocDI92aAkX0HgKzx2ycdkwX0q6rqDzLWgqPxv3+f6ClExORselVRcLVewdV6BeviRRgz0hA6CSFJ+B1Ohpvawoq6zIaut45gKytieJKs7FX6jtVjKcjFVlZE/7HoH0620kJcV3pAUcjauAZPTz+DpyPP+PZ5YuOh0OklLKnzS1Ikr0RFMhqmaAbMjNCLmt6DJ0LmEwB4+gYxZqVP6RGis5pBpwtpTMyWlldPsH5radzGj5rhXvzPfRNRWo3+5o8h0vNRGg/if+7fQZ7570sd7gO/F4yW2M1VI6ZEehe5QVXVGmAn8CkhxDbgIyM/HwZSgNEm6Kqqvq2q6kpgA/B5IYSZ4OqmV/+Sp3sv2u1TEEL8hRDikBDiUFdX4mv1o8XnGKbpN7sSPY2w6KwWhhouT/u+s6md/uNn6Dtymt5DJxk8cwHZGefmK7KM3hb65uNq66T/WD3W4kXkbtswbcx5PMJoIGdrLcOXWklfuZSMtVV07TkUlTEA4Pddu1nX1jQ9q98bo9a8EeRF99edC/n+wIlz+J1ucraOLZysJQX0150lZWnwfI1Y4RtwBKo8kgz10lF8v/g7lKYTqD3NszIGAJRju/D99ydRzu+P0Qw1Yk1EHgJVVdtGvncKIZ4ENqqq+k1gB4AQogK4I8hx9UKIYWAVgVX8eImxIqBt5OcWAh6GlpGQQRrQO7L9pknHvA50A+lCCP2Il2D8WJPn8GPgxxAIGUTy/00m2l/Yg384uWWBdTYLqZVlMRF8iTUDJ8+js1lGBYGmw9ncjrM5UN5nzsvGvnQxQjfVXlY8XnoPnRpNFuw9NPNEM583/D4LmaXVgoY3chluDqLzHw0RhD0VT/gPW3G56dpzaLSc0VZSiPNyG0NnL5J9Qw3db8UnjwBARSBm1tIwvshe/K/9FNwxCmm4BvE/9+/o7/wHpKWbYjOmRswIaxAIIWyApKrq0MjPO4AHhRC5IwaCBHwR+OHI/mVA84jrvwSoBC6pqtothBgSQlwHvA18EPjuyGmeAT4E7APuA14dyU14EfjquETCHcDnR957bWTfX48c+3QMPo+kYz7IAeuMBjzd4WOIiUIfgUEwHveVbtxXQpf3xYJrPc9KCEH+6mwaZ2kQRJJnYkizI7si80h17j6IuSB3Ql5Cz/7jM1YnDIfebkWSktAYuEpv8JDbjFEV5FOvagZBEhJJyCAPeFMIcRw4ADynquoLwJ8JIc4BZwiszh8d2X8LcFwIcYxA9cEnxyUj/iWB6oQGoBG46gv/GZAlhGgAPg18DkBV1V7gIeDgyNeDI9sAPgt8euSYrJExFhyeSTHNZMTbN4iqqHHtKjcbdMbkrEi9ctaR6CkknOpbJG77QiWV96yYcZOnUInR9vJizAW5uDuiM/DcbRONFFWW6Tlwgpwt69HHofX4taQHA8RFIVFj9oT1EKiqegGYolihqup3gCm1bqqqPgY8Ns1YhwiEDyZvdxNITAx2zH8TSFAMNq+NYaY/7+l46c1ETyEiXC0d2JeVoMoy3t7Q2vhzjTBGrto3l/iG50b7P9mxZxlYvQ0qasrxOEGWVRQZFBlkWaAqoCoCRSXwswqKIlAVFUURON0SPdNUvBkz03DMIqwzAVWl683DGLPSybpuHT37Y9Ph0e9w0taVR2HuLEMn8wiRHpuyU43YovUySGJURaHj5b2JnkbEOM5fRjIZw2Z0zyWGtJSYlhXGEtkbv8z1+YjJrsc0g8V347HpQwE6S+xr/L09/fT0HAupkhgt+77+Grc8uIV0W/KG3mKJUr8bTDZ0VVsTPRWNcWgGQRLTX3cWd2dPoqcRFYrHS9fuQ0nT+TC1qiwucd9YMNPmRRoTcYSKqon4lWP6Bh2kVJRO23UxKlSV9ks60lfObpi+oUw6miT8bgW/Vx6twMhcbKK4oCtpchXU9rPInRcQeiOicAXCknxy29cimkGQxLTPk3BBMPrqzkWU3R9P4p0ZPlsUr2YQzBZVUelpmr4cLtJEwpkwWN+IzmzCVl7M8Ey7J47jzK/2kf9Pm8iw94bfOQhOr5U93zkeNGTXCNSXFbD83uUUF3Qmh2Eg+/D/4Rug02P45C8Q+mRQbLy2mV9qJtcY7S+9FX6nJMU/OET6qhjVmc+QSBvXJArfoAMlSvlijYlcuSTTX38Za3HwmHTvwRMYs9Ljdn7Z7UGIka6WMRjr9a8doLktN+okQ1VVOfSMM2T+juNiGwe/9Qovfa+HK705s51uzBAl1SBpa9NkQDMIkpiBE6HFVJIaIXA2dyR0CpIpOZMJx+Ma0gyC2XDpZCBMFaqZlhRETyKWOBqbMedmYsxMm/VYstPN2998lboD0TV/6uzLpXNvZMmTjktt9LQmgYdgBP22D2pyxkmCZhAkMTc9/2NWfPbjGOJQ5hRvMmpW4GpLbNZ0spYbjsc9nOgZzF9kr0L7/kDTK701uCKlMSMVd+fMXPDR4OnuI6M6gs6JEXL+N29y8VIuqqLil3XIcugH5sWD0SXOpmQlxwNY5C4Be3KWK1+LaH6aJCZz/Soy168i98YNvH7HJyJSZEsWdObExwOlJC03HE9vp0RWUfj9NKbS3aqMtsMePNMYtDdC2splcU9utZYUgKJy5ZV9ZNaumpV65XgO/+erHNHpUGUZa2EuGz+2nKzU7gkNh64y0BC5N27x7RspLrgSkznOGEsqurU7kWrvQhiSX3ztWkEzCOYBBTtv5Lqff40z33qU/uNnEj2diBBS4p1PV7soJjMX9/WzrEZbIc2Ey+OUst2dvWRfv47ufWPaAKbsDPrC9DCYLbbSQvwOF57ugBdi6PxlMqqX03c0Np0c1ZGmSs7WTl7/SieGVDvpVYuRjDr8Ti8+hwt3zwDensi1P4aae/DKaRh1idPO1m18N7qadyXs/BrBSfxdWyMiyj94D7cfe5p7Wnaz4vOfQDeNizRZiGd2d6TMBw/BYGMbzn6t2iBa+tr9NL0y0Tj2Dg6TUbMCyRBY59jLi/EPxk+DIm3lUvxDzlFjAMA3METfsTPkbFkfl3P6Bh10HTjNlTdP0HPkLIPnmqIyBgD6TjSy9zdOVCWBHketoiAp0QyCeYa1MI91X/00dzW+TMVf3Y9kSL6HnmQxM3Aqus5/8aD30Emyb6hJ9DTCcmL3/AkFJQsnXp9aajh46jx9R05jLsxl0W1b6TkQP/2J7BtqGDx3CU9PECGhEUXDnG1BW84nBd2HznC5JS9h55eFjov9sfGiaMQOzSCYp1jyc6j97pe489wLlH3o3qRw0V8lq3ZVUngIAHoOnkh6o6D59bM0n55fqoVev8JXdp3m1v/azVd2ncY7h+WT/R1+Og82Bn1PMhqwLsql/eW95GyrJaNmBWmrlmFIT43Z+XO2baD7rSOoYYSlunYfImfreoQ+OSOzx366H6d37sJqLquVxmwrJ/Os/Kfj1/y/89/m6cafz9n5NcKTPE8RjRlhLy3i+p9/jZr/+HyipzJGEjV3V70+ut86QvqaykRPJSRHHm+mp2V+hA68foUV33yOJ5rPsPHd3TzRfIYV33xuzoyCiyenuW0JQfqaykAegSzTtfsQfUdOB1pgG/WB5L9Zkrttw4QuiOHo2nOY1OVL4qqFMFP8Difnj06txFHjVAJo8vp5sdzMrmVWPPrA7/Bk7z6+f/wLcTmfRvQkp+mqETX2JYsTPYUx4igXO1P6686Ss7WWrj3J0WNhMr5BB7t/eIktf1FKzuLk/rP815fPYMv0UVcHBgM8/DCsXu3jX18+w5d3xq70Lhh97T4uvBg8HJWztXbah7W7sxdLUT452zZMO7bq99Oz//i07ZRzt22gMwpj4CoDJ85izssibXVF0mmLDLYNjv58LsfKvkIjnTYdJlmlut3N1svOmJ1L8nvJH/LRmDUxf6DfO7UT5fne4/z+wk+QVR96YWB78XupydsWs7loBCe57zwaEZN93VpqvvV50tdW8tr2j0TUIz5eOBqbEnbuUMiu5O4uKDvd7P3vFjZ/pCipjYK9F7u5690BYwAC3+++G/Y9Gf++G01ndKOZ95PxDYZuJ+1q6cDVEro8L6WiFNUv45gkRZyztXZGxsBV3Fd6cHf1JZ1R6ulz4PFlourh2WUWZClQ0ujRC/rNsfUUDKTY6LAHv64fOfgJDMKEAKoy11PXM9bUza/62NX0K1Zl1GA0zj9NlvlE8i3lNGaEKSuDqr/7MKmV5Qk1Bsz5OQkXJApGztZahi+1JHoaYfENOnjjO2e5ciF5wweby7J55hnwjeT1+Xzw9NNwfen0aoGxIpQUh946+3r2oXOXUHy+UTEwnc1C1nXrYvMQVxS69hwi54aa0UqIRNN/8gJ/+Owhnv7V5VFj4Cr+GT4dZEXluVPtfPWlep471Y6sqPSl2vjFChPDpumNDJ/qwat6JhgD49GMgfijGQQLjP4TZxN6flMSxkoBhmwuPN3zpLWsqnLxZPJWHnx+exXDvQZWr4bPfhZWrwZnn4HPb69K6Ly69x4NGRKIFGdzB+ZFuaSvrcSUk0HP/mPhD4qCrreOYC0tJGP9LFsbxpCe90ztbaCfwbpCVlT+5LE3efjAAdxr6nn4wAH+5LE38SsKbv1UQSWN5EIzCBYY/XWJNQiMWekIvR5jRirW4rw5FwcyFmRhKsufsr3+S5k4HqpFn2qb0/nMlJbXz9LbmpxeAqNe4vQ/3MF7Fldx8Mkc3rO4itP/cAdG/RzcTsLYSV27D5K9uXrWpxk6ewG91YrzUtusxwqG4/xl+g6fIm11BZkbVsflHBGzJJPhd0w1CAxy9EbpC/UdtCu97D8s87Wvw/7DMm1yL3uOz+5zNEqamuFckBx+K42Y4He6qPvid+b0nCV3biSt0EZKliDF7sKkd6G/u3JUXtXnL+DihQwanz/NcFMgfisZ9ChhSrYiYdGNaynZlIUkQYdO4kj2AAOrjKgGQdFThehcgSXOQIUeDDq6brbit60g/dMzjwXPJfX7FDa/Rw0qVZtojHop7gmEwYgkGta99yg5W9bHXbI4FlxNMrQuLsBWWojscjN8qRVPV/z7L1yl97Z00E29xtpT9CgGI5IvckXD4639bN8pT8gv2XG7zDNtfaycxXVcmpLcVUILBc0gWED4Bh0ovul7w8cMIchct4ySLUUsKesEJmcij/3hG/Q+Kio6WbY0i15HJSajD5txAIcnjcEhM6oqcA6odBy/Qvfhc+gsJoRON6WNq2Q0kF1TgdBJZC7NpKTSi908BATyFfSFRbxSNrb6b37/1Ha0trPueWMMALTvPUdD6QqW1SafQZAoZF9kq9Zk0uWIBGdTG86msVW0OT8H6+JF6Mwm/MNOfH2DePsHQ7Y3nimujcE7K3bb9PymysJ7zwh0vsgSclcXpPGlZ+ChhwPGgM8HTz4FNQ/MLr9kZ+n7ZnW8RmRoBsECwpSdQcHtN9L2/BsTtuusFsruv4uUyjK8fQMMX25j4FQDzuZ2LItysBZkYzQrGMx6+hq7UBWV0hsKcTtVmnc3MnhurGqgaMd6VtxoJtUywNWHcSQISZCVejULXZBiGSTFMlLylAcVFQL1vgqEELi8Fp7/whFUWcaYkUrpzrUsXePBanQS8BlPzWY3RuDeHF5uxpCViq9nMOy+ycKJ354jr2QJqTnJp0iZCGRveBdBzpb1dO07OgeziR/uji7cHV1T3xCClIoyzLmZ9J84h69/dteyXJODt2r6ZL2WNAP/s1rw3rN67MMTW3P6TBZOZAnqsw1saPdR0eVEVaG3B9asgbvugueeg95eeOHfX6dqawl648weOXaj1u9jLtAMggWEpNfj7Ru7QWRUr6D0/rtY8sC7MWZM36td7e/A9+inAi82Xr0kAg/7ZZWZ7P5VoG64YvtiihZdAeJTvnfVNW4xuii8pZrcylRKinvQ6cInA6YMOkDVQyi3pF5i+KPLMH4j+V3JV1F8fprO6Fg1NcR7TRKJ/r5v0BFWRXDeoqoMnb3A0NkLCIOelKUlow45yWTCkJ6CEAK/04Wnqw9X65VpyzQBOj9SEPpvBuix6vnBOh3FAzqKBv04jBK9Fh1tqXrUkWOfTjVQnqPn9Mtn2bwF6urAaoWvfQ1uuQXWrpV5/dGj3PKJ2Sd9asQPzSBYYKz43MdRZYXMmhXYSgojO8g2fWWAXufn5g8YRx7Wc9cyddOyLukMAAAgAElEQVQOF0JELn8s+TwYZB2+UJnMioq10ct8e1Scf6GR4opS0vI0L4HRFr42frC+kYz1K+k7fGpW55rLOP5MUH1+hhouh95JkrCVFGLKyUBnteAfdo5+LsrqbNwbIqwKEoLmdCPN6VOVDa9yIdNIfbqO3S/Bxz4GX/7y2Hv33AO/e23m949HDv4fMozZfHLtwzMeQyM8mkGwwCi6653RHxRmhZCIpLZoz/lyRTo+fYhHvayy7N/78P/+xCxnNvfILg/nDgs23J7omSQesy38daH4/IGHuSRFloUYhIyaFfQdOR1+x2RHURi+3Mrw5dbAayHI2LCaDlsXXX9ZHPZvP1r67AYkKaBL8dBDY3kETz8NfovMf3/yWRavzeOmB6qjDB+o9HmDhFA0Ysr8yrzRiBPz9zLoyy/khVV5HM+Y3hgQTj/LP9OO/3fx634XbxydbtRQqjzXCKYIq1idTe3kbJl5UyvJNP1KeF6jqvSfPMuVz5ThK4t9CW5BVTbZeYL+fli1akynoq0NzM4r3PeONjreOsr33/tL/N755qtb+MzfJ4FGDJmfD5rW4mJ+usTNifTQnQLTj3hw70kuDflo6am7xKk35+fvKZboDZF/Bj37jpG6fMmMzjN8sXVGx80HVJcX+7PxCf9VbC5Gl7WIjGyJrGz4/vcFrZ0G8vPh5En4+tcD+QWZKV5efzT6xM9eT3KHceY7mkGggXLs+URPYUa8kDsckcsz/eTCWImceao+acWK5gp9FGkUis+Pb2AIferUEtRw6GIgg5zUxCkKKOkk3vu121n/wHasq2u598Ed5JRnc++9U3tfNNVFb5QcbH8pxjPWGI9mEFzjqO5h5L2/TvQ0okdI9Jkju6td+rAd15fWY95aMb9dwarK+SOJnkRiSc2KLifA1dZJWlVZ1Oe52stgoaJY4nfrl3QSVVtLuPmjNVRtLaFkXX7Q3heL1+RFPfalocQqsS50NIPgWsfjAHkOxIxijCrpRkuewu5r1tHxrhTq/72AC3/cRPePNuL97HqM71qFZDaFHyCJaH2rkaGu+ff7ihWpOQYWba6I6pieA3XkbK2N6piFbBBI6TacN81dHetND1TTM2ic0Puid8jITQ9ELzE96NVCBvFEMwiudfyRy5ImC6rOQF9u7syONekYqrbS+p4Uzn4pm4t/qMX9T7WYb6xEJEkHulAoXh+njtgjqsdfqKy9WWDMSI3qmO63jpBRE3kzoa7dB8m/dQupVeUIXWzbACeajk8vRs6dO0NYb9TzqcfvZ9GWan73WgGLtlTzqcfvn5FIkVdJ7hbm8x1xLWUu19bWqocOJU8v8mRAuXwc/xMPJnoaEaOY7fxyhYkr1tgHQaUBH7l7PGS82I/77YaYjz9bhCSRfUMNXXsOsfb9K1hWe+3a81cu+tnz3TNRHWNelIOnqw/VHz4Pw5STid/pQh52IZmMpFSUYkxPBVR8/UM4Lrbgd0yW7E5+/Btzaf7u8piXG841JsnC+yv/lgJ7aaKnMu8QQhxWVTWoy0wzCK5x5MPPIO/+n0RPI2J+vzaHCynxv2YNbR5SzvkDuVcy5D7Vl3AjIXPDKnoPngy8EILV71tORa1IyuZHc8GRlxUu7IpOKyB7cw3de8MnYmTfUEP3W9PvJwx6MtYtR2c2MXyxBWdLR1TzMGalI+l1+BxO5GFXVMfOFGE00PzLdfhK50fHz0hZlrqG91Z+KtHTmDeEMgiS30eqEVfUrkuJnkLEqEYLRW4DKf6xxLIKh4HFnX1IHhcoMr7ULL69ZvYPSF+Bid6CMbdqzzuspB7IZNELw/heOBNSDjZeDJxuHHuhqpz439MMdFZRc4tAb1pYbu1IWL1Vpf1YFq72qb0tpkNVwv/ehCTRG0aUSB0RP3J3dCO7PVgK87AvKcY/5GTgdAOKZ2ooLmP9ShSPj+HLrXh7+ke320oKsS7Ox3GhBVdr/NRAez5StOCMAYDzg3U8cvAT2PRp/G31NxI9nXmNZhBc46iu+dPoR3hdbDobejXlMRmBOCTdCcHgJiuDm6wYP5TCkp8M4XmlHnWGSngzIVjeQNMrZ+i7uIjae9LIKrq2/pwNZh3V9+aw978iNwiGzk8v9WsrK8JakAs6HV27w3fF1NssyO5ATNvVemX0Ya5PTSFr4xr8zsC1KhkMCAHd+44FHWdUSVCnI2frenoPnUJ2RS7bHQmuWxcx8MHisPtZ9nST/mw3kldF8qr035zG0H0RSqAnmGH/AD+s+zL/Z81XEj2Vecu1dQfRmMoCczc7jTriYhCMw1tqpuN2mbxj6aQsK0Ho9Xi6exkcv4KPMWmrljFw8nzQ94YutPPaf3Sw9PblrLxBxWC+drwFBUv1LH5HFU2vRpZP4O3pJ3P9KnoPnxzdllG9HFVWQJLoChEmGI99WQkDp4KHkPyDQ3TtmUFoUpbp2nMYW1kRqizjbGqPfowgeLfk0fFQZUT72vf2Y35tLPxhqJpfegw9ng5eufwE7yx5Nw6vg1+f+zZ3ln6QfPviRE9tXqAZBNc6YmElpjmMc2TgqIHmN+Mb4FgK89BbJt5ALYW5DJxunHWjHL3NEmY+Kg3PnabtaDZbPphNau6186e99iZB2wFrxEl+im/MYExbXUHf0fqoz2ldlIsjhLdhNgxfbCF9TWXMDIKh9RGWUCoqtpMzz2ew/rET7/IU/IVhrtVY4FdAH/zetb/zRQ53vY5PDXhvflb/CAZh4pNr/kVroxyGa+euoRGcBWAQtBYXU5cWiNl2mJzETYZtHHrnVPd9sPjv1W50qSuXYc5KZ6jhMq62zqjOlb62ip63I+vD4Gzr5o2f+tn6kXzS86+NP2+TXUfR5hIuvRTZg72/7ixZG9fg7u7F0x2+tXYw4p3W6myOjTEg2cw47siPaN/U37Yizk4Mv9jq3fQqKkih/6akQR+LvnkZzHou/mIVSmocO3P6FZbcfRRHbQpDN2fgui4TdZJX7KoxMP71ie5DXF+wI37zWgDM/6eBxuxYAAaBVwcn02VOpst0W+bGQ6CPsuJs8NR5OncfxNXRTdZ168jZWos5PzvscZaCXIYvt0V1Lk93P6999yIX65RrpiFSyYro/p86mwVvzwDu9pl10IukdHE2eAccMRlHGXZTdn8dtheuQIhrQbhlcn7YMmW7/lAn2d9qRLhCJ2OmPt6K0juM0jZA+mNTx4klhssulK4hrLvayPvMKcpvfRvLnu6wx2nGQHiujSWExvQsgByCXMfcK/d5UwQziq4qCj37A8llOVtrcXeEvpFZixfR8/bxqE8juzwc/vlpWjctZfVNOtLy4rhiSwKyi3TYinMZbg7vfdGZTTgam/ENDM34fL1HTmPMSp9QLZCsKJ1D5P5zPepvuui+L5vhW3JQJ1WlmI4PoAwHT2RMebwFVRL0fHr6RlEpx8dCDRmPt+OusuGtsOMvssT8HmM8P9FYUlxeCr54jr4/HWLwXXn4i4O3xHzs9DdxyU663K3ohIHP1X4vpvNaCMz/5aHG7OiPrn46GbH1drF8QCIviBs/XvTVGGbfAEdV0dun7+ebtXHNjIyB8XS83cDLXz/LKz8b4vwhBWf/wmyOJCRB5tLw8WGh05FevRxnU3Rel8kobg8pFaVIxjgZWnHw7IhT3eR85Qzl9xwl/WeX0XV5YKRyxbo/tGFjvOKb3kugqBhPjVUrKS4veZ8/TfF7DlD+vjpS/7cZfZNz9FyzxXR2eOoUXF7Sfn6Z4vccIP1nl4N+fk3D5+lyB7pYyuq1K/8dCk2Y6BpG9Xnwff9+UOeudC6eOHIK+EHl3Ekxl/+gH/XR4KVk0aBPsWHJy0Znt9J/LBAHT19TibOlA2/vwKzHn0zGisV03w45aUZutJlZKDUJp/Yq1P9uev0AncVM2oqlEyoMZoutvBghwNHYHLMxr2JelDPjkEakCJ0OkWFFHXKjekI/JCWbmeEtGQxty8B5QyaqNeBg1jc5Kb7vQNhzSXYLvgo7wxVmPJU2vEts+IosqPboHNXF/7ce/duh9Rr6PlZK/1+Uhp6P0PH52v+K6twLAU2YSCMo6pXGBWMMeP0KDz55gD80tbB4bR43PVA9I630aGh6t4XFj+lnHU/2Dw0zNDSy6tHpMNit9NfFr6tb3+km/nFtKlccOozA32faudFiotJkIFOnwyRmn5bpdcp0t6gM9OoY7lPwexTMKTpMNrCmqGTkqKRk6xBhktWiISV9+sWNpSAXfYotpsYAwPCFZsz52ZjzsnFfCR/HjgZDig1VlvF0xq+hjyrLqN2RhU6UYTeWF9uxvNiOZDMzeGsWkkclt91OJBkPisOF7oiL1EmVnVKmHX+RGXehEU+hEX+RGW+pFV+Jlf/f3nmHx1VcD/udrepttZIsyZIlW5Yt23KT3CvFgAGbYnoLkACBJJAEAiQhkEA+QkIq5BcghRSSUEIPxYYYN2zj3nHvkm31Xnd3vj/2ypas3dWutE3yvM+zj1Zz586c0dXePffMKTL6rM+wlJj2NtDTXSvxL0dpmmWhbcRZpa/bHKAXoBc4ZPCTi4U7SiE4h5GN1RCdBI39u4JYm81BwbMfEJ3UzqIF8N57pfz+o529LqDiLbZUM7qrC7C/5l0EgFfY7X3a2/aWRrPzi7gNeLqqgac73dJHmAz8e1ASI81GrxUDKSV1ZTZKD+s5sbORqp1HezR7G+NiMMVHMW5BEoOG9v06JSS7ni+hMJ+mYyd8ju7wlpaTFURmppFQmO9XRa5+72FMlgSsM4uo3bU/rPwVHI0txLzlNL9HzizySiFwO1ZVA7qqBqK2wdkbaLpB8Rx/MpfWwngA9GWtOKq7bxl0H9TBoJ8f4cgfRzkVAI2kPx8h8T9ltIyJw/jdmVDcB8EHIEohOIfR509HVhzGse6tUIvSJ57+ZDfRSe1s2wZGIzz1FIwZ08aylzdzwd2B/cSfuDiSlNcCOoXfscdGnFYIXLG7zcb4I2Uk6XR8pUHHVSeSSc6AnMKumwvSITl12M6JAzpO7qjwyqGvM+11DbTXNXBkeyKD3PureU1ssh5jfAztnTz0LZMKqdq0K+BRAc3HT9J8/CTWmUVUrt2Co90/87VV1lC+cgMmS4LH5FSuEHo9SRNHgQBbYwvSZsPR1k5EmtWreg7e4gjg39ZxopaYpZWnFQLzHu9VD92OCuJeP07dDc4MjaLRRuJb5TjqmzGtbubi524MiMz9Ga8UAiHEYaAesAM2KWWREGIs8AIQAxwGbpJS1gkhLgR+BphwPoA8JKVcqo2zDBgEdLikzpNSlgkhzMDfgYlAJXCdlPKwds5twA+1/k9JKf+mtecArwJJwCbgFill/6vlG2qCmHo3UKw+VMGCq5zKADh/LlwI//kscHnhO2gcGUHEpKG0rAtclkJ/s9UqkV54flc5HJza0siRbeUcAWouKcCkhXXa2iUlG8toKu27mfz4ij2sastj+CQ91mx9r4s1CZ0gb14W+5ac2c9vPlEWcGWgM+UrNxA/Ko+WUxW9znHgirbKGtpq6rHOLqZq3XaPqY3jCoYRkZxA7a6DVK7rbr1qOHiMxImjqN64s89y6SPMAd3eAkhYVkvtNc3YMiIx7fXNFmH5zUFn2vHrM4l95wSOWme8sNDriS8YFghx+zW+WAjmSik7f/r/BDwopVwuhLgDeAh4DKgALpdSlgohRgOLgc7JsG+SUp7t2XcnUC2lHCaEuB54BrhOCJEEPA4U4cwFslEI8Z6Uslrr82sp5atCiBe0Mf7gw3oUAF4UewkWdofk4y9PsrWkhrEZCVw8Mg29F3vM03KSeeu9Cp56yqkMtLfDu+9C1ozUnieVEtHmQDQ7FSNHgo9e4zrBl7/JYOSjBlqWB/bG6C+qvE0kJyWzSs4EIh3wsbKgL5xcu4+TayFh5GCyxscyeLiDyDjfDZjxFtllyyUY2y9nU7tzH+bUZKKzM5w1CvyF3U758vUYE+JIGDcCJEi7DWl34Ghrx9bUQltlDXW79tNThZLWskp0ZpPLIky+kFQ8pndpmn3AUVpL9s1bKbt3MFF7fazxICWWX+3HYRJYX68443sgBFseeZbc268mcewIf4vcb/EqykCzEBR1VgiEEHVAvJRSCiEGA4ullAVnnSdwKgjpUspWzULw4NkKgRBiMfCElHKNEMIAnASswPXAHCnl3Vq/F4FlOC0D5UCalNImhJiqnX+Rp3WoKIPu2Jb9BcfmD0ItBnaH5Jp/rOKEo4oLL7HzyUd6BumSeOOWGT0qBR0+BFGJ7Sxc6FQGqupNXvkQ5PyxFv64+fTvRmsC+uEptGdE0DrIQEuy7nSWNrsJ2mMF7XECW7QOXTvomx0YGiUZr9fR6mU+/VDzzoQI3pjUs1YwpNzGT98M/hcqgM5kZMw1eQyb4Ft556O77Kz7k++piAOB2ZqEISrSv0qBH7HOLOrTl7kxLgZ0OtprwrtAmjEhzqOMafNmMOXPPyUq07uMjv0df0QZSGCJEEICL0opXwJ2AAuAd4FrAFeltK4GNkvZJY/ky0IIO/Amzi0AidOCcAxA+4KvBSyd2zWOa20WoEZKaTurvRtCiLuAuwCyslSBi26EiYXg4y9PcsJRxdqNdoxGePIpO5MnVPHxlye5dNQgj+eaDDp2PXgpT3+ym9Xv1ZI7OY0b7vIuyiBicy2dnznay2toL3c6bxlw7od5Q2vPXcKG7V5WRZxwJHSx2o62drb+cxeVx/OZfLnB62iE9GECY1wM7XX+yfTXF1rLq9BnpTsT84RheHdf/RwiM1Kp+zL8t8pihg72uD1ycskqPixcwJSX/x+ZCy8IomThh7cKwXRtCyAF+EQIsRu4A/idEOJHwHs4/QVOI4QYhdOs3zlf5E1SyhIhRCxOheAWnL4Drj7tshft3RudystL4LQQuF/iOUqYhB1uLanhwkvsXfwA5s23s217bY8KAYDDmkb2D6xEReJ1ZrSIAy20bDjYB6n7IWYje7yscVDct9w9fuH48j1EJxYwZpZ319Rg0pEyLoOSFeGxfdN0tJSkotFUbfBvuKM/aDrec1Iy66wiGg87LRxmaxJ6swl7axs6vR5dhJl4k5HareFtGfOU/KuDtupa2mpCYw0LJ7zKVCilLNV+lgFvA5OklLullPOklBOBfwOnVUUhRKbW71Yp5YFO45RoP+uBfwGTtEPH0SwM2pZBPFDVuV0jEyjFuQ2RoPXt3K7wEV3ORHTDp4M5OqRyjM1I4JOP9HQUomtvhyUf6ilMj/fq/HeyHZRHCZ/SpGa+3/vKbuFGgyWKo+kRNCdGgt79x7o8wYD04mk7ok2SdSo8fHT3vLOLIzu8t2QlZ4VXqiXppwx9/qb5+Emistwr29E5mVRt3EnT0RM0HT1B9cadVKzeTPXGnVSu20b5ivXUbt1NdE4mydMnBFFy37DV9xymmFQ8hpxbFgZBmvCmR4VACBGtPdEjhIjG+cS/Q7MWIITQ4YwCeEH7PQH4AHhUSvl5p3EMQohk7b0RuAzntgM4LQy3ae8XAUu1rYTFwDwhRKIQIlGbe7F27DOtL9q57/buT3Buo8stwnDpd9CNnBVSOS4emcYgXRKTJ+h55GGYPEFPuj6Ji0d62NcTOqoGZfBmoZVj3tr2O2MPzxt1b/jvMMmjCyL56nUR/OCKaDC6tgKsGOzdmosOtYE9PKxHABv/eYCqEu9M3MmDwkdugOpNOzFbw6/srnXGRPRRkS5TcMePyqOtqhZ7Y89Kc+Oh41R8vomYvOxAiNlnvMkiOfan30boVCb/Hp0KhRC5OJ/2wbnF8C8p5U+FEPcD92ntb+FUAKQQ4ofAo0DngNl5QCOwAjACeuBT4DtSSrsQIgL4BzAep2XgeinlQW3+O4Dva+P8VEr5cie5OsIONwM3n+Wr0A3lVOgex941OI5sRtaVI4/6MdGOD3REGWwrraUwPd5jlMGxrMH8N7WRBnPvP8Smoy0MvnEjjrYBkNdcr+M718ZwKt75dJxaa+fCHa2MK9cxqKINbM4n7Htvjac2qoe/mZQ8/1YrieXhZUGJTLNw3j3WHqMPHHbJu48fwN7ko0d6ALFMHos+wgQ43QnaKqup3bk/ZPLEj85zzi8l8aPzQErq9hxG2mzEDB1MS3k1Nh/9MFJmFVO2Yn2AJO4d3kZ6RKRYGPPENxj61WvQGQd2ITBPToWqloGiC46j27C9+eNQi+ERe3Q8vxrvnw9tzgu18JfNPXfsB7w4J4oVI8zd2uObHNz4hfPL8Q9ze95PBZi6r41vrGyDMFOWCm8sYHhRz0rg8leaKN8U3v4hyVPGUbtrf9AdIPXRkZgS42l24UMgTEaQEtkLh8NwVAiSp03wKQlTfMEwZr//AjG5rnzkBwaqloHCa8Sg/FCL0CO6thachqa+o2+0Ex5xFn0nucG1qbw2Sue1ItDBmjwTx5N0fG2NnqEn209bGEKNLiKaM3nN3GPJjqDcf8n4AkLF2i1EpqeSMG4kIJ1bNHo9bVU1PmUk9JXEMflUrHVdlEuGmQLYV4TetyRXtbv2s2Tqdcz58CWSJo4OkFThi9o0UXQlTKIOgoaPN4xw5b3xESxzYR0AwOaA9cfg/S+dP23eXeNjFgM/uiySR64MrcNpB4njC8h77kVEVmGPfS1h5kfgjubSU5SvWE/5ig2Uf76J8hXraT5ZQfLUcQGZL2VWsVtloK+Eo7W5pdz3bJEtZZV8OucWTixZFQCJwhulECi60g9SGQtbm9/iultSB4aRbFe6gaoYFx9nm4OYdzaR31jK926qI7+xlJh3NnmtFACY2yWYQ7+vOv7Z72GMisZ49ePopt3gsa8lXSD04RVt4C0Jo4ZRsWYLydPG+3UNSUWjA2rSd7TbMMSGh/IIzrTK9XsP9+pcW0MTy+bfxbYnnsPRPrCsJp5QCoGiK0YzutEXILIKEZbBoA/9F0E3pCTS5qenkX5qIIhItZA8fQLWmUUkTxtPo8lNx80lZCTb2b4NnnkGtm+DDIsdNnuXPW/SgTZ+/GELtIb2pph63hTSzpt6+nfD5EUYFv3Y7f+nKUrPyCvDf/vrbCyTCilf43yCr1i9mcTxBejcRIz4gjEhjoZDx/s8jicq125BZ9BjnVVEVFY6hFghixmW1acHHGm3s+PHz7Nk+g00+7m0dbiiFAJFF4TegOHCr2O8+nGMt/4G4z0vo5/3DYiMC7VoXYix+eeb3OBm3z2cicoahK25lYrPN1G+cgMVqzcz9YAbJ7CTDSxc4Ez0ZLfD4sWQnAzsLIM2z34BxQfbuP+TxrBwLBz70293a9MNHo3hqy9AnNXlOSMmC5LH5QRaNL9hnTGRynXbuuzjV23YjmXqeI/nCZ0O68yJWGdOxJTo+nMaXzA0KOWT26rrKF+xgaajpQgpiR81jLgQFREyJSX4ZZyq9dtZf8/jHH/3U5Yv/HpYZMEMFEohUHhEmCLRj5qL8cafI1L8UKPWT0Ta/aMQtKT0L7NyTO5gpEN2Cwmbv9dOcp2LL/i0GN59D1pa4Mor4fHHYdo0yM+2EfvmBo9KwUV7wsORMOfWK0ie4npPXReVgOH2/0MMndT9mF5QfLnZmXM/zIlMT6Fqi+saDHW7DnhMuBU7IpfylRspX7kRoTcQnZPZ5bh1xkQqVgc/kkY6HNTu3E/drv0kT5+AyeKfL2hv6Wvhps4cf+dTVl79LUreW8onM26g8ejAzIOnFAKFV4g4K4brnkRXMDfUoviVmpHhrRBEpqcQO3wIscOHYJk6juZTFS7DxWhpZ9p+FzfA8RmUVOgZOhQOHoS1a+HnP4ft2yE9DVjWPRe93i6ZvreVkcdDm6nQlJTA9Fd/zZS//sxjP51Oh3HBw+jn3N7tizM60UDRDZluzgwPDLHR6CMjsDc0uTzeWlFFgoeKfObkxC59bU0tp5WguIKhlK/a6F+Be0HF55twtLVjnVnkUzbRvuDvL21pdyrINdv3snjytVRu2O7X8cMBpRAovEYYzOjn3Yf+vK+BbmA447XkRqCP9rYesH9Inj6BlNnFWGcXn7lBCoF1xkSSp09AZzISVzAU66xiWsqqqN97mPq9h6lcs8Vj5riEZhd+FQYdDVdMoLRMx6WX0qVWxKWXAkdrukQfGG2SX7zfyr1Lm0KeqbDouR+Sfd18r6sd6sdfhuG25yC6a1bAjHwDeZcXuDkr9MSNyKXhwFGPfVpOVhCRmuzy2NkKYuupChIK850Jh8IobbKtvpHylRtInjI24HOZLAm0nCgP2PgtJ8v5dNbNHHv7k4DNEQpUYiJFr3CU7sb232eh0fewHn/wr/HJlPjJoXnk/cdpWbMfhMCcnEhreZV/BnZDTO5gGg6eSadqSopHHxV55sau0/XKGcoeG8FjFxk5kuxCWXttGyNSm9m2zakMNDZCRgakpeEsGf0elFToabhiAtE2yKy2k1Vp58YdYKoJfsZC6/QJXLDyXz6VPu7A4XBg//QF5M7/nWmzOVj290aqdhzxp5h9xpcSxBGpFmKH5+BobUMYDQi9npZTldTvcZGAKUwrLALE5edQt+dQQOdInFBA9aZdAZ0DACEoeu4xht93U+Dn8hOeEhMpC4GiV+jSR2C88ReIdPemzEDSpvPfzU5GOL9A0+fPZuGRz8i6br7fxnaFLqJrvoC2qtquT3m99IzW17fw+Kc2YppdnF+cTkkJjBkDDz8MWVlOZWD79u7RB40ROvYMMvLJ6Ai+fbmJg5nBtaAADLpkVq+UAdC2EObdi+Gan4DJKbvOoGPK1ZHEDgmfmvdxBcOo+GKr1/1bTlVSvnIDleu2OR1KV6x3rQwASIk+KvjXzRvsQQjjM8QEKfxRSjZ+66mwy9DYW5RCoOg1IiYRw6In0I27JOhzt/pRITAL5xd01OA0DJERTPjlI0z4zfcZ+rVr/TZHZ0wJsQhDYLZczDXN3LFay+EvJUPKbc4nxSEW2qzRHD8BL74INbVOy0DnLYSFC+qTl0UAACAASURBVIGTXZ0Va6J1PHGJmY/HuEl6FCB2PvUHtj3xHLam3lsndJmjMNz9MiLbaaKOijcw+/YE4oeH3qfAMmUsTcdOBDQzoM4UhiHDQKSbrQ9/4mgLnv+LdDj4/MbvUrFum0/JmRzt7bRW1dBSVklLgK2S3qK2DBR+wb7zM+z/ewnswfkgvjzRQkVk352T8hIKubD5fBYXLyJ52njOX/r300+mrVU1fDTuCpqOnejzPF0QAp3J6Fcv6LM5mh6B0SEYVGPnwYURnEjUO/eTj9VARRNUNZFvrGK7toXQ3u60HsSUW9l4ba7LMaftbeW+lW3Qizz3vWXe2tdJntz3PWdHQxVy31oc5YdoKytn0zsVnPj4c2yNrh35AoU+wkzCuJFUBihbYAcJhfnUbNsT0Dl6i3VWMeUBfqL2tqiRv0mcMIr8b95M7leu6rHvwb++xdrbHz39u3VmEcO/cRODr7wwoAWWVC0DRcDRj5qLSM7G9v4zUB/4JB7pLQYqIvsWFpdkTmHR0K+j0+kY/8tH2Pf8K5xYsor0i2YCYE5KYPqrv2Lp+V/B3uKxkGaPRGWmEZmegi7SjGy3+1RwpTdklTqtBCtGmJ3KAIBOQHai82VzUPJOLWPG2J0+BO9CaYWe56viuatd0mrsrmytHm6mJlrH9//Xjmjq29/DGzIWnOcXZQBAF5ME4+ejx1kFY+bNYG9tY+/zr7D5wWf8MkePMphNxAzNCrgyAGBMiA34HL1FBnjLQB8dGRJlAJylrtfe/ijSbmfondd47Hu2H0X5yg2Ur9xAZHoKw+6+jmF3XUdkmuscG4FCbRko/IYuNRfjTb9ADB4T8LnibH0PF7xt5MPotBro+d+4mct2f3xaGejAOm0Cc5f8xadYdn10JNZZRSRPHUf8mOEY4mJoOn6SynXbKF++PuDKQAeOmAhWD3XzpKFFH+yJSefn/4zjsHkQ1yWNwICOr3ze7NYhbVeGkR9eYgJ9gG8dQlD45P0BnUJvNjHyu3cw+rF7AzpPB5bJY6ndGbiiRZ2xNYRX6erO2AJcljomJ7RbQvEFwxh01n3EFXW7Xft/NJeWsf3x53g3ay77/vAvf4vnEWUhUPgVERmH4arHsH/2JxzblgRsngRb376QsmPziTJ69yWfMrOI8z/7O0svvIO2qp6zvSVNHB1wk2iPCMEvZ+g5YtGT1ODAaJeYbGC0SeJbHFy+086aLEFLXArEpXDDDkl8ufNLZNbuVmoj4I3iSOxnF3+Skrm72wIekpi16CISC4PjsDrmx9+i5VQl+196LaDzNJ8oC+j4nTHE+FbdMpgEOtOfKTE+oON7InnaeGa//wJmL7Ik9hRpoY80k7HwfH+J5hVKIVD4HaHToz/vLkRcCvZVrwRkjryyRkjT9SrJiVkfyY3DH/DpnKQJoxj54B1s/f6veuzbXlvvs0z+xjK5kIc+9uzBnu8h9P3yLa1MOqnjB5eYaTaf+Rtfsq2VC3YGfrvg2JtL+HTOLWRecT6ZV1xAzJDAPfUJISj6v8dprajm2FuBU2IjkhNp2BecsMfGw4GtW9AXojJSaQxgXQUZogJtKXMmMeeDlzB4Ed3hsNlo2O8598S4Zx4kKj3VX+J5hdoyUAQEIQT64ivRX/IA6P2vdxrqq0ntpVV0xqD5p7cKfGHo165BZ3ZXRchJ/Og8mlxlEgwyffV5AEg92cydn5/5IxcebefmLwKvDIDzpl62fB2bvv007+Wcz0fjr+DQK+8GbD6dXs+0fz5LypzuKZD9RcWaLUTnZmKdWRTwkMDWsiqXynLixFFYZxWRMquYpKLRXo0VkZJE/Jh8IjP9E7JZvmojlsljXUba6MymHj9jPdFSFhqP/cZDJTi8dLhtOHTcYxVF6/QJDLvrOn+J5jVKIVAEFP2ImRiu+hGY/R8XnNTumx+BUWdiWtrFTBk0r1fzRSQnMeKB29wet86YSO2OfUEpIuMJ68wiarbs9stYU/e28o2lTYwoaeeh5baQlceu2b6X+AAXydFHmJn1zv95TBPcVxoPHqd85Qavv4x7i72l1WVRoebjpyhfsYGyFeup3rK7x/oCxoQ4HO02arfvwd7YRPzo4X6Rr/KLrcSNyCF5+gTiRjqzcposCTha23C0thGXn9MrBURnNHRJ+hVMGo+U8NlFd9LqxbaiO/8BAJ3RyKSXnkT04qGlryiFQBFwdJmjMFz8Lb+Pm9rqfWhORnQu35v4HHMHX9mnOcc88U0SJ4zq1m6ZXEj558FxFuwJf3uxT93byo8/c5AydqRfx/WFgkfvIsnF393fmOJjmfvxn4jOzgjoPA37j2CMD2wkgDGuuxLeuRqitNlIGJ3ncYz4kbm0VdcBzkqGtTv2kjihwC/1CGp37KPi803UfXmA8hXruyjSdXsOYatrINJHk3l07mBnWc8QUfnFVtbf83iP/TwpBAXfvzvgyq87lEKgCAq63CJ0oy/w65g5Dd7dlGKM8dw64rt+mVMfYeaCz/5O2gXTTrdZJhVSuWFnWKSKNacme2229AVbQxMVqzdjmTIOg4/VA+Py+1aCOGHM8KBFAgBEplmZ/vpvAhoL3lxaRmIALREAlWu2YDkrbPNsc3zl+u1EZrj+0o3KSqd25/5u7dWbdpE0MbAWDnA6H0ZnD/LpnIhOhZ5CxdE3PqZqs+e0yfVuHArjRg5l1KN3B0Isr1AKgSJo6Gd/BeL95ySTfKKE2FbPJmyDMHJnwQ/R+bEYkzEuhtkfvMiQmxcQPzqPyo07Q/pU0hlzgG+I1Zt2klQ0GrM1qefOwNinv8slW95lyM0LPPYbdtd1XLrrQxLHa0WIhMAQG01kegpTXn4avalv+8q+kjypkHHPPBjQOfqShdFb2mvqQH9ma63lZNeCP/amFkyJcRgT4rq068wmdCaj24gAEeiw0w45fM22GAIzuyu2/eh3Ho+7sxBMeukn6PvoQ9EXVJSBImgIUySGi76F7Y3HQPphL1pKMloM7Da7HksguGXkg8SY4lwe7wt6k4mpf3uGFVfeR+2O4MSWe4M+gOlqhV5Pwph8ypauJWZYNvbWNmweQsjyvn4DBQ9/DSEEIx64jcOvvOey34zXf0P6ZXMxREZwyaa3sTU1o4+M6HUtA3+R/8BtnFr2BSXvLfX72EKn67PznDfU7TlEbN4QTJYEhF6H0OloOVXZpU/tjn2YkxNJKhqDzmRA2uy0VtbQsN9DRESQrGE2D9U9XdFWXRsgSXyj9L+fsf3J3zP6B1/v5gvQeKSEGheWl2H3XE/KDJcJBIOGSl2sCDq2Vf/Esf4tv4y1tCCNjUmuTeQLcm5nTPIUv8zjjqP/+ZhV1wQ2gY4vJE4YRfWmnQEZO3nqOCrWnPFPiB+dR/3+ozhcRDRkLDiPmW89j057OpUOBxVfbOXIqx9w7I2PadZK02bfeBnT//nLgMjrD1qravho/JU0HS3167iWyYVUfrHNr2MGk9hh2dR7Uhj8RESqhZaKGu8scEKgizDjaA5s4iNfiMpMQxj0ONptyHYbjnYb7fWNSFvXe1bkICuXfvkRpgD7lYCqdqgIM/RTr0VY+7av3EGD3rV1YErqhQFXBoCAhql1oDObuu0Fu8MYwIQ0FWu2YJ115j5Su2Mf8SNyuz3pWiaPZfq/f3VaGQDnE7F16niKfvtDFh5bzvnL/kHevTcy/uffC5i8/sCclMCM137t92JU0tE/H8QiUpOxTp9AfQDzCHSm5VQlkWnJXkVlROdkhpUyANB0/CSNh0toLjlFS1klbdW13ZQBgKLnfxQUZaAnlEKgCDpCb8Qw/wEwRvRtoIgYTkV1/xcuSpnD+VmL+ja2l7RVBdZEGTU4jajMNCq/2Eq8G49wkyUB68yJJBWPAb2OqOz0gIUsVa3bjui0LVG95UviC4aeVgpihmUz+/0XPCZn0en1pM6eRPHvHyfKjUNbOJE8ZRwTfvWIX8eUtvDwOfGFpOLRtJyqcEbTBNFnprnklDO3Rw//05GpliBJ5F+sMyYy+KrehUL7G6UQKEKCSMpEf+HXez+AORrjdT9lWEbXnOFFKXO4KPuGPkrnPSc/WR2wsZOKR9Ne30TDAWdGs+bSMqyzikmZVYx1djHWWcVYJhXSVlNP+cqNVK3fTtlnX9B0pJSE8YEJEbS3tBKTld6lrXrzl1gmFWKMi2HuR38kwkuHw/7E8G/c7JdEMdYZE7HOLKK6By/0cKS1sqZbGGDcqDysM4sCVs67g5aTFVgmFXrsIwIYFRJIWiuqObXsi1CLASgfAkWIsX32JxxbPvL9xKQMTLf9DofDxpby1WytXE169BAuyr7e/0J6oL2hkdbyKhYXL6LVTwmJYvOy0UdHUbPly16PET8mH3OS5kwpnZX9Kr/wnMrYW1yVr9WZjJiSEpj2j593CckcSDja21k67w7Klq3r1fmRGak0l5zys1TBxRATRXROJnqTicYjJbRWVAMQnZuJ2ZJI1frtAZs7rmAodbsOuD0eziWfvSHv6zcw8bc/CGi4K3j2IVAKgSKkSFs7tjceQ5700VM/PhXTHf8XGKF6wfvDL6J+32G/jCWMBqSfcwn4uwa9dWYR5Ss3dGurWr+dkd/7KoOvnkfCmPyQRwr4m9bKaj4uXtSrXPyu/mYDjaSi0VRt2BGw8eNGDqXuS9dKgT4mCntDU8DmDgbDv3kLRb/7YUDnUE6FirBFGIwYLv0ORPiW7AZHeO3B6iPNfR5D6HRYZxb5XRmwTB3nN2UgfsxwEscX0F7f2O1YW1UN9pZWdvzk93w0diEfjr6MY+98ykB66DBbEhnfi/wEEWnJlK/eHACJwgtXiYz8idlNquWo7PR+rwwAZFw+N6TzK4VAEXJEXAqGi+8HPD9Nitxi9HPuRAydhC5nQnCE85Lc26/y+Zy4EblYZ04kZXYxKbOLickdHJAnSJ0f93drt++levMul9sZZ8eM1+7az8or7+OT6TdQNoCejAdffRHxozyn/D2buOE5YZO8KpAEOmFR1aad6KO7O6xGDkoJ6LxBQQhSgxC15AmVmEgRFuhyJqCbfDWOL/7j8rgYPBrDgu8hhA79+PlBlq5n8r91K8ff/pQyL5/E4wqGUbdrP/inBpFHHC7CnHpDZHoKzaVlbo+7K/tcsWYzn866ibE//Tajvn+PX2QJJUKnY8zj97HqWu9KaOujI6nux3vbvmCIjcYWwCd1e1OLWx+W/oIxIQ7LpEKSJxeSVDT6dE0LnUEfcP+BnlAKgSJs0E+5Flm6B3msu2OSLmssQoSvQUvodEx5+Wk+LFyArdHzDVFnNjmVgSBRt+sAydMnUNGL4kuGmCji8nPRR0X06BDXVl3ncZ9822O/dZbeDXE2Nn/QYSWo3dmz70tiYX6XhE4DmajMVFpOlPfcsQ+Ur1hP8rTxVG/bc3qbQHooJRxuXPblh0SmWUMthkuUQqAIG4ROj2H+t2l/5UFo7FrTXKTnh0gq74nJHUz29fM58Gc3Vg6DAVNiHFFZg6jeGJhsgq5or62n4vNNxAzLJjLdeSNytLajMxtxtNsQHVs1wmnyFUIgEdTu2EdMbqZPTmLlKzdgmTqOynXbu5nIpcPB6hsf5JIt72BO8lx2N9zxxUrQn55e+0JUZhpNJe4tSP6kYvVmYvOGnHbkbaupC8q8fcGUlEDciBwcbeGrvCiFQBFWiKh4DJd+t1u9A2EdEjqhvKTkw+UcfNl1Sub40Xk0l5yitbyK1vIql30CTcP+IzTsP4LQ64lMT6Hp2AmP/ZNnTKRi1Uaf56lcs4XEiaOo2banm4Nk07ETfHHnD5j51vP9PgLBWytBf81K6AuRGak47PaAWwc6U7/vMKakeNqqamkqCd68vmJOTmTUD+4h754b0Ef03fk4kISvDVZxzqLLGIF+5i1d2uxL/4j0R0GkACGlZOP9P0U6ustonVVE3e5Dp+vKh5rECQU9KgMAuj44iFVv3Eli4YhuCWuETheUdM/BoMNK4A5TUjxR2elujw8kgrFV4IqY3CyMCXHY6lz7r4Sa9PmzuWzPx4x44CthrwyAUggUYYpuwuXop1wHOmc+fMfuldhXvxpiqdxTtWG7y+pw1pkTKV+xwWX+8lARLBN21cYdXXLQGxPimPPRHxlx/2393jrQgauIg4TCfCLTU51PrkdKB3zuAYDGYydDMm97bT1RWYNCMrdHhKDwyfuZ/f4L/Wp7TCkEirBECIF+6rUYrn/6dI4Cx5fLke3hVbwEnFkAN3zrpy6Ptdd1j9cPNVXrtxPpRQ0Bhx/yIVSudRZEihuRy0Xr3mDQvBl9HjOcEDodBQ9/9fTvhthoanbup7m0f2ck9BV/hrb6Qv2+wxiiIpx1PsJEyTRbEpi7+M+M/uG9AaspEij6l7SKcw5d6lB0BXOcv9RXYP/0hbBLdLPx/qeoXNs/vMiFXk/8qDzMPdQbsEwZR4WfEukYY6K5cM1rxOUN8ct44cbgRRefDh2z1TeeE/kGzkZvNhGREpoaFpVrt1K7Yx9xI4diTIgLiQwdWCYVcvGmtxl04fSQytFblEKgCHt0o847/d6xeyWy8lgIpenKgT+/wf4XX3N7PNyeEMwpSW4TC3VgiInya/Gd8b/4HuYQ36gDiSEygiE3Xe78JUyeUoNN/b7DtJRVYUyI61HZDBR1u/ZjSoojIkRVD/Puu4kLVvyT6Kz+6zcSXncrhcIFuuRsROrQMw2t4ZGitGLdNtbf+2OPffyR0thX9FERJE4cRVLRaJKKRncpm2yIjnJ/ohBEZqQSO3wI5uREIjNSMSX27ovcEBvN1Fd+wYWrXyVmWFavxuhPDP3qNYBTmTqXaa+pQx8VgXVmEWZLYtDnbzx4HF2EOajWCn1UJFNf+QXFz/8IvVYGvL+iwg4V/QLdqPOwnzqAbtR5iJQhoRYHR3s7qxZ9q8eY4rbq2oDMH5GWjNmSgLTZqdtz6HR73IhcWsqruuU5sM4qpm7PIRr2H3GbcdAYG01zyakuCYisMyZS7iH00DpjIoaYKNqq64gdlkXM0CyM8bHU7dpP1jUXozf17xuktySNLyBxwiiajp1wbhucwzQdKaXpSCmg5d6Ij0EfHYXZmkj15i/BRSSOv+ePyk4nIiWJlrLAhvjGDh/CzDefI2H08IDOEyyUQqDoF+jyZyJSh6FLGxZqUQDQGY0kjh/ZY/ievanV6zHnrX0dU2IcTcdO0nTsBNXb9nDwz/+hva6hSz+TJYG2mnpaTlYAztS4xrgYDNFRNB4/6bLIS+dUr8a4GGKGZtF4pMTpOCglINBHmbvNhZstD2N8LON/8T2G3rko7LZFQsXwe29g6w9+E2oxwgppsznLglfW0HS01O9VN93RdKSU2PycgCoEWdfNZ/JLT2KM87EwWxjjlUIghDgM1AN2wCalLBJCjAVeAGKAw8BNUso6IcSFwM8AE9AGPCSlXKqNMxH4KxAJfAjcL6WUQggz8HdgIlAJXCelPKydcxvQUQ/yKSnl37T2HOBVIAnYBNwipWzr9V9CEdaIiGhEmCgDHYz87h2UvLfUYx97i3cKQVRWOpZJhQghnIVwNAqf+Cb7X3qNvb//J42HSwBIGJ1H2fIzN1V7YzP2swoLeaJu90HYfdC7zi62xM3WJOatfpXYYdlez3kukHvHIhztNjY/9POA5vPvz9TvPdRzJ3/NtecQ0dkZNB4p8d+gQpC16CIKHr2bpPEF/hs3TPBFtZ8rpRzXqY7yn4BHpJRjgLeBh7T2CuByrf024B+dxvgDcBeQp70u1trvBKqllMOAXwPPAAghkoDHgcnAJOBxIUTHxtQzwK+llHlAtTaGQhE0kqeNx5QY7/a4Zeo4r2P+m46WsnjyNZxa9kWXdmNcDCMfvJMFB//HpTs/YPwvvocpKR6h1/dJdq+xdzXvGqKjmPPhS0oZcIEQgrx7buCy3R+Tde0loRYn7LBMKgy6X4G/EkPpjEZy77iay778kBmv/3ZAKgMAwpsQLs1CUCSlrOjUVgfEa0/4g4HFUsqCs84TOBWEdJxP8p9JKUdox24A5kgp7xZCLAaekFKuEUIYgJOAFbi+o492zovAMpyWgXIgTUppE0JM1c6/yNM6ioqK5IYNAz9JiCI4ONrbeSt1uks/AeusIspX9O5/7bLdHxGXn+uxT+PRUt7NDmzt9KxrL6Gp5NTpokjCYGD2+38g/eJZAZ13oHBiySqOvbWEyPQUItNTMcREYW9qxtbQhK2hifb6RppKTlHy7v+6b9UMICLSkokZlt2rNNj+QGcyEpmegikpnoYDx9xW5XSFPjKCYXddy4jv3kH04DBMgNQLhBAbOz3Yd8FbHwIJLBFCSOBFKeVLwA5gAfAucA0w2MV5VwObpZStQogM4HinY8eBDO19BnAMQPuCrwUsndvPOscC1EgpbS7GUiiCgr21ze2WQHNp79K4pl0wrUdlACA6K73HcsR9wWxJYNq/fgkOByc+Wc2Rf71P2rwZShnwgUHzZniViMnW3ELJe0s59Pd3OLF4FXIA5TEwW5NwtLWHTBkAcLS103i4hJbyKq+31uJG5JJz6xUM/eo1RIQojDIUeKsQTJdSlgohUoBPhBC7gTuA3wkhfgS8h9Nf4DRCiFE4zfrzOppcjCt7OOZrezeEEHfh3KYgK2vghz8pgocxJppB86Zz/N3/dTvWsP8IhrhYn3OsFzz8Na/7Dr/vJrY99luX9RP6SuoF09Dp9aDXkzF/NhnzZ/t9DoUTQ2QE2dfNJ/u6+TSfquDoGx9z+JX3qPxia6hF6xOWKWOp33eEtqrARNr4QuzwIQiDwWPZcbMlgewbLiPn1oUkFY0ZMOm1fcErHwIpZan2swynv8AkKeVuKeU8KeVE4N/AgY7+QohMrd+tUsqO9uNAZqdhM4HSTscGa+cagHigqnP7WedUAAla37PHOlv2l6SURVLKIqs1PGtQK/onx9/7HyUfLHd7XKf37YaSOL6A1POnet1/1PfvYd4Xr2OdPsGnebxh0EUDK8VwfyEyNZn8b9zMRWtfZ8brv8Fs6T958M/GVt9EW2VNqMUAnKZ/V8qAzmgk88oLmfn277midCVFzz2GpbjwnFQGwAuFQAgRLYSI7XiP84l/h2YtQAihwxkF8IL2ewLwAfColPLzjnGklCeAeiHEFM234Fac2w3gtDDcpr1fBCyVTueGxcA8IUSi5kw4D6evggQ+0/qindsxlkIRcE4sWcWqa+73a9Gikd/7qs83IkvRGC5c9W+uOLacBQc+ZcGh/zHhN9/vsywDreZAfyTrmku4YNW/Qpb5ry9YZxb1WBY6WESkJlOzdXe39sFXX8Rluz9i1lvPM/iKC86ZnBme8MZCkAqsEkJsBdYBH0gpPwZuEELsBXbjfDp/Wev/DWAY8JgQYov2StGOfR1ndMJ+nBaFj7T2PwMWIcR+4DvAIwBSyirgSWC99vqJ1gbwMPAd7RyLNoZCEXBOLV/Hiivu6zEpkcmHKmfROZlkLfLoE+uRqMw0YnIHEzMkk7yv30DahdOJykzDlBhP6tzJPo0VP3o4UV4UP1IEnvgRQ5nzwYvojMGpUNlXTJYEkmdMDKsKj7H5OV1+Txw3kvOX/YOZ//kdMbmuXN/OXXr0IZBSHgTGumj/LfBbF+1PAU+5GWsDMNpFewtOx0RX5/wF+IsbuQZGYXVFv6HxaCkrrrgPe3PPVReNcdGn3w+6ZBbjnv4u7fUN2OobT3uZt2vvLcVj/FYxTm8yMXfxn5F2O3VfHqBq405OffaFx3NMSQk42tux1Teq7YIww1JcyNinv8PmB58JtSg9Ej8qLyiJh3yiUyRd4VMPUPDIXU7/GEU3VKZChcJLpJSsufVh2mvqvOpft/sQY//fd6jbfZCc264gceyIAEt4BiEEwmAgYUw+EanJPfYffOUFTHrpSer2HsIYE91jf0VwGfHtr3Dyk885sXhVqEXxiD+30PxF+coNWGcVk3n5XEY+qNLVeEIpBAqFlxz6x7uULV/nVV9jQhxz/vsC1ukTAyxVzwi9553B+FF5Ti9snY74EUM99lWEBqHTMe2fz7Ji4b2Ua3khwpGqDTuIGGSl5USnsFudjqTxBdgam5xZMkOAUga8QykECoUXOOx2tj7yrFd9o4dkMOfDPxI/Mjy+XHtKozv6sXvJvm5+kKRR9BazJZHzPv0rSy/4StgqBY62dszJicQNHwLSaVVrOVlO1cYdgDO+P9hKQcGjdytlwEuUQqBQeEHlum00n+g52VDSxFHM/u+LRKaFT4hruweFwJycSNyInhMhKcIDfYSZ4hd/woejLwu1KG6p3b7X7bGIFEtQFYK0C6Yx9qkHgjZff0eVKVMovKD0v8t67JN24XQuWP5KWCkD4N5CEJ2dwVVla4Lq26DoOwmj8og7y3O+v1C5fjvR2UFKKisEE371iKrG6QPKQqBQeEHpxys9HrdMGcest5/HEB0VJIm8R2fs/jFPmTOJSS89ec4mYOnvFDxyF2tvfzTUYviMvbkFQ2zUmSyGWuKiiFQLsXlDnOlmpUTa7Ei7nbbqOhoOHO3VXJkLziNhTL7/hD8HUAqBQuEF5y35M8fe/pSjr3/EqaVru+Sbjy8YxpwPXgxLZQCc+7YdORH0kWYSxgwn47K5xOUNCa1gil6Tc+sVHPjTG2HrS+CJ2h3OhEWWyWOp1BSC2Pwcl8XA9JERROdk0njoeLdjPTH0qy4j2RUe8Kra4UBBVTtU+IOW8iqOvbWEo69/RMOh41y44p9EZaaFWizFOUbpR8tZNv+uUIvRa5KKR6Mzm6lYtZGkotFUbdjhsl9EWjI6o4GmYye9HjtykJWFR5f5LbfHQMIf1Q4VCoVGhDWJvLuvJ+/u63HY7SrJiSIkpF04HbM1idbyqp47hyFV63dgSowjZXYxdbsPue3XcrKCyPQUDHEx2LwsE53zlauUMtALlLeFQtEHlDKgCBU6g6Hfh4u2VddRtnw9LacqPPZrX9rM+AAACyhJREFULi0jsdB7f4Chd1zdV9HOSZRCoFAoFP2U7BvDN/zQ35Sv2kiCFxExKbMnETssOwgSDTyUQqBQKBT9lOQp40iZc+6UdGmvre+xz9A7lXWgtyiFQKFQKPopQgimvfIsZov3lTX7M42HSzwm0jLGxTD46t5XDT3XUQqBQqFQ9GOiMlKZ8tefhVqMoGG2Jrk9ln3DpRiiIoMozcBCKQQKhULRz8m4bC75D9wWajGCgq2pGbObCp5D71wUZGkGFkohUCgUigHA+GcfPieS8VRv3ElrWSWWSYWYOm2VJIwZTlLRmBBK1v9RCoFCoVAMAHR6PZNeepKRD50Dlf2kpHLdNnQGPfGj8gDIvXORSsXdR1TmBoVCoRggCCEY98xDmBLj2fr9X4VanIDTcqqS9oYmEseNJOfmBaEWp9+jLAQKhUIxgBBCMOrRuyn6/Y9CLUpQsDc2E5ufg9mSGGpR+j1KIVAoFIoByPB7b2LqK79AnAPZNFVmQv+gFAKFQqEYoOTctICZbz+PzmwKtSgBIyornbQLpoVajAGBUggUCoViAJN5+XnM/fhPGGKjQy1KQMi9/SqETn2V+QP1V1QoFIoBTuqcyVy88S0SJ4zy67j6qEgSxo5g0MUzSSoajT7C7NfxeyIqM438b94c1DkHMirKQKFQKM4B4vKGMG/1q2z9/q/Y85u/IR2OXo0TmZ5CxoLzyFx4PqlzJndRAhw2G/X7jlC1aSel/11GyX8/w9bQ5K8ldMGUGM/Mt59XzoR+REgpQy1D0CgqKpIbNmwItRgKhUIRUmq272HzQz/nxOJVXvVPGDuCTE0JSJwwyut4f3tLKyc/Xc2xN5dw/N3/0VZd2xexTxORZuW8T/5CwujhfhnvXEIIsVFKWeTymFIIFAqF4tykatNOjr25hBNLVtFyqhJbYzMRKUlEpqcQOciKZfJYMi6fS8yQzD7P5Whvp2z5eo69tYSS9z+j6fjJXo0z6OKZTHn5aSLTrH2W6VxEKQQaSiFQKBSK8KCp9BRVG3dStWEHleu303z8JLbGZu3VhK2xGSEE0TmZxOXnEDt8CJZJhWRff6nKSNgHPCkEyodAoVAoFEEnKj2VqPRUMi8/z+VxKSXS4UB3DuRRCBeUQqBQKBSKsEMIcU4kVQonVNihQqFQKBQKpRAoFAqFQqFQCoFCoVAoFAqUQqBQKBQKhQKlECgUCoVCoUApBAqFQqFQKFAKgUKhUCgUCpRCoFAoFAqFAqUQKBQKhUKhQCkECoVCoVAoUAqBQqFQKBQKlEKgUCgUCoUCpRAoFAqFQqFAKQQKhUKhUCjwUiEQQhwWQmwXQmwRQmzQ2sYKIdZo7e8LIeK0dosQ4jMhRIMQ4vmzxlkmhNijjbNFCJGitZuFEK8JIfYLIb4QQgzpdM5tQoh92uu2Tu05Wt992rmmvv85FAqFQqE4N/HFQjBXSjlOSlmk/f4n4BEp5RjgbeAhrb0FeAx40M04N2njjJNSlmltdwLVUsphwK+BZwCEEEnA48BkYBLwuBAiUTvnGeDXUso8oFobQ6FQKBQKRS/oy5ZBPrBCe/8JcDWAlLJRSrkKp2LgLQuBv2nv/wOcL4QQwEXAJ1LKKilltTbPxdqx87S+aOde0Ye1KBQKhUJxTuOtQiCBJUKIjUKIu7S2HcAC7f01wGAvx3pZ2y54TPtiB8gAjgFIKW1ALWDp3K5xXGuzADVa387tCoVCoVAoeoHBy37TpZSl2p7/J0KI3cAdwO+EED8C3gPavBjnJilliRAiFngTuAX4OyBc9JW9aO+GpsB0KDENQog9XsgZTJKBilAL4UfUesKXgbQWUOsJZwbSWmBgrSfb3QGvFAIpZan2s0wI8TYwSUr5LDAPQAgxHLjUi3FKtJ/1Qoh/4fQL+DvOJ/zBwHEhhAGIB6q09jmdhsgEluG8MAlCCINmJcgESt3M+RLwkjfrDAVCiA2d/DL6PWo94ctAWguo9YQzA2ktMPDW444etwyEENHaEz1CiGicSsCOThECOuCHwAs9jGMQQiRr743AZTi3HcBpYeiIIFgELJVSSmAxME8Ikag5E84DFmvHPtP6op37rndLVigUCoVCcTbeWAhSgbe17X4D8C8p5cdCiPuFEPdpfd4CXu44QQhxGIgDTEKIK3B+kR8BFmvKgB74FPijdsqfgX8IIfbjtAxcDyClrBJCPAms1/r9REpZpb1/GHhVCPEUsFkbQ6FQKBQKRS/oUSGQUh4Exrpo/y3wWzfnDHEz3EQ3/VtwOia6OvYX4C9u5JrkZp7+RNhuZ/QStZ7wZSCtBdR6wpmBtBYYeOtxiXBa3xUKhUKhUJzLqNTFCoVCoVAolELQF9ykdH5CCFHSKT3z/E79H9XSM+8RQlzUqX2iNs5+IcTvOvIz9Calc7DWI4QYIoRo7tT+QqdxQr4eV2vR2r+p/f13CiF+3qm9310bd+sJ92vjbj3a/B0yHxZCbOnUP2yvjy9r6cfXZpwQYm1HmxBiUqf+/e3auFxLf7g2AUdKqV69fAGHgeSz2p4AHnTRtwDYCpiBHOAAoNeOrQOm4syv8BFwidZ+L/CC9v564DXtfRJwUPuZqL1PDPJ6hgA73IwT8vW4WctcnM6sZu33lH5+bdytJ6yvjbv1nHX8l8CP+sP18XEt/fLaAEs6yTMfWNZfr42HtYT9tQn0S1kIgsdC4FUpZauU8hCwH5gkhBgExEkp10jnf9LfOZOG2aeUzsFcjDvCfD1fB34mpWwFZ16NTnL1x2vjbj0u6Qfr6ZBTANcC/+4kW3+8Pq7W4q5fuK9F4owcA2eemI68L/3x2rhbi0vCfC1+RSkEfcNVSmeAbwghtgkh/iLOFGNyl4Y5Q3t/dnuXc6R3KZ2DuR6AHCHEZiHEciHEzE4yh8N6XK1lODBTM+0tF0IUny3XWfOHy1p8XQ+E97Vxt54OZgKnpJT7zpbtLBnCZT2+rAX657V5APiFEOIY8Czw6NmynSVDuKzHl7VA+F+bgOJt6mKFa1yldP4D8CTOf8QncZoL76B3aZj7nLrZR3xZzwkgS0pZKYSYCLwjhBjVg2zBXI+rtRhwmu+mAMXA60KI3F7KFQ7Xxt16wv3agIv1SCk7iqXdQNcn6nC/Pr6spV9eG5xJ4L4tpXxTCHEtzrwvF/RStlDfB9ytpT9cm4CiLAR9QHZK6YyzBPQkKeUpKaVdSunAmXipw/mmIz1zBx3plo9r789u73KO6J7S2dVYQVuPZiKs1N5vxLl3ODxc1uNqLdo8b0kn6wAHzhzl/fLauFtPuF8bD+vpmPsq4LVO3cP6+viyln58bW7DmYAO4A36yX3Nl7X0h2sTcNw5F6hXj84q0UBsp/erce4RDerU59s499cARtHV+eYgZ5xv1uN8yutwWJmvtd9HV4eV17X3ScAhnE+Hidr7pCCvx9pJ/lygpEOGUK/Hw1ruwZntEpwf9GOajP312rhbT9heG0/r0X6/GFh+Vv+wvT69WEu/vDbAl8Acrf18YGN/vTYe1hLW1yYYr5AL0F9f2j/MVu21E/iB1v4PYDuwDWeNhs5fqD/AqXXuQfNS1dqLcNZ1OAA8z5mEURE4Ndj9OL1cczudc4fWvh+4PdjrAa7W+m0FNgGXh8t6PKzFBLyiybYJOK+fXxuX6wnna+NpPdqxvwL3uDgnLK+Pr2vpr9cGmAFs1Nq/ACb212vjbi3hfm2C8VKZChUKhUKhUCgfAoVCoVAoFEohUCgUCoVCgVIIFAqFQqFQoBQChUKhUCgUKIVAoVAoFAoFSiFQKBQKhUKBUggUCoVCoVCgFAKFQqFQKBTA/weh1Myu2wHPDgAAAABJRU5ErkJggg==\n", + "text/plain": [ + "<Figure size 864x576 with 1 Axes>" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "fig, ax = plt.subplots(figsize=(12,8))\n", + "stadtteile_final.plot(ax=ax, column='VG', legend=True, cmap='RdYlGn', scheme='quantiles') #OrRd #RdYlGn\n", + "aerzte_mit_stadtteil.plot(ax=ax, marker='o', color='yellow', edgecolor='black', markersize=25)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.7" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Tutorials/Grundlagen 1 - if-Anweisungen und Vergleiche.ipynb b/Tutorials/Grundlagen 1 - if-Anweisungen und Vergleiche.ipynb index be0b380..3185d8d 100644 --- a/Tutorials/Grundlagen 1 - if-Anweisungen und Vergleiche.ipynb +++ b/Tutorials/Grundlagen 1 - if-Anweisungen und Vergleiche.ipynb @@ -11,7 +11,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "In Python spielt die korrekte Einrückung eine wichtige Rolle. Einrückungen müssen unter anderem bei if-Anweisungen erfolgen, ansonsten kann der Code nicht korrekt erstellt (kompiliert) werden. Der folgende Ausschnitt zeigt eine if-Anweisung mit korrekter Einrückung. In den meisten Python-Entwicklungsumgebungen wird die Einrückung nach Drücken der Enter-Taste automatisch erstellt." + "In Python spielt die korrekte Einrückung eine wichtige Rolle. Einrückungen müssen unter anderem bei <b>if-Anweisungen</b> erfolgen, ansonsten kann der Code nicht korrekt erstellt werden. Der folgende Ausschnitt zeigt eine if-Anweisung mit korrekter Einrückung. In den meisten Python-Entwicklungsumgebungen wird die Einrückung nach Drücken der Enter-Taste automatisch erstellt." ] }, { @@ -37,8 +37,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Der Teil \"if zahl > 1\" war eine Bedingung. Hätte die Variable zahl den Wert 1 gehabt, wäre die print-Ausgabe nicht erfolgt. \n", - "Man kann aber auch festlegen, was passieren soll, wenn die Bedingung nicht erfüllt wird. Beachte auch hier die korrekte Einrückung sowie die Syntax der Anweisung (mit Doppelpunkt!)." + "Der Teil \"if zahl > 1\" war eine Bedingung. Hätte die Variable <i>zahl</i> den Wert 1 gehabt, wäre die print-Ausgabe nicht erfolgt. \n", + "Man kann aber auch festlegen, was passieren soll, wenn die Bedingung nicht erfüllt wird. Beachten Sie auch hier die korrekte Einrückung sowie die generelle Syntax der Anweisung." ] }, { @@ -66,7 +66,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Um mehrere Fälle unterscheiden zu können, gibt es das Schlüsselwort \"elif\". Außerdem können mehrere gleichzeitig geltende Bedingungen mit dem Schlüsselwort \"and\" kombiniert werden. Es gibt auch das Schlüsselwort \"or\" (hier nicht dargestellt), bei dem nur eine der beiden Bedingungen gelten muss." + "Um mehrere Fälle unterscheiden zu können, gibt es das Schlüsselwort <b>elif</b>. Außerdem können mehrere gleichzeitig geltende Bedingungen mit dem Schlüsselwort <b>and</b> kombiniert werden. Es gibt auch das Schlüsselwort <b>or</b> (hier nicht dargestellt), bei dem nur eine der beiden Bedingungen gelten muss." ] }, { @@ -98,7 +98,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Im vorigen Beispiel wurde außerdem ein doppeltes Istgleich-Zeichen verwendet. Dieses braucht man, um zwei Werte miteinander zu vergleichen. Nicht zu verwechseln mit dem einzelnen Istgleich-Zeichen: Damit weist man einer Variablen einen Wert zu." + "Im vorigen Beispiel wurde außerdem ein doppeltes Istgleich-Zeichen verwendet. Dieses braucht man, um zwei Werte miteinander zu vergleichen. Nicht zu verwechseln mit dem einzelnen Istgleich-Zeichen, mit dem man einer Variablen einen Wert zuweist!" ] }, { @@ -146,7 +146,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Die Bedingung, dass zwei Werte ungleich sind, kann man mit einem != ausdrücken:" + "Die Bedingung, dass zwei Werte ungleich sind, kann man mit einem <b>!=</b> ausdrücken:" ] }, { diff --git a/Tutorials/Grundlagen 2 - Schleifen, Listen, Dictionaries.ipynb b/Tutorials/Grundlagen 2 - Schleifen, Listen, Dictionaries.ipynb index 16c6178..560a5e0 100644 --- a/Tutorials/Grundlagen 2 - Schleifen, Listen, Dictionaries.ipynb +++ b/Tutorials/Grundlagen 2 - Schleifen, Listen, Dictionaries.ipynb @@ -12,7 +12,7 @@ "metadata": {}, "source": [ "Neben if-Anweisungen sind auch Schleifen ein wichtiges Konstrukt in Python (bzw. Programmiersprachen im Allgemeinen!).\n", - "Wir behandeln hier erstmal nur sogenannte for-Schleifen:" + "Wir behandeln hier erstmal nur sogenannte <b>for-Schleifen</b>:" ] }, { @@ -33,22 +33,22 @@ } ], "source": [ - "for i in range(0,5):\n", - " print(i)" + "for i in range(0,5): \n", + " print(i) #auch hier die Einrückung beachten" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Was ist hier passiert? Was bedeutet das i? Ganz einfach: Das i ist eine Variable. In jedem Durchlauf nimmt sie einen anderen Wert an. In diesem Fall wird von 0 bis 5 gezählt, wobei 5 nicht mit eingeschlossen ist." + "Was bedeutet das i? Ganz einfach: Das i ist eine Variable, die in jedem Durchlauf einen anderen Wert annimmt. In diesem Fall wird von 0 bis 5 gezählt, wobei 5 nicht mit eingeschlossen ist." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Am häufigsten benötigt man for-Schleifen, um durch Listen zu laufen (iterieren). Beispielsweise eine Liste mit Strings oder eine Liste mit Zahlen oder auch gemischte Listen." + "Häufig benötigt man for-Schleifen, um Listen zu durchlaufen (<i>iterieren</i>). Z.B. eine Liste mit Strings oder eine Liste mit Zahlen oder auch gemischte Listen." ] }, { @@ -77,29 +77,29 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Wie ihr euch sicher denken könnt, ist auch x hier eine Variable. Und auch sie nimmt pro Durchlauf einen anderen Wert an. Hier sind aber keine Zahlen-Limits vorgegeben, sondern eine Liste mit 4 Werten. Die Länge der Liste kann man sich mit len() übrigens auch explizit ausgeben lassen und die Schleife alternativ so formulieren:" + "Wie Sie sich sicher denken können, ist auch x hier eine Variable. Und auch sie nimmt pro Durchlauf einen anderen Wert an. Hier sind aber keine Zahlen-Limits vorgegeben, sondern eine Liste mit 4 Werten, die bis zu ihrem Ende durchlaufen wird. Die Länge der Liste kann man sich mit <b>len()</b> übrigens auch explizit ausgeben lassen und die Schleife alternativ so formulieren:" ] }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "0\n", - "1\n", - "2\n", - "3\n" + "apfel\n", + "banane\n", + "pfirsich\n", + "weintraube\n" ] } ], "source": [ "obst = [\"apfel\", \"banane\", \"pfirsich\", \"weintraube\"]\n", "for i in range(0, len(obst)):\n", - " print(i)" + " print(obst[i])" ] }, { @@ -108,7 +108,7 @@ "source": [ "Allerdings ist die Version oben deutlich bequemer zu schreiben.\n", "\n", - "Auf ein Element an einer bestimmten Stelle in der Liste lässt sich wie folgt zugreifen:" + "Wie an diesem Beispiel auch zu erkennen ist, greift man auf eine Element an einer bestimmmten Stelle in der Liste mithilfe eckiger Klammern und dem entsprechenden Index zu:" ] }, { @@ -132,7 +132,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Warum wird hier nicht \"apfel\" ausgegeben, obwohl ich das 1. Element angegeben habe? \n", + "Warum wird hier nicht \"apfel\" ausgegeben, obwohl wir das 1. Element angegeben haben? \n", "Das liegt daran, dass in der Programmierung immer von 0 an gerechnet wird. Das erste Element einer Liste ist also Element 0:" ] }, @@ -181,14 +181,14 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Achtung: Das -1 ist wichtig, denn len(obst) gibt in diesem Fall ja 4 zurück. Wenn wir aber mit 0 zu zählen anfangen, steht \"weintraube\" an Stelle 3 und nicht an Stelle 4. Einen Listeneintrag mit Index 4 gibt es nicht, wir würden also einen Fehler bekommen. " + "Achtung: Das -1 ist wichtig, denn <i>len(obst)</i> gibt in diesem Fall ja 4 zurück. Wenn wir aber mit 0 zu zählen anfangen, steht \"weintraube\" an Stelle 3 und nicht an Stelle 4. Einen Listeneintrag mit Index 4 gibt es nicht, wir würden also einen Fehler bekommen. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Man kann einer Liste auch einen neuen Eintrag hinzufügen. Dieser wird mit \"append\" hinten angelegt:" + "Wenn man an eine Liste einen neuen Eintrag anhängen will, verwendet man <b>append</b>:" ] }, { @@ -213,12 +213,12 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Ebenfalls häufig verwendet werden Dictionaries. Hiermit speichert man \"Key-Value-Pairs\", also einen Schlüsselbegriff und einen zugehörigen Wert. Beispiel:" + "Ebenfalls häufig verwendet werden <b>Dictionaries</b>. Hiermit speichert man \"Key-Value-Pairs\", also einen Schlüsselbegriff und einen zugehörigen Wert. Beispiel:" ] }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 3, "metadata": {}, "outputs": [ { @@ -230,7 +230,7 @@ } ], "source": [ - "vorrat = {\"apfel\": 4, \"banane\": 3, \"weintraube\": 24} #beachte die geschweiften Klammern!\n", + "vorrat = {\"apfel\": 4, \"banane\": 3, \"weintraube\": 24} #beachte die geschweiften Klammern und Anführungszeichen!\n", "anzahl_apfel = vorrat[\"apfel\"] #greife auf den Wert (value) des Schlüssels (key) \"apfel\" zu\n", "print(\"Es sind noch \"+ str(anzahl_apfel) + \" Äpfel verfügbar.\")\n" ] @@ -239,28 +239,28 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Dictionaries können nachträglich auch verändert werden:" + "Dictionaries können nachträglich verändert werden:" ] }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "3\n", - "0\n" + "Bananen: 3\n", + "Bananen: 0\n" ] } ], "source": [ "vorrat = {\"apfel\": 4, \"banane\": 3, \"weintraube\": 24}\n", - "print(vorrat[\"banane\"]) #Noch gibt es Bananen...\n", + "print(\"Bananen: \"+str(vorrat[\"banane\"])) #Noch gibt es Bananen...\n", "vorrat[\"banane\"] = 0 #Jetzt nicht mehr!\n", - "print(vorrat[\"banane\"]) " + "print(\"Bananen: \"+str(vorrat[\"banane\"])) " ] }, { @@ -272,21 +272,21 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "{'art': 'Granny Smith', 'herkunft': 'Südtirol', 'anzahl': 5}\n" + "{'art': 'Granny Smith', 'herkunft': 'Australien', 'anzahl': 5}\n" ] } ], "source": [ "apfel = {} \n", "apfel[\"art\"] = \"Granny Smith\" \n", - "apfel[\"herkunft\"] = \"Südtirol\"\n", + "apfel[\"herkunft\"] = \"Australien\"\n", "apfel[\"anzahl\"] = 5\n", "print(apfel)" ] @@ -300,7 +300,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 9, "metadata": {}, "outputs": [ { @@ -308,7 +308,7 @@ "output_type": "stream", "text": [ "dict_keys(['art', 'herkunft', 'anzahl'])\n", - "dict_values(['Granny Smith', 'Südtirol', 5])\n" + "dict_values(['Granny Smith', 'Australien', 5])\n" ] } ], @@ -326,7 +326,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 10, "metadata": {}, "outputs": [ { @@ -334,7 +334,7 @@ "output_type": "stream", "text": [ "Granny Smith\n", - "Südtirol\n", + "Australien\n", "5\n" ] } diff --git a/Tutorials/Grundlagen 3 - Funktionen.ipynb b/Tutorials/Grundlagen 3 - Funktionen.ipynb new file mode 100644 index 0000000..1781058 --- /dev/null +++ b/Tutorials/Grundlagen 3 - Funktionen.ipynb @@ -0,0 +1,157 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Funktionen" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Funktionen werden an dieser Stelle nur kurz behandelt, weil wir in der späteren Aufgabenstellung noch keine selbst schreiben werden. Dennoch werden wir immer wieder Funktionen aus externen Libraries verwenden und sollten deshalb Kenntnis darüber haben, was sie bedeuten.\n", + "\n", + "Funktionen dienen in erster Linie der Strukturierung und Wiederverwendung von Code. Statt den Code einer häufig ausgeführten Berechnung immer wieder aufzuschreiben, ist es viel sinnvoller, ihn in eine Funktion zu packen und dann mit einer Zeile Code einfach nur diese Funktion aufzurufen. Außerdem kann eine Funktion über eine Bibliothek auch anderen zur Verfügung gestellt werden, die sich dann die Mühe ersparen können, die Funktion selbst zu programmieren.\n", + "\n", + "Der folgende Codeabschnitt ist ein simples Beispiel für eine Funktion ohne Rückgabewert, d.h. es passiert lediglich etwas innerhalb der Funktion, aber es wird kein Ergebnis zur weiteren Verarbeitung generiert." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "def hello_world():\n", + " print(\"Hello World!\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Aufgerufen wird die Funktion wie folgt:" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Hello World!\n" + ] + } + ], + "source": [ + "hello_world()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Im Folgenden eine Funktion, die über das Schlüsselwort <i>return</i> das Ergebnis der gewünschten Berechnung zurückliefert:" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [], + "source": [ + "def multiplikation(x, y): \n", + " return x*y" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "x und y sind spezielle Variablen, die Parameter genannt werden. Eine Funktion kann auch mehr oder weniger bzw. gar keine Parameter (wie im vorherigen Beispiel) haben. Sie werden innerhalb der Funktion zur Berechnung des gewünschten Ergebnisses verwendet." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "125\n" + ] + } + ], + "source": [ + "zahl1 = 5\n", + "zahl2 = 25\n", + "produkt = multiplikation(zahl1,zahl2)#Um mit dem Ergebnis weiterzuarbeiten, speichert man es in einer Variablen\n", + "print(produkt)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Als letztes Beispiel binden wir die <i>random</i>-Module der populären externen Library <b>numpy</b> ein, um zwei dort angebotene Funktionen zur Erstellung von Zufallszahlen zu nutzen. " + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "-0.3754555993388598\n", + "[84 73 63 91]\n" + ] + } + ], + "source": [ + "import numpy.random as npr\n", + "zufallszahl = npr.normal() #Aufruf der Funktion \"normal()\", die eine einzelne Zufallszahl generiert\n", + "print(zufallszahl)\n", + "numpy_array = npr.randint(low=1, high=100, size=4) #generiere vier Zufallszahlen zwischen 1 und 100\n", + "print(numpy_array)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Die erste Funktion erfordert keinen Parameter. Sie ist so angelegt, dass sie eine Zahl zwischen 0 und 1 zurückliefert. Für die zweite Funktion, <i>randint</i>, gibt es einen notwendigen (<i>low</i>) und drei optionale Parameter, wovon hier zwei genutzt wurden (siehe auch die Dokumentation unter https://docs.scipy.org/doc/numpy-1.15.1/reference/generated/numpy.random.randint.html). Wird ein optionaler Parameter nicht gesetzt, so verwendet die Funktion einen internen Standardwert. Beispielsweise würde ohne die Angabe von <i>size=4</i> nur eine Zahl zurückgeliefert. Um übergebene Parameter korrekt zuordnen zu können, werden hier ihre Namen in der Form <i>parametername=</i> mitgeliefert." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.7" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Tutorials/Grundlagen 3 - Pandas DataFrames.ipynb b/Tutorials/Grundlagen 4 - Pandas DataFrames.ipynb similarity index 67% rename from Tutorials/Grundlagen 3 - Pandas DataFrames.ipynb rename to Tutorials/Grundlagen 4 - Pandas DataFrames.ipynb index 9e1e1a7..a423d97 100644 --- a/Tutorials/Grundlagen 3 - Pandas DataFrames.ipynb +++ b/Tutorials/Grundlagen 4 - Pandas DataFrames.ipynb @@ -4,21 +4,21 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## DataFrames" + "## Pandas DataFrames" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Die zuvor verwendeten Listen und Dictionaries sind interner Teil von Python und können ohne weiteres sofort verwendet werden. Es gibt aber auch Module von externen Code-\"Bibliotheken\"/Libraries, die man einbinden kann und die noch viele weitere Funktionalitäten anbieten, je nachdem was man gerade braucht. Ein Beispiel sind DataFrames von der Python-Bibliothek \"Pandas\". Bei DataFrames handelt es sich um eine spezielle Datenstruktur, die mit Tabellen vergleichbar sind. In der Handhabung ähneln sie aber auch den bereits behandelten Dictionaries.\n", + "Die zuvor verwendeten Listen und Dictionaries sind interner Teil von Python und können ohne weiteres sofort verwendet werden. Es gibt aber auch Module von externen Code-\"Bibliotheken\"/Libraries, die man einbinden kann und die noch viele weitere Funktionalitäten anbieten, je nachdem was man gerade braucht. Ein Beispiel sind <b>DataFrames</b> von der Python-Bibliothek \"Pandas\". Bei DataFrames handelt es sich um eine spezielle Datenstruktur, die mit Tabellen vergleichbar sind. In der Handhabung ähneln sie zudem den bereits behandelten Dictionaries.\n", "\n", - "Grundsätzlich gilt: Die Online-API-Referenz der entsprechenden Bibliothek gibt detailliert Auskunft darüber, wie die Syntax der angebotenen Komponenten aussehen muss, welche Funktionalitäten vorhanden sind, etc. In unserem Fall schaut man also im Zweifel unter https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html nach." + "Grundsätzlich gilt: Die Online-Dokumentation der entsprechenden Bibliothek gibt detailliert Auskunft darüber, wie die Syntax der angebotenen Komponenten aussehen muss, welche Funktionalitäten vorhanden sind, etc. In unserem Fall schaut man also im Zweifel unter https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html nach." ] }, { "cell_type": "code", - "execution_count": 32, + "execution_count": 2, "metadata": {}, "outputs": [ { @@ -33,7 +33,7 @@ ], "source": [ "import pandas as pd #hiermit binden wir die externe Bibliothek Pandas ein und kürzen sie ab sofort mit pd ab\n", - "df = pd.DataFrame() #nun können wir ein DataFrame von Pandas erzeugen. Beachte die Syntax!\n", + "df = pd.DataFrame() #nun können wir ein neues DataFrame von Pandas erzeugen.\n", "print(df)" ] }, @@ -46,7 +46,7 @@ }, { "cell_type": "code", - "execution_count": 33, + "execution_count": 3, "metadata": {}, "outputs": [ { @@ -75,12 +75,12 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "\"NaN\" steht für \"Not a Number\" und bedeutet hier, dass die Tabelle noch keine gültigen Daten enthält. Es gibt übrigens viele verschiedene Möglichkeiten, ein DataFrame anzulegen und auch mit Werten zu füllen. Hier ein Beispiel mit einem Dictionary. Das 0 und 1 am linken Rand ist ein namenloser Zeilen-Index, der von 0 aufwärts gezählt wird." + "\"NaN\" steht für \"Not a Number\" und bedeutet hier, dass die Tabelle noch keine gültigen Daten enthält. Es gibt übrigens viele verschiedene Möglichkeiten, ein DataFrame anzulegen und mit Werten zu füllen. Hier ein Beispiel mit einem Dictionary mit Spaltennamen als Keys und Listen als Werten für die Spalte. Das 0 und 1 am linken Rand ist ein namenloser Zeilen-Index, der von 0 aufwärts gezählt wird." ] }, { "cell_type": "code", - "execution_count": 34, + "execution_count": 4, "metadata": {}, "outputs": [ { @@ -103,12 +103,12 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Oder auf Grundlage einer Liste von Dictionaries:" + "Oder auf Grundlage einer Liste von Dictionaries, die jeweils die Werte für eine Zeile enthalten:" ] }, { "cell_type": "code", - "execution_count": 35, + "execution_count": 5, "metadata": {}, "outputs": [ { @@ -131,12 +131,12 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Oder auf Grundlage einer Liste von Listen:" + "Oder stattdessen auf Grundlage einer Liste von Listen, die ebenfalls jeweils die Zeilenwerte definieren:" ] }, { "cell_type": "code", - "execution_count": 36, + "execution_count": 6, "metadata": {}, "outputs": [ { @@ -161,12 +161,12 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "In vielen Fällen legen wir ein DataFrame aber gar nicht mühsam selbst an, sondern laden es aus einer anderen Datenquelle. Zum Beispiel aus einer CSV-Datei (CSV = Comma Separated Values, also eine einfache Tabelle, die durch Kommas getrennt wird)." + "In vielen Fällen legen wir ein DataFrame aber gar nicht mühsam selbst an, sondern laden es aus einer anderen Datenquelle. Zum Beispiel aus einer <b>CSV-Datei</b> (CSV = Comma Separated Values, also eine einfache Tabelle, die durch Kommas getrennt wird). Dazu müssen wir den Pfad zur Datei sowie den Dateinamen einschließlich der Dateiendung eingeben. In unserem Fall navigieren wir mithilfe der ../-Syntax erstmal aus unserem aktuellen Verzeichnis heraus, um dann auf die gewünschte Datei im Nachbarordner <i>Daten</i> zuzugreifen." ] }, { "cell_type": "code", - "execution_count": 37, + "execution_count": 7, "metadata": {}, "outputs": [ { @@ -219,7 +219,7 @@ }, { "cell_type": "code", - "execution_count": 38, + "execution_count": 8, "metadata": {}, "outputs": [ { @@ -253,7 +253,7 @@ }, { "cell_type": "code", - "execution_count": 39, + "execution_count": 9, "metadata": {}, "outputs": [ { @@ -264,6 +264,14 @@ "Columns: [ID, Fachgebiet1, Adresse, PLZ, Privatarzt, Stadt, Land]\n", "Index: []\n" ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/tljh/user/lib/python3.6/site-packages/pandas/core/ops/__init__.py:1115: FutureWarning: elementwise comparison failed; returning scalar instead, but in the future will perform elementwise comparison\n", + " result = method(y)\n" + ] } ], "source": [ @@ -280,7 +288,7 @@ }, { "cell_type": "code", - "execution_count": 40, + "execution_count": 10, "metadata": {}, "outputs": [ { @@ -306,12 +314,12 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Tatsächlich wird PLZ als Ganzzahl gespeichert. Das erklärt, wieso unsere Abfrage oben mit den String-Anführungszeichen nicht funktioniert hat. Richtig wäre es so:" + "Tatsächlich wird PLZ als Ganzzahl gespeichert. Das erklärt, wieso unsere Abfrage mit den String-Anführungszeichen nicht funktioniert hat. Richtig wäre es so:" ] }, { "cell_type": "code", - "execution_count": 41, + "execution_count": 11, "metadata": {}, "outputs": [ { @@ -340,7 +348,7 @@ }, { "cell_type": "code", - "execution_count": 42, + "execution_count": 12, "metadata": {}, "outputs": [ { @@ -364,16 +372,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "DataFrames können anschließend auch einfach wieder als CSV-Dateien gespeichert werden:" - ] - }, - { - "cell_type": "code", - "execution_count": 43, - "metadata": {}, - "outputs": [], - "source": [ - "selektion.to_csv(\"../Daten/Selektion.csv\") " + "Hinweis: Mithilfe von <b>df[\"PLZ\"] = df[\"PLZ\"].astype(str)</b> könnten wir sogar den Datentyp der kompletten Spalte ändern. Im Moment wollen wir sie aber noch als Ganzzahl belassen." ] }, { @@ -385,7 +384,7 @@ }, { "cell_type": "code", - "execution_count": 44, + "execution_count": 14, "metadata": {}, "outputs": [ { @@ -417,14 +416,14 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Mit head() (bzw. tail()) kann man sich die ersten (bzw. letzten) Zeilen eines großen DataFrames ausgegeben lassen.\n", + "Mit <b>head()</b> (bzw. <b>tail()</b>) kann man sich die ersten (bzw. letzten) Zeilen eines großen DataFrames ausgegeben lassen.\n", "\n", "Wir legen nun ein neues Feld mit Namen \"Bundesland\" an und füllen es einheitlich mit dem Wert \"Hamburg\". Nebenbei wollen wir \"Fachgebiet1\" in \"Fachgebiet\" umbenennen:" ] }, { "cell_type": "code", - "execution_count": 45, + "execution_count": 15, "metadata": {}, "outputs": [ { @@ -457,12 +456,12 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Warum hat die Umbennung nicht funktioniert? Ganz einfach, die Funktion \"rename()\" nimmt eine Änderung vor und liefert als Ergebnis den geänderten DataFrame zurück, aber diesen haben wir in keiner Variable gespeichert. Die Änderung hat somit keine Auswirkung. Folgendes funktioniert aber:" + "Warum hat die Umbennung nicht funktioniert? Ganz einfach, die Funktion <b>rename()</b> nimmt eine Änderung vor und liefert als Ergebnis einen neuen, geänderten DataFrame zurück, aber diesen haben wir in keiner Variable gespeichert. Die Änderung hat somit keine Auswirkung. Folgendes funktioniert aber:" ] }, { "cell_type": "code", - "execution_count": 46, + "execution_count": 16, "metadata": {}, "outputs": [ { @@ -494,12 +493,12 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Ebenso werden alle vorgenommenen Änderungen an der Original-Datei verloren gehen, sobald wir unser Programm beenden! Um die Tabelle dauerhaft zu speichern, sollte man sie am Ende also nochmal explizit als Datei abspeichern (z.B. mit to_csv), wie oben gezeigt." + "Achtung: Es werden alle vorgenommenen Änderungen verloren gehen, sobald wir unser Programm beenden! Um die Tabelle dauerhaft zu speichern, sollte man sie am Ende also nochmal explizit als Datei exportieren (z.B. mit <b>to_csv</b>). Im Folgenden speichern wir nur die ersten fünf Zeilen unserer Tabelle in einer neuen Datei namens \"Selektion\"." ] }, { "cell_type": "code", - "execution_count": 47, + "execution_count": 17, "metadata": {}, "outputs": [], "source": [ @@ -511,13 +510,90 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Eine Spalte mit nur einem festen Wert anzulegen, war nicht so schwer. Aber was, wenn wir unterschiedliche Werte abhängig von einer anderen Spalte setzen wollen?\n", - "Das ist mit DataFrames nicht ganz so einfach und erfordert z.T. recht komplizierte Syntax. Um das zu umgehen, kann man auch einfach eine leere Liste anlegen, dann durch das DataFrame durchiterieren und führ jede Zeile ein neues Dictionary mit den gewünschten Werten anlegen, das dann an die Liste angehängt wird. Entweder erstellt man das Dictionary komplett neu, oder man nutzt die bereits vorhandenen Zeilenwerte und ergänzt diese nur." + "Ähnlich wie beim Anlegen der \"Bundesland\"-Spalte kann man auch Spalten anlegen, die das Ergebnis einer mathematischen Berechnung zwischen anderen Spalten sind - vorausgesetzt, sie sind als Zahlenformat gespeichert. Um das auszuprobieren, legen wir eine neue Spalte \"komische_berechnung\" an, die das Ergebnis der Division der Werte in der Spalte \"ID\" durch die Werte in der Spalte \"PLZ\" beinhaltet. Diese Berechnung ergibt keinen Sinn, soll aber auch nur das Prinzip verdeutlichen." + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " Unnamed: 0 ID Fachgebiet Adresse PLZ \\\n", + "0 0 2 Hals-Nasen-Ohrenheilkunde Waitzstr. 7 22607 \n", + "1 1 52 Hals-Nasen-Ohrenheilkunde Neuer Wall 43 20354 \n", + "2 2 102 Hals-Nasen-Ohrenheilkunde Möllner Landstr. 26 a 22111 \n", + "3 3 125 Hals-Nasen-Ohrenheilkunde Wandsbeker Marktstr. 73 22041 \n", + "4 4 148 Hals-Nasen-Ohrenheilkunde Sand 35 21073 \n", + "\n", + " Privatarzt Stadt Land Bundesland komische_berechnung \n", + "0 NaN Hamburg Germany Hamburg 0.000088 \n", + "1 NaN Hamburg Germany Hamburg 0.002555 \n", + "2 NaN Hamburg Germany Hamburg 0.004613 \n", + "3 NaN Hamburg Germany Hamburg 0.005671 \n", + "4 NaN Hamburg Germany Hamburg 0.007023 \n" + ] + } + ], + "source": [ + "df[\"komische_berechnung\"] = df[\"ID\"]/df[\"PLZ\"]\n", + "print(df)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Eine neue Spalte auf diese Weise anzulegen, war ziemlich einfach. Es sollte erwähnt werden, dass es noch andere Methoden gibt, die auch auf eine korrekte Indizierung der neu angelegten Spalten im DataFrame Wert legen. Aber für unseren Bedarf ist die Methode oben erstmal ausreichend. \n", + "\n", + "Nun löschen wir diese Spalte lieber wieder:" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " Unnamed: 0 ID Fachgebiet Adresse PLZ \\\n", + "0 0 2 Hals-Nasen-Ohrenheilkunde Waitzstr. 7 22607 \n", + "1 1 52 Hals-Nasen-Ohrenheilkunde Neuer Wall 43 20354 \n", + "2 2 102 Hals-Nasen-Ohrenheilkunde Möllner Landstr. 26 a 22111 \n", + "3 3 125 Hals-Nasen-Ohrenheilkunde Wandsbeker Marktstr. 73 22041 \n", + "4 4 148 Hals-Nasen-Ohrenheilkunde Sand 35 21073 \n", + "\n", + " Privatarzt Stadt Land Bundesland \n", + "0 NaN Hamburg Germany Hamburg \n", + "1 NaN Hamburg Germany Hamburg \n", + "2 NaN Hamburg Germany Hamburg \n", + "3 NaN Hamburg Germany Hamburg \n", + "4 NaN Hamburg Germany Hamburg \n" + ] + } + ], + "source": [ + "df = df.drop(\"komische_berechnung\", 1) #Hierbei weist 1 auf eine Spalte hin und 0 auf eine Zeile. \n", + "print(df)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Es gibt auch Fälle, da wollen wir eine Spalte anlegen, die in etwas komplexerer Abhängigkeit zu einer anderen Spalte steht, oder wir wollen bestehende Werte in Abhängigkeit von irgendwelchen anderen Informationen updaten. So etwas kann schnell eine relativ komplizierte und unintutive Syntax erfordern.\n", + "\n", + "Um das zu umgehen, können wir auch einfach unser bestehendes Wissen über Schleifen, Listen und Dictionaries nutzen. Wir legen zunächst eine leere Liste anlegen, iterieren dann durch das DataFrame und legen für jede Zeile ein neues Dictionary mit den gewünschten Zeilen-Werten an. Entweder erstellt man das Dictionary komplett neu, oder man nutzt die bereits vorhandenen Zeilenwerte und ergänzt diese nur. Danach fügt man das Dictionary der Liste hinzu und am Ende erstellt man aus dieser Liste ein neues DataFrame. Der folgende Codeausschnitt verdeutlicht, wie man durch ein DataFrame iteriert:" ] }, { "cell_type": "code", - "execution_count": 48, + "execution_count": 47, "metadata": {}, "outputs": [ { @@ -589,7 +665,7 @@ ], "source": [ "df = pd.DataFrame(pd.read_csv(\"../Daten/Selektion.csv\", sep=','))\n", - "for index, data in df.iterrows(): # Syntax, um durch ein DataFrame zu iterieren\n", + "for index, data in df.iterrows(): # Syntax, um durch die Zeilen (Rows = Reihen = Zeilen) eines DataFrame zu iterieren\n", " print(index) #Index der aktuellen Zeile\n", " print(data) #Daten in dieser Zeile\n", " print(type(data)) " @@ -599,12 +675,12 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Der Datentyp \"Series\" sagt uns noch nichts. Es reicht aber, zu wissen, dass man eine Series auch leicht in ein Dictionary umwandeln kann." + "Der Datentyp \"Series\" sagt uns noch nichts. Wie bei einem Dictionary kann man jedoch z.B. mit data[\"Adresse\"] auf einen Series-Eintrag zugreifen. Außerdem lässt sich die komplette Series auch einfach in ein Dictionary umwandeln:" ] }, { "cell_type": "code", - "execution_count": 49, + "execution_count": 53, "metadata": {}, "outputs": [ { @@ -628,66 +704,40 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Wenn wir nun also noch eine Spalte mit eigenen Werten zu unserer Tabelle hinzufügen wollen, können wir dieses Dictionary nehmen und in gewohnter Art um einen Eintrag ergänzen. In unserem Fall legen wir eine neue Spalte \"komische_berechnung\" an, die die Postleitzahl durch die ID teilt. Diese Berechnung ergibt keinerlei Sinn, soll aber auch nur das Prinzip verdeutlichen." + "Angenommen, wir haben nun außerdem ein komplett separates Dictionary gegeben..." ] }, { "cell_type": "code", - "execution_count": 50, + "execution_count": 54, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[{'Unnamed: 0': 0, 'ID': 2, 'Fachgebiet': 'Hals-Nasen-Ohrenheilkunde', 'Adresse': 'Waitzstr. 7', 'PLZ': 22607, 'Privatarzt': nan, 'Stadt': 'Hamburg', 'Land': 'Germany', 'Bundesland': 'Hamburg', 'komische_berechnung': 11303.5}, {'Unnamed: 0': 1, 'ID': 52, 'Fachgebiet': 'Hals-Nasen-Ohrenheilkunde', 'Adresse': 'Neuer Wall 43', 'PLZ': 20354, 'Privatarzt': nan, 'Stadt': 'Hamburg', 'Land': 'Germany', 'Bundesland': 'Hamburg', 'komische_berechnung': 391.4230769230769}, {'Unnamed: 0': 2, 'ID': 102, 'Fachgebiet': 'Hals-Nasen-Ohrenheilkunde', 'Adresse': 'Möllner Landstr. 26 a', 'PLZ': 22111, 'Privatarzt': nan, 'Stadt': 'Hamburg', 'Land': 'Germany', 'Bundesland': 'Hamburg', 'komische_berechnung': 216.77450980392157}, {'Unnamed: 0': 3, 'ID': 125, 'Fachgebiet': 'Hals-Nasen-Ohrenheilkunde', 'Adresse': 'Wandsbeker Marktstr. 73', 'PLZ': 22041, 'Privatarzt': nan, 'Stadt': 'Hamburg', 'Land': 'Germany', 'Bundesland': 'Hamburg', 'komische_berechnung': 176.328}, {'Unnamed: 0': 4, 'ID': 148, 'Fachgebiet': 'Hals-Nasen-Ohrenheilkunde', 'Adresse': 'Sand 35', 'PLZ': 21073, 'Privatarzt': nan, 'Stadt': 'Hamburg', 'Land': 'Germany', 'Bundesland': 'Hamburg', 'komische_berechnung': 142.38513513513513}]\n", - ".................................................................\n", - " Unnamed: 0 ID Fachgebiet Adresse PLZ \\\n", - "0 0 2 Hals-Nasen-Ohrenheilkunde Waitzstr. 7 22607 \n", - "1 1 52 Hals-Nasen-Ohrenheilkunde Neuer Wall 43 20354 \n", - "2 2 102 Hals-Nasen-Ohrenheilkunde Möllner Landstr. 26 a 22111 \n", - "3 3 125 Hals-Nasen-Ohrenheilkunde Wandsbeker Marktstr. 73 22041 \n", - "4 4 148 Hals-Nasen-Ohrenheilkunde Sand 35 21073 \n", - "\n", - " Privatarzt Stadt Land Bundesland komische_berechnung \n", - "0 NaN Hamburg Germany Hamburg 11303.500000 \n", - "1 NaN Hamburg Germany Hamburg 391.423077 \n", - "2 NaN Hamburg Germany Hamburg 216.774510 \n", - "3 NaN Hamburg Germany Hamburg 176.328000 \n", - "4 NaN Hamburg Germany Hamburg 142.385135 \n" - ] - } - ], + "outputs": [], "source": [ - "neu = list() #Synonym zu neu = [], d.h. Erstellen einer neuen leeren Liste\n", - "for index, data in df.iterrows(): \n", - " values = data.to_dict() #erhalte die Werte in dieser Zeile als Dictionary\n", - " values[\"komische_berechnung\"] = values[\"PLZ\"]/values[\"ID\"] #füge dem Dictionary einen neuen Eintrag hinzu\n", - " neu.append(values)\n", - "print(neu) #Liste mit Dictionaries!\n", - "df = pd.DataFrame(neu) #aus einer Liste mit Dictionaries können wir wieder ein DataFrame basteln!\n", - "print(\".................................................................\")\n", - "print(df)" + "zusatz_infos = {\"Waitzstr. 7\": \"Othmarschen\", \n", + " \"Neuer Wall 43\" : \"Neustadt\",\n", + " \"Sand 35\" : \"Harburg\" }" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Wichtig: Hätten wir nur \"values\" verändert, aber nicht in einer neuen Liste gespeichert, so hätte das das DataFrame nicht verändert! Mit anderen Worten, ein DataFrame kann während des Durchiterierens nicht so einfach verändert werden - besser liest man nur die nötigen Werte aus und legt damit dynamisch ein neues an.\n", + "... und wollen eine neue Spalte \"Stadtteil\" zu unserer Tabelle hinzufügen, die ihre Informationen aus diesem Dictionary bezieht, sofern vorhanden. \n", "\n", - "Wollen wir nun unsere \"komische_berechnung\"-Spalte wieder löschen, gehen wir so vor:" + "In jedem Schleifen-Durchgang lesen wir also die Adresse aus dem DataFrame und nutzen Sie als Schlüssel für das Dictionary, um den zugehörigen Wert zu erhalten. Für den Fall, dass der Schlüssel nicht existiert, setzen wir den Wert auf \"Unbekannt\"." ] }, { "cell_type": "code", - "execution_count": 51, + "execution_count": 59, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ + "[{'Unnamed: 0': 0, 'ID': 2, 'Fachgebiet': 'Hals-Nasen-Ohrenheilkunde', 'Adresse': 'Waitzstr. 7', 'PLZ': 22607, 'Privatarzt': nan, 'Stadt': 'Hamburg', 'Land': 'Germany', 'Bundesland': 'Hamburg', 'Stadtteil': 'Othmarschen'}, {'Unnamed: 0': 1, 'ID': 52, 'Fachgebiet': 'Hals-Nasen-Ohrenheilkunde', 'Adresse': 'Neuer Wall 43', 'PLZ': 20354, 'Privatarzt': nan, 'Stadt': 'Hamburg', 'Land': 'Germany', 'Bundesland': 'Hamburg', 'Stadtteil': 'Neustadt'}, {'Unnamed: 0': 2, 'ID': 102, 'Fachgebiet': 'Hals-Nasen-Ohrenheilkunde', 'Adresse': 'Möllner Landstr. 26 a', 'PLZ': 22111, 'Privatarzt': nan, 'Stadt': 'Hamburg', 'Land': 'Germany', 'Bundesland': 'Hamburg', 'Stadtteil': 'Unbekannt'}, {'Unnamed: 0': 3, 'ID': 125, 'Fachgebiet': 'Hals-Nasen-Ohrenheilkunde', 'Adresse': 'Wandsbeker Marktstr. 73', 'PLZ': 22041, 'Privatarzt': nan, 'Stadt': 'Hamburg', 'Land': 'Germany', 'Bundesland': 'Hamburg', 'Stadtteil': 'Unbekannt'}, {'Unnamed: 0': 4, 'ID': 148, 'Fachgebiet': 'Hals-Nasen-Ohrenheilkunde', 'Adresse': 'Sand 35', 'PLZ': 21073, 'Privatarzt': nan, 'Stadt': 'Hamburg', 'Land': 'Germany', 'Bundesland': 'Hamburg', 'Stadtteil': 'Harburg'}]\n", + ".................................................................\n", " Unnamed: 0 ID Fachgebiet Adresse PLZ \\\n", "0 0 2 Hals-Nasen-Ohrenheilkunde Waitzstr. 7 22607 \n", "1 1 52 Hals-Nasen-Ohrenheilkunde Neuer Wall 43 20354 \n", @@ -695,19 +745,36 @@ "3 3 125 Hals-Nasen-Ohrenheilkunde Wandsbeker Marktstr. 73 22041 \n", "4 4 148 Hals-Nasen-Ohrenheilkunde Sand 35 21073 \n", "\n", - " Privatarzt Stadt Land Bundesland \n", - "0 NaN Hamburg Germany Hamburg \n", - "1 NaN Hamburg Germany Hamburg \n", - "2 NaN Hamburg Germany Hamburg \n", - "3 NaN Hamburg Germany Hamburg \n", - "4 NaN Hamburg Germany Hamburg \n" + " Privatarzt Stadt Land Bundesland Stadtteil \n", + "0 NaN Hamburg Germany Hamburg Othmarschen \n", + "1 NaN Hamburg Germany Hamburg Neustadt \n", + "2 NaN Hamburg Germany Hamburg Unbekannt \n", + "3 NaN Hamburg Germany Hamburg Unbekannt \n", + "4 NaN Hamburg Germany Hamburg Harburg \n" ] } ], "source": [ - "df = df.drop(\"komische_berechnung\", 1) #Hierbei weist 1 auf eine Spalte hin und 0 auf eine Zeile. \n", + "liste_mit_zeilen = list() #Synonym zu neu = [], d.h. Erstellen einer neuen leeren Liste\n", + "for index, data in df.iterrows(): \n", + " zeile = data.to_dict() #erhalte die bereits bestehenden Werte in dieser Zeile als Dictionary\n", + " if zeile[\"Adresse\"] in zusatz_infos.keys(): #falls dieser Schlüssel im separaten Dictionary existiert...\n", + " zeile[\"Stadtteil\"] = zusatz_infos[data[\"Adresse\"]] #... füge den zugehörigen Wert zur Zeile hinzu \n", + " else:\n", + " zeile[\"Stadtteil\"] = \"Unbekannt\"\n", + " liste_mit_zeilen.append(zeile)\n", + "print(liste_mit_zeilen) #Liste mit Zeilen in Form von Dictionaries!\n", + "df = pd.DataFrame(liste_mit_zeilen) #aus einer Liste mit Dictionaries können wir wieder ein DataFrame basteln!\n", + "print(\".................................................................\")\n", "print(df)" ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Wichtig: Hätten wir versucht, während des Schleifendurchlaufs Teile der \"data\"-Series und damit des DataFrames direkt zu verändern, anstatt nur Informationen zu extrahieren und in einer neuen Liste zu speichern, so hätte das keine Auswirkungen auf das DataFrame gehabt. Mit anderen Worten, ein DataFrame kann während des Durchiterierens nicht auf diese Weise verändert werden. Es gibt zwar noch diverse andere Möglichkeiten zum Manipulieren von DataFrames, aber wie bereits erwähnt erfordern diese meist das Wissen um spezielle Syntax." + ] } ], "metadata": { -- GitLab