Added notebooks and models

This commit is contained in:
mayersn 2019-08-07 17:57:12 -04:00
parent f4ce991790
commit 0fb6efadd5
28 changed files with 37002 additions and 0 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
python/Models/CNN.pb Normal file

Binary file not shown.

BIN
python/Models/LSTM.pb Normal file

Binary file not shown.

View File

@ -0,0 +1,340 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"%matplotlib inline\n",
"\n",
"from scipy.odr import *\n",
"from scipy.stats import *\n",
"import numpy as np\n",
"import pandas as pd\n",
"import os\n",
"import time\n",
"import matplotlib.pyplot as plt\n",
"from multiprocessing import Pool"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"def cast_to_int(row):\n",
" try:\n",
" return np.array([a if float(a) >= 0 else 0 for a in row[2:-1]], dtype=np.uint8)\n",
" except Exception as e:\n",
" return None\n",
" \n",
"def load_csv(file):\n",
" temp_df = pd.read_csv(file, header=None, names = [\"UserID\", \"Age\", \"Gender\"], delimiter=\";\")\n",
" return temp_df"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"CPU times: user 298 ms, sys: 443 ms, total: 741 ms\n",
"Wall time: 937 ms\n"
]
}
],
"source": [
"%%time\n",
"pool = Pool(os.cpu_count() - 2)\n",
"data_files = [\"DataStudyCollection/%s\" % file for file in os.listdir(\"DataStudyCollection\") if file.endswith(\".csv\") and \"userData\" in file]\n",
"df_lst = pool.map(load_csv, data_files)\n",
"dfAll = pd.concat(df_lst)\n",
"dfAll = dfAll.sort_values(\"UserID\")\n",
"dfAll = dfAll.reset_index(drop=True)\n",
"pool.close()"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"24.166666666666668"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dfAll.Age.mean()"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1.4245742398014511"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dfAll.Age.std()"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"21"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dfAll.Age.min()"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"26"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dfAll.Age.max()"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>UserID</th>\n",
" <th>Age</th>\n",
" <th>Gender</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>1</td>\n",
" <td>23</td>\n",
" <td>male</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>2</td>\n",
" <td>24</td>\n",
" <td>male</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>3</td>\n",
" <td>25</td>\n",
" <td>male</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>4</td>\n",
" <td>25</td>\n",
" <td>male</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>5</td>\n",
" <td>26</td>\n",
" <td>male</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5</th>\n",
" <td>6</td>\n",
" <td>23</td>\n",
" <td>male</td>\n",
" </tr>\n",
" <tr>\n",
" <th>6</th>\n",
" <td>7</td>\n",
" <td>21</td>\n",
" <td>female</td>\n",
" </tr>\n",
" <tr>\n",
" <th>7</th>\n",
" <td>8</td>\n",
" <td>24</td>\n",
" <td>male</td>\n",
" </tr>\n",
" <tr>\n",
" <th>8</th>\n",
" <td>9</td>\n",
" <td>24</td>\n",
" <td>male</td>\n",
" </tr>\n",
" <tr>\n",
" <th>9</th>\n",
" <td>10</td>\n",
" <td>24</td>\n",
" <td>male</td>\n",
" </tr>\n",
" <tr>\n",
" <th>10</th>\n",
" <td>11</td>\n",
" <td>25</td>\n",
" <td>female</td>\n",
" </tr>\n",
" <tr>\n",
" <th>11</th>\n",
" <td>12</td>\n",
" <td>26</td>\n",
" <td>male</td>\n",
" </tr>\n",
" <tr>\n",
" <th>12</th>\n",
" <td>13</td>\n",
" <td>22</td>\n",
" <td>female</td>\n",
" </tr>\n",
" <tr>\n",
" <th>13</th>\n",
" <td>14</td>\n",
" <td>24</td>\n",
" <td>male</td>\n",
" </tr>\n",
" <tr>\n",
" <th>14</th>\n",
" <td>15</td>\n",
" <td>24</td>\n",
" <td>male</td>\n",
" </tr>\n",
" <tr>\n",
" <th>15</th>\n",
" <td>16</td>\n",
" <td>26</td>\n",
" <td>female</td>\n",
" </tr>\n",
" <tr>\n",
" <th>16</th>\n",
" <td>17</td>\n",
" <td>26</td>\n",
" <td>male</td>\n",
" </tr>\n",
" <tr>\n",
" <th>17</th>\n",
" <td>18</td>\n",
" <td>23</td>\n",
" <td>male</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" UserID Age Gender\n",
"0 1 23 male\n",
"1 2 24 male\n",
"2 3 25 male\n",
"3 4 25 male\n",
"4 5 26 male\n",
"5 6 23 male\n",
"6 7 21 female\n",
"7 8 24 male\n",
"8 9 24 male\n",
"9 10 24 male\n",
"10 11 25 female\n",
"11 12 26 male\n",
"12 13 22 female\n",
"13 14 24 male\n",
"14 15 24 male\n",
"15 16 26 female\n",
"16 17 26 male\n",
"17 18 23 male"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dfAll"
]
}
],
"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.7.3"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -0,0 +1,338 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## This notebook creates one dataframe from all participants data\n",
"## It also removes 1% of the data as this is corrupted"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"%matplotlib inline\n",
"\n",
"from scipy.odr import *\n",
"from scipy.stats import *\n",
"import numpy as np\n",
"import pandas as pd\n",
"import os\n",
"import time\n",
"import matplotlib.pyplot as plt\n",
"import ast\n",
"from multiprocessing import Pool, cpu_count\n",
"\n",
"import scipy\n",
"\n",
"from IPython import display\n",
"from matplotlib.patches import Rectangle\n",
"\n",
"from sklearn.metrics import mean_squared_error\n",
"import json\n",
"\n",
"import scipy.stats as st\n",
"from sklearn.metrics import r2_score\n",
"\n",
"\n",
"from matplotlib import cm\n",
"from mpl_toolkits.mplot3d import axes3d\n",
"import matplotlib.pyplot as plt\n",
"\n",
"import copy\n",
"\n",
"from sklearn.model_selection import LeaveOneOut, LeavePOut\n",
"\n",
"from multiprocessing import Pool"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"def cast_to_int(row):\n",
" try:\n",
" return np.array([a if float(a) >= 0 else 0 for a in row[2:-1]], dtype=np.uint8)\n",
" except Exception as e:\n",
" return None\n",
" \n",
"def load_csv(file):\n",
" temp_df = pd.read_csv(file, delimiter=\";\")\n",
" temp_df.Image = temp_df.Image.str.split(',')\n",
" temp_df.Image = temp_df.Image.apply(cast_to_int)\n",
" return temp_df"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"['DataStudyCollection/17_studyData.csv', 'DataStudyCollection/2_studyData.csv', 'DataStudyCollection/12_studyData.csv', 'DataStudyCollection/15_studyData.csv', 'DataStudyCollection/5_studyData.csv', 'DataStudyCollection/1_studyData.csv', 'DataStudyCollection/14_studyData.csv', 'DataStudyCollection/10_studyData.csv', 'DataStudyCollection/13_studyData.csv', 'DataStudyCollection/18_studyData.csv', 'DataStudyCollection/6_studyData.csv', 'DataStudyCollection/16_studyData.csv', 'DataStudyCollection/3_studyData.csv', 'DataStudyCollection/7_studyData.csv', 'DataStudyCollection/8_studyData.csv', 'DataStudyCollection/9_studyData.csv', 'DataStudyCollection/11_studyData.csv', 'DataStudyCollection/4_studyData.csv']\n",
"CPU times: user 1.86 s, sys: 1.03 s, total: 2.89 s\n",
"Wall time: 17.3 s\n"
]
}
],
"source": [
"%%time\n",
"pool = Pool(cpu_count() - 2)\n",
"data_files = [\"DataStudyCollection/%s\" % file for file in os.listdir(\"DataStudyCollection\") if file.endswith(\".csv\") and \"studyData\" in file]\n",
"print(data_files)\n",
"df_lst = pool.map(load_csv, data_files)\n",
"dfAll = pd.concat(df_lst)\n",
"pool.close()"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1010014"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df = dfAll[dfAll.Image.notnull()]\n",
"len(df)"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"loaded 1013841 values\n",
"removed 3827 values (thats 0.377%)\n",
"new df has size 1010014\n"
]
}
],
"source": [
"print(\"loaded %s values\" % len(dfAll))\n",
"print(\"removed %s values (thats %s%%)\" % (len(dfAll) - len(df), round((len(dfAll) - len(df)) / len(dfAll) * 100, 3)))\n",
"print(\"new df has size %s\" % len(df))"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"df = df.reset_index(drop=True)\n"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>userID</th>\n",
" <th>Timestamp</th>\n",
" <th>Current_Task</th>\n",
" <th>Task_amount</th>\n",
" <th>TaskID</th>\n",
" <th>VersionID</th>\n",
" <th>RepetitionID</th>\n",
" <th>Actual_Data</th>\n",
" <th>Is_Pause</th>\n",
" <th>Image</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>17</td>\n",
" <td>1547138602677</td>\n",
" <td>0</td>\n",
" <td>34</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>False</td>\n",
" <td>False</td>\n",
" <td>[1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 2, 0, ...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>17</td>\n",
" <td>1547138602697</td>\n",
" <td>0</td>\n",
" <td>34</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>False</td>\n",
" <td>False</td>\n",
" <td>[1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 2, 0, ...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>17</td>\n",
" <td>1547138602796</td>\n",
" <td>0</td>\n",
" <td>34</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>False</td>\n",
" <td>False</td>\n",
" <td>[1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 2, 0, ...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>17</td>\n",
" <td>1547138602817</td>\n",
" <td>0</td>\n",
" <td>34</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>False</td>\n",
" <td>False</td>\n",
" <td>[1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 2, 0, ...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>17</td>\n",
" <td>1547138602863</td>\n",
" <td>0</td>\n",
" <td>34</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>False</td>\n",
" <td>False</td>\n",
" <td>[1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 2, 0, ...</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" userID Timestamp Current_Task Task_amount TaskID VersionID \\\n",
"0 17 1547138602677 0 34 0 0 \n",
"1 17 1547138602697 0 34 0 0 \n",
"2 17 1547138602796 0 34 0 0 \n",
"3 17 1547138602817 0 34 0 0 \n",
"4 17 1547138602863 0 34 0 0 \n",
"\n",
" RepetitionID Actual_Data Is_Pause \\\n",
"0 0 False False \n",
"1 0 False False \n",
"2 0 False False \n",
"3 0 False False \n",
"4 0 False False \n",
"\n",
" Image \n",
"0 [1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 2, 0, ... \n",
"1 [1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 2, 0, ... \n",
"2 [1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 2, 0, ... \n",
"3 [1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 2, 0, ... \n",
"4 [1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 2, 0, ... "
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df.head()"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"df.to_pickle(\"DataStudyCollection/AllData.pkl\")"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"sorted(df.userID.unique())"
]
}
],
"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
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,890 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"## USE for Multi GPU Systems\n",
"#import os\n",
"#os.environ[\"CUDA_VISIBLE_DEVICES\"]=\"0\"\n",
"\n",
"%matplotlib inline\n",
"\n",
"from scipy.odr import *\n",
"from scipy.stats import *\n",
"import numpy as np\n",
"import pandas as pd\n",
"import os\n",
"import time\n",
"import matplotlib.pyplot as plt\n",
"import ast\n",
"from multiprocessing import Pool\n",
"\n",
"import scipy\n",
"\n",
"from IPython import display\n",
"from matplotlib.patches import Rectangle\n",
"\n",
"from sklearn.metrics import mean_squared_error\n",
"import json\n",
"\n",
"import scipy.stats as st\n",
"from sklearn.metrics import r2_score\n",
"\n",
"\n",
"from matplotlib import cm\n",
"from mpl_toolkits.mplot3d import axes3d\n",
"import matplotlib.pyplot as plt\n",
"from matplotlib.patches import Ellipse\n",
"\n",
"import copy\n",
"\n",
"from sklearn.model_selection import LeaveOneOut, LeavePOut\n",
"\n",
"from multiprocessing import Pool\n",
"import cv2\n",
"\n",
"import sklearn\n",
"import random\n",
"from sklearn import neighbors\n",
"from sklearn import svm\n",
"from sklearn import tree\n",
"from sklearn import ensemble\n",
"from sklearn.model_selection import GridSearchCV\n",
"from sklearn.metrics import classification_report\n",
"\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"import pandas as pd\n",
"import math\n",
"\n",
"# Importing matplotlib to plot images.\n",
"import matplotlib.pyplot as plt\n",
"import numpy as np\n",
"%matplotlib inline\n",
"\n",
"# Importing SK-learn to calculate precision and recall\n",
"import sklearn\n",
"from sklearn import metrics\n",
"from sklearn.model_selection import train_test_split, cross_val_score, LeaveOneGroupOut\n",
"from sklearn.utils import shuffle\n",
"from sklearn.model_selection import GridSearchCV\n",
"from sklearn.metrics.pairwise import euclidean_distances\n",
"from sklearn.metrics import confusion_matrix\n",
"from sklearn.metrics import accuracy_score\n",
"\n",
"import pickle as pkl\n",
"import h5py\n",
"\n",
"from pathlib import Path\n",
"import os.path\n",
"import sys\n",
"import datetime\n",
"import time\n",
"\n",
"import skimage\n",
"\n",
"target_names = [\"Knuckle\", \"Finger\"]"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"from skimage import measure\n",
"from skimage.measure import find_contours, approximate_polygon, \\\n",
" subdivide_polygon, EllipseModel, LineModelND"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"def getEllipseParams(img):\n",
" points = np.argwhere(img > 40)\n",
" \n",
" contours = skimage.measure.find_contours(img, 40)\n",
" points_to_approx = []\n",
" highest_val = 0\n",
" for n, contour in enumerate(contours):\n",
" if (len(contour) > highest_val):\n",
" points_to_approx = contour\n",
" highest_val = len(contour) \n",
" \n",
" try:\n",
" contour = np.fliplr(points_to_approx)\n",
" except Exception as inst:\n",
" return [-1, -1, -1, -1, -1]\n",
" \n",
"\n",
" ellipse = skimage.measure.fit.EllipseModel()\n",
" ellipse.estimate(contour)\n",
" try:\n",
" xc, yc, a, b, theta = ellipse.params \n",
" except Exception as int:\n",
" return [-1, -1, -1, -1, -1]\n",
" \n",
" return [xc, yc, a, b, theta]"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[ 1 2 9 6 4 14 17 16 12 3 10 18 5] [13 8 11 15 7]\n",
"13 : 5\n",
"0.7222222222222222 : 0.2777777777777778\n"
]
}
],
"source": [
"# the data, split between train and test sets\n",
"df = pd.read_pickle(\"DataStudyCollection/df_statistics.pkl\")\n",
"\n",
"lst = df.userID.unique()\n",
"np.random.seed(42)\n",
"np.random.shuffle(lst)\n",
"test_ids = lst[-5:]\n",
"train_ids = lst[:-5]\n",
"\n",
"df[\"Set\"] = \"Test\"\n",
"df.loc[df.userID.isin(train_ids), \"Set\"] = \"Train\"\n",
"print(train_ids, test_ids)\n",
"print(len(train_ids), \":\", len(test_ids))\n",
"print(len(train_ids) / len(lst), \":\", len(test_ids)/ len(lst))\n",
"\n",
"#df_train = df[df.userID.isin(train_ids)]\n",
"#df_test = df[df.userID.isin(test_ids) & (df.Version == \"Normal\")]\n"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<matplotlib.patches.Ellipse at 0x7ff60430b668>"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAJ4AAAD8CAYAAACGuR0qAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAADetJREFUeJzt3XuQVPWZxvHvO8AwMAy3gCNBRbCQDV4yuoSoYArvqNkga0K8ZXHXCmrFXbWyu2VlqzS7+YdaNWx243pJQImV6LoaSjZFokhijHeZaBBULuE+AgPKZYIyzDDv/tFnKsNlunu6e/rt6Xk+VVPdfW79UvVwus85/TuvuTsixVYRXYD0TgqehFDwJISCJyEUPAmh4EkIBU9CKHgSQsGTEH2L+WaV1t+rqO58AbO061ufDP9PDrWlnZ3xGo2u4uStid273H1kpuXyCp6ZTQd+APQBfuzuc9MtX0U1X6y4uPPtVVamfb+KmkFp5/uf9qefnyFY3tycdr5k9oI/vSmb5XL+qDWzPsADwOXAROBaM5uY6/akd8nnO95kYJ27r3f3g8CTwIzClCXlLp/gjQa2dHi9NZl2GDObY2bLzWx5C/ook5RuP6p190fcfZK7T+pH/+5+O+kh8gleA3Bih9cnJNNEMsoneG8B481srJlVAtcAiwtTlpS7nE+nuHurmd0GPEfqdMoCd1+VdiWztKdMKgYOTL96htMp1jf9P6d1R2Pa+VI8eZ3Hc/clwJIC1SK9iC6ZSQgFT0IoeBKiqD8SKKR+lX353NljOHnCKCoqjLY2Z/PKzbxfv4HmT1uiy5MMelzwaoYO5Ou3XsSV151L1cCjj5BbDrbyxtKVPPEfv2T9Kp1WLFU9KnjnXnIa3773GqprBgDwx/caWP2HzTR/2kJlVT8mnHEC404bzdQr65h6ZR2/fuZNHvjOU3zSdCC4cjlSaQVv5PBOZ13x9S/yrXtm0Keigpc2bOTe3/2O9xp3HrbMwHpj5OBqbpz2l8w67/NcePVkTvnSeG6b/ywbd+7msw/uTfv2bQcU0GLpEQcXZ08Zzz/860z6VFQw7+VX+Ntnfn5U6Nrt3Lefexe/xNX3Pc77DY2MGTmM+bd+lVHDaopctaRT8sEbMqyaf5w7C4B5r7zKD19/I6v1Nu/aw+wf/g9vrtvCcUMG8dA3Z1IzLM2vn6WoSj541956IcNH1rDirfX8d5aha/fpwVbuePT/WLttF+NqP8Mt/35DN1UpXVXSwauuqWL6174AwIPfW0xbDmMimg40c/ujiznQ0srF10+lbpp+JF0KSjp4508/g6oBlbz96lo2rNme83a2fLSXh5e+DqC9Xoko6eCdOXkcAK++kP5HL9l47MV6Ptq+h7Gnn8iZ5/9F3tuT/JR08M6YNBaAFW9tyHtbrYfaWDL/1wB85ZZL8t6e5Keo5/EMsDRjZ33An69EVPbvy8hRQzl4sJVNDXvwAZWsveHBtNuvbz6Ydv4Pvnoj3/iXv2by5XX0H11LS3PrYfPbtupKR7GU7B6vZnDq6kTT3k8yjofN1kc79vLHVQ30r6rkc2efXJBtSm5KNniDaqoA2N9U2JFpq95aD8CEujEF3a50TckG75NPUh+bAwcVdmTahxtTVzxGjBpa0O1K15Rs8PZ8nLodxdACX23Ys7Mptd0R6cdvSPcq2eC1HGxl7+799O3Xh5HHDynYdv+071MABiXfISVGyQYPYM17HwJwWt1JBdtmdRK4/fqpVKiSDt47b6YOBL4wZXzBtlkzNDWEsmnPJwXbpnRdUc/jOelvFVbRcPi419eefIVv3nkZUy+cyEN3/oSz/+3WtNs/OCT9/fVOOrCasafWArBt/XZcv78LU9J7vA83NFL/m1VUDazk0uvOK8g2zzg3tfdc+dragmxPclPSwQNYPP9FAGb9/WUMqa7Ka1ujxx3HSaeO4tP9B1j7h80FqE5yVfLBe+P5d1nxyhqGjqjhjplfymtbV825EIDfLlpOa8uhQpQnOSr54AH85z/9lIPNLcw873S+ck5uv6ebcPwILrt+Cm1tbSx6eFmBK5Su6hHB27puB4/c/TQAd19/KeefPrZL6w/o15f7rrmCyv79+OXjL7Np9bbuKFO6oEcED+AXj/6W+c+9Sd8+Fcy7eQbXXXBWVusNGVjFj2+6mlNqP8Om1dt45O7/7eZKJRulNbwxg/969mUM+LvLJvPPX7uAS846lYeXvMbrHxx9oGAGl585gTsvm8LoYUP4cPc+vnfjQ7rLQImwYnboHmzDPV27gYpBGe5/V9kPgClfPovb77+BwcNTy2/ftIt3X1vD9i0f4w4jPzuMuvMnMGrMCADWvbuFe/7mIXatTn8kq3G1+XvBn65390mZlsu3z8VGoAk4BLRm84aF8Mov3ubtF9/nr26axsxbLub4MSM4PglZR7s+3M3j9y/hhafeoC1D8xUprrz2eEnwJrn7rmyWL9Qe77B1Koxxp5/AaeeMZ8iIwZgZ+3bv54P6Dax5ZxNtbX/+97Xt0Z0EultR9niloK3NWbdiC+tWbMH6HR1MKU35HtU68LyZ1ZvZnEIUJL1Dvnu8qe7eYGbHAUvN7AN3f6njAkkg5wBUkf7m2tJ75LXHc/eG5LERWESqzdSRy6jBihwlnyZ61WZW0/4cuBRYWajCpLzl81FbCyxKxsn2BX7m7r/KuFaao+i2pqY8ypGeJJ8GK+uBzxewFulFesy1WikvCp6EUPAkhIInIRQ8CaHgSQgFT0IoeBJCwZMQCp6EUPAkhIInIRQ8CaHgSQgFT0IoeBJCwZMQCp6EUPAkhIInIRQ8CaHgSQgFT0IoeBJCwZMQCp6EUPAkhIInIRQ8CaHgSQgFT0JkDJ6ZLTCzRjNb2WHacDNbamZrk8dh3VumlJts9niPAdOPmHYXsMzdxwPLktciWcsYvOQu7h8fMXkGsDB5vhC4qsB1SZnL9Tterbu3997cTup+yCJZy/vgwlM9qTq9o7aZzTGz5Wa2vIXmfN9OykSuwdthZqMAksfGzhZUnws5llyDtxiYnTyfDTxbmHKkt8jmdMoTwGvABDPbamY3AXOBS8xsLXBx8lokaxn7XLj7tZ3MuqjAtUgvoisXEkLBkxAKnoRQ8CSEgichFDwJoeBJCAVPQih4EkLBkxAKnoRQ8CSEgichFDwJoeBJCAVPQih4EkLBkxAKnoRQ8CSEgichFDwJoeBJCAVPQih4EkLBkxAKnoRQ8CSEgichFDwJoeBJCAVPQuTaYOW7ZtZgZu8kf1d0b5lSbnJtsAIwz93rkr8lhS1Lyl2uDVZE8pLPd7zbzGxF8lHcaS8z9bmQY8k1eA8CpwB1wDbg/s4WVJ8LOZacgufuO9z9kLu3AT8CJhe2LCl3OQWvvatPYiawsrNlRY4lY5+LpMHKNGCEmW0F7gGmmVkdqR5mG4Gbu7FGKUO5NliZ3w21SC+iKxcSQsGTEAqehFDwJISCJyEUPAmh4EkIBU9CKHgSQsGTEAqehFDwJISCJyEUPAmh4EkIBU9CKHgSQsGTEAqehFDwJISCJyEUPAmh4EkIBU9CKHgSQsGTEAqehFDwJISCJyEUPAmh4EmIbPpcnGhmvzGz98xslZndnkwfbmZLzWxt8tjpDbhFjpTNHq8V+La7TwTOAb5lZhOBu4Bl7j4eWJa8FslKNn0utrn775PnTcD7wGhgBrAwWWwhcFV3FSnlJ+OtaDsys5OBs4A3gFp335bM2g7UdrLOHGAOQBUDc61TykzWBxdmNgh4BrjD3fd1nOfuTupG3EdRnws5lqyCZ2b9SIXup+7+82Tyjva2A8ljY/eUKOUom6NaI3WX9/fd/fsdZi0GZifPZwPPFr48KVfZfMebAnwDeNfM3kmmfQeYCzxlZjcBm4BZ3VOilKNs+ly8DFgnsy8qbDnSW+jKhYRQ8CSEgichFDwJoeBJCAVPQih4EkLBkxAKnoRQ8CSEgichFDwJoeBJCAVPQih4EkLBkxAKnoRQ8CSEgichFDwJoeBJCAVPQih4EkLBkxAKnoRQ8CSEgichFDwJoeBJCAVPQih4EiKfPhffNbMGM3sn+bui+8uVcpHNHUHb+1z83sxqgHozW5rMm+fu93VfeVKusrkj6DZgW/K8ycza+1yI5KxL3/GO6HMBcJuZrTCzBWopJV2RT5+LB4FTgDpSe8T7O1lvjpktN7PlLTQXoGQpBzn3uXD3He5+yN3bgB8Bk4+1rhqsyLHk3OeivblKYiawsvDlSbnKp8/FtWZWR6qV1Ebg5m6pUMpSPn0ulhS+HOktdOVCQih4EkLBkxAKnoRQ8CSEgichFDwJYe5evDcz20mqqXK7EcCuohXQdaVeH5RejWPcfWSmhYoavKPe3Gy5u08KKyCDUq8PekaNx6KPWgmh4EmI6OA9Evz+mZR6fdAzajxK6Hc86b2i93jSS4UEz8ymm9lqM1tnZndF1JCJmW00s3eToZvLS6CeBWbWaGYrO0wbbmZLzWxt8thjxr0UPXhm1gd4ALgcmEjqB6UTi11Hli5w97oSOV3xGDD9iGl3AcvcfTywLHndI0Ts8SYD69x9vbsfBJ4EZgTU0aO4+0vAx0dMngEsTJ4vBK4qalF5iAjeaGBLh9dbKc1xug48b2b1ZjYnuphO1CbjngG2A7WRxXRFNmMuequp7t5gZscBS83sg2SvU5Lc3c2sx5yiiNjjNQAndnh9QjKtpLh7Q/LYCCyik+GbwXa0j/ZLHhuD68laRPDeAsab2VgzqwSuARYH1NEpM6tO7hODmVUDl1KawzcXA7OT57OBZwNr6ZKif9S6e6uZ3QY8B/QBFrj7qmLXkUEtsCg1pJi+wM/c/VeRBZnZE8A0YISZbQXuAeYCT5nZTaR+9TMrrsKu0ZULCaErFxJCwZMQCp6EUPAkhIInIRQ8CaHgSQgFT0L8Pyp94TKMVNfuAAAAAElFTkSuQmCC\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"fig, ax = plt.subplots(1)\n",
"img = df.iloc[0].Blobs\n",
"xc, yc, a, b, theta = getEllipseParams(img)\n",
"ax.imshow(img)\n",
"e = Ellipse(xy=[xc,yc], width=a*2, height=b*2, angle=math.degrees(theta), fill=False, lw=2, edgecolor='w')\n",
"ax.add_artist(e)\n"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"lst = df.Blobs.apply(lambda x: getEllipseParams(x))"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"lst2 = np.vstack(lst.values)"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(618012, 5)"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"lst2.shape"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
"df[\"XC\"] = lst2[:,0]\n",
"df[\"YC\"] = lst2[:,1]\n",
"df[\"EllipseW\"] = lst2[:,2]\n",
"df[\"EllipseH\"] = lst2[:,3]\n",
"df[\"EllipseTheta\"] = lst2[:,4]"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"df[\"Area\"] = df[\"EllipseW\"] * df[\"EllipseH\"] * np.pi\n",
"df[\"AvgCapa\"] = df.Blobs.apply(lambda x: np.mean(x))\n",
"df[\"SumCapa\"] = df.Blobs.apply(lambda x: np.sum(x))"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[8, 11, 6, 7, 16, 15, 14, 10, 9, 2, 3, 13, 17, 5, 12, 1, 4]"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"lst = list(range(1, df.userID.max()))\n",
"SEED = 42#448\n",
"random.seed(SEED)\n",
"random.shuffle(lst)\n",
"lst"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [],
"source": [
"dfY = df[df.Set == \"Train\"].copy(deep=True)\n",
"dfT = df[(df.Set == \"Test\") & (df.Version == \"Normal\")].copy(deep=True)"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [],
"source": [
"minmax = min(len(dfY[dfY.Input == \"Finger\"]), len(dfY[dfY.Input == \"Knuckle\"]))\n",
"dfX = dfY[dfY.Input == \"Finger\"].sample(minmax)\n",
"dfZ = dfY[dfY.Input == \"Knuckle\"].sample(minmax)\n",
"dfY = pd.concat([dfX,dfZ])\n",
"\n",
"minmax = min(len(dfT[dfT.Input == \"Finger\"]), len(dfT[dfT.Input == \"Knuckle\"]))\n",
"dfX = dfT[dfT.Input == \"Finger\"].sample(minmax)\n",
"dfZ = dfT[dfT.Input == \"Knuckle\"].sample(minmax)\n",
"dfT = pd.concat([dfX,dfZ])"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>userID</th>\n",
" <th>Timestamp</th>\n",
" <th>Current_Task</th>\n",
" <th>Task_amount</th>\n",
" <th>TaskID</th>\n",
" <th>VersionID</th>\n",
" <th>RepetitionID</th>\n",
" <th>Actual_Data</th>\n",
" <th>Is_Pause</th>\n",
" <th>Image</th>\n",
" <th>...</th>\n",
" <th>InputMethod</th>\n",
" <th>Set</th>\n",
" <th>XC</th>\n",
" <th>YC</th>\n",
" <th>EllipseW</th>\n",
" <th>EllipseH</th>\n",
" <th>EllipseTheta</th>\n",
" <th>Area</th>\n",
" <th>AvgCapa</th>\n",
" <th>SumCapa</th>\n",
" </tr>\n",
" <tr>\n",
" <th>Input</th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>Finger</th>\n",
" <td>9421</td>\n",
" <td>9421</td>\n",
" <td>9421</td>\n",
" <td>9421</td>\n",
" <td>9421</td>\n",
" <td>9421</td>\n",
" <td>9421</td>\n",
" <td>9421</td>\n",
" <td>9421</td>\n",
" <td>9421</td>\n",
" <td>...</td>\n",
" <td>9421</td>\n",
" <td>9421</td>\n",
" <td>9421</td>\n",
" <td>9421</td>\n",
" <td>9421</td>\n",
" <td>9421</td>\n",
" <td>9421</td>\n",
" <td>9421</td>\n",
" <td>9421</td>\n",
" <td>9421</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Knuckle</th>\n",
" <td>9421</td>\n",
" <td>9421</td>\n",
" <td>9421</td>\n",
" <td>9421</td>\n",
" <td>9421</td>\n",
" <td>9421</td>\n",
" <td>9421</td>\n",
" <td>9421</td>\n",
" <td>9421</td>\n",
" <td>9421</td>\n",
" <td>...</td>\n",
" <td>9421</td>\n",
" <td>9421</td>\n",
" <td>9421</td>\n",
" <td>9421</td>\n",
" <td>9421</td>\n",
" <td>9421</td>\n",
" <td>9421</td>\n",
" <td>9421</td>\n",
" <td>9421</td>\n",
" <td>9421</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>2 rows × 31 columns</p>\n",
"</div>"
],
"text/plain": [
" userID Timestamp Current_Task Task_amount TaskID VersionID \\\n",
"Input \n",
"Finger 9421 9421 9421 9421 9421 9421 \n",
"Knuckle 9421 9421 9421 9421 9421 9421 \n",
"\n",
" RepetitionID Actual_Data Is_Pause Image ... InputMethod Set \\\n",
"Input ... \n",
"Finger 9421 9421 9421 9421 ... 9421 9421 \n",
"Knuckle 9421 9421 9421 9421 ... 9421 9421 \n",
"\n",
" XC YC EllipseW EllipseH EllipseTheta Area AvgCapa SumCapa \n",
"Input \n",
"Finger 9421 9421 9421 9421 9421 9421 9421 9421 \n",
"Knuckle 9421 9421 9421 9421 9421 9421 9421 9421 \n",
"\n",
"[2 rows x 31 columns]"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dfT.groupby(\"Input\").count()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# FEATURE SET: sum of capacitance, avg of capacitance, ellipse area, ellipse width, height and theta."
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [],
"source": [
"features = [\"SumCapa\", \"AvgCapa\", \"Area\", \"EllipseW\", \"EllipseH\", \"EllipseTheta\"]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# ZeroR"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [],
"source": [
"dfT[\"InputMethodPred\"] = 1"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[[ 0 9421]\n",
" [ 0 9421]]\n",
"Accuray: 0.50\n",
"Recall: 0.50\n",
"Precision: 0.50\n",
"F1-Score: 0.33\n",
" precision recall f1-score support\n",
"\n",
" Knuckle 0.00 0.00 0.00 9421\n",
" Finger 0.50 1.00 0.67 9421\n",
"\n",
" micro avg 0.50 0.50 0.50 18842\n",
" macro avg 0.25 0.50 0.33 18842\n",
"weighted avg 0.25 0.50 0.33 18842\n",
"\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"/usr/local/lib/python3.6/dist-packages/sklearn/metrics/classification.py:1143: UndefinedMetricWarning: F-score is ill-defined and being set to 0.0 in labels with no predicted samples.\n",
" 'precision', 'predicted', average, warn_for)\n",
"/usr/local/lib/python3.6/dist-packages/sklearn/metrics/classification.py:1143: UndefinedMetricWarning: Precision and F-score are ill-defined and being set to 0.0 in labels with no predicted samples.\n",
" 'precision', 'predicted', average, warn_for)\n"
]
}
],
"source": [
"print(confusion_matrix(dfT.InputMethod.values, dfT.InputMethodPred.values, labels=[0, 1]))\n",
"print(\"Accuray: %.2f\" % accuracy_score(dfT.InputMethod.values, dfT.InputMethodPred.values))\n",
"print(\"Recall: %.2f\" % metrics.recall_score(dfT.InputMethod.values, dfT.InputMethodPred.values, average=\"macro\"))\n",
"print(\"Precision: %.2f\" % metrics.average_precision_score(dfT.InputMethod.values, dfT.InputMethodPred.values, average=\"macro\"))\n",
"print(\"F1-Score: %.2f\" % metrics.f1_score(dfT.InputMethod.values, dfT.InputMethodPred.values, average=\"macro\"))\n",
"print(classification_report(dfT.InputMethod.values, dfT.InputMethodPred.values, target_names=target_names))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# DecisionTreeClassifier"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Fitting 5 folds for each of 240 candidates, totalling 1200 fits\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[Parallel(n_jobs=30)]: Using backend LokyBackend with 30 concurrent workers.\n",
"[Parallel(n_jobs=30)]: Done 140 tasks | elapsed: 10.4s\n",
"[Parallel(n_jobs=30)]: Done 390 tasks | elapsed: 31.4s\n",
"[Parallel(n_jobs=30)]: Done 740 tasks | elapsed: 1.3min\n",
"[Parallel(n_jobs=30)]: Done 1200 out of 1200 | elapsed: 2.4min finished\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'max_depth': 22, 'min_samples_split': 2} 0.8120637794585754\n",
"[[7409 2012]\n",
" [3096 6325]]\n",
"Accuray: 0.73\n",
"Recall: 0.73\n",
"Precision: 0.67\n",
"F1-Score: 0.73\n",
" precision recall f1-score support\n",
"\n",
" Knuckle 0.71 0.79 0.74 9421\n",
" Finger 0.76 0.67 0.71 9421\n",
"\n",
" micro avg 0.73 0.73 0.73 18842\n",
" macro avg 0.73 0.73 0.73 18842\n",
"weighted avg 0.73 0.73 0.73 18842\n",
"\n",
"CPU times: user 7.26 s, sys: 3.38 s, total: 10.6 s\n",
"Wall time: 2min 29s\n"
]
}
],
"source": [
"%%time\n",
"param_grid = {'max_depth': range(2,32,1),\n",
" 'min_samples_split':range(2,10,1)}\n",
"#TODO: Create Baseline for different ML stuff\n",
"clf = GridSearchCV(tree.DecisionTreeClassifier(), \n",
" param_grid,\n",
" cv=5 , n_jobs=os.cpu_count()-2, verbose=1)\n",
"clf.fit(dfY[features].values, dfY.InputMethod.values)\n",
"print(clf.best_params_, clf.best_score_)\n",
"dfT[\"InputMethodPred\"] = clf.predict(dfT[features].values) \n",
"\n",
"print(confusion_matrix(dfT.InputMethod.values, dfT.InputMethodPred.values, labels=[0, 1]))\n",
"print(\"Accuray: %.3f\" % accuracy_score(dfT.InputMethod.values, dfT.InputMethodPred.values))\n",
"print(\"Recall: %.3f\" % metrics.recall_score(dfT.InputMethod.values, dfT.InputMethodPred.values, average=\"macro\"))\n",
"print(\"Precision: %.3f\" % metrics.average_precision_score(dfT.InputMethod.values, dfT.InputMethodPred.values, average=\"macro\"))\n",
"print(\"F1-Score: %.3f\" % metrics.f1_score(dfT.InputMethod.values, dfT.InputMethodPred.values, average=\"macro\"))\n",
"print(classification_report(dfT.InputMethod.values, dfT.InputMethodPred.values, target_names=target_names))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# RandomForestClassifier"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Fitting 5 folds for each of 180 candidates, totalling 900 fits\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[Parallel(n_jobs=94)]: Using backend LokyBackend with 94 concurrent workers.\n",
"[Parallel(n_jobs=94)]: Done 12 tasks | elapsed: 1.2min\n",
"[Parallel(n_jobs=94)]: Done 262 tasks | elapsed: 4.0min\n",
"[Parallel(n_jobs=94)]: Done 612 tasks | elapsed: 9.2min\n",
"[Parallel(n_jobs=94)]: Done 900 out of 900 | elapsed: 12.8min finished\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'max_depth': 60, 'n_estimators': 63} 0.8669582104371696\n",
"[[8175 1246]\n",
" [2765 6656]]\n",
"Accuray: 0.79\n",
"Recall: 0.71\n",
"Precision: 0.74\n",
"F1-Score: 0.77\n",
" precision recall f1-score support\n",
"\n",
" Knuckle 0.75 0.87 0.80 9421\n",
" Finger 0.84 0.71 0.77 9421\n",
"\n",
" micro avg 0.79 0.79 0.79 18842\n",
" macro avg 0.79 0.79 0.79 18842\n",
"weighted avg 0.79 0.79 0.79 18842\n",
"\n",
"CPU times: user 42.1 s, sys: 834 ms, total: 42.9 s\n",
"Wall time: 13min 28s\n"
]
}
],
"source": [
"%%time\n",
"param_grid = {'n_estimators': range(55,64,1),\n",
" 'max_depth': range(50,70,1)}\n",
"#TODO: Create Baseline for different ML stuff\n",
"clf = GridSearchCV(ensemble.RandomForestClassifier(), \n",
" param_grid,\n",
" cv=5 , n_jobs=os.cpu_count()-2, verbose=1)\n",
"clf.fit(dfY[features].values, dfY.InputMethod.values)\n",
"print(clf.best_params_, clf.best_score_)\n",
"dfT[\"InputMethodPred\"] = clf.predict(dfT[features].values) \n",
"\n",
"print(confusion_matrix(dfT.InputMethod.values, dfT.InputMethodPred.values, labels=[0, 1]))\n",
"print(\"Accuray: %.2f\" % accuracy_score(dfT.InputMethod.values, dfT.InputMethodPred.values))\n",
"print(\"Recall: %.2f\" % metrics.recall_score(dfT.InputMethod.values, dfT.InputMethodPred.values))\n",
"print(\"Precision: %.2f\" % metrics.average_precision_score(dfT.InputMethod.values, dfT.InputMethodPred.values))\n",
"print(\"F1-Score: %.2f\" % metrics.f1_score(dfT.InputMethod.values, dfT.InputMethodPred.values))\n",
"print(classification_report(dfT.InputMethod.values, dfT.InputMethodPred.values, target_names=target_names))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# kNN"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Fitting 5 folds for each of 62 candidates, totalling 310 fits\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[Parallel(n_jobs=94)]: Using backend LokyBackend with 94 concurrent workers.\n",
"[Parallel(n_jobs=94)]: Done 12 tasks | elapsed: 17.7s\n",
"[Parallel(n_jobs=94)]: Done 310 out of 310 | elapsed: 1.5min finished\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'n_neighbors': 2} 0.800546827088748\n",
"[[8187 1234]\n",
" [4318 5103]]\n",
"Accuray: 0.71\n",
"Recall: 0.54\n",
"Precision: 0.67\n",
"F1-Score: 0.65\n",
" precision recall f1-score support\n",
"\n",
" Knuckle 0.65 0.87 0.75 9421\n",
" Finger 0.81 0.54 0.65 9421\n",
"\n",
" micro avg 0.71 0.71 0.71 18842\n",
" macro avg 0.73 0.71 0.70 18842\n",
"weighted avg 0.73 0.71 0.70 18842\n",
"\n",
"CPU times: user 1.74 s, sys: 300 ms, total: 2.04 s\n",
"Wall time: 1min 30s\n"
]
}
],
"source": [
"%%time\n",
"param_grid = {'n_neighbors': range(2,64,1),\n",
" #weights': ['uniform', 'distance']\n",
" }\n",
"#TODO: Create Baseline for different ML stuff\n",
"clf = GridSearchCV(neighbors.KNeighborsClassifier(),\n",
" param_grid,\n",
" cv=5 , n_jobs=os.cpu_count()-2, verbose=1)\n",
"clf.fit(dfY[features].values, dfY.InputMethod.values)\n",
"print(clf.best_params_, clf.best_score_)\n",
"dfT[\"InputMethodPred\"] = clf.predict(dfT[features].values) \n",
"\n",
"print(confusion_matrix(dfT.InputMethod.values, dfT.InputMethodPred.values, labels=[0, 1]))\n",
"print(\"Accuray: %.2f\" % accuracy_score(dfT.InputMethod.values, dfT.InputMethodPred.values))\n",
"print(\"Recall: %.2f\" % metrics.recall_score(dfT.InputMethod.values, dfT.InputMethodPred.values, average=\"macro\"))\n",
"print(\"Precision: %.2f\" % metrics.average_precision_score(dfT.InputMethod.values, dfT.InputMethodPred.values, average=\"macro\"))\n",
"print(\"F1-Score: %.2f\" % metrics.f1_score(dfT.InputMethod.values, dfT.InputMethodPred.values, average=\"macro\"))\n",
"print(classification_report(dfT.InputMethod.values, dfT.InputMethodPred.values, target_names=target_names))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# SVM"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Fitting 5 folds for each of 9 candidates, totalling 45 fits\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[Parallel(n_jobs=94)]: Using backend LokyBackend with 94 concurrent workers.\n",
"[Parallel(n_jobs=94)]: Done 42 out of 45 | elapsed: 1056.5min remaining: 75.5min\n",
"[Parallel(n_jobs=94)]: Done 45 out of 45 | elapsed: 1080.5min finished\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'C': 10.0, 'gamma': 10.0} 0.8256943024851795\n",
"CPU times: user 2h 42min 9s, sys: 23.6 s, total: 2h 42min 33s\n",
"Wall time: 20h 43min 1s\n"
]
}
],
"source": [
"%%time\n",
"C_range = np.logspace(1, 3,3)\n",
"gamma_range = np.logspace(-1, 1, 3)\n",
"param_grid = dict(gamma=gamma_range, C=C_range)\n",
"clf = GridSearchCV(sklearn.svm.SVC(), \n",
" param_grid,\n",
" cv=5 , n_jobs=os.cpu_count()-2, verbose=1)\n",
"clf.fit(dfY[features].values, dfY.InputMethod.values)\n",
"print(clf.best_params_, clf.best_score_)\n",
"\n",
"dfT[\"InputMethodPred\"] = clf.predict(dfT[features].values)"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'C': 10.0, 'gamma': 10.0} 0.8256943024851795\n",
"[[7106 2315]\n",
" [2944 6477]]\n",
"Accuray: 0.72\n",
"Recall: 0.69\n",
"Precision: 0.66\n",
"F1-Score: 0.71\n",
" precision recall f1-score support\n",
"\n",
" Knuckle 0.71 0.75 0.73 9421\n",
" Finger 0.74 0.69 0.71 9421\n",
"\n",
" micro avg 0.72 0.72 0.72 18842\n",
" macro avg 0.72 0.72 0.72 18842\n",
"weighted avg 0.72 0.72 0.72 18842\n",
"\n"
]
}
],
"source": [
"print(clf.best_params_, clf.best_score_)\n",
"print(confusion_matrix(dfT.InputMethod.values, dfT.InputMethodPred.values, labels=[0, 1]))\n",
"print(\"Accuray: %.2f\" % accuracy_score(dfT.InputMethod.values, dfT.InputMethodPred.values))\n",
"print(\"Recall: %.2f\" % metrics.recall_score(dfT.InputMethod.values, dfT.InputMethodPred.values))\n",
"print(\"Precision: %.2f\" % metrics.average_precision_score(dfT.InputMethod.values, dfT.InputMethodPred.values))\n",
"print(\"F1-Score: %.2f\" % metrics.f1_score(dfT.InputMethod.values, dfT.InputMethodPred.values))\n",
"print(classification_report(dfT.InputMethod.values, dfT.InputMethodPred.values, target_names=target_names))"
]
}
],
"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
}

13240
python/Step_07_CNN.ipynb Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,152 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Filtering the data for the LSTM: removes all the rows, where we used the revert button, when the participant performed a wrong gesture\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%matplotlib inline\n",
"\n",
"from scipy.odr import *\n",
"from scipy.stats import *\n",
"import numpy as np\n",
"import pandas as pd\n",
"import os\n",
"import time\n",
"import matplotlib.pyplot as plt\n",
"import ast\n",
"from multiprocessing import Pool, cpu_count\n",
"\n",
"import scipy\n",
"\n",
"from IPython import display\n",
"from matplotlib.patches import Rectangle\n",
"\n",
"from sklearn.metrics import mean_squared_error\n",
"import json\n",
"\n",
"import scipy.stats as st\n",
"from sklearn.metrics import r2_score\n",
"\n",
"\n",
"from matplotlib import cm\n",
"from mpl_toolkits.mplot3d import axes3d\n",
"import matplotlib.pyplot as plt\n",
"\n",
"import copy\n",
"\n",
"from sklearn.model_selection import LeaveOneOut, LeavePOut\n",
"\n",
"from multiprocessing import Pool\n",
"import cv2"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"dfAll = pd.read_pickle(\"DataStudyCollection/AllData.pkl\")\n",
"dfAll.head()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df_actual = dfAll[(dfAll.Actual_Data == True) & (dfAll.Is_Pause == False)]\n",
"df_actual.head()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(\"all: %s, actual data: %s\" % (len(dfAll), len(df_actual)))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%%time\n",
"# filter out all gestures, where the revert button was pressed during the study and the gestrue was repeated\n",
"def is_max(df):\n",
" df_temp = df.copy(deep=True)\n",
" max_version = df_temp.RepetitionID.max()\n",
" df_temp[\"IsMax\"] = np.where(df_temp.RepetitionID == max_version, True, False)\n",
" df_temp[\"MaxRepetition\"] = [max_version] * len(df_temp)\n",
" return df_temp\n",
"\n",
"df_filtered = df_actual.copy(deep=True)\n",
"df_grp = df_filtered.groupby([df_filtered.userID, df_filtered.TaskID, df_filtered.VersionID])\n",
"pool = Pool(cpu_count() - 1)\n",
"result_lst = pool.map(is_max, [grp for name, grp in df_grp])\n",
"df_filtered = pd.concat(result_lst)\n",
"df_filtered = df_filtered[df_filtered.IsMax == True]\n",
"pool.close()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df_filtered.to_pickle(\"DataStudyCollection/df_lstm.pkl\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(\"actual: %s, filtered data: %s\" % (len(df_actual), len(df_filtered)))"
]
},
{
"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
}

File diff suppressed because one or more lines are too long

2550
python/Step_11_LSTM.ipynb Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,494 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import pandas as pd\n",
"import matplotlib.pyplot as plt\n",
"import numpy as np\n",
"%matplotlib inline"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"df = pd.read_pickle(\"DataStudyCollection/df_statistics.pkl\")"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAPUAAAD4CAYAAAA0L6C7AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAA8lJREFUeJzt2D1qVGEYhmFHJ/4VCppOrCyt7azF3hXYuAB7EdcjQgo7N+AKBMHCysJmCiMJYnKsD2M1zOFLbq5rAS9PcW4+OKtpmq4AHVdHDwD2S9QQI2qIETXEiBpi1kscfX7/1YX6pX765NHoCVvOr61GT5i5/fnb6AkzZ5vN6AkX3qfz9//9iLzUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXErJc4urpxfYmzO7v35vvoCVueHX4ZPWHm6MXT0RPmNpvRCy4tLzXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihpj1IlcPDhY5u6t3D49GT9jy+Pqt0RNmPty5OXoCe+KlhhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghZr3E0enkZImzO3v59vXoCVv+3F2NnjDz4OeP0RNm/o4ecIl5qSFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiFkvcXQ6/r3E2Z0dfvw6esK21Wr0gpmzX8ejJ7AnXmqIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTHrJY6en54ucXZ3F20PLMhLDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDzGqaptEbgD3yUkOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0x/wB+HS+RtgmxWAAAAABJRU5ErkJggg==\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAPUAAAD4CAYAAAA0L6C7AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAA91JREFUeJzt2DFqVGEYhlEnDsSAChZaWFiK2LkJSzegpZXrcA8uwspaa8FObLRUG9s4KCSGybW+jEUIuf76cE45xccLw8MPdzVN0yWgY2/0AOBiiRpiRA0xooYYUUPMeomjD/cf/1Of1PcOroyesGt/f/SCuePj0Qtmtj9+jp6w63Q7esHM69OXqz/97qWGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFmvcTRabtd4uy5nd69M3rCjs+Pro2eMHPz/enoCTPX3nwcPWHHdrMZPeFMvNQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmLWSxxdXb68xNlzO7x3dfSEHZ+evhg9Yeb+2yejJ8xcf/fv/WeXNpvRC87ESw0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ8x69IC/4caHw9ETdjx4/mz0hJlbX05GT5iZjo5GT/hveakhRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaohZL3F07+DKEmfP7+u30Qt23H61GT1hZvp1MnoCF8RLDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghZr3E0e1ms8TZlsPvoxcQ5aWGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFmNU3T6A3ABfJSQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTG/ASBTOQKG6jN+AAAAAElFTkSuQmCC\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAPUAAAD4CAYAAAA0L6C7AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAA91JREFUeJzt2S1ulGEYhlGGDgUDKRIJVWUJeLaAx2FZA5ptYFgCCQbLBkhQJBQUP4GKIXQ+9JdBkNLpO71yjqx4cifNNW8ys5im6QrQcXX0AOB8iRpiRA0xooYYUUPMchtHH+492qmv1Bf7+6MnbNi7fTB6wsyu/Qqy/vZ99IQN02o1esLMq/XLxd/+7qWGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFmuY2ji+W1bZw9s8XR4egJG349/zF6wsz7d3dGT5i5/+zD6Akbfn/6PHrCP/FSQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIWY4ecBF+3r05esKGN0cvRk+YOTx+PHrC3I3roxdcWl5qiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpilts4Op2ebuPsmd16+3H0hA0Pnj4ZPWHm3vFq9IS59Xr0gkvLSw0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ8xy9ICLsP7ydfSEDQevV6MnzCz2duvzfTpdj55wae3WfxL4b6KGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFmuZWr69OtnD2r9cnJ6AmbdnETCV5qiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiFtM0jd4AnCMvNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BDzB5HPOlI/So2zAAAAAElFTkSuQmCC\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAPUAAAD4CAYAAAA0L6C7AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAA/pJREFUeJzt2T2OW2UYhmF7bAEphgjoIroBKVkAFXWyCdoUsBaWQkuVWQAdDQVdKqQoPwo/GiFNiH1SH5liZObwObeuq3Tx6pGlW59kr6dpWgEdZ6MHALdL1BAjaogRNcSIGmK2Sxx99OE3J/WT+tmdj0ZPOLD+7JPRE2b2r16PnjCzv7oaPeHQif1TdLn/Yf1vn3upIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qI2S5x9Ozu+RJnj/b7wy9HTzjw8ePfRk+YefP9/dETZj548vPoCYem3egFN+KlhhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQs13k6mazyNljPf96Gj3hwE8Pfhw9Yeare9+NnjDz6bQfPeG95aWGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFmu8jV6+tFzh7r88tp9IQDF/98O3rCzMWvf4+eMLc+wfdm2o1ecCMn+M0B/4WoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQsx094P9w/suL0RMOfPHsfPSEme3Lv0ZPmNltNqMnHJj2u9ETbsRLDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghZrvE0d0ffy5x9nintme1Wq2ejh4w93b0AG6NlxpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihpj1NE2jNwC3yEsNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xLwD3C47I4MwRxwAAAAASUVORK5CYII=\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAPUAAAD4CAYAAAA0L6C7AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAA9ZJREFUeJzt2D1qFWEYhmETDoREwWCTwkosLW1cgSuwtBZ0F27CJWhhaekyLKzUJgFthAQt8jvWw7GQkOFLbq+rnOLlaW4+mI1pmm4BHZujBwBXS9QQI2qIETXEiBpiVkscfbr9/Fr9Ut/c2ho9Yd1123R2NnrBzMWv36MnrJlOT0ZPmPl48X7jb9+91BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xKyWOLq5s7PE2Uub7u+NnrDm8NHu6Akzu59+jp4ws7l/PnrCmvPTk9ET/omXGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDzGqJoxt3bi9x9tK+Pbs3esKazy/ejJ4w8/j1y9ETZvbefR894cbyUkOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUELMaPeB/9ergyegJM3e/nIyewBXxUkOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUELNa4uh0eLTE2Ut78PbH6Alrvn54OHrCzPbB/ugJM+fHx6Mn3FheaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMasljp4fHS1x9vKu255r6Gz0AK6MlxpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihpiNaZpGbwCukJcaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiPkDAyM3Nq0aV9kAAAAASUVORK5CYII=\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAPUAAAD4CAYAAAA0L6C7AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAA75JREFUeJzt2C2OU2EYhmGGFCYEgSEZEgwkKFAYJB4cW8CzATZA2ACLGJbACnAgCIafZBCgK0YwKQd9UlSZk69z57pkxZtH9O6X9GCapktAx+XRA4DzJWqIETXEiBpiRA0xqyWOPrn9Yq/+Uj+7czR6wpZptV+/p1c+n4yeMPf7bPSCLZv1evSEmXd/3h786/P9+mYB/03UECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIWS1xdLp+bYmzO3v45uPoCVteH30YPWHm6eNnoyfMbL6djJ5wYXmpIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXErBa5enh1kbO7On7/aPSELV8f3Bw9YebL81ujJ8zcffl99IQLy0sNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUPMapGrP34ucnZX91+djp6w5fTwxugJM/d+fRo9YWYzesAF5qWGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFmtcTRzXq9xNnd7dseWJCXGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcQcTNM0egNwjrzUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ8xfwk8uZpcYacUAAAAASUVORK5CYII=\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAPUAAAD4CAYAAAA0L6C7AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAA8hJREFUeJzt2LFtU2EYhlGcWITUIGigIBUTMAINK0DFNAxAwQw01FDSMQQSDSIBJAQRTWJfastUJle/8+icAT69xX38S15M03QD6DgYPQC4WqKGGFFDjKghRtQQs5zj6JPjZ3v1l/rhndujJ2xbLEYv2HD55evoCZvWq9EL9t779Zt/fkReaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYpZzHD04vjXH2Z39evxg9IQtf+7u1+/pvbcXoydsWJ2ejZ5wbe3XlwX8N1FDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BCznOPo+uH9Oc7u7MOr16MnbFlN69ETNjz9+Hz0hE2nZ6MXXFteaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYpZzHD38eT7H2Z2dvHsxesKWo09HoydsOPn2efSEDZejB1xjXmqIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmKWcxydfp/PcXZnj17eHD1h700XF6MncEW81BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYpZzHF19/zHH2d3t2x6YkZcaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooaYxTRNozcAV8hLDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcT8BePyM5XVDyMSAAAAAElFTkSuQmCC\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAPUAAAD4CAYAAAA0L6C7AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAA8xJREFUeJzt2KGKVGEch2FHhnWCsAgbrBbvQLCJyUsQjGLxXrwJMdoN2gxmg9hsCxYNsirjCnPMhzENe/h2X54nTvjzY+Dlg7Oapuka0HF99ADgYokaYkQNMaKGGFFDzHqJo4+On16qT+qrzWb0hD2rG0ejJ8zsvn0fPWFmt92OnnDpvdu9Xv3vdy81xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0x6yWOrjabJc4e7Nf9O6Mn7Dl9/Hf0hJm7L45HT5j7+Hn0givLSw0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIWa9yNXjm4ucPdTXJ39GT9jz5cHL0RNmHr56NnrCzNHoAVeYlxpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihpj1Ild//Fzk7KFuvbk9esKee2+fj54wc/Lh0+gJM7vRA64wLzXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTHrJY5O2+0SZw928v509IQ90+/L9R/tzs9HT+CCeKkhRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSslzi6Oztb4uzBLtseWJKXGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGmNU0TaM3ABfISw0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXE/AOiQTRpF6XfyQAAAABJRU5ErkJggg==\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAPUAAAD4CAYAAAA0L6C7AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAA71JREFUeJzt2DGKU2EYhlGTicLEapagoDuZykIQrN2NixB34BKsXIWCipUwIlYDERyTWF9iIXGuv/NwTpni403x8MNd7Pf7W0DHcvQA4HqJGmJEDTGihhhRQ8xqjqPny6f/1Sf1k7Oz0RMOLO6uR0+Y2F9djZ4wsf36bfSEQ7vt6AUTr3evFr/73UsNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUPMapary5NZzh7r7fMHoycc+PT4xegJE08+nI+eMPH90Xr0hAO7y8vRE/6IlxpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ8xqjqPLO7fnOHu008+z/M2/8vDNs9ETJpbv16MnTNxfvRs94cbyUkOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUELOa4+jux9UcZ4927+XH0RMOrU9HL5jaXIxeMLHdbEZPuLG81BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xKxmubrbznL2WD8vvoyeAP+MlxpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXELPb7/egNwDXyUkOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xvwCLTy8+CemsOgAAAABJRU5ErkJggg==\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAPUAAAD4CAYAAAA0L6C7AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAA9FJREFUeJzt2L1qFVEYhtFz4kkEA9oINjZW2gpegWAtWOUCvDALG7HR2juwsLQXtNMEiT8ETMZ6OBYhZNjxYa1yio+3edgw62maVkDHzugBwOUSNcSIGmJEDTGihpjNEkefbA6u1C/1nb3d0RO2rPdvjJ4wc3r0ffSEubPT0QuuvHdnr9f/+u6lhhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghZrPE0Wu3bi5x9sK+Pn0wesKWP88OR0+Y2Xl7f/SEmdsvP4yesGU6ORk94Vy81BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYjZLHF1f31vi7IX9uLsePWHLx0evRk+YeTgdjJ4ws/Nmf/SELacnJ6MnnIuXGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGmM0SR89+/lri7IXde/Fp9IQtj98/Hz1h5s6336MnzJweHo2e8N/yUkOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUELNZ4ujZ8fESZy/squ1ZrVar3c9fRk+YmUYP4NJ4qSFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUPMepqm0RuAS+SlhhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmL+AhRbNW5yBk8IAAAAAElFTkSuQmCC\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAPUAAAD4CAYAAAA0L6C7AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAA71JREFUeJzt2KGKVGEch2FnGVZEm2gTQVzQ5iWIweItWO3ejd1qd8NGm9Vk0GYTBWUXB3WP+TimYQ6f+/I88YQ/v/LywVlN03QJ6DgYPQDYL1FDjKghRtQQI2qIWS9x9PGVp//VL/WDa1dHT9h28/roBTOrsx+jJ8ycf/4yesKW89PT0RNmTs5frf713UsNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUPMeomj02azxNmdfX/yYPSELTeefxw9Yeb98dHoCTO3X3wbPeHC8lJDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaohZL3J1tVrk7K4+PRq9YNubuyejJ8zcuX9r9AT2xEsNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUPMeomjq8PDJc7u7Ojl2egJWx6+fjZ6wsy9D19HT5iZfv4aPeHC8lJDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BCzXuLotNkscXZ3b9+NXrDl8ugBf/k9egB746WGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMatpmkZvAPbISw0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXE/AFdwi3mpFIf/wAAAABJRU5ErkJggg==\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAPUAAAD4CAYAAAA0L6C7AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAA8FJREFUeJzt2D1qVGEYhuGTzCDptEtnFxS3Idor6Ios3IGLcAfa2caAvaIIWoiVPwOCMMf6MBYSMn7JzXWVp3h5mpsPzsE8zxPQcTh6AHCxRA0xooYYUUOMqCFmvY+j9w4fXapf6qsb10dP2LE9uTl6wsL22mr0hIXVm7ejJ+zYbjajJyy83D4/+Nt3LzXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTHrfRw9PDrax9lz+/rwzugJO06fPBs9YeHVr9ELlp7efzB6wq53H0Yv+CdeaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMeu9XF2t9nL2vObLNWeapml6/P7u6AkLZ69PRk9YuP378+gJV5aXGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGmPXoAf/D8YtPoyfs+HF6PHrCwq2fX0ZPWJi/fR894cryUkOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUELPex9HtZrOPs+d22fZM0zRNH0cPoMpLDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmIO5nkevQG4QF5qiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIeYPDXQwTAtceasAAAAASUVORK5CYII=\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAPUAAAD4CAYAAAA0L6C7AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAA71JREFUeJzt2D1qVGEYhmEnmUgIqJ2NnfFnEdY2lhbuxaW4BisrCxXcg31ALIzYRAIyjWesh7Ea5uQbb66rPMXL09x8cBbr9foW0HE0egCwX6KGGFFDjKghRtQQs5zj6PPjVwf1S/3o7Gz0hC2LA9u0vr4ePWHDtFqNnnDwPkxvF//67qWGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFmOcfR43t35zi7s9/PnoyesOXq/GT0hA0P3n0bPWHD9PWw9vxPvNQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmKWowfchPuvL0ZP2PL54afREza8eP9y9AT2xEsNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUPMco6ji9PTOc7u7MvH89ETtjy683j0hA1P/1yOnsCeeKkhRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaohZznF0uvo1x9mdPXxzMXrCttsnoxdsmH78HD2BPfFSQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIWc5xdFqt5ji7s+n75egJcGO81BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xCzW6/XoDcAeeakhRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGmL9/Ay6J4ZxVMAAAAABJRU5ErkJggg==\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAPUAAAD4CAYAAAA0L6C7AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAA85JREFUeJzt2DFqVGEYhlEjozZB7NMEFdyDlaVi4wbsbASzEhehrVimdAkKomhhY2ehQkhSTZNc68tYDbn8ycM55RQfbzEPP9ydaZquAR3XRw8ALpaoIUbUECNqiBE1xKyWOPpk7+BSfVKfbu+OnrDp+HT0gpnp5HLtOV+vR0+49D6cv9/53+9eaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYlZLHD16tL/E2a3tvvg1esKGP4f3R0+Y2Xv7ffSEufV69IIry0sNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFmtcTR3w+nJc5u7c6z49ETNnz5cTh6wszTd49HT5g7Phm94MryUkOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUELNa4uj+4dkSZ7f26vPH0RM2PHjzcvSEmbunX0dP4IJ4qSFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiFktcfTm0XqJs1t7ffB89IQN937+HT1h7sYifwUG8FJDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaohZLXF0+vRtibNbuzV6wH+cjR5AlpcaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooaYnWmaRm8ALpCXGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaoj5B69YNYmBemy4AAAAAElFTkSuQmCC\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAPUAAAD4CAYAAAA0L6C7AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAA8VJREFUeJzt2D1qVGEYhmHHTCUS04ighVrqOizch1buwCVYC27CBViIe7C2F4TY+JNIwmSO9WGshhy+8ea6yileHgZuPjiraZpuAB03Rw8ArpeoIUbUECNqiBE1xKyXOPr85MVBfVJf3TkePWHHdH4+esLM9sfP0RNmps1m9ISD93H7fvWv373UECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXErBe5+uDeImf39fXZ3dETdtz/9H30hLnfZ6MXzG02oxf8t7zUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpi1ksc/fPwZImze/v8+t3oCTueHr8aPWHm0dtvoyfMXF1cjJ7w3/JSQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQs17i6K0vp0uc3dvjDy9HT9hx+3L0grnp8sAGsTcvNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMesljk6/zpY4u7cnb45GT9i13Y5eMDMdHeB/xF681BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYtZLHL06PV3i7P4ObQ8syEsNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUPMapqm0RuAa+SlhhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmL+Ag0ZNoQqADd8AAAAAElFTkSuQmCC\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAPUAAAD4CAYAAAA0L6C7AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAA8RJREFUeJzt2LGOTGEch2EzGStWIQhRiFJ0bkIhLsAliLtwIe6ARq/TUopJ1BKJhMgikV3rqCejmszJt948T3mKf37Nmy85i2mazgEdy9EDgP0SNcSIGmJEDTGihpjVHEcf3Hhypn6p/75za/SEM2/5Zj16wobp5Hj0hDPv1Z8Xi39991JDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BCzmuPodPP6HGd39vL5s9ETthwuD0ZP2PDw/qPREzacvv8wesJ/y0sNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFmNcfR5bfvc5zd2b3Xj0dP2HL65cLoCRvuflyPnsCeeKkhRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaohZzXF0unRxjrM7u3L55+gJW36sD0dP2HRwfvQC9sRLDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDzGqWq58+z3J2V1ef3h49Ycu1X19HT9h0fDJ6AXvipYYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUELOa4+jp0dEcZ3f39t3oBVum0QPI8lJDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BCzmKZp9AZgj7zUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ8xfJqYvv8PtX+kAAAAASUVORK5CYII=\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAPUAAAD4CAYAAAA0L6C7AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAA/RJREFUeJzt2DGKFGkch+Fu7QmU1UBUjJQ9gAfwAF7B0MBAwQt5CGMjL+HCYqAsuywTiCAjkzgtdJdx0QYyTPnpy/OEFfz5JS8f1HqaphXQcWn0AOBiiRpiRA0xooYYUUPMZomjDy8/+qV+qV++dm30hAPrq1dGT5iZzs5GT5jZf/m19qxWq9W03Y6eMPN6/3L9ve9eaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYjZLHF1vjpY4e353bo1ecOD9k9ujJ8zce3U2esLM0d//jZ5wYLfdjp7wQ7zUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiNqMH/Ayn92+OnnDg3eMXoyfM3P/0fPSEmbvH10dPOHRyMnrBD/FSQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQs1ni6LTbLXH23K58/Dp6woFnxw9GT5j543g/esLc2Xb0gt+WlxpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihpjNIlen/SJnz+vor39GTzjw/9M/R0+YufHh39ETZnYnn0dP+G15qSFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xGwWuTpNi5w9r93p6egJh968Hb1gZj96ABfGSw0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ8x6mqbRG4AL5KWGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYr4BVeNAAZSwwgYAAAAASUVORK5CYII=\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAPUAAAD4CAYAAAA0L6C7AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAA8hJREFUeJzt2D1qFWEYhmGjB4IWERREETdgZ5/aBVjHytL9uAlXIO7AUsTGP4xIwJQimoSTsR6OhYQMX3JzXeUUL09z88FsTdN0Bei4OnoAcL5EDTGihhhRQ4yoIWa1xNHH1/cu1C/1a3fvjJ6w4eeje6MnzNz49mv0hLl3H0cv2DAdHY2eMPP69OXWv757qSFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiFktcfTq9vYSZ8/sy96D0RM2vH/+YvSEmWf7u6MnzBw8vT96wob1h8+jJ/wXLzXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihpjVEken9XqJs2e28/V09IQNu2+fjJ4w833/9ugJMw//HIyecGl5qSFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiFktcXQ6Plni7JndevVp9IRNb3ZGL5i5+ftg9ISZ9Y/D0RMuLS81xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xqyWOTifHS5w9s/Xh4egJmy7iJhK81BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFma5qm0RuAc+SlhhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmL+AimdOMFSSmsTAAAAAElFTkSuQmCC\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAPUAAAD4CAYAAAA0L6C7AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAA/1JREFUeJzt2DFrXXUcx+GmvVksxBidhWLW4itwdBFfQJxd7NKxb0poRwffQPdCO8UgSBEEUZOQWHrv7Xw4DuGSwz9+eJ7xDD++y4c/nL3tdnsP6Lg/egBwu0QNMaKGGFFDjKghZrXE0a9XJ3fql/qDT49GT5j59/HnoydM7J+/Gz1hYu/1L6MnzGwuL0dPmPh58+Pef333UkOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUELNa5OpmvcjZXf3x7fHoCTM/PHsxesLEy3++GD1h4u3JZ6MnzGzOLkdPuBEvNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGmNUSRx8cHCxxdmcX31yMnjDz/ce/j54w8dVHp6MnTDx59HT0hJnV2a+jJ9yIlxpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihpjVEkc3V9dLnN3Z4fOHoyfMfLn/3egJE9evDkdPmDg+/W30hJn3owfckJcaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooaY1RJHt+v1Emd39slPb0ZPmDl6eTh6wtTVn6MXTGzOL0ZP+N/yUkOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiFktcnWzXuTsrtZ//T16wtxd3ESClxpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihpi97XY7egNwi7zUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ8wHM75AaUOPz7EAAAAASUVORK5CYII=\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAPUAAAD4CAYAAAA0L6C7AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAA91JREFUeJzt2DtqVGEch2EnGYgWIlip4AUre9egthZa2dm6HzeRJWQXEhRUvCCIlZWEmNuxPoyFxBk+fXme8hR/fs3LB2cxTdMFoGNr9ABgvUQNMaKGGFFDjKghZrmJow+2nv5Tv9SX16+NnrDix/1boyfMXPp2MHrCzGL//egJK84OD0dPmNk721387ruXGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGmOUmjm5dvLiJs+f28fnd0RNWvH7xcvSEmcfvHo2eMHP05PLoCasOD0cv+CNeaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMctNHJ1OzzZx9tyOr0yjJ6x4c3QwesLMq/07oyfM3Dt5O3rCf8tLDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDzGKaprUffbjzbP1H/8L2zRujJ6z4efvq6AkzO5+/j54wc/rl6+gJK6bjo9ETZvbOdhe/++6lhhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghZrmJo9Px0SbOntvJh0+jJ6zY/sc2nYwewNp4qSFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUPMYpqm0RuANfJSQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTG/AKCLP+/TEaq6AAAAAElFTkSuQmCC\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAPUAAAD4CAYAAAA0L6C7AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAABAdJREFUeJzt2LGL13Ucx/F+x8+GTryg8Shw8B8QbbIxkMam9v6EdpcWVzedHR0dXZ2VQsQho6WCqChQrwPvfs5fvg7Hj/v2uXvyeIzf4c1refKB72qz2XwAdOyMHgCcLlFDjKghRtQQI2qIWS9x9Mv1N2fql/rO7kejJ8yctU2bNwejJ0wcvXo9esLc8dHoBROPjh+s3vfdSw0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ8x6iaOrC4uc3d7l/dELZv69sjd6wsTFn1+NnjCxev7T6Akzm8Oj0RNOxEsNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFmvcTRnY/3lji7td+/H71g7un1e6MnTNz48evREyb2vv1k9ISZt7/+NnrCiXipIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIWY8e8H/4Yv/l6AkzNz+7NnrCxK0XD0dPmLjz4VejJ5xbXmqIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmLWSxw9/vufJc5u7cntq6MnzPxx/7/REya+u/v56AkTn/71bPSEc8tLDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghZr3I1Z3VIme3tff4l9ETZi79sDt6wsTq4M/REyaODg9HTzi3vNQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSsNpvN6A3AKfJSQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTHvAMqWOe4STpmsAAAAAElFTkSuQmCC\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAPUAAAD4CAYAAAA0L6C7AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAABAFJREFUeJzt2LFrnHUcx3GTu0AJhjhUqYNIwMXBqaurY5cOduj/0TF0de5cwVmdHCP6D3QsFFwcbbbADUa45JwfzkGOPPxyb16v8YYvHw7e/OA52Gw2HwAdh6MHAHdL1BAjaogRNcSIGmKWcxz9ZvHtvfqkvvjibPSELeuPT0ZPmDj683L0hIn1X+9HT7j3Lm5/PPiv373UECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXELOc4enh8PMfZnf3x8nT0hC0XX78aPWHi6XcvRk+YePT91egJW26vr0dP+F+81BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYpZzHD385OEcZ3d2/viX0RO2nB19OHrCxIMnl6MnTP2wGL1gb3mpIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIWc5y9fqfWc7u6verL0dP2PLs5LfREyZWfz8YPWHio5ub0RP2lpcaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooaY5RxHN+ubOc7u7M1PX42esOX8+Wr0hImjX09HT5haLEYv2FteaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMcs5jm5WqznO7uyz1+9GT9jy9ufPR0+Y+PTqfv1Ht+v16Al7y0sNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUPMwWazGb0BuENeaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCHmX+qLOZmn6i25AAAAAElFTkSuQmCC\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAPUAAAD4CAYAAAA0L6C7AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAABBlJREFUeJzt2D+rlnUcx3HP3R0HT4ODS4iKNYSzg1uNPQchGsTVubEHUIu0NrQ3BOEg+CDEpqKcBA1BoT8Ypzzncr64Gg43Xvz07es13sOXz3C/+cG1N03TKaBjM3oA8GqJGmJEDTGihhhRQ8x2jaOfnv7stfqkvrlwbvSEheMzB6MnzGz+eD56wszxw0ejJyxMh4ejJ8zcPf5+7/9+91JDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BCzXePoZn9/jbM7++3G+6MnLFz5+JfRE2Z+unN59ISZS7eejp6wcHR4OHrCiXipIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEbNc4On14fo2zO7t97evRExZufvDJ6Akz3z24NXrCzJc/fj56wtL9P0cvOBEvNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMds1ju798+8aZ3f2639nR09Y2Lx3MHrCzNX9d0dPmDneX+Wv+VbwUkOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUELNd5erjJ6uc3dUX314fPWHh3s/fjJ4w89Wzj0ZPmHnn2d+jJywcjR5wQl5qiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0x2zWOTi9erHF2Zxd/eDJ6wsKVo5ujJ8wc/D6NnjBz9q8Hoye8sbzUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXE7E3TNHoD8Ap5qSFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooaYl0upQEIS4h/yAAAAAElFTkSuQmCC\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAPUAAAD4CAYAAAA0L6C7AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAA+VJREFUeJzt2D1qFWEYhmFPPOJPglroAgQr7VIEXIC1rRuwsHEF7sM96BLcgGBjpZXYSxS0SiLJWA/HQg4ZvuTmusopXp7m5oNZTdN0BejYGT0AOF+ihhhRQ4yoIUbUELNe4ujT9fML9Uv96u290RM2rHZ3R0+YOf1+OHrCzPTnZPSEC+/92bvVv757qSFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiFkvcXR1bZGzW/v26vHoCRv2Dg5HT5i59/ru6Akz06fPoydcWl5qiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0x6yWO7ty8scTZre0dHI6esOHj/tvRE2b2n7wcPWHm/qfRCy4vLzXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTHrJY5Op2dLnN3a7ps7oydsePDsxegJMw8/H42eMLO6fn30hA3T8fHoCf/FSw0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ8x6iaPT0fESZ7d268PX0RM2PPpye/SEmenX79ETZs7OptETLi0vNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGmPUSR6c/J0uc3drpj5+jJ2y6iJtI8FJDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BCzmqZp9AbgHHmpIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihpi/ghc5L1BWVhIAAAAASUVORK5CYII=\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAPUAAAD4CAYAAAA0L6C7AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAA9pJREFUeJzt2LGOTGEch2FHRiKh00g0QiQ6oRCVlntQuAYX4AZcg0qrVCp0bkEiKO0mRGUJa/eoT0Y12ZNvvXmecop/fsnMmy+ZaZ7nM0DH2dEDgJMlaogRNcSIGmJEDTGbNY4+uPj4VP2lPl25PHrClun7j9ETFo6+fhs9YWE+/D16wqn3+vjl9K/PvdQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcRs1jh6ePfmGmd3dv3Zu9ETtrz5dGP0hIUbT0YvWPqztz96wn/LSw0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIWazxtH9e+fXOLuzc/fn0RO2vP/0YvSEhYeXH42esLS3P3rBf8tLDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDzGaNoxc+z2ucTfk1H46esDAdHo2esOAXtDsvNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMZs1jl56u7/G2Z19fHp79IQtt57fGT1h4dqXD6MncEK81BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYjZrHJ0Ofq5xdmdXXx2MnrBl+nM8esLC/ON0fWfszksNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUPMNM/z6A3ACfJSQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTF/AX8OOewwYPNOAAAAAElFTkSuQmCC\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAPUAAAD4CAYAAAA0L6C7AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAA+1JREFUeJzt2L2OjGEch2GzO0S1gkItxFFodSoJcQZqlTNxAkqH4CB8RCORkA0FlY/4SNh91W9exWYZz7hzXeUU//wyyT1PMqtpmk4AHTujBwB/l6ghRtQQI2qIETXErDdx9Nrura36S321uzt6wsLOmb3RE+Z2tus7mj5/Hj1h4fD799ETZh4dPlz97nMvNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMevRA/6FnfPnRk9YeHv78ugJMz/2Ri+Yu/jgzegJC4ev90dPOBIvNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGmPVGrk7TRs4e1/vrl0ZPWHh67/7oCTPvD76MnjBz8/Hd0RMWTr/eHz3hSLzUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXErDdydbXayNnjOvvi2+gJC1ef3Rg9Yebd0wujJ8xcebI/esLCz9EDjshLDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDzHojV1fb9Vtx8vmr0RMWTt3ZGz1hZu/ry9ETZg4+fRo94b+1XfUBf0zUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXErDdy9fBgI2eP6+DDx9ETlrZxEwleaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYlbTNI3eAPxFXmqIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKgh5hdJrjn3aK68hQAAAABJRU5ErkJggg==\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAPUAAAD4CAYAAAA0L6C7AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAABBJJREFUeJzt2LGKXGUch2FnnTibKIFFSGtjZR9yA8Eidbr0XoEXY2FhZSNegSB2goVFICRdigQLq5ikcHV2TurDUViGHL7dl+cpp/jz48DLB7OZpukDoONk9ADg/RI1xIgaYkQNMaKGmO0aR7/cPbpSf6mffPLx6AkLm91HoyfMTPv96Akzh1d/jZ6wcNW+0U+HHzb/9buXGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGmO0aR6f9v2ucPdr+i89GT1h4cf/W6Akzd37fj54wc+vnJ6MnLEz7q/WN/o+XGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDzHaNoye73Rpnj/by639GT1h4eu+70RNmfnx7e/SEmW8fPhg9Yenxs9ELLsVLDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDzHaNo5vT3Rpnj3bjw4vRExYupsPoCTN3T/8YPWHmm9unoycsXJcX8LrsBC5J1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiNmucXT6+3yNs0c7/f5s9ISFz//8avSEmU9/vTF6wsydJ89GT1i4GD3gkrzUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpitmscPZyfr3H2aGe/PB89YeHst5ujJ8xMr9+MnjBzeHO19lwnXmqIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmI20zSN3gC8R15qiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIeYdY2JDaF9OZsQAAAAASUVORK5CYII=\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAPUAAAD4CAYAAAA0L6C7AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAA+lJREFUeJzt2TGOTWEch2F35hIakolI1IJGO5VSLEFhA2I5orICjSXoFUJiD8IkCiQKMnLnqE+OQiaOb7x5nvIW//yaN19yz2aapnNAx97oAcDfJWqIETXEiBpiRA0x2zWO3t97cKb+Ut+/fHn0hIXN1YPRE2Z2H45GT5iZjo9HT1g6Y1+KXp682Pzudy81xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0x2zWObs5fWOPsqb1/dGf0hIV7D1+PnjDz6unh6AkzB8/fjp6wMP08Hj3hj3ipIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEbNc4unfp4hpnT+3HtWn0hIUn19+MnjBz++bh6AkzB6MH/Me81BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xGzXOLr79m2Ns6d269nR6AkLd988Hj1h5sa7T6MnzOx2u9ET/lteaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYrajB/wLu/cfR09YuPL5y+gJMyfff4yeMLPZ3x89YWE62Y2e8Ee81BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYrarXJ2mVc6e1vTzePSEhd3Xs7eJBi81xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xm2maRm8A/iIvNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BDzCz6KPk4JUCCpAAAAAElFTkSuQmCC\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAPUAAAD4CAYAAAA0L6C7AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAA/dJREFUeJzt2LGKVGcch+GdcRRNmkXBLl26XIKdkEJsbLwK8XL0JrTQMuQKhLQJYpGQWEkUXFBX0JljfTgWy+L47b48TznFx28YXv4wq2maDoCO9egBwLclaogRNcSIGmJEDTGbfTz66/rumfpLfXXx0ugJC+urh6MnzB1/HL1gZvvu/egJS7vt6AUzv+8erb72uUsNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUPMZvSA72H1y8+jJyz8e+tw9ISZK/9PoyfMXH/81+gJC9u3R6MnnIhLDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghZrOXV9cX9vLsaT2/9+PoCQv/3H44esLM0e549ISZOy/vj56wcOm3P0ZPOBGXGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGmM3oAd/DtWdn72s+uPHT6AkzR59/GD1h5vKrD6MnLOxGDzghlxpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihpjNXl6ddnt59rSuP3kxesLC0z9vjp4ws/60HT1hZv33f6MnnFsuNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGmM1eXp2mvTx7WtvXb0ZPWFidsU1n6xc7ONiOHnCOudQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSspmkavQH4hlxqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIeYLUEY8gMmWSP8AAAAASUVORK5CYII=\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAPUAAAD4CAYAAAA0L6C7AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAA/ZJREFUeJzt2DFuXGUYhlGPc/FELpw9IFGwAXZAsoJU1KTIYlKkyxqooUFCQqJDSEhR6jRZAKQIxGP7ph5dkMzYV//w6JzSxadXM3rml7yZ5/kE6DgdPQC4X6KGGFFDjKghRtQQM61x9OvTp0f1L/XNdjt6wtLNUX1EJ/PucvQE/qMfb77b/NPfvdQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcRMaxx9cHGxxtmDvX/85egJC2fvr0dP2HP28+vRE/bMu6vRE5Zujus7+zdeaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMdMaR//+6os1zh7sl5evRk9Y+DjvRk/Y8+Tb56Mn7Nn+8OvoCf9bXmqIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmKmVY7+db3G2YN9/+Hh6AkLn08fRk/Yc3V+XL/v281m9ISleR694FaO65sE7kzUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qImVY5+ubtGmcP9uLZN6MnLFydPxg9Yc+j39+NnrDnevps9ISFeXc5esKteKkhRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcRMaxy9/uPPNc4ebPrpt9ETFlb54O/gavQA7o2XGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGmM08z6M3APfISw0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEfAJxZDrYSGDmAAAAAABJRU5ErkJggg==\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAPUAAAD4CAYAAAA0L6C7AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAA/NJREFUeJzt2LGKVGcch+HZ3SkMrFoEtNtrsAhBiJXoLQi5A+8gXZpcQ8BGbyApQyAkEFtvwMYrkEAshF3UeE7qw1gs4558k5fnKbf482OZdz6Yo3meN0DH8egBwNUSNcSIGmJEDTGihpjtGkcfnjw6qJ/Ut7dvjZ6w64troxcsTK//Gj1hYTo/Hz3h4P0+/XT0qb97qSFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiNmucfT49HSNs3t7+cPZ6Ak7vv3qxegJC78+uzd6wsLtHw/r/7PZbDab6ePoBZfipYYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUELNd4+jxzRtrnN3b47vPR0/Y8d2Xr0ZPWPj5mzujJywcPTkZPWHHPH0cPeFSvNQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcRs1zg6/f1mjbN7++X7+6Mn7Hj69YPRExbOfns3egJXxEsNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUPMdo2j08XFGmf3dvrHy9ETdlz/87C+T+f3H0ZPWJj+Oaw9/yeH9ckCPpuoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qI2a5ydZ5XObuv6e3b0RPgP+OlhhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKgh5mie59EbgCvkpYYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpi/gWimDjGN6I/ugAAAABJRU5ErkJggg==\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAPUAAAD4CAYAAAA0L6C7AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAABAVJREFUeJzt2M2qjWEch2Fr7yXlYw+QwY5SSsZmUmYGDsBAzsDAYZg4BWcgOQDFhANwBgx85CMp5WNjGb+9Brud5eHuuobv4N9vcvfUu1itVvuAjo3RA4A/S9QQI2qIETXEiBpilus4ennj6j/1S33z2NHRE2YWW0dGT5j6tjN6wcSPN+9GT5hZ7XwbPWHiwc+7i99991JDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BCzHD3gb1gcOTx6wszbS9ujJ0xsPf86esLE8s270RP+W15qiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xy7Vc3dhcy9m9enbt5OgJM49u3B49YeLOh/OjJ0w8uXJm9ISZ7y9ejp6wK15qiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpilus4unHo4DrO7tmBC+9HT5g5sXlo9ISJm0efjp4w8fDsxdETZjZfvBw9YVe81BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xCzXcXT15es6zu7ZzuNjoyfM3Du3NXrCxPsf26MnTOz/8GX0hJmfowfskpcaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUPMcvSAv+HU/dejJ8zc+nh99ISJz8cXoydMnP70avSE/5aXGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGmMVqtRq9AfiDvNQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDzC8pATidXPUl+QAAAABJRU5ErkJggg==\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAPUAAAD4CAYAAAA0L6C7AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAA9pJREFUeJzt2cHKjGEch2HzzUSUwlLkLGzFwlE4AWVr4XRslZ2FnICNslE2kqz07VhgMfNavw2l4fWMu+tazuLfr5nunvq+1TRNZ4COk9EDgL9L1BAjaogRNcSIGmI2Sxy9e/7eUf1J/eTGtdET9mwvXRg9YWb99sPoCTPbL19GT9h3ZP8perF7svrZ515qiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiNkscPbl+dYmzB7v99PXoCXseXnk3esLMzUf3R0+Yufz45egJ/y0vNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGmM0iV9frRc6WvPy2HT1h5tzn3egJc6sjfG+m4/rNfuUIvzngT4gaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xm0Wufjpd5Oyhnj+4NXrCnmcX7oyeMHPx1fvRE2Z26/XoCXum3Xb0hN/ipYYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIWazxNHd129LnD3Y2TcfR0/Yc/ZkNXrC3JH9ZhzOSw0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIWazxNHp+/clzh5se3o6egL8M15qiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiVtM0jd4A/EVeaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCHmB5e8NvThaQtjAAAAAElFTkSuQmCC\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAPUAAAD4CAYAAAA0L6C7AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAA+5JREFUeJzt2KGKVWsch+G9Z3bScLCooCC2c9CkzWTxFsQLMYp3YPUmRLwAkycZxGCymgzCIKKGGfYs82IbZOPim3l5nrjCn195+WCtp2laAR0HowcAf5eoIUbUECNqiBE1xGyWOPpg8+hM/VI/uHhh9IRdN66NXjCz/nI0esLM6dHX0RN2TCfHoyfMvD59sf7ddy81xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xm0Wunm4XObuvn/f/Gz1hx62nH0ZPmPn/5Z3RE2auP3s3esK55aWGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BCzWeTqweEiZ/f1+d7Z2rNarVZvrr0dPWHmyaMfoyfMvH9+afSEHduT49ET/oiXGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGmM0iV0+3i5zd181X30dP2HH39sPRE2aOPv8zesLMv9PH0RPOLS81xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xm0WurteLnN3X4cdPoyfsuPL48ugJM1dPvoyeMLM9Ph494dzyUkOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiNkscnWaFjm7r+23b6Mn7DqLm0jwUkOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUELOepmn0BuAv8lJDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMb8AVtk7Rfu4C/MAAAAASUVORK5CYII=\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAPUAAAD4CAYAAAA0L6C7AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAA8NJREFUeJzt2SFuFGEch2G2TBF4EkgwICq5BTcAwwEQ3IA7oLkErhIOgEUWBSFAgoAgSA3bDnozCLLZyVfePI9c8c/PvPmSnc08z9eAjqPRA4DDEjXEiBpiRA0xooaYaY2jD48eX6m/1Kc7t0dPWDh/cHf0hB03z76NnrBj++nz6AlLV+xL0ZvLV5u//e6lhhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghZlrl6mazytl9fXl0f/SEhXfPX46esOPe6dPRE3acPPs6esLSfDF6wT/xUkOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiJnWOLq5cWONs3s7/jWPnrDw+vx49IQd08/roydwIF5qiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpipjWOzr+3a5zd263T96MnLLw4ezJ6wo6Tjx9GT9ixnS9HT/hveakhRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaoiZVrl6ebHK2X1dfP8xesLC5u3V2rQdPYCD8VJDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGmM08z6M3AAfkpYYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpi/gAA0TNCJbjRYgAAAABJRU5ErkJggg==\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAPUAAAD4CAYAAAA0L6C7AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAABABJREFUeJzt2bGKVGcch2FnM7BrSBMhaBOxtZA0goKNjdcQL8NG8ArSeSVeghdgIUlhJYtoI6TIohYuy67sHuvhpJDF4zf78jzlFH9+DLx8MLOapukS0LEzegDwfYkaYkQNMaKGGFFDzHqJow/WD7fqJ/Wdvd3RE2ZWu9u1aTo+Hj1hw9nR0egJc1v2T9Hzs2er//vcSw0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ8x6iaM7e7tLnD23k7s3R0+YOfhju76jay8+j56wYfX369ETZqYvJ6MnfBMvNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGmPUSR3eu/LrE2XO78/Tl6Akzf119NXrChkf/3h49YcP+n7+PnjBz+ubd6AnfxEsNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUPMevSAH+HN4W+jJ8wcnB6OnrDh1s/vR0/YsP/TjdETLiwvNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMesljp7+d7DE2XP7+OTm6Akz9+89Hj1hwy/vz0ZP2HDl09vREy4sLzXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihpj1Ekenk5Mlzp7b+p/90RNmrr++PHrCVjv98Gn0hAvLSw0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xIgaYkQNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ8xqmqbRG4DvyEsNMaKGGFFDjKghRtQQI2qIETXEiBpiRA0xooYYUUOMqCFG1BAjaogRNcSIGmJEDTGihhhRQ4yoIUbUECNqiBE1xHwFOXw+G2qP3g0AAAAASUVORK5CYII=\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"for y in df.Input.unique():\n",
" for x in df.userID.unique():\n",
" img = df[(df.userID == x) & (df.Input == y)].iloc[100].Blobs[1:7, 1:7]\n",
" plt.axis('off')\n",
" plt.imshow(img)\n",
" plt.savefig(\"./out/blob_%s_%i.pdf\" % (y,x) , bbox_inches='tight', transparent=False, pad_inches=0)\n",
" plt.show()"
]
}
],
"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
}

View File

@ -0,0 +1,366 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## This notebook creates one dataframe from all participants data\n",
"## It also removes 1% of the data as this is corrupted"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"%matplotlib inline\n",
"\n",
"from scipy.odr import *\n",
"from scipy.stats import *\n",
"import numpy as np\n",
"import pandas as pd\n",
"import os\n",
"import time\n",
"import matplotlib.pyplot as plt\n",
"import ast\n",
"from multiprocessing import Pool, cpu_count\n",
"\n",
"import scipy\n",
"\n",
"from IPython import display\n",
"from matplotlib.patches import Rectangle\n",
"\n",
"from sklearn.metrics import mean_squared_error\n",
"import json\n",
"\n",
"import scipy.stats as st\n",
"from sklearn.metrics import r2_score\n",
"\n",
"\n",
"from matplotlib import cm\n",
"from mpl_toolkits.mplot3d import axes3d\n",
"import matplotlib.pyplot as plt\n",
"\n",
"import copy\n",
"\n",
"from sklearn.model_selection import LeaveOneOut, LeavePOut\n",
"\n",
"from multiprocessing import Pool"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"def cast_to_int(row):\n",
" try:\n",
" return np.array([a if float(a) >= 0 else 0 for a in row[2:-1]], dtype=np.uint8)\n",
" except Exception as e:\n",
" return None\n",
" \n",
"def load_csv(file):\n",
" temp_df = pd.read_csv(file, delimiter=\";\")\n",
" temp_df.Image = temp_df.Image.str.split(',')\n",
" temp_df.Image = temp_df.Image.apply(cast_to_int)\n",
" return temp_df"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"['DataStudyEvaluation/2_studyData.csv', 'DataStudyEvaluation/12_studyData.csv', 'DataStudyEvaluation/5_studyData.csv', 'DataStudyEvaluation/1_studyData.csv', 'DataStudyEvaluation/10_studyData.csv', 'DataStudyEvaluation/6_studyData.csv', 'DataStudyEvaluation/3_studyData.csv', 'DataStudyEvaluation/7_studyData.csv', 'DataStudyEvaluation/8_studyData.csv', 'DataStudyEvaluation/9_studyData.csv', 'DataStudyEvaluation/11_studyData.csv', 'DataStudyEvaluation/4_studyData.csv']\n",
"CPU times: user 1.35 s, sys: 786 ms, total: 2.14 s\n",
"Wall time: 1min 43s\n"
]
}
],
"source": [
"%%time\n",
"pool = Pool(cpu_count() - 2)\n",
"data_files = [\"DataStudyEvaluation/%s\" % file for file in os.listdir(\"DataStudyEvaluation\") if file.endswith(\".csv\") and \"studyData\" in file]\n",
"print(data_files)\n",
"df_lst = pool.map(load_csv, data_files)\n",
"dfAll = pd.concat(df_lst)\n",
"pool.close()"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"608084"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df = dfAll[dfAll.Image.notnull()]\n",
"df = df[df.userID != \"userID\"]\n",
"df.userID = pd.to_numeric(df.userID)\n",
"len(df)"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"loaded 610816 values\n",
"removed 2732 values (thats 0.447%)\n",
"new df has size 608084\n"
]
}
],
"source": [
"print(\"loaded %s values\" % len(dfAll))\n",
"print(\"removed %s values (thats %s%%)\" % (len(dfAll) - len(df), round((len(dfAll) - len(df)) / len(dfAll) * 100, 3)))\n",
"print(\"new df has size %s\" % len(df))"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"df = df.reset_index(drop=True)"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>userID</th>\n",
" <th>Timestamp</th>\n",
" <th>Current_Task</th>\n",
" <th>Task_amount</th>\n",
" <th>TaskID</th>\n",
" <th>VersionID</th>\n",
" <th>RepetitionID</th>\n",
" <th>Actual_Data</th>\n",
" <th>Is_Pause</th>\n",
" <th>Image</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>2</td>\n",
" <td>1553593631562</td>\n",
" <td>0</td>\n",
" <td>34</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>false</td>\n",
" <td>false</td>\n",
" <td>[3, 3, 3, 2, 0, 0, 1, 0, 0, 0, 1, 2, 1, 0, 0, ...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>2</td>\n",
" <td>1553593631595</td>\n",
" <td>0</td>\n",
" <td>34</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>false</td>\n",
" <td>false</td>\n",
" <td>[3, 3, 3, 2, 0, 0, 1, 0, 0, 0, 1, 222, 0, 0, 0...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>2</td>\n",
" <td>1553593631634</td>\n",
" <td>0</td>\n",
" <td>34</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>false</td>\n",
" <td>false</td>\n",
" <td>[3, 3, 3, 2, 0, 0, 1, 0, 0, 0, 1, 222, 0, 0, 0...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>2</td>\n",
" <td>1553593631676</td>\n",
" <td>0</td>\n",
" <td>34</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>false</td>\n",
" <td>false</td>\n",
" <td>[3, 3, 3, 2, 0, 0, 1, 0, 0, 0, 1, 222, 0, 0, 0...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>2</td>\n",
" <td>1553593631716</td>\n",
" <td>0</td>\n",
" <td>34</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>false</td>\n",
" <td>false</td>\n",
" <td>[3, 3, 3, 2, 0, 0, 1, 0, 0, 0, 1, 222, 0, 0, 0...</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" userID Timestamp Current_Task Task_amount TaskID VersionID \\\n",
"0 2 1553593631562 0 34 0 0 \n",
"1 2 1553593631595 0 34 0 0 \n",
"2 2 1553593631634 0 34 0 0 \n",
"3 2 1553593631676 0 34 0 0 \n",
"4 2 1553593631716 0 34 0 0 \n",
"\n",
" RepetitionID Actual_Data Is_Pause \\\n",
"0 0 false false \n",
"1 0 false false \n",
"2 0 false false \n",
"3 0 false false \n",
"4 0 false false \n",
"\n",
" Image \n",
"0 [3, 3, 3, 2, 0, 0, 1, 0, 0, 0, 1, 2, 1, 0, 0, ... \n",
"1 [3, 3, 3, 2, 0, 0, 1, 0, 0, 0, 1, 222, 0, 0, 0... \n",
"2 [3, 3, 3, 2, 0, 0, 1, 0, 0, 0, 1, 222, 0, 0, 0... \n",
"3 [3, 3, 3, 2, 0, 0, 1, 0, 0, 0, 1, 222, 0, 0, 0... \n",
"4 [3, 3, 3, 2, 0, 0, 1, 0, 0, 0, 1, 222, 0, 0, 0... "
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df.head()"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([ 2, 12, 5, 1, 10, 6, 3, 7, 8, 9, 11, 4])"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df.userID.unique()"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [],
"source": [
"df.userID = pd.to_numeric(df.userID)\n",
"df.TaskID = pd.to_numeric(df.TaskID)\n",
"df.VersionID = pd.to_numeric(df.VersionID)\n",
"df.Timestamp = pd.to_numeric(df.Timestamp)\n",
"df.Current_Task = pd.to_numeric(df.Current_Task)\n",
"df.Task_amount = pd.to_numeric(df.Task_amount)\n",
"df.RepetitionID = pd.to_numeric(df.RepetitionID)\n",
"df.loc[df.Actual_Data == \"false\", \"Actual_Data\"] = False\n",
"df.loc[df.Actual_Data == \"true\", \"Actual_Data\"] = True\n",
"df.loc[df.Is_Pause == \"false\", \"Is_Pause\"] = False\n",
"df.loc[df.Is_Pause == \"true\", \"Is_Pause\"] = True"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [],
"source": [
"df.to_pickle(\"DataStudyEvaluation/AllData.pkl\")"
]
},
{
"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
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,283 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Filtering the data for the LSTM: removes all the rows, where we used the revert button, when the participant performed a wrong gesture\n"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"%matplotlib inline\n",
"\n",
"import numpy as np\n",
"import pandas as pd\n",
"from multiprocessing import Pool, cpu_count"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>userID</th>\n",
" <th>Timestamp</th>\n",
" <th>Current_Task</th>\n",
" <th>Task_amount</th>\n",
" <th>TaskID</th>\n",
" <th>VersionID</th>\n",
" <th>RepetitionID</th>\n",
" <th>Actual_Data</th>\n",
" <th>Is_Pause</th>\n",
" <th>Image</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>8351</th>\n",
" <td>2</td>\n",
" <td>1553594010364</td>\n",
" <td>1</td>\n",
" <td>510</td>\n",
" <td>28</td>\n",
" <td>2</td>\n",
" <td>0</td>\n",
" <td>True</td>\n",
" <td>False</td>\n",
" <td>[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, ...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>8352</th>\n",
" <td>2</td>\n",
" <td>1553594010414</td>\n",
" <td>1</td>\n",
" <td>510</td>\n",
" <td>28</td>\n",
" <td>2</td>\n",
" <td>0</td>\n",
" <td>True</td>\n",
" <td>False</td>\n",
" <td>[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, ...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>8353</th>\n",
" <td>2</td>\n",
" <td>1553594010445</td>\n",
" <td>1</td>\n",
" <td>510</td>\n",
" <td>28</td>\n",
" <td>2</td>\n",
" <td>0</td>\n",
" <td>True</td>\n",
" <td>False</td>\n",
" <td>[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, ...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>8354</th>\n",
" <td>2</td>\n",
" <td>1553594010485</td>\n",
" <td>1</td>\n",
" <td>510</td>\n",
" <td>28</td>\n",
" <td>2</td>\n",
" <td>0</td>\n",
" <td>True</td>\n",
" <td>False</td>\n",
" <td>[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, ...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>8355</th>\n",
" <td>2</td>\n",
" <td>1553594010525</td>\n",
" <td>1</td>\n",
" <td>510</td>\n",
" <td>28</td>\n",
" <td>2</td>\n",
" <td>0</td>\n",
" <td>True</td>\n",
" <td>False</td>\n",
" <td>[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, ...</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" userID Timestamp Current_Task Task_amount TaskID VersionID \\\n",
"8351 2 1553594010364 1 510 28 2 \n",
"8352 2 1553594010414 1 510 28 2 \n",
"8353 2 1553594010445 1 510 28 2 \n",
"8354 2 1553594010485 1 510 28 2 \n",
"8355 2 1553594010525 1 510 28 2 \n",
"\n",
" RepetitionID Actual_Data Is_Pause \\\n",
"8351 0 True False \n",
"8352 0 True False \n",
"8353 0 True False \n",
"8354 0 True False \n",
"8355 0 True False \n",
"\n",
" Image \n",
"8351 [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, ... \n",
"8352 [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, ... \n",
"8353 [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, ... \n",
"8354 [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, ... \n",
"8355 [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, ... "
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dfAll = pd.read_pickle(\"DataStudyEvaluation/AllData.pkl\")\n",
"df_actual = dfAll[(dfAll.Actual_Data == True) & (dfAll.Is_Pause == False)]\n",
"df_actual.head()"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"12"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"len(df_actual.userID.unique())"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"all: 608084, actual data: 495142\n"
]
}
],
"source": [
"print(\"all: %s, actual data: %s\" % (len(dfAll), len(df_actual)))"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"CPU times: user 23.3 s, sys: 3.08 s, total: 26.3 s\n",
"Wall time: 26 s\n"
]
}
],
"source": [
"%%time\n",
"# filter out all gestures, where the revert button was pressed during the study and the gestrue was repeated\n",
"def is_max(df):\n",
" df_temp = df.copy(deep=True)\n",
" max_version = df_temp.RepetitionID.max()\n",
" df_temp[\"IsMax\"] = np.where(df_temp.RepetitionID == max_version, True, False)\n",
" df_temp[\"MaxRepetition\"] = [max_version] * len(df_temp)\n",
" return df_temp\n",
"\n",
"df_filtered = df_actual.copy(deep=True)\n",
"df_grp = df_filtered.groupby([df_filtered.userID, df_filtered.TaskID, df_filtered.VersionID])\n",
"pool = Pool(cpu_count() - 1)\n",
"result_lst = pool.map(is_max, [grp for name, grp in df_grp])\n",
"df_filtered = pd.concat(result_lst)\n",
"df_filtered = df_filtered[df_filtered.IsMax == True]\n",
"pool.close()"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"df_filtered.to_pickle(\"DataStudyEvaluation/df_lstm.pkl\")"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"actual: 495142, filtered data: 457271\n"
]
}
],
"source": [
"print(\"actual: %s, filtered data: %s\" % (len(df_actual), len(df_filtered)))"
]
}
],
"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
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

162
python/Step_41_R.ipynb Normal file
View File

@ -0,0 +1,162 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"\n",
"\tFriedman rank sum test\n",
"\n",
"data: Score and Task and ID\n",
"Friedman chi-squared = 12, df = 1, p-value = 0.000532\n"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"df = read.csv(\"./DataStudyEvaluation/R_TLX.csv\")\n",
"df$ID <- factor(df$ID)\n",
"df$Task <- factor(df$Task)\n",
"friedman.test(Score ~ Task | ID, data = df)"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"\n",
"\tFriedman rank sum test\n",
"\n",
"data: Score and Task and ID\n",
"Friedman chi-squared = 8.3333, df = 1, p-value = 0.003892\n"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"df = read.csv(\"./DataStudyEvaluation/R_SUS.csv\")\n",
"df$ID <- factor(df$ID)\n",
"df$Task <- factor(df$Task)\n",
"friedman.test(Score ~ Task | ID, data = df)"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"\n",
"\tFriedman rank sum test\n",
"\n",
"data: Easiness and Task and ID\n",
"Friedman chi-squared = 8.3333, df = 1, p-value = 0.003892\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"\n",
"\tFriedman rank sum test\n",
"\n",
"data: Speed and Task and ID\n",
"Friedman chi-squared = 12, df = 1, p-value = 0.000532\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"\n",
"\tFriedman rank sum test\n",
"\n",
"data: Success and Task and ID\n",
"Friedman chi-squared = 6.4, df = 1, p-value = 0.01141\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"\n",
"\tFriedman rank sum test\n",
"\n",
"data: Accuracy and Task and ID\n",
"Friedman chi-squared = 11, df = 1, p-value = 0.0009111\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"\n",
"\tFriedman rank sum test\n",
"\n",
"data: Comfort and Task and ID\n",
"Friedman chi-squared = 12, df = 1, p-value = 0.000532\n"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"df = read.csv(\"./DataStudyEvaluation/R_Quest.csv\")\n",
"df$ID <- factor(df$ID)\n",
"df$Task <- factor(df$Task)\n",
"friedman.test(Easiness ~ Task | ID, data = df)\n",
"friedman.test(Speed ~ Task | ID, data = df)\n",
"friedman.test(Success ~ Task | ID, data = df)\n",
"friedman.test(Accuracy ~ Task | ID, data = df)\n",
"friedman.test(Comfort ~ Task | ID, data = df)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "R",
"language": "R",
"name": "ir"
},
"language_info": {
"codemirror_mode": "r",
"file_extension": ".r",
"mimetype": "text/x-r-source",
"name": "R",
"pygments_lexer": "r",
"version": "3.5.3"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -0,0 +1,251 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"def findnth(haystack, needle, n):\n",
" parts= haystack.split(needle, n+1)\n",
" if len(parts)<=n+1:\n",
" return -1\n",
" return len(haystack)-len(parts[-1])-len(needle)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"I think it depends on how I hold this and how I hold my hand. - P1 / Q1\n",
"irst of all you know, [it was something new, so for I didn't feel confident about it and actually I felt like it's a little bit uncomfortable. but when I changed my hand position, it was okay. - P1 / Q1\n",
"it was something new, so for I didn't feel confident about it and actually I felt like it's a little bit uncomfortable. but when I changed my hand position, it was okay. - P1 / Q1\n",
"es ist ungewohnt und umständlich. - P2 / Q1\n",
"ich glaub man ist vor allem ungenau. - P2 / Q1\n",
"mit den fingerspitzen bin ichs irgenwie gewohnt, ich kann so präzise wörter auswählen. - P2 / Q1\n",
"mit dem knöchel, also ich seh noch weniger von dem objekt, was ich auswählen will. also das fat-finger-problem wird noch größer. und dadurch glaub ich wirds noch ungenauer. - P2 / Q1\n",
"an sich ist es ganz nett für manche sachen. - P3 / Q1\n",
"hat jetzt halt nicht so gut funktoniert - P3 / Q1\n",
"wenns funktioniert hat war es eigentlich ganz cool für manche sachen - P3 / Q1\n",
"ja es ist interessant - P4 / Q1\n",
"wars irgendwie noch nicht ausgereift, es gab irgendwie diverse false positives bei mir, also vielleicht lags am prototypen-system, war halt noch langsam - P4 / Q1\n",
"es ist irgendwie immer noch angenehmer gesten einfach mit dem finger zu zeichnen als mit dem knuckle. - P4 / Q1\n",
"es hat trotzdem noch relativ gut funktioniert dafür - P5 / Q1\n",
"ich wurde eher bestätigt in meinen schlechten erwartungen - P5 / Q1\n",
"I think it's not convenient - P6 / Q1\n",
"it's awkward - P6 / Q1\n",
"With one knuckle it's still okay - P6 / Q1\n",
"I would survive it and if it gave me some super awesome functionality it might make sense - P6 / Q1\n",
"two knuckles is a no-go - P6 / Q1\n",
"ich find eigentlich die Idee ganz cool - P7 / Q1\n",
"wenns schneller gehen würde und es das besser erkennen würde hätt ich die Idee, also fänd ichs glaub ich besser - P7 / Q1\n",
"ich dann doch finde dass mans eh schon gewohnt ist so doppelklick auf ein wort zu machen - P7 / Q1\n",
"halt irgend ne andere funktion auf den knuckle als ne funktion für die es eh schon ne gute lösung gibt fänd ich besser - P7 / Q1\n",
"sehr langsam, sehr verzögert - P8 / Q1\n",
"ist erstmal ungewohnt - P9 / Q1\n",
"nach ner zeit hat der knöchel echt so angefangen weh zu tun - P9 / Q1\n",
"ich fand eigentlich ganz interessant - P10 / Q1\n",
"fands sehr interessant und gut eigentlich - P10 / Q1\n",
"sehr ungewohnt - P11 / Q1\n",
"es kommt einfach viel natürlicher rüber mit dem finger das zu handlen - P11 / Q1\n",
"paar funktionen sind ganz okay - P12 / Q1\n",
"das mit dem hand auflegen mit den zwei fingern ist bisschen komisch, mit dem doppeltap fühlt es sich so an als würde man dem handy so eine punchen - P12 / Q1\n",
"so kreis oder so, ist halt bisschen aufwändig, falls man das verwenden will irgendwo schnell - P12 / Q1\n",
"if it would enable us to do something more, or faster, or anything more than we have right now, yeah I would use it - P1 / Q2\n",
"wirklich eingeschränkt - P2 / Q2\n",
"mit der zeit tuts mit dem knuckle weh - P2 / Q2\n",
"hier kommt noch so das ungewohnte, der ungewohnte schmerz erstmal hinzu - P2 / Q2\n",
"bis es das system wirklich erkennt umständlich, wenn man die gesten mehrmals ausführen muss, wobei man mit dem finger wahrscheinlich trainiert ist - P2 / Q2\n",
"ich denk es wär nützlich - P3 / Q2\n",
"nicht um andere funltionen die man schon hat zu erstetzen, sondern einfach um noch zusätzlich mehr gesten zu haben - P3 / Q2\n",
"dieses screenshot - P3 / Q2\n",
"bei manchen sachen wo man halt keine gesten benutzen kann weils die einfach noch garnicht gibt, kann man die gesten sozusagen erweitern, aber nicht unbedingt ersetzen - P3 / Q2\n",
"ja wenns gut integriert ist kann mal halt noch mehr gesten zu den schon existierenden gesten dazu machen - P4 / Q2\n",
"wenn man jetzt gesten regelmäßig benutzt ist das sicher gut - P4 / Q2\n",
"mir nicht einfällt wie man das weiter ausbauen und nützen könnte - P5 / Q2\n",
"it depends probably on the application - P6 / Q2\n",
"I wouldn't replace finger touching with knuckle touching at all - P6 / Q2\n",
"if you are offering to add some extra functionality, I'm not able to use now, where I might need comlex gestures, then it might be a good thing - P6 / Q2\n",
"ne nützliche sache - P7 / Q2\n",
"wenns halt irgendwelche sachen sind, die normalerweise halt total umständlich wären, dann darauf ne knucklefunktion, das fänd ich cool - P7 / Q2\n",
"eher weniger. - P8 / Q2\n",
"nützlich wäre für irgendwas wo man halt alle anderen fingereingaben schon belegt hat, dann würde es bestimmt sinn machen - P9 / Q2\n",
"ich finds eigentlich sehr nützlich, also grade die verschiedenen gesten mit dem swipe left, swipe right, das ist sehr intuitiv und kann man auch sehr gut benutzen - P10 / Q2\n",
"ich kann mir halt nicht vorstellen dass es funktionen gibt die man lieber mit dem knöchel benutzt statt mit dem finger. - P11 / Q2\n",
"wenn man es als distinkte von den fingern zu unterscheidende funktion einführt, ein paar davon vielleicht - P12 / Q2\n",
"it was for me the hardest thing to complete the tasks but it wasn't too hard - P1 / Q3\n",
"bereits angesprochen ja, nicht so einfach. umständlich ja. - P2 / Q3\n",
" normal, ich fands eigentlich relativ einfach bis auf die eine funktion mit dem rotieren, das fand ich total bescheuert, also das war garnicht gut. - P3 / Q3\n",
"eigentlich nicht schwierig - P4 / Q3\n",
"generell haltung etc? - P5 / Q3\n",
"sehr schwierig, weil man hat keine möglichkeit das mit einer hand zu machen, also mit der hand das handy halten und noch nen knöchelinput zu machen. - P5 / Q3\n",
"not very much - P6 / Q3\n",
"touching with two knuckles at the same time, it's more complicated because you have to find the right angle, because the fingers have different lengths. - P6 / Q3\n",
"tippen fand ich super, das rechts und links swipen fand ich super, weil das geht schnell, hoch und runter geht auch schnell, aber alles andere war irgendwie, also man derht halt die ganze hand, und das find ich schon ist ein ziemlich großer zeitaufwand. - P7 / Q3\n",
"wenns jetzt ne andere funktion wäre, wo ich erstmal in irgendein menü gehen muss, und irgendwas raussuchen muss, oder wo ich irgendwo hingucken muss oder sonstirgendwas, dann find ich knuckle besser. - P7 / Q3\n",
"immer wenn ich zwei knuckles benutzen musste war es scheisse. es war unpraktisch und unbequem. - P7 / Q3\n",
"feedback war noch zu langsam. - P8 / Q3\n",
"nicht schwierig. - P9 / Q3\n",
"fand ich jetzt nicht schwierig wirklich. - P10 / Q3\n",
"ein bisschen schwerer als mit dem finger. aber man gewöhnt sich schnell dran. - P11 / Q3\n",
"ziemlich einfach. - P12 / Q3\n",
"something new. maybe people would like to try something new. - P1 / Q4\n",
"yeah if we for example use it like we are writing, maybe it will be more natural for our hand to use it that way. - P1 / Q4\n",
"ich könnte mir vorstellen dass es ne gute alternative zum finger ist für speziele eingaben, aber nicht als reguläre eingabe. - P2 / Q4\n",
"ich tipp mal kurz zweimal mit dem knuckle auf as telefon und das heisst hey telefon geh mal lautlos, so als shortcut könnt ich mir das vorstellen - P2 / Q4\n",
"nicht irgenwie um irgendwas zu machen was präzise sein muss, also wo ich ne präzise stelle auswählen muss. also nen text kopieren oder einfügen, weil da muss die stelle passen was ich kopieren oder wo ichs einfügen will. wenn ichs an der falschen position einfüge ists auch wieder doof. - P2 / Q4\n",
"für mach den ton aus, oder geh in flugmodus, irgendwie so, dafür, für dinge die schnell gehen, so lehn den anruf ab, da könnt ichs mir eher vorstellen. - P2 / Q4\n",
"einfach mehr gesten hast, du kannst halt einfach mehr sachen machen die du bis jetzt noch nicht machen konntest. - P3 / Q4\n",
"ich denk für so ein paar shortcuts oder so ist das halt, wenn man ne funktion hat die da drauf gemapped ist, jetzt so irgendwie ein swipe oder ein tap, kann ich mir schon vorstellen, aber jetzt größere gesten, dann ist es zu, weiss nicht. - P4 / Q4\n",
"falls es gut genug unterscheidbar ist vom finger ist es einfach noch ne weitere eingabemöglichkeit. - P4 / Q4\n",
"you have more, like an extra dimension - P6 / Q4\n",
"selten benutzte funktionen kannst du darauf legen - P7 / Q4\n",
"ich finds schon praktisch so - P7 / Q4\n",
"ist schon praktisch - P7 / Q4\n",
"man hat halt mehr eingabemöglichkeiten - P8 / Q4\n",
"mehr kraft aufwenden kann und halt extra tiefe hat - P9 / Q4\n",
"sind intuitiv, also schnell zu lernen, und bieten viele möglichkeiten halt auch an. - P10 / Q4\n",
"ne geste find ich an sich besser. - P10 / Q4\n",
"man kann es machen wenns einem kalt ist und einem die fingerspitzen wehtun und man wenig gefühl hat auf jeden fall. besser als mit nase zum beispiel. - P12 / Q4\n",
"distinkte merkmale, man bekommt halt ne größere vielfalt an movements die man machen kann. - P12 / Q4\n",
"I don't know it it's a need to do something like that with knuckles - P1 / Q5\n",
"for sure many people will have to learn how to do that - P1 / Q5\n",
"it's not natural for sure - P1 / Q5\n",
"my hand hurts me - P1 / Q5\n",
"bereits gesagt - P2 / Q5\n",
"halt nicht für irgendwelche eingaben die akkurat sein sollen - P2 / Q5\n",
"knöchel tut ein bisschen weh, aber ich hab damit ja auch über 250 mal was gemacht, und im normalfall benutzt man den knöchel nicht, ich glaub wenn ich da jetzt ab und zu mal ne geste damit mach, dann ist es nicht so schlimm - P3 / Q5\n",
"irgendwie bisschen ungewohnt - P4 / Q5\n",
"es ist nur zweihändig möglich, also einhändig - ne, geht nicht - P4 / Q5\n",
"schränkt die bewegungsfreiheit ein, hat weniger auflagefläche als ein finger und ist ungenauer - P5 / Q5\n",
"man sieht nicht genau wo man hin tappt. - P5 / Q5\n",
"Well I think that the awkwardness of movements - P6 / Q5\n",
"+two knckletouchs+ you cannot flex the single segments of your fingers. - P6 / Q5\n",
"zeitverzögerung, weil der finger ist ja eh schon am handy, jetzt obs der faumen oder zeigefinger ist is ja egal, der finger is eh schon am handy, aber wenn ich meinen knuckle benutzen muss, dann muss ich die gesamte hand drehen und wieder zurückdrehen. - P7 / Q5\n",
"auch irgendwie unbequem. sobald ich irgendwas mehr machen musste als nur einen strich ziehen oder einmal tippen, fand ichs unbequem. - P7 / Q5\n",
"obwohl ich glaub mit zwei knuckeln tippen wäre auch okay gewesen. - P7 / Q5\n",
"auf die dauer sehr anstrengend - P8 / Q5\n",
"ich glaub auch für die haut, die ist dann vielleicht auch nicht so strapazierfähig - P8 / Q5\n",
"halt umständlich. - P8 / Q5\n",
"es ist unangenehm - P9 / Q5\n",
"nicht wirklich intuitiv - P9 / Q5\n",
"unangenehme am knöchel nach ner zeit - P10 / Q5\n",
"wenn man sowieso alles mit den fingern macht, dann halt umzuswitchen auf den knuckle, das find ich irgendwie nicht so vorteilhaft. - P11 / Q5\n",
"ich glaub auf dauer fühlt sichs bisschen komisch an - P12 / Q5\n",
"ja also ich hatte halt oft das gefühl, dass meine eingabe einfach nicht erkannt wird. - P2 / Q6\n",
"naja halt dass es funktioniert. - P3 / Q6\n",
"also einmal die erkennung, aber das ist ja irgendwie klar. - P4 / Q6\n",
"shortcuts, menüs, den weg zum homebutton, oder das runterziehen von der leiste oben, ja irgenwie für shortcuts oder so systemshorcuts, könnt ich mir das gut vorstellen. - P4 / Q6\n",
"-finger joint- of the finger would be a way to use this. - P6 / Q6\n",
"also kreis war noch okay, weil das war im grunde einmal ne bewegung ziehen, genauso hoch, runter, rechts, links, und dann einmal drauftippen oder mit zwei fingern drauftippen. - P7 / Q6\n",
"was ich halt verbessern würde auf jeden fall wären irgendwelche andern funktionen darauf legen, also nicht jetzt recht swipen links swipen, obwohl je nachdem was es für ne app war, war der pfeil auch noch ganz nett, dieses um seite zu wechseln, das fand ich auch ganz cool,das fand ich ganz nützlich. - P7 / Q6\n",
"vielleicht um durch apps zu swipen wärs vielleicht ganz nice - P7 / Q6\n",
"auf jeden fall dass das feedback schneller ist, ja an sich nur das feedback. - P8 / Q6\n",
"ja also so für shortcuts eben. - P2 / Q7\n",
"klar man könnte zum beispiel sagen ich mach dieses doppeltap - P3 / Q7\n",
"screenshot mach - P3 / Q7\n",
"favorisierte app öffne - P3 / Q7\n",
"ein mailprogramm - P4 / Q7\n",
"zeichnest du mit dem stift, und der knuckle ist der pinsel - P4 / Q7\n",
"mehrere inputmöglichkeiten die du dann halt statt auf ein menü zu klicken und ausführen halt einfach den knuckle hast - P4 / Q7\n",
"bei anderen input geräten, wie computer beispielsweise, ist das vllt ganz cool, noch ne neue dimension mit rein zu bringen - P5 / Q7\n",
"Well like controlling the phone in general - P6 / Q7\n",
"popping up a menu or something - P6 / Q7\n",
"manipulation of objects in 3D - P6 / Q7\n",
"wecker snoozen - P7 / Q7\n",
"die lautstärke verändern - P7 / Q7\n",
"wenn du den kreis so, zum beispiel nach links drehen machts halt leiser, nach rechts drehen machts halt lauter, so wies halt so intuitiv wäre bei nem drehknopf so - P7 / Q7\n",
"shortcuts drauf zu legen die man halt oft braucht - P7 / Q7\n",
"taschenlampe - P7 / Q7\n",
"flugmodus oder sowas reinmachen - P7 / Q7\n",
"zum aufwecken vom handy - P8 / Q7\n",
"auf anderen devices wo das mehr sinn machen würde - P9 / Q7\n",
"um ein lied weiter zu machen - P10 / Q7\n",
"zwei lieder überspringen - P10 / Q7\n",
"verschiedene funktionen in apps dadurch implementieren kann - P10 / Q7\n",
"der einzige moment wo ich mein handy mit meinem knöchel benutz ist tatsächlich wenns zu kalt ist oder ich aus irgendeinem grund meine finger nicht benutzen kann weil sie schmutzig sind - P12 / Q7\n",
"-yes- - P1 / Q8\n",
"I will have to, I will use it - P1 / Q8\n",
"I will learn how to do it very fast - P1 / Q8\n",
"-ja- - P2 / Q8\n",
"wo so shortuts hilfreich sind - P2 / Q8\n",
"stell nen timer von 1:30 - P2 / Q8\n",
"stell nen wecker auf morgen wie immer um 8 - P2 / Q8\n",
"einstellungen, timer reset, sondern start, stopp - P2 / Q8\n",
"kurz so machen muss ohne dass man sich durch die settings durchnavigieren muss - P2 / Q8\n",
"ja - P3 / Q8\n",
"-ja, für shortcuts- - P4 / Q8\n",
"wenns natürlich super funktioniert und ich sehe dass es mir vorteile bringt, dann ja - P5 / Q8\n",
"I think it depends on if it makes things easier or faster, or has some kind of advantage, I probably would use it - P6 / Q8\n",
"taschenlampe würd ich hundert pro benutzen - P7 / Q8\n",
"lautstärke würd ich auch benutzen - P7 / Q8\n",
"eher nicht. - P8 / Q8\n",
"ich glaub nicht. - P9 / Q8\n",
"ja - P10 / Q8\n",
"wahrscheinlich nicht. - P11 / Q8\n",
"wahrscheinlich eher nicht, aber ich benutz auch so praktisch keine funktionen meines handys. - P12 / Q8\n",
"manchmal hab ich halt das L und das gespiegelte L vertauscht - P3 / Q9\n",
"probleme mit recht und links gehabt - P3 / Q9\n",
"if the prototype was to work more smoothly and faster, I might have a different impression on the whole interaction - P6 / Q9\n",
"ich denk mal wenn man das jetzt am tag vielleicht 10-20 mal benutzt dann ist das noch vollkommen okay - P10 / Q9\n"
]
}
],
"source": [
"for question in range(1, 10):\n",
" fname = \"q\" + str(question) + \".txt\"\n",
" with open(\"./DataStudyEvaluation-Qs/\" + fname) as f:\n",
" content = f.readlines()\n",
" # you may also want to remove whitespace characters like `\\n` at the end of each line\n",
" content = [x.strip() for x in content] \n",
"\n",
" for participant in range(len(content)):\n",
" line = content[participant]\n",
" count = 0\n",
" while (findnth(line, \"[\", count) > -1):\n",
" start = findnth(line, \"[\", count)\n",
" end = findnth(line, \"]\", count)\n",
" count = count + 1\n",
" \n",
" answer = line[start+1:end]\n",
" answer = answer.replace(\"\\t\", \" \")\n",
" print(answer, \"- P\" + str(participant+1), \"/ Q\" + str(question))\n"
]
}
],
"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
}