6831 lines (6830 with data), 588.9 kB
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/home/reina/anaconda3/envs/RSNA/lib/python3.6/importlib/_bootstrap.py:219: ImportWarning: can't resolve package from __spec__ or __package__, falling back on __name__ and __path__\n",
" return f(*args, **kwds)\n",
"/home/reina/anaconda3/envs/RSNA/lib/python3.6/importlib/_bootstrap.py:219: ImportWarning: can't resolve package from __spec__ or __package__, falling back on __name__ and __path__\n",
" return f(*args, **kwds)\n"
]
}
],
"source": [
"from __future__ import absolute_import\n",
"from __future__ import division\n",
"from __future__ import print_function\n",
"\n",
"\n",
"import numpy as np # linear algebra\n",
"import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n",
"import os\n",
"import datetime\n",
"import seaborn as sns\n",
"import pydicom\n",
"import time\n",
"import gc\n",
"import operator \n",
"from apex import amp \n",
"import matplotlib.pyplot as plt\n",
"import torch\n",
"import torch.nn as nn\n",
"import torch.utils.data as D\n",
"import torch.nn.functional as F\n",
"from sklearn.model_selection import KFold\n",
"from tqdm import tqdm, tqdm_notebook\n",
"from IPython.core.interactiveshell import InteractiveShell\n",
"InteractiveShell.ast_node_interactivity = \"all\"\n",
"import warnings\n",
"warnings.filterwarnings(action='once')\n",
"import pickle\n",
"%load_ext autoreload\n",
"%autoreload 2\n",
"%matplotlib inline\n",
"from skimage.io import imread,imshow\n",
"from helper import *\n",
"from apex import amp\n",
"import helper\n",
"import torchvision.models as models\n",
"from torch.optim import Adam\n",
"from defenitions import *"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"SEED = 8153\n",
"device=device_by_name(\"Tesla\")\n",
"#device=device_by_name(\"RTX\")\n",
"#device = \"cpu\"\n",
"sendmeemail=Email_Progress(my_gmail,my_pass,to_email,'Densenet161-folds0 results')"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"def get_submission(test_df,pred):\n",
" epidural_df=pd.DataFrame(data={'ID':'ID_'+test_df.PatientID.values+'_epidural','Label':torch.sigmoid(pred[:,0])})\n",
" intraparenchymal_df=pd.DataFrame(data={'ID':'ID_'+test_df.PatientID.values+'_intraparenchymal','Label':torch.sigmoid(pred[:,1])})\n",
" intraventricular_df=pd.DataFrame(data={'ID':'ID_'+test_df.PatientID.values+'_intraventricular','Label':torch.sigmoid(pred[:,2])})\n",
" subarachnoid_df=pd.DataFrame(data={'ID':'ID_'+test_df.PatientID.values+'_subarachnoid','Label':torch.sigmoid(pred[:,3])})\n",
" subdural_df=pd.DataFrame(data={'ID':'ID_'+test_df.PatientID.values+'_subdural','Label':torch.sigmoid(pred[:,4])})\n",
" any_df=pd.DataFrame(data={'ID':'ID_'+test_df.PatientID.values+'_any','Label':torch.sigmoid(pred[:,5])}) \n",
" return pd.concat([epidural_df,\n",
" intraparenchymal_df,\n",
" intraventricular_df,\n",
" subarachnoid_df,\n",
" subdural_df,\n",
" any_df]).sort_values('ID').reset_index(drop=True)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(674510, 15)"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"text/plain": [
"(674252, 15)"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
},
{
"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>PatientID</th>\n",
" <th>epidural</th>\n",
" <th>intraparenchymal</th>\n",
" <th>intraventricular</th>\n",
" <th>subarachnoid</th>\n",
" <th>subdural</th>\n",
" <th>any</th>\n",
" <th>PID</th>\n",
" <th>StudyI</th>\n",
" <th>SeriesI</th>\n",
" <th>WindowCenter</th>\n",
" <th>WindowWidth</th>\n",
" <th>ImagePositionZ</th>\n",
" <th>ImagePositionX</th>\n",
" <th>ImagePositionY</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>63eb1e259</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>a449357f</td>\n",
" <td>62d125e5b2</td>\n",
" <td>0be5c0d1b3</td>\n",
" <td>['00036', '00036']</td>\n",
" <td>['00080', '00080']</td>\n",
" <td>180.199951</td>\n",
" <td>-125.0</td>\n",
" <td>-8.000000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>2669954a7</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>363d5865</td>\n",
" <td>a20b80c7bf</td>\n",
" <td>3564d584db</td>\n",
" <td>['00047', '00047']</td>\n",
" <td>['00080', '00080']</td>\n",
" <td>922.530821</td>\n",
" <td>-156.0</td>\n",
" <td>45.572849</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>52c9913b1</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>9c2b4bd7</td>\n",
" <td>3e3634f8cf</td>\n",
" <td>973274ffc9</td>\n",
" <td>40</td>\n",
" <td>150</td>\n",
" <td>4.455000</td>\n",
" <td>-125.0</td>\n",
" <td>-115.063000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>4e6ff6126</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>3ae81c2d</td>\n",
" <td>a1390c15c2</td>\n",
" <td>e5ccad8244</td>\n",
" <td>['00036', '00036']</td>\n",
" <td>['00080', '00080']</td>\n",
" <td>100.000000</td>\n",
" <td>-99.5</td>\n",
" <td>28.500000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>7858edd88</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>c1867feb</td>\n",
" <td>c73e81ed3a</td>\n",
" <td>28e0531b3a</td>\n",
" <td>40</td>\n",
" <td>100</td>\n",
" <td>145.793000</td>\n",
" <td>-125.0</td>\n",
" <td>-132.190000</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" PatientID epidural intraparenchymal intraventricular subarachnoid \\\n",
"0 63eb1e259 0 0 0 0 \n",
"1 2669954a7 0 0 0 0 \n",
"2 52c9913b1 0 0 0 0 \n",
"3 4e6ff6126 0 0 0 0 \n",
"4 7858edd88 0 0 0 0 \n",
"\n",
" subdural any PID StudyI SeriesI WindowCenter \\\n",
"0 0 0 a449357f 62d125e5b2 0be5c0d1b3 ['00036', '00036'] \n",
"1 0 0 363d5865 a20b80c7bf 3564d584db ['00047', '00047'] \n",
"2 0 0 9c2b4bd7 3e3634f8cf 973274ffc9 40 \n",
"3 0 0 3ae81c2d a1390c15c2 e5ccad8244 ['00036', '00036'] \n",
"4 0 0 c1867feb c73e81ed3a 28e0531b3a 40 \n",
"\n",
" WindowWidth ImagePositionZ ImagePositionX ImagePositionY \n",
"0 ['00080', '00080'] 180.199951 -125.0 -8.000000 \n",
"1 ['00080', '00080'] 922.530821 -156.0 45.572849 \n",
"2 150 4.455000 -125.0 -115.063000 \n",
"3 ['00080', '00080'] 100.000000 -99.5 28.500000 \n",
"4 100 145.793000 -125.0 -132.190000 "
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"train_df = pd.read_csv(data_dir+'train.csv')\n",
"train_df.shape\n",
"train_df=train_df[~train_df.PatientID.isin(bad_images)].reset_index(drop=True)\n",
"train_df=train_df.drop_duplicates().reset_index(drop=True)\n",
"train_df.shape\n",
"train_df.head()"
]
},
{
"cell_type": "code",
"execution_count": 5,
"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>PatientID</th>\n",
" <th>epidural</th>\n",
" <th>intraparenchymal</th>\n",
" <th>intraventricular</th>\n",
" <th>subarachnoid</th>\n",
" <th>subdural</th>\n",
" <th>any</th>\n",
" <th>SeriesI</th>\n",
" <th>PID</th>\n",
" <th>StudyI</th>\n",
" <th>WindowCenter</th>\n",
" <th>WindowWidth</th>\n",
" <th>ImagePositionZ</th>\n",
" <th>ImagePositionX</th>\n",
" <th>ImagePositionY</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>28fbab7eb</td>\n",
" <td>0.5</td>\n",
" <td>0.5</td>\n",
" <td>0.5</td>\n",
" <td>0.5</td>\n",
" <td>0.5</td>\n",
" <td>0.5</td>\n",
" <td>ebfd7e4506</td>\n",
" <td>cf1b6b11</td>\n",
" <td>93407cadbb</td>\n",
" <td>30</td>\n",
" <td>80</td>\n",
" <td>158.458000</td>\n",
" <td>-125.0</td>\n",
" <td>-135.598000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>877923b8b</td>\n",
" <td>0.5</td>\n",
" <td>0.5</td>\n",
" <td>0.5</td>\n",
" <td>0.5</td>\n",
" <td>0.5</td>\n",
" <td>0.5</td>\n",
" <td>6d95084e15</td>\n",
" <td>ad8ea58f</td>\n",
" <td>a337baa067</td>\n",
" <td>30</td>\n",
" <td>80</td>\n",
" <td>138.729050</td>\n",
" <td>-125.0</td>\n",
" <td>-101.797981</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>a591477cb</td>\n",
" <td>0.5</td>\n",
" <td>0.5</td>\n",
" <td>0.5</td>\n",
" <td>0.5</td>\n",
" <td>0.5</td>\n",
" <td>0.5</td>\n",
" <td>8e06b2c9e0</td>\n",
" <td>ecfb278b</td>\n",
" <td>0cfe838d54</td>\n",
" <td>30</td>\n",
" <td>80</td>\n",
" <td>60.830002</td>\n",
" <td>-125.0</td>\n",
" <td>-133.300003</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>42217c898</td>\n",
" <td>0.5</td>\n",
" <td>0.5</td>\n",
" <td>0.5</td>\n",
" <td>0.5</td>\n",
" <td>0.5</td>\n",
" <td>0.5</td>\n",
" <td>e800f419cf</td>\n",
" <td>e96e31f4</td>\n",
" <td>c497ac5bad</td>\n",
" <td>30</td>\n",
" <td>80</td>\n",
" <td>55.388000</td>\n",
" <td>-125.0</td>\n",
" <td>-146.081000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>a130c4d2f</td>\n",
" <td>0.5</td>\n",
" <td>0.5</td>\n",
" <td>0.5</td>\n",
" <td>0.5</td>\n",
" <td>0.5</td>\n",
" <td>0.5</td>\n",
" <td>faeb7454f3</td>\n",
" <td>69affa42</td>\n",
" <td>854e4fbc01</td>\n",
" <td>30</td>\n",
" <td>80</td>\n",
" <td>33.516888</td>\n",
" <td>-125.0</td>\n",
" <td>-118.689819</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" PatientID epidural intraparenchymal intraventricular subarachnoid \\\n",
"0 28fbab7eb 0.5 0.5 0.5 0.5 \n",
"1 877923b8b 0.5 0.5 0.5 0.5 \n",
"2 a591477cb 0.5 0.5 0.5 0.5 \n",
"3 42217c898 0.5 0.5 0.5 0.5 \n",
"4 a130c4d2f 0.5 0.5 0.5 0.5 \n",
"\n",
" subdural any SeriesI PID StudyI WindowCenter WindowWidth \\\n",
"0 0.5 0.5 ebfd7e4506 cf1b6b11 93407cadbb 30 80 \n",
"1 0.5 0.5 6d95084e15 ad8ea58f a337baa067 30 80 \n",
"2 0.5 0.5 8e06b2c9e0 ecfb278b 0cfe838d54 30 80 \n",
"3 0.5 0.5 e800f419cf e96e31f4 c497ac5bad 30 80 \n",
"4 0.5 0.5 faeb7454f3 69affa42 854e4fbc01 30 80 \n",
"\n",
" ImagePositionZ ImagePositionX ImagePositionY \n",
"0 158.458000 -125.0 -135.598000 \n",
"1 138.729050 -125.0 -101.797981 \n",
"2 60.830002 -125.0 -133.300003 \n",
"3 55.388000 -125.0 -146.081000 \n",
"4 33.516888 -125.0 -118.689819 "
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"test_df = pd.read_csv(data_dir+'test.csv')\n",
"test_df.head()"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"split_sid = train_df.PID.unique()\n",
"splits=list(KFold(n_splits=3,shuffle=True, random_state=SEED).split(split_sid))\n"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"def my_loss(y_pred,y_true,weights):\n",
" if len(y_pred.shape)==len(y_true.shape):\n",
" loss = F.binary_cross_entropy_with_logits(y_pred,y_true,weights.repeat(y_pred.shape[0],1))\n",
" else:\n",
" loss0 = F.binary_cross_entropy_with_logits(y_pred,y_true[...,0],weights.repeat(y_pred.shape[0],1),reduction='none')\n",
" loss1 = F.binary_cross_entropy_with_logits(y_pred,y_true[...,1],weights.repeat(y_pred.shape[0],1),reduction='none')\n",
" loss = (y_true[...,2]*loss0+(1.0-y_true[...,2])*loss1).mean() \n",
" return loss"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"class parameter_scheduler():\n",
" def __init__(self,model,do_first=['classifier'],num_epoch=1):\n",
" self.model=model\n",
" self.do_first = do_first\n",
" self.num_epoch=num_epoch\n",
" def __call__(self,epoch):\n",
" if epoch>=self.num_epoch:\n",
" for n,p in self.model.named_parameters():\n",
" p.requires_grad=True\n",
" else:\n",
" for n,p in self.model.named_parameters():\n",
" p.requires_grad= any(nd in n for nd in self.do_first)\n"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
"def get_optimizer_parameters(model,klr):\n",
" zero_layer=['conv0','norm0','ws_norm']\n",
" param_optimizer = list(model.named_parameters())\n",
" num_blocks=4\n",
" no_decay=['bias']\n",
" optimizer_grouped_parameters=[\n",
" {'params': [p for n, p in param_optimizer if (not any(nd in n for nd in no_decay) and any(nd in n for nd in zero_layer))], 'lr':klr*2e-5,'weight_decay': 0.01},\n",
" {'params': [p for n, p in param_optimizer if any(nd in n for nd in no_decay) and any(nd in n for nd in zero_layer)], 'lr':klr*2e-5, 'weight_decay': 0.0}\n",
" ]\n",
" optimizer_grouped_parameters.extend([\n",
" {'params': [p for n, p in param_optimizer if (not any(nd in n for nd in no_decay) and ('wso' in n))], 'lr':klr*1e-5,'weight_decay': 0.01},\n",
" {'params': [p for n, p in param_optimizer if any(nd in n for nd in no_decay) and ('wso' in n)], 'lr':klr*1e-5, 'weight_decay': 0.0}\n",
" ])\n",
" optimizer_grouped_parameters.extend([\n",
" {'params': [p for n, p in param_optimizer if (not any(nd in n for nd in no_decay) and ('classifier' in n))], 'lr':klr*1e-3,'weight_decay': 0.01},\n",
" {'params': [p for n, p in param_optimizer if any(nd in n for nd in no_decay) and ('classifier' in n)], 'lr':klr*1e-3, 'weight_decay': 0.0}\n",
" ])\n",
" for i in range(num_blocks):\n",
" optimizer_grouped_parameters.extend([\n",
" {'params': [p for n, p in param_optimizer if (not any(nd in n for nd in no_decay) and ('denseblock{}'.format(i+1) in n))], 'lr':klr*(2.0**i)*2e-5,'weight_decay': 0.01},\n",
" {'params': [p for n, p in param_optimizer if any(nd in n for nd in no_decay) and ('denseblock{}'.format(i+1) in n)], 'lr':klr*(2.0**i)*2e-5, 'weight_decay': 0.0}\n",
" ])\n",
" optimizer_grouped_parameters.extend([\n",
" {'params': [p for n, p in param_optimizer if (not any(nd in n for nd in no_decay) and ('norm5' in n))], 'lr':klr*1e-4,'weight_decay': 0.01},\n",
" {'params': [p for n, p in param_optimizer if any(nd in n for nd in no_decay) and ('norm5' in n)], 'lr':klr*1e-4, 'weight_decay': 0.0}\n",
" ])\n",
" return(optimizer_grouped_parameters)\n",
"\n",
" "
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<torch._C.Generator at 0x7f06349ec5d0>"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"text/plain": [
"(449982,)"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"text/plain": [
"(224270,)"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"application/javascript": [
"/* Put everything inside the global mpl namespace */\n",
"window.mpl = {};\n",
"\n",
"\n",
"mpl.get_websocket_type = function() {\n",
" if (typeof(WebSocket) !== 'undefined') {\n",
" return WebSocket;\n",
" } else if (typeof(MozWebSocket) !== 'undefined') {\n",
" return MozWebSocket;\n",
" } else {\n",
" alert('Your browser does not have WebSocket support.' +\n",
" 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
" 'Firefox 4 and 5 are also supported but you ' +\n",
" 'have to enable WebSockets in about:config.');\n",
" };\n",
"}\n",
"\n",
"mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n",
" this.id = figure_id;\n",
"\n",
" this.ws = websocket;\n",
"\n",
" this.supports_binary = (this.ws.binaryType != undefined);\n",
"\n",
" if (!this.supports_binary) {\n",
" var warnings = document.getElementById(\"mpl-warnings\");\n",
" if (warnings) {\n",
" warnings.style.display = 'block';\n",
" warnings.textContent = (\n",
" \"This browser does not support binary websocket messages. \" +\n",
" \"Performance may be slow.\");\n",
" }\n",
" }\n",
"\n",
" this.imageObj = new Image();\n",
"\n",
" this.context = undefined;\n",
" this.message = undefined;\n",
" this.canvas = undefined;\n",
" this.rubberband_canvas = undefined;\n",
" this.rubberband_context = undefined;\n",
" this.format_dropdown = undefined;\n",
"\n",
" this.image_mode = 'full';\n",
"\n",
" this.root = $('<div/>');\n",
" this._root_extra_style(this.root)\n",
" this.root.attr('style', 'display: inline-block');\n",
"\n",
" $(parent_element).append(this.root);\n",
"\n",
" this._init_header(this);\n",
" this._init_canvas(this);\n",
" this._init_toolbar(this);\n",
"\n",
" var fig = this;\n",
"\n",
" this.waiting = false;\n",
"\n",
" this.ws.onopen = function () {\n",
" fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n",
" fig.send_message(\"send_image_mode\", {});\n",
" if (mpl.ratio != 1) {\n",
" fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n",
" }\n",
" fig.send_message(\"refresh\", {});\n",
" }\n",
"\n",
" this.imageObj.onload = function() {\n",
" if (fig.image_mode == 'full') {\n",
" // Full images could contain transparency (where diff images\n",
" // almost always do), so we need to clear the canvas so that\n",
" // there is no ghosting.\n",
" fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
" }\n",
" fig.context.drawImage(fig.imageObj, 0, 0);\n",
" };\n",
"\n",
" this.imageObj.onunload = function() {\n",
" fig.ws.close();\n",
" }\n",
"\n",
" this.ws.onmessage = this._make_on_message_function(this);\n",
"\n",
" this.ondownload = ondownload;\n",
"}\n",
"\n",
"mpl.figure.prototype._init_header = function() {\n",
" var titlebar = $(\n",
" '<div class=\"ui-dialog-titlebar ui-widget-header ui-corner-all ' +\n",
" 'ui-helper-clearfix\"/>');\n",
" var titletext = $(\n",
" '<div class=\"ui-dialog-title\" style=\"width: 100%; ' +\n",
" 'text-align: center; padding: 3px;\"/>');\n",
" titlebar.append(titletext)\n",
" this.root.append(titlebar);\n",
" this.header = titletext[0];\n",
"}\n",
"\n",
"\n",
"\n",
"mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n",
"\n",
"}\n",
"\n",
"\n",
"mpl.figure.prototype._root_extra_style = function(canvas_div) {\n",
"\n",
"}\n",
"\n",
"mpl.figure.prototype._init_canvas = function() {\n",
" var fig = this;\n",
"\n",
" var canvas_div = $('<div/>');\n",
"\n",
" canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n",
"\n",
" function canvas_keyboard_event(event) {\n",
" return fig.key_event(event, event['data']);\n",
" }\n",
"\n",
" canvas_div.keydown('key_press', canvas_keyboard_event);\n",
" canvas_div.keyup('key_release', canvas_keyboard_event);\n",
" this.canvas_div = canvas_div\n",
" this._canvas_extra_style(canvas_div)\n",
" this.root.append(canvas_div);\n",
"\n",
" var canvas = $('<canvas/>');\n",
" canvas.addClass('mpl-canvas');\n",
" canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n",
"\n",
" this.canvas = canvas[0];\n",
" this.context = canvas[0].getContext(\"2d\");\n",
"\n",
" var backingStore = this.context.backingStorePixelRatio ||\n",
"\tthis.context.webkitBackingStorePixelRatio ||\n",
"\tthis.context.mozBackingStorePixelRatio ||\n",
"\tthis.context.msBackingStorePixelRatio ||\n",
"\tthis.context.oBackingStorePixelRatio ||\n",
"\tthis.context.backingStorePixelRatio || 1;\n",
"\n",
" mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n",
"\n",
" var rubberband = $('<canvas/>');\n",
" rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n",
"\n",
" var pass_mouse_events = true;\n",
"\n",
" canvas_div.resizable({\n",
" start: function(event, ui) {\n",
" pass_mouse_events = false;\n",
" },\n",
" resize: function(event, ui) {\n",
" fig.request_resize(ui.size.width, ui.size.height);\n",
" },\n",
" stop: function(event, ui) {\n",
" pass_mouse_events = true;\n",
" fig.request_resize(ui.size.width, ui.size.height);\n",
" },\n",
" });\n",
"\n",
" function mouse_event_fn(event) {\n",
" if (pass_mouse_events)\n",
" return fig.mouse_event(event, event['data']);\n",
" }\n",
"\n",
" rubberband.mousedown('button_press', mouse_event_fn);\n",
" rubberband.mouseup('button_release', mouse_event_fn);\n",
" // Throttle sequential mouse events to 1 every 20ms.\n",
" rubberband.mousemove('motion_notify', mouse_event_fn);\n",
"\n",
" rubberband.mouseenter('figure_enter', mouse_event_fn);\n",
" rubberband.mouseleave('figure_leave', mouse_event_fn);\n",
"\n",
" canvas_div.on(\"wheel\", function (event) {\n",
" event = event.originalEvent;\n",
" event['data'] = 'scroll'\n",
" if (event.deltaY < 0) {\n",
" event.step = 1;\n",
" } else {\n",
" event.step = -1;\n",
" }\n",
" mouse_event_fn(event);\n",
" });\n",
"\n",
" canvas_div.append(canvas);\n",
" canvas_div.append(rubberband);\n",
"\n",
" this.rubberband = rubberband;\n",
" this.rubberband_canvas = rubberband[0];\n",
" this.rubberband_context = rubberband[0].getContext(\"2d\");\n",
" this.rubberband_context.strokeStyle = \"#000000\";\n",
"\n",
" this._resize_canvas = function(width, height) {\n",
" // Keep the size of the canvas, canvas container, and rubber band\n",
" // canvas in synch.\n",
" canvas_div.css('width', width)\n",
" canvas_div.css('height', height)\n",
"\n",
" canvas.attr('width', width * mpl.ratio);\n",
" canvas.attr('height', height * mpl.ratio);\n",
" canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n",
"\n",
" rubberband.attr('width', width);\n",
" rubberband.attr('height', height);\n",
" }\n",
"\n",
" // Set the figure to an initial 600x600px, this will subsequently be updated\n",
" // upon first draw.\n",
" this._resize_canvas(600, 600);\n",
"\n",
" // Disable right mouse context menu.\n",
" $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n",
" return false;\n",
" });\n",
"\n",
" function set_focus () {\n",
" canvas.focus();\n",
" canvas_div.focus();\n",
" }\n",
"\n",
" window.setTimeout(set_focus, 100);\n",
"}\n",
"\n",
"mpl.figure.prototype._init_toolbar = function() {\n",
" var fig = this;\n",
"\n",
" var nav_element = $('<div/>')\n",
" nav_element.attr('style', 'width: 100%');\n",
" this.root.append(nav_element);\n",
"\n",
" // Define a callback function for later on.\n",
" function toolbar_event(event) {\n",
" return fig.toolbar_button_onclick(event['data']);\n",
" }\n",
" function toolbar_mouse_event(event) {\n",
" return fig.toolbar_button_onmouseover(event['data']);\n",
" }\n",
"\n",
" for(var toolbar_ind in mpl.toolbar_items) {\n",
" var name = mpl.toolbar_items[toolbar_ind][0];\n",
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
" var image = mpl.toolbar_items[toolbar_ind][2];\n",
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
"\n",
" if (!name) {\n",
" // put a spacer in here.\n",
" continue;\n",
" }\n",
" var button = $('<button/>');\n",
" button.addClass('ui-button ui-widget ui-state-default ui-corner-all ' +\n",
" 'ui-button-icon-only');\n",
" button.attr('role', 'button');\n",
" button.attr('aria-disabled', 'false');\n",
" button.click(method_name, toolbar_event);\n",
" button.mouseover(tooltip, toolbar_mouse_event);\n",
"\n",
" var icon_img = $('<span/>');\n",
" icon_img.addClass('ui-button-icon-primary ui-icon');\n",
" icon_img.addClass(image);\n",
" icon_img.addClass('ui-corner-all');\n",
"\n",
" var tooltip_span = $('<span/>');\n",
" tooltip_span.addClass('ui-button-text');\n",
" tooltip_span.html(tooltip);\n",
"\n",
" button.append(icon_img);\n",
" button.append(tooltip_span);\n",
"\n",
" nav_element.append(button);\n",
" }\n",
"\n",
" var fmt_picker_span = $('<span/>');\n",
"\n",
" var fmt_picker = $('<select/>');\n",
" fmt_picker.addClass('mpl-toolbar-option ui-widget ui-widget-content');\n",
" fmt_picker_span.append(fmt_picker);\n",
" nav_element.append(fmt_picker_span);\n",
" this.format_dropdown = fmt_picker[0];\n",
"\n",
" for (var ind in mpl.extensions) {\n",
" var fmt = mpl.extensions[ind];\n",
" var option = $(\n",
" '<option/>', {selected: fmt === mpl.default_extension}).html(fmt);\n",
" fmt_picker.append(option)\n",
" }\n",
"\n",
" // Add hover states to the ui-buttons\n",
" $( \".ui-button\" ).hover(\n",
" function() { $(this).addClass(\"ui-state-hover\");},\n",
" function() { $(this).removeClass(\"ui-state-hover\");}\n",
" );\n",
"\n",
" var status_bar = $('<span class=\"mpl-message\"/>');\n",
" nav_element.append(status_bar);\n",
" this.message = status_bar[0];\n",
"}\n",
"\n",
"mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n",
" // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n",
" // which will in turn request a refresh of the image.\n",
" this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n",
"}\n",
"\n",
"mpl.figure.prototype.send_message = function(type, properties) {\n",
" properties['type'] = type;\n",
" properties['figure_id'] = this.id;\n",
" this.ws.send(JSON.stringify(properties));\n",
"}\n",
"\n",
"mpl.figure.prototype.send_draw_message = function() {\n",
" if (!this.waiting) {\n",
" this.waiting = true;\n",
" this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n",
" }\n",
"}\n",
"\n",
"\n",
"mpl.figure.prototype.handle_save = function(fig, msg) {\n",
" var format_dropdown = fig.format_dropdown;\n",
" var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n",
" fig.ondownload(fig, format);\n",
"}\n",
"\n",
"\n",
"mpl.figure.prototype.handle_resize = function(fig, msg) {\n",
" var size = msg['size'];\n",
" if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n",
" fig._resize_canvas(size[0], size[1]);\n",
" fig.send_message(\"refresh\", {});\n",
" };\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n",
" var x0 = msg['x0'] / mpl.ratio;\n",
" var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n",
" var x1 = msg['x1'] / mpl.ratio;\n",
" var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n",
" x0 = Math.floor(x0) + 0.5;\n",
" y0 = Math.floor(y0) + 0.5;\n",
" x1 = Math.floor(x1) + 0.5;\n",
" y1 = Math.floor(y1) + 0.5;\n",
" var min_x = Math.min(x0, x1);\n",
" var min_y = Math.min(y0, y1);\n",
" var width = Math.abs(x1 - x0);\n",
" var height = Math.abs(y1 - y0);\n",
"\n",
" fig.rubberband_context.clearRect(\n",
" 0, 0, fig.canvas.width, fig.canvas.height);\n",
"\n",
" fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n",
" // Updates the figure title.\n",
" fig.header.textContent = msg['label'];\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_cursor = function(fig, msg) {\n",
" var cursor = msg['cursor'];\n",
" switch(cursor)\n",
" {\n",
" case 0:\n",
" cursor = 'pointer';\n",
" break;\n",
" case 1:\n",
" cursor = 'default';\n",
" break;\n",
" case 2:\n",
" cursor = 'crosshair';\n",
" break;\n",
" case 3:\n",
" cursor = 'move';\n",
" break;\n",
" }\n",
" fig.rubberband_canvas.style.cursor = cursor;\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_message = function(fig, msg) {\n",
" fig.message.textContent = msg['message'];\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_draw = function(fig, msg) {\n",
" // Request the server to send over a new figure.\n",
" fig.send_draw_message();\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n",
" fig.image_mode = msg['mode'];\n",
"}\n",
"\n",
"mpl.figure.prototype.updated_canvas_event = function() {\n",
" // Called whenever the canvas gets updated.\n",
" this.send_message(\"ack\", {});\n",
"}\n",
"\n",
"// A function to construct a web socket function for onmessage handling.\n",
"// Called in the figure constructor.\n",
"mpl.figure.prototype._make_on_message_function = function(fig) {\n",
" return function socket_on_message(evt) {\n",
" if (evt.data instanceof Blob) {\n",
" /* FIXME: We get \"Resource interpreted as Image but\n",
" * transferred with MIME type text/plain:\" errors on\n",
" * Chrome. But how to set the MIME type? It doesn't seem\n",
" * to be part of the websocket stream */\n",
" evt.data.type = \"image/png\";\n",
"\n",
" /* Free the memory for the previous frames */\n",
" if (fig.imageObj.src) {\n",
" (window.URL || window.webkitURL).revokeObjectURL(\n",
" fig.imageObj.src);\n",
" }\n",
"\n",
" fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
" evt.data);\n",
" fig.updated_canvas_event();\n",
" fig.waiting = false;\n",
" return;\n",
" }\n",
" else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n",
" fig.imageObj.src = evt.data;\n",
" fig.updated_canvas_event();\n",
" fig.waiting = false;\n",
" return;\n",
" }\n",
"\n",
" var msg = JSON.parse(evt.data);\n",
" var msg_type = msg['type'];\n",
"\n",
" // Call the \"handle_{type}\" callback, which takes\n",
" // the figure and JSON message as its only arguments.\n",
" try {\n",
" var callback = fig[\"handle_\" + msg_type];\n",
" } catch (e) {\n",
" console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n",
" return;\n",
" }\n",
"\n",
" if (callback) {\n",
" try {\n",
" // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n",
" callback(fig, msg);\n",
" } catch (e) {\n",
" console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n",
" }\n",
" }\n",
" };\n",
"}\n",
"\n",
"// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n",
"mpl.findpos = function(e) {\n",
" //this section is from http://www.quirksmode.org/js/events_properties.html\n",
" var targ;\n",
" if (!e)\n",
" e = window.event;\n",
" if (e.target)\n",
" targ = e.target;\n",
" else if (e.srcElement)\n",
" targ = e.srcElement;\n",
" if (targ.nodeType == 3) // defeat Safari bug\n",
" targ = targ.parentNode;\n",
"\n",
" // jQuery normalizes the pageX and pageY\n",
" // pageX,Y are the mouse positions relative to the document\n",
" // offset() returns the position of the element relative to the document\n",
" var x = e.pageX - $(targ).offset().left;\n",
" var y = e.pageY - $(targ).offset().top;\n",
"\n",
" return {\"x\": x, \"y\": y};\n",
"};\n",
"\n",
"/*\n",
" * return a copy of an object with only non-object keys\n",
" * we need this to avoid circular references\n",
" * http://stackoverflow.com/a/24161582/3208463\n",
" */\n",
"function simpleKeys (original) {\n",
" return Object.keys(original).reduce(function (obj, key) {\n",
" if (typeof original[key] !== 'object')\n",
" obj[key] = original[key]\n",
" return obj;\n",
" }, {});\n",
"}\n",
"\n",
"mpl.figure.prototype.mouse_event = function(event, name) {\n",
" var canvas_pos = mpl.findpos(event)\n",
"\n",
" if (name === 'button_press')\n",
" {\n",
" this.canvas.focus();\n",
" this.canvas_div.focus();\n",
" }\n",
"\n",
" var x = canvas_pos.x * mpl.ratio;\n",
" var y = canvas_pos.y * mpl.ratio;\n",
"\n",
" this.send_message(name, {x: x, y: y, button: event.button,\n",
" step: event.step,\n",
" guiEvent: simpleKeys(event)});\n",
"\n",
" /* This prevents the web browser from automatically changing to\n",
" * the text insertion cursor when the button is pressed. We want\n",
" * to control all of the cursor setting manually through the\n",
" * 'cursor' event from matplotlib */\n",
" event.preventDefault();\n",
" return false;\n",
"}\n",
"\n",
"mpl.figure.prototype._key_event_extra = function(event, name) {\n",
" // Handle any extra behaviour associated with a key event\n",
"}\n",
"\n",
"mpl.figure.prototype.key_event = function(event, name) {\n",
"\n",
" // Prevent repeat events\n",
" if (name == 'key_press')\n",
" {\n",
" if (event.which === this._key)\n",
" return;\n",
" else\n",
" this._key = event.which;\n",
" }\n",
" if (name == 'key_release')\n",
" this._key = null;\n",
"\n",
" var value = '';\n",
" if (event.ctrlKey && event.which != 17)\n",
" value += \"ctrl+\";\n",
" if (event.altKey && event.which != 18)\n",
" value += \"alt+\";\n",
" if (event.shiftKey && event.which != 16)\n",
" value += \"shift+\";\n",
"\n",
" value += 'k';\n",
" value += event.which.toString();\n",
"\n",
" this._key_event_extra(event, name);\n",
"\n",
" this.send_message(name, {key: value,\n",
" guiEvent: simpleKeys(event)});\n",
" return false;\n",
"}\n",
"\n",
"mpl.figure.prototype.toolbar_button_onclick = function(name) {\n",
" if (name == 'download') {\n",
" this.handle_save(this, null);\n",
" } else {\n",
" this.send_message(\"toolbar_button\", {name: name});\n",
" }\n",
"};\n",
"\n",
"mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n",
" this.message.textContent = tooltip;\n",
"};\n",
"mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n",
"\n",
"mpl.extensions = [\"eps\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
"\n",
"mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n",
" // Create a \"websocket\"-like object which calls the given IPython comm\n",
" // object with the appropriate methods. Currently this is a non binary\n",
" // socket, so there is still some room for performance tuning.\n",
" var ws = {};\n",
"\n",
" ws.close = function() {\n",
" comm.close()\n",
" };\n",
" ws.send = function(m) {\n",
" //console.log('sending', m);\n",
" comm.send(m);\n",
" };\n",
" // Register the callback with on_msg.\n",
" comm.on_msg(function(msg) {\n",
" //console.log('receiving', msg['content']['data'], msg);\n",
" // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
" ws.onmessage(msg['content']['data'])\n",
" });\n",
" return ws;\n",
"}\n",
"\n",
"mpl.mpl_figure_comm = function(comm, msg) {\n",
" // This is the function which gets called when the mpl process\n",
" // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
"\n",
" var id = msg.content.data.id;\n",
" // Get hold of the div created by the display call when the Comm\n",
" // socket was opened in Python.\n",
" var element = $(\"#\" + id);\n",
" var ws_proxy = comm_websocket_adapter(comm)\n",
"\n",
" function ondownload(figure, format) {\n",
" window.open(figure.imageObj.src);\n",
" }\n",
"\n",
" var fig = new mpl.figure(id, ws_proxy,\n",
" ondownload,\n",
" element.get(0));\n",
"\n",
" // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n",
" // web socket which is closed, not our websocket->open comm proxy.\n",
" ws_proxy.onopen();\n",
"\n",
" fig.parent_element = element.get(0);\n",
" fig.cell_info = mpl.find_output_cell(\"<div id='\" + id + \"'></div>\");\n",
" if (!fig.cell_info) {\n",
" console.error(\"Failed to find cell for figure\", id, fig);\n",
" return;\n",
" }\n",
"\n",
" var output_index = fig.cell_info[2]\n",
" var cell = fig.cell_info[0];\n",
"\n",
"};\n",
"\n",
"mpl.figure.prototype.handle_close = function(fig, msg) {\n",
" var width = fig.canvas.width/mpl.ratio\n",
" fig.root.unbind('remove')\n",
"\n",
" // Update the output cell to use the data from the current canvas.\n",
" fig.push_to_output();\n",
" var dataURL = fig.canvas.toDataURL();\n",
" // Re-enable the keyboard manager in IPython - without this line, in FF,\n",
" // the notebook keyboard shortcuts fail.\n",
" IPython.keyboard_manager.enable()\n",
" $(fig.parent_element).html('<img src=\"' + dataURL + '\" width=\"' + width + '\">');\n",
" fig.close_ws(fig, msg);\n",
"}\n",
"\n",
"mpl.figure.prototype.close_ws = function(fig, msg){\n",
" fig.send_message('closing', msg);\n",
" // fig.ws.close()\n",
"}\n",
"\n",
"mpl.figure.prototype.push_to_output = function(remove_interactive) {\n",
" // Turn the data on the canvas into data in the output cell.\n",
" var width = this.canvas.width/mpl.ratio\n",
" var dataURL = this.canvas.toDataURL();\n",
" this.cell_info[1]['text/html'] = '<img src=\"' + dataURL + '\" width=\"' + width + '\">';\n",
"}\n",
"\n",
"mpl.figure.prototype.updated_canvas_event = function() {\n",
" // Tell IPython that the notebook contents must change.\n",
" IPython.notebook.set_dirty(true);\n",
" this.send_message(\"ack\", {});\n",
" var fig = this;\n",
" // Wait a second, then push the new image to the DOM so\n",
" // that it is saved nicely (might be nice to debounce this).\n",
" setTimeout(function () { fig.push_to_output() }, 1000);\n",
"}\n",
"\n",
"mpl.figure.prototype._init_toolbar = function() {\n",
" var fig = this;\n",
"\n",
" var nav_element = $('<div/>')\n",
" nav_element.attr('style', 'width: 100%');\n",
" this.root.append(nav_element);\n",
"\n",
" // Define a callback function for later on.\n",
" function toolbar_event(event) {\n",
" return fig.toolbar_button_onclick(event['data']);\n",
" }\n",
" function toolbar_mouse_event(event) {\n",
" return fig.toolbar_button_onmouseover(event['data']);\n",
" }\n",
"\n",
" for(var toolbar_ind in mpl.toolbar_items){\n",
" var name = mpl.toolbar_items[toolbar_ind][0];\n",
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
" var image = mpl.toolbar_items[toolbar_ind][2];\n",
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
"\n",
" if (!name) { continue; };\n",
"\n",
" var button = $('<button class=\"btn btn-default\" href=\"#\" title=\"' + name + '\"><i class=\"fa ' + image + ' fa-lg\"></i></button>');\n",
" button.click(method_name, toolbar_event);\n",
" button.mouseover(tooltip, toolbar_mouse_event);\n",
" nav_element.append(button);\n",
" }\n",
"\n",
" // Add the status bar.\n",
" var status_bar = $('<span class=\"mpl-message\" style=\"text-align:right; float: right;\"/>');\n",
" nav_element.append(status_bar);\n",
" this.message = status_bar[0];\n",
"\n",
" // Add the close button to the window.\n",
" var buttongrp = $('<div class=\"btn-group inline pull-right\"></div>');\n",
" var button = $('<button class=\"btn btn-mini btn-primary\" href=\"#\" title=\"Stop Interaction\"><i class=\"fa fa-power-off icon-remove icon-large\"></i></button>');\n",
" button.click(function (evt) { fig.handle_close(fig, {}); } );\n",
" button.mouseover('Stop Interaction', toolbar_mouse_event);\n",
" buttongrp.append(button);\n",
" var titlebar = this.root.find($('.ui-dialog-titlebar'));\n",
" titlebar.prepend(buttongrp);\n",
"}\n",
"\n",
"mpl.figure.prototype._root_extra_style = function(el){\n",
" var fig = this\n",
" el.on(\"remove\", function(){\n",
"\tfig.close_ws(fig, {});\n",
" });\n",
"}\n",
"\n",
"mpl.figure.prototype._canvas_extra_style = function(el){\n",
" // this is important to make the div 'focusable\n",
" el.attr('tabindex', 0)\n",
" // reach out to IPython and tell the keyboard manager to turn it's self\n",
" // off when our div gets focus\n",
"\n",
" // location in version 3\n",
" if (IPython.notebook.keyboard_manager) {\n",
" IPython.notebook.keyboard_manager.register_events(el);\n",
" }\n",
" else {\n",
" // location in version 2\n",
" IPython.keyboard_manager.register_events(el);\n",
" }\n",
"\n",
"}\n",
"\n",
"mpl.figure.prototype._key_event_extra = function(event, name) {\n",
" var manager = IPython.notebook.keyboard_manager;\n",
" if (!manager)\n",
" manager = IPython.keyboard_manager;\n",
"\n",
" // Check for shift+enter\n",
" if (event.shiftKey && event.which == 13) {\n",
" this.canvas_div.blur();\n",
" event.shiftKey = false;\n",
" // Send a \"J\" for go to next cell\n",
" event.which = 74;\n",
" event.keyCode = 74;\n",
" manager.command_mode();\n",
" manager.handle_keydown(event);\n",
" }\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_save = function(fig, msg) {\n",
" fig.ondownload(fig, null);\n",
"}\n",
"\n",
"\n",
"mpl.find_output_cell = function(html_output) {\n",
" // Return the cell and output element which can be found *uniquely* in the notebook.\n",
" // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n",
" // IPython event is triggered only after the cells have been serialised, which for\n",
" // our purposes (turning an active figure into a static one), is too late.\n",
" var cells = IPython.notebook.get_cells();\n",
" var ncells = cells.length;\n",
" for (var i=0; i<ncells; i++) {\n",
" var cell = cells[i];\n",
" if (cell.cell_type === 'code'){\n",
" for (var j=0; j<cell.output_area.outputs.length; j++) {\n",
" var data = cell.output_area.outputs[j];\n",
" if (data.data) {\n",
" // IPython >= 3 moved mimebundle to data attribute of output\n",
" data = data.data;\n",
" }\n",
" if (data['text/html'] == html_output) {\n",
" return [cell, data, j];\n",
" }\n",
" }\n",
" }\n",
" }\n",
"}\n",
"\n",
"// Register the function which deals with the matplotlib target/channel.\n",
"// The kernel may be null if the page has been refreshed.\n",
"if (IPython.notebook.kernel != null) {\n",
" IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n",
"}\n"
],
"text/plain": [
"<IPython.core.display.Javascript object>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"<img src=\"data:image/png;base64,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\" width=\"720\">"
],
"text/plain": [
"<IPython.core.display.HTML object>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"HBox(children=(IntProgress(value=0, max=2), HTML(value='')))"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"HBox(children=(IntProgress(value=0, max=5633), HTML(value='')))"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"HBox(children=(IntProgress(value=0, max=7009), HTML(value='')))"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'loss': 0.212038938213553, 'val_loss': 0.1112252275226538}\n"
]
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"HBox(children=(IntProgress(value=0, max=5633), HTML(value='')))"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"HBox(children=(IntProgress(value=0, max=7009), HTML(value='')))"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'loss': 0.1739646898146159, 'val_loss': 0.10833032741023337}\n",
"\n",
"0.10833032741023337\n"
]
}
],
"source": [
"%matplotlib nbagg\n",
"\n",
"num_split=0\n",
"np.random.seed(SEED+num_split)\n",
"torch.manual_seed(SEED+num_split)\n",
"torch.cuda.manual_seed(SEED+num_split)\n",
"#torch.backends.cudnn.deterministic = True\n",
"idx_train = train_df[train_df.PID.isin(set(split_sid[splits[num_split][0]]))].index.values\n",
"idx_validate = train_df[train_df.PID.isin(set(split_sid[splits[num_split][1]]))].index.values\n",
"idx_train.shape\n",
"idx_validate.shape\n",
"\n",
"klr=1\n",
"batch_size=32\n",
"num_workers=12\n",
"num_epochs=2\n",
"model_name,version = 'Densenet161_3' , 'basic_splits'\n",
"model = MyDenseNet(models.densenet161(pretrained=True),\n",
" len(hemorrhage_types),\n",
" num_channels=3,\n",
" drop_out=0.2,\n",
" wso=((40,80),(80,200),(600,2800)),\n",
" strategy='none',\n",
" dont_do_grad=[],\n",
" extra_pool=4,\n",
" )\n",
"\n",
"_=model.to(device)\n",
"weights = torch.tensor([1.,1.,1.,1.,1.,2.],device=device)\n",
"loss_func=my_loss\n",
"targets_dataset=D.TensorDataset(torch.tensor(train_df[hemorrhage_types].values,dtype=torch.float))\n",
"transform=MyTransform(flip=True,zoom=0.05,rotate=15,out_size=512,shift=40)\n",
"imagedataset = ImageDataset(train_df,transform=transform.random,base_path=train_images_dir,\n",
" window_eq=False,equalize=False,rescale=True)\n",
"transform_val=MyTransform(out_size=512)\n",
"imagedataset_val = ImageDataset(train_df,transform=transform_val.random,base_path=train_images_dir,\n",
" window_eq=False,equalize=False,rescale=True)\n",
"combined_dataset=DatasetCat([imagedataset,targets_dataset])\n",
"combined_dataset_val=DatasetCat([imagedataset_val,targets_dataset])\n",
"#param_s=parameter_scheduler(model,num_epoch=0)\n",
"optimizer_grouped_parameters=get_optimizer_parameters(model,klr)\n",
"sampling=sampler(train_df[hemorrhage_types].values[idx_train],0.2,[10,1,1,1,1,0])\n",
"sample_ratio=1.02*float(sampling().shape[0])/idx_train.shape[0]\n",
"train_dataset=D.Subset(combined_dataset,idx_train)\n",
"validate_dataset=D.Subset(combined_dataset_val,idx_validate)\n",
"num_train_optimization_steps = num_epochs*(sample_ratio*len(train_dataset)//batch_size+int(len(train_dataset)%batch_size>0))\n",
"fig,ax = plt.subplots(figsize=(10,7))\n",
"gr=loss_graph(fig,ax,num_epochs,int(num_train_optimization_steps/num_epochs)+1,limits=[0.05,0.4])\n",
"sched=WarmupExpCosineWithWarmupRestartsSchedule( t_total=num_train_optimization_steps, cycles=num_epochs//2,tau=1)\n",
"optimizer = BertAdam(optimizer_grouped_parameters,lr=klr*1e-3,schedule=sched)\n",
"model, optimizer = amp.initialize(model, optimizer, opt_level=\"O1\",verbosity=0)\n",
"history,best_model= model_train(model,\n",
" optimizer,\n",
" train_dataset,\n",
" batch_size,\n",
" num_epochs,\n",
" loss_func,\n",
" weights=weights,\n",
" do_apex=False,\n",
" model_apexed=True,\n",
" validate_dataset=validate_dataset,\n",
" param_schedualer=None,\n",
" weights_data=None,\n",
" metric=None,\n",
" return_model=True,\n",
" num_workers=num_workers,\n",
" sampler=sampling,\n",
" graph=gr,\n",
" call_progress=sendmeemail)\n",
"torch.save(model.state_dict(), models_dir+models_format.format(model_name,version,num_split))\n",
"torch.save(best_model.state_dict(), models_dir+models_format.format(model_name,version+'_best',num_split))"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<torch._C.Generator at 0x7f06349ec5d0>"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"text/plain": [
"(449982,)"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"text/plain": [
"(224270,)"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"text/plain": [
"<All keys matched successfully>"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"application/javascript": [
"/* Put everything inside the global mpl namespace */\n",
"window.mpl = {};\n",
"\n",
"\n",
"mpl.get_websocket_type = function() {\n",
" if (typeof(WebSocket) !== 'undefined') {\n",
" return WebSocket;\n",
" } else if (typeof(MozWebSocket) !== 'undefined') {\n",
" return MozWebSocket;\n",
" } else {\n",
" alert('Your browser does not have WebSocket support.' +\n",
" 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
" 'Firefox 4 and 5 are also supported but you ' +\n",
" 'have to enable WebSockets in about:config.');\n",
" };\n",
"}\n",
"\n",
"mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n",
" this.id = figure_id;\n",
"\n",
" this.ws = websocket;\n",
"\n",
" this.supports_binary = (this.ws.binaryType != undefined);\n",
"\n",
" if (!this.supports_binary) {\n",
" var warnings = document.getElementById(\"mpl-warnings\");\n",
" if (warnings) {\n",
" warnings.style.display = 'block';\n",
" warnings.textContent = (\n",
" \"This browser does not support binary websocket messages. \" +\n",
" \"Performance may be slow.\");\n",
" }\n",
" }\n",
"\n",
" this.imageObj = new Image();\n",
"\n",
" this.context = undefined;\n",
" this.message = undefined;\n",
" this.canvas = undefined;\n",
" this.rubberband_canvas = undefined;\n",
" this.rubberband_context = undefined;\n",
" this.format_dropdown = undefined;\n",
"\n",
" this.image_mode = 'full';\n",
"\n",
" this.root = $('<div/>');\n",
" this._root_extra_style(this.root)\n",
" this.root.attr('style', 'display: inline-block');\n",
"\n",
" $(parent_element).append(this.root);\n",
"\n",
" this._init_header(this);\n",
" this._init_canvas(this);\n",
" this._init_toolbar(this);\n",
"\n",
" var fig = this;\n",
"\n",
" this.waiting = false;\n",
"\n",
" this.ws.onopen = function () {\n",
" fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n",
" fig.send_message(\"send_image_mode\", {});\n",
" if (mpl.ratio != 1) {\n",
" fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n",
" }\n",
" fig.send_message(\"refresh\", {});\n",
" }\n",
"\n",
" this.imageObj.onload = function() {\n",
" if (fig.image_mode == 'full') {\n",
" // Full images could contain transparency (where diff images\n",
" // almost always do), so we need to clear the canvas so that\n",
" // there is no ghosting.\n",
" fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
" }\n",
" fig.context.drawImage(fig.imageObj, 0, 0);\n",
" };\n",
"\n",
" this.imageObj.onunload = function() {\n",
" fig.ws.close();\n",
" }\n",
"\n",
" this.ws.onmessage = this._make_on_message_function(this);\n",
"\n",
" this.ondownload = ondownload;\n",
"}\n",
"\n",
"mpl.figure.prototype._init_header = function() {\n",
" var titlebar = $(\n",
" '<div class=\"ui-dialog-titlebar ui-widget-header ui-corner-all ' +\n",
" 'ui-helper-clearfix\"/>');\n",
" var titletext = $(\n",
" '<div class=\"ui-dialog-title\" style=\"width: 100%; ' +\n",
" 'text-align: center; padding: 3px;\"/>');\n",
" titlebar.append(titletext)\n",
" this.root.append(titlebar);\n",
" this.header = titletext[0];\n",
"}\n",
"\n",
"\n",
"\n",
"mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n",
"\n",
"}\n",
"\n",
"\n",
"mpl.figure.prototype._root_extra_style = function(canvas_div) {\n",
"\n",
"}\n",
"\n",
"mpl.figure.prototype._init_canvas = function() {\n",
" var fig = this;\n",
"\n",
" var canvas_div = $('<div/>');\n",
"\n",
" canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n",
"\n",
" function canvas_keyboard_event(event) {\n",
" return fig.key_event(event, event['data']);\n",
" }\n",
"\n",
" canvas_div.keydown('key_press', canvas_keyboard_event);\n",
" canvas_div.keyup('key_release', canvas_keyboard_event);\n",
" this.canvas_div = canvas_div\n",
" this._canvas_extra_style(canvas_div)\n",
" this.root.append(canvas_div);\n",
"\n",
" var canvas = $('<canvas/>');\n",
" canvas.addClass('mpl-canvas');\n",
" canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n",
"\n",
" this.canvas = canvas[0];\n",
" this.context = canvas[0].getContext(\"2d\");\n",
"\n",
" var backingStore = this.context.backingStorePixelRatio ||\n",
"\tthis.context.webkitBackingStorePixelRatio ||\n",
"\tthis.context.mozBackingStorePixelRatio ||\n",
"\tthis.context.msBackingStorePixelRatio ||\n",
"\tthis.context.oBackingStorePixelRatio ||\n",
"\tthis.context.backingStorePixelRatio || 1;\n",
"\n",
" mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n",
"\n",
" var rubberband = $('<canvas/>');\n",
" rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n",
"\n",
" var pass_mouse_events = true;\n",
"\n",
" canvas_div.resizable({\n",
" start: function(event, ui) {\n",
" pass_mouse_events = false;\n",
" },\n",
" resize: function(event, ui) {\n",
" fig.request_resize(ui.size.width, ui.size.height);\n",
" },\n",
" stop: function(event, ui) {\n",
" pass_mouse_events = true;\n",
" fig.request_resize(ui.size.width, ui.size.height);\n",
" },\n",
" });\n",
"\n",
" function mouse_event_fn(event) {\n",
" if (pass_mouse_events)\n",
" return fig.mouse_event(event, event['data']);\n",
" }\n",
"\n",
" rubberband.mousedown('button_press', mouse_event_fn);\n",
" rubberband.mouseup('button_release', mouse_event_fn);\n",
" // Throttle sequential mouse events to 1 every 20ms.\n",
" rubberband.mousemove('motion_notify', mouse_event_fn);\n",
"\n",
" rubberband.mouseenter('figure_enter', mouse_event_fn);\n",
" rubberband.mouseleave('figure_leave', mouse_event_fn);\n",
"\n",
" canvas_div.on(\"wheel\", function (event) {\n",
" event = event.originalEvent;\n",
" event['data'] = 'scroll'\n",
" if (event.deltaY < 0) {\n",
" event.step = 1;\n",
" } else {\n",
" event.step = -1;\n",
" }\n",
" mouse_event_fn(event);\n",
" });\n",
"\n",
" canvas_div.append(canvas);\n",
" canvas_div.append(rubberband);\n",
"\n",
" this.rubberband = rubberband;\n",
" this.rubberband_canvas = rubberband[0];\n",
" this.rubberband_context = rubberband[0].getContext(\"2d\");\n",
" this.rubberband_context.strokeStyle = \"#000000\";\n",
"\n",
" this._resize_canvas = function(width, height) {\n",
" // Keep the size of the canvas, canvas container, and rubber band\n",
" // canvas in synch.\n",
" canvas_div.css('width', width)\n",
" canvas_div.css('height', height)\n",
"\n",
" canvas.attr('width', width * mpl.ratio);\n",
" canvas.attr('height', height * mpl.ratio);\n",
" canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n",
"\n",
" rubberband.attr('width', width);\n",
" rubberband.attr('height', height);\n",
" }\n",
"\n",
" // Set the figure to an initial 600x600px, this will subsequently be updated\n",
" // upon first draw.\n",
" this._resize_canvas(600, 600);\n",
"\n",
" // Disable right mouse context menu.\n",
" $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n",
" return false;\n",
" });\n",
"\n",
" function set_focus () {\n",
" canvas.focus();\n",
" canvas_div.focus();\n",
" }\n",
"\n",
" window.setTimeout(set_focus, 100);\n",
"}\n",
"\n",
"mpl.figure.prototype._init_toolbar = function() {\n",
" var fig = this;\n",
"\n",
" var nav_element = $('<div/>')\n",
" nav_element.attr('style', 'width: 100%');\n",
" this.root.append(nav_element);\n",
"\n",
" // Define a callback function for later on.\n",
" function toolbar_event(event) {\n",
" return fig.toolbar_button_onclick(event['data']);\n",
" }\n",
" function toolbar_mouse_event(event) {\n",
" return fig.toolbar_button_onmouseover(event['data']);\n",
" }\n",
"\n",
" for(var toolbar_ind in mpl.toolbar_items) {\n",
" var name = mpl.toolbar_items[toolbar_ind][0];\n",
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
" var image = mpl.toolbar_items[toolbar_ind][2];\n",
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
"\n",
" if (!name) {\n",
" // put a spacer in here.\n",
" continue;\n",
" }\n",
" var button = $('<button/>');\n",
" button.addClass('ui-button ui-widget ui-state-default ui-corner-all ' +\n",
" 'ui-button-icon-only');\n",
" button.attr('role', 'button');\n",
" button.attr('aria-disabled', 'false');\n",
" button.click(method_name, toolbar_event);\n",
" button.mouseover(tooltip, toolbar_mouse_event);\n",
"\n",
" var icon_img = $('<span/>');\n",
" icon_img.addClass('ui-button-icon-primary ui-icon');\n",
" icon_img.addClass(image);\n",
" icon_img.addClass('ui-corner-all');\n",
"\n",
" var tooltip_span = $('<span/>');\n",
" tooltip_span.addClass('ui-button-text');\n",
" tooltip_span.html(tooltip);\n",
"\n",
" button.append(icon_img);\n",
" button.append(tooltip_span);\n",
"\n",
" nav_element.append(button);\n",
" }\n",
"\n",
" var fmt_picker_span = $('<span/>');\n",
"\n",
" var fmt_picker = $('<select/>');\n",
" fmt_picker.addClass('mpl-toolbar-option ui-widget ui-widget-content');\n",
" fmt_picker_span.append(fmt_picker);\n",
" nav_element.append(fmt_picker_span);\n",
" this.format_dropdown = fmt_picker[0];\n",
"\n",
" for (var ind in mpl.extensions) {\n",
" var fmt = mpl.extensions[ind];\n",
" var option = $(\n",
" '<option/>', {selected: fmt === mpl.default_extension}).html(fmt);\n",
" fmt_picker.append(option)\n",
" }\n",
"\n",
" // Add hover states to the ui-buttons\n",
" $( \".ui-button\" ).hover(\n",
" function() { $(this).addClass(\"ui-state-hover\");},\n",
" function() { $(this).removeClass(\"ui-state-hover\");}\n",
" );\n",
"\n",
" var status_bar = $('<span class=\"mpl-message\"/>');\n",
" nav_element.append(status_bar);\n",
" this.message = status_bar[0];\n",
"}\n",
"\n",
"mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n",
" // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n",
" // which will in turn request a refresh of the image.\n",
" this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n",
"}\n",
"\n",
"mpl.figure.prototype.send_message = function(type, properties) {\n",
" properties['type'] = type;\n",
" properties['figure_id'] = this.id;\n",
" this.ws.send(JSON.stringify(properties));\n",
"}\n",
"\n",
"mpl.figure.prototype.send_draw_message = function() {\n",
" if (!this.waiting) {\n",
" this.waiting = true;\n",
" this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n",
" }\n",
"}\n",
"\n",
"\n",
"mpl.figure.prototype.handle_save = function(fig, msg) {\n",
" var format_dropdown = fig.format_dropdown;\n",
" var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n",
" fig.ondownload(fig, format);\n",
"}\n",
"\n",
"\n",
"mpl.figure.prototype.handle_resize = function(fig, msg) {\n",
" var size = msg['size'];\n",
" if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n",
" fig._resize_canvas(size[0], size[1]);\n",
" fig.send_message(\"refresh\", {});\n",
" };\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n",
" var x0 = msg['x0'] / mpl.ratio;\n",
" var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n",
" var x1 = msg['x1'] / mpl.ratio;\n",
" var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n",
" x0 = Math.floor(x0) + 0.5;\n",
" y0 = Math.floor(y0) + 0.5;\n",
" x1 = Math.floor(x1) + 0.5;\n",
" y1 = Math.floor(y1) + 0.5;\n",
" var min_x = Math.min(x0, x1);\n",
" var min_y = Math.min(y0, y1);\n",
" var width = Math.abs(x1 - x0);\n",
" var height = Math.abs(y1 - y0);\n",
"\n",
" fig.rubberband_context.clearRect(\n",
" 0, 0, fig.canvas.width, fig.canvas.height);\n",
"\n",
" fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n",
" // Updates the figure title.\n",
" fig.header.textContent = msg['label'];\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_cursor = function(fig, msg) {\n",
" var cursor = msg['cursor'];\n",
" switch(cursor)\n",
" {\n",
" case 0:\n",
" cursor = 'pointer';\n",
" break;\n",
" case 1:\n",
" cursor = 'default';\n",
" break;\n",
" case 2:\n",
" cursor = 'crosshair';\n",
" break;\n",
" case 3:\n",
" cursor = 'move';\n",
" break;\n",
" }\n",
" fig.rubberband_canvas.style.cursor = cursor;\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_message = function(fig, msg) {\n",
" fig.message.textContent = msg['message'];\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_draw = function(fig, msg) {\n",
" // Request the server to send over a new figure.\n",
" fig.send_draw_message();\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n",
" fig.image_mode = msg['mode'];\n",
"}\n",
"\n",
"mpl.figure.prototype.updated_canvas_event = function() {\n",
" // Called whenever the canvas gets updated.\n",
" this.send_message(\"ack\", {});\n",
"}\n",
"\n",
"// A function to construct a web socket function for onmessage handling.\n",
"// Called in the figure constructor.\n",
"mpl.figure.prototype._make_on_message_function = function(fig) {\n",
" return function socket_on_message(evt) {\n",
" if (evt.data instanceof Blob) {\n",
" /* FIXME: We get \"Resource interpreted as Image but\n",
" * transferred with MIME type text/plain:\" errors on\n",
" * Chrome. But how to set the MIME type? It doesn't seem\n",
" * to be part of the websocket stream */\n",
" evt.data.type = \"image/png\";\n",
"\n",
" /* Free the memory for the previous frames */\n",
" if (fig.imageObj.src) {\n",
" (window.URL || window.webkitURL).revokeObjectURL(\n",
" fig.imageObj.src);\n",
" }\n",
"\n",
" fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
" evt.data);\n",
" fig.updated_canvas_event();\n",
" fig.waiting = false;\n",
" return;\n",
" }\n",
" else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n",
" fig.imageObj.src = evt.data;\n",
" fig.updated_canvas_event();\n",
" fig.waiting = false;\n",
" return;\n",
" }\n",
"\n",
" var msg = JSON.parse(evt.data);\n",
" var msg_type = msg['type'];\n",
"\n",
" // Call the \"handle_{type}\" callback, which takes\n",
" // the figure and JSON message as its only arguments.\n",
" try {\n",
" var callback = fig[\"handle_\" + msg_type];\n",
" } catch (e) {\n",
" console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n",
" return;\n",
" }\n",
"\n",
" if (callback) {\n",
" try {\n",
" // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n",
" callback(fig, msg);\n",
" } catch (e) {\n",
" console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n",
" }\n",
" }\n",
" };\n",
"}\n",
"\n",
"// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n",
"mpl.findpos = function(e) {\n",
" //this section is from http://www.quirksmode.org/js/events_properties.html\n",
" var targ;\n",
" if (!e)\n",
" e = window.event;\n",
" if (e.target)\n",
" targ = e.target;\n",
" else if (e.srcElement)\n",
" targ = e.srcElement;\n",
" if (targ.nodeType == 3) // defeat Safari bug\n",
" targ = targ.parentNode;\n",
"\n",
" // jQuery normalizes the pageX and pageY\n",
" // pageX,Y are the mouse positions relative to the document\n",
" // offset() returns the position of the element relative to the document\n",
" var x = e.pageX - $(targ).offset().left;\n",
" var y = e.pageY - $(targ).offset().top;\n",
"\n",
" return {\"x\": x, \"y\": y};\n",
"};\n",
"\n",
"/*\n",
" * return a copy of an object with only non-object keys\n",
" * we need this to avoid circular references\n",
" * http://stackoverflow.com/a/24161582/3208463\n",
" */\n",
"function simpleKeys (original) {\n",
" return Object.keys(original).reduce(function (obj, key) {\n",
" if (typeof original[key] !== 'object')\n",
" obj[key] = original[key]\n",
" return obj;\n",
" }, {});\n",
"}\n",
"\n",
"mpl.figure.prototype.mouse_event = function(event, name) {\n",
" var canvas_pos = mpl.findpos(event)\n",
"\n",
" if (name === 'button_press')\n",
" {\n",
" this.canvas.focus();\n",
" this.canvas_div.focus();\n",
" }\n",
"\n",
" var x = canvas_pos.x * mpl.ratio;\n",
" var y = canvas_pos.y * mpl.ratio;\n",
"\n",
" this.send_message(name, {x: x, y: y, button: event.button,\n",
" step: event.step,\n",
" guiEvent: simpleKeys(event)});\n",
"\n",
" /* This prevents the web browser from automatically changing to\n",
" * the text insertion cursor when the button is pressed. We want\n",
" * to control all of the cursor setting manually through the\n",
" * 'cursor' event from matplotlib */\n",
" event.preventDefault();\n",
" return false;\n",
"}\n",
"\n",
"mpl.figure.prototype._key_event_extra = function(event, name) {\n",
" // Handle any extra behaviour associated with a key event\n",
"}\n",
"\n",
"mpl.figure.prototype.key_event = function(event, name) {\n",
"\n",
" // Prevent repeat events\n",
" if (name == 'key_press')\n",
" {\n",
" if (event.which === this._key)\n",
" return;\n",
" else\n",
" this._key = event.which;\n",
" }\n",
" if (name == 'key_release')\n",
" this._key = null;\n",
"\n",
" var value = '';\n",
" if (event.ctrlKey && event.which != 17)\n",
" value += \"ctrl+\";\n",
" if (event.altKey && event.which != 18)\n",
" value += \"alt+\";\n",
" if (event.shiftKey && event.which != 16)\n",
" value += \"shift+\";\n",
"\n",
" value += 'k';\n",
" value += event.which.toString();\n",
"\n",
" this._key_event_extra(event, name);\n",
"\n",
" this.send_message(name, {key: value,\n",
" guiEvent: simpleKeys(event)});\n",
" return false;\n",
"}\n",
"\n",
"mpl.figure.prototype.toolbar_button_onclick = function(name) {\n",
" if (name == 'download') {\n",
" this.handle_save(this, null);\n",
" } else {\n",
" this.send_message(\"toolbar_button\", {name: name});\n",
" }\n",
"};\n",
"\n",
"mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n",
" this.message.textContent = tooltip;\n",
"};\n",
"mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n",
"\n",
"mpl.extensions = [\"eps\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
"\n",
"mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n",
" // Create a \"websocket\"-like object which calls the given IPython comm\n",
" // object with the appropriate methods. Currently this is a non binary\n",
" // socket, so there is still some room for performance tuning.\n",
" var ws = {};\n",
"\n",
" ws.close = function() {\n",
" comm.close()\n",
" };\n",
" ws.send = function(m) {\n",
" //console.log('sending', m);\n",
" comm.send(m);\n",
" };\n",
" // Register the callback with on_msg.\n",
" comm.on_msg(function(msg) {\n",
" //console.log('receiving', msg['content']['data'], msg);\n",
" // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
" ws.onmessage(msg['content']['data'])\n",
" });\n",
" return ws;\n",
"}\n",
"\n",
"mpl.mpl_figure_comm = function(comm, msg) {\n",
" // This is the function which gets called when the mpl process\n",
" // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
"\n",
" var id = msg.content.data.id;\n",
" // Get hold of the div created by the display call when the Comm\n",
" // socket was opened in Python.\n",
" var element = $(\"#\" + id);\n",
" var ws_proxy = comm_websocket_adapter(comm)\n",
"\n",
" function ondownload(figure, format) {\n",
" window.open(figure.imageObj.src);\n",
" }\n",
"\n",
" var fig = new mpl.figure(id, ws_proxy,\n",
" ondownload,\n",
" element.get(0));\n",
"\n",
" // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n",
" // web socket which is closed, not our websocket->open comm proxy.\n",
" ws_proxy.onopen();\n",
"\n",
" fig.parent_element = element.get(0);\n",
" fig.cell_info = mpl.find_output_cell(\"<div id='\" + id + \"'></div>\");\n",
" if (!fig.cell_info) {\n",
" console.error(\"Failed to find cell for figure\", id, fig);\n",
" return;\n",
" }\n",
"\n",
" var output_index = fig.cell_info[2]\n",
" var cell = fig.cell_info[0];\n",
"\n",
"};\n",
"\n",
"mpl.figure.prototype.handle_close = function(fig, msg) {\n",
" var width = fig.canvas.width/mpl.ratio\n",
" fig.root.unbind('remove')\n",
"\n",
" // Update the output cell to use the data from the current canvas.\n",
" fig.push_to_output();\n",
" var dataURL = fig.canvas.toDataURL();\n",
" // Re-enable the keyboard manager in IPython - without this line, in FF,\n",
" // the notebook keyboard shortcuts fail.\n",
" IPython.keyboard_manager.enable()\n",
" $(fig.parent_element).html('<img src=\"' + dataURL + '\" width=\"' + width + '\">');\n",
" fig.close_ws(fig, msg);\n",
"}\n",
"\n",
"mpl.figure.prototype.close_ws = function(fig, msg){\n",
" fig.send_message('closing', msg);\n",
" // fig.ws.close()\n",
"}\n",
"\n",
"mpl.figure.prototype.push_to_output = function(remove_interactive) {\n",
" // Turn the data on the canvas into data in the output cell.\n",
" var width = this.canvas.width/mpl.ratio\n",
" var dataURL = this.canvas.toDataURL();\n",
" this.cell_info[1]['text/html'] = '<img src=\"' + dataURL + '\" width=\"' + width + '\">';\n",
"}\n",
"\n",
"mpl.figure.prototype.updated_canvas_event = function() {\n",
" // Tell IPython that the notebook contents must change.\n",
" IPython.notebook.set_dirty(true);\n",
" this.send_message(\"ack\", {});\n",
" var fig = this;\n",
" // Wait a second, then push the new image to the DOM so\n",
" // that it is saved nicely (might be nice to debounce this).\n",
" setTimeout(function () { fig.push_to_output() }, 1000);\n",
"}\n",
"\n",
"mpl.figure.prototype._init_toolbar = function() {\n",
" var fig = this;\n",
"\n",
" var nav_element = $('<div/>')\n",
" nav_element.attr('style', 'width: 100%');\n",
" this.root.append(nav_element);\n",
"\n",
" // Define a callback function for later on.\n",
" function toolbar_event(event) {\n",
" return fig.toolbar_button_onclick(event['data']);\n",
" }\n",
" function toolbar_mouse_event(event) {\n",
" return fig.toolbar_button_onmouseover(event['data']);\n",
" }\n",
"\n",
" for(var toolbar_ind in mpl.toolbar_items){\n",
" var name = mpl.toolbar_items[toolbar_ind][0];\n",
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
" var image = mpl.toolbar_items[toolbar_ind][2];\n",
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
"\n",
" if (!name) { continue; };\n",
"\n",
" var button = $('<button class=\"btn btn-default\" href=\"#\" title=\"' + name + '\"><i class=\"fa ' + image + ' fa-lg\"></i></button>');\n",
" button.click(method_name, toolbar_event);\n",
" button.mouseover(tooltip, toolbar_mouse_event);\n",
" nav_element.append(button);\n",
" }\n",
"\n",
" // Add the status bar.\n",
" var status_bar = $('<span class=\"mpl-message\" style=\"text-align:right; float: right;\"/>');\n",
" nav_element.append(status_bar);\n",
" this.message = status_bar[0];\n",
"\n",
" // Add the close button to the window.\n",
" var buttongrp = $('<div class=\"btn-group inline pull-right\"></div>');\n",
" var button = $('<button class=\"btn btn-mini btn-primary\" href=\"#\" title=\"Stop Interaction\"><i class=\"fa fa-power-off icon-remove icon-large\"></i></button>');\n",
" button.click(function (evt) { fig.handle_close(fig, {}); } );\n",
" button.mouseover('Stop Interaction', toolbar_mouse_event);\n",
" buttongrp.append(button);\n",
" var titlebar = this.root.find($('.ui-dialog-titlebar'));\n",
" titlebar.prepend(buttongrp);\n",
"}\n",
"\n",
"mpl.figure.prototype._root_extra_style = function(el){\n",
" var fig = this\n",
" el.on(\"remove\", function(){\n",
"\tfig.close_ws(fig, {});\n",
" });\n",
"}\n",
"\n",
"mpl.figure.prototype._canvas_extra_style = function(el){\n",
" // this is important to make the div 'focusable\n",
" el.attr('tabindex', 0)\n",
" // reach out to IPython and tell the keyboard manager to turn it's self\n",
" // off when our div gets focus\n",
"\n",
" // location in version 3\n",
" if (IPython.notebook.keyboard_manager) {\n",
" IPython.notebook.keyboard_manager.register_events(el);\n",
" }\n",
" else {\n",
" // location in version 2\n",
" IPython.keyboard_manager.register_events(el);\n",
" }\n",
"\n",
"}\n",
"\n",
"mpl.figure.prototype._key_event_extra = function(event, name) {\n",
" var manager = IPython.notebook.keyboard_manager;\n",
" if (!manager)\n",
" manager = IPython.keyboard_manager;\n",
"\n",
" // Check for shift+enter\n",
" if (event.shiftKey && event.which == 13) {\n",
" this.canvas_div.blur();\n",
" event.shiftKey = false;\n",
" // Send a \"J\" for go to next cell\n",
" event.which = 74;\n",
" event.keyCode = 74;\n",
" manager.command_mode();\n",
" manager.handle_keydown(event);\n",
" }\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_save = function(fig, msg) {\n",
" fig.ondownload(fig, null);\n",
"}\n",
"\n",
"\n",
"mpl.find_output_cell = function(html_output) {\n",
" // Return the cell and output element which can be found *uniquely* in the notebook.\n",
" // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n",
" // IPython event is triggered only after the cells have been serialised, which for\n",
" // our purposes (turning an active figure into a static one), is too late.\n",
" var cells = IPython.notebook.get_cells();\n",
" var ncells = cells.length;\n",
" for (var i=0; i<ncells; i++) {\n",
" var cell = cells[i];\n",
" if (cell.cell_type === 'code'){\n",
" for (var j=0; j<cell.output_area.outputs.length; j++) {\n",
" var data = cell.output_area.outputs[j];\n",
" if (data.data) {\n",
" // IPython >= 3 moved mimebundle to data attribute of output\n",
" data = data.data;\n",
" }\n",
" if (data['text/html'] == html_output) {\n",
" return [cell, data, j];\n",
" }\n",
" }\n",
" }\n",
" }\n",
"}\n",
"\n",
"// Register the function which deals with the matplotlib target/channel.\n",
"// The kernel may be null if the page has been refreshed.\n",
"if (IPython.notebook.kernel != null) {\n",
" IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n",
"}\n"
],
"text/plain": [
"<IPython.core.display.Javascript object>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"<img src=\"data:image/png;base64,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\" width=\"NaN\">"
],
"text/plain": [
"<IPython.core.display.HTML object>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"HBox(children=(IntProgress(value=0, max=3), HTML(value='')))"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"HBox(children=(IntProgress(value=0, max=14062), HTML(value='')))"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"HBox(children=(IntProgress(value=0, max=7009), HTML(value='')))"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'loss': 0.07458001077127371, 'val_loss': 0.08623016369950948}\n"
]
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"HBox(children=(IntProgress(value=0, max=14062), HTML(value='')))"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"HBox(children=(IntProgress(value=0, max=7009), HTML(value='')))"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'loss': 0.07500519356493322, 'val_loss': 0.08447535222967352}\n"
]
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"HBox(children=(IntProgress(value=0, max=14062), HTML(value='')))"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"HBox(children=(IntProgress(value=0, max=7009), HTML(value='')))"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'loss': 0.06783495590024316, 'val_loss': 0.08535336141405052}\n",
"\n",
"0.08447535222967352\n"
]
}
],
"source": [
"%matplotlib nbagg\n",
"\n",
"num_split=0\n",
"np.random.seed(SEED+num_split)\n",
"torch.manual_seed(SEED+num_split)\n",
"torch.cuda.manual_seed(SEED+num_split)\n",
"#torch.backends.cudnn.deterministic = True\n",
"idx_train = train_df[train_df.PID.isin(set(split_sid[splits[num_split][0]]))].index.values\n",
"idx_validate = train_df[train_df.PID.isin(set(split_sid[splits[num_split][1]]))].index.values\n",
"idx_train.shape\n",
"idx_validate.shape\n",
"\n",
"klr=1\n",
"batch_size=32\n",
"num_workers=12\n",
"num_epochs=3\n",
"model_name,version = 'Densenet161_3' , 'classifier__splits'\n",
"#model1 = MyDenseNet(models.densenet161(pretrained=True),len(hemorrhage_types),num_channels=3)\n",
"model = MyDenseNet(models.densenet161(pretrained=True),\n",
" len(hemorrhage_types),\n",
" num_channels=3,\n",
" drop_out=0.2,\n",
" wso=((40,80),(80,200),(600,2800)),\n",
" strategy='none',\n",
" dont_do_grad=[],\n",
" extra_pool=4,\n",
" pool_type='max'\n",
" )\n",
"model.load_state_dict(torch.load(models_dir+models_format.format(model_name,'basic_splits',num_split),map_location=torch.device(device)))\n",
"_=model.to(device)\n",
"weights = torch.tensor([1.,1.,1.,1.,1.,2.],device=device)\n",
"loss_func=my_loss\n",
"targets_dataset=D.TensorDataset(torch.tensor(train_df[hemorrhage_types].values,dtype=torch.float))\n",
"transform=MyTransform(flip=True,zoom=0.05,rotate=15,out_size=512,shift=40)\n",
"imagedataset = ImageDataset(train_df,transform=transform.random,base_path=train_images_dir,\n",
" window_eq=False,equalize=False,rescale=True)\n",
"transform_val=MyTransform(out_size=512)\n",
"imagedataset_val = ImageDataset(train_df,transform=transform_val.random,base_path=train_images_dir,\n",
" window_eq=False,equalize=False,rescale=True)\n",
"combined_dataset=DatasetCat([imagedataset,targets_dataset])\n",
"combined_dataset_val=DatasetCat([imagedataset_val,targets_dataset])\n",
"#param_s=parameter_scheduler(model,num_epoch=0)\n",
"pre_proc = Mixup(0.4,device=device)\n",
"optimizer_grouped_parameters=get_optimizer_parameters(model,klr)\n",
"#sampling=simple_sampler(train_df[hemorrhage_types].values[idx_train],0.25)\n",
"#sampling=sampler(train_df[hemorrhage_types].values[idx_train],5,[0,0,0,0,0,2],train_df.SeriesI.values[idx_train])\n",
"sample_ratio= 1.0 #1.003*float(sampling().shape[0])/idx_train.shape[0]\n",
"train_dataset=D.Subset(combined_dataset,idx_train)\n",
"validate_dataset=D.Subset(combined_dataset_val,idx_validate)\n",
"num_train_optimization_steps = num_epochs*(sample_ratio*len(train_dataset)//batch_size+int(len(train_dataset)%batch_size>0))\n",
"fig,ax = plt.subplots(figsize=(10,7))\n",
"gr=loss_graph(fig,ax,num_epochs,int(num_train_optimization_steps/num_epochs)+1,limits=(0.05,0.2))\n",
"sched=WarmupExpCosineWithWarmupRestartsSchedule( t_total=num_train_optimization_steps, cycles=num_epochs,tau=1.5)\n",
"optimizer = BertAdam(optimizer_grouped_parameters,lr=klr*1e-3,schedule=sched)\n",
"model, optimizer = amp.initialize(model, optimizer, opt_level=\"O1\",verbosity=0)\n",
"history,best_model= model_train(model,\n",
" optimizer,\n",
" train_dataset,\n",
" batch_size,\n",
" num_epochs,\n",
" loss_func,\n",
" weights=weights,\n",
" do_apex=False,\n",
" model_apexed=True,\n",
" validate_dataset=validate_dataset,\n",
" param_schedualer=None,\n",
" weights_data=None,\n",
" metric=None,\n",
" return_model=True,\n",
" num_workers=num_workers,\n",
" sampler=None,\n",
" pre_process = None,\n",
" graph=gr,\n",
" call_progress=sendmeemail)\n",
"\n",
"torch.save(model.state_dict(), models_dir+models_format.format(model_name,version,num_split))\n",
"torch.save(best_model.state_dict(), models_dir+models_format.format(model_name,version+'_best',num_split))"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<torch._C.Generator at 0x7f06349ec5d0>"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"text/plain": [
"(449019,)"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"text/plain": [
"(225233,)"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"application/javascript": [
"/* Put everything inside the global mpl namespace */\n",
"window.mpl = {};\n",
"\n",
"\n",
"mpl.get_websocket_type = function() {\n",
" if (typeof(WebSocket) !== 'undefined') {\n",
" return WebSocket;\n",
" } else if (typeof(MozWebSocket) !== 'undefined') {\n",
" return MozWebSocket;\n",
" } else {\n",
" alert('Your browser does not have WebSocket support.' +\n",
" 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
" 'Firefox 4 and 5 are also supported but you ' +\n",
" 'have to enable WebSockets in about:config.');\n",
" };\n",
"}\n",
"\n",
"mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n",
" this.id = figure_id;\n",
"\n",
" this.ws = websocket;\n",
"\n",
" this.supports_binary = (this.ws.binaryType != undefined);\n",
"\n",
" if (!this.supports_binary) {\n",
" var warnings = document.getElementById(\"mpl-warnings\");\n",
" if (warnings) {\n",
" warnings.style.display = 'block';\n",
" warnings.textContent = (\n",
" \"This browser does not support binary websocket messages. \" +\n",
" \"Performance may be slow.\");\n",
" }\n",
" }\n",
"\n",
" this.imageObj = new Image();\n",
"\n",
" this.context = undefined;\n",
" this.message = undefined;\n",
" this.canvas = undefined;\n",
" this.rubberband_canvas = undefined;\n",
" this.rubberband_context = undefined;\n",
" this.format_dropdown = undefined;\n",
"\n",
" this.image_mode = 'full';\n",
"\n",
" this.root = $('<div/>');\n",
" this._root_extra_style(this.root)\n",
" this.root.attr('style', 'display: inline-block');\n",
"\n",
" $(parent_element).append(this.root);\n",
"\n",
" this._init_header(this);\n",
" this._init_canvas(this);\n",
" this._init_toolbar(this);\n",
"\n",
" var fig = this;\n",
"\n",
" this.waiting = false;\n",
"\n",
" this.ws.onopen = function () {\n",
" fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n",
" fig.send_message(\"send_image_mode\", {});\n",
" if (mpl.ratio != 1) {\n",
" fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n",
" }\n",
" fig.send_message(\"refresh\", {});\n",
" }\n",
"\n",
" this.imageObj.onload = function() {\n",
" if (fig.image_mode == 'full') {\n",
" // Full images could contain transparency (where diff images\n",
" // almost always do), so we need to clear the canvas so that\n",
" // there is no ghosting.\n",
" fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
" }\n",
" fig.context.drawImage(fig.imageObj, 0, 0);\n",
" };\n",
"\n",
" this.imageObj.onunload = function() {\n",
" fig.ws.close();\n",
" }\n",
"\n",
" this.ws.onmessage = this._make_on_message_function(this);\n",
"\n",
" this.ondownload = ondownload;\n",
"}\n",
"\n",
"mpl.figure.prototype._init_header = function() {\n",
" var titlebar = $(\n",
" '<div class=\"ui-dialog-titlebar ui-widget-header ui-corner-all ' +\n",
" 'ui-helper-clearfix\"/>');\n",
" var titletext = $(\n",
" '<div class=\"ui-dialog-title\" style=\"width: 100%; ' +\n",
" 'text-align: center; padding: 3px;\"/>');\n",
" titlebar.append(titletext)\n",
" this.root.append(titlebar);\n",
" this.header = titletext[0];\n",
"}\n",
"\n",
"\n",
"\n",
"mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n",
"\n",
"}\n",
"\n",
"\n",
"mpl.figure.prototype._root_extra_style = function(canvas_div) {\n",
"\n",
"}\n",
"\n",
"mpl.figure.prototype._init_canvas = function() {\n",
" var fig = this;\n",
"\n",
" var canvas_div = $('<div/>');\n",
"\n",
" canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n",
"\n",
" function canvas_keyboard_event(event) {\n",
" return fig.key_event(event, event['data']);\n",
" }\n",
"\n",
" canvas_div.keydown('key_press', canvas_keyboard_event);\n",
" canvas_div.keyup('key_release', canvas_keyboard_event);\n",
" this.canvas_div = canvas_div\n",
" this._canvas_extra_style(canvas_div)\n",
" this.root.append(canvas_div);\n",
"\n",
" var canvas = $('<canvas/>');\n",
" canvas.addClass('mpl-canvas');\n",
" canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n",
"\n",
" this.canvas = canvas[0];\n",
" this.context = canvas[0].getContext(\"2d\");\n",
"\n",
" var backingStore = this.context.backingStorePixelRatio ||\n",
"\tthis.context.webkitBackingStorePixelRatio ||\n",
"\tthis.context.mozBackingStorePixelRatio ||\n",
"\tthis.context.msBackingStorePixelRatio ||\n",
"\tthis.context.oBackingStorePixelRatio ||\n",
"\tthis.context.backingStorePixelRatio || 1;\n",
"\n",
" mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n",
"\n",
" var rubberband = $('<canvas/>');\n",
" rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n",
"\n",
" var pass_mouse_events = true;\n",
"\n",
" canvas_div.resizable({\n",
" start: function(event, ui) {\n",
" pass_mouse_events = false;\n",
" },\n",
" resize: function(event, ui) {\n",
" fig.request_resize(ui.size.width, ui.size.height);\n",
" },\n",
" stop: function(event, ui) {\n",
" pass_mouse_events = true;\n",
" fig.request_resize(ui.size.width, ui.size.height);\n",
" },\n",
" });\n",
"\n",
" function mouse_event_fn(event) {\n",
" if (pass_mouse_events)\n",
" return fig.mouse_event(event, event['data']);\n",
" }\n",
"\n",
" rubberband.mousedown('button_press', mouse_event_fn);\n",
" rubberband.mouseup('button_release', mouse_event_fn);\n",
" // Throttle sequential mouse events to 1 every 20ms.\n",
" rubberband.mousemove('motion_notify', mouse_event_fn);\n",
"\n",
" rubberband.mouseenter('figure_enter', mouse_event_fn);\n",
" rubberband.mouseleave('figure_leave', mouse_event_fn);\n",
"\n",
" canvas_div.on(\"wheel\", function (event) {\n",
" event = event.originalEvent;\n",
" event['data'] = 'scroll'\n",
" if (event.deltaY < 0) {\n",
" event.step = 1;\n",
" } else {\n",
" event.step = -1;\n",
" }\n",
" mouse_event_fn(event);\n",
" });\n",
"\n",
" canvas_div.append(canvas);\n",
" canvas_div.append(rubberband);\n",
"\n",
" this.rubberband = rubberband;\n",
" this.rubberband_canvas = rubberband[0];\n",
" this.rubberband_context = rubberband[0].getContext(\"2d\");\n",
" this.rubberband_context.strokeStyle = \"#000000\";\n",
"\n",
" this._resize_canvas = function(width, height) {\n",
" // Keep the size of the canvas, canvas container, and rubber band\n",
" // canvas in synch.\n",
" canvas_div.css('width', width)\n",
" canvas_div.css('height', height)\n",
"\n",
" canvas.attr('width', width * mpl.ratio);\n",
" canvas.attr('height', height * mpl.ratio);\n",
" canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n",
"\n",
" rubberband.attr('width', width);\n",
" rubberband.attr('height', height);\n",
" }\n",
"\n",
" // Set the figure to an initial 600x600px, this will subsequently be updated\n",
" // upon first draw.\n",
" this._resize_canvas(600, 600);\n",
"\n",
" // Disable right mouse context menu.\n",
" $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n",
" return false;\n",
" });\n",
"\n",
" function set_focus () {\n",
" canvas.focus();\n",
" canvas_div.focus();\n",
" }\n",
"\n",
" window.setTimeout(set_focus, 100);\n",
"}\n",
"\n",
"mpl.figure.prototype._init_toolbar = function() {\n",
" var fig = this;\n",
"\n",
" var nav_element = $('<div/>')\n",
" nav_element.attr('style', 'width: 100%');\n",
" this.root.append(nav_element);\n",
"\n",
" // Define a callback function for later on.\n",
" function toolbar_event(event) {\n",
" return fig.toolbar_button_onclick(event['data']);\n",
" }\n",
" function toolbar_mouse_event(event) {\n",
" return fig.toolbar_button_onmouseover(event['data']);\n",
" }\n",
"\n",
" for(var toolbar_ind in mpl.toolbar_items) {\n",
" var name = mpl.toolbar_items[toolbar_ind][0];\n",
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
" var image = mpl.toolbar_items[toolbar_ind][2];\n",
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
"\n",
" if (!name) {\n",
" // put a spacer in here.\n",
" continue;\n",
" }\n",
" var button = $('<button/>');\n",
" button.addClass('ui-button ui-widget ui-state-default ui-corner-all ' +\n",
" 'ui-button-icon-only');\n",
" button.attr('role', 'button');\n",
" button.attr('aria-disabled', 'false');\n",
" button.click(method_name, toolbar_event);\n",
" button.mouseover(tooltip, toolbar_mouse_event);\n",
"\n",
" var icon_img = $('<span/>');\n",
" icon_img.addClass('ui-button-icon-primary ui-icon');\n",
" icon_img.addClass(image);\n",
" icon_img.addClass('ui-corner-all');\n",
"\n",
" var tooltip_span = $('<span/>');\n",
" tooltip_span.addClass('ui-button-text');\n",
" tooltip_span.html(tooltip);\n",
"\n",
" button.append(icon_img);\n",
" button.append(tooltip_span);\n",
"\n",
" nav_element.append(button);\n",
" }\n",
"\n",
" var fmt_picker_span = $('<span/>');\n",
"\n",
" var fmt_picker = $('<select/>');\n",
" fmt_picker.addClass('mpl-toolbar-option ui-widget ui-widget-content');\n",
" fmt_picker_span.append(fmt_picker);\n",
" nav_element.append(fmt_picker_span);\n",
" this.format_dropdown = fmt_picker[0];\n",
"\n",
" for (var ind in mpl.extensions) {\n",
" var fmt = mpl.extensions[ind];\n",
" var option = $(\n",
" '<option/>', {selected: fmt === mpl.default_extension}).html(fmt);\n",
" fmt_picker.append(option)\n",
" }\n",
"\n",
" // Add hover states to the ui-buttons\n",
" $( \".ui-button\" ).hover(\n",
" function() { $(this).addClass(\"ui-state-hover\");},\n",
" function() { $(this).removeClass(\"ui-state-hover\");}\n",
" );\n",
"\n",
" var status_bar = $('<span class=\"mpl-message\"/>');\n",
" nav_element.append(status_bar);\n",
" this.message = status_bar[0];\n",
"}\n",
"\n",
"mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n",
" // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n",
" // which will in turn request a refresh of the image.\n",
" this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n",
"}\n",
"\n",
"mpl.figure.prototype.send_message = function(type, properties) {\n",
" properties['type'] = type;\n",
" properties['figure_id'] = this.id;\n",
" this.ws.send(JSON.stringify(properties));\n",
"}\n",
"\n",
"mpl.figure.prototype.send_draw_message = function() {\n",
" if (!this.waiting) {\n",
" this.waiting = true;\n",
" this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n",
" }\n",
"}\n",
"\n",
"\n",
"mpl.figure.prototype.handle_save = function(fig, msg) {\n",
" var format_dropdown = fig.format_dropdown;\n",
" var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n",
" fig.ondownload(fig, format);\n",
"}\n",
"\n",
"\n",
"mpl.figure.prototype.handle_resize = function(fig, msg) {\n",
" var size = msg['size'];\n",
" if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n",
" fig._resize_canvas(size[0], size[1]);\n",
" fig.send_message(\"refresh\", {});\n",
" };\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n",
" var x0 = msg['x0'] / mpl.ratio;\n",
" var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n",
" var x1 = msg['x1'] / mpl.ratio;\n",
" var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n",
" x0 = Math.floor(x0) + 0.5;\n",
" y0 = Math.floor(y0) + 0.5;\n",
" x1 = Math.floor(x1) + 0.5;\n",
" y1 = Math.floor(y1) + 0.5;\n",
" var min_x = Math.min(x0, x1);\n",
" var min_y = Math.min(y0, y1);\n",
" var width = Math.abs(x1 - x0);\n",
" var height = Math.abs(y1 - y0);\n",
"\n",
" fig.rubberband_context.clearRect(\n",
" 0, 0, fig.canvas.width, fig.canvas.height);\n",
"\n",
" fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n",
" // Updates the figure title.\n",
" fig.header.textContent = msg['label'];\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_cursor = function(fig, msg) {\n",
" var cursor = msg['cursor'];\n",
" switch(cursor)\n",
" {\n",
" case 0:\n",
" cursor = 'pointer';\n",
" break;\n",
" case 1:\n",
" cursor = 'default';\n",
" break;\n",
" case 2:\n",
" cursor = 'crosshair';\n",
" break;\n",
" case 3:\n",
" cursor = 'move';\n",
" break;\n",
" }\n",
" fig.rubberband_canvas.style.cursor = cursor;\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_message = function(fig, msg) {\n",
" fig.message.textContent = msg['message'];\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_draw = function(fig, msg) {\n",
" // Request the server to send over a new figure.\n",
" fig.send_draw_message();\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n",
" fig.image_mode = msg['mode'];\n",
"}\n",
"\n",
"mpl.figure.prototype.updated_canvas_event = function() {\n",
" // Called whenever the canvas gets updated.\n",
" this.send_message(\"ack\", {});\n",
"}\n",
"\n",
"// A function to construct a web socket function for onmessage handling.\n",
"// Called in the figure constructor.\n",
"mpl.figure.prototype._make_on_message_function = function(fig) {\n",
" return function socket_on_message(evt) {\n",
" if (evt.data instanceof Blob) {\n",
" /* FIXME: We get \"Resource interpreted as Image but\n",
" * transferred with MIME type text/plain:\" errors on\n",
" * Chrome. But how to set the MIME type? It doesn't seem\n",
" * to be part of the websocket stream */\n",
" evt.data.type = \"image/png\";\n",
"\n",
" /* Free the memory for the previous frames */\n",
" if (fig.imageObj.src) {\n",
" (window.URL || window.webkitURL).revokeObjectURL(\n",
" fig.imageObj.src);\n",
" }\n",
"\n",
" fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
" evt.data);\n",
" fig.updated_canvas_event();\n",
" fig.waiting = false;\n",
" return;\n",
" }\n",
" else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n",
" fig.imageObj.src = evt.data;\n",
" fig.updated_canvas_event();\n",
" fig.waiting = false;\n",
" return;\n",
" }\n",
"\n",
" var msg = JSON.parse(evt.data);\n",
" var msg_type = msg['type'];\n",
"\n",
" // Call the \"handle_{type}\" callback, which takes\n",
" // the figure and JSON message as its only arguments.\n",
" try {\n",
" var callback = fig[\"handle_\" + msg_type];\n",
" } catch (e) {\n",
" console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n",
" return;\n",
" }\n",
"\n",
" if (callback) {\n",
" try {\n",
" // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n",
" callback(fig, msg);\n",
" } catch (e) {\n",
" console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n",
" }\n",
" }\n",
" };\n",
"}\n",
"\n",
"// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n",
"mpl.findpos = function(e) {\n",
" //this section is from http://www.quirksmode.org/js/events_properties.html\n",
" var targ;\n",
" if (!e)\n",
" e = window.event;\n",
" if (e.target)\n",
" targ = e.target;\n",
" else if (e.srcElement)\n",
" targ = e.srcElement;\n",
" if (targ.nodeType == 3) // defeat Safari bug\n",
" targ = targ.parentNode;\n",
"\n",
" // jQuery normalizes the pageX and pageY\n",
" // pageX,Y are the mouse positions relative to the document\n",
" // offset() returns the position of the element relative to the document\n",
" var x = e.pageX - $(targ).offset().left;\n",
" var y = e.pageY - $(targ).offset().top;\n",
"\n",
" return {\"x\": x, \"y\": y};\n",
"};\n",
"\n",
"/*\n",
" * return a copy of an object with only non-object keys\n",
" * we need this to avoid circular references\n",
" * http://stackoverflow.com/a/24161582/3208463\n",
" */\n",
"function simpleKeys (original) {\n",
" return Object.keys(original).reduce(function (obj, key) {\n",
" if (typeof original[key] !== 'object')\n",
" obj[key] = original[key]\n",
" return obj;\n",
" }, {});\n",
"}\n",
"\n",
"mpl.figure.prototype.mouse_event = function(event, name) {\n",
" var canvas_pos = mpl.findpos(event)\n",
"\n",
" if (name === 'button_press')\n",
" {\n",
" this.canvas.focus();\n",
" this.canvas_div.focus();\n",
" }\n",
"\n",
" var x = canvas_pos.x * mpl.ratio;\n",
" var y = canvas_pos.y * mpl.ratio;\n",
"\n",
" this.send_message(name, {x: x, y: y, button: event.button,\n",
" step: event.step,\n",
" guiEvent: simpleKeys(event)});\n",
"\n",
" /* This prevents the web browser from automatically changing to\n",
" * the text insertion cursor when the button is pressed. We want\n",
" * to control all of the cursor setting manually through the\n",
" * 'cursor' event from matplotlib */\n",
" event.preventDefault();\n",
" return false;\n",
"}\n",
"\n",
"mpl.figure.prototype._key_event_extra = function(event, name) {\n",
" // Handle any extra behaviour associated with a key event\n",
"}\n",
"\n",
"mpl.figure.prototype.key_event = function(event, name) {\n",
"\n",
" // Prevent repeat events\n",
" if (name == 'key_press')\n",
" {\n",
" if (event.which === this._key)\n",
" return;\n",
" else\n",
" this._key = event.which;\n",
" }\n",
" if (name == 'key_release')\n",
" this._key = null;\n",
"\n",
" var value = '';\n",
" if (event.ctrlKey && event.which != 17)\n",
" value += \"ctrl+\";\n",
" if (event.altKey && event.which != 18)\n",
" value += \"alt+\";\n",
" if (event.shiftKey && event.which != 16)\n",
" value += \"shift+\";\n",
"\n",
" value += 'k';\n",
" value += event.which.toString();\n",
"\n",
" this._key_event_extra(event, name);\n",
"\n",
" this.send_message(name, {key: value,\n",
" guiEvent: simpleKeys(event)});\n",
" return false;\n",
"}\n",
"\n",
"mpl.figure.prototype.toolbar_button_onclick = function(name) {\n",
" if (name == 'download') {\n",
" this.handle_save(this, null);\n",
" } else {\n",
" this.send_message(\"toolbar_button\", {name: name});\n",
" }\n",
"};\n",
"\n",
"mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n",
" this.message.textContent = tooltip;\n",
"};\n",
"mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n",
"\n",
"mpl.extensions = [\"eps\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
"\n",
"mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n",
" // Create a \"websocket\"-like object which calls the given IPython comm\n",
" // object with the appropriate methods. Currently this is a non binary\n",
" // socket, so there is still some room for performance tuning.\n",
" var ws = {};\n",
"\n",
" ws.close = function() {\n",
" comm.close()\n",
" };\n",
" ws.send = function(m) {\n",
" //console.log('sending', m);\n",
" comm.send(m);\n",
" };\n",
" // Register the callback with on_msg.\n",
" comm.on_msg(function(msg) {\n",
" //console.log('receiving', msg['content']['data'], msg);\n",
" // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
" ws.onmessage(msg['content']['data'])\n",
" });\n",
" return ws;\n",
"}\n",
"\n",
"mpl.mpl_figure_comm = function(comm, msg) {\n",
" // This is the function which gets called when the mpl process\n",
" // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
"\n",
" var id = msg.content.data.id;\n",
" // Get hold of the div created by the display call when the Comm\n",
" // socket was opened in Python.\n",
" var element = $(\"#\" + id);\n",
" var ws_proxy = comm_websocket_adapter(comm)\n",
"\n",
" function ondownload(figure, format) {\n",
" window.open(figure.imageObj.src);\n",
" }\n",
"\n",
" var fig = new mpl.figure(id, ws_proxy,\n",
" ondownload,\n",
" element.get(0));\n",
"\n",
" // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n",
" // web socket which is closed, not our websocket->open comm proxy.\n",
" ws_proxy.onopen();\n",
"\n",
" fig.parent_element = element.get(0);\n",
" fig.cell_info = mpl.find_output_cell(\"<div id='\" + id + \"'></div>\");\n",
" if (!fig.cell_info) {\n",
" console.error(\"Failed to find cell for figure\", id, fig);\n",
" return;\n",
" }\n",
"\n",
" var output_index = fig.cell_info[2]\n",
" var cell = fig.cell_info[0];\n",
"\n",
"};\n",
"\n",
"mpl.figure.prototype.handle_close = function(fig, msg) {\n",
" var width = fig.canvas.width/mpl.ratio\n",
" fig.root.unbind('remove')\n",
"\n",
" // Update the output cell to use the data from the current canvas.\n",
" fig.push_to_output();\n",
" var dataURL = fig.canvas.toDataURL();\n",
" // Re-enable the keyboard manager in IPython - without this line, in FF,\n",
" // the notebook keyboard shortcuts fail.\n",
" IPython.keyboard_manager.enable()\n",
" $(fig.parent_element).html('<img src=\"' + dataURL + '\" width=\"' + width + '\">');\n",
" fig.close_ws(fig, msg);\n",
"}\n",
"\n",
"mpl.figure.prototype.close_ws = function(fig, msg){\n",
" fig.send_message('closing', msg);\n",
" // fig.ws.close()\n",
"}\n",
"\n",
"mpl.figure.prototype.push_to_output = function(remove_interactive) {\n",
" // Turn the data on the canvas into data in the output cell.\n",
" var width = this.canvas.width/mpl.ratio\n",
" var dataURL = this.canvas.toDataURL();\n",
" this.cell_info[1]['text/html'] = '<img src=\"' + dataURL + '\" width=\"' + width + '\">';\n",
"}\n",
"\n",
"mpl.figure.prototype.updated_canvas_event = function() {\n",
" // Tell IPython that the notebook contents must change.\n",
" IPython.notebook.set_dirty(true);\n",
" this.send_message(\"ack\", {});\n",
" var fig = this;\n",
" // Wait a second, then push the new image to the DOM so\n",
" // that it is saved nicely (might be nice to debounce this).\n",
" setTimeout(function () { fig.push_to_output() }, 1000);\n",
"}\n",
"\n",
"mpl.figure.prototype._init_toolbar = function() {\n",
" var fig = this;\n",
"\n",
" var nav_element = $('<div/>')\n",
" nav_element.attr('style', 'width: 100%');\n",
" this.root.append(nav_element);\n",
"\n",
" // Define a callback function for later on.\n",
" function toolbar_event(event) {\n",
" return fig.toolbar_button_onclick(event['data']);\n",
" }\n",
" function toolbar_mouse_event(event) {\n",
" return fig.toolbar_button_onmouseover(event['data']);\n",
" }\n",
"\n",
" for(var toolbar_ind in mpl.toolbar_items){\n",
" var name = mpl.toolbar_items[toolbar_ind][0];\n",
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
" var image = mpl.toolbar_items[toolbar_ind][2];\n",
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
"\n",
" if (!name) { continue; };\n",
"\n",
" var button = $('<button class=\"btn btn-default\" href=\"#\" title=\"' + name + '\"><i class=\"fa ' + image + ' fa-lg\"></i></button>');\n",
" button.click(method_name, toolbar_event);\n",
" button.mouseover(tooltip, toolbar_mouse_event);\n",
" nav_element.append(button);\n",
" }\n",
"\n",
" // Add the status bar.\n",
" var status_bar = $('<span class=\"mpl-message\" style=\"text-align:right; float: right;\"/>');\n",
" nav_element.append(status_bar);\n",
" this.message = status_bar[0];\n",
"\n",
" // Add the close button to the window.\n",
" var buttongrp = $('<div class=\"btn-group inline pull-right\"></div>');\n",
" var button = $('<button class=\"btn btn-mini btn-primary\" href=\"#\" title=\"Stop Interaction\"><i class=\"fa fa-power-off icon-remove icon-large\"></i></button>');\n",
" button.click(function (evt) { fig.handle_close(fig, {}); } );\n",
" button.mouseover('Stop Interaction', toolbar_mouse_event);\n",
" buttongrp.append(button);\n",
" var titlebar = this.root.find($('.ui-dialog-titlebar'));\n",
" titlebar.prepend(buttongrp);\n",
"}\n",
"\n",
"mpl.figure.prototype._root_extra_style = function(el){\n",
" var fig = this\n",
" el.on(\"remove\", function(){\n",
"\tfig.close_ws(fig, {});\n",
" });\n",
"}\n",
"\n",
"mpl.figure.prototype._canvas_extra_style = function(el){\n",
" // this is important to make the div 'focusable\n",
" el.attr('tabindex', 0)\n",
" // reach out to IPython and tell the keyboard manager to turn it's self\n",
" // off when our div gets focus\n",
"\n",
" // location in version 3\n",
" if (IPython.notebook.keyboard_manager) {\n",
" IPython.notebook.keyboard_manager.register_events(el);\n",
" }\n",
" else {\n",
" // location in version 2\n",
" IPython.keyboard_manager.register_events(el);\n",
" }\n",
"\n",
"}\n",
"\n",
"mpl.figure.prototype._key_event_extra = function(event, name) {\n",
" var manager = IPython.notebook.keyboard_manager;\n",
" if (!manager)\n",
" manager = IPython.keyboard_manager;\n",
"\n",
" // Check for shift+enter\n",
" if (event.shiftKey && event.which == 13) {\n",
" this.canvas_div.blur();\n",
" event.shiftKey = false;\n",
" // Send a \"J\" for go to next cell\n",
" event.which = 74;\n",
" event.keyCode = 74;\n",
" manager.command_mode();\n",
" manager.handle_keydown(event);\n",
" }\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_save = function(fig, msg) {\n",
" fig.ondownload(fig, null);\n",
"}\n",
"\n",
"\n",
"mpl.find_output_cell = function(html_output) {\n",
" // Return the cell and output element which can be found *uniquely* in the notebook.\n",
" // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n",
" // IPython event is triggered only after the cells have been serialised, which for\n",
" // our purposes (turning an active figure into a static one), is too late.\n",
" var cells = IPython.notebook.get_cells();\n",
" var ncells = cells.length;\n",
" for (var i=0; i<ncells; i++) {\n",
" var cell = cells[i];\n",
" if (cell.cell_type === 'code'){\n",
" for (var j=0; j<cell.output_area.outputs.length; j++) {\n",
" var data = cell.output_area.outputs[j];\n",
" if (data.data) {\n",
" // IPython >= 3 moved mimebundle to data attribute of output\n",
" data = data.data;\n",
" }\n",
" if (data['text/html'] == html_output) {\n",
" return [cell, data, j];\n",
" }\n",
" }\n",
" }\n",
" }\n",
"}\n",
"\n",
"// Register the function which deals with the matplotlib target/channel.\n",
"// The kernel may be null if the page has been refreshed.\n",
"if (IPython.notebook.kernel != null) {\n",
" IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n",
"}\n"
],
"text/plain": [
"<IPython.core.display.Javascript object>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"<img src=\"data:image/png;base64,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\" width=\"720\">"
],
"text/plain": [
"<IPython.core.display.HTML object>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"HBox(children=(IntProgress(value=0, max=2), HTML(value='')))"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"HBox(children=(IntProgress(value=0, max=5758), HTML(value='')))"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"HBox(children=(IntProgress(value=0, max=7039), HTML(value='')))"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'loss': 0.20887301142686854, 'val_loss': 0.11688730684149386}\n"
]
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"HBox(children=(IntProgress(value=0, max=5758), HTML(value='')))"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"HBox(children=(IntProgress(value=0, max=7039), HTML(value='')))"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'loss': 0.16667988125900893, 'val_loss': 0.11078236175250906}\n",
"0.11078236175250906\n"
]
}
],
"source": [
"%matplotlib nbagg\n",
"\n",
"num_split=1\n",
"np.random.seed(SEED+num_split)\n",
"torch.manual_seed(SEED+num_split)\n",
"torch.cuda.manual_seed(SEED+num_split)\n",
"#torch.backends.cudnn.deterministic = True\n",
"idx_train = train_df[train_df.PID.isin(set(split_sid[splits[num_split][0]]))].index.values\n",
"idx_validate = train_df[train_df.PID.isin(set(split_sid[splits[num_split][1]]))].index.values\n",
"idx_train.shape\n",
"idx_validate.shape\n",
"\n",
"klr=1\n",
"batch_size=32\n",
"num_workers=12\n",
"num_epochs=2\n",
"model_name,version = 'Densenet161_3' , 'basic_splits'\n",
"model = MyDenseNet(models.densenet161(pretrained=True),\n",
" len(hemorrhage_types),\n",
" num_channels=3,\n",
" drop_out=0.2,\n",
" wso=((40,80),(80,200),(600,2800)),\n",
" strategy='none',\n",
" dont_do_grad=[],\n",
" pool_type='max',\n",
" extra_pool=4,\n",
" )\n",
"\n",
"_=model.to(device)\n",
"weights = torch.tensor([1.,1.,1.,1.,1.,2.],device=device)\n",
"loss_func=my_loss\n",
"targets_dataset=D.TensorDataset(torch.tensor(train_df[hemorrhage_types].values,dtype=torch.float))\n",
"transform=MyTransform(flip=True,zoom=0.05,rotate=15,out_size=512,shift=40)\n",
"imagedataset = ImageDataset(train_df,transform=transform.random,base_path=train_images_dir,\n",
" window_eq=False,equalize=False,rescale=True)\n",
"transform_val=MyTransform(out_size=512)\n",
"imagedataset_val = ImageDataset(train_df,transform=transform_val.random,base_path=train_images_dir,\n",
" window_eq=False,equalize=False,rescale=True)\n",
"combined_dataset=DatasetCat([imagedataset,targets_dataset])\n",
"combined_dataset_val=DatasetCat([imagedataset_val,targets_dataset])\n",
"#param_s=parameter_scheduler(model,num_epoch=0)\n",
"optimizer_grouped_parameters=get_optimizer_parameters(model,klr)\n",
"sampling=sampler(train_df[hemorrhage_types].values[idx_train],0.2,[10,1,1,1,1,0])\n",
"sample_ratio=1.02*float(sampling().shape[0])/idx_train.shape[0]\n",
"train_dataset=D.Subset(combined_dataset,idx_train)\n",
"validate_dataset=D.Subset(combined_dataset_val,idx_validate)\n",
"num_train_optimization_steps = num_epochs*(sample_ratio*len(train_dataset)//batch_size+int(len(train_dataset)%batch_size>0))\n",
"fig,ax = plt.subplots(figsize=(10,7))\n",
"gr=loss_graph(fig,ax,num_epochs,int(num_train_optimization_steps/num_epochs)+1,limits=[0.05,0.4])\n",
"sched=WarmupExpCosineWithWarmupRestartsSchedule( t_total=num_train_optimization_steps, cycles=num_epochs//2,tau=1)\n",
"optimizer = BertAdam(optimizer_grouped_parameters,lr=klr*1e-3,schedule=sched)\n",
"model, optimizer = amp.initialize(model, optimizer, opt_level=\"O1\",verbosity=0)\n",
"history,best_model= model_train(model,\n",
" optimizer,\n",
" train_dataset,\n",
" batch_size,\n",
" num_epochs,\n",
" loss_func,\n",
" weights=weights,\n",
" do_apex=False,\n",
" model_apexed=True,\n",
" validate_dataset=validate_dataset,\n",
" param_schedualer=None,\n",
" weights_data=None,\n",
" metric=None,\n",
" return_model=True,\n",
" num_workers=num_workers,\n",
" sampler=sampling,\n",
" graph=gr,\n",
" call_progress=sendmeemail)\n",
"torch.save(model.state_dict(), models_dir+models_format.format(model_name,version,num_split))\n",
"torch.save(best_model.state_dict(), models_dir+models_format.format(model_name,version+'_best',num_split))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<torch._C.Generator at 0x7f06349ec5d0>"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"text/plain": [
"(449019,)"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"text/plain": [
"(225233,)"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"text/plain": [
"<All keys matched successfully>"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"application/javascript": [
"/* Put everything inside the global mpl namespace */\n",
"window.mpl = {};\n",
"\n",
"\n",
"mpl.get_websocket_type = function() {\n",
" if (typeof(WebSocket) !== 'undefined') {\n",
" return WebSocket;\n",
" } else if (typeof(MozWebSocket) !== 'undefined') {\n",
" return MozWebSocket;\n",
" } else {\n",
" alert('Your browser does not have WebSocket support.' +\n",
" 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
" 'Firefox 4 and 5 are also supported but you ' +\n",
" 'have to enable WebSockets in about:config.');\n",
" };\n",
"}\n",
"\n",
"mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n",
" this.id = figure_id;\n",
"\n",
" this.ws = websocket;\n",
"\n",
" this.supports_binary = (this.ws.binaryType != undefined);\n",
"\n",
" if (!this.supports_binary) {\n",
" var warnings = document.getElementById(\"mpl-warnings\");\n",
" if (warnings) {\n",
" warnings.style.display = 'block';\n",
" warnings.textContent = (\n",
" \"This browser does not support binary websocket messages. \" +\n",
" \"Performance may be slow.\");\n",
" }\n",
" }\n",
"\n",
" this.imageObj = new Image();\n",
"\n",
" this.context = undefined;\n",
" this.message = undefined;\n",
" this.canvas = undefined;\n",
" this.rubberband_canvas = undefined;\n",
" this.rubberband_context = undefined;\n",
" this.format_dropdown = undefined;\n",
"\n",
" this.image_mode = 'full';\n",
"\n",
" this.root = $('<div/>');\n",
" this._root_extra_style(this.root)\n",
" this.root.attr('style', 'display: inline-block');\n",
"\n",
" $(parent_element).append(this.root);\n",
"\n",
" this._init_header(this);\n",
" this._init_canvas(this);\n",
" this._init_toolbar(this);\n",
"\n",
" var fig = this;\n",
"\n",
" this.waiting = false;\n",
"\n",
" this.ws.onopen = function () {\n",
" fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n",
" fig.send_message(\"send_image_mode\", {});\n",
" if (mpl.ratio != 1) {\n",
" fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n",
" }\n",
" fig.send_message(\"refresh\", {});\n",
" }\n",
"\n",
" this.imageObj.onload = function() {\n",
" if (fig.image_mode == 'full') {\n",
" // Full images could contain transparency (where diff images\n",
" // almost always do), so we need to clear the canvas so that\n",
" // there is no ghosting.\n",
" fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
" }\n",
" fig.context.drawImage(fig.imageObj, 0, 0);\n",
" };\n",
"\n",
" this.imageObj.onunload = function() {\n",
" fig.ws.close();\n",
" }\n",
"\n",
" this.ws.onmessage = this._make_on_message_function(this);\n",
"\n",
" this.ondownload = ondownload;\n",
"}\n",
"\n",
"mpl.figure.prototype._init_header = function() {\n",
" var titlebar = $(\n",
" '<div class=\"ui-dialog-titlebar ui-widget-header ui-corner-all ' +\n",
" 'ui-helper-clearfix\"/>');\n",
" var titletext = $(\n",
" '<div class=\"ui-dialog-title\" style=\"width: 100%; ' +\n",
" 'text-align: center; padding: 3px;\"/>');\n",
" titlebar.append(titletext)\n",
" this.root.append(titlebar);\n",
" this.header = titletext[0];\n",
"}\n",
"\n",
"\n",
"\n",
"mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n",
"\n",
"}\n",
"\n",
"\n",
"mpl.figure.prototype._root_extra_style = function(canvas_div) {\n",
"\n",
"}\n",
"\n",
"mpl.figure.prototype._init_canvas = function() {\n",
" var fig = this;\n",
"\n",
" var canvas_div = $('<div/>');\n",
"\n",
" canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n",
"\n",
" function canvas_keyboard_event(event) {\n",
" return fig.key_event(event, event['data']);\n",
" }\n",
"\n",
" canvas_div.keydown('key_press', canvas_keyboard_event);\n",
" canvas_div.keyup('key_release', canvas_keyboard_event);\n",
" this.canvas_div = canvas_div\n",
" this._canvas_extra_style(canvas_div)\n",
" this.root.append(canvas_div);\n",
"\n",
" var canvas = $('<canvas/>');\n",
" canvas.addClass('mpl-canvas');\n",
" canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n",
"\n",
" this.canvas = canvas[0];\n",
" this.context = canvas[0].getContext(\"2d\");\n",
"\n",
" var backingStore = this.context.backingStorePixelRatio ||\n",
"\tthis.context.webkitBackingStorePixelRatio ||\n",
"\tthis.context.mozBackingStorePixelRatio ||\n",
"\tthis.context.msBackingStorePixelRatio ||\n",
"\tthis.context.oBackingStorePixelRatio ||\n",
"\tthis.context.backingStorePixelRatio || 1;\n",
"\n",
" mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n",
"\n",
" var rubberband = $('<canvas/>');\n",
" rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n",
"\n",
" var pass_mouse_events = true;\n",
"\n",
" canvas_div.resizable({\n",
" start: function(event, ui) {\n",
" pass_mouse_events = false;\n",
" },\n",
" resize: function(event, ui) {\n",
" fig.request_resize(ui.size.width, ui.size.height);\n",
" },\n",
" stop: function(event, ui) {\n",
" pass_mouse_events = true;\n",
" fig.request_resize(ui.size.width, ui.size.height);\n",
" },\n",
" });\n",
"\n",
" function mouse_event_fn(event) {\n",
" if (pass_mouse_events)\n",
" return fig.mouse_event(event, event['data']);\n",
" }\n",
"\n",
" rubberband.mousedown('button_press', mouse_event_fn);\n",
" rubberband.mouseup('button_release', mouse_event_fn);\n",
" // Throttle sequential mouse events to 1 every 20ms.\n",
" rubberband.mousemove('motion_notify', mouse_event_fn);\n",
"\n",
" rubberband.mouseenter('figure_enter', mouse_event_fn);\n",
" rubberband.mouseleave('figure_leave', mouse_event_fn);\n",
"\n",
" canvas_div.on(\"wheel\", function (event) {\n",
" event = event.originalEvent;\n",
" event['data'] = 'scroll'\n",
" if (event.deltaY < 0) {\n",
" event.step = 1;\n",
" } else {\n",
" event.step = -1;\n",
" }\n",
" mouse_event_fn(event);\n",
" });\n",
"\n",
" canvas_div.append(canvas);\n",
" canvas_div.append(rubberband);\n",
"\n",
" this.rubberband = rubberband;\n",
" this.rubberband_canvas = rubberband[0];\n",
" this.rubberband_context = rubberband[0].getContext(\"2d\");\n",
" this.rubberband_context.strokeStyle = \"#000000\";\n",
"\n",
" this._resize_canvas = function(width, height) {\n",
" // Keep the size of the canvas, canvas container, and rubber band\n",
" // canvas in synch.\n",
" canvas_div.css('width', width)\n",
" canvas_div.css('height', height)\n",
"\n",
" canvas.attr('width', width * mpl.ratio);\n",
" canvas.attr('height', height * mpl.ratio);\n",
" canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n",
"\n",
" rubberband.attr('width', width);\n",
" rubberband.attr('height', height);\n",
" }\n",
"\n",
" // Set the figure to an initial 600x600px, this will subsequently be updated\n",
" // upon first draw.\n",
" this._resize_canvas(600, 600);\n",
"\n",
" // Disable right mouse context menu.\n",
" $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n",
" return false;\n",
" });\n",
"\n",
" function set_focus () {\n",
" canvas.focus();\n",
" canvas_div.focus();\n",
" }\n",
"\n",
" window.setTimeout(set_focus, 100);\n",
"}\n",
"\n",
"mpl.figure.prototype._init_toolbar = function() {\n",
" var fig = this;\n",
"\n",
" var nav_element = $('<div/>')\n",
" nav_element.attr('style', 'width: 100%');\n",
" this.root.append(nav_element);\n",
"\n",
" // Define a callback function for later on.\n",
" function toolbar_event(event) {\n",
" return fig.toolbar_button_onclick(event['data']);\n",
" }\n",
" function toolbar_mouse_event(event) {\n",
" return fig.toolbar_button_onmouseover(event['data']);\n",
" }\n",
"\n",
" for(var toolbar_ind in mpl.toolbar_items) {\n",
" var name = mpl.toolbar_items[toolbar_ind][0];\n",
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
" var image = mpl.toolbar_items[toolbar_ind][2];\n",
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
"\n",
" if (!name) {\n",
" // put a spacer in here.\n",
" continue;\n",
" }\n",
" var button = $('<button/>');\n",
" button.addClass('ui-button ui-widget ui-state-default ui-corner-all ' +\n",
" 'ui-button-icon-only');\n",
" button.attr('role', 'button');\n",
" button.attr('aria-disabled', 'false');\n",
" button.click(method_name, toolbar_event);\n",
" button.mouseover(tooltip, toolbar_mouse_event);\n",
"\n",
" var icon_img = $('<span/>');\n",
" icon_img.addClass('ui-button-icon-primary ui-icon');\n",
" icon_img.addClass(image);\n",
" icon_img.addClass('ui-corner-all');\n",
"\n",
" var tooltip_span = $('<span/>');\n",
" tooltip_span.addClass('ui-button-text');\n",
" tooltip_span.html(tooltip);\n",
"\n",
" button.append(icon_img);\n",
" button.append(tooltip_span);\n",
"\n",
" nav_element.append(button);\n",
" }\n",
"\n",
" var fmt_picker_span = $('<span/>');\n",
"\n",
" var fmt_picker = $('<select/>');\n",
" fmt_picker.addClass('mpl-toolbar-option ui-widget ui-widget-content');\n",
" fmt_picker_span.append(fmt_picker);\n",
" nav_element.append(fmt_picker_span);\n",
" this.format_dropdown = fmt_picker[0];\n",
"\n",
" for (var ind in mpl.extensions) {\n",
" var fmt = mpl.extensions[ind];\n",
" var option = $(\n",
" '<option/>', {selected: fmt === mpl.default_extension}).html(fmt);\n",
" fmt_picker.append(option)\n",
" }\n",
"\n",
" // Add hover states to the ui-buttons\n",
" $( \".ui-button\" ).hover(\n",
" function() { $(this).addClass(\"ui-state-hover\");},\n",
" function() { $(this).removeClass(\"ui-state-hover\");}\n",
" );\n",
"\n",
" var status_bar = $('<span class=\"mpl-message\"/>');\n",
" nav_element.append(status_bar);\n",
" this.message = status_bar[0];\n",
"}\n",
"\n",
"mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n",
" // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n",
" // which will in turn request a refresh of the image.\n",
" this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n",
"}\n",
"\n",
"mpl.figure.prototype.send_message = function(type, properties) {\n",
" properties['type'] = type;\n",
" properties['figure_id'] = this.id;\n",
" this.ws.send(JSON.stringify(properties));\n",
"}\n",
"\n",
"mpl.figure.prototype.send_draw_message = function() {\n",
" if (!this.waiting) {\n",
" this.waiting = true;\n",
" this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n",
" }\n",
"}\n",
"\n",
"\n",
"mpl.figure.prototype.handle_save = function(fig, msg) {\n",
" var format_dropdown = fig.format_dropdown;\n",
" var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n",
" fig.ondownload(fig, format);\n",
"}\n",
"\n",
"\n",
"mpl.figure.prototype.handle_resize = function(fig, msg) {\n",
" var size = msg['size'];\n",
" if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n",
" fig._resize_canvas(size[0], size[1]);\n",
" fig.send_message(\"refresh\", {});\n",
" };\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n",
" var x0 = msg['x0'] / mpl.ratio;\n",
" var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n",
" var x1 = msg['x1'] / mpl.ratio;\n",
" var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n",
" x0 = Math.floor(x0) + 0.5;\n",
" y0 = Math.floor(y0) + 0.5;\n",
" x1 = Math.floor(x1) + 0.5;\n",
" y1 = Math.floor(y1) + 0.5;\n",
" var min_x = Math.min(x0, x1);\n",
" var min_y = Math.min(y0, y1);\n",
" var width = Math.abs(x1 - x0);\n",
" var height = Math.abs(y1 - y0);\n",
"\n",
" fig.rubberband_context.clearRect(\n",
" 0, 0, fig.canvas.width, fig.canvas.height);\n",
"\n",
" fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n",
" // Updates the figure title.\n",
" fig.header.textContent = msg['label'];\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_cursor = function(fig, msg) {\n",
" var cursor = msg['cursor'];\n",
" switch(cursor)\n",
" {\n",
" case 0:\n",
" cursor = 'pointer';\n",
" break;\n",
" case 1:\n",
" cursor = 'default';\n",
" break;\n",
" case 2:\n",
" cursor = 'crosshair';\n",
" break;\n",
" case 3:\n",
" cursor = 'move';\n",
" break;\n",
" }\n",
" fig.rubberband_canvas.style.cursor = cursor;\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_message = function(fig, msg) {\n",
" fig.message.textContent = msg['message'];\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_draw = function(fig, msg) {\n",
" // Request the server to send over a new figure.\n",
" fig.send_draw_message();\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n",
" fig.image_mode = msg['mode'];\n",
"}\n",
"\n",
"mpl.figure.prototype.updated_canvas_event = function() {\n",
" // Called whenever the canvas gets updated.\n",
" this.send_message(\"ack\", {});\n",
"}\n",
"\n",
"// A function to construct a web socket function for onmessage handling.\n",
"// Called in the figure constructor.\n",
"mpl.figure.prototype._make_on_message_function = function(fig) {\n",
" return function socket_on_message(evt) {\n",
" if (evt.data instanceof Blob) {\n",
" /* FIXME: We get \"Resource interpreted as Image but\n",
" * transferred with MIME type text/plain:\" errors on\n",
" * Chrome. But how to set the MIME type? It doesn't seem\n",
" * to be part of the websocket stream */\n",
" evt.data.type = \"image/png\";\n",
"\n",
" /* Free the memory for the previous frames */\n",
" if (fig.imageObj.src) {\n",
" (window.URL || window.webkitURL).revokeObjectURL(\n",
" fig.imageObj.src);\n",
" }\n",
"\n",
" fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
" evt.data);\n",
" fig.updated_canvas_event();\n",
" fig.waiting = false;\n",
" return;\n",
" }\n",
" else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n",
" fig.imageObj.src = evt.data;\n",
" fig.updated_canvas_event();\n",
" fig.waiting = false;\n",
" return;\n",
" }\n",
"\n",
" var msg = JSON.parse(evt.data);\n",
" var msg_type = msg['type'];\n",
"\n",
" // Call the \"handle_{type}\" callback, which takes\n",
" // the figure and JSON message as its only arguments.\n",
" try {\n",
" var callback = fig[\"handle_\" + msg_type];\n",
" } catch (e) {\n",
" console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n",
" return;\n",
" }\n",
"\n",
" if (callback) {\n",
" try {\n",
" // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n",
" callback(fig, msg);\n",
" } catch (e) {\n",
" console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n",
" }\n",
" }\n",
" };\n",
"}\n",
"\n",
"// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n",
"mpl.findpos = function(e) {\n",
" //this section is from http://www.quirksmode.org/js/events_properties.html\n",
" var targ;\n",
" if (!e)\n",
" e = window.event;\n",
" if (e.target)\n",
" targ = e.target;\n",
" else if (e.srcElement)\n",
" targ = e.srcElement;\n",
" if (targ.nodeType == 3) // defeat Safari bug\n",
" targ = targ.parentNode;\n",
"\n",
" // jQuery normalizes the pageX and pageY\n",
" // pageX,Y are the mouse positions relative to the document\n",
" // offset() returns the position of the element relative to the document\n",
" var x = e.pageX - $(targ).offset().left;\n",
" var y = e.pageY - $(targ).offset().top;\n",
"\n",
" return {\"x\": x, \"y\": y};\n",
"};\n",
"\n",
"/*\n",
" * return a copy of an object with only non-object keys\n",
" * we need this to avoid circular references\n",
" * http://stackoverflow.com/a/24161582/3208463\n",
" */\n",
"function simpleKeys (original) {\n",
" return Object.keys(original).reduce(function (obj, key) {\n",
" if (typeof original[key] !== 'object')\n",
" obj[key] = original[key]\n",
" return obj;\n",
" }, {});\n",
"}\n",
"\n",
"mpl.figure.prototype.mouse_event = function(event, name) {\n",
" var canvas_pos = mpl.findpos(event)\n",
"\n",
" if (name === 'button_press')\n",
" {\n",
" this.canvas.focus();\n",
" this.canvas_div.focus();\n",
" }\n",
"\n",
" var x = canvas_pos.x * mpl.ratio;\n",
" var y = canvas_pos.y * mpl.ratio;\n",
"\n",
" this.send_message(name, {x: x, y: y, button: event.button,\n",
" step: event.step,\n",
" guiEvent: simpleKeys(event)});\n",
"\n",
" /* This prevents the web browser from automatically changing to\n",
" * the text insertion cursor when the button is pressed. We want\n",
" * to control all of the cursor setting manually through the\n",
" * 'cursor' event from matplotlib */\n",
" event.preventDefault();\n",
" return false;\n",
"}\n",
"\n",
"mpl.figure.prototype._key_event_extra = function(event, name) {\n",
" // Handle any extra behaviour associated with a key event\n",
"}\n",
"\n",
"mpl.figure.prototype.key_event = function(event, name) {\n",
"\n",
" // Prevent repeat events\n",
" if (name == 'key_press')\n",
" {\n",
" if (event.which === this._key)\n",
" return;\n",
" else\n",
" this._key = event.which;\n",
" }\n",
" if (name == 'key_release')\n",
" this._key = null;\n",
"\n",
" var value = '';\n",
" if (event.ctrlKey && event.which != 17)\n",
" value += \"ctrl+\";\n",
" if (event.altKey && event.which != 18)\n",
" value += \"alt+\";\n",
" if (event.shiftKey && event.which != 16)\n",
" value += \"shift+\";\n",
"\n",
" value += 'k';\n",
" value += event.which.toString();\n",
"\n",
" this._key_event_extra(event, name);\n",
"\n",
" this.send_message(name, {key: value,\n",
" guiEvent: simpleKeys(event)});\n",
" return false;\n",
"}\n",
"\n",
"mpl.figure.prototype.toolbar_button_onclick = function(name) {\n",
" if (name == 'download') {\n",
" this.handle_save(this, null);\n",
" } else {\n",
" this.send_message(\"toolbar_button\", {name: name});\n",
" }\n",
"};\n",
"\n",
"mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n",
" this.message.textContent = tooltip;\n",
"};\n",
"mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n",
"\n",
"mpl.extensions = [\"eps\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
"\n",
"mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n",
" // Create a \"websocket\"-like object which calls the given IPython comm\n",
" // object with the appropriate methods. Currently this is a non binary\n",
" // socket, so there is still some room for performance tuning.\n",
" var ws = {};\n",
"\n",
" ws.close = function() {\n",
" comm.close()\n",
" };\n",
" ws.send = function(m) {\n",
" //console.log('sending', m);\n",
" comm.send(m);\n",
" };\n",
" // Register the callback with on_msg.\n",
" comm.on_msg(function(msg) {\n",
" //console.log('receiving', msg['content']['data'], msg);\n",
" // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
" ws.onmessage(msg['content']['data'])\n",
" });\n",
" return ws;\n",
"}\n",
"\n",
"mpl.mpl_figure_comm = function(comm, msg) {\n",
" // This is the function which gets called when the mpl process\n",
" // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
"\n",
" var id = msg.content.data.id;\n",
" // Get hold of the div created by the display call when the Comm\n",
" // socket was opened in Python.\n",
" var element = $(\"#\" + id);\n",
" var ws_proxy = comm_websocket_adapter(comm)\n",
"\n",
" function ondownload(figure, format) {\n",
" window.open(figure.imageObj.src);\n",
" }\n",
"\n",
" var fig = new mpl.figure(id, ws_proxy,\n",
" ondownload,\n",
" element.get(0));\n",
"\n",
" // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n",
" // web socket which is closed, not our websocket->open comm proxy.\n",
" ws_proxy.onopen();\n",
"\n",
" fig.parent_element = element.get(0);\n",
" fig.cell_info = mpl.find_output_cell(\"<div id='\" + id + \"'></div>\");\n",
" if (!fig.cell_info) {\n",
" console.error(\"Failed to find cell for figure\", id, fig);\n",
" return;\n",
" }\n",
"\n",
" var output_index = fig.cell_info[2]\n",
" var cell = fig.cell_info[0];\n",
"\n",
"};\n",
"\n",
"mpl.figure.prototype.handle_close = function(fig, msg) {\n",
" var width = fig.canvas.width/mpl.ratio\n",
" fig.root.unbind('remove')\n",
"\n",
" // Update the output cell to use the data from the current canvas.\n",
" fig.push_to_output();\n",
" var dataURL = fig.canvas.toDataURL();\n",
" // Re-enable the keyboard manager in IPython - without this line, in FF,\n",
" // the notebook keyboard shortcuts fail.\n",
" IPython.keyboard_manager.enable()\n",
" $(fig.parent_element).html('<img src=\"' + dataURL + '\" width=\"' + width + '\">');\n",
" fig.close_ws(fig, msg);\n",
"}\n",
"\n",
"mpl.figure.prototype.close_ws = function(fig, msg){\n",
" fig.send_message('closing', msg);\n",
" // fig.ws.close()\n",
"}\n",
"\n",
"mpl.figure.prototype.push_to_output = function(remove_interactive) {\n",
" // Turn the data on the canvas into data in the output cell.\n",
" var width = this.canvas.width/mpl.ratio\n",
" var dataURL = this.canvas.toDataURL();\n",
" this.cell_info[1]['text/html'] = '<img src=\"' + dataURL + '\" width=\"' + width + '\">';\n",
"}\n",
"\n",
"mpl.figure.prototype.updated_canvas_event = function() {\n",
" // Tell IPython that the notebook contents must change.\n",
" IPython.notebook.set_dirty(true);\n",
" this.send_message(\"ack\", {});\n",
" var fig = this;\n",
" // Wait a second, then push the new image to the DOM so\n",
" // that it is saved nicely (might be nice to debounce this).\n",
" setTimeout(function () { fig.push_to_output() }, 1000);\n",
"}\n",
"\n",
"mpl.figure.prototype._init_toolbar = function() {\n",
" var fig = this;\n",
"\n",
" var nav_element = $('<div/>')\n",
" nav_element.attr('style', 'width: 100%');\n",
" this.root.append(nav_element);\n",
"\n",
" // Define a callback function for later on.\n",
" function toolbar_event(event) {\n",
" return fig.toolbar_button_onclick(event['data']);\n",
" }\n",
" function toolbar_mouse_event(event) {\n",
" return fig.toolbar_button_onmouseover(event['data']);\n",
" }\n",
"\n",
" for(var toolbar_ind in mpl.toolbar_items){\n",
" var name = mpl.toolbar_items[toolbar_ind][0];\n",
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
" var image = mpl.toolbar_items[toolbar_ind][2];\n",
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
"\n",
" if (!name) { continue; };\n",
"\n",
" var button = $('<button class=\"btn btn-default\" href=\"#\" title=\"' + name + '\"><i class=\"fa ' + image + ' fa-lg\"></i></button>');\n",
" button.click(method_name, toolbar_event);\n",
" button.mouseover(tooltip, toolbar_mouse_event);\n",
" nav_element.append(button);\n",
" }\n",
"\n",
" // Add the status bar.\n",
" var status_bar = $('<span class=\"mpl-message\" style=\"text-align:right; float: right;\"/>');\n",
" nav_element.append(status_bar);\n",
" this.message = status_bar[0];\n",
"\n",
" // Add the close button to the window.\n",
" var buttongrp = $('<div class=\"btn-group inline pull-right\"></div>');\n",
" var button = $('<button class=\"btn btn-mini btn-primary\" href=\"#\" title=\"Stop Interaction\"><i class=\"fa fa-power-off icon-remove icon-large\"></i></button>');\n",
" button.click(function (evt) { fig.handle_close(fig, {}); } );\n",
" button.mouseover('Stop Interaction', toolbar_mouse_event);\n",
" buttongrp.append(button);\n",
" var titlebar = this.root.find($('.ui-dialog-titlebar'));\n",
" titlebar.prepend(buttongrp);\n",
"}\n",
"\n",
"mpl.figure.prototype._root_extra_style = function(el){\n",
" var fig = this\n",
" el.on(\"remove\", function(){\n",
"\tfig.close_ws(fig, {});\n",
" });\n",
"}\n",
"\n",
"mpl.figure.prototype._canvas_extra_style = function(el){\n",
" // this is important to make the div 'focusable\n",
" el.attr('tabindex', 0)\n",
" // reach out to IPython and tell the keyboard manager to turn it's self\n",
" // off when our div gets focus\n",
"\n",
" // location in version 3\n",
" if (IPython.notebook.keyboard_manager) {\n",
" IPython.notebook.keyboard_manager.register_events(el);\n",
" }\n",
" else {\n",
" // location in version 2\n",
" IPython.keyboard_manager.register_events(el);\n",
" }\n",
"\n",
"}\n",
"\n",
"mpl.figure.prototype._key_event_extra = function(event, name) {\n",
" var manager = IPython.notebook.keyboard_manager;\n",
" if (!manager)\n",
" manager = IPython.keyboard_manager;\n",
"\n",
" // Check for shift+enter\n",
" if (event.shiftKey && event.which == 13) {\n",
" this.canvas_div.blur();\n",
" event.shiftKey = false;\n",
" // Send a \"J\" for go to next cell\n",
" event.which = 74;\n",
" event.keyCode = 74;\n",
" manager.command_mode();\n",
" manager.handle_keydown(event);\n",
" }\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_save = function(fig, msg) {\n",
" fig.ondownload(fig, null);\n",
"}\n",
"\n",
"\n",
"mpl.find_output_cell = function(html_output) {\n",
" // Return the cell and output element which can be found *uniquely* in the notebook.\n",
" // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n",
" // IPython event is triggered only after the cells have been serialised, which for\n",
" // our purposes (turning an active figure into a static one), is too late.\n",
" var cells = IPython.notebook.get_cells();\n",
" var ncells = cells.length;\n",
" for (var i=0; i<ncells; i++) {\n",
" var cell = cells[i];\n",
" if (cell.cell_type === 'code'){\n",
" for (var j=0; j<cell.output_area.outputs.length; j++) {\n",
" var data = cell.output_area.outputs[j];\n",
" if (data.data) {\n",
" // IPython >= 3 moved mimebundle to data attribute of output\n",
" data = data.data;\n",
" }\n",
" if (data['text/html'] == html_output) {\n",
" return [cell, data, j];\n",
" }\n",
" }\n",
" }\n",
" }\n",
"}\n",
"\n",
"// Register the function which deals with the matplotlib target/channel.\n",
"// The kernel may be null if the page has been refreshed.\n",
"if (IPython.notebook.kernel != null) {\n",
" IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n",
"}\n"
],
"text/plain": [
"<IPython.core.display.Javascript object>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"<img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABaAAAAPwCAYAAADH/tkFAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAGTiSURBVHhe7N0HfJzVlTfgK8kNF5ptqgmmmN5C7zWhpZCQSsqGNNJ3U3dJwiYESGVTviSkkGRJJb1sQu8h9N57NR1TTDMukv3d+84dZjQaSSNbsmak58nv7Hve15abBlj/5+jcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACMCG35OlodGOv/xeqI9dNYX4tV7ZOx3herM9acWO+JdX+s5F2xjiq14bhYvyi19U2dOnXJzJkz8x0AQPO6+uqrn4iX6aU7AACApTeaA+gUOt8R65WxHox1ZazDYt0Sq2yfWJfHmhfrQ7H2jvWWWKvGuirW9rGWxLo61naxno5V13bbbbfkqqvShwAANLe2trb0/9uk/z8HAABgmbTn62i0Y6y7Yt0Ta2Gs38U6JFa182Ol8Dm5LNaMUhsOiHV2rKdipdA59WmaGgAAAACAbDQH0GvHeqDUFtIUdHrWm/fGOr3UDvhjAQAAAABGndEcQNdbP5LWadTzjljpy1CPL+4a/9gjYqW9G1fNmZNWSAMAAAAAjB6jOYBOU8vrlNpCWq/xcKnt5hWxPh/rtbEWpAdRox97YqwUXG8/fbpzfAAAAACA0WU0B9Dp0MFZsdaLNS7WW2P9PVa1l8f6cawUPj+eHmRnxto/1iq5Up+eAQAAAACQjeYAujPWR2Ol4PjWWH+IdXOsY2KlwDlJKzcmx/pjrOtilQPqdPjgsbFSiJ0qfUx6BgAAAABAVm+XMUNgu+22W3LVVWkdNABAc2tra7s6XtIaMQAAgGUymiegAQAAAAAYQgJoAAAAAACGhAAaAAAAAIAhIYAGAAAAAGBICKABAAAAABgSAmgAAAAAAIaEABoAAAAAgCEhgAYAAAAAYEgIoFvQt866PWz632fkOwAAAACA5iSAbkGLl4SwsGtxvgMAAAAAaE4C6BbU3hZCV0qhAQAAAACamAC6BbWnBDpaskQIDQAAAAA0LwF0C2pvKwXQpqABAAAAgGYmgG5BHXkCWv4MAAAAADQzAXQLygPQYbEVHAAAAABAExNAt6COnEALoAEAAACAZiaAbkF2QAMAAAAArUAA3YLa7YAGAAAAAFqAALoF5fw5LJZAAwAAAABNTADdgjpemoAWQAMAAAAAzUsA3YLayjugBdAAAAAAQBMTQLeg8goO+TMAAAAA0MwE0C2oI09AW8EBAAAAADQzAXQLai+v4HAIIQAAAADQxATQLag97+AwAA0AAAAANDMBdAsq74A2AQ0AAAAANDMBdAvqyAm0HdAAAAAAQDMTQLegNocQAgAAAAAtQADdgjpeCqCLCwAAAABAUxJAtyA7oAEAAACAViCAbkHtdkADAAAAAC1AAN2C2ssrOBYXFwAAAACApiSAbkEd+bNmAhoAAAAAaGYC6BbUlieguwTQAAAAAEATE0C3oI4cQC8RQAMAAAAATUwA3YLKO6C77IAGAAAAAJqYALoFtZfyZzugAQAAAICmJoBuQe05gRZAAwAAAADNTADdgsorOBZbwQEAAAAANLHRHkAfGOv2WHfFOjI9qLFnrGtidcZ6Y3pQ5Ruxbo51a6zvxsqLMYZeR/6smYAGAAAAAJrZaA6gO2KdEOugWJvFOixfq82OdXisk4u7il1j7RZrq1hbxNoh1l6xlou28iGEAmgAAAAAoImN5gB6x1hp8vmeWAtj/S7WIbGq3Rfrhli1yy5S8jsh1rhY42ONjfVYrOWiIwfQSwTQAAAAAEATG80B9NqxHii1hQdjpWeNuDTW+bEeyXVmrLSKY7ko74DusgMaAAAAAGhiozmArrezudGR4g1jbRprRqwUWu8bK+2LrnVErKtSzZkzp3gwGNrtgAYAAAAAWsBoDqDTxPM6pbaQwuSHS22/Xh/rsljP5zo91s6xap0Ya/tU06dPLx4MhvIE9OLFAmgAAAAAoHmN5gD6ylizYq0XK+1yfmusv8dqRDqcMB06OCZW2v+c+uW2gqOjPQfQ8mcAAAAAoImN5gC6M9ZHY5X3N/8h1s2xjon12ljJDrHSpPSbYv04Vvr25E+x7o51Y6zrc/0j1nKR8+fQZQUHAAAAANDERnMAnZwWa6NYG8T6cnoQfSFWeRI6TUmn1RyTYk2NtXmspCvWB2KlPdCbxfpkrOWmvIJjiQAaAAAAAGhioz2AbknlALrLDg4AAAAAoIkJoFuQHdAAAAAAQCsQQLegPAAdFkugAQAAAIAmJoBuQeUVHIvtgAYAAAAAmpgAugVZwQEAAAAAtAIBdAsqr+DoMgENAAAAADQxAXQL6sgJ9BIBNAAAAADQxATQLai8A7rLDg4AAAAAoIkJoFtQux3QAAAAAEALEEC3oJw/h8USaAAAAACgiQmgW1DHSxPQAmgAAAAAoHkJoFvQSzugBdAAAAAAQBMTQLegcgAtfwYAAAAAmpkAugWVd0B32QENAAAAADQxAXQLsgMaAAAAAGgFAugW1JZXcCw2AQ0AAAAANDEBdItKU9DyZwAAAACgmQmgW1TawtFlBQcAAAAA0MQE0C0qreGwAxoAAAAAaGYC6BbV0dYW5M8AAAAAQDMTQLeoYgWHJdAAAAAAQBMTQLeo9uIQQgE0AAAAANC8BNAtqj3tgDYBDQAAAAA0MQF0i+ooJqDzDQAAAABAExJAt6hiB7QVHAAAAABAExNAt6i0gmOJABoAAAAAaGIC6BaVAuguOzgAAAAAgCYmgG5RdkADAAAAAM1OAN2i2tpCWCyBBgAAAACamAC6RZUmoAXQAAAAAEDzEkC3qGIHtPwZAAAAAGhiAugW1Z5WcJiABgAAAACamAC6RaUJ6CUCaAAAAACgiQmgW1SxgsMhhAAAAABAExNAt6j24hDCfAMAAAAA0IQE0C2q2AEtgQYAAAAAmpgAukV1FBPQAmgAAAAAoHkJoFtUW9oBLX8GAAAAAJqYALpFdbSFsMQENAAAAADQxEZzAH1grNtj3RXryPSgxp6xronVGeuN6UGVl8U6K9atsW6JNTPWctWeJqDtgAYAAAAAmthoDaA7Yp0Q66BYm8U6LF+rzY51eKyTi7vufhnr+Fibxtox1uOxlqt2O6ABAAAAgCY3WgPoFBqnyed7Yi2M9btYh8Sqdl+sG2ItLu4qUlA9JtbZxV0Iz8eaV2qXn/a2+Aur/ZUBAAAAADSR0RpArx3rgVJbeDBWetaIjWLNjfWXWNfGSpPQaaJ6ueowAQ0AAAAANLnRGkC35Wu1RtPcNP28R6xPx9oh1vqx0qqOeo6IdVWqOXPmFA8GS7EDWgANAAAAADSx0RpAp4nndUptYUash0ttv9LHpsnntL4jHVD4t1jbxqrnxFjbp5o+fXrxYLCkANoZhAAAAABAMxutAfSVsWbFWi/WuFhvjfX3WI1IH7tKrHKivG+sW0rt8lPaAS2BBgAAAACa12gNoNPk8kdjnRnr1lh/iHVzrGNivTZWktZrpGnnN8X6caz07UlXrLR+49xYN8ZK6zx+Emu5sgMaAAAAAGh2ozWATk6LlQ4U3CDWl9OD6AuxypPQadI5reaYFGtqrM1jlZ0da6tYW8ZK+58Xxlqu2qzgAAAAAACa3GgOoFuaFRwAAAAAQLMTQLcoKzgAAAAAgGYngG5RaQVHlwAaAAAAAGhiAugW1dHWFuTPAAAAAEAzE0C3qLQDussOaAAAAACgiQmgW1S7HdAAAAAAQJMTQLeo9ra2sNgENAAAAADQxATQLSrtgJY/AwAAAADNTADdotrjZ+7RZ+eHky6+Nz8BAAAAAGguAugWlVZwJF/6xy3FFQAAAACg2QigW1Q5gAYAAAAAaFYC6BbV0S6ABgAAAACamwC6RRmABgAAAACanQC6RXVIoAEAAACAJieAblHtVnAAAAAAAE1OAN2iqgeglyxZkjsAAAAAgOYhgG5RP7nwntyF8OQLC3MHAAAAANA8BNAtanHV0PPCzsW5AwAAAABoHgLoEWDewq7cAQAAAAA0DwF0izp027VzF8Jvr5idOwAAAACA5iGAblFj2yufup9ddG/uAAAAAACahwC6RY3paMsdAAAAAEBzEkC3qN9cbu0GAAAAANDcBNAAAAAAAAwJAXSLmrHKCrkDAAAAAGhOAugWtdN6U3MHAAAAANCcBNAtavUVx+cOAAAAAKA5CaBb1CoTx+UuhJUnjs0dAAAAAEDzEEC3qMN3mxmOPWTzop87b1FxBQAAAABoJgLoFjW2oz28c5eZ+Q4AAAAAoPkIoFvcFmuvGPbbZLV8BwAAAADQPATQLW5Me3tY2LU43wEAAAAANA8BdIt7et7CcPfjz+c7AAAAAIDmIYBucfc/OS88/Mz8fAcAAAAA0DwE0AAAAAAADAkBNAAAAAAAQ0IA3eJWmTg2dwAAAAAAzUUA3eL223T1sNZKE/IdAAAAAEDzEEC3uDHtbaFz8ZJ8BwAAAADQPEZ7AH1grNtj3RXryPSgxp6xronVGeuN6UGNFWM9FOv7xd0w6GhvC10CaAAAAACgCY3mALoj1gmxDoq1WazD8rXa7FiHxzq5uOvp2Fj/LLXDI01Ady0RQAMAAAAAzWc0B9A7xkqTz/fEWhjrd7EOiVXtvlg3xFpc3HW3XazVY51V3A2Tjvb20NUlgAYAAAAAms9oDqDXjvVAqS08GCs9a0T6c/tmrM8Ud8NoTIcd0AAAAABAcxrNAXRbvlZrNMn9cKzTYlUH2PUcEeuqVHPmzCkeDDY7oAEAAACAZjWaA+g08bxOqS3MiPVwqe3XLrE+Giut6PifWP8W62uxap0Ya/tU06dPLx4MtrQDunNxvQ0hAAAAAADDazQH0FfGmhVrvVjjYr011t9jNeLtsV4Wa2asT8f6ZawjYy13aQI6DUAvNgUNAAAAADSZ0RxAd8ZKU8xnxro11h9i3RzrmFivjZXsECtNSr8p1o9jpW9vKmkCOulaIoAGAAAAAJrLaA6gk7THeaNYG8T6cnoQfSFWeRI6TUmn1RyTYk2NtXmsWj+PlYLsYdHRXvoU2gMNAAAAADSb0R5At7zyBHSnABoAAAAAaDIC6BZ38d1PFNeHnn6xuAIAAAAANAsBdIu74PY5xfWa2U8XVwAAAACAZiGAHiEWO4QQAAAAAGgyAugW98G90vmJIcxabUpxBQAAAABoFgLoFrfLBlOLa0f8TN73xAthvc+eGu56/LniGQAAAADAcBJAt7gJY0qfwvmLFoe/X/9wSJs4/nbtw8UzAAAAAIDhJIBucRPGdhTX+Yu6QmfX4qIf09FWXAEAAAAAhpMAusWVA+gFnYvD4nwOYUebABoAAAAAGH4C6BY3YWzpUzhvYVdYnPZvRPJnAAAAAKAZCKBbXGcee/70H68PZ93yWNG3SaABAAAAgCYggG5xi/Le5+Sux58vru0CaAAAAACgCQigW9ykcWNyV/Hs/EW5AwAAAAAYPgLoFjdpfM8A+ocX3J07AAAAAIDhI4BucRPHdeQOAAAAAKC5CKBb3PgxPT+Fb9xuRu4AAAAAAIaPALrFtdU5cHDa5PG5AwAAAAAYPgLoEahr8eLcAQAAAAAMHwH0CNS5eEnuAAAAAACGjwB6BDrp4vtyBwAAAAAwfATQAAAAAAAMCQE0AAAAAABDQgANAAAAAMCQEEADAAAAADAkBNAAAAAAAAwJATQAAAAAAENCAD3CbL3OyqGtLd8AAAAAAAwjAfQI09m1OCxZEkLX4vh/AAAAAACGkQB6BJixygq5C+GFBZ3FdVHX4uIKAAAAADBcBNAjwFmf2DN3Iay0wtji+tiz88Ojz8wvegAAAACA4TBSAuj/iLVirLT9+Gexrom1f6xRYeK4MbkL4fk8Ab3X8ReEnb96btEDAAAAAAyHkRJAvyfWs7FS6Dw91rtjfS3WqDN5QmkCGgAAAABguI2UADpNPicHxzop1vWxys9GlVH5mwYAAAAAmtJICaCvjnVWrBRAnxlrSqxReQrfqpPG5Q4AAAAAYHiNlAD6vbGOjLVDrHmx0h6KtIZj1HnTdjNyBwAAAAAwvEZKAL1LrNtjzY31jlhHxXom1qhx8vt2Cqd8bPcwfuxI+ZQCAAAAAK1upKSVP4yVJp+3jvWfse6P9ctYo8auG04LW6y9UhjbIYAGAAAAAJrDSEkrO2MtiXVIrP+XK+2BHnUE0AAAAABAsxgpaeVzsT4b652xTo3VESvtgR51rrz3qdwBAAAAAAyvkRJAvyXWgljvifVorLVjHR+rLwfGSnuj74qVDjCstWesa2Kl6eo3pgfZNrEujXVzrBtipZ+7abS15SZbvDgNhgMAAAAALH8jJYBOofNvYq0U69Wx5sfqawd0mpA+IdZBsTaLdVi+Vpsd6/BYJxd3FWnX9L/F2jxWCrG/E2vlWE1h+pTxuSt58oWFuQMAAAAAWL5GSgD95lhXxHpT7i+PVT21XGvHWGny+Z5YKaH9Xay0P7rafbHShPPi4q7ijlh3ltrwcKzHY00v7prABtMn567knjnP5w4AAAAAYPkaKQH052PtEOtdsdJ0cgqY/ztWb9KKjgdKbeHBWOnZQKWfZ1ysu4u7JrDmyivkrqTLCg4AAAAAYJiMlAA6/T7SJHLZk7H6+r3VbEouDDSpXTPWr2K9O1btlHTZEbGuSjVnzpziwVCbOinl4RUTx4/JHQAAAADA8jVSAugzYp0ZK+1sTnVqrNNi9SZNPK9TagszYqV1Go1aMVb6OY6KdVl60IsTY22favr05bOlo6O9e7Z+xb0piwcAAAAAWP5GSgD9mVgp7N0q1ta5/69Yvbky1qxY68VKI8NvjfX3WI1I3/+vsdIhh39MD5pJR1v3ANoGDgAAAABguIyUADr5c6xPxvpErBQQ96Uz1kdjpanpW2P9IdbNsY6J9dpYSdopnSal08GGP46Vvj1JhxzuGStNWl+Xa5tYTaG9ZgJ65/Wn5g4AAAAAYPmqtwu5lTwXq96Mb/p9pedpVUZT2G677ZZcdVVaBz30Zh6ZtoOU/N9Hdgtbr7NyvgMA6F9bW9vV8ZLWiAEAACyTVp+AnhIrhcy1VX4+6l1w+5wikP7qaWnQGwAAAABg+RlJKzio4/+uf6i4/vjCe4orAAAAAMDyIoAe4TZdwyA4AAAAADA8BNAj0O4bTstdCKfe+EjuAAAAAACWLwH0CPSdt24TPrDX+vkOAAAAAGB4CKBHoGmTx4cP7rlBvqvo7Fqcu749N39RWNDZle8AAAAAAJaOAHqEGjum56f20B9ekru+bXn0WeFNP7o03wEAAAAALB0B9Ag1pr0tdxU3PPhM7vo3kO8LAAAAAFCPAHqE6qgTQAMAAAAALE8C6BGqo21gAfTDc18MB3z7wvDYs/PzEwAAAACAZSOAHqHaBzgBffLls8Ptjz0XdvrKufkJAAAAAMCyEUBTGNPRM7Ce89yC3AEAAAAADJwAmsLYjp4vhU/+4brcAQAAAAAMnACawrg6AfRNDz2Tu4G78I454a7Hn893AAAAAMBoJICmUG8Fx4LOxbkbuH/73yvCK771z3wHAAAAAIxGAuhRpmvxktx1V28Fx7yFXbkDAAAAABg4AfQo8+drHgwzjzw1PPrM/PykpN4KDgAAAACAZSF1HMFWGNuRu4pfXnpfcb354e77nTvae67gSJ6Ztyh3AAAAAAADI4AewSaNH5O7iiV5A0ftKo6u8jfU+N55d+YOAAAAAGBgBNAj2OTxPSegewugF/eyG/rFRfZAAwAAAABLRwA9gk0cV2cCOl9rJ547ewmg73jsudzVl4Lrzq7F+S4F3EvCDy64K98BAAAAAKOZAHoEm1RnAvrWR54trgsWVULjZHEvKziuvO/p3NV3yAkXhw0/f3q+K33/b5xxe74DAAAAAEYzAfQINm5M5dN78JZr5K7k6H/cnLuS2pUcjbrxoe6HGS7s7B5sAwAAAACjlwB6BLt29tzchbDjzFVzV/Lc/M7clSxNAH3WzY/mrqK3wwwBAAAAgNFHAD2CrTJxXO5CmDC2+zqON28/I3clSxNAH/Grq3MXwqK8B3pRzQR0b4cbAgAAAAAjnwB6BNt+5iq5C2FMR/dP9YxVJuauZKCTy7WB9Z2PPV9c53d2FdeyhVUHFAIAAAAAo4sAegR7+Tor5y6EufMW5q6ksyYY7uoqBco7r999VceU8WNy113n4u4f/+KiUvD80ZOvLa5lXznt1twNzCk3PBw+/JvKhDUAAAAA0HoE0CPY7rOm5y6EPar6ZGEOnMvKE9A/f/eO4dr/fmXRJ4uqgubL7nky3PHYc0VfOwFdG2iX/fLS+3M3MCnIPu3GR8OCmolqAAAAAKB1CKBHsJetWlmzseFqk3NXUh0YL1myJNz1+POhra20K3qVSePCq7Zcs/i26qD5rSdeFvb/9oVF31kTQKcAO/04g+2FBQJoAAAAAGhVAugRbEx7W+7iJ7rSFi6798ni+uTzC8KrvntROOWGR0J1fnz8m7YqrovypPSvL+s+yfzP2+fkruSki+8Lp9/0aL7rbmkOOCzrbbIaAAAAAGh+AugRrL0qdW5L481Vbnro2eL64d9cE255pNRXmziu++7no/52U+5Kfnzh3bkrOfuWx8Jn/nh9vutuaSajO/KvvXbSGgAAAABoHQLoUSwFw5ff+1S+G5hygF3thYX112XMfmpe7hr3UgBds6sa6rn90efC/U++kO8AAAAAaBYC6FHs8ecW5G5oPT1vYe4a15EntqsPQYTeHPCdC8Nex1+Q7wAAAABoFgLoEW7H9VYNm6wxJd91d98TjU2Mzjzy1NxV7LXR9Nz1r3b9R3/mL+oKL8ZKTEDTn8XWtAAAAAA0LQH0CPeHD+wSzvj4nvmuu7eceFnu6tt0zRVz190djz0X/nlH90MI+/JiL6s5evP7Kx/IXToE0QQ0fbvk7tKBmgAAAAA0HwE0vdpj1rTcdbf/ty/MXXcHb7lG7rr7xSX35a4xCzsrofNdjz+fO6gvTcwDAAAA0JwE0PTqxAvvyV1jelvXvKAqUG7ED/95d+5C+Pjvr8sd1LfQlDwAAABA0xJAjyL/95HdwjfftHW+G3wLOutPovb2vNa///bacNV9T4WnXuh+aOGSJXb80rvFXh8AAAAATUsAPYpsvc7K4Q3bzch3g+PVW62Zu7QKoTSJOmXCmOI6ddK44nrZPU8V177MfnJe+Pv1D4c3/ujS/KSi0yFz9GHCmI7cAQAAANBsRnsAfWCs22PdFevI9KBGOr3vmlidsd6YHlR5V6w7c6W+5f3g7dvmruRDe2+Qu959/22Vj3n8ufnFdceZq4bLP7dfOOndOxT3jfjhP9OnoL5nX1yUO+hp7VVWyB0AAAAAzWY0B9BpbPKEWAfF2izWYflabXasw2OdXNxVrBrri7F2irVj7leJ1dIO3rIyzZy8b/f1cteYR54pBdDfees2YfUVJ4SxHY2/vH57xQO56+mv1z6UO+hpoDvGAQAAAFh+RnMAnYLjNHabTtpLS4d/F+uQWNXui3VDrNqE64BYZ8dKuyWezn2apm5ZW81YKXcVE8YObLXBvIVdYfqU8WHKhLHF/fgxjb28Ovs5RC6t5oDevO6Ei3MHAAAAQLMZzQH02rGqx24fjJWeNWJZPrbp/Ogd24ZfvTcNc3c3kAnmso62ttyFsMK4SoC9qI+Q+QcX3J27+sa0V35MAAAAAKB1jOYAul6q2ehpd41+7BGxrko1Z86c4kEzeOsO6+Su5MAt1gwrrVCaWq42tmPgwW9HVVi8QtUE9RG/TH8MIdz+6HNh5pGnhrsef664v+Ox58K3zr6j6Hsz1w5oAAAAAGhJozmATlPL1UnsjFiN7npo9GNPjLV9qunTpxcPmsHX3rBV7vrWVjXN3KjqD6le4XH+7aUA/u/Xl/Y5n37jo8X1bw3sd35mngAaAAAAAFrRaA6gr4w1K1Y6aW9crLfG+nusRpwZa/9Y6eDBVKlPz1rGZw7YOHfL7v17VA4rrJ6ArrcDuryio2tJaWC8v/UbSb0J6K7FS8Lvr5zdY3/0kvzjMjpdfX9ayQ4AAABAsxjNAXRnrI/GSsHxrbH+EOvmWMfEem2sZIdYadr5TbF+HCt9e5IOHzw2VgqxU6WPSc9axltq1nAsjfJu5k9XhdnVO6DrTVCX90p3di0Jc+elsx/7l8LmWn+86oHwX3++Mfz0onvDv+6cE44/87Zitcd6nz0tfw9GoxsenJs7AAAAAJrBaA6gk5RWbhRrg1hfTg+iL8QqT0KncDmt15gUa2qszWOV/W+sDXOdlB60krHtjX3qbzh6/7DJGlPyXXflfHn8mMqqjTqZczdjcgD92LPzwzbHnF30S+PpvJbjxgefCe/82RXhhPMrk9QpiGZ0Ov7M23MHAAAAQDMY7QH0qDWmwQMGV5wwNrz+5Wvnu+7aqs5i3GB6yui7r+Cop3yw4R+vToPlS++2R58trqfe+EhxheTFRV25AwAAAKAZCKBHqUYD6OTtO6+bu+5WX2l87irBc3s/I9DlFRzLIk04/991jZ4XyWhyyNZr5Q4AAACAZiCAHqUaXcGRrDC2smKj7E3bzQi/P2KXfJcC6NKP198E9IV3zMld/7ZZZ+XcLb2nXlhYrOlgdBiM1wwAAAAAg0cAPUq19xMUV6sXKk8c1xHWWnmFfJe+T+na3wT0ubc9nrv+/emDlYA7BclL45ATLgqv+f5FYcmSngcZAgAAAABDSwBNw8aPqbxcnnmxdAhgWUcOnvsKtm9+eGCTyNVh9tx5pQB68eLGguRy4PzAUy8W10N/eElxZWQbyBsrAAAAAAw9ATQN+d5hLw9nfHzPfBfChJq1HNfnNRd9rZZ+1Xcvyl1jqoepZz81r7h2NTjJ3FkTVF87e27uGMkWdi7OHQAAAADNQABNQ16z9VphvWmT8l33aehqz87vzF3JSe/eIXcD11aVQB9+0pXFtavBCeh6QeSCzq6w81fODWfd/Gh+wkizsEsADQAAANBMBNAslf03XyN33d31+PO5K9l49Sm5W3YpVK6dbO7NxXc9kbuKufMWhUefnR8+99eb8hNGgulTxoe3bL9O0ZuABgAAAGguAmiWym4bTstd33qblF4aP/nXPaGzwQnXOc8vyF3FR35zTXFd7EDClvN/1z0U3v/Lq/Jdd+nTmXY/j4m1yAQ0AAAAQFMRQI9yK60wNndDY+rk8WH9qtUdvbn7KwfnrrsdZq6SuxCOP/P2cMsjz+a7+l611ZrFdXr8eWtddf/TxbV8QCGt4z9+d104+5bH8l2tJcW+8HFj2k1AAwAAADQZAfQodvnn9gsX/uc++a4xE8d1P3ywEfc88ULuetfR3hYuOXLffFfx3t3Xz13J235yee7qe8dO6xbXFVcYG+6e030dSFntnmpax3Gn3JK7EOYv6gqf/+uN4el5i0LaFj62QwANAAAA0GwE0KPY6itOGPAE9Lmf2iv8/oid813FGvHHSsq7eKvtt8lquevbWiuvkLuKsR2Vgwj7ctSrNg2/eu+OYUz+/p1dS8LzvQTNjR5kSPP56UX35i6Ev1zzUPjN5bOLz2eagH7mxUXhF5fen78VAAAAgGYggGZA1lxphbDT+lPzXcW/7zeruKYgsNYrNls9d40b11F6aabJ6N6sNqWyZuN9e6wf9pg1/aXv37l4cZ8fO1DXPTA3/Pifd+c7mkH1a62tmIEumbfQhDsAAABAsxBAMyiWxP8l9QLoCWMbf5lNnTSuuH73sG2Ka1+zyif+2/a5q0gH0SVpKnYwVz2/7oSLw1dPv21Ipqd/+q97ikP2GJjqNxiqX3eX3v1k7npK4fQTdQ6oHCpp3/hpNz7icEQAAABg1BJAM6jqhb4rjG18b/SWM1YqruPHlD5mcR+B72PPzs9dRTmU/OQfrg+v+f5FRT+YykFiCjHvf7K023rrL50VZh55aljQ2VXcD9Rxp95aHLLHwHRUpc5V+XPo7OM18/oTLgnbH3dO+OCvrg7fO/fO/HTonHHTo+HDv7kmHP33m/MTAAAAgNFFAM2gaM9hYL0AenxNAL31Oivnrqfy6o10oFzS28TxKR/b/aWfs1r549I+4IF68Ol54ZrZTxf9vU+8EDrrTK2ed9vj4QcX3FWEmHsdf0HxrPxzpbCxmT36zPwRdUhfe9W/vdqqXgtrrdRzl3jZ7Y89V1zPuPnR8M2z7whfPe3WsN5nTy2eDYWTr5hdXNOuagAAAIDRSADNoCjHf+VVHNUm5Gnmst+8b6fc9fTl128ZPrLPBmHXDUp7pquDxWqzVp8cJo3vOVk90L3P8xd1hW+ffUcxvbz7188Ph/7gknDDg3PDPv9zQXjnz67I36siTbN+44zb811pxULZQALoo/52Y3jvz6/Md0MvBfk7f/Xc8Mk/tN6kdW9T8B1VCfTPL7kvdyFcdk/vKzhq/fjCewZ1VUutoVjZAgAAANBKBNAMir4moFcYVwmKN1p9crfVCcnO66+auxCmTxkfPnPAJqE9B8nlnc57bTS9uJalSeld6hyGWP7+fUk/1mEnXlaszfjJhfeE/3funeFXl96fvzWE137/4uJ6aQ4yq0PmWqfc8Eju6q8E6c2vL5sdzr3t8Xw39NKhjEn1r7cVvP4HF4cD/9+F+S6EvTeuvA5qX0dv3+llxfVbZ99RXP941QPhrJsfDZfc/URxPxyeX+BARAAAAGB0E0AzOHIWWG/gs/YQwurVCb98z47hfw/fId/1NHPapOK6x6xp4TMHbFz0SZqMrjcd3cgE9Pgx7S+Fy2kNQ/LQ3BeLaz19TchWf9yDT1f66x+YG+7M6x6aQc6fW861s+eGOx57Pt+FMG3y+NylMP3h3JVMmTC2uJanjj/zpxvCEb+6OrztJ5eHB56aVzzrzUDePBiIGx58JncAAAAAo5MAmkFRjn3rreCoPoQw7WgeU5VA77nR9DBx3Jh819N60yaFKz//ivDe3dcLb9h2Rn7au+ofuzf11iKcdHFlhUO1NP3cVzh96d2VdQ+PP7egmKo+8+ZHwyEnXBxe+e0Lw3fOKQXcvaleL9HXpPWyKv8eBrqipNlUf+5Or1l5ktd/vzTtXe3Z+X3vBN/pK+fmDgAAAIDBJIBmUPS1gmNCVQD9o3dsF79vvmlQWsuRpp3XWGlCftK7RgLWu+ZUJmr78+rvXRQ+9Jur811P/7xjTu4qPvCryvf/zjl35q6ienL3nicqv5bB2hec9lmfcP5dxbXsFd/6Z3Ft9Z3EnfnXXxvWp097edd4vd/iEGb7vapdv5EOgexvEhsAAABgpBFAMyjKg8eL6yR91QH0OqtOrLs6Y7DUC6C3mrFS7kruf7LxEPDmh58NNz30bL5bOnPnLcxdyUdPvjZ3KRiu7DfuGqSUNO2zPv7M28PPLrq3mHxO09gjRVeebj7txu7Tz6tOGtdt13itJ19YWEynN+KJ5xeE5+pMTKdA/8g/39Dwuo7n53cPoNMhkHt84/x8BwAAADA6CKAZFG15CUf9CejBe5n94QO7hG+9eet8F8L/fWS3cMrHds93lVUg1Y48aJPcDY9tjjk7d317/NkFuatvz2+cH35+8b35rncLOksh7dx5i8JP/3VPsY+6VfzqsvvDg0/3/gbB2bc8Vlx/f9UDxbXsiecXhkPzipbXbbNWca127Cm35K5/2x93Ttjy6LPyXcX5tz0efnflA+GL/3dzftK3Wx9dtjcuAAAAAEYCATSDojzUXG8Celx5Oe8g2HG9VV8KGpOt11k5bLF2ZcJ5lUnjclfR2TV0+xem1vn5llZv07FX3/90Mb07+6l54eh/9B+k3vfEC8X1xAvvaamVGyko/++/3RR2/3rvU8KL4ufytkefDRfWWX2SpqCTv133cFiYQ/iyux7vf+1K+jM+8cK7811P5TUzi7oaO9HxtBseyV13jU5iAwAAAIwEAmgGxdMvlNZM3PjQM8W1Wnnlxq4bTC2uZZutuWLuhlZtGDmY0mqHRn3rrNuLKdqB+tWl9Q9I7M2l91QORvzlpffnrvn9159vyF3fDvzOv3LXu42OOj13A/OV027LXSkQr3Zdvv/XnU8U17IXF3bVDaV3nzUtdz0N5YGTDI1P/P46bx4AAADAUhBAMyjG5QPg5i+qHHxX7YrP7Rf+9/Ad8l0I531qr/D7D+yc74bW/M6ul6Zjh9N3z7srvPvnV+a7xrUP8NTGB59+MXet5akBhPm13rx9ZSp+sNTuzi7vEt9zo+nFtWzTL5wRZn3+9PDHmrUga6zY+6GZ5TUpZekNnLSvm+b112sfyh0AAAAwEAJoBsVqU8YX183X6n7gX9lqK07odhjh+tMnhykTxua7obXOKhPDEXuun++W3rgxS/+PS2/BfCM6hvDQxmYykGnyWl87dKvcNWb7dVfJXeP6OzzzM3/qPsHd2cf6kwWLugfQLz/27LDb184LnQ2u9yi7ZvbTxYqWgUiHKKZJ3jNuqr8ihL610k51AAAAaAYCaAbFDuutGtZeeYXwH/vNyk+G37/+c5+i0p7o9+y2XvjiazbL37J0PvXKjXI3cK+rmaYdiI4BTkA3gyvufaoIOQcy1bvyCo2/IfGKTVfLXQjTJo8f0JT4mitNCJ/cf+Cfy/LPcM6tj4VXfuuf+a53C/sIkxd01X9D4twBrmg59AeXhDf88JJ815hbHykdjvjBX19TXBmYr5x2a+4AAACARgigGRQrrTA2XHzkvkXY2yzGdrSHdVadWPRpevndu60XPnvQJsX90ij/WNVS+NmI2x59LncDV73TuZnMnbcwXHJ3ZR/yg0/PK0LnvY8/P7z5x5cWz044/67i2oiZ0yblrn/V6zqOf9PApp+TXTeYFjZZY0q+6928hZ25C6F6nvnOXg41LO9CT/o6/PLhufNz111fh0amP+/+DkC8Z87zxefg4T6Cf+unl83l9z6VOwAAAKARAmhGrHqTwwMJOWvts/Fqsbrv/33i+QW5GxxX3VcJt2Y/OS/MeW5BWKFqdcmO6626TAfYpTcKBsuuXzsvvO0nl4ebHy4dPPnJ319fXO+Lv+6ytP6kUa/acs3iOnNq/Y8pf3tyzezKGoSB/nmUV2P0ti6m2mZfODP+vq4LCzq7wuf+cmN+2ruHn6kEvxfeMSd3Pf3nn0p/Vo1KwfI2x5wddvzyOflJT8/MWxT2/WZpMvvjv7uuuNZTbzL7jsee6xa2D1Q66HNxH+H5YCqvEDn1huFZIfLG7QZ/33it9Ll85sVFxe/zJxfek58CAABAaxJAM2KNqRNA9zVh2p8VxnWEk969Y75bNh/ae4Pw94/ulu8q3vijS8OLC7uKQG/P488PO3z5nLD/Zqvnby2ttkiH472woLOYOE4TyHc+1n26+u07vSx3PaVQqzqwTRO7z81flO9C8eN+8FdXhweemhfue+KF8KvL7s/f0tO8+OtMXvXdi8Lz8eOuqArPy75+xm3hr9c+mO/6tjj/usoBdm2w3Lm4/vRvX5PG9Ry2Y+nPZ9yYxtZ2/OXah8LGR53RY0d1enOgVvWe877+7O54rP4EdfXe6PR5+chvrimmvc++5bHi2dPzKp+ral89/dbw2b9WdlDP6eONkZMuvjd3Jbc9+mzY/9sXFj/X0kjB80ZHnR5fuwNbBbK0bs9fTfDbK2YX1+VtWXbBNyK9EbD1MWeFrb90VnH/ZSs/AAAAaHECaEaVU2/sOTX5z8/snbve/fXDu+ZucKSDBbeaUX9dyaZfOKMI9MrGV4WayQ0PPhMO+8llYfevn19MIL/y2xfmbynp78zCi++qrPRIh99teXQp6EouuH1OOOPmR8MHf3112Pt/Lgj//beb+l37kHz51Fty19Mn8mR0f2rfHPjT1d2D6zNvLoWwtW56qDSB3ahPvKK0pzytaFkWl9VZjXL/ky/krnHVk8OTxlU+1ydfPrt4vf7wgrvCdXUOvqt+4+DH/7wnnHbjo/mu5xR5OgTzd1fMLia576+aUE8O/M6/imtvqyXSxPHrf3BxMSVdz4LO0uujeip9KJVf3+U3LJa30+r8O2Qwld/YAQAAgJFCAM2INWXCmNxV1JuKXndq/2s5xrRX/lE5dNu1c9e3kw7fIXc91f4ydttwau56SlPJtVIIvbSefKH36dgbc5h788Olg+qSFF72565ediIPRO3072f+VJno7csfrqoE1V87dMvc9a4tJ5jVn9OlkX61v7m8+5Tze35+Ve76d8ODc4tDGhdVTXaPqQrF5y8qPW+Pv97Tb6qEy2fk/sN9TCzvPqv7qphN/vuMcORfbgzHnXJrfL3XX3HSW/C501fODdfOnltMSdfz7XPuyN3y0ZaPg7z+gbnh0B9c3OMrAIba3F6m0AdLenMKAAAARhIBNCPObcceWByIWB3mlU2vOTTwzI/vmbu+VWdCX3rt5uHY122R73r36LP1D5pLyiFo2S7r9x5A/+CCu3M3OF5Y0Hug/ItL7stdRW+Tr9WuvO/p3NX36z7WUZRVB+2zn+o+pZtssfaKueuuetf3W/N6jd7MWm1y7kJDhxD25d9/e234/F9vyncD99rvXxx2+9p5xbqVsserXjP/d91DxfXHNTuAj/77zcX1X3dWDoCstdZKE4rrs/MXdZuwTmtBXrXVWvlucEysmtpeHq66vzSp/cLCrmLquvYrAIZKb7vJB5v8GQAAgJFGAM2Ik/bwrr3yCvmuuy3Wrhw8t+ZKE8LGdULIKePHhM3W7B52Vn+5/5QJY8M7d14335W8Y+eXhfu+9qpw2Wf3y0/qTy6X1R6Q+D9nLb8p0s/99cYe+4vTJG4yuc7U+CoTx+Vu6R31t/pB7UV3PlHsL06qg/Yj/9zzwL/eNi58+y3b5K5/Z39yr9wN7WFyaW9z2Q4zV8ldRXUQng5zLKue+r7nifrrPPp6Y6MsTZOnz+lWR58Vjjml+3qUzqqVKtWHXi6t6oD7R/8c3DdL6vnOOXfmbvlacRAP8OxL1R8nAAAAjAgCaEaVXatWXfziPT0PFLz8c/uFG790QBjT0T0g7i8UeuN26xTXNfLkabLbhtNy11OdTSBDZvL4nqFyOhywOoQurzGod7DeojqH/NUeELi03vGzy4v9xbXKq0CqfeHVm+WuIoX+O663ar4bmPYh/CTcUrXC5I8f3LX4dX7nLduEq496RdhqxkrFZHLZc/N7f6OiN9U/fj3pwMZP/P66ov95zVR79aGN6dDLWumgyuqp7P50Vb0Wvnb6bblbvtLBnUNteU16n5MPnAQAAICRQgDNqDJ+TCVE2mj1ntPP5R3Rm6/VfQK6v72s26zT80DB9CHTp3Rf+VFW3nd855cPCnfFWlYzjzw1nH/b4/muuw/suX7uKtLvZ4cvn5PvKvuG67ng9sfDqTd0P3itXig9VNLqjRTg7tTHmpJmc/YtlZ3NZa97+dph6uTxxf7ux57tfQ93Iw7+bungwN6kz88VvRwquLCfQyW3/tJZ4b2/uDLf9a96d3dy26N9h+NDIR3cOdA3RZ58fkGxzqSRQzaTNVasvLk0lG56uOebL4P1hg8AAAAMBwE0o8r4MfVf8qvVBMVHv3bzcPL7dwr//Mze4fBdZ4bNagLpRjw898Vwxn/ske+668qh3diO9mJX9YxV6q8MGYi/XlvaGVybVc3KQft60yqHLdaevzfn+d4D0a+eflv4yMndD7zrL8QcqHoB24f23qC4/uEDuxTXpHrFSaNWnVRaIfK2nfreDz2YUtA8nMqvr3qqJ6B709d+6Vozaw7x/NjJ14bjTrnlpbUuy+ra2U+HB+rsBK/17IsDmyQ/Nv4a03T4mTf3fLOgnv7/1JZO+lz97KJ7Xzrs85eX9tyX3tfnc1ldcvcTxaGfAAAAMFQE0Iwq4+ocTJj8+n07FYFnOaxMk9K7bjAtrDt1UhFG1+5sbsQjz8wvgsgDN1+juJ8wtvJz104Qf+vN/e8xvuLzfYev1asQqpWnsKuntK+dPTd3Jb+uE3r1ZSArGsoe62N3cb1AO+3dTm8YTBxXWSFSveKkUdMmjwsXfHrv4vDIWhf91z7hR+/YNt8Nnil1dmkPxD1zns9dyaY1O8n7k/Y819s9nXz7nMb3jVfvi+7NfTW7qu98/Pnw04vuDZ/4XWkFyLJ6/Q8uCXt84/yiT2F0b9LakYEoT243Gu4OVQb8t2sfKsLw757b+27r2inzwfD8gs5iTcvbfnJ5+OjJ1+anAAAAMPhGewB9YKzbY90V68j0oEZK7n4fK3375bFmxkrSaVS/iJVOSksnqH02Fi2gvPf3rTuUdjaXpXUc/3XgJqGtn1Ub1c79VOVAu2pj8/7oA3LwXPaRvTfMXc8wdtL4/vfLrjal7/C1dk1G2XbrrhJ+9d4dw39X7VC+7dHSzueygU5ANrq2oNpOXzk3dz3V7vCdOmlceGTu/LCgTtCdQuNGfPE1pd9vyuVnTptUTJvXmrHKxLDetMqBgEvrFZuunrvSn+WX/tH94L+BSH+2jz7T/fVx6yMDW2tx8V1Phivv6z2s7U1tGLvh50/PXe9+fGHPHd7JFYNwwGG1dGBiCqN7M9C1MOU3laoPGO3LUK3BeHpe6cDKF/MEdD19BdCzn5y3VDuwj/jlVS991cQtA3x9AQAAwECM5gA6JX4nxEoLeFNSdVi+VntvrJTipOTw27G+Hit5U6wUTm8Za7tYH4hVDqdpcnccd1D4yuvTp27ZbDC9fnBZnrIel9d9lA80LN8n/7xjTu5KGp3C3GyAk7Ble8ya3udU7sPPzA/X9DFdmtz1eGUqt7ofiPJhh7V+f+UDuSt58oWF4e/XP5zvult75b7Xldx27IHFXu19Nl6tuF9lYmmqvTeDcRbhyhPHvvTGQzrEryy9qTFQsz5/+jIF2MkZDa6VqJZC/9lVqy7u6OVztTR+fdn9xZ7yZTks8A9XdX+N1BromyLlALrRD6v+J3TxIE4kl6f/q//9UKve4aBlex5/fnj/L6/Kd6V98G//6WX5rneX3P1k7hr/9w8AAAAsjdEcQO8YK002p/G9NIL2u1iHxKqW7tOkc/KnWGkHQkot0t/W0+LTlOilNCx9vBGyFpGCnvIk9FD4xhu3DutPmxQm5dURaYVH2iOdQuCyp14oTT2Wtfczef3VQ0uB+TffvHVxXRr1JoCrHdrHdGly/Jm3FdfbH30uvP2n6QsC+lZv3cl//vmG3HVXHXz2p78p9QljO4q92mnq+djXbRG+//aX52+pr/a1sMesabkL4axP7BlWiD9efyaO6whfeE1pxcdPqiaC31Izad+o23sJfyeP73+1R/q1LI20wmXfb16Q70L48G+67/1O6k0BV09/9+aov91UXP9xQ/03Ff7fOXeGU+K3/faK2b1OGv/hqgdzV1+9afm+lA8WbThMrvpu9VbGpF937eR6I56bX9pdnSaZe7PP/1Q+L9XKwfFFd3Xf2Z0m4Kul32NaudGb2n8fAQAAwGAazQH02rGqR+pSupGeVav+Pulv78/EmhorhdFp8WnaeTA71v/EGtyvN6dlvWqrNcN5n977pQnLaZPHFyF0X/uL+wugy2sCqg8SrCdNP156T/fwabCcefNjRch2wHcuzE96uvWYA8PZn9gznPPJPetOXD/0dOVguuqg8TeXp3+MBma/TUoTzn15587r9ru6pBxElk2Pn6/dNyyF0Gk1y63Hpk09Ffd+9eDcVey98fQwLk9A/6Jqn/aCzqWf+K2nrxCxrL83Gnozd96i+DnJN1H1lPta+bVbL+Q959bHcte/tEYj+cEFd4XP/PH6Ypf4CeffVeylTnuIP/uXG8Pnc1g9UL1N19fz1hMvDX+8uhRo97Y7vVb1qo7y6opq6SDBnb96bvxzG9jk+MU5PD79poFPrTc69X38WbeHLb54ZvHnfv+TL4SvnpY2RwEAAMDyMZoD6HqJX20S0dv3SdPTKVlaK9Z6sT4Va/1YtY6Ilb42+qo5c7qvXGBk+I/9ZoUfvSNtYenfin2swNhkjSnh3bvNLA7LO+Vju+enFeUhzTTd25975lQOhSuvhRgsH/tt98PKfvO+nXJXssK4jjBr9Slhw9Wm1N2t+3jVKoHqnb3VBzQ24srPvyL8YJAOD5yWD2ksS7/un/zb9uGSI/fNTyrSmwr1JrD33WT1MKa95+9hwpien69/37eyC3woDPbnPOnIP2bt5G9/KzU++YfrijdFytIUc3rj4Rtn3F4EwD+/5N5w/JlpDX/FyUvxZkTyoToT27257J7K+4WNHvBX/XJ+tmrNStn3zktfUDPw9TTLspak0anvf+R1NunPfa/jL+h1bzcAAAAMhdEcQKfxt+qvj58Rq/brw6u/T0oPV4qVkou3xTojVkohHo91caztY9U6MVZ6vv306ZX1C4wcn3jlRuHALbofNtibtBairDaMTmsgvviazYu1EVusnV5m3S3o44Cygdh8rcZ3SH/8FbNyV3FKzUGHKZCdXhPglvUX7FVPB286wN3W6eccXyfcXRpprcV9X3tVvgvhDdvNKIL0tersmv7QXhsU17fv9LLimpQD3/Ku72qrTOq5f3ow17985oCNc1dRLwhfVg88VZpcX1QVeP73324Km34h/Wuwu2mTK7/nv1zTc1K4+o2Hr5xWWusy2F5Y0BkuvfvJ8My8RX3uT04aXcGxpOr9yXoHBq47dWJxXXGFdEZt46p/rPk1P+7+m/W93qSvCej1P3tq8eeQAv8Hq77yoDfVX5EAAAAAg2k0B9BXxkoJW5pgTonJW2P9PVa1dP+uUhveGOu8WOlv6WlEL41HpiQp7UTYOdbQJCmMSFf/9ytz17e35aBz5aqD9A7esrHAO6kO+5KTDt8hd327/bgDG9pfnHbQvnbr9IUAPf3bLuvmrr7q8LG88uJX701fXDA8tl5n5eK6y/ppy05379s9/WsihPfvWfpCh+Net0VxTc771N7FtTY87E3tyo++VO9Xrvdh79q159mnY8f0/+N/+fVbhEO2qf9560t54vbxZ+eHX11WWTVSLYX3ffnxP+/OXd8eiz/Ha753Ub4bmDR5fdhPLgtbH3NW2OHL5+Sn9TU6AV393eYv6hn83vBg2tBUf/d5X8o7oJMUGFcrf3VFWvFS6+xbHgvbH9f991YdIqdf7/7fvjCcFb9fI35XcxAoAAAADJbRHECnv+l/NNaZsdJCzD/EujnWMbFeGyv5WayURqWvrf5krCNjJSfEmhwrLStNQfZJseqfrgZ1NLqn9yuv3zJc+tl9wxu3SwP6JVPGNzZh+crNVg8nvbt74Lzain3vQ07SWo00XdzIQGRaV3HotrWr00s+vf/G4Y7jDsp3FWklQ9rXmw6cKysfprZKVdC+vP3yPTuGP31wl26T6mWff9Wm4bZjDwwr5enW6jUc66xamnw97caB7/Dtz54bVQ5EvPvLPXdP1x5K+Jbt13lpWrkvb99p3fCtN28TfjTANSZvOfHS4rrjV84trvXUC2erffPsO3LXu7SneKf4c9z4UCnUbdRN8fvv9JVzin3ljTr2lFty17fbHq2cM/viwt53cfd3SGat6kMuf3BB93A+TctPGtcRNpye/nPT3ft/mbY7dVf+56jsobkvNnwwYtq/DQAAAENhNAfQyWmxNoqVvq7+y+lB9IVY5Uno9Df3N8VKS1vTaGZ5cWZa8pmebx5rs1jHx4J+XXXUK8K1DU4/l625UvdVEL+/qjKpePOXDshdT2mP8T4b939QX60d11u1uJYPUezLUy8s7DVMT0HcuDH1vy1Np1YrHwTX32GMQymFy9vPLP3ea6XfS+3+7RQcVh+0mA7Ua8Q2LytNWjfiiar1Ef2t7rjzyweFrx66Zb6rSPvFk2+8YaviWpY+v2nC+rAd+590L0vh9i0PV4LYevpbedGIL/49vRfYv5fX/Fm++nsXhceeXfafv9az8xd1C/Y36WNlTL3d532pPljyvNvSRqeS9PlMxsZ/hmp3b9czb2FneKHOPulGJ7wBAABgqIz2ABqWq2mTx9fdC1xr5Yljwwfyuoe+TBo/Jmy/7ir5bnCMyUFn+rWmgPKPH9yluK9nkzVWDHPn9TyQrT9PPL8wdyVdeVVIbeh9xsf3yF3zue6LrwxXH1V5M6G/lSNle8yqrFOYmfcG9+ahud2nV4961aa56ym9EVAvpD7j43sWO65fX2dSPU17f/XQ7sF0f66Z/XTuhs4Ft/d9aOvRr0nv+6U95RuFW445IGxZZ2/6skr7lS++64miT7ukq6VVGZ1VoXD16ou+9jLXU73n+d4nqg8QLf3nOf3z9ctLu687qbe3OgXN1b+msqdf6P7PGgAAACxvAmhoQtd9Yf/w2YPrh41//lApEP76G0rTrn/60K7FdbCUVwikMPin79o+7NDLVHCy8RpT+p38rTeVW6s8AZ0yt398dPeiT1LA3azSmpLqCe90gGS16oMNa33qlekLL0L47mEvL67JhLE9/3Wcdk3//oidw4Wf2ae433OjSnj9rgYD77JG177056i/pc1Dwyf9uR6+23rFda/45zFx3Jiwaj9v6lQfeFlP7eqK5Pgzbw9v/+nl4XN/vTHs8Y3z89OS4069NezzzQvyXdpnnrY4ldTuXe/PX67teVBjf+pNWXfGn/fOx9MX53T3/fPTBikAAAAYPgJoaDHbrbtqEb69ZYfSAYX1nP2JPXM39Gat3nM/bbXDdnxZv2tHygFgWsGx5YyVit9fXwFuM2pkZUnZx/abVfz+tppRWiGRJnjfvVvpoMOy12y9VnGg307rTw0vy5PSG60+JVz0X/uEe796cPjSIZWDEJdVebf10npPza99eUsrMvqy8VFn5K6+e+b0DG5PvLC0cenkyyu7yqtVr+T4yb/uzV0IixpcxbI0Hnx6Xjjk+xd1OxCxLE1lXzt7br4DAACA5iGAhhFow9X6DoXLliXkfdtOpQB89QYONuxv7Uj5oLSBhLgjxe3HHRj++uFdwxo1f47je9mfPWOViS9NqSfnf3rvcMmR++a7pbNtL3upt5pRWm3xtX6m2PeYVTkscTgsa/D6ym9fmLuBOfj//St84vfX5buS6hUcaV92eS1GWtPxkd9cUxzC+c6fXV48G6jdv35+uP7BZ8IPLug51ZymtL9+xm35buDSpD0AAAAMBQE0jDApVK4OKGvdduyBuVs2G0xvLORuxFm3PFZcn32xciBbq5m12uTwH/vNyneNS6s80i7m2uy90V3C602bFNZauXJQ5Qlv2zZ39W28eulQwmrfecvLi3UftXacuWpxGN5bd+x92j7Z9mWDu4e8N/tuMvBDNZfGk883dpDhLY88G/5as0JjUR5PfuzZ+eHg7/4rHP2P0oGKf7/+4XDqjY8U/b/uLO2WrrfLuTdn3PRo7kL49WXdd0IPhmlTxucOAAAABpcAGkaQw3edmbveTRjbkbvGjauzP3gg4Vnyuz4mLMu7jdeb3n2PcitJof/SBNBlm9ccpLdg0dKtcnjVVmuGFSeMyXfd3XHcQeHUf6/s2C5baeLY8Jqt1sp3FWkivZHd0enjv/mmrcPO61f2hb9h2xm5K2nktdmf8257PHdLr5Fgf7vjzsndwD2Vw+s5z5Wuv75sdjj2lFvCDQ8+U9yXXXD74+FTf7w+3/Xvg7++Onc9D/FcVh/dZ8NBfUMJAAAAqgmgYQRJX+Y/FI5/01a5qygfHNiovlZ1lNcUjO1o7RUc7cuwQiRNEV991CvCO3YuTRvPWKUy1TxQf/3IbrnrLh2amKat61lxhUpoPW1yaRq2+s2KSeP6fuPiDdvNCK+uCrG/+eatw1dev2Wxyzr5wqs3K671nPTuHXI3dOYvKh1EmA7rSyb28/up548fLB0AWmvztSqHZR79j1tyV/Gzi+4N02smjA8/6coe09Nl36s6nHIopZdr+vx8eJ8N8hMAAAAYfAJoGAG++JpSuLfrho3t4h3oIX8HbbFm2Gm9ynRrMqYqbD39P/boc8K5P5fc/WRxHds+uv+VNHXy+HDc67YMP3/3DuEzB26cnw7celMHPklevbblzduXpper3xD4Sj97oJMVaqbr057wFKam11pf4fw+G68WbvrSAeG8T+2Vn9T3sX03zN3AvfnHlxbXzsWlNzs+8YqNwrt2WbfoG7X9uqu8FM5Xq7capPb9mbSipVE7zOz+z9pgOmDz1XMXwm/fv3Px+Zk4rv7EPAAAAAwGATSMAGm9wSkf2z0csPka+cnSOXTbtXPXXZqc/dZbtsl3Je+sCu82XXPFsPP6U/Ndfas1sGN2WSaIm8V34p/TOZ/sO0jtz94br1bshl5ay/rnWN4pveZKlSnsMb28OVA92ZxeJ8m6UycW10aU3wiZPH5MWL+fNRDp+yyt8gqMrrw6ZkxHW3j02dLhl41KIX29KejvnVc5FPBDe5emiZfE/1U74fyeBwf2pnpNSKMHilb7/MGb5q6nb7658s/xy5fT7m4AAABGNwE0jAApGNuiZodwozZZo3Qo3SdfuVH4VlU4VWvlFcbmLoTfH7HzgAPScjg50r3u5WsvVWg4FKYsZWD7th1fFv738O27vSGxdp2VIGnFxnt2Xy/fpYnp0uf4hQWldRe1DtpiYG+QnPz+nbrtjp63sP6Pu806K+euf+XdzGlC+cybS4dfJgM59LEvK+V/TmpXpF8ze27uejr2dVuEf6+a7n48/xqTtJ95oF6x2erhN+/bKd+V7J6/OiKF+Kuv6MBBAAAAlh8BNIxy5cnlSf2EldXfvvUAAr+y6pUdDL0UQJ7xiT3z3cCkCep9N1m921qO2pD37q8cXKzYqHbrI88W1yfyQXy1fviO7XLXmF03mBaOfu3m+S6EM256NHfd7TGrsdUzM488NRzwnQuL/qxbuv9Ysz5/etj8C2fku57+vcEDJsurN8p7zRvx7IuLwif3r6xcqd5PvffGpQM6B+K5+YvCbjXreH70zu3CjUfvX/R/+fBu4fg3bjVq3hQCAABgePnbJ4xyL39ZKVjcouogtf6MX4rgqjrMZOilAHLtvEqjUR/ca4Pww7dvm+/6Vu/9hLvnPJ+7xqSdygNx+2PP5a67gUyclyeTU1B82I7dA/QX6kxYn/HxPcJ1X3hl8RUCA7EoH3bYiG+ffUfuSspflZAszTqVKRMqX61QNq6j/aXn6XXxpu3XKXoAAAAYagJoGOUO2WbtcMmR+4ad+tnhnPzk37YvDjFbljB5lYmVcOwdO3cPABleRx60SThoyzXzXd/qvQYGMlF70uE7hJPf39jBleVDNs/5ZP2J7nRIZpIC7auOekXRJ//6z31y11N7/PUf97ot8l1FmpKutskaK4aVJ47LdyWfO3iT3PVU3v3c20qPeusvpk4u/fi3HnNguO3YA7v92fb3lQM/qjNVPiOvS/nGG7YqrokvQAAAAGC4CKCBlw6d688rN1s9/Pid2+e7gUsB26Wf3S/f9X6wHa1po9Urk7v92WWDqQ0H1u/ebb3isMINV6v/46cf588f2iWc9O4dwrTJlYC3rwnwlPF2tLeFr79hy/ykcQc3ENKfduMjuevutVuvlbuKjhw4rzCuI0wY2323egrKe7PfJquFNVaakO8qyru4d92w8qZSXz8OAAAADCXpD7Dc1AZs1btuaX7Xf3H/YsI4raSo5y3brxM/v+3htH/fIz/p3WAHotutu2qP1RN9/RTlELn2sMBG1E5EVyvvgD77lsoBh9UeeWZ+7io2qlq5USuF5GXv36Ny4GNywtu3fSm8rmfGKhNzF/+8jUADAAAwTATQwLDZveqgtD9/aNfc0axWWmFsMWHcWwC7yqRx4bZjDwqb9bFP/MyP7xk+vf9G/U4/n/epvXI3cKvGX0eSVln09ibHfpuuVlxfWNBZXOu55ZgDctfd5H4O7OxavCQ8+cLCfNfdKTf0nIxOE969qQ6YO9rbw8nv2ynflUL86i8iOPaQzYtJ8Wof2WeD3AEAAMDwEEADw6dqKHO7AR5IR2vaeI0p4aP7zsp3PY3tKL0oGl0LU89fP7xr+Nabty76o1+zeXGtVZ5Uvnb23FJTx8RxfQfNvblngIcx7rXR9Nz1VD25nA7/TKtLytI3Tar6Ndab5v7MAZv0CKUBAABgeRJAA8vdKzZdvVjXALU+sGdpYre/w/f6su7USeHQbWcU/ZgcaNfq7CqltZPG15+QnpqnqHuzSz60c/3pk4pr9eGCQ7Xu4n17rNftgMI0AT1zWunnTw7Zpud+aQAAABhuAmhgufvpu7YPX3/jVvkOKj59wMbFxO6YfJDestph5qq56261HBhv+7L6k/c754C5N789Yufi13nep/YOx71ui3DBp/cpni9ZsqTP8Pw9fazb6E/1tHNSlUUX+tpNDQAAAMNFAA0Mm7bqHRwwBNZZdWLdFRTlwzAP2HyN4lrr2Ndtkbv+vWPndbtNWlcfHFgt7Txfd2rlYMCBKk9Wv2qr0gGK5Wnow3edGQ7b8WVFDwAAAM1GAA0Mu/Wr1gjAUHjVlqXQNrnrywflrnRw4oxVuu+b3neT1V46yHCg0m7ptBqjnoVdi8PLcgC9LJPQJ7xt226h+tGv3Tx89dAt8x0AAAA0FwE0MGzKOV0veR0MmhVXGJu7tBe6+3/6aldmfOet2+SucdU/woNPv5i7EDZcbXL4zltKP96irsVhn41XC/97+PbhcwdvUjxrxGcO2Di8YtPV8h0AAAC0FgE0MOzGtPtXEUNr1w163+lce2jgihMqYfVApaMNv37GbaWb6JxP7hWem7+o6K+dPbe47rvJ6kUIvuZKE4r7/nxknw3DT9+1Q74DAACA1iL1AYZdbQAIg229Pta8fPvN24Q9Zk3Ld0unvI85eWFBZ+5K5s4rBdC1zv/03uGmLx2Q7wAAAGBkEkADw6Yc2Y2tOsANhkI5gP7+215eXKttvc7K4Vfv3SnfLZu0A/q2R58r+nF51Uf1+o9q6SDEyePH5DsAAAAYmQTQwLDr7dA2GCyTxo8pDu579VZr5Sc93fylA8ItxwzeRPKrtyodfJh+bgAAABitBNDAsCmvLeiwgoMmkILiieOWLiwuv4KXFFugS4553RbFdcYqKxRXAAAAGI0E0MCwWZL2FUQdJqAZgSaN6yiuO68/NXzu4E3CFZ/fr7gHAACA0UQADQybrhxAt/s3ES2u/B5KfkkXqg8mPGLPDcJqUybkOwAAABg9xD7AsOlanCegreAAAAAAGJEE0MCwyfmzQwhpedXTzgAAAECFABoYNotNQDPCpFf0y1+2cthj1rTSAwAAABjlBNDAsHlpBYfpUUaQ9MaKqX4AAAAoEUADw6Z8CKH1BYwY8TXduXhJGGOqHwAAAAoCaGDYVFZwFBdoaeX3UdJkf7sAGgAAAApiH2DYlCeg7YBmpEiv6BRAm4AGAACAEgE0MGzKO6Dty2UkKL+K757zfHhhYVe+AwAAgNFNAA0Mm8UmoBlh0ks6va9y4R1z8hMAAAAY3QTQwLDpWly6dpiAZgRwmCYAAAD0NNoD6ANj3R7rrlhHpgc1xsf6faz07ZfHmhmrbKtYl8a6OdaNsSbEAgagfAihA9sYKZYUW6ABAACAstEcQHfEOiHWQbE2i3VYvlZ7b6ynY20Y69uxvh4rGRPr17E+GGvzWHvHWhQLGICXDiE0OcoIkF7F+SUNAAAAZKM5gN4xVppsvifWwli/i3VIrGrp/helNvwp1n6xUsawf6wbYl0fK3kylhOnYIDKsfPkCek9HWh95YM1AQAAgJLRHECvHeuBUlt4MFZ6Vq36+3TGeibW1FgbxUopw5mxron1n7GAATp02xnhQ3tvED7xyvSPFLS2NMi/oDMvNgcAAAAKozmArvc1/7Wja719nzSuuXust+fr62Ol6ehaR8S6KtWcOXOKB0DFuDHt4b8O3CRMHm8CmpFh/iJfDAMAAADVRnMAnSae1ym1hRmxHi61L6n+PikhWynWU7HS83/GeiLWvFinxdo2Vq0TY22favr06cUDAEamtvi/5xekL5YBAAAAykZzAH1lrFmx1os1LtZbY/09VrV0/65SG94Y67xY5dUbW8WaGCsF03vFuiUWAKOYABoAAAC6G80BdEoJPhorhcm3xvpDrJtjHRPrtbGSn8VKO5/TYYWfjHVkrOTpWN+KlULs62KlPdCnxgJgtGqL/2HpcgghAAAAVBvNAXSSVmek0882iPXl9CD6QqzyJPT8WG+KtWGsHWPdE6vs17E2j7VFLIcQAhBWXKG0z/zo12xWXAEAAGC0G+0BNAAMinRq7cLO0gT0qpPHF1cAAAAY7QTQADBIFnYtLq7jOlIcDQAAAAigAWCQLOosBdBj2v3nFQAAABJ/QwaAQdDWVpmAHjvGf14BAAAg8TdkABgkV9//dLcrAAAAjHYCaAAYBG3xf1PGjyn6vTaaVlwBAABgtBNAA8AgGT+29J/VaZPHF1cAAAAY7QTQADAI0g7o+YtKO6DHj+korgAAADDaCaABYJAs6OwqruMdQggAAAAFf0MGgEHQFmtR15KiL6/iAAAAgNHO35ABYJBZwQEAAAAlAmgAGARtaQl0NLajLXS0l3oAAAAY7QTQADCITD8DAABAhQAaAAZBeebZAYQAAABQ4W/JADCInnxhYe4AAAAAATQADAZrnwEAAKAHATQAAAAAAENCAA0Ag8AANAAAAPQkgAaAQTC2w39SAQAAoJa/LQPAIPjWW7YJnzt4k3Dmx/fMTwAAAAABNAAMgr02mh6O2HODsPEaU/ITAAAAQAANAAAAAMCQEEADAAAAADAkBNAAAAAAAAwJATQAAAAAAENCAA0AAAAAwJAQQAMAAAAAMCQE0AAAAAAADAkBNAAAAAAAQ0IADQAAAADAkBBAAwAAAAAwJATQAAAAAAAMCQE0AAAAAABDQgANAAAAAMCQEEADAAAAADAkBNAAAAAAAAyJtnxl6M2JdX+pHRTTYj1RaqGleS0zkng9M1JsHGtKqQUAAGA0uipfodV5LTOSeD0zUngtAwAAg8IKDgAAAAAAhoQAGgAAAACAIdGRr7Smq/MVWp3XMiOJ1zMjhdcyAAAAAAAAAAAAAAAAAABN7sBYt8e6K9aR6QG0oP+N9Xism4o7aF3rxDo/1q2xbo71H7GgVU2IdUWs62Ol1/OXYgEAADCKpL3dd8daP9a4WOkviJvFglazZ6xtYwmgaXVrxkqv5WRKrDti+fcyraot1uRSG8bGujzWzsUdAADAUmjPV1rHjrHS5PM9sRbG+l2sQ2JBq7kw1lOlFlraI7GuKbXhuVhpEnrt4g5az5JYz5faIoBOlZ4BAAAsFQF060mhxgOltvBgLEEHQHOYGevlsdLUKLSq9NVW18VKa5LOjuX1DAAALDUBdOtJXxpby2QSwPBLawv+HOvjsZ5ND6BFdcXaJtaMWOkrr7aIBQAAsFQE0K0nTTynA6/K0l8OHy61AAyTtKYghc+/ifWX9ABGgLmxLoiVDj8GAABglBgTK+1/Xi9W+RDCzWNBK0rrChxCSKtLX5nyy1jfKe6gtU2PtXKpDSvE+lesVxd3AAAAjBoHx7oj1t2xPp8eQAv6bax0eNuiWGmy/72xoBXtHiutQrohVtqbmyr9expa0Vaxro2VXs/pDcIvxAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWtrMWDeV2oYcHmutUtur9H2+X2oBAAAAlq/2fAWg9TQSQAMAAAAMGwE0QHMZE+sXsW6I9adYE2N9IdaVsdJ09Imx2mK9Mdb2sX4T67pYK8TaIdYlsa6PdUWsKbGSFFKfEevOWN9IDwAAAAAAGF3SCo4lsXYr7kL431ifjrVqcVfyq1ivKbXhglgphE7GxbonVgqhkxVjpTA7TUmn5yvFmhDr/ljrxAIAAAAYciagAZrLA7EuLrXh17F2j7VPrMtj3Rhr31ibx6q1caxHYqVJ6eTZWJ2lNpwb65lY82PdEmvdWAAAAABDTgAN0FzSBHS1dP+DWGnlxpaxfhIrTTLXSms5aj+2bEG+Jl2x0mQ0AAAAwJATQAM0l5fF2qXUhsNiXVRqwxOxJsdKQXTZc7HKe55vi5V2PZdXcKTngmYAAABgWAmgAZrLrbHeFSsdQph2P/8wVpp6Tus3/harvGIj+XmsH8VKhxB2xHpLrO/FSocQnh2r3qQ0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8P/bgwMaAAAAhEHvn9ocbgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACcqAH6qMeZRReFDgAAAABJRU5ErkJggg==\" width=\"720\">"
],
"text/plain": [
"<IPython.core.display.HTML object>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"HBox(children=(IntProgress(value=0, max=3), HTML(value='')))"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"HBox(children=(IntProgress(value=0, max=14032), HTML(value='')))"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"HBox(children=(IntProgress(value=0, max=7039), HTML(value='')))"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'loss': 0.08000715392810209, 'val_loss': 0.0840423224571725}\n"
]
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"HBox(children=(IntProgress(value=0, max=14032), HTML(value='')))"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"HBox(children=(IntProgress(value=0, max=7039), HTML(value='')))"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'loss': 0.07516958098892379, 'val_loss': 0.08315527216200035}\n"
]
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"HBox(children=(IntProgress(value=0, max=14032), HTML(value='')))"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"%matplotlib nbagg\n",
"\n",
"num_split=1\n",
"np.random.seed(SEED+num_split)\n",
"torch.manual_seed(SEED+num_split)\n",
"torch.cuda.manual_seed(SEED+num_split)\n",
"#torch.backends.cudnn.deterministic = True\n",
"idx_train = train_df[train_df.PID.isin(set(split_sid[splits[num_split][0]]))].index.values\n",
"idx_validate = train_df[train_df.PID.isin(set(split_sid[splits[num_split][1]]))].index.values\n",
"idx_train.shape\n",
"idx_validate.shape\n",
"\n",
"klr=1\n",
"batch_size=32\n",
"num_workers=12\n",
"num_epochs=3\n",
"model_name,version = 'Densenet161_3' , 'classifier__splits'\n",
"#model1 = MyDenseNet(models.densenet161(pretrained=True),len(hemorrhage_types),num_channels=3)\n",
"model = MyDenseNet(models.densenet161(pretrained=True),\n",
" len(hemorrhage_types),\n",
" num_channels=3,\n",
" drop_out=0.2,\n",
" wso=((40,80),(80,200),(600,2800)),\n",
" strategy='none',\n",
" dont_do_grad=[],\n",
" extra_pool=4,\n",
" pool_type='max'\n",
" )\n",
"model.load_state_dict(torch.load(models_dir+models_format.format(model_name,'basic_splits',num_split),map_location=torch.device(device)))\n",
"_=model.to(device)\n",
"weights = torch.tensor([1.,1.,1.,1.,1.,2.],device=device)\n",
"loss_func=my_loss\n",
"targets_dataset=D.TensorDataset(torch.tensor(train_df[hemorrhage_types].values,dtype=torch.float))\n",
"transform=MyTransform(flip=True,zoom=0.05,rotate=15,out_size=512,shift=40)\n",
"imagedataset = ImageDataset(train_df,transform=transform.random,base_path=train_images_dir,\n",
" window_eq=False,equalize=False,rescale=True)\n",
"transform_val=MyTransform(out_size=512)\n",
"imagedataset_val = ImageDataset(train_df,transform=transform_val.random,base_path=train_images_dir,\n",
" window_eq=False,equalize=False,rescale=True)\n",
"combined_dataset=DatasetCat([imagedataset,targets_dataset])\n",
"combined_dataset_val=DatasetCat([imagedataset_val,targets_dataset])\n",
"#param_s=parameter_scheduler(model,num_epoch=0)\n",
"pre_proc = Mixup(0.4,device=device)\n",
"optimizer_grouped_parameters=get_optimizer_parameters(model,klr)\n",
"#sampling=simple_sampler(train_df[hemorrhage_types].values[idx_train],0.25)\n",
"#sampling=sampler(train_df[hemorrhage_types].values[idx_train],5,[0,0,0,0,0,2],train_df.SeriesI.values[idx_train])\n",
"sample_ratio= 1.0 #1.003*float(sampling().shape[0])/idx_train.shape[0]\n",
"train_dataset=D.Subset(combined_dataset,idx_train)\n",
"validate_dataset=D.Subset(combined_dataset_val,idx_validate)\n",
"num_train_optimization_steps = num_epochs*(sample_ratio*len(train_dataset)//batch_size+int(len(train_dataset)%batch_size>0))\n",
"fig,ax = plt.subplots(figsize=(10,7))\n",
"gr=loss_graph(fig,ax,num_epochs,int(num_train_optimization_steps/num_epochs)+1,limits=(0.05,0.2))\n",
"sched=WarmupExpCosineWithWarmupRestartsSchedule( t_total=num_train_optimization_steps, cycles=num_epochs,tau=1.5)\n",
"optimizer = BertAdam(optimizer_grouped_parameters,lr=klr*1e-3,schedule=sched)\n",
"model, optimizer = amp.initialize(model, optimizer, opt_level=\"O1\",verbosity=0)\n",
"history,best_model= model_train(model,\n",
" optimizer,\n",
" train_dataset,\n",
" batch_size,\n",
" num_epochs,\n",
" loss_func,\n",
" weights=weights,\n",
" do_apex=False,\n",
" model_apexed=True,\n",
" validate_dataset=validate_dataset,\n",
" param_schedualer=None,\n",
" weights_data=None,\n",
" metric=None,\n",
" return_model=True,\n",
" num_workers=num_workers,\n",
" sampler=None,\n",
" pre_process = None,\n",
" graph=gr,\n",
" call_progress=sendmeemail)\n",
"\n",
"torch.save(model.state_dict(), models_dir+models_format.format(model_name,version,num_split))\n",
"torch.save(best_model.state_dict(), models_dir+models_format.format(model_name,version+'_best',num_split))"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<torch._C.Generator at 0x7f06349ec5d0>"
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"text/plain": [
"(449503,)"
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"text/plain": [
"(224749,)"
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"application/javascript": [
"/* Put everything inside the global mpl namespace */\n",
"window.mpl = {};\n",
"\n",
"\n",
"mpl.get_websocket_type = function() {\n",
" if (typeof(WebSocket) !== 'undefined') {\n",
" return WebSocket;\n",
" } else if (typeof(MozWebSocket) !== 'undefined') {\n",
" return MozWebSocket;\n",
" } else {\n",
" alert('Your browser does not have WebSocket support.' +\n",
" 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
" 'Firefox 4 and 5 are also supported but you ' +\n",
" 'have to enable WebSockets in about:config.');\n",
" };\n",
"}\n",
"\n",
"mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n",
" this.id = figure_id;\n",
"\n",
" this.ws = websocket;\n",
"\n",
" this.supports_binary = (this.ws.binaryType != undefined);\n",
"\n",
" if (!this.supports_binary) {\n",
" var warnings = document.getElementById(\"mpl-warnings\");\n",
" if (warnings) {\n",
" warnings.style.display = 'block';\n",
" warnings.textContent = (\n",
" \"This browser does not support binary websocket messages. \" +\n",
" \"Performance may be slow.\");\n",
" }\n",
" }\n",
"\n",
" this.imageObj = new Image();\n",
"\n",
" this.context = undefined;\n",
" this.message = undefined;\n",
" this.canvas = undefined;\n",
" this.rubberband_canvas = undefined;\n",
" this.rubberband_context = undefined;\n",
" this.format_dropdown = undefined;\n",
"\n",
" this.image_mode = 'full';\n",
"\n",
" this.root = $('<div/>');\n",
" this._root_extra_style(this.root)\n",
" this.root.attr('style', 'display: inline-block');\n",
"\n",
" $(parent_element).append(this.root);\n",
"\n",
" this._init_header(this);\n",
" this._init_canvas(this);\n",
" this._init_toolbar(this);\n",
"\n",
" var fig = this;\n",
"\n",
" this.waiting = false;\n",
"\n",
" this.ws.onopen = function () {\n",
" fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n",
" fig.send_message(\"send_image_mode\", {});\n",
" if (mpl.ratio != 1) {\n",
" fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n",
" }\n",
" fig.send_message(\"refresh\", {});\n",
" }\n",
"\n",
" this.imageObj.onload = function() {\n",
" if (fig.image_mode == 'full') {\n",
" // Full images could contain transparency (where diff images\n",
" // almost always do), so we need to clear the canvas so that\n",
" // there is no ghosting.\n",
" fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
" }\n",
" fig.context.drawImage(fig.imageObj, 0, 0);\n",
" };\n",
"\n",
" this.imageObj.onunload = function() {\n",
" fig.ws.close();\n",
" }\n",
"\n",
" this.ws.onmessage = this._make_on_message_function(this);\n",
"\n",
" this.ondownload = ondownload;\n",
"}\n",
"\n",
"mpl.figure.prototype._init_header = function() {\n",
" var titlebar = $(\n",
" '<div class=\"ui-dialog-titlebar ui-widget-header ui-corner-all ' +\n",
" 'ui-helper-clearfix\"/>');\n",
" var titletext = $(\n",
" '<div class=\"ui-dialog-title\" style=\"width: 100%; ' +\n",
" 'text-align: center; padding: 3px;\"/>');\n",
" titlebar.append(titletext)\n",
" this.root.append(titlebar);\n",
" this.header = titletext[0];\n",
"}\n",
"\n",
"\n",
"\n",
"mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n",
"\n",
"}\n",
"\n",
"\n",
"mpl.figure.prototype._root_extra_style = function(canvas_div) {\n",
"\n",
"}\n",
"\n",
"mpl.figure.prototype._init_canvas = function() {\n",
" var fig = this;\n",
"\n",
" var canvas_div = $('<div/>');\n",
"\n",
" canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n",
"\n",
" function canvas_keyboard_event(event) {\n",
" return fig.key_event(event, event['data']);\n",
" }\n",
"\n",
" canvas_div.keydown('key_press', canvas_keyboard_event);\n",
" canvas_div.keyup('key_release', canvas_keyboard_event);\n",
" this.canvas_div = canvas_div\n",
" this._canvas_extra_style(canvas_div)\n",
" this.root.append(canvas_div);\n",
"\n",
" var canvas = $('<canvas/>');\n",
" canvas.addClass('mpl-canvas');\n",
" canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n",
"\n",
" this.canvas = canvas[0];\n",
" this.context = canvas[0].getContext(\"2d\");\n",
"\n",
" var backingStore = this.context.backingStorePixelRatio ||\n",
"\tthis.context.webkitBackingStorePixelRatio ||\n",
"\tthis.context.mozBackingStorePixelRatio ||\n",
"\tthis.context.msBackingStorePixelRatio ||\n",
"\tthis.context.oBackingStorePixelRatio ||\n",
"\tthis.context.backingStorePixelRatio || 1;\n",
"\n",
" mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n",
"\n",
" var rubberband = $('<canvas/>');\n",
" rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n",
"\n",
" var pass_mouse_events = true;\n",
"\n",
" canvas_div.resizable({\n",
" start: function(event, ui) {\n",
" pass_mouse_events = false;\n",
" },\n",
" resize: function(event, ui) {\n",
" fig.request_resize(ui.size.width, ui.size.height);\n",
" },\n",
" stop: function(event, ui) {\n",
" pass_mouse_events = true;\n",
" fig.request_resize(ui.size.width, ui.size.height);\n",
" },\n",
" });\n",
"\n",
" function mouse_event_fn(event) {\n",
" if (pass_mouse_events)\n",
" return fig.mouse_event(event, event['data']);\n",
" }\n",
"\n",
" rubberband.mousedown('button_press', mouse_event_fn);\n",
" rubberband.mouseup('button_release', mouse_event_fn);\n",
" // Throttle sequential mouse events to 1 every 20ms.\n",
" rubberband.mousemove('motion_notify', mouse_event_fn);\n",
"\n",
" rubberband.mouseenter('figure_enter', mouse_event_fn);\n",
" rubberband.mouseleave('figure_leave', mouse_event_fn);\n",
"\n",
" canvas_div.on(\"wheel\", function (event) {\n",
" event = event.originalEvent;\n",
" event['data'] = 'scroll'\n",
" if (event.deltaY < 0) {\n",
" event.step = 1;\n",
" } else {\n",
" event.step = -1;\n",
" }\n",
" mouse_event_fn(event);\n",
" });\n",
"\n",
" canvas_div.append(canvas);\n",
" canvas_div.append(rubberband);\n",
"\n",
" this.rubberband = rubberband;\n",
" this.rubberband_canvas = rubberband[0];\n",
" this.rubberband_context = rubberband[0].getContext(\"2d\");\n",
" this.rubberband_context.strokeStyle = \"#000000\";\n",
"\n",
" this._resize_canvas = function(width, height) {\n",
" // Keep the size of the canvas, canvas container, and rubber band\n",
" // canvas in synch.\n",
" canvas_div.css('width', width)\n",
" canvas_div.css('height', height)\n",
"\n",
" canvas.attr('width', width * mpl.ratio);\n",
" canvas.attr('height', height * mpl.ratio);\n",
" canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n",
"\n",
" rubberband.attr('width', width);\n",
" rubberband.attr('height', height);\n",
" }\n",
"\n",
" // Set the figure to an initial 600x600px, this will subsequently be updated\n",
" // upon first draw.\n",
" this._resize_canvas(600, 600);\n",
"\n",
" // Disable right mouse context menu.\n",
" $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n",
" return false;\n",
" });\n",
"\n",
" function set_focus () {\n",
" canvas.focus();\n",
" canvas_div.focus();\n",
" }\n",
"\n",
" window.setTimeout(set_focus, 100);\n",
"}\n",
"\n",
"mpl.figure.prototype._init_toolbar = function() {\n",
" var fig = this;\n",
"\n",
" var nav_element = $('<div/>')\n",
" nav_element.attr('style', 'width: 100%');\n",
" this.root.append(nav_element);\n",
"\n",
" // Define a callback function for later on.\n",
" function toolbar_event(event) {\n",
" return fig.toolbar_button_onclick(event['data']);\n",
" }\n",
" function toolbar_mouse_event(event) {\n",
" return fig.toolbar_button_onmouseover(event['data']);\n",
" }\n",
"\n",
" for(var toolbar_ind in mpl.toolbar_items) {\n",
" var name = mpl.toolbar_items[toolbar_ind][0];\n",
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
" var image = mpl.toolbar_items[toolbar_ind][2];\n",
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
"\n",
" if (!name) {\n",
" // put a spacer in here.\n",
" continue;\n",
" }\n",
" var button = $('<button/>');\n",
" button.addClass('ui-button ui-widget ui-state-default ui-corner-all ' +\n",
" 'ui-button-icon-only');\n",
" button.attr('role', 'button');\n",
" button.attr('aria-disabled', 'false');\n",
" button.click(method_name, toolbar_event);\n",
" button.mouseover(tooltip, toolbar_mouse_event);\n",
"\n",
" var icon_img = $('<span/>');\n",
" icon_img.addClass('ui-button-icon-primary ui-icon');\n",
" icon_img.addClass(image);\n",
" icon_img.addClass('ui-corner-all');\n",
"\n",
" var tooltip_span = $('<span/>');\n",
" tooltip_span.addClass('ui-button-text');\n",
" tooltip_span.html(tooltip);\n",
"\n",
" button.append(icon_img);\n",
" button.append(tooltip_span);\n",
"\n",
" nav_element.append(button);\n",
" }\n",
"\n",
" var fmt_picker_span = $('<span/>');\n",
"\n",
" var fmt_picker = $('<select/>');\n",
" fmt_picker.addClass('mpl-toolbar-option ui-widget ui-widget-content');\n",
" fmt_picker_span.append(fmt_picker);\n",
" nav_element.append(fmt_picker_span);\n",
" this.format_dropdown = fmt_picker[0];\n",
"\n",
" for (var ind in mpl.extensions) {\n",
" var fmt = mpl.extensions[ind];\n",
" var option = $(\n",
" '<option/>', {selected: fmt === mpl.default_extension}).html(fmt);\n",
" fmt_picker.append(option)\n",
" }\n",
"\n",
" // Add hover states to the ui-buttons\n",
" $( \".ui-button\" ).hover(\n",
" function() { $(this).addClass(\"ui-state-hover\");},\n",
" function() { $(this).removeClass(\"ui-state-hover\");}\n",
" );\n",
"\n",
" var status_bar = $('<span class=\"mpl-message\"/>');\n",
" nav_element.append(status_bar);\n",
" this.message = status_bar[0];\n",
"}\n",
"\n",
"mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n",
" // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n",
" // which will in turn request a refresh of the image.\n",
" this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n",
"}\n",
"\n",
"mpl.figure.prototype.send_message = function(type, properties) {\n",
" properties['type'] = type;\n",
" properties['figure_id'] = this.id;\n",
" this.ws.send(JSON.stringify(properties));\n",
"}\n",
"\n",
"mpl.figure.prototype.send_draw_message = function() {\n",
" if (!this.waiting) {\n",
" this.waiting = true;\n",
" this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n",
" }\n",
"}\n",
"\n",
"\n",
"mpl.figure.prototype.handle_save = function(fig, msg) {\n",
" var format_dropdown = fig.format_dropdown;\n",
" var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n",
" fig.ondownload(fig, format);\n",
"}\n",
"\n",
"\n",
"mpl.figure.prototype.handle_resize = function(fig, msg) {\n",
" var size = msg['size'];\n",
" if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n",
" fig._resize_canvas(size[0], size[1]);\n",
" fig.send_message(\"refresh\", {});\n",
" };\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n",
" var x0 = msg['x0'] / mpl.ratio;\n",
" var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n",
" var x1 = msg['x1'] / mpl.ratio;\n",
" var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n",
" x0 = Math.floor(x0) + 0.5;\n",
" y0 = Math.floor(y0) + 0.5;\n",
" x1 = Math.floor(x1) + 0.5;\n",
" y1 = Math.floor(y1) + 0.5;\n",
" var min_x = Math.min(x0, x1);\n",
" var min_y = Math.min(y0, y1);\n",
" var width = Math.abs(x1 - x0);\n",
" var height = Math.abs(y1 - y0);\n",
"\n",
" fig.rubberband_context.clearRect(\n",
" 0, 0, fig.canvas.width, fig.canvas.height);\n",
"\n",
" fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n",
" // Updates the figure title.\n",
" fig.header.textContent = msg['label'];\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_cursor = function(fig, msg) {\n",
" var cursor = msg['cursor'];\n",
" switch(cursor)\n",
" {\n",
" case 0:\n",
" cursor = 'pointer';\n",
" break;\n",
" case 1:\n",
" cursor = 'default';\n",
" break;\n",
" case 2:\n",
" cursor = 'crosshair';\n",
" break;\n",
" case 3:\n",
" cursor = 'move';\n",
" break;\n",
" }\n",
" fig.rubberband_canvas.style.cursor = cursor;\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_message = function(fig, msg) {\n",
" fig.message.textContent = msg['message'];\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_draw = function(fig, msg) {\n",
" // Request the server to send over a new figure.\n",
" fig.send_draw_message();\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n",
" fig.image_mode = msg['mode'];\n",
"}\n",
"\n",
"mpl.figure.prototype.updated_canvas_event = function() {\n",
" // Called whenever the canvas gets updated.\n",
" this.send_message(\"ack\", {});\n",
"}\n",
"\n",
"// A function to construct a web socket function for onmessage handling.\n",
"// Called in the figure constructor.\n",
"mpl.figure.prototype._make_on_message_function = function(fig) {\n",
" return function socket_on_message(evt) {\n",
" if (evt.data instanceof Blob) {\n",
" /* FIXME: We get \"Resource interpreted as Image but\n",
" * transferred with MIME type text/plain:\" errors on\n",
" * Chrome. But how to set the MIME type? It doesn't seem\n",
" * to be part of the websocket stream */\n",
" evt.data.type = \"image/png\";\n",
"\n",
" /* Free the memory for the previous frames */\n",
" if (fig.imageObj.src) {\n",
" (window.URL || window.webkitURL).revokeObjectURL(\n",
" fig.imageObj.src);\n",
" }\n",
"\n",
" fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
" evt.data);\n",
" fig.updated_canvas_event();\n",
" fig.waiting = false;\n",
" return;\n",
" }\n",
" else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n",
" fig.imageObj.src = evt.data;\n",
" fig.updated_canvas_event();\n",
" fig.waiting = false;\n",
" return;\n",
" }\n",
"\n",
" var msg = JSON.parse(evt.data);\n",
" var msg_type = msg['type'];\n",
"\n",
" // Call the \"handle_{type}\" callback, which takes\n",
" // the figure and JSON message as its only arguments.\n",
" try {\n",
" var callback = fig[\"handle_\" + msg_type];\n",
" } catch (e) {\n",
" console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n",
" return;\n",
" }\n",
"\n",
" if (callback) {\n",
" try {\n",
" // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n",
" callback(fig, msg);\n",
" } catch (e) {\n",
" console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n",
" }\n",
" }\n",
" };\n",
"}\n",
"\n",
"// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n",
"mpl.findpos = function(e) {\n",
" //this section is from http://www.quirksmode.org/js/events_properties.html\n",
" var targ;\n",
" if (!e)\n",
" e = window.event;\n",
" if (e.target)\n",
" targ = e.target;\n",
" else if (e.srcElement)\n",
" targ = e.srcElement;\n",
" if (targ.nodeType == 3) // defeat Safari bug\n",
" targ = targ.parentNode;\n",
"\n",
" // jQuery normalizes the pageX and pageY\n",
" // pageX,Y are the mouse positions relative to the document\n",
" // offset() returns the position of the element relative to the document\n",
" var x = e.pageX - $(targ).offset().left;\n",
" var y = e.pageY - $(targ).offset().top;\n",
"\n",
" return {\"x\": x, \"y\": y};\n",
"};\n",
"\n",
"/*\n",
" * return a copy of an object with only non-object keys\n",
" * we need this to avoid circular references\n",
" * http://stackoverflow.com/a/24161582/3208463\n",
" */\n",
"function simpleKeys (original) {\n",
" return Object.keys(original).reduce(function (obj, key) {\n",
" if (typeof original[key] !== 'object')\n",
" obj[key] = original[key]\n",
" return obj;\n",
" }, {});\n",
"}\n",
"\n",
"mpl.figure.prototype.mouse_event = function(event, name) {\n",
" var canvas_pos = mpl.findpos(event)\n",
"\n",
" if (name === 'button_press')\n",
" {\n",
" this.canvas.focus();\n",
" this.canvas_div.focus();\n",
" }\n",
"\n",
" var x = canvas_pos.x * mpl.ratio;\n",
" var y = canvas_pos.y * mpl.ratio;\n",
"\n",
" this.send_message(name, {x: x, y: y, button: event.button,\n",
" step: event.step,\n",
" guiEvent: simpleKeys(event)});\n",
"\n",
" /* This prevents the web browser from automatically changing to\n",
" * the text insertion cursor when the button is pressed. We want\n",
" * to control all of the cursor setting manually through the\n",
" * 'cursor' event from matplotlib */\n",
" event.preventDefault();\n",
" return false;\n",
"}\n",
"\n",
"mpl.figure.prototype._key_event_extra = function(event, name) {\n",
" // Handle any extra behaviour associated with a key event\n",
"}\n",
"\n",
"mpl.figure.prototype.key_event = function(event, name) {\n",
"\n",
" // Prevent repeat events\n",
" if (name == 'key_press')\n",
" {\n",
" if (event.which === this._key)\n",
" return;\n",
" else\n",
" this._key = event.which;\n",
" }\n",
" if (name == 'key_release')\n",
" this._key = null;\n",
"\n",
" var value = '';\n",
" if (event.ctrlKey && event.which != 17)\n",
" value += \"ctrl+\";\n",
" if (event.altKey && event.which != 18)\n",
" value += \"alt+\";\n",
" if (event.shiftKey && event.which != 16)\n",
" value += \"shift+\";\n",
"\n",
" value += 'k';\n",
" value += event.which.toString();\n",
"\n",
" this._key_event_extra(event, name);\n",
"\n",
" this.send_message(name, {key: value,\n",
" guiEvent: simpleKeys(event)});\n",
" return false;\n",
"}\n",
"\n",
"mpl.figure.prototype.toolbar_button_onclick = function(name) {\n",
" if (name == 'download') {\n",
" this.handle_save(this, null);\n",
" } else {\n",
" this.send_message(\"toolbar_button\", {name: name});\n",
" }\n",
"};\n",
"\n",
"mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n",
" this.message.textContent = tooltip;\n",
"};\n",
"mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n",
"\n",
"mpl.extensions = [\"eps\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
"\n",
"mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n",
" // Create a \"websocket\"-like object which calls the given IPython comm\n",
" // object with the appropriate methods. Currently this is a non binary\n",
" // socket, so there is still some room for performance tuning.\n",
" var ws = {};\n",
"\n",
" ws.close = function() {\n",
" comm.close()\n",
" };\n",
" ws.send = function(m) {\n",
" //console.log('sending', m);\n",
" comm.send(m);\n",
" };\n",
" // Register the callback with on_msg.\n",
" comm.on_msg(function(msg) {\n",
" //console.log('receiving', msg['content']['data'], msg);\n",
" // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
" ws.onmessage(msg['content']['data'])\n",
" });\n",
" return ws;\n",
"}\n",
"\n",
"mpl.mpl_figure_comm = function(comm, msg) {\n",
" // This is the function which gets called when the mpl process\n",
" // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
"\n",
" var id = msg.content.data.id;\n",
" // Get hold of the div created by the display call when the Comm\n",
" // socket was opened in Python.\n",
" var element = $(\"#\" + id);\n",
" var ws_proxy = comm_websocket_adapter(comm)\n",
"\n",
" function ondownload(figure, format) {\n",
" window.open(figure.imageObj.src);\n",
" }\n",
"\n",
" var fig = new mpl.figure(id, ws_proxy,\n",
" ondownload,\n",
" element.get(0));\n",
"\n",
" // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n",
" // web socket which is closed, not our websocket->open comm proxy.\n",
" ws_proxy.onopen();\n",
"\n",
" fig.parent_element = element.get(0);\n",
" fig.cell_info = mpl.find_output_cell(\"<div id='\" + id + \"'></div>\");\n",
" if (!fig.cell_info) {\n",
" console.error(\"Failed to find cell for figure\", id, fig);\n",
" return;\n",
" }\n",
"\n",
" var output_index = fig.cell_info[2]\n",
" var cell = fig.cell_info[0];\n",
"\n",
"};\n",
"\n",
"mpl.figure.prototype.handle_close = function(fig, msg) {\n",
" var width = fig.canvas.width/mpl.ratio\n",
" fig.root.unbind('remove')\n",
"\n",
" // Update the output cell to use the data from the current canvas.\n",
" fig.push_to_output();\n",
" var dataURL = fig.canvas.toDataURL();\n",
" // Re-enable the keyboard manager in IPython - without this line, in FF,\n",
" // the notebook keyboard shortcuts fail.\n",
" IPython.keyboard_manager.enable()\n",
" $(fig.parent_element).html('<img src=\"' + dataURL + '\" width=\"' + width + '\">');\n",
" fig.close_ws(fig, msg);\n",
"}\n",
"\n",
"mpl.figure.prototype.close_ws = function(fig, msg){\n",
" fig.send_message('closing', msg);\n",
" // fig.ws.close()\n",
"}\n",
"\n",
"mpl.figure.prototype.push_to_output = function(remove_interactive) {\n",
" // Turn the data on the canvas into data in the output cell.\n",
" var width = this.canvas.width/mpl.ratio\n",
" var dataURL = this.canvas.toDataURL();\n",
" this.cell_info[1]['text/html'] = '<img src=\"' + dataURL + '\" width=\"' + width + '\">';\n",
"}\n",
"\n",
"mpl.figure.prototype.updated_canvas_event = function() {\n",
" // Tell IPython that the notebook contents must change.\n",
" IPython.notebook.set_dirty(true);\n",
" this.send_message(\"ack\", {});\n",
" var fig = this;\n",
" // Wait a second, then push the new image to the DOM so\n",
" // that it is saved nicely (might be nice to debounce this).\n",
" setTimeout(function () { fig.push_to_output() }, 1000);\n",
"}\n",
"\n",
"mpl.figure.prototype._init_toolbar = function() {\n",
" var fig = this;\n",
"\n",
" var nav_element = $('<div/>')\n",
" nav_element.attr('style', 'width: 100%');\n",
" this.root.append(nav_element);\n",
"\n",
" // Define a callback function for later on.\n",
" function toolbar_event(event) {\n",
" return fig.toolbar_button_onclick(event['data']);\n",
" }\n",
" function toolbar_mouse_event(event) {\n",
" return fig.toolbar_button_onmouseover(event['data']);\n",
" }\n",
"\n",
" for(var toolbar_ind in mpl.toolbar_items){\n",
" var name = mpl.toolbar_items[toolbar_ind][0];\n",
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
" var image = mpl.toolbar_items[toolbar_ind][2];\n",
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
"\n",
" if (!name) { continue; };\n",
"\n",
" var button = $('<button class=\"btn btn-default\" href=\"#\" title=\"' + name + '\"><i class=\"fa ' + image + ' fa-lg\"></i></button>');\n",
" button.click(method_name, toolbar_event);\n",
" button.mouseover(tooltip, toolbar_mouse_event);\n",
" nav_element.append(button);\n",
" }\n",
"\n",
" // Add the status bar.\n",
" var status_bar = $('<span class=\"mpl-message\" style=\"text-align:right; float: right;\"/>');\n",
" nav_element.append(status_bar);\n",
" this.message = status_bar[0];\n",
"\n",
" // Add the close button to the window.\n",
" var buttongrp = $('<div class=\"btn-group inline pull-right\"></div>');\n",
" var button = $('<button class=\"btn btn-mini btn-primary\" href=\"#\" title=\"Stop Interaction\"><i class=\"fa fa-power-off icon-remove icon-large\"></i></button>');\n",
" button.click(function (evt) { fig.handle_close(fig, {}); } );\n",
" button.mouseover('Stop Interaction', toolbar_mouse_event);\n",
" buttongrp.append(button);\n",
" var titlebar = this.root.find($('.ui-dialog-titlebar'));\n",
" titlebar.prepend(buttongrp);\n",
"}\n",
"\n",
"mpl.figure.prototype._root_extra_style = function(el){\n",
" var fig = this\n",
" el.on(\"remove\", function(){\n",
"\tfig.close_ws(fig, {});\n",
" });\n",
"}\n",
"\n",
"mpl.figure.prototype._canvas_extra_style = function(el){\n",
" // this is important to make the div 'focusable\n",
" el.attr('tabindex', 0)\n",
" // reach out to IPython and tell the keyboard manager to turn it's self\n",
" // off when our div gets focus\n",
"\n",
" // location in version 3\n",
" if (IPython.notebook.keyboard_manager) {\n",
" IPython.notebook.keyboard_manager.register_events(el);\n",
" }\n",
" else {\n",
" // location in version 2\n",
" IPython.keyboard_manager.register_events(el);\n",
" }\n",
"\n",
"}\n",
"\n",
"mpl.figure.prototype._key_event_extra = function(event, name) {\n",
" var manager = IPython.notebook.keyboard_manager;\n",
" if (!manager)\n",
" manager = IPython.keyboard_manager;\n",
"\n",
" // Check for shift+enter\n",
" if (event.shiftKey && event.which == 13) {\n",
" this.canvas_div.blur();\n",
" event.shiftKey = false;\n",
" // Send a \"J\" for go to next cell\n",
" event.which = 74;\n",
" event.keyCode = 74;\n",
" manager.command_mode();\n",
" manager.handle_keydown(event);\n",
" }\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_save = function(fig, msg) {\n",
" fig.ondownload(fig, null);\n",
"}\n",
"\n",
"\n",
"mpl.find_output_cell = function(html_output) {\n",
" // Return the cell and output element which can be found *uniquely* in the notebook.\n",
" // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n",
" // IPython event is triggered only after the cells have been serialised, which for\n",
" // our purposes (turning an active figure into a static one), is too late.\n",
" var cells = IPython.notebook.get_cells();\n",
" var ncells = cells.length;\n",
" for (var i=0; i<ncells; i++) {\n",
" var cell = cells[i];\n",
" if (cell.cell_type === 'code'){\n",
" for (var j=0; j<cell.output_area.outputs.length; j++) {\n",
" var data = cell.output_area.outputs[j];\n",
" if (data.data) {\n",
" // IPython >= 3 moved mimebundle to data attribute of output\n",
" data = data.data;\n",
" }\n",
" if (data['text/html'] == html_output) {\n",
" return [cell, data, j];\n",
" }\n",
" }\n",
" }\n",
" }\n",
"}\n",
"\n",
"// Register the function which deals with the matplotlib target/channel.\n",
"// The kernel may be null if the page has been refreshed.\n",
"if (IPython.notebook.kernel != null) {\n",
" IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n",
"}\n"
],
"text/plain": [
"<IPython.core.display.Javascript object>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"<img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABaAAAAPwCAYAAADH/tkFAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAALv9SURBVHhe7N0HmF1V2TbgNZmSSS+E0EsgQOi9SC8KKKgoduBXsCEqfooFe0PFhliwo6ggKuDnZwGkg3QIvdcQQiAhvU2f+dees8ZpZ2pmyJlz7pvrufa7d0gmCk7iMyvvDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEDBKEtXKAbPxkyMmdN6BwAAAMDa2jJmRcyM1jsYIAU0xWTxmDFjpm6//fbpFgAAAIC18eijj4aampolcVwv9wQGRgFNMZm9RzR79ux0CwAAAMDa2HPPPcM9UTbmnsDAjEpXAAAAAAAYUgpoAAAAAACGhQIaAAAAAIBhoYAGAAAAAGBYKKABAAAAABgWCmgAAAAAAIaFAhoAAAAAgGGhgAYAAAAAYFgooAEAAAAAGBYKaAAAAAAAhoUCGgAAAACAYaGABgAAAABgWCigAQAAAAAYFgpoAAAAAACGhQIaAAAAAIBhoYAGAAAAAGBYKKABAAAAABgWCmgAAAAAAIaFAhoAAAAAgGGhgAYAAAAAYFgooAEAAAAAGBYKaAAAAAAAhoUCGgAAAACAYaGABgAAAABgWCigAQAAAAAYFgpoAAAAAACGhQK6NG0a85uY+TF1MXNizo2ZEjNYB8c0xbTEnJU96MH+MZfHLIlZE/NAzP/ElMcAAAAAAEVEAV16to6ZHXNyzJ0xP4h5JuZjMbfFrBczUBNifheTFcq9eWPMTTFZWf2/MefFVMVkP4c/xQAAAAAARUQBXXp+GjM95vSY42LOjDk8JiuBt4v5RsxA/TBmUsy3Wu/ymxjzq5jslPShMe+N+VTMbjFZ8f2WmHfEAAAAAABFQgFdWraKOTImW7mRnT7u6Msxq2NOihmXPein7FRzdpo6K7SzlR49yQrm9WOyk853Zw+S2pgv5MbwoXQFAAAAAIqAArq0ZCedM1fFNOfG/1oZc0vM2Jj9sgf9kJ2kzk41/y3mwuxBL9o+9pXp2lG2liNb35Hthx6dPQAAAAAARr6ydKU0fDfmkynfzx508ZOYD8ecFvOz7EEfsuL5wJgdYxbEvCfmtzHZGo+2U81t7orZKyXbQd3VQzHZj7NDzKPZg0GYvUc0e3a+H37kOOHXt4f75i5Ld4Vr2w0nhB+/c/ew6ZTsaxYAAABAMdpzzz3DPVE25p7AwDgBXVqyPc2Z5enaVdvzyenam1NisvUbWVmdlc99GcqPnTXM+TIrZsSrqW8Kq0dA7p27LPzpzufTzxoAAAAAulNA01HbifiWdO3JljHnxlwS85fswRDo78emgCxaVZcmAAAAAOjOCo7SMlQrOK6LydZlZFmUPUis4BgCa+obQ3MB1/D/emB++MxlD7bOb9h14/Cjd+7eOgMAAADFxwoO1pYT0KXl8XTdNl272iZdn0jXnuwRk72A8OWYrCptS1Y+Zz4fk91nO6Lb9PaxK2JmxDTGPJM9KGVjqyrC+NGFm8ljq9LPNCvLm9IEAAAAAN0poEvL9el6ZEzXf/YTYg6IqYm5PXvQi9/HnJ8nN8Vk7ovJ7q9uvcvJTk1njk7Xjg6Oyd5kd2uMnQ4FbmxVeZrivywN2dcMAAAAACA/BXRpeTrmqphsh3O2aqOjr8aMi8nK5dXZgyR7sV/Xl/udHvO+PGk7Af2vmOz+vNa7nEtjsnUd74jJ1nC0qY45Kzf2uvaDAtGxgHYCGgAAAIDeKKBLT7bfeWHMj2KyFRnfislOJ388Jlu9ka3P6CjbxzzYncwdrYh5f0zWXt4Q8+uY78Rkp6VfFZMV1H+OocCNqcw2puQsXlWfJgAAAADoTgFderJT0NkJ5Ati9o05I2brmKyQzorgxTHDJSu8D4nJVnUcH/PRmIaYT8RkJ6ML+NV7tOl4AnrukjVpAgAAAIDuFNCl6fmYk2M2isneKLdFzMdilsR0VZbSH1mpnf29X2i9y++WmNfFTIkZE7NzzA9i7HIYISorOn/aqG9sThMAAAAAdKaABgZk40nZ2u52dY2+dgAAAABAfgpoYEDKyjofiH9+SU2aAAAAAKAzBTSwVj55yf1pAgAAAIDOFNDAWnnkxRVpAgAAAIDOFNAAAAAAAAwLBTQAAAAAAMNCAQ0AAAAAwLBQQAMAAAAAMCwU0AAAAAAADAsFNAAAAAAAw0IBDQzYd96yS5oAAAAAoGcKaGDAdt9scppyVtY2pAkAAAAA2imggQGrLO/8qePllXVpAgAAAIB2CmhgwDacVJ2mnPqm5jQBAAAAQDsFNDBg1ZXlacqpb1RAAwAAANCdAhoYlD02b98DrYAGAAAAIB8FNDAoVRXtnz4U0AAAAADko4AGBqViVPunjzo7oAEAAADIQwENDMrNTy1KUwg3Pv5ymgAAAACgnQIaGJTqyvZPH4/MX5EmAAAAAGingAYG5S17bpqmEHbaZFKaAAAAAKCdAhoYlO02nJimEGobm9IEAAAAAO0U0MCgjKksT1MItfUKaAAAAAC6U0ADg9KxgF6jgAYAAAAgDwU0MChjq9oL6JoGBTQAAAAA3SmggUGp7nACWgENAAAAQD4KaGBQxnQ8AW0FBwAAAAB5KKCBQbGCAwAAAIC+KKCBQen4EkInoAEAAADIRwENDEqnFRxOQAMAAACQhwIaGBQnoAEAAADoiwIaGJTqjgV0Q1NoaWlJdwAAAACQo4AGBqV8VFkYXdH+KaS2oTlNAAAAAJCjgAYGzR5oAAAAAHqjgAYGraq8/VPIS8tr0wQAAAAAOQpoYNAWrqxLUwjnXP14mgAAAAAgRwENDIlrHl2YJgAAAADIUUADAAAAADAsFNDAkKlvbE4TAAAAACiggbXwtr02TVOOFxECAAAA0JECGhi0M1+7fZpyFq9ufykhAAAAACiggUGbOq4qvGqr9dJdCKvrmtIEAAAAAApoYC2NG12RphBW1TWmCQAAAAAU0MBamlDdXkCvrG1IEwAAAAAooIG1NLFTAe0ENAAAAADtFNDAWpk0pjJNISyvcQIaAAAAgHYKaGCtTFRAAwAAANADBTSwVjoW0BfcOidNAAAAAKCABtZSdWV5mnJeWFaTJgAAAABKnQIaWCtV5Z0/jXz3ysfSBAAAAECpU0ADa6WsLA3J3+6bnyYAAAAASp0CGlgrjU0taQIAAACAzhTQwFppaGpOEwAAAAB0poAG1kp1pU8jAAAAAOSnOQLWyhHbb5AmAAAAAOhMAQ2slcryUeG8d+2R7kLYfOrYNAEAAABQ6hTQwFrbYr320nn86Io0AQAAAFDqFNDAWuu4B/qRF1ekCQAAAIBSp4AG1tqE6so05SyvaUgTAAAAAKVMAQ2stQ0mVqcpZ8GK2jQBAAAAUMoU0MCQ+8tdz6cJAAAAgFKmgAaG3IKVdWkCAAAAoJQpoIEhscnkMWkKYb+tpqYJAAAAgFKmgAaGxJE7bpCmEGrqm9IEAAAAQClTQANDYlxVRZpCWKOABgAAACBSQANDYkxVeZoU0AAAAADkKKCBITG2QwFdU9+YJgAAAABKmQIaGBKdCugGJ6ABAAAAUEADQ6S6smMB3ZwmAAAAAEqZAhoYEmM6FtB2QAMAAAAQKaCBIdHxJYQ1DXZAAwAAAKCABoaIE9AAAAAAdKWABoaEHdAAAAAAdKWABobE2A4rONbUW8EBAAAAgAIaGCLjqyvSFMKqWgU0AAAAAApoYIhMrK5MUwgrFdAAAAAARApoYEiMrmj/dFLf1BxqG7yIEAAAAKDUKaCBIVFWVpamnOsfW5gmAAAAAEqVAhoYFn+5+/k0AQAAAFCqFNDAsNhmgwlpAgAAAKBUKaCBITNz+vg0hbDVtHFpAgAAAKBUKaCBIXPgzGlpCqHGSwgBAAAASp4CGhgyoyvbP6UooAEAAABQQANDZkxleZpCqK1XQAMAAACUOgU0MGQ6FtBOQAMAAACggAaGzJiqDiegG5rTBAAAAECpUkADQ6baCWgAAAAAOlBAA0NGAQ0AAABARwpoYMh4CSEAAAAAHSmggSEztsMO6NX1jWkCAAAAoFQpoIEhM7G6Mk0h3P7MkjQBAAAAUKoU0MCQGTu6/QR0ZsGK2jQBAAAAUIoU0MCQ2XjSmDTl3Pf8sjQBAAAAUIoU0MCQGdNhB3Tm4fkr0gQAAABAKVJAA8PmR9c+mSYAAAAASpECGgAAAACAYaGABgAAAABgWCiggWH1/JI1aQIAAACg1CiggWH1nX8/niYAAAAASo0CGhhWdz27JDQ3t6Q7AAAAAEqJAhoYVi+tqA27fe2q8MlL7k9PAAAAACgVCmhg2K2obQyXzp4X7n9+WXoCAAAAQClQQAND6oCZ66Wpu7leSAgAAABQUhTQwJA6+827pKm7qx5ZEOobm9MdAAAAAMVOAQ0Mqc2mjg0PfOXIdNfZP+6fH772z4fTHQAAAADFTgENDLmJ1ZVp6u7C2+emCQAAAIBip4AGAAAAAGBYKKCBYXHma2elqbvahqY0AQAAAFDMFNDAsPjgwVulqbsfX/dkmgAAAAAoZgpoYFiUlZWFE/bdPN11dt71T6cJAAAAgGKmgAaGzUvLa9PUXUtLS5oAAAAAKFYKaGDYNPVSMs9bWpMmAAAAAIqVAhoYNh89fGaauqtr9CJCAAAAgGKngAaGzR6bTwk/fMdu6a6z2obmNAEAAABQrBTQwLDJXkT4xt02SXedraprTBMAAAAAxUoBDQy7yz70qjS1+9u9L4QfXP1EWLK6Pj0BAAAAoNgooIFht+cWU8N/Pn1Yusv5013Phx9e+2T48t8fTk8AAAAAKDYKaOAVsdnUseHYXTZKd+3+cf/8NAEAAABQbBTQwCtmdEV5mgAAAAAoBQpo4BVTXZn/U85zi1enCQAAAIBiooAGXjHTJ1SnqbPTL743TQAAAAAUEwU08IqZOq4yTZ3dP295mgAAAAAoJgpo4BVjBzQAAABAaVFAA6+YyoqyNHW3pr4xTQAAAAAUCwU08IqpLO/5U843L380TQAAAAAUCwU08IqpqW9KU3cX3j43TQAAAAAUCwU08IrZcFJ1mvJraWlJEwAAAADFQAENvGKmT+i9gL716cVpAgAAAKAYKKCBV8zoit4/5dw9Z2maAAAAACgGCmjgFVPVRwH965ufSRMAAAAAxUABXZo2jflNzPyYupg5MefGTInpr0/FXB6Tfd9VMStiHow5Jyb78fPJFvz2lNtjKHJ9FdBH7rBhmgAAAAAoBgro0rN1zOyYk2PujPlBTHbs9GMxt8WsF9MfH4zZOObGmJ/GnB+TLfD9eMzDMbvH5PNczFfz5NcxFLm+CuiN+nhJIQAAAAAjiwK69GRl8fSY02OOizkz5vCYrIjeLuYbMf2xU8xuMe+O+XRMVjwfGvOBmIkxPf042Ynpr+SJAroEVJX3/imnpqEpTQAAAAAUAwV0adkq5siYrAQ+L3vQwZdjVsecFDMue9CH2nTt6i/puk26wn/1VUDXKqABAAAAiooCurRkJ50zV8U058b/WhlzS8zYmP2yB4P0+nR9IF27mhxzSsznYj4cszYfixFm1KiyNLU767jsMH2OE9AAAAAAxUUBXVqyFRuZJ9K1qyfTddt07Y/3xWQrNL4X8++Y38Vke56z1R757BqT7YvOVnT8JCbbO31fzM4x/ZXtsM6XWTGMMBOqK9IUQl1D16+LAAAAADCSKaBLy6R0XZ6uXbU9z04p91dWQGfrO86IydZ7ZEXwq2PayuyOzok5IGb9mAkxe8dcGpOV0tfFbBJDkfveW7N/3O3GVbUX0Hc8uyRNAAAAABQDBTQdte1HaEnX/shWaGTfb1pMVkBnshL66NzYSVZS3xqzKGZVzN0xb425LCb7/p+M6Y89e8hjMRS47TfKvvbQbuKYyjTFfzFW1YV75i5NdwAAAACMdAro0tJ2wrntJHRXE9O1pxPSvVkcc3VMVkLXxPw+ZkxMf/w8XQ9OV4pY1xcRTh3XXkBnPnzRPWkCAAAAYKRTQJeWx9O1px3P26RrTzui+2NZTLbXOVuzsWP2oB9eTtdx6UoR22xq9p7LnA0nVoeq8vJ0l/Pi8to0AQAAADDSKaBLy/Xpmp1S7vrPPtuLkO1nzk4v3549WAttu5wb07Uv2RqPzDPpShGrriwPf/7AfuE9+28ZLjhl7zDKZyEAAACAoqX6KS1Px1wVs2XMh7MHHXw1JjuBnK3OWJ09SGaldLRFzFa5sZsPxmQvF3w+5sHsQbJHTL4TzrvEfCM3hgvTlSK371brha+8Yccwa8OJYZPJ3Te1XDZ7XpoAAAAAGMkU0KXntJiFMT+K+VvMt2Kui/l4TLZ64/MxHT2a0tHuMU/F3Bzzm5jsx/hlzAMx2T7n7AWDJ8U0xbQ5PebFmOxj/jjmezH/jMkW/q4X86uYi2MoMWVlZeFzr+v8NY4zLrk/LF5Vl+4AAAAAGKkU0KUnOwW9V8wFMfvGnBGzdUxWSL8qJnuZYF+y0vgHMVUxx8R8MuadMS0x34/ZIebGmI6y4vmamJ1i3h2TFdJ7xlwR88aYD8Rk358S9P6Duh+ov3dutk4cAAAAgJFMAV2asvUYJ8dsFJOVyNlKjY/FLInpqiylo7kxWXG9T8wGMZUx2Q7pXWOyMjr78bvKCug3x8yMmRiTfdzs478+5u8xlLDsFHRXDU3NaQIAAABgpFJAAwWpsdmBeAAAAICRTgENFIQdN84OxrdbXdeYJgAAAABGKgU0UBB+f0q20aXd8pqGNAEAAAAwUimggYKw3vjR4bOvnZXuQpi/rCZNAAAAAIxUCmigYKw/YXSaQvjdbc+F5WucggYAAAAYyRTQQMGYPLYyTTnnXvtEmgAAAAAYiRTQQMGYWN25gP7tLXPSBAAAAMBIpIAGCsb46oo0AQAAAFAMFNBAwRhXpYAGAAAAKCYKaKBgTHACGgAAAKCoKKCBgjFudPcCurGpOU0AAAAAjDQKaKBgVJZ3/5S0qq4xTQAAAACMNApooKD859OHpSnnsnteSBMAAAAAI40CGigom00dm6acr//zkTQBAAAAMNIooAEAAAAAGBYKaAAAAAAAhoUCGig4nzl6VppCmDZ+dJoAAAAAGGkU0EDBefvem6UphFV1DaGpuSXdAQAAADCSKKCBgjN1XFUYP7qida5taA6r6hpbZwAAAABGFgU0UJDGVJWnKYSa+qY0AQAAADCSKKCBgjS2QwG9pt4JaAAAAICRSAENFKQxlR0LaCegAQAAAEYiBTRQkDqegH55VV14eWVdaPYyQgAAAIARRQENFKSxVbmXEGZO/u1dYe9vXBO2+tzl4bSLZoeWFkU0AAAAwEiggAYKUseXEHZ0+YMvhZueXJTuAAAAAChkCmigIHVcwdHVUwtXpQkAAACAQqaABgpSbwV0bYOXEgIAAACMBApooCCNqWzfAd1VnQIaAAAAYERQQAMFaXlNQ5q6q2tsThMAAAAAhUwBDRSky+6Zl6buVtY1pgkAAACAQqaABgrSrptOSlN3f7xjbpoAAAAAKGQKaKAgnXHkdmnKb0Vtzys6AAAAACgMCmigIK0/YXSa8vv6Px5JEwAAAACFSgENFKTxoyvSlN8ls3veEQ0AAABAYVBAAwVpbFV5mnq22ssIAQAAAAqaAhooSOP6OAGdUUADAAAAFDYFNFCQRleMClUxvVlT35QmAAAAAAqRAhooSGVlZaG+sTnd5aeABgAAAChsCmhgxFpTbwUHAAAAQCFTQAMj1vzltaGu0SloAAAAgEKlgAZGjG++aefW3dBtTr/43rDdF64MH/j93eH7Vz0emptb0rcAAAAAUAgU0EDB2mzqmDTlbLHe2FCXZy/0VY8sCD++7qlw2T3z0hMAAAAACoECGihYvz9l3zTl7DNjapry++0tc9IEAAAAQCFQQAMFa8a0ceG0Q7dunT94yFahsrz3T1mrvZQQAAAAoKAooIGC9umjZ4Wnv/m68NnXbp+e9GxlrQIaAAAAoJAooIGCVz6qLE0hfP51PRfRS1bXpwkAAACAQqCABkaUw2atnyYAAAAACp0CGhhRxo+uTBMAAAAAhU4BDYwo40aXp6m7LdcbmyYAAAAACoECGhhRxlVVpKm7OYvXpAkAAACAQqCABkaUUR1eSJjPUi8iBAAAACgYCmhgxDl81vQ0dffw/BVpAgAAAGBdU0ADI87UcVVp6u7E8+9IEwAAAADrmgIaGHEqy33qAgAAABgJtDjAiFNZ3vse6GcXrU4TAAAAAOuSAhoYcfo6AX36xfemCQAAAIB1SQENjDgHzpyWphA2mlSdpnYPvrA8TQAAAACsSwpoYMQ5dLv1w3sPnBH23nJK+NX/2yuU9b6RAwAAAIB1RAENjDhlZWXhi8fuEC45df+w0yaTQpWXEgIAAAAUJK0NMOJNGlOZJgAAAAAKiQIaGPHOO2GPNLWrb2xOEwAAAADrigIaGPH22mJK+MsHX5XuclbXNaYJAAAAgHVFAQ2MeNlO6H1mTA0bTapOT0KoaWhKEwAAAADrigIaKBpjKsvTpIAGAAAAKAQKaKBoVHcsoOsV0AAAAADrmgIaKBpjqtoL6FonoAEAAADWOQU0UDSs4AAAAAAoLApooGhYwQEAAABQWBTQQNHouILDCWgAAACAdU8BDRSNMZXtn9LsgAYAAABY9xTQQNHouAN6jRUcAAAAAOucAhooGtUdVnAooAEAAADWPQU0UDQ6noCus4IDAAAAYJ1TQANFo2MBXdvYnCYAAAAA1hUFNFA0qjsU0DVWcAAAAACscwpooGh0PAFdYwUHAAAAwDqngAaKRseXEK6ua0wTAAAAAOuKAhooGuuPH52mEBavqk8TAAAAAOuKAhooGmM7nICubbSCAwAAAGBdU0ADRWN0ZfuntFo7oAEAAADWOQU0UDSqK9pPQD+xYFVobGpOdwAAAACsCwpooGhUVnT+lHbtYwvTBAAAAMC6oIAGisakMZVpynl5ZV2aAAAAAFgXFNBA0Rg/uiJNOWVlaQAAAABgnVBAA0XllANmpCmEmnovIgQAAABYlxTQQFEZU9X+aW1NfVNo8CJCAAAAgHVGAQ0UlbFV7Ws4zrn6ibD3N64Jtz29OD0BAAAA4JWkgAaKypjK8jTlLFvTEN792zvTHQAAAACvJAU0UFTGVnUuoDP1jdZwAAAAAKwLCmigqEwcU5kmAAAAANY1BTRQVCYroAEAAAAKhgIaKCqjK/v3aa2puSU89MLy0NBkPQcAAADAcFFAA0VldEX3HdD5bP25y8OxP745bPP5K9ITAAAAAIaaAhooKtU9nID+4B/uDktX17fOD89f3nptsyQ9BwAAAGBoKaCBotLTCeh/P7wg7P71q8OVD70Ynl20Oj3NWV7TkCYAAAAAhpICGigqfe2APvXCe8LzS2rSXc6q2sY0AQAAADCUFNBAUamu7HsH9N1zlqQpZ2WdE9AAAAAAw0EBDRSV0RV9f1qbUF2RppzVdU1pAgAAAGAoKaCBopLtgN5riynpLr+VXVZurHICGgAAAGBYKKCBovPbk/cOv/5/e4WbP3NYetLZtY8tTFPOKiegAQAAAIaFAhooOhOqK8Ord9ggbDixOj3pnZcQAgAAAAwPBTRQtCrKR4U3775JuuuZFRwAAAAAw0MBDRS1c96+W3jP/lumu/wefGFFmgAAAAAYSgpooOjNmDYuTfm9vLIuTQAAAAAMJQU0UPTeutemacpvQnVFmgAAAAAYSgpooOiNraoIj3ztqHTX3fI1dkADAAAADAcFNFASshJ65vTx6a6zxxesDC0tLekOAAAAgKGigAZKxk/etXuaunt4vhcRAgAAAAw1BTRQMmZtODFMnzA63XX29/vnpwkAAACAoaKABkpKTy8c/OVNz6QJAAAAgKGigAZKytwla9LUXU19U5oAAAAAGAoKaKCkTJ9Qnabubn16UZoAAAAAGAoKaKCkrKxtSFN3l86elyYAAAAAhoICGigpe2wxJU3dPfjC8jQBAAAAMBQU0EBJqW9sTlN385bWpAkAAACAoaCABkpKTUPnFw3uvvnkNIUwY9q4NA2/xavq0gQAAABQvBTQQEl5/0FbpSmEE/fbPLxup43SXQjPLlqdpuHT0NQctjzzX2HPs64JH7343vQUAAAAoDgpoIGSctSOG4ZPHrltOOWAGeFTR84KZWXpG14h/374pTSF8I/754fm5pZ0BwAAAFB8FNBASSkfVRY+cvg24Uuv3yFMGlsZTth3i/QtOU3DXAg/sWBVmnJW1jWmCQAAAKD4KKCBkjamqjxNOUtW16dpeGw4sTpNOcvXNKQJAAAAoPgooAE62Psb14RvX/lY+OcD80NjU3N6OnRa4l8dLV0zvIU3AAAAwLqkgAbo4mc3PB0+8sd7w/k3P5ueDJ2WLhs+7pqzJE0AAAAAxUcBDZS8MZWd13C0+dYVj6Vp6LR0aaBHvdJvQQQAAAB4BSmggZL3up03StPw6/qOw1ueWpQmAAAAgOKjgAZK3gPzlqVp8Grqm8JVD78UFq+qS0/ya+5yAvraxxamCQAAAKD4KKCBkjd2dEWaBu+4824JH/jD7LDnWdeE2oam9LS7rjugAQAAAIqZAhooeeOq8u+AztzazxUZjy9YmaYQ3vmr29PUXdcT0FXlPg0DAAAAxUvzAZS8il5K4D/eOTdNPZv93NI05dw7t+eVHl1PQG+1/rg0AQAAABQfBTRQ8k45YMs0dffPB14MjU3N6S6/7/77sTS1q2vMv4aj6wnousbef2wAAACAkUwBDZS8Q7ZdP035XfHQS2nKb6NJY9LU7rjzbk1TZ11XQPf10kIAAACAkUwBXZo2jflNzPyYrP2aE3NuzJSY/vpUzOUx2fddFbMi5sGYc2KyH78nO8T8JWZhTG3M4zFfjene4MErpKysLE35PfTC8jTlt8+MqWlq9+iLK8JLy7N/xTvregJ6RW1jWLCi+98HAAAAUAwU0KVn65jZMSfH3Bnzg5hnYj4Wc1vMejH98cGYjWNujPlpzPkxi2M+HvNwzO4xXe0bc1fMcTHXxPwwJiuuvxRzdczoGFgnvn7cTmnqrqqi90+VTc1dzzXn7Peta8P7f393WFPfmJ503wGd+do/H0kTAAAAQHFRQJeerCyeHnN6TFYEnxlzeExWRG8X842Y/sjaut1i3h3z6ZiseD405gMxE2O6/jjlMb+NGRvzlph3xXwmJiulL4s5ICb7MWCdeMfem4Xj98h/eP+OZ5ekKb+up5o7uvqRBeF//nRfuot/b56y+l8PvJgmAAAAgOKigC4tW8UcGZOtzTgve9DBl2NWx5wUMy570IeedgZk6zUy26Rrm0Nito+5Kebv2YMkewNbVmBnTo3pfRcCDJPK8lHh+2/bNVz98YPDBhM7H8a/89klYXVd+ynmrhqaei6gM1c9siBNWVmdBgAAAIASoIAuLdlJ58xVMVnx29HKmFtishPK+2UPBun16fpAurZp+9hXpmtH2QqQJ2K2iMlKclhnttlgQth/62nprt3vb3suTd31Vk531dLtNYQAAAAAxUsBXVqyFRuZrOzN58l03TZd++N9MV+J+V7Mv2N+F5M1ddlqj46G8mNnO6zzZVYMrLWq8u6fGn/9n+zrJPmdc3VP/1p319MJ6LrGprzrOQAAAABGMgV0aZmUrsvTtau255PTtT+yAjpb33FGTLbeIyuCXx3TVii3GY6PDcPirXt13wW9eHV967WlpSX89Ianwhl/uT8sWFEbltc0tD5v8+XX75Cm/LLvn89+37w2HP79G8LyNZ1/PAAAAICRTAFNR237lwdyDDNb15F9v2xnQVZAZ7IS+ujc2G8D+dh79pDHYmCt7bXl1HDWcdl7Njv7v/teCA++sDx858rHw2X3zAsfunB2uPjOuelbc55cuCpNnTU25bbe9PTCwqVrGsKcxWvCt654ND0BAAAAGPkU0KWl7ZRx22nkriama0+nlHuzOObqmKyEron5fcyYmDbD+bFhyJ24X7aSvLOP/em+8Kv/PJvuQrhn7rJw9hWdv+5R29AU3rP/lumu3Yra3J7oHvrn/7rioZfSBAAAADDyKaBLy+Pp2tOe5W3Stf8LbbtbFnNbzPoxO2YPklfiY8Ow+8f989OU3xGzNghv2bP7Co9la3IrPPpa89x1pQcAAADASKaALi3Xp2t2SrnrP/sJMQfEZKeXb88erIVN0jV35DPnunTNt5pjq5ismM5eXtjzm95gBHjtThuGbTfI/ufU2bJULPe0AxoAAACgGCmgS8vTMVfFZPsBPpw96OCrMeNistUZq7MHyayUjrLdBFlpnM8HY/aOeT7mwexBcmNMttz24Jg3ZA+S7N/Bb+fG8PMY7RwF4427bZym/hs1qixUVYwKHzi48/9EFq+qD1c+9FJ4aL4tMwAAAEDpUECXntNiFsb8KOZvMd+KyU4nfzwmW3/x+ZiOstK461vRdo95KubmmN/EZD/GL2MeiMlK5OwtbCfFNMW0yeaTY9bEXBrzx5izY+6IeUvMLTE/iIGC8aVjd0hT/0yorkhTCJ973fbh9bu2F9hnXvZAOPXC2eGWp7J16QAAAAClQQFderJT0HvFXBCzb8wZMVvHZIX0q2L6047dE5OVxVUxx8R8MuadMdnp5e/HZK1dduK5q6xszk5H/19MtgYkK72zlxJ+LeY1MXUxUDDWGz86Tf0zprI8TTkPv9B+2nnx6twO6P54z2/vDO/73d32QQMAAAAjngK6NGXrMbLTyBvFZCVytlLjYzFLYroqS+lobkxWXO8Ts0FMZUy29HbXmKyMzn78njwS89aYaTFZu5ftfv5yTLZ7GgrOLptmXyPpn3fss3macp5Z1HGbTf/d8PjL4ZpHF4Rv/Cv7nwsAAADAyKWABujFqYdkf0Cgf965z2Zpyikf1fVrNwPzl7vnpQkAAABgZFJAA/TikG3XDxNGt+927klWNm80aUy6y3lXlxPRAAAAAKVGAQ3Qi3GjK8LfP3pguutZeVn3085H7bhhmgAAAABKkwIaoA8zpo0LefrlTvJ9+4HbZKvOAQAAAEqXAhqgH2785GFpyq+lJQ1dTKzue30HAAAAQLFSQAP0w+brjQ0ff/W26S6E0w7t/HLC+qbmNHW2orYxTd29YdeN09SzpuYemm0AAACAEUABDdBPpx22dfjOW3YJP3rn7uETr2kvowdr6Zr6NPWsrrEpTQAAAAAjjwIaoJ8qy0eFt+21WevJ5Yo4r41TD9k6LFxRl+56VtuQ/2Q1AAAAwEiggAZYByaPrQwf78cp6uU1DWkCAAAAGHkU0ADDaLfNJqepu6N23CB89PCZYe8tp4SDtpmWnnb2q/88kyYAAACAkUcBDTCMzn37bmHm9PGhrCw9SLKXC5bFh2ccuV245NT9w3kn7JG+pbOHX1ieJgAAAICRRwENMIy2nDYuXPOJQ8Kz3zomPclpaWlJU87E6sowuqL7p+R5S2vSBAAAADDyKKABBmnquKo09c8bd9u49ZoVzW/aY9PWuaPxoyvS1G7x6vo0AQAAAIw8CmiAQbrwvfumKYTTDt06TT374rE7hE8dtV347cl7h00mj0lP2+20yaQ0tcv39wEAAACMFApogEHaYeOJ4c7PHRFuPfPw8OmjZ6WnPZs2fnT48GEzw/5b53/h4NffuFOoruz8aXnH+DEAAAAARioFNMBamD6xOmw8RKeUN19vbLj9s0eEb7xpp/QkhKseWRAamprTHQAAAMDIooAGKCCTx1aFnbus4rhs9rw0AQAAAIwsCmiAAtP15YZn/vXBNAEAAACMLApogALTtYAGAAAAGKkU0AAFZmxVRZra3fb04jQBAAAAjBwKaIACNKosDcmJ59+RJgAAAICRQwENUIDu+Nyr05Rz3G6bpAkAAABg5FBAAxSg9SeMDntuMSXdhbDBxNHhlqcWhQfmLUtPAAAAAAqfAhqgQL12pw3TFMJPb3g6nPDrO8IbfnJL+NG1T6anAAAAAIVNAQ1QoBqbW9LU2TlXP5EmAAAAgMKmgAYoUPc/b90GAAAAMLIpoAEK1IcO3TpNAAAAACOTAhqgQO2y6eQ0AQAAAIxMCmiAEaihqTlNAAAAAIVLAQ0wAq2qbUwTAAAAQOFSQAMUsO++ZZc0dbaitiFNAAAAAIVLAQ1QwI7aacM0dbbSCWgAAABgBFBAjwyzYj4e88GYSdkDoDSMr6pIU2ePvLgiTQAAAACFSwFdWL4U82LM1Na7nFfH3BvzvZifxtwTs14MUAJGjSoL7z9oRiiP145+dsPTaQIAAAAoXArowvLamMdilrTe5XwrpiXmyzE/i5kR87EYoER8/pgdwsNfPSpsMnlMehLCplPaZwAAAIBCpYAuLFvGPJobW20Ss2dMdvL5rJiPxFwXc1wMUEKqK8vDKQdmX3/KqalvShMAAABA4VJAF5YpMR1PPx8Qk51+/mfrXc7smM1zI1BK7pm7NE0h3P1c+wwAAABQqBTQheXlmOzUc5vDYhpi7mi9y6mK8c8NStDE6so0AQAAAIwMiszCcl/MG2J2ipkZ8/aYm2NqYtpkazqyFxUCJeaEff3hBwAAAGBkUUAXlu/ETIq5P+bxNH8/pk11zKExd7feASVl0pjOJ6CbmrMNPQAAAACFSwFdWP4Tc2zM32L+N+YtMVfEtNk/Zk5M9m1Aiem6guOye+aFS+5+PtQ2eCEhAAAAUJgU0IXnypjjY7LyuWvRfF3M7jGXtt4BJWXS2M4F9KcvfSB8Kub8m59NTwAAAAAKiwJ65JgSMy43ArT77r+zjT0AAAAAhUcBXViOiMn2QGdlc5vpMTfGLIpZEnNODAAAAABAwVNAF5aPxrw5ZmnrXc73Yg6KeSpmcczHYt4WA/BfS1bXpwkAAACgcCigC8uuMTfnxlZjYrJd0FfHbJfyfMypMQD/ddvT2denAAAAAAqLArqwZOs25ufGVvvGVMdc0HoXwsqYf8ZkRTRQgv7ywVelqbOysjQAAAAAFBAFdGGpi8lOPbfJVm+0xNzUepezImZqbgRKzT4z8v/P/9anF4WWluzTBQAAAEDhUEAXlmdjDs+NrY6PeTLmhda7nM1ishcSAvzXhbfPDX+/v+MfoAAAAABY9xTQheV3MTvH3BHznzT/MaajPWIez40A7T72p/vSBAAAAFAYFNCF5Wcxf4rZK+aAmGzf87dj2uwTs33MDa13AF0c9J3r0gQAAACw7imgC0tDzLtipsRMinljTLYXus0zMbvH/Lj1DihJ20wfn6bunl9SE/54x9x0BwAAALBuKaALU/aiwZW5sZNs9/P9Mctb74CSdN4J2Saenn3ufx9MEwAAAMC6pYAuTGNjToz5fsz5Meek+3ExQInbdoMJ4dlvvS6cfMCW6QkAAABAYVJAF57XxTwXk72Q8OMxJ8f8T7qfE3NsDFDiysrKwgFbT0t3AAAAAIVJAV1Ysj9X/9eYyTEXxZwS89p0ze6z55fG7BkDlLiqip4/hbe0tIQH5y0PW575r9Zc/ciC9C0AAAAArxwFdGH5fExLzEEx/y/mgph/p2t2f2BM9u2fiwFK3O6bZ1+Tyu8XNz0TjvvpLekuhPf//u40AQAAALxyFNCFJSueL4m5vfWuuztishPQ2d8HlLgJ1ZXht+/ZO911dvYVj4Wm5uzrVe2yU9EAAAAAryQFdGGZFPN8buzR3JiJuREodYfNmh4+97pZ6a53dY3NaQIAAAB4ZSigC8v8mH1yY4/2inkxNwKE8IGDtw7feNNO6a5nNfVNaQIAAAB4ZSigC8vlMYfHnBlTnj3oIPtndUbMq2Oyvw/gv07Yd4vwqaO2S3f5/eo/z6QJAAAA4JWhgC4sX495KeYbMU/F/D7m2zG/i3ky5jsx2befFQPQyYcPm5mm/H56w9PhqYWr0h0AAADA8FNAF5asXD4g5pqYLWJOjPlUzEkxM2Ky5wfGWMEBDMoPrnkiTf23aFVd+MDv7w6/vOnp0NhkjzQAAADQfwrowjMn5qiYzWLeEJOVz9k1u8+ePxsDkNf40RVpym/GeuPS1H97nXVNuOqRBeGblz8Wvv7PR9JTAAAAgL4poAvXCzH/jLkoXbN7gF6trm9MU34Tx/ReUPfld7c9FxqcggYAAAD6SQG9bv1mkDk/BqCblpY09GCgO6Cbmrv/gBfckv1BDQAAAIC+laUr68ZgjxFmjVB5bqSD2XtEs2fPTrdQel77w/+ER19cke7ym3P2MWnqW21DU5j1xSvTXbuB/BgAAACMXHvuuWe4J8rG3BMYGCeg163sxYKDyVYxAN389UP7p2lo9LRuY00fqz4AAAAAMgrodeu5tQhAN2OqysMDXzky3XU3ZWxlmvqnpr4pTZ3t8KV/t56OfublVaGlr70fAAAAQMlSQAMUmYnVleGgbaalu86WrmlIU/+cemHPK22y1RyHf//G8JnLHkhPAAAAADpTQAMUodOP2CZNIXzudbPSlPPYS73viO7onrnL0tSzv9w9L00AAAAAnSmgAYrQ3ltODX//yAHh0lNfFd57YOe18QtW1KVp6DT2sCsaAAAAKG0KaIAitcumk8NeW04N5aPKwhbrjU1PQ2hoHPqyeE1D/l3RAAAAQGlTQAOUgMlj2l8++MALy9M0dNbUKaABAACA7hTQACXg/nntpfOPrn0yTQNz0fv2TVN3q+sb0wQAAADQTgENUIKam1v63Nv88xufTlPOPjOmhi8cs3266+zmJxelCQAAAKCdAhqgBHzg4PYXEe61xZSw1ecuDzM/f0V4auHK9LSzh+cvD2df8Vi6y6ksHxXqeyitv/z3h9MEAAAA0E4BDVACtt9oQppCuPu5pWkK4dXn3JSmdg1NzeGYH92c7jo7ZNv10wQAAADQNwU0QAmorihPU373zF0a/nrPvFDb0BSOOrd7Kd1mx40npQkAAACgbwpogBIwbnRFmrp7fsma8Jaf3Ro+8Zf7wy9veiY88/Lq9C0Ds6puaF9EmJXhX//nI+Hz//tgWFHbkJ4CAAAAI4kCGqAETBxTmabuPn3pA6G5JTefc/UTuaEX571rjzR1tu83rknT0PjTnXPD+Tc/Gy66Y274zpWd91EDAAAAI4MCGqAETKju+QT0bc8sTlP/vHanDcNF79s3XPah/dOTnNX1TWlaOy0tLWHLM/8VvvKPR9KTEC68fW6aAAAAgJFEAQ1QAiZW93wCuj9+9f/2SlP8hWNUWThg5rSw5xZT0pPByXZOv+3nt4UrH3opPcn51KUPpAkAAAAY6RTQACVgUi8rOPryn08fFl6zwwbpbmjUNTa17py+c86ScOqFs9PTnEtnz0tTd9npaAAAAGDkUEADlICqisF9ut9vq6lhs6lj0113R++4YZrixyjv/8eo6bKuo7ltCXUvPn3p/WHfb17b7cQ0AAAAULgU0AAl4py37Zqm/vvRO3ZPU35nH79zmkJobmnpViz3ZOmahjTl1DU2p6lnf7l7Xli4sq7biWkAAACgcCmgAUrEm3bfJE39N31idZrymzy2KlSWl7XOjc0tYfsvXRnOvuKx1vue3Pf8snDY925Idzk1De3F9cReXpjYpr4fhTUAAACw7imgAUpEWVmuKB5qDU2d12f8/Man47OeC+LjzrslTe3W1DemKYSxVX0X0H2V3AAAAEBhUEADlJBPHrltmobXmrr8qzh6eolgx9UdTf140eBvbnk2TQAAAEAhU0ADlJCPHL5NeOobrw1PnPXasNX649LTobe6w4nmjhavrk9TZ6/5wU3hojuea53780JCAAAAYGRQQAOUmIryUaGqYlT424cPCNtMH5+edveV1++QpoFbXZe/gO7pZHTm8//7UOu1PyegAQAAgJFBAQ1QoiZWV4a/f+TAMHlsZev9TptMbL1m3rDrxuFd+26R7nr36aO3S1O71R1WanS0piF/Md1RUz9OQLf9nAEAAIDCpoAGKGFjqsrDv//n4HDeu/YIf/7Aq8Kcs48Jz37rdeFH79y99ZR0f7xp903S1G5NTyegeyimO+pPAQ0AAACMDApogBK3wcTqcMwuG4Vxoyta78vKylqv/bXRpDFpanf/vOVp6uy2pxenKb9s/3PHkjpfuZ1ZtqYhPL9kTbobGj29IBEAAAAYPAU0AEPu21c+lqac+ctqwjMvrwrf/ffj6UnOtPFVacrZ6nOXpyln0pieV218/M/3pWntPTBvWXjVt64LW575r3DLU4vSUwAAAGBtKaABWGvZGo+Odt10UppCePyllWH/s68Lh3//xvSk3R/eu2+a8pvYSwF993NL07T2Tjr/zvDSitrW+YRf3xHunrOkdQYAAADWjgIagLW23YYTwrlv3y3d5dZ6tDnq3JvS1N32G7W/+DCf3k5AZ7Jye+HK2nD2FY+Fi++cGxatqkvfMjDLaxrSlPPbW+akCQAAAFgbCmgAhsTGk9t3Qb+ciuBVPbyMMPO+A2e0Xjea1F5WdzWuqjxN+b3157eGz/31wfDzG58On43Xvc66Jtz0xMvpWwevpqHvlyX2JXuZ4v/d90L4+/3z7ZcGAACgZCmgARgS608YnaYQXl6ZK6AbGptbr/l8+LCZrdcXl+dWX+RTUd77L1MrahvDNY8uTHc5v73l2TQN3oouJ6IH48qHXgof+9N94fSL7w1XxBkAAABKkQIagCExvUsBnZ36bWjOX0DP2nBCmDKu8wsI86ksL0tT/13/+NqfgM5Wiqyts698NE0hnHbRPWkCAACA0qKABmBIjBtdEcamlRl1jc1hZV1j6xqKfB57aWWaelc7yFUYx//s1vC1fzwy6NUXbSe418a8pTVpAgAAgNKlgAZgyIypbN/ZvGB5bWhsWrvdx01dDlD3ti+6o9nPLQ2/ueXZcEM/TkPnK6mvemRBmgav6w87FKU2AAAAjDQKaACGTHYKus3tzy4JS1bXp7ueXXvGIWnq7uBtp6Up55JTX5Wm/rn9mcVp6tmKmp5flDiUfn3zM2kCAACA0qGABmDIvLCsfe3E+f95Jpz1r0fSXWdv2HXjNIWw1bRxaepuw4nVoazDGuhNp4xNU//cO3dZmnr28PzlaRpeTy5YlSYAAAAoHQpoAIbMJpPHpCmEOYvXhLvmLE13nW0wsf2FhWUdG+YOZkwbFyrKR4W/nXZA+OAhW4V//8/B6Vv67845S9LUs9GV3X8pHBV/SoPdH52pa+y+u3pN/Stz0hoAAAAKiQIagCFT39hlaXMPpo5rL6Az5759t7DN9PHhjNdsG96656Zhp00mtj7L7LrZ5PDZ124ftttwQuv9UHvbL25PU7vs3Yk1g3wBYma7L1yZpnav1KoPAAAAKCQKaACGTFYc98eE6vZd0Znjdt8kXP2JQ8JHj9gmfPetu4Z/fvSg1uJ5bVVV9P3LXFPWNufx6Isr0jQwy9c0pKmzRwb54wEAAMBIpoAGYMh89Y07pal3VeWD/+Xnzbtvkqa+NfdQLvfHw/MHVxjf+OTLaepubX4+AAAAMBIpoAEYMhtPqk5T7yor8u997o8vv2HHcPoR24SzjtspXHvGIeGIWdNbd0Tn09jcEpatqU93A3PZ7Hlp6r/GpuZw+sX3prvuVtkDDQAAQIlRQAMwZHp6oeDHjtgmTTmVa3ECetKYyvCJ12wbTtxvi7D1+uPD+e/Zu3VH9J5bTEl/R2df+NtDaerb1HFVaQrh/nnL09Q/2UsLd//61ekuv57WcwAAAECxUkADMOw+cvjMNOWUxb+G2hHbT09TZ/984MU0dbdwZW2acvuiTzlgy3QXwvoTRofbnl4c3v2bO8Mldz+fnvbsgXnLw8ra7iecqyvbf6ldXqOABgAAoLQooAEYUgfOnJamnG++aeduJ54bm5vTNHQO3mb9NPXf0tXthfAWU8eGw2a1l9hjq8rDO391e7jxiZfDpy59IDwyf0V4809vCe/45W1hRW3798vmS2fPC9+8/NH0pN2OG08MM6aNT3chHPvjm9MEAAAApUEBDcCQqm/qXC5PHVeZpnYNTUP/Mr4J1RVp6uzoHTdMU3f1je0/1+wE9CaTx6S7EBauqEtTzpl/fSDcM3dZuP2ZJeErf384PY3PL3sgfPKS+8Mdzy5JT9ptNKk6PPpi55cZLl7V+ccFAACAYqaABmBI3dmliH3NDt0L4Ox08VDbfOrYNHVW29iUpu46luVZAT2hur0sr2no/P2yFRtt/nrPC2kK4fIHX0pTd58+elaa2tV2KL0BAACg2CmgARhW5aNy+57f/aotWq+bThkTDu+w6mKo9PQCxLqGngvfhg4FdLYmpO3n2l+1XUrqrrbdYEI4dLvOq0H6+j4AAABQTBTQAAypbaa37zzu6Euv3zH85YOvCv/66EGhunLoT0D35LZnFqepu04rOLrsqe7L7OeWhllfvDLddTdrwwmt128fv0vrtc2aOgU0AAAApUMBDcCQeuc+m6cphDfsunGacieh95kxNUwa230n9FA57117hK2mjQuv3n6D9CSn40nnjjqfgM6dfs6+f38c/7Nb05RfW7m9wcTq1pcRtllT35gmAAAAKH4KaACG1In7bRGzeThml43CF47dPj19ZWQf87pPHho++7rOu5f3/sY1rSeWu6rr8hLCzJG9vLRwIFbUNqQphGnjR6cphPnLazqdvC5UP73hqXDkD24Mlz/4YnoCAAAAA6eABmBIZUXuWcft3HoaefqE6vT0ldX1FPOyNQ3hHb+8rVvx+5E/3pOm3A7ozJQhOqG9aFV9mjq/dPHjf74/HPDt68Ly+HMqVItX1YXvXPl4eGLBqnDaRe3/HQEAAMBAKaABKDr5XkjY0NQSFqyoTXc5zS1piJ5YsLL1uumUsa3XoTSqy8/n5ZV14btXPZbuCs+KWmtCAAAAGBoKaACKUse1F21+cPUT4danFrXOKzusyMhkp30zHU8rr41vvmnnNIXw8PzlaWp34e1z01R42taRtHl20eo0AQAAwMAooAEoSotW1aWp3V/vfSGceP4d4fklazqtyOhoo8lrvzbk7DfvHN6y56bpLoT37L9lmkaG5o5Hw6NXn3NjWF5TuCtDAAAAKFwKaACK0tbrd94D3SbrVs+/+dnQ0NR5H/T0CbkT0xtNGtN6HawjZk0P79hn806niDeYmL/UzorwQtTSuX8OTfG/tD/eUbgntgEAAChcCmgAitKXXr9jmrq78YmXW/cwdzQjvbiwunLtfml8/8FbpandqFHdd1JnPvvXB9NUWJau6X46fEWXlSUAAADQHwpoAIrSwdtMS1N32U7jM//6QLrL+ezrtm+9jq4oD+/cZ/PWub8+ffR2YcLoinDMzhuFfWdMTU/bdX0JYZub0z7qQnPO1U+kqV3XndkAAADQHwpoAIpSWQ+lb5vnl9SkKWe3zSanKYRvvXnn8IVjcoX0odut33rtzbE7bxzu+/KR4bwT9sj7cV+19Xpp6mz9tPaj0Dy1MPdCxo68iBAAAIDBUEADQB7vO2irMOfsY8IFJ+8Tjt1lo9Zn+23V/XRzZtzo8lDew5qNzPjRFWnqbOdNJqWp8E0YXZkmAAAA6D8FNABF6+L375emtfPDd+we/v6RA8If3rtvetLuE6/ZNqw3fnAnma97bGGaCt/a7sYGAACgNPl/kwAUrWz1xQNfOTLd9WyzqWPSlF92unmXTSeHyvJRYY/N21d1XPOJQ8LpR2yT7gan68sQC8ELyzqvJ8lc8dBLaQIAAID+U0CXpk1jfhMzPyZrPubEnBszJaY/xsWcEPPHmMdissWgK2Pujjkjpiomn5ZecnsMwJCbWN336ohszUZ/ZaehT9h383DO23YNM6ePT08H76EXlqepsNU1NoeGpuZ0BwAAAP2jgC49W8fMjjk55s6YH8Q8E/OxmNti8r8pq7ODYi6MOSrmoZgfx1wcs0nM92Kuj6mOyee5mK/mya9jANaJzaaMTVPfNps6NnzjTTuHN++RfS1v7S1a9cqdgF64ojY8MG9ZaGnJvu7X2Y1PvBw+c+kD4cF5PRfiC+L3BwAAgIFQQJeen8ZMjzk95riYM2MOj8mK6O1ivhHTl+zPYZ8Yk72V6y0x2Y/xgZhtY+6J2T/mwzH5ZKetv5InCmhgnano5QWCw+1Tlz7wipyCzlZ97PPNa8MbfnJL+NCF2afqdnWNTeEjf7wn/Pnu58PxP7s1Pe1upJzWBgAAoHAooEvLVjHZMtSsBD4ve9DBl2OyVRonxWQrNnpzX8xFMfWtd+2yNRzfz43h0HQFWOdmbTghTfmNegUK6AmjK9LU3bE/vjnsddY14d65S9OTofeja59MUwhXPvxSuOmJl9NdCMtrGsLK2sbWub6XNRunXnhPeGm5U9AAAAD0nwK6tGQnnTNXxXRtGLLy+JaY7M+h75c9GKSGdM01Gd1lb+86JeZzMdkp6bX5WAD98tHD1+5FgUPh1+/eK5SVxV94Y16/68bpabtsFcebftrz6eO19eyi7GuM7f7fb7ItTDlNzd1XcrR5176bpynn9T+5OU0AAADQNwV0aclWbGSeSNeu2o7HZas0BisrlzNXpmtXu8acH5Ot+vhJTLZ3OjtRvXMMwLA4cOa0MK6qPN119vMT90jT8Np3q/XCTZ86LNz8mcPDIduun54Ov+sfXxgO/94N4eanFqUn3TU29VxAj+9ycjtb5QEAAAD9pYAuLZPStaclnm3Ps1PKg/GRmKNjskL5N9mDLs6JOSAma16yPw+/d8ylMVkpfV1M9hLD/sheopgvs2IAupk0tjJc9P79wudft324+wuvDnPOPibc8MlDw71ffE04eqdsnf0rI3uB4caTx4RJYyrTk+4ae1mBMRg/vf6p8EyX089t1tTn/rBKYy8noBXOAAAArA0FNB21LUHtuYno2Ztjzo3JXlB4fEzbKo6OzojJ/nx5dgxvVczdMW+NuSxmWswnYwCGxW6bTQ7vP3irMG386Nb7LaeNC1PGVbXOr7QJ1T3vg/5hh13Nvfn3wy+FLc/8V2sWr+q5JL5rTs97pa99dGHr9epHsk/d+b2wrCZNAAAAMHAK6NLSdsK57SR0VxPTtacT0j05LuZPMVmTkb188JmYgfh5uh6crn3Zs4c8FgNQ8CrLe/7l98fXPZWmnjU0NYcP/iH7gx85e551TZoGZlVd7gT0Ny/v+dPnj96xe5pydtio7ZeKEB6evzxc9fBLQ35qGwAAgOKhgC4tj6drTzue297S1dOO6HyyE8yXxCyIOSSm7WMMxMvpOi5dAYraLpv29HXA/lm6pj5N7eoam9LUf4/MX/HfNRw92XBSdfjDe/dJdyHUpo8zd/GacOyPbw4f+MPscMGtc1qfAQAAQFcK6NJyfboeGdP1n322kznbz5z9Wevbswf98K6Yi2Pmx2Tlc//+3Hh3+6XrQE9OA4xI2Qno0RWD/yV4VW330nj5mnybj3r3h9ufCyf8+o5017OZ08enKX6ifnl1eNvPbwsHf/f60JIWNp31r0dzAwAAAHShgC4tT8dcFbNlzIezBx18NSY7gfz7mI5vq8pe7Jfv5X7vjvlDzNyYbHVGX+XxHjH5TjjvEvON3BguTFeAovf7U9pPFQ/Un+96Pk3t1tTnPwFd1rbdvwf3zl2Wpp6NG915Z/Wdc5akCQAAAHqngC49p8Vku5p/FPO3mG/FXBfz8Zhs9cbnYzrKjrV1Pdp2WMxvYrJ/f7JT1SfHfKVL/iemo9NjXozJPuaPY74X88+Ye2LWi/lVTHaaGqAkdDxV3NWX/++hsKK25xPNv7ip+9f8eiqgK0cN/pf6Lxyzfet1QpcCOp/BrAABAACg+CmgS092CnqvmAti9o05I2brmKyQflXM4pi+bBHT9u/OKTFfzpOuBXRWPGdvydopJjs9nRXS2YsDr4h5Y8wHYtIf5gYofpPGVKapu9/d9lz4/P8+lO76p6ah+1qOlpaWUN/lBYEfPXxmmvp23O6btF7L+jpGHT25YFWaAAAAoJ0CujRlf3Y7O7W8UUxVTFYofywm35+pzlqHrs1DVl63Pe8p2ZqPjrIC+s0xWfMxMSb7uNnHf33M32MASkpFee+/BP/j/my9fn75Tk+3nYDOTk5/9q8Phi/+7aGwqq5zKX3fl14TKgZwIrq6sjxNAAAAMDgKaAAYYaaOy76G11lNKqD/cNtz4eI757a+YPB7/3689VlmXFV5mDy2KqzJc1K6JxWjsq8n9s+cxR1fHwAAAAA5CmgAWEfes3/XPyzSPw1d1mpkshPQTc0t4bsdSudslUeb8dW5Pc51Dd2/b08GUkB/5I/3pgkAAADaKaABYB2ZPnF0mgamvrF7iZyt3jj4O9l7YfObPqG69Xrifpu3XvM5+807pymnvEMBPZAyGgAAANoooAFgHdlwYq4UHqiH569IU7vvX/VEeGFZTbrrbuKY3AnomdMnhCN32KB17mifLaeG55asSXc5HV8++JN37ZGmnjU3e5csAAAAnSmgAWAd2XvLqWnK7/kuhXDm8ZdWpqmz5TUNacpvYnVlmkL46Ql7hM++dla6y7lzzpLw9r02S3fdZaX1Bw7eqnU+fNb01mtXc+PPd97S7j9nAAAASpcCGgDWkc2mjg3fevPO4bDt1k9POssK3a6ueXRBmgZmQtoBnakoHxU+eMjW6a7dltPGhf23Xq91/shhM1uvbUaNKgufe932Yc7Zx4TfvGfv1hK7q0O/d0M48NvXh1ufWpSeAAAAUOoU0ACwDr1zn83Db0/eJ8ycPj49adeYZ6XF6rrGNA1MxxPQvfnj+/cLz37rdeGTR22XnuT3up03Ciftt0W66+xdv74jTQAAAJQ6BTQAFIDK8u6/JP/ixqfTFEJLS0uYv6wmrKlvSk8GZuKY7gX06Ir8vw3ouPu5N58+uveSujeXzZ4Xjvj+DeHX/3kmPQEAAKAYKaABoAAcsm33NRy3Pr04TSG8//d3h/3Pvi5ccOuc9GRgOq7gaFM+qn9Fc08mVFeG4/fYNN11lhXmbeobm9MUwgPzloUtz/xXOOOS+8PTL68OZ/3r0bBqkKe6AQAAKHwKaAAoAB87Ypuw74zuLyXMytmVtQ3hmkcXpieDk28Fx9oW0JkNJ41OU2czPnt5a9GcZdsvXBHe97u7Wp+/8bxbWq8dLVtTnyYAAACKjQIaAArAmKry8OcPvip88007pyc5F97+XPjQhfeku85+edKe4bx3dX8ZYD75VnB86dgd0hTCF47ZPk0Ds8HE6jT1LivQ3/2bO0OHg9H/dd/zy9IEAABAsVFAA0ABefUO09OUs3BFXbj5qUXprrOsyz1ml41yN32YmGcFx5t23yR8+fU7hDNfOyuc2MMLBfsyfnT3H7cnNz7xcpo6+8gf700TAAAAxUYBDQAFZMrYqjTl/OaWZ9PU3RGzcmX11HGdv08+2b7mrirKR4WTD5gRTj1k61BdWZ6eDkxVDy8yBAAAgIz/1wgABaSyvP+/NGcFcmZsVd/l8bjRgyuY+/Lsy6vTBAAAAN0poAFghOu6V/nYPGs58p2AHgrjBrCCozct+ZZDAwAAMOIpoAGgwLx1z03T1D/Hd/j7j9l5o/CTPC8m7M+ajsGYsf64NK2dNfVNaQIAAKCYKKABoMBMmzA6TT075227pimEDx2ydXjDrhuHV2+/QfjyG3bIPTt069Zr5rbPHp6moXfotuuH1+604VoX3EtW16cJAACAYlKWrlAMZu8RzZ49O90CjEznXP1E+NG1T6a77u7+wqvDtPF9l9S1DU1hdMWoUFY2/L/cNze3hJN+c0e45anF6cnA/PF9+4b9Z05LdwAAQKHYc889wz1RNuaewMA4AQ0ABaaqvOfC+Muv36Ff5XOmurL8FSmfM6NGlYWz37xLuhu4BStr0wQAAEAxUUADQIGpKM//y/N3jt8lnHzAjHRXeDabOja8ZocNWufj9+i8x/qIWdPDRpOq013Oew9s/8/y0vK6NAEAAFBMFNAAUGAqRuU/tbzNBuPTVLh+edKe4YZPHhq+99Zdwu9P2SdkB7CrKkaFL71+hzCmsjz9XTkbTmwvpBescAKa0tHY1BzOv/nZcN71T7WuygEAgGKmgAaAAtPTC/123XRymgpXtvJjy2njWq8Hb7t+uOUzh4c7PntE2GK9ceHs49tXdHzrzTuH6RPbV4lccOucNEHx+/v988PX//lI+O6/Hw+/vOmZ9BQAAIqTAhoACszrd904bDplTLoLYYOJo8N1ZxzSumd5pNl48pgwJRXqe285JZz/7r3CD96+a3jLnpuGsVUVrc/bbHnmv9IExe3bVz6WptxLRwEAoJgpoAGgwFSWjwrXfOKQcNXHDw5zzj4m3P7ZI8JW6xf++o2+ZKeij9h+g/Cm3Tdt/c84tqrzSg4oFdkLQgEAoFQooAGgAGUF1bYbTGids+K2GI3JU0DXNdqHS/GbNKYyTQAAUPwU0ADAOjFhdOcVHJkFy+vSBMVrVV1jmnJaWlrSBAAAxUcBDQCsExtNbt9z3ebe55emCYrX5lPHpimnvqk5TQAAUHwU0ADAOjF+dEU4Ytb0dJfzsT/dlyYoXvvMmJqmnDV1Vs8AAFC8FNAAwDrzi5P2TBOUjrL4V0drGhTQAAAULwU0ALDOVJR3/63IVQ+/lCYoDXfPWZImAAAoPgpoAKCgfOAPs9MExakl/tXRmZc9mCYAACg+CmgAYJ3adbPJaYLSNH3i6DQBAEDxUUADAOvUBe/ZO01Qmg7ddv00AQBA8VFAAwDr1JRxVWGb6ePTXU5Tc0uY/dySsLymIT0ZevOX1YQ/3zU3LFxZm57AurGyrjFNAABQfBTQAMA6976DZqQpZ+vPXR6O/9lt4cBvXxdqG5rS06HT3NwS9j/7uvCZyx4M+3zj2tZ7WFdW1iqgAQAoXgpoAGCdm9nlBHSbrJib9cUrw/t+d1d6MnjPvLwqnHT+HeGLf3soLOhy6vm0i+5JEwy/li5f71hZO3wn/QEAYF1TQAMA69wem09JU37XPLowPLd4dbrrnzmLVod5S9ekuxC+dcVj4T9PLgp/uP25cPrF96anOVc+/FKa4JXnBDQAAMVMAQ0ArHNlZWVp6tnvb3suTX279elF4dDv3RAO/Pb1rYVzS0tLuPqRBelbQ7hrztI05bx5903SBK88BTQAAMVMAQ0AjAg9renIfOvyR8MBZ18X/vnA/NayueNKjWzlxt/ueyHd5bdkTX2a4JU3d0n7SX0AACg2CmgAYET47F8fTFNnTy1cFX5x0zPhhWU14SN/vDfsedY1Ydmazjt1P/7n+9OU3+JVw1NAX/fYgrDzV/4dfn7j0+kJ5GcPNAAAxUoBDQAUhO03mpimnuUr6Z5YsDJNOUtWD7xMXryqLk1D65QL7m5dr3D2FY+F551ypRcX3TE3TQAAUFwU0ABAQTh5/y3T1LOFK3NF8X+efDm84Sc3hx9d+2RYXrP2J0cXra5vXd0xnA76zvXhqYWdy3JoM5gvnAAAwEiggAYACsIGk6rT1LMrHnyx9XrS+XeGB+YtD+dc/UTrdW3VNzaHlXVr/yK4+55fFl73w/+ET15yf2hoak5P2736nJvCudc8ke6g3dbrj0sTAAAUFwU0AFAQ9ttqapp69r2rnghf+fvD6S7n4juHZnXB8i57o7OT1f9777wwf1lNetK3D/z+7vDIiyvCpbPnhW0+f0V62tm51zyZJkpVvtP2q+qa0gQAAMVFAQ0AFITRFeXho4fPTHc9u+DWOWkaWrUNnQvA7BRz9vLCt/78ttDY5TRzc3NLuOWpReGdv7w9fO0fj/z3tHPbihAYqIF8oQMAAEYSBTQAUDCeWrgqTa+8mi4F9NWPLGi9vrCsJjze4UWHWfl88HevDyf8+o5w2zOLw29ueTb86a7n07fC4LzsixcAABQpBTQAUDBev+vGacrZaFJ1v1ZzDIXahvZTzl1PPLdtTFi6uj786Lonw7ylnU+r/uP++WmCwfESQgAAipUCGgAoGEfvuGGaQthivbHhts8eEf74vv3Sk+HV8QT0itrOLyRcGe+zlRuHff+GvDuc871wsDfXpNPV0GaxAhoAgCKlgAYACsaoUWXh5s8cFr7xpp3CJR981X+fvRJq6tsL6GVrOpeB7/zV7a0rN5Z1eVFhm46np/vjfb+/OyxeZeVCqcrzDsKwuq7zFz0AAKBYKKABgIKy6ZSx4YR9twjTJ1anJ0Nr/63XS1NnX/jbQ2kK4aXltWnqn0dfXJGm/rvv+WVpghDqGjvvIAcAgGKhgAYACl5PpXFH5aPKwrfevHO6y6+qYlT4yGEz011ni1bVhdnPLWmdz722+5qN/thx44lp6tsj8wdeWlO8BnqKHgAARgoFNABQ8L771l3T1LMZ08aFY3bZKN3l7LLppHDSfluEC07eO7x9r83CZafuH/bbar1w4Mxpoap8VJg8tjL9nTk/ue6p0NLSEu58NldE91fbx23Os1qhJ9c8tjBNEMLymvzrXQAAYKRTQAMABW+TyWPCZR/K7YTuyZq6xjCxurK1bH7bXpuGqz9+cPj7Rw4MXz9up3DodtPDt9+yS9h500mtO6UvfN++4YGvHBnef9BW6XvnXP/4y2HGZy9Pd/3X0Jg7vdqcp4HOXqZYXdn9t1wHzuz7VDfFqaevU9Snf48AAKCYKKABgBFhzy2mpim/+Wlvc1Y2f+ctu4ZtNpjQet+T6sryMHFM5xPQg3XVIwvC80vWhKY8b5d7+96bhZs+fVj424cPSE9yBnJamtLw4vKaNAEAQPFQQAMAI8anjtqu9ZrtWt56/XGt89qYWF2RprV30Heu73aCdffNJ4cPHbJ1mD6hOuy22eTwxt02Tt8SQk19U5izaHX49KX3h7/c/Xx6Sikb6MsvAQBgJFBAAwAjxocPmxnu//KR4V+nHxReWNb5tOjrd20vd/trvXGj0zQwW60/rnW1Rldzl6xJUwjXnXFI+N/TDghlZWXpSeeXKa6uawxnX/FY+Mvd88KnL30gzH5uafoWStXZVz6WJgAAKB4KaABgRJmU1mbUNnQ+bfyjd+yWpv7LTlIPxr//5+Bw8fv3S3f5lY9qL57bjK1qP3G9pr4pXPnwS+kuhON/dmu47enF6Y5SlJ2IBwCAYqOABgCKQseTxv01ZVxVOO9de6S7/smK5YqY8X2s7xiV5+cztqo8TSHc+MTLaWp34vl3pIlilmdVeKt37bt5mgAAoHgooAGAknbMLhuFWRv2/sLCjr7y+h1ay+5xHU4z55PvBHRleftvvVbVNaapXZM3E5a0ilF+aw4AQPHxu1wAYET63lt3TdPa+9obd0pT30561Zat13wFc0dTx1Wlqd2W6/X94sTFq+rSlNPc3NLtGcWjqqL9t+P/uH9+mgAAoHgooAGAEen4PTaJ2TTMnD4+/PkDve9j7svGk6vT1LvNpo5JU86MaT0XytWV7es22mye58WFXd33/LI0hXDlQy+GrT53edjzrGvCBbc8m55STOob23eZP2MHNAAARUgBDQCMSNkajO+/bddwzScOCftutV56Ojhj8pTFmW03GB9+f8o+6S6Ejx62TZpy/v6RA9I0dB56YUWaQjj1wnvSFMJX/vFImhjpWuJfAABQKhTQAEDJW2/86DR19qN37h4O3nb9cPcXXh2u+vjB4W17b5a+JWdCdWWaOvvaG3dM08Atr2lovT61cFXrFQAAYCRTQAMAdJG9mDA7WT1rw4mt99PGjw7bbpD/RYWV5d13Qf+/tCd6MBavzu17/vSl97deu3r0xRXh3GueCM+8rKAuBtkaGQAAKGYKaACA6NXbb5CmEM48elbrbun+2Hhy573QXzp2hzTld9679khTfitrG1uv98xt3wXdJtsXfPzPbg3nXvNkOPz7N4abnng5LFldn751aDQ0NYcrHnwx3D1nSXoSQl1jU1hRmzuZzdCaOKYiTSGMH90+AwBAsVBAAwBEX3nDDuF9B84IPz9xz7DZ1L5fFtjm7DfvkqYQ3rzHJuGU+GP05sgd24vufFb2UvTOXbImrKlvSnch/L/f3Bn2+PrV4cLbnwtNzUOzV/jiO+eGD110T3jLz28Lj720IixeVRcO/Pb1Ya+zrgm3PLUo/V0MldEV7fvHaxva/9kCAECxUEADAESbThkbvnDsDuHonTZMT/pnv62mhr988FWtLyv83lt2TU97Vlne+2+/7pqzNE3d/eaWZ9PU2Rf+9lC44NY56a5dS0tLmL+sJt31Lfv7v/R/D6e7EI4+9z9hz7OuCS+vrGs9fX3Cr+9o/XtYOx3/K6yqGBXK0haXxuaW0NjUnLsBAIAioYAGAFgLZWVlYZ8ZU1tfVjhqVPd90INx/WML09TZH++Ym6buvv7PR0JNh9PRmff+7u6w/9nXha/8vb1U7smv//NMmPHZy9Ndz2560inooZT9G9OxkK5XQAMAUGQU0AAAr7BPHbVdmvI7+YK70jQwP7n+yTSF8NLy2nBdKrLznY7u6LnFq8NZ/3o03fXu3b+5M00MhycXeLkkAADFRQENAPAK+/BhM8Mnj9w23YXwhl03TtPa+ecDL6Yp98LCjp5dtDpN3T364oo0sa5l+7wBAKCYKKABANaBUw/ZOrz3wBnhTbtvEr70+h3S07Xz3OI1aQqhoblzAf3Da55IU3cdX4TH8Otti3Z1pX8WAAAUFwU0AMA6UFE+Knzx2B3CD96+W5g2fnT45Ul7pm9ZO4/Mz51mrm3ovA/6b/fNT1N3a7rsju7Nawf4kkZ61/YCwjb7b71emgAAoDgooAEACsDum09J09r59pWPtV67FtC9WV3XmCbWhdft3F7q3/HskjQBAEBxUEADABSASWMq09TZ8Xtsmqb+eWFZTeu1tqHzCo5MS0v+5Q+rBlBAr6xVVg+1+59fnqYQ1p8wOk0AAFAcFNAAAAWgqiL/b8s+eMhWYddNJ6W7dgdtMy1NnR28zfqt15o8azXmLc2V010N5AT08pqGNDFoXb4Q8JY927/IsMJ/vwAAFBkFNABAARtTWR7un9d+QrbNH967b/j28TuHUV12CM9ZvLr1WtvYvYDuqTzueAL6U0dtFx752lHhS8fmfzHigy90/7n0pKm5JVz+4IvhyodeCs1xpruy+Nf0ie2nnhX8AAAUGwU0AECB2Hr9cWlqN7G6+2qOUw6Y0Xp9+96bh9lfeE349NHbtd5nrntsYes13wqOJavr09TZ3CVr0hTChhOrw9iqinDKgTPC3V94dTjt0K27vSBx9nP921P874dfCqdddE849cLZ4Z2/uj09pavxoyvSFMLqAbwQEgAARgIFNABAgfjrhw4IW6w3Nt3ljBtdnqZ2px8xM00hTBlXFR6ZvyLdtavJ8xLCxavr0tQu2wt9xUMvpbvQ6eNPGz86fProWeGI7TdIT3KO/9lt4dDvXp/uepaVz22yl+vNXdxedNNuXFV7Ab3GCyEBACgyCmgAgAIxaWxl+P0p+6S7nIryUeGvp+2f7kL40KFbh8ljq9JdzrG7bJymnLvnLAlf/NtD6a7dQy90L6qvemRBmnI2mjwmTe3Ku+75iOYsXhNeXJ5/p3RP7oo/L7ob2+GLDKvrFdAAABQXBTQAQAHZYr1x4agdN2jd7fyZo2e1Pttj8ynhmW++Ltz/5SP/+6yjI7afnqact/z8tjR1dtEdz4WtPvuv8L1/P9568jnzqUvub722mT6hfR9xX+6eszRN/fPtKx9LU2nrug270wloKzgAACgyCmgAgALzi5P2Cg999ajW085tRo0qC5PGdN8Hnaks799v6bK90Nm7AH9y/VPhu/9+PDz0wvKworbziduefqwZ07rvp35ywcrWIvuMv9wftjzzX+G6xzqfpt6ky2nq9cb3v9wuFWVlndesrLaCAwCAIqOABgAoQNmLAIfTT294Ohz745vTXc62G4xPU3fvPTD34sOOfnHTM+Hu55aGy+6Z13p/ygV3//dkdWbm9M4/3qu2Wi9NdNTxn7UT0AAAFBsFNABAERg/eu0L63Petluaunvspe77o+sam8Nbu6z7WF7TkKYQarqUqTUNTvfm03EFhxPQAAAUGwU0AEARyFY5rK0NJlanqbsDZ05LU+8uuTt3GjpT09C5gF5d1/n+peW14ehzbwqHfvf68PD85elp8etwSLxV55cQNnU6RQ4AACOdAhoAoAjM2nBCmjo75227pqlvE6p7PkV91I4bpql337j80dbr0tX14cEXOpfKa+pzp3uzU74X3PJs+OjF94THXloZ5ixeE776j0dav63UZF83yPZuV6Xd203NLaG+qbl1BgCAYqCABgAoAhecvE+aOnvT7pukqW/Vle0ncbsqKysLnz56u3TXt+9e9Xia2t33fK6QznZHf+Ufj4S75ixtvc/c+eySNJWmjqeg13Q5KQ4AACOZAhoAoAiMy7MDelRZrjjuj503mZSmnp126Mxw22cPT3e9++Mdc9PUbtGqunDir+8IP7r2yfSENmM7lP+r00lxAAAoBgpoAIAi0fVFhG/YdeM09e2nJ+yRpt5tNGlMmvKbNr4qTfnd/NSiNPVPbUNT+PNdc8P1jy1MT4ZOtibk3GueCJc/+GJ6su6M7fDPbk2XlzcCAMBIpoAGACgS33tr533PG03OlcX9WcMxpqrn9RsDsWhV/ZCWxedd/1T4zGUPhpMvuCtc+dDQFsXv/NXt4dxrngynXXRPePrlVelpuysfeikccPZ14cv/91B6MjRa4l9dLa9pSFMIS1bXpwkAAEY+BTQAQJE4eNtpacppOxG9z4yprdfeVFX0/7eFZx23U5ryy8riwTjmR/8JdY2dT//++Lqn0hTCqRfek6ahkb0Asc0Ft8xJU86yNfXx480OLyyrCb+77bnw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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQC4i8v+kZhy3ZNYezwAAAABJRU5ErkJggg==\" width=\"720\">"
],
"text/plain": [
"<IPython.core.display.HTML object>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "17e4d6a8e9c442fa8f338dd3fac6320b",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"HBox(children=(IntProgress(value=0, max=2), HTML(value='')))"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "e847cfe3d77c46c39e035c1a662cc081",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"HBox(children=(IntProgress(value=0, max=5735), HTML(value='')))"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "5e0b2825f51b4e4fa8dc36b60eeeaa68",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"HBox(children=(IntProgress(value=0, max=7024), HTML(value='')))"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'loss': 0.20606761486412598, 'val_loss': 0.10316659465518617}\n"
]
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "bbfca15899ec4345982dc68cb229f83f",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"HBox(children=(IntProgress(value=0, max=5735), HTML(value='')))"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "1713193520bc425c8086f2eafb9c238a",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"HBox(children=(IntProgress(value=0, max=7024), HTML(value='')))"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'loss': 0.17250198044943754, 'val_loss': 0.10809300407069335}\n",
"0.10316659465518617\n"
]
}
],
"source": [
"%matplotlib nbagg\n",
"\n",
"num_split=2\n",
"np.random.seed(SEED+num_split)\n",
"torch.manual_seed(SEED+num_split)\n",
"torch.cuda.manual_seed(SEED+num_split)\n",
"#torch.backends.cudnn.deterministic = True\n",
"idx_train = train_df[train_df.PID.isin(set(split_sid[splits[num_split][0]]))].index.values\n",
"idx_validate = train_df[train_df.PID.isin(set(split_sid[splits[num_split][1]]))].index.values\n",
"idx_train.shape\n",
"idx_validate.shape\n",
"\n",
"klr=1\n",
"batch_size=32\n",
"num_workers=12\n",
"num_epochs=2\n",
"model_name,version = 'Densenet161_3' , 'basic_splits'\n",
"model = MyDenseNet(models.densenet161(pretrained=True),\n",
" len(hemorrhage_types),\n",
" num_channels=3,\n",
" drop_out=0.2,\n",
" wso=((40,80),(80,200),(600,2800)),\n",
" strategy='none',\n",
" dont_do_grad=[],\n",
" pool_type='max',\n",
" extra_pool=4,\n",
" )\n",
"\n",
"_=model.to(device)\n",
"weights = torch.tensor([1.,1.,1.,1.,1.,2.],device=device)\n",
"loss_func=my_loss\n",
"targets_dataset=D.TensorDataset(torch.tensor(train_df[hemorrhage_types].values,dtype=torch.float))\n",
"transform=MyTransform(flip=True,zoom=0.05,rotate=15,out_size=512,shift=40)\n",
"imagedataset = ImageDataset(train_df,transform=transform.random,base_path=train_images_dir,\n",
" window_eq=False,equalize=False,rescale=True)\n",
"transform_val=MyTransform(out_size=512)\n",
"imagedataset_val = ImageDataset(train_df,transform=transform_val.random,base_path=train_images_dir,\n",
" window_eq=False,equalize=False,rescale=True)\n",
"combined_dataset=DatasetCat([imagedataset,targets_dataset])\n",
"combined_dataset_val=DatasetCat([imagedataset_val,targets_dataset])\n",
"#param_s=parameter_scheduler(model,num_epoch=0)\n",
"optimizer_grouped_parameters=get_optimizer_parameters(model,klr)\n",
"sampling=sampler(train_df[hemorrhage_types].values[idx_train],0.2,[10,1,1,1,1,0])\n",
"sample_ratio=1.02*float(sampling().shape[0])/idx_train.shape[0]\n",
"train_dataset=D.Subset(combined_dataset,idx_train)\n",
"validate_dataset=D.Subset(combined_dataset_val,idx_validate)\n",
"num_train_optimization_steps = num_epochs*(sample_ratio*len(train_dataset)//batch_size+int(len(train_dataset)%batch_size>0))\n",
"fig,ax = plt.subplots(figsize=(10,7))\n",
"gr=loss_graph(fig,ax,num_epochs,int(num_train_optimization_steps/num_epochs)+1,limits=[0.05,0.4])\n",
"sched=WarmupExpCosineWithWarmupRestartsSchedule( t_total=num_train_optimization_steps, cycles=num_epochs//2,tau=1)\n",
"optimizer = BertAdam(optimizer_grouped_parameters,lr=klr*1e-3,schedule=sched)\n",
"model, optimizer = amp.initialize(model, optimizer, opt_level=\"O1\",verbosity=0)\n",
"history,best_model= model_train(model,\n",
" optimizer,\n",
" train_dataset,\n",
" batch_size,\n",
" num_epochs,\n",
" loss_func,\n",
" weights=weights,\n",
" do_apex=False,\n",
" model_apexed=True,\n",
" validate_dataset=validate_dataset,\n",
" param_schedualer=None,\n",
" weights_data=None,\n",
" metric=None,\n",
" return_model=True,\n",
" num_workers=num_workers,\n",
" sampler=sampling,\n",
" graph=gr,\n",
" call_progress=sendmeemail)\n",
"torch.save(model.state_dict(), models_dir+models_format.format(model_name,version,num_split))\n",
"torch.save(best_model.state_dict(), models_dir+models_format.format(model_name,version+'_best',num_split))"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<torch._C.Generator at 0x7f06349ec5d0>"
]
},
"execution_count": 22,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"text/plain": [
"(449503,)"
]
},
"execution_count": 22,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"text/plain": [
"(224749,)"
]
},
"execution_count": 22,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"text/plain": [
"<All keys matched successfully>"
]
},
"execution_count": 22,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"application/javascript": [
"/* Put everything inside the global mpl namespace */\n",
"window.mpl = {};\n",
"\n",
"\n",
"mpl.get_websocket_type = function() {\n",
" if (typeof(WebSocket) !== 'undefined') {\n",
" return WebSocket;\n",
" } else if (typeof(MozWebSocket) !== 'undefined') {\n",
" return MozWebSocket;\n",
" } else {\n",
" alert('Your browser does not have WebSocket support.' +\n",
" 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
" 'Firefox 4 and 5 are also supported but you ' +\n",
" 'have to enable WebSockets in about:config.');\n",
" };\n",
"}\n",
"\n",
"mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n",
" this.id = figure_id;\n",
"\n",
" this.ws = websocket;\n",
"\n",
" this.supports_binary = (this.ws.binaryType != undefined);\n",
"\n",
" if (!this.supports_binary) {\n",
" var warnings = document.getElementById(\"mpl-warnings\");\n",
" if (warnings) {\n",
" warnings.style.display = 'block';\n",
" warnings.textContent = (\n",
" \"This browser does not support binary websocket messages. \" +\n",
" \"Performance may be slow.\");\n",
" }\n",
" }\n",
"\n",
" this.imageObj = new Image();\n",
"\n",
" this.context = undefined;\n",
" this.message = undefined;\n",
" this.canvas = undefined;\n",
" this.rubberband_canvas = undefined;\n",
" this.rubberband_context = undefined;\n",
" this.format_dropdown = undefined;\n",
"\n",
" this.image_mode = 'full';\n",
"\n",
" this.root = $('<div/>');\n",
" this._root_extra_style(this.root)\n",
" this.root.attr('style', 'display: inline-block');\n",
"\n",
" $(parent_element).append(this.root);\n",
"\n",
" this._init_header(this);\n",
" this._init_canvas(this);\n",
" this._init_toolbar(this);\n",
"\n",
" var fig = this;\n",
"\n",
" this.waiting = false;\n",
"\n",
" this.ws.onopen = function () {\n",
" fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n",
" fig.send_message(\"send_image_mode\", {});\n",
" if (mpl.ratio != 1) {\n",
" fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n",
" }\n",
" fig.send_message(\"refresh\", {});\n",
" }\n",
"\n",
" this.imageObj.onload = function() {\n",
" if (fig.image_mode == 'full') {\n",
" // Full images could contain transparency (where diff images\n",
" // almost always do), so we need to clear the canvas so that\n",
" // there is no ghosting.\n",
" fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
" }\n",
" fig.context.drawImage(fig.imageObj, 0, 0);\n",
" };\n",
"\n",
" this.imageObj.onunload = function() {\n",
" fig.ws.close();\n",
" }\n",
"\n",
" this.ws.onmessage = this._make_on_message_function(this);\n",
"\n",
" this.ondownload = ondownload;\n",
"}\n",
"\n",
"mpl.figure.prototype._init_header = function() {\n",
" var titlebar = $(\n",
" '<div class=\"ui-dialog-titlebar ui-widget-header ui-corner-all ' +\n",
" 'ui-helper-clearfix\"/>');\n",
" var titletext = $(\n",
" '<div class=\"ui-dialog-title\" style=\"width: 100%; ' +\n",
" 'text-align: center; padding: 3px;\"/>');\n",
" titlebar.append(titletext)\n",
" this.root.append(titlebar);\n",
" this.header = titletext[0];\n",
"}\n",
"\n",
"\n",
"\n",
"mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n",
"\n",
"}\n",
"\n",
"\n",
"mpl.figure.prototype._root_extra_style = function(canvas_div) {\n",
"\n",
"}\n",
"\n",
"mpl.figure.prototype._init_canvas = function() {\n",
" var fig = this;\n",
"\n",
" var canvas_div = $('<div/>');\n",
"\n",
" canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n",
"\n",
" function canvas_keyboard_event(event) {\n",
" return fig.key_event(event, event['data']);\n",
" }\n",
"\n",
" canvas_div.keydown('key_press', canvas_keyboard_event);\n",
" canvas_div.keyup('key_release', canvas_keyboard_event);\n",
" this.canvas_div = canvas_div\n",
" this._canvas_extra_style(canvas_div)\n",
" this.root.append(canvas_div);\n",
"\n",
" var canvas = $('<canvas/>');\n",
" canvas.addClass('mpl-canvas');\n",
" canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n",
"\n",
" this.canvas = canvas[0];\n",
" this.context = canvas[0].getContext(\"2d\");\n",
"\n",
" var backingStore = this.context.backingStorePixelRatio ||\n",
"\tthis.context.webkitBackingStorePixelRatio ||\n",
"\tthis.context.mozBackingStorePixelRatio ||\n",
"\tthis.context.msBackingStorePixelRatio ||\n",
"\tthis.context.oBackingStorePixelRatio ||\n",
"\tthis.context.backingStorePixelRatio || 1;\n",
"\n",
" mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n",
"\n",
" var rubberband = $('<canvas/>');\n",
" rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n",
"\n",
" var pass_mouse_events = true;\n",
"\n",
" canvas_div.resizable({\n",
" start: function(event, ui) {\n",
" pass_mouse_events = false;\n",
" },\n",
" resize: function(event, ui) {\n",
" fig.request_resize(ui.size.width, ui.size.height);\n",
" },\n",
" stop: function(event, ui) {\n",
" pass_mouse_events = true;\n",
" fig.request_resize(ui.size.width, ui.size.height);\n",
" },\n",
" });\n",
"\n",
" function mouse_event_fn(event) {\n",
" if (pass_mouse_events)\n",
" return fig.mouse_event(event, event['data']);\n",
" }\n",
"\n",
" rubberband.mousedown('button_press', mouse_event_fn);\n",
" rubberband.mouseup('button_release', mouse_event_fn);\n",
" // Throttle sequential mouse events to 1 every 20ms.\n",
" rubberband.mousemove('motion_notify', mouse_event_fn);\n",
"\n",
" rubberband.mouseenter('figure_enter', mouse_event_fn);\n",
" rubberband.mouseleave('figure_leave', mouse_event_fn);\n",
"\n",
" canvas_div.on(\"wheel\", function (event) {\n",
" event = event.originalEvent;\n",
" event['data'] = 'scroll'\n",
" if (event.deltaY < 0) {\n",
" event.step = 1;\n",
" } else {\n",
" event.step = -1;\n",
" }\n",
" mouse_event_fn(event);\n",
" });\n",
"\n",
" canvas_div.append(canvas);\n",
" canvas_div.append(rubberband);\n",
"\n",
" this.rubberband = rubberband;\n",
" this.rubberband_canvas = rubberband[0];\n",
" this.rubberband_context = rubberband[0].getContext(\"2d\");\n",
" this.rubberband_context.strokeStyle = \"#000000\";\n",
"\n",
" this._resize_canvas = function(width, height) {\n",
" // Keep the size of the canvas, canvas container, and rubber band\n",
" // canvas in synch.\n",
" canvas_div.css('width', width)\n",
" canvas_div.css('height', height)\n",
"\n",
" canvas.attr('width', width * mpl.ratio);\n",
" canvas.attr('height', height * mpl.ratio);\n",
" canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n",
"\n",
" rubberband.attr('width', width);\n",
" rubberband.attr('height', height);\n",
" }\n",
"\n",
" // Set the figure to an initial 600x600px, this will subsequently be updated\n",
" // upon first draw.\n",
" this._resize_canvas(600, 600);\n",
"\n",
" // Disable right mouse context menu.\n",
" $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n",
" return false;\n",
" });\n",
"\n",
" function set_focus () {\n",
" canvas.focus();\n",
" canvas_div.focus();\n",
" }\n",
"\n",
" window.setTimeout(set_focus, 100);\n",
"}\n",
"\n",
"mpl.figure.prototype._init_toolbar = function() {\n",
" var fig = this;\n",
"\n",
" var nav_element = $('<div/>')\n",
" nav_element.attr('style', 'width: 100%');\n",
" this.root.append(nav_element);\n",
"\n",
" // Define a callback function for later on.\n",
" function toolbar_event(event) {\n",
" return fig.toolbar_button_onclick(event['data']);\n",
" }\n",
" function toolbar_mouse_event(event) {\n",
" return fig.toolbar_button_onmouseover(event['data']);\n",
" }\n",
"\n",
" for(var toolbar_ind in mpl.toolbar_items) {\n",
" var name = mpl.toolbar_items[toolbar_ind][0];\n",
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
" var image = mpl.toolbar_items[toolbar_ind][2];\n",
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
"\n",
" if (!name) {\n",
" // put a spacer in here.\n",
" continue;\n",
" }\n",
" var button = $('<button/>');\n",
" button.addClass('ui-button ui-widget ui-state-default ui-corner-all ' +\n",
" 'ui-button-icon-only');\n",
" button.attr('role', 'button');\n",
" button.attr('aria-disabled', 'false');\n",
" button.click(method_name, toolbar_event);\n",
" button.mouseover(tooltip, toolbar_mouse_event);\n",
"\n",
" var icon_img = $('<span/>');\n",
" icon_img.addClass('ui-button-icon-primary ui-icon');\n",
" icon_img.addClass(image);\n",
" icon_img.addClass('ui-corner-all');\n",
"\n",
" var tooltip_span = $('<span/>');\n",
" tooltip_span.addClass('ui-button-text');\n",
" tooltip_span.html(tooltip);\n",
"\n",
" button.append(icon_img);\n",
" button.append(tooltip_span);\n",
"\n",
" nav_element.append(button);\n",
" }\n",
"\n",
" var fmt_picker_span = $('<span/>');\n",
"\n",
" var fmt_picker = $('<select/>');\n",
" fmt_picker.addClass('mpl-toolbar-option ui-widget ui-widget-content');\n",
" fmt_picker_span.append(fmt_picker);\n",
" nav_element.append(fmt_picker_span);\n",
" this.format_dropdown = fmt_picker[0];\n",
"\n",
" for (var ind in mpl.extensions) {\n",
" var fmt = mpl.extensions[ind];\n",
" var option = $(\n",
" '<option/>', {selected: fmt === mpl.default_extension}).html(fmt);\n",
" fmt_picker.append(option)\n",
" }\n",
"\n",
" // Add hover states to the ui-buttons\n",
" $( \".ui-button\" ).hover(\n",
" function() { $(this).addClass(\"ui-state-hover\");},\n",
" function() { $(this).removeClass(\"ui-state-hover\");}\n",
" );\n",
"\n",
" var status_bar = $('<span class=\"mpl-message\"/>');\n",
" nav_element.append(status_bar);\n",
" this.message = status_bar[0];\n",
"}\n",
"\n",
"mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n",
" // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n",
" // which will in turn request a refresh of the image.\n",
" this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n",
"}\n",
"\n",
"mpl.figure.prototype.send_message = function(type, properties) {\n",
" properties['type'] = type;\n",
" properties['figure_id'] = this.id;\n",
" this.ws.send(JSON.stringify(properties));\n",
"}\n",
"\n",
"mpl.figure.prototype.send_draw_message = function() {\n",
" if (!this.waiting) {\n",
" this.waiting = true;\n",
" this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n",
" }\n",
"}\n",
"\n",
"\n",
"mpl.figure.prototype.handle_save = function(fig, msg) {\n",
" var format_dropdown = fig.format_dropdown;\n",
" var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n",
" fig.ondownload(fig, format);\n",
"}\n",
"\n",
"\n",
"mpl.figure.prototype.handle_resize = function(fig, msg) {\n",
" var size = msg['size'];\n",
" if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n",
" fig._resize_canvas(size[0], size[1]);\n",
" fig.send_message(\"refresh\", {});\n",
" };\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n",
" var x0 = msg['x0'] / mpl.ratio;\n",
" var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n",
" var x1 = msg['x1'] / mpl.ratio;\n",
" var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n",
" x0 = Math.floor(x0) + 0.5;\n",
" y0 = Math.floor(y0) + 0.5;\n",
" x1 = Math.floor(x1) + 0.5;\n",
" y1 = Math.floor(y1) + 0.5;\n",
" var min_x = Math.min(x0, x1);\n",
" var min_y = Math.min(y0, y1);\n",
" var width = Math.abs(x1 - x0);\n",
" var height = Math.abs(y1 - y0);\n",
"\n",
" fig.rubberband_context.clearRect(\n",
" 0, 0, fig.canvas.width, fig.canvas.height);\n",
"\n",
" fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n",
" // Updates the figure title.\n",
" fig.header.textContent = msg['label'];\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_cursor = function(fig, msg) {\n",
" var cursor = msg['cursor'];\n",
" switch(cursor)\n",
" {\n",
" case 0:\n",
" cursor = 'pointer';\n",
" break;\n",
" case 1:\n",
" cursor = 'default';\n",
" break;\n",
" case 2:\n",
" cursor = 'crosshair';\n",
" break;\n",
" case 3:\n",
" cursor = 'move';\n",
" break;\n",
" }\n",
" fig.rubberband_canvas.style.cursor = cursor;\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_message = function(fig, msg) {\n",
" fig.message.textContent = msg['message'];\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_draw = function(fig, msg) {\n",
" // Request the server to send over a new figure.\n",
" fig.send_draw_message();\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n",
" fig.image_mode = msg['mode'];\n",
"}\n",
"\n",
"mpl.figure.prototype.updated_canvas_event = function() {\n",
" // Called whenever the canvas gets updated.\n",
" this.send_message(\"ack\", {});\n",
"}\n",
"\n",
"// A function to construct a web socket function for onmessage handling.\n",
"// Called in the figure constructor.\n",
"mpl.figure.prototype._make_on_message_function = function(fig) {\n",
" return function socket_on_message(evt) {\n",
" if (evt.data instanceof Blob) {\n",
" /* FIXME: We get \"Resource interpreted as Image but\n",
" * transferred with MIME type text/plain:\" errors on\n",
" * Chrome. But how to set the MIME type? It doesn't seem\n",
" * to be part of the websocket stream */\n",
" evt.data.type = \"image/png\";\n",
"\n",
" /* Free the memory for the previous frames */\n",
" if (fig.imageObj.src) {\n",
" (window.URL || window.webkitURL).revokeObjectURL(\n",
" fig.imageObj.src);\n",
" }\n",
"\n",
" fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
" evt.data);\n",
" fig.updated_canvas_event();\n",
" fig.waiting = false;\n",
" return;\n",
" }\n",
" else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n",
" fig.imageObj.src = evt.data;\n",
" fig.updated_canvas_event();\n",
" fig.waiting = false;\n",
" return;\n",
" }\n",
"\n",
" var msg = JSON.parse(evt.data);\n",
" var msg_type = msg['type'];\n",
"\n",
" // Call the \"handle_{type}\" callback, which takes\n",
" // the figure and JSON message as its only arguments.\n",
" try {\n",
" var callback = fig[\"handle_\" + msg_type];\n",
" } catch (e) {\n",
" console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n",
" return;\n",
" }\n",
"\n",
" if (callback) {\n",
" try {\n",
" // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n",
" callback(fig, msg);\n",
" } catch (e) {\n",
" console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n",
" }\n",
" }\n",
" };\n",
"}\n",
"\n",
"// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n",
"mpl.findpos = function(e) {\n",
" //this section is from http://www.quirksmode.org/js/events_properties.html\n",
" var targ;\n",
" if (!e)\n",
" e = window.event;\n",
" if (e.target)\n",
" targ = e.target;\n",
" else if (e.srcElement)\n",
" targ = e.srcElement;\n",
" if (targ.nodeType == 3) // defeat Safari bug\n",
" targ = targ.parentNode;\n",
"\n",
" // jQuery normalizes the pageX and pageY\n",
" // pageX,Y are the mouse positions relative to the document\n",
" // offset() returns the position of the element relative to the document\n",
" var x = e.pageX - $(targ).offset().left;\n",
" var y = e.pageY - $(targ).offset().top;\n",
"\n",
" return {\"x\": x, \"y\": y};\n",
"};\n",
"\n",
"/*\n",
" * return a copy of an object with only non-object keys\n",
" * we need this to avoid circular references\n",
" * http://stackoverflow.com/a/24161582/3208463\n",
" */\n",
"function simpleKeys (original) {\n",
" return Object.keys(original).reduce(function (obj, key) {\n",
" if (typeof original[key] !== 'object')\n",
" obj[key] = original[key]\n",
" return obj;\n",
" }, {});\n",
"}\n",
"\n",
"mpl.figure.prototype.mouse_event = function(event, name) {\n",
" var canvas_pos = mpl.findpos(event)\n",
"\n",
" if (name === 'button_press')\n",
" {\n",
" this.canvas.focus();\n",
" this.canvas_div.focus();\n",
" }\n",
"\n",
" var x = canvas_pos.x * mpl.ratio;\n",
" var y = canvas_pos.y * mpl.ratio;\n",
"\n",
" this.send_message(name, {x: x, y: y, button: event.button,\n",
" step: event.step,\n",
" guiEvent: simpleKeys(event)});\n",
"\n",
" /* This prevents the web browser from automatically changing to\n",
" * the text insertion cursor when the button is pressed. We want\n",
" * to control all of the cursor setting manually through the\n",
" * 'cursor' event from matplotlib */\n",
" event.preventDefault();\n",
" return false;\n",
"}\n",
"\n",
"mpl.figure.prototype._key_event_extra = function(event, name) {\n",
" // Handle any extra behaviour associated with a key event\n",
"}\n",
"\n",
"mpl.figure.prototype.key_event = function(event, name) {\n",
"\n",
" // Prevent repeat events\n",
" if (name == 'key_press')\n",
" {\n",
" if (event.which === this._key)\n",
" return;\n",
" else\n",
" this._key = event.which;\n",
" }\n",
" if (name == 'key_release')\n",
" this._key = null;\n",
"\n",
" var value = '';\n",
" if (event.ctrlKey && event.which != 17)\n",
" value += \"ctrl+\";\n",
" if (event.altKey && event.which != 18)\n",
" value += \"alt+\";\n",
" if (event.shiftKey && event.which != 16)\n",
" value += \"shift+\";\n",
"\n",
" value += 'k';\n",
" value += event.which.toString();\n",
"\n",
" this._key_event_extra(event, name);\n",
"\n",
" this.send_message(name, {key: value,\n",
" guiEvent: simpleKeys(event)});\n",
" return false;\n",
"}\n",
"\n",
"mpl.figure.prototype.toolbar_button_onclick = function(name) {\n",
" if (name == 'download') {\n",
" this.handle_save(this, null);\n",
" } else {\n",
" this.send_message(\"toolbar_button\", {name: name});\n",
" }\n",
"};\n",
"\n",
"mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n",
" this.message.textContent = tooltip;\n",
"};\n",
"mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n",
"\n",
"mpl.extensions = [\"eps\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
"\n",
"mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n",
" // Create a \"websocket\"-like object which calls the given IPython comm\n",
" // object with the appropriate methods. Currently this is a non binary\n",
" // socket, so there is still some room for performance tuning.\n",
" var ws = {};\n",
"\n",
" ws.close = function() {\n",
" comm.close()\n",
" };\n",
" ws.send = function(m) {\n",
" //console.log('sending', m);\n",
" comm.send(m);\n",
" };\n",
" // Register the callback with on_msg.\n",
" comm.on_msg(function(msg) {\n",
" //console.log('receiving', msg['content']['data'], msg);\n",
" // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
" ws.onmessage(msg['content']['data'])\n",
" });\n",
" return ws;\n",
"}\n",
"\n",
"mpl.mpl_figure_comm = function(comm, msg) {\n",
" // This is the function which gets called when the mpl process\n",
" // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
"\n",
" var id = msg.content.data.id;\n",
" // Get hold of the div created by the display call when the Comm\n",
" // socket was opened in Python.\n",
" var element = $(\"#\" + id);\n",
" var ws_proxy = comm_websocket_adapter(comm)\n",
"\n",
" function ondownload(figure, format) {\n",
" window.open(figure.imageObj.src);\n",
" }\n",
"\n",
" var fig = new mpl.figure(id, ws_proxy,\n",
" ondownload,\n",
" element.get(0));\n",
"\n",
" // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n",
" // web socket which is closed, not our websocket->open comm proxy.\n",
" ws_proxy.onopen();\n",
"\n",
" fig.parent_element = element.get(0);\n",
" fig.cell_info = mpl.find_output_cell(\"<div id='\" + id + \"'></div>\");\n",
" if (!fig.cell_info) {\n",
" console.error(\"Failed to find cell for figure\", id, fig);\n",
" return;\n",
" }\n",
"\n",
" var output_index = fig.cell_info[2]\n",
" var cell = fig.cell_info[0];\n",
"\n",
"};\n",
"\n",
"mpl.figure.prototype.handle_close = function(fig, msg) {\n",
" var width = fig.canvas.width/mpl.ratio\n",
" fig.root.unbind('remove')\n",
"\n",
" // Update the output cell to use the data from the current canvas.\n",
" fig.push_to_output();\n",
" var dataURL = fig.canvas.toDataURL();\n",
" // Re-enable the keyboard manager in IPython - without this line, in FF,\n",
" // the notebook keyboard shortcuts fail.\n",
" IPython.keyboard_manager.enable()\n",
" $(fig.parent_element).html('<img src=\"' + dataURL + '\" width=\"' + width + '\">');\n",
" fig.close_ws(fig, msg);\n",
"}\n",
"\n",
"mpl.figure.prototype.close_ws = function(fig, msg){\n",
" fig.send_message('closing', msg);\n",
" // fig.ws.close()\n",
"}\n",
"\n",
"mpl.figure.prototype.push_to_output = function(remove_interactive) {\n",
" // Turn the data on the canvas into data in the output cell.\n",
" var width = this.canvas.width/mpl.ratio\n",
" var dataURL = this.canvas.toDataURL();\n",
" this.cell_info[1]['text/html'] = '<img src=\"' + dataURL + '\" width=\"' + width + '\">';\n",
"}\n",
"\n",
"mpl.figure.prototype.updated_canvas_event = function() {\n",
" // Tell IPython that the notebook contents must change.\n",
" IPython.notebook.set_dirty(true);\n",
" this.send_message(\"ack\", {});\n",
" var fig = this;\n",
" // Wait a second, then push the new image to the DOM so\n",
" // that it is saved nicely (might be nice to debounce this).\n",
" setTimeout(function () { fig.push_to_output() }, 1000);\n",
"}\n",
"\n",
"mpl.figure.prototype._init_toolbar = function() {\n",
" var fig = this;\n",
"\n",
" var nav_element = $('<div/>')\n",
" nav_element.attr('style', 'width: 100%');\n",
" this.root.append(nav_element);\n",
"\n",
" // Define a callback function for later on.\n",
" function toolbar_event(event) {\n",
" return fig.toolbar_button_onclick(event['data']);\n",
" }\n",
" function toolbar_mouse_event(event) {\n",
" return fig.toolbar_button_onmouseover(event['data']);\n",
" }\n",
"\n",
" for(var toolbar_ind in mpl.toolbar_items){\n",
" var name = mpl.toolbar_items[toolbar_ind][0];\n",
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
" var image = mpl.toolbar_items[toolbar_ind][2];\n",
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
"\n",
" if (!name) { continue; };\n",
"\n",
" var button = $('<button class=\"btn btn-default\" href=\"#\" title=\"' + name + '\"><i class=\"fa ' + image + ' fa-lg\"></i></button>');\n",
" button.click(method_name, toolbar_event);\n",
" button.mouseover(tooltip, toolbar_mouse_event);\n",
" nav_element.append(button);\n",
" }\n",
"\n",
" // Add the status bar.\n",
" var status_bar = $('<span class=\"mpl-message\" style=\"text-align:right; float: right;\"/>');\n",
" nav_element.append(status_bar);\n",
" this.message = status_bar[0];\n",
"\n",
" // Add the close button to the window.\n",
" var buttongrp = $('<div class=\"btn-group inline pull-right\"></div>');\n",
" var button = $('<button class=\"btn btn-mini btn-primary\" href=\"#\" title=\"Stop Interaction\"><i class=\"fa fa-power-off icon-remove icon-large\"></i></button>');\n",
" button.click(function (evt) { fig.handle_close(fig, {}); } );\n",
" button.mouseover('Stop Interaction', toolbar_mouse_event);\n",
" buttongrp.append(button);\n",
" var titlebar = this.root.find($('.ui-dialog-titlebar'));\n",
" titlebar.prepend(buttongrp);\n",
"}\n",
"\n",
"mpl.figure.prototype._root_extra_style = function(el){\n",
" var fig = this\n",
" el.on(\"remove\", function(){\n",
"\tfig.close_ws(fig, {});\n",
" });\n",
"}\n",
"\n",
"mpl.figure.prototype._canvas_extra_style = function(el){\n",
" // this is important to make the div 'focusable\n",
" el.attr('tabindex', 0)\n",
" // reach out to IPython and tell the keyboard manager to turn it's self\n",
" // off when our div gets focus\n",
"\n",
" // location in version 3\n",
" if (IPython.notebook.keyboard_manager) {\n",
" IPython.notebook.keyboard_manager.register_events(el);\n",
" }\n",
" else {\n",
" // location in version 2\n",
" IPython.keyboard_manager.register_events(el);\n",
" }\n",
"\n",
"}\n",
"\n",
"mpl.figure.prototype._key_event_extra = function(event, name) {\n",
" var manager = IPython.notebook.keyboard_manager;\n",
" if (!manager)\n",
" manager = IPython.keyboard_manager;\n",
"\n",
" // Check for shift+enter\n",
" if (event.shiftKey && event.which == 13) {\n",
" this.canvas_div.blur();\n",
" event.shiftKey = false;\n",
" // Send a \"J\" for go to next cell\n",
" event.which = 74;\n",
" event.keyCode = 74;\n",
" manager.command_mode();\n",
" manager.handle_keydown(event);\n",
" }\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_save = function(fig, msg) {\n",
" fig.ondownload(fig, null);\n",
"}\n",
"\n",
"\n",
"mpl.find_output_cell = function(html_output) {\n",
" // Return the cell and output element which can be found *uniquely* in the notebook.\n",
" // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n",
" // IPython event is triggered only after the cells have been serialised, which for\n",
" // our purposes (turning an active figure into a static one), is too late.\n",
" var cells = IPython.notebook.get_cells();\n",
" var ncells = cells.length;\n",
" for (var i=0; i<ncells; i++) {\n",
" var cell = cells[i];\n",
" if (cell.cell_type === 'code'){\n",
" for (var j=0; j<cell.output_area.outputs.length; j++) {\n",
" var data = cell.output_area.outputs[j];\n",
" if (data.data) {\n",
" // IPython >= 3 moved mimebundle to data attribute of output\n",
" data = data.data;\n",
" }\n",
" if (data['text/html'] == html_output) {\n",
" return [cell, data, j];\n",
" }\n",
" }\n",
" }\n",
" }\n",
"}\n",
"\n",
"// Register the function which deals with the matplotlib target/channel.\n",
"// The kernel may be null if the page has been refreshed.\n",
"if (IPython.notebook.kernel != null) {\n",
" IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n",
"}\n"
],
"text/plain": [
"<IPython.core.display.Javascript object>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"<img src=\"data:image/png;base64,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\" width=\"720\">"
],
"text/plain": [
"<IPython.core.display.HTML object>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "ee1c929344d84520a1f9739532f6f12f",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"HBox(children=(IntProgress(value=0, max=3), HTML(value='')))"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "1fd034336d064c10840656fc46f077a9",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"HBox(children=(IntProgress(value=0, max=14047), HTML(value='')))"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "99cc6bb36f974341abe28b2d480aabf3",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"HBox(children=(IntProgress(value=0, max=7024), HTML(value='')))"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'loss': 0.07909837087169497, 'val_loss': 0.08144222121488978}\n"
]
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "ba18a7b165984084b58047ca4cfc6c82",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"HBox(children=(IntProgress(value=0, max=14047), HTML(value='')))"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "f204e8ad53ba45438547fdc7d8de013e",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"HBox(children=(IntProgress(value=0, max=7024), HTML(value='')))"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'loss': 0.07260369182006554, 'val_loss': 0.08076523827359182}\n"
]
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "6d81f0f8ab034a92aff069495e9fcd7b",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"HBox(children=(IntProgress(value=0, max=14047), HTML(value='')))"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "ea2203b9578c4023b7f76df27dde92b9",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"HBox(children=(IntProgress(value=0, max=7024), HTML(value='')))"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'loss': 0.0691204885223411, 'val_loss': 0.080848135731886}\n",
"0.08076523827359182\n"
]
}
],
"source": [
"%matplotlib nbagg\n",
"\n",
"num_split=2\n",
"np.random.seed(SEED+num_split)\n",
"torch.manual_seed(SEED+num_split)\n",
"torch.cuda.manual_seed(SEED+num_split)\n",
"#torch.backends.cudnn.deterministic = True\n",
"idx_train = train_df[train_df.PID.isin(set(split_sid[splits[num_split][0]]))].index.values\n",
"idx_validate = train_df[train_df.PID.isin(set(split_sid[splits[num_split][1]]))].index.values\n",
"idx_train.shape\n",
"idx_validate.shape\n",
"\n",
"klr=1\n",
"batch_size=32\n",
"num_workers=12\n",
"num_epochs=3\n",
"model_name,version = 'Densenet161_3' , 'classifier_splits'\n",
"#model1 = MyDenseNet(models.densenet161(pretrained=True),len(hemorrhage_types),num_channels=3)\n",
"model = MyDenseNet(models.densenet161(pretrained=True),\n",
" len(hemorrhage_types),\n",
" num_channels=3,\n",
" drop_out=0.2,\n",
" wso=((40,80),(80,200),(600,2800)),\n",
" strategy='none',\n",
" dont_do_grad=[],\n",
" extra_pool=4,\n",
" pool_type='max'\n",
" )\n",
"model.load_state_dict(torch.load(models_dir+models_format.format(model_name,'basic_splits',num_split),map_location=torch.device(device)))\n",
"_=model.to(device)\n",
"weights = torch.tensor([1.,1.,1.,1.,1.,2.],device=device)\n",
"loss_func=my_loss\n",
"targets_dataset=D.TensorDataset(torch.tensor(train_df[hemorrhage_types].values,dtype=torch.float))\n",
"transform=MyTransform(flip=True,zoom=0.05,rotate=15,out_size=512,shift=40)\n",
"imagedataset = ImageDataset(train_df,transform=transform.random,base_path=train_images_dir,\n",
" window_eq=False,equalize=False,rescale=True)\n",
"transform_val=MyTransform(out_size=512)\n",
"imagedataset_val = ImageDataset(train_df,transform=transform_val.random,base_path=train_images_dir,\n",
" window_eq=False,equalize=False,rescale=True)\n",
"combined_dataset=DatasetCat([imagedataset,targets_dataset])\n",
"combined_dataset_val=DatasetCat([imagedataset_val,targets_dataset])\n",
"#param_s=parameter_scheduler(model,num_epoch=0)\n",
"pre_proc = Mixup(0.4,device=device)\n",
"optimizer_grouped_parameters=get_optimizer_parameters(model,klr)\n",
"#sampling=simple_sampler(train_df[hemorrhage_types].values[idx_train],0.25)\n",
"#sampling=sampler(train_df[hemorrhage_types].values[idx_train],5,[0,0,0,0,0,2],train_df.SeriesI.values[idx_train])\n",
"sample_ratio= 1.0 #1.003*float(sampling().shape[0])/idx_train.shape[0]\n",
"train_dataset=D.Subset(combined_dataset,idx_train)\n",
"validate_dataset=D.Subset(combined_dataset_val,idx_validate)\n",
"num_train_optimization_steps = num_epochs*(sample_ratio*len(train_dataset)//batch_size+int(len(train_dataset)%batch_size>0))\n",
"fig,ax = plt.subplots(figsize=(10,7))\n",
"gr=loss_graph(fig,ax,num_epochs,int(num_train_optimization_steps/num_epochs)+1,limits=(0.05,0.2))\n",
"sched=WarmupExpCosineWithWarmupRestartsSchedule( t_total=num_train_optimization_steps, cycles=num_epochs,tau=1.5)\n",
"optimizer = BertAdam(optimizer_grouped_parameters,lr=klr*1e-3,schedule=sched)\n",
"model, optimizer = amp.initialize(model, optimizer, opt_level=\"O1\",verbosity=0)\n",
"history,best_model= model_train(model,\n",
" optimizer,\n",
" train_dataset,\n",
" batch_size,\n",
" num_epochs,\n",
" loss_func,\n",
" weights=weights,\n",
" do_apex=False,\n",
" model_apexed=True,\n",
" validate_dataset=validate_dataset,\n",
" param_schedualer=None,\n",
" weights_data=None,\n",
" metric=None,\n",
" return_model=True,\n",
" num_workers=num_workers,\n",
" sampler=None,\n",
" pre_process = None,\n",
" graph=gr,\n",
" call_progress=sendmeemail)\n",
"\n",
"torch.save(model.state_dict(), models_dir+models_format.format(model_name,version,num_split))\n",
"torch.save(best_model.state_dict(), models_dir+models_format.format(model_name,version+'_best',num_split))"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<All keys matched successfully>"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "b8cf249e3252435a9b9d69dfd788d336",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"HBox(children=(IntProgress(value=0, max=819), HTML(value='')))"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n"
]
}
],
"source": [
"model_name,version, num_split = 'Densenet161_3' , 'classifier_splits',0\n",
"model = MyDenseNet(models.densenet161(pretrained=True),\n",
" len(hemorrhage_types),\n",
" num_channels=3,\n",
" drop_out=0.2,\n",
" wso=((40,80),(80,200),(600,2800)),\n",
" strategy='none',\n",
" dont_do_grad=[],\n",
" extra_pool=4,\n",
" pool_type='max',\n",
" return_features=True\n",
" )\n",
"model.load_state_dict(torch.load(models_dir+models_format.format(model_name,version,num_split),map_location=torch.device(device)))\n",
"_=model.to(device)\n",
"transform=MyTransform(flip=True,zoom=0.05,rotate=15,out_size=512,shift=40)\n",
"transform_val=MyTransform(out_size=512)\n",
"indexes=np.arange(test_df.shape[0]).repeat(8)\n",
"imagedataset_test=D.Subset(ImageDataset(test_df,transform=transform.random,base_path=test_images_dir,\n",
" window_eq=False,equalize=False,rescale=True),indexes)\n",
"pred,features = model_run(model,imagedataset_test,do_apex=True,batch_size=96,num_workers=18)\n",
"pickle_file=open(outputs_dir+outputs_format.format(model_name,version,'features_test',num_split),'wb')\n",
"pickle.dump(features,pickle_file,protocol=4)\n",
"pickle_file.close()\n",
"pickle_file=open(outputs_dir+outputs_format.format(model_name,version,'predictions_test',num_split),'wb')\n",
"pickle.dump(pred,pickle_file,protocol=4)\n",
"pickle_file.close()"
]
},
{
"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>ID</th>\n",
" <th>Label</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>ID_000012eaf_any</td>\n",
" <td>0.002726</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>ID_000012eaf_epidural</td>\n",
" <td>0.000023</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>ID_000012eaf_intraparenchymal</td>\n",
" <td>0.000494</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>ID_000012eaf_intraventricular</td>\n",
" <td>0.000140</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>ID_000012eaf_subarachnoid</td>\n",
" <td>0.000619</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5</th>\n",
" <td>ID_000012eaf_subdural</td>\n",
" <td>0.001694</td>\n",
" </tr>\n",
" <tr>\n",
" <th>6</th>\n",
" <td>ID_0000ca2f6_any</td>\n",
" <td>0.004521</td>\n",
" </tr>\n",
" <tr>\n",
" <th>7</th>\n",
" <td>ID_0000ca2f6_epidural</td>\n",
" <td>0.000045</td>\n",
" </tr>\n",
" <tr>\n",
" <th>8</th>\n",
" <td>ID_0000ca2f6_intraparenchymal</td>\n",
" <td>0.000900</td>\n",
" </tr>\n",
" <tr>\n",
" <th>9</th>\n",
" <td>ID_0000ca2f6_intraventricular</td>\n",
" <td>0.000160</td>\n",
" </tr>\n",
" <tr>\n",
" <th>10</th>\n",
" <td>ID_0000ca2f6_subarachnoid</td>\n",
" <td>0.001351</td>\n",
" </tr>\n",
" <tr>\n",
" <th>11</th>\n",
" <td>ID_0000ca2f6_subdural</td>\n",
" <td>0.001957</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" ID Label\n",
"0 ID_000012eaf_any 0.002726\n",
"1 ID_000012eaf_epidural 0.000023\n",
"2 ID_000012eaf_intraparenchymal 0.000494\n",
"3 ID_000012eaf_intraventricular 0.000140\n",
"4 ID_000012eaf_subarachnoid 0.000619\n",
"5 ID_000012eaf_subdural 0.001694\n",
"6 ID_0000ca2f6_any 0.004521\n",
"7 ID_0000ca2f6_epidural 0.000045\n",
"8 ID_0000ca2f6_intraparenchymal 0.000900\n",
"9 ID_0000ca2f6_intraventricular 0.000160\n",
"10 ID_0000ca2f6_subarachnoid 0.001351\n",
"11 ID_0000ca2f6_subdural 0.001957"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"text/plain": [
"(471270, 2)"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"submission_df=get_submission(test_df,pred[(np.arange(pred.shape[0]).reshape(pred.shape[0]//8,8))].mean(1))\n",
"#submission_df=get_submission(test_df,pred)\n",
"submission_df.head(12)\n",
"submission_df.shape\n",
"sub_num=25\n",
"submission_df.to_csv('/media/hd/notebooks/data/RSNA/submissions/submission{}.csv'.format(sub_num),\n",
" index=False, columns=['ID','Label'])\n"
]
},
{
"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.6"
}
},
"nbformat": 4,
"nbformat_minor": 2
}