mpii/pose_ordering.ipynb

1669 lines
895 KiB
Plaintext
Raw Permalink Normal View History

2021-04-13 17:32:51 +02:00
{
"cells": [
{
"cell_type": "markdown",
"id": "e7f2abd1",
"metadata": {},
"source": [
"To install kernel run:\n",
"\n",
"```\n",
"poetry run ipython kernel install --user --name=mpii\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": 296,
"id": "8b90027a",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Using matplotlib backend: nbAgg\n"
]
}
],
"source": [
"# imports\n",
"import os\n",
"from pathlib import Path\n",
"from scipy.io import loadmat\n",
"import scipy\n",
"import tqdm\n",
"import pickle\n",
"import logging\n",
"import time\n",
"import gc\n",
"%matplotlib\n",
"%matplotlib notebook\n",
"import matplotlib\n",
"import matplotlib.pyplot as plt\n",
"import numpy as np\n",
"from PIL import Image\n",
"from threading import Lock\n"
]
},
{
"cell_type": "code",
"execution_count": 46,
"id": "f5818c76",
"metadata": {},
"outputs": [],
"source": [
"# logging\n",
"logging.basicConfig(level=logging.WARNING)\n",
"logger = logging.getLogger('pose_ordering')\n",
"logger.setLevel(logging.INFO)"
]
},
{
"cell_type": "code",
"execution_count": 33,
"id": "7f6fe12f",
"metadata": {},
"outputs": [],
"source": [
"# config\n",
"\n",
"mpii_idx_to_jnt = {0: 'rankl', 1: 'rknee', 2: 'rhip', 5: 'lankl', 4: 'lknee', 3: 'lhip',\n",
" 6: 'pelvis', 7: 'thorax', 8: 'upper_neck', 11: 'relb', 10: 'rwri', 9: 'head',\n",
" 12: 'rsho', 13: 'lsho', 14: 'lelb', 15: 'lwri'}\n",
"\n",
"angles = [\n",
" ['rwri', 'relb', 'rsho'],\n",
" ['relb', 'rsho','thorax'],\n",
" ['rsho','thorax', 'pelvis'],\n",
" ['thorax','pelvis', 'rhip'],\n",
" ['pelvis', 'rhip', 'rknee'],\n",
" [ 'rhip', 'rknee', 'rankl'],\n",
" ['rsho','thorax','upper_neck'],\n",
" ['lwri', 'lelb', 'lsho'],\n",
" ['lelb', 'lsho','thorax'],\n",
" ['lsho','thorax','pelvis'],\n",
" ['thorax','pelvis','lhip'],\n",
" ['pelvis','lhip', 'lknee'],\n",
" ['lhip', 'lknee', 'lankl'],\n",
" ['lsho','thorax','upper_neck'],\n",
" ['thorax','upper_neck', 'head'],\n",
"]\n",
"\n",
"bones = [\n",
" ['rankl', 'rknee', 'orange'],\n",
" ['rknee', 'rhip', 'orange'],\n",
" ['rhip','pelvis', 'orange'],\n",
" ['lankl', 'lknee', 'yellow'],\n",
" ['lknee', 'lhip', 'yellow'],\n",
" ['lhip','pelvis', 'yellow'],\n",
"\n",
" ['rwri', 'relb', 'red'],\n",
" ['relb','rsho', 'red'],\n",
" ['rsho','thorax', 'red'],\n",
" ['lwri', 'lelb', 'blue'],\n",
" ['lelb','lsho', 'blue'],\n",
" ['lsho','thorax', 'blue'],\n",
"\n",
" ['thorax','upper_neck', 'pink'],\n",
" ['upper_neck','head', 'pink'],\n",
" ['thorax','pelvis', 'green'],\n",
"]\n",
"\n",
"\n",
"filename = 'mpii_human_pose_v1_u12_2/mpii_human_pose_v1_u12_1.mat'\n",
"\n",
"\n",
"#matplotlib plot size\n",
"default_dpi = matplotlib.rcParamsDefault['figure.dpi']\n",
"matplotlib.rcParams['figure.dpi'] = default_dpi*2\n"
]
},
{
"cell_type": "code",
"execution_count": 18,
"id": "3d511d3a",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"DEBUG:pose_ordering:Loading pickled version\n"
]
}
],
"source": [
"%timeit\n",
"if os.path.exists(filename + '.p'):\n",
" with open(filename + '.p', 'rb') as fp:\n",
" gc.disable() # speeds up pickle.load by ~30%\n",
" logger.debug('Loading pickled version')\n",
" mat = pickle.load(fp)\n",
" gc.enable()\n",
"else:\n",
" logger.debug(f'Loading {filename}')\n",
" mat = loadmat(filename)\n",
" with open(filename + '.p', 'wb') as fp:\n",
" pickle.dump(mat, fp)"
]
},
{
"cell_type": "code",
"execution_count": 19,
"id": "4abd4ab9",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"24987"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"\n",
"mpii = mat['RELEASE'][0,0]\n",
"num_images = mpii['annolist'][0].shape[0]\n",
"\n",
"num_images"
]
},
{
"cell_type": "code",
"execution_count": 20,
"id": "7c985ce9",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 1200x800 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"plt.plot([1,2], [-1,4]) \n",
" \n",
"# function to show the plot \n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": 233,
"id": "9b5f975e",
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
" 0%| | 0/24987 [00:00<?, ?it/s]<ipython-input-233-6c8ee7259d48>:43: FutureWarning: elementwise comparison failed; returning scalar instead, but in the future will perform elementwise comparison\n",
" vis = point['is_visible'].flatten() if 'is_visible' in point else []\n",
"100%|██████████| 24987/24987 [00:19<00:00, 1282.47it/s]\n"
]
}
],
"source": [
"has_values = 0\n",
"visualise = False\n",
"\n",
"vectors = []\n",
"vector_points = []\n",
"\n",
"for idx in tqdm.tqdm(range(num_images)):\n",
"# for idx in range(num_images):\n",
" # # is_training = mpii['img_train'][0,idx] # whether in train or test set\n",
" # person_ids = mpii['single_person'][idx][0].flatten()\n",
"\n",
" # if not len(person_ids):\n",
" # # skip, because not enough persons\n",
" # continue\n",
" \n",
" annotations = mpii['annolist'][0,idx]\n",
" anno_file = str(annotations[0]['name'][0][0][0])\n",
" filename = '/home/ruben/Documents/Projecten/2020/Security Vision/tryouts/MPII Human Pose Dataset/images/'+anno_file\n",
" logger.debug(filename)\n",
" \n",
" if visualise:\n",
" image = Image.open(filename)\n",
"\n",
" if not len(annotations['annorect']):\n",
" continue\n",
"\n",
" for annotation in annotations['annorect'][0]:\n",
" # TODO : We might need to mirror the objects following a particular rule (see also Impett & Moretti)\n",
" try:\n",
" annotation_points = annotation['annopoints'][0,0]['point'][0]\n",
" except Exception as e:\n",
" # no points tagged for this one\n",
" continue\n",
"\n",
" # logger.debug(points.shape[0])\n",
"\n",
" points = {}\n",
"\n",
" for point in annotation_points:\n",
" x = float(point['x'].flatten()[0])\n",
" y = float(point['y'].flatten()[0])\n",
" id_ = point['id'][0][0]\n",
" vis = point['is_visible'].flatten() if 'is_visible' in point else []\n",
" joint = mpii_idx_to_jnt[id_]\n",
" vis = int(vis[0]) if len(vis) else 0\n",
" points[joint] = np.array([x,y, vis])\n",
"\n",
" \n",
" if not all([joint in points for joint in mpii_idx_to_jnt.values()]):\n",
" logger.debug(f\"Not enough points: {points=}\")\n",
" break\n",
"\n",
"# if 'rhip' not in points or 'lhip' not in points or 'thorax' not in points:\n",
"# logger.info(f\"Not enough points: {points=}\")\n",
"# continue\n",
" \n",
"\n",
" visible_joints = [joint for joint in mpii_idx_to_jnt.values() if joint in points]\n",
" \n",
" if visualise:\n",
" plt.imshow(image)\n",
" plt.plot(np.array([points[joint][0] for joint in visible_joints]), np.array([points[joint][1] for joint in visible_joints]), 'o')\n",
" \n",
" for bone in bones:\n",
" if not all([bone[0] in points, bone[1] in points]):\n",
" continue\n",
" \n",
" if visualise:\n",
" plt.plot([points[bone[0]][0], points[bone[1]][0]], [points[bone[0]][1], points[bone[1]][1]], color=bone[2])\n",
"\n",
" \n",
" annotation_vector = []\n",
"\n",
" for joints in angles:\n",
" if not all([p in points for p in joints]):\n",
" # check if all points to calculate joints are available \n",
" annotation_vector.append(None) # CHOICE store null\n",
" continue\n",
" \n",
" v1 = points[joints[0]] - points[joints[1]]\n",
" v2 = points[joints[2]] - points[joints[1]]\n",
"\n",
" angle = np.arctan2(v2[1], v2[0]) - np.arctan2(v1[1], v1[0])\n",
" annotation_vector.append(angle*angle) # CHOICE squared angle?\n",
" if visualise:\n",
" plt.text(int(points[joints[1]][0]), int(points[joints[1]][1]), f\"{angle:.4}\")\n",
" \n",
" vector_points.append(points)\n",
" vectors.append([annotation_vector, idx, len(vector_points)-1])\n",
" \n",
" \n",
" has_values += 1\n",
"# print(annotations)\n",
"# break\n",
" if visualise:\n",
" plt.show() # show image\n",
" if has_values > 2:\n",
" break\n"
]
},
{
"cell_type": "code",
"execution_count": 144,
"id": "41c21986",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"17969 [[10.301455313174841, 0.8738769777401664, 7.932846045996372, 33.90556982877595, 4.788006833143501, 11.579460281021154, 6.330558392334423, 0.590823723139596, 5.670376354016367, 0.10566517419166079, 7.019067218895686, 0.9921823387865951, 7.12304248234401, 0.39129098417224434, 2.9091346049064142e-11], 4] [[2.199207456110774, 1.3408538112736343, 0.9907647738998692, 3.8666010567179896, 0.42119523559718064, 2.7174019285215865, 2.563494948040972, 1.3928467439375065, 2.901393929071837, 4.646466934360204, 27.37712157435963, 2.2728260851251068, 7.166142323804702, 22.581788879995116, 9.869588546386826], 24984]\n"
]
}
],
"source": [
"\n",
"print(len(vectors), vectors[1], vectors[-1])"
]
},
{
"cell_type": "code",
"execution_count": 118,
"id": "6a91c2d3",
"metadata": {},
"outputs": [],
"source": [
"from sklearn.preprocessing import StandardScaler\n"
]
},
{
"cell_type": "code",
"execution_count": 145,
"id": "b9478c7a",
"metadata": {},
"outputs": [],
"source": [
"values = [v[0] for v in vectors]"
]
},
{
"cell_type": "code",
"execution_count": 265,
"id": "6e8d9b47",
"metadata": {},
"outputs": [],
"source": [
"x = StandardScaler().fit_transform(values) # normalizing the features\n"
]
},
{
"cell_type": "code",
"execution_count": 266,
"id": "821f483d",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(2.7179541485275698e-15, 1.0)"
]
},
"execution_count": 266,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"x.mean(), np.std(x)"
]
},
{
"cell_type": "code",
"execution_count": 267,
"id": "e6b5e4ef",
"metadata": {},
"outputs": [],
"source": [
"from sklearn.decomposition import PCA"
]
},
{
"cell_type": "code",
"execution_count": 268,
"id": "2ee95e88",
"metadata": {},
"outputs": [],
"source": [
"# If 0 < n_components < 1 and svd_solver == 'full', select the number of components such that the amount of variance that needs to be explained is greater than the percentage specified by n_components.: https://medium.com/@ansjin/dimensionality-reduction-using-pca-on-multivariate-timeseries-data-b5cc07238dc4\n",
"pca = PCA(n_components=None)\n",
"principalComponents = pca.fit_transform(x)"
]
},
{
"cell_type": "code",
"execution_count": 269,
"id": "0d54404f",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([0.1947121 , 0.14030244, 0.13287677, 0.09570534, 0.07844851,\n",
" 0.06633996, 0.06156485, 0.0560413 , 0.04303254, 0.03463799,\n",
" 0.02883156, 0.02305097, 0.01668491, 0.015404 , 0.01236676])"
]
},
"execution_count": 269,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pca.explained_variance_ratio_"
]
},
{
"cell_type": "code",
"execution_count": 270,
"id": "515999d3",
"metadata": {},
"outputs": [],
"source": [
"# pca.components_\n",
"# pca.get_precision()\n",
"\n",
"plt.plot(np.cumsum(pca.explained_variance_ratio_))\n",
"plt.xlabel('number of components')\n",
"plt.ylabel('cumulative explained variance');"
]
},
{
"cell_type": "code",
"execution_count": 271,
"id": "8519803d",
"metadata": {},
"outputs": [],
"source": [
"def get_catname(act) -> str:\n",
" return str(act['cat_name'][0][0]) if len(act['cat_name'][0]) else 'unknown'"
]
},
{
"cell_type": "code",
"execution_count": 294,
"id": "17631429",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[-2.35999232, 0.69057281],\n",
" [-0.61853026, 1.07182264],\n",
" [-1.18063219, -0.16670125],\n",
" ...,\n",
" [ 1.95397646, -2.77908482],\n",
" [ 1.47253967, -0.71394096],\n",
" [ 1.82195482, -2.03658075]])"
]
},
"execution_count": 294,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# cats = [mpii['act'][v[1]]['cat_name'][0] for v in vectors]\n",
"cats= np.unique([get_catname(act) for act in mpii['act']]).tolist()\n",
"cats"
]
},
{
"cell_type": "code",
"execution_count": 326,
"id": "b0a25c9c",
"metadata": {
"scrolled": true
},
"outputs": [
{
"data": {
"application/javascript": [
"/* Put everything inside the global mpl namespace */\n",
"/* global mpl */\n",
"window.mpl = {};\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(\n",
" '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",
"\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 = document.createElement('div');\n",
" this.root.setAttribute('style', 'display: inline-block');\n",
" this._root_extra_style(this.root);\n",
"\n",
" parent_element.appendChild(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 (fig.ratio !== 1) {\n",
" fig.send_message('set_dpi_ratio', { dpi_ratio: fig.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 = document.createElement('div');\n",
" titlebar.classList =\n",
" 'ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix';\n",
" var titletext = document.createElement('div');\n",
" titletext.classList = 'ui-dialog-title';\n",
" titletext.setAttribute(\n",
" 'style',\n",
" 'width: 100%; text-align: center; padding: 3px;'\n",
" );\n",
" titlebar.appendChild(titletext);\n",
" this.root.appendChild(titlebar);\n",
" this.header = titletext;\n",
"};\n",
"\n",
"mpl.figure.prototype._canvas_extra_style = function (_canvas_div) {};\n",
"\n",
"mpl.figure.prototype._root_extra_style = function (_canvas_div) {};\n",
"\n",
"mpl.figure.prototype._init_canvas = function () {\n",
" var fig = this;\n",
"\n",
" var canvas_div = (this.canvas_div = document.createElement('div'));\n",
" canvas_div.setAttribute(\n",
" 'style',\n",
" 'border: 1px solid #ddd;' +\n",
" 'box-sizing: content-box;' +\n",
" 'clear: both;' +\n",
" 'min-height: 1px;' +\n",
" 'min-width: 1px;' +\n",
" 'outline: 0;' +\n",
" 'overflow: hidden;' +\n",
" 'position: relative;' +\n",
" 'resize: both;'\n",
" );\n",
"\n",
" function on_keyboard_event_closure(name) {\n",
" return function (event) {\n",
" return fig.key_event(event, name);\n",
" };\n",
" }\n",
"\n",
" canvas_div.addEventListener(\n",
" 'keydown',\n",
" on_keyboard_event_closure('key_press')\n",
" );\n",
" canvas_div.addEventListener(\n",
" 'keyup',\n",
" on_keyboard_event_closure('key_release')\n",
" );\n",
"\n",
" this._canvas_extra_style(canvas_div);\n",
" this.root.appendChild(canvas_div);\n",
"\n",
" var canvas = (this.canvas = document.createElement('canvas'));\n",
" canvas.classList.add('mpl-canvas');\n",
" canvas.setAttribute('style', 'box-sizing: content-box;');\n",
"\n",
" this.context = canvas.getContext('2d');\n",
"\n",
" var backingStore =\n",
" this.context.backingStorePixelRatio ||\n",
" this.context.webkitBackingStorePixelRatio ||\n",
" this.context.mozBackingStorePixelRatio ||\n",
" this.context.msBackingStorePixelRatio ||\n",
" this.context.oBackingStorePixelRatio ||\n",
" this.context.backingStorePixelRatio ||\n",
" 1;\n",
"\n",
" this.ratio = (window.devicePixelRatio || 1) / backingStore;\n",
"\n",
" var rubberband_canvas = (this.rubberband_canvas = document.createElement(\n",
" 'canvas'\n",
" ));\n",
" rubberband_canvas.setAttribute(\n",
" 'style',\n",
" 'box-sizing: content-box; position: absolute; left: 0; top: 0; z-index: 1;'\n",
" );\n",
"\n",
" // Apply a ponyfill if ResizeObserver is not implemented by browser.\n",
" if (this.ResizeObserver === undefined) {\n",
" if (window.ResizeObserver !== undefined) {\n",
" this.ResizeObserver = window.ResizeObserver;\n",
" } else {\n",
" var obs = _JSXTOOLS_RESIZE_OBSERVER({});\n",
" this.ResizeObserver = obs.ResizeObserver;\n",
" }\n",
" }\n",
"\n",
" this.resizeObserverInstance = new this.ResizeObserver(function (entries) {\n",
" var nentries = entries.length;\n",
" for (var i = 0; i < nentries; i++) {\n",
" var entry = entries[i];\n",
" var width, height;\n",
" if (entry.contentBoxSize) {\n",
" if (entry.contentBoxSize instanceof Array) {\n",
" // Chrome 84 implements new version of spec.\n",
" width = entry.contentBoxSize[0].inlineSize;\n",
" height = entry.contentBoxSize[0].blockSize;\n",
" } else {\n",
" // Firefox implements old version of spec.\n",
" width = entry.contentBoxSize.inlineSize;\n",
" height = entry.contentBoxSize.blockSize;\n",
" }\n",
" } else {\n",
" // Chrome <84 implements even older version of spec.\n",
" width = entry.contentRect.width;\n",
" height = entry.contentRect.height;\n",
" }\n",
"\n",
" // Keep the size of the canvas and rubber band canvas in sync with\n",
" // the canvas container.\n",
" if (entry.devicePixelContentBoxSize) {\n",
" // Chrome 84 implements new version of spec.\n",
" canvas.setAttribute(\n",
" 'width',\n",
" entry.devicePixelContentBoxSize[0].inlineSize\n",
" );\n",
" canvas.setAttribute(\n",
" 'height',\n",
" entry.devicePixelContentBoxSize[0].blockSize\n",
" );\n",
" } else {\n",
" canvas.setAttribute('width', width * fig.ratio);\n",
" canvas.setAttribute('height', height * fig.ratio);\n",
" }\n",
" canvas.setAttribute(\n",
" 'style',\n",
" 'width: ' + width + 'px; height: ' + height + 'px;'\n",
" );\n",
"\n",
" rubberband_canvas.setAttribute('width', width);\n",
" rubberband_canvas.setAttribute('height', height);\n",
"\n",
" // And update the size in Python. We ignore the initial 0/0 size\n",
" // that occurs as the element is placed into the DOM, which should\n",
" // otherwise not happen due to the minimum size styling.\n",
" if (fig.ws.readyState == 1 && width != 0 && height != 0) {\n",
" fig.request_resize(width, height);\n",
" }\n",
" }\n",
" });\n",
" this.resizeObserverInstance.observe(canvas_div);\n",
"\n",
" function on_mouse_event_closure(name) {\n",
" return function (event) {\n",
" return fig.mouse_event(event, name);\n",
" };\n",
" }\n",
"\n",
" rubberband_canvas.addEventListener(\n",
" 'mousedown',\n",
" on_mouse_event_closure('button_press')\n",
" );\n",
" rubberband_canvas.addEventListener(\n",
" 'mouseup',\n",
" on_mouse_event_closure('button_release')\n",
" );\n",
" rubberband_canvas.addEventListener(\n",
" 'dblclick',\n",
" on_mouse_event_closure('dblclick')\n",
" );\n",
" // Throttle sequential mouse events to 1 every 20ms.\n",
" rubberband_canvas.addEventListener(\n",
" 'mousemove',\n",
" on_mouse_event_closure('motion_notify')\n",
" );\n",
"\n",
" rubberband_canvas.addEventListener(\n",
" 'mouseenter',\n",
" on_mouse_event_closure('figure_enter')\n",
" );\n",
" rubberband_canvas.addEventListener(\n",
" 'mouseleave',\n",
" on_mouse_event_closure('figure_leave')\n",
" );\n",
"\n",
" canvas_div.addEventListener('wheel', function (event) {\n",
" if (event.deltaY < 0) {\n",
" event.step = 1;\n",
" } else {\n",
" event.step = -1;\n",
" }\n",
" on_mouse_event_closure('scroll')(event);\n",
" });\n",
"\n",
" canvas_div.appendChild(canvas);\n",
" canvas_div.appendChild(rubberband_canvas);\n",
"\n",
" this.rubberband_context = rubberband_canvas.getContext('2d');\n",
" this.rubberband_context.strokeStyle = '#000000';\n",
"\n",
" this._resize_canvas = function (width, height, forward) {\n",
" if (forward) {\n",
" canvas_div.style.width = width + 'px';\n",
" canvas_div.style.height = height + 'px';\n",
" }\n",
" };\n",
"\n",
" // Disable right mouse context menu.\n",
" this.rubberband_canvas.addEventListener('contextmenu', function (_e) {\n",
" event.preventDefault();\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 toolbar = document.createElement('div');\n",
" toolbar.classList = 'mpl-toolbar';\n",
" this.root.appendChild(toolbar);\n",
"\n",
" function on_click_closure(name) {\n",
" return function (_event) {\n",
" return fig.toolbar_button_onclick(name);\n",
" };\n",
" }\n",
"\n",
" function on_mouseover_closure(tooltip) {\n",
" return function (event) {\n",
" if (!event.currentTarget.disabled) {\n",
" return fig.toolbar_button_onmouseover(tooltip);\n",
" }\n",
" };\n",
" }\n",
"\n",
" fig.buttons = {};\n",
" var buttonGroup = document.createElement('div');\n",
" buttonGroup.classList = 'mpl-button-group';\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",
" /* Instead of a spacer, we start a new button group. */\n",
" if (buttonGroup.hasChildNodes()) {\n",
" toolbar.appendChild(buttonGroup);\n",
" }\n",
" buttonGroup = document.createElement('div');\n",
" buttonGroup.classList = 'mpl-button-group';\n",
" continue;\n",
" }\n",
"\n",
" var button = (fig.buttons[name] = document.createElement('button'));\n",
" button.classList = 'mpl-widget';\n",
" button.setAttribute('role', 'button');\n",
" button.setAttribute('aria-disabled', 'false');\n",
" button.addEventListener('click', on_click_closure(method_name));\n",
" button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n",
"\n",
" var icon_img = document.createElement('img');\n",
" icon_img.src = '_images/' + image + '.png';\n",
" icon_img.srcset = '_images/' + image + '_large.png 2x';\n",
" icon_img.alt = tooltip;\n",
" button.appendChild(icon_img);\n",
"\n",
" buttonGroup.appendChild(button);\n",
" }\n",
"\n",
" if (buttonGroup.hasChildNodes()) {\n",
" toolbar.appendChild(buttonGroup);\n",
" }\n",
"\n",
" var fmt_picker = document.createElement('select');\n",
" fmt_picker.classList = 'mpl-widget';\n",
" toolbar.appendChild(fmt_picker);\n",
" this.format_dropdown = fmt_picker;\n",
"\n",
" for (var ind in mpl.extensions) {\n",
" var fmt = mpl.extensions[ind];\n",
" var option = document.createElement('option');\n",
" option.selected = fmt === mpl.default_extension;\n",
" option.innerHTML = fmt;\n",
" fmt_picker.appendChild(option);\n",
" }\n",
"\n",
" var status_bar = document.createElement('span');\n",
" status_bar.classList = 'mpl-message';\n",
" toolbar.appendChild(status_bar);\n",
" this.message = status_bar;\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",
"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",
"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], msg['forward']);\n",
" fig.send_message('refresh', {});\n",
" }\n",
"};\n",
"\n",
"mpl.figure.prototype.handle_rubberband = function (fig, msg) {\n",
" var x0 = msg['x0'] / fig.ratio;\n",
" var y0 = (fig.canvas.height - msg['y0']) / fig.ratio;\n",
" var x1 = msg['x1'] / fig.ratio;\n",
" var y1 = (fig.canvas.height - msg['y1']) / fig.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,\n",
" 0,\n",
" fig.canvas.width / fig.ratio,\n",
" fig.canvas.height / fig.ratio\n",
" );\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",
" 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.handle_history_buttons = function (fig, msg) {\n",
" for (var key in msg) {\n",
" if (!(key in fig.buttons)) {\n",
" continue;\n",
" }\n",
" fig.buttons[key].disabled = !msg[key];\n",
" fig.buttons[key].setAttribute('aria-disabled', !msg[key]);\n",
" }\n",
"};\n",
"\n",
"mpl.figure.prototype.handle_navigate_mode = function (fig, msg) {\n",
" if (msg['mode'] === 'PAN') {\n",
" fig.buttons['Pan'].classList.add('active');\n",
" fig.buttons['Zoom'].classList.remove('active');\n",
" } else if (msg['mode'] === 'ZOOM') {\n",
" fig.buttons['Pan'].classList.remove('active');\n",
" fig.buttons['Zoom'].classList.add('active');\n",
" } else {\n",
" fig.buttons['Pan'].classList.remove('active');\n",
" fig.buttons['Zoom'].classList.remove('active');\n",
" }\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",
" var img = evt.data;\n",
" if (img.type !== 'image/png') {\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",
" img.type = 'image/png';\n",
" }\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",
"\n",
" fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
" img\n",
" );\n",
" fig.updated_canvas_event();\n",
" fig.waiting = false;\n",
" return;\n",
" } else if (\n",
" typeof evt.data === 'string' &&\n",
" evt.data.slice(0, 21) === 'data:image/png;base64'\n",
" ) {\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(\n",
" \"No handler for the '\" + msg_type + \"' message type: \",\n",
" msg\n",
" );\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(\n",
" \"Exception inside the 'handler_\" + msg_type + \"' callback:\",\n",
" e,\n",
" e.stack,\n",
" msg\n",
" );\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",
" }\n",
" if (e.target) {\n",
" targ = e.target;\n",
" } else if (e.srcElement) {\n",
" targ = e.srcElement;\n",
" }\n",
" if (targ.nodeType === 3) {\n",
" // defeat Safari bug\n",
" targ = targ.parentNode;\n",
" }\n",
"\n",
" // pageX,Y are the mouse positions relative to the document\n",
" var boundingRect = targ.getBoundingClientRect();\n",
" var x = e.pageX - (boundingRect.left + document.body.scrollLeft);\n",
" var y = e.pageY - (boundingRect.top + document.body.scrollTop);\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",
" }\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",
" this.canvas.focus();\n",
" this.canvas_div.focus();\n",
" }\n",
"\n",
" var x = canvas_pos.x * this.ratio;\n",
" var y = canvas_pos.y * this.ratio;\n",
"\n",
" this.send_message(name, {\n",
" x: x,\n",
" y: y,\n",
" button: event.button,\n",
" step: event.step,\n",
" guiEvent: simpleKeys(event),\n",
" });\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",
" // Prevent repeat events\n",
" if (name === 'key_press') {\n",
" if (event.key === this._key) {\n",
" return;\n",
" } else {\n",
" this._key = event.key;\n",
" }\n",
" }\n",
" if (name === 'key_release') {\n",
" this._key = null;\n",
" }\n",
"\n",
" var value = '';\n",
" if (event.ctrlKey && event.key !== 'Control') {\n",
" value += 'ctrl+';\n",
" }\n",
" else if (event.altKey && event.key !== 'Alt') {\n",
" value += 'alt+';\n",
" }\n",
" else if (event.shiftKey && event.key !== 'Shift') {\n",
" value += 'shift+';\n",
" }\n",
"\n",
" value += 'k' + event.key;\n",
"\n",
" this._key_event_extra(event, name);\n",
"\n",
" this.send_message(name, { key: value, 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",
"\n",
"///////////////// REMAINING CONTENT GENERATED BY embed_js.py /////////////////\n",
"// prettier-ignore\n",
"var _JSXTOOLS_RESIZE_OBSERVER=function(A){var t,i=new WeakMap,n=new WeakMap,a=new WeakMap,r=new WeakMap,o=new Set;function s(e){if(!(this instanceof s))throw new TypeError(\"Constructor requires 'new' operator\");i.set(this,e)}function h(){throw new TypeError(\"Function is not a constructor\")}function c(e,t,i,n){e=0 in arguments?Number(arguments[0]):0,t=1 in arguments?Number(arguments[1]):0,i=2 in arguments?Number(arguments[2]):0,n=3 in arguments?Number(arguments[3]):0,this.right=(this.x=this.left=e)+(this.width=i),this.bottom=(this.y=this.top=t)+(this.height=n),Object.freeze(this)}function d(){t=requestAnimationFrame(d);var s=new WeakMap,p=new Set;o.forEach((function(t){r.get(t).forEach((function(i){var r=t instanceof window.SVGElement,o=a.get(t),d=r?0:parseFloat(o.paddingTop),f=r?0:parseFloat(o.paddingRight),l=r?0:parseFloat(o.paddingBottom),u=r?0:parseFloat(o.paddingLeft),g=r?0:parseFloat(o.borderTopWidth),m=r?0:parseFloat(o.borderRightWidth),w=r?0:parseFloat(o.borderBottomWidth),b=u+f,F=d+l,v=(r?0:parseFloat(o.borderLeftWidth))+m,W=g+w,y=r?0:t.offsetHeight-W-t.clientHeight,E=r?0:t.offsetWidth-v-t.clientWidth,R=b+v,z=F+W,M=r?t.width:parseFloat(o.width)-R-E,O=r?t.height:parseFloat(o.height)-z-y;if(n.has(t)){var k=n.get(t);if(k[0]===M&&k[1]===O)return}n.set(t,[M,O]);var S=Object.create(h.prototype);S.target=t,S.contentRect=new c(u,d,M,O),s.has(i)||(s.set(i,[]),p.add(i)),s.get(i).push(S)}))})),p.forEach((function(e){i.get(e).call(e,s.get(e),e)}))}return s.prototype.observe=function(i){if(i instanceof window.Element){r.has(i)||(r.set(i,new Set),o.add(i),a.set(i,window.getComputedStyle(i)));var n=r.get(i);n.has(this)||n.add(this),cancelAnimationFrame(t),t=requestAnimationFrame(d)}},s.prototype.unobserve=function(i){if(i instanceof window.Element&&r.has(i)){var n=r.get(i);n.has(this)&&(n.delete(this),n.size||(r.delete(i),o.delete(i))),n.size||r.delete(i),o.size||cancelAnimationFrame(t)}},A.DOMRectReadOnly=c,A.ResizeObserver=s,A.ResizeObserverEntry=h,A}; // eslint-disable-line\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\", \"Left button pans, Right button zooms\\nx/y fixes axis, CTRL fixes aspect\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\\nx/y fixes axis, CTRL fixes aspect\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n",
"\n",
"mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
"\n",
"mpl.default_extension = \"png\";/* global mpl */\n",
"\n",
"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.binaryType = comm.kernel.ws.binaryType;\n",
" ws.readyState = comm.kernel.ws.readyState;\n",
" function updateReadyState(_event) {\n",
" if (comm.kernel.ws) {\n",
" ws.readyState = comm.kernel.ws.readyState;\n",
" } else {\n",
" ws.readyState = 3; // Closed state.\n",
" }\n",
" }\n",
" comm.kernel.ws.addEventListener('open', updateReadyState);\n",
" comm.kernel.ws.addEventListener('close', updateReadyState);\n",
" comm.kernel.ws.addEventListener('error', updateReadyState);\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",
" var data = msg['content']['data'];\n",
" if (data['blob'] !== undefined) {\n",
" data = {\n",
" data: new Blob(msg['buffers'], { type: data['blob'] }),\n",
" };\n",
" }\n",
" // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
" ws.onmessage(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 = document.getElementById(id);\n",
" var ws_proxy = comm_websocket_adapter(comm);\n",
"\n",
" function ondownload(figure, _format) {\n",
" window.open(figure.canvas.toDataURL());\n",
" }\n",
"\n",
" var fig = new mpl.figure(id, ws_proxy, ondownload, element);\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;\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",
" fig.cell_info[0].output_area.element.on(\n",
" 'cleared',\n",
" { fig: fig },\n",
" fig._remove_fig_handler\n",
" );\n",
"};\n",
"\n",
"mpl.figure.prototype.handle_close = function (fig, msg) {\n",
" var width = fig.canvas.width / fig.ratio;\n",
" fig.cell_info[0].output_area.element.off(\n",
" 'cleared',\n",
" fig._remove_fig_handler\n",
" );\n",
" fig.resizeObserverInstance.unobserve(fig.canvas_div);\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.innerHTML =\n",
" '<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 / this.ratio;\n",
" var dataURL = this.canvas.toDataURL();\n",
" this.cell_info[1]['text/html'] =\n",
" '<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 () {\n",
" fig.push_to_output();\n",
" }, 1000);\n",
"};\n",
"\n",
"mpl.figure.prototype._init_toolbar = function () {\n",
" var fig = this;\n",
"\n",
" var toolbar = document.createElement('div');\n",
" toolbar.classList = 'btn-toolbar';\n",
" this.root.appendChild(toolbar);\n",
"\n",
" function on_click_closure(name) {\n",
" return function (_event) {\n",
" return fig.toolbar_button_onclick(name);\n",
" };\n",
" }\n",
"\n",
" function on_mouseover_closure(tooltip) {\n",
" return function (event) {\n",
" if (!event.currentTarget.disabled) {\n",
" return fig.toolbar_button_onmouseover(tooltip);\n",
" }\n",
" };\n",
" }\n",
"\n",
" fig.buttons = {};\n",
" var buttonGroup = document.createElement('div');\n",
" buttonGroup.classList = 'btn-group';\n",
" var button;\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",
" /* Instead of a spacer, we start a new button group. */\n",
" if (buttonGroup.hasChildNodes()) {\n",
" toolbar.appendChild(buttonGroup);\n",
" }\n",
" buttonGroup = document.createElement('div');\n",
" buttonGroup.classList = 'btn-group';\n",
" continue;\n",
" }\n",
"\n",
" button = fig.buttons[name] = document.createElement('button');\n",
" button.classList = 'btn btn-default';\n",
" button.href = '#';\n",
" button.title = name;\n",
" button.innerHTML = '<i class=\"fa ' + image + ' fa-lg\"></i>';\n",
" button.addEventListener('click', on_click_closure(method_name));\n",
" button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n",
" buttonGroup.appendChild(button);\n",
" }\n",
"\n",
" if (buttonGroup.hasChildNodes()) {\n",
" toolbar.appendChild(buttonGroup);\n",
" }\n",
"\n",
" // Add the status bar.\n",
" var status_bar = document.createElement('span');\n",
" status_bar.classList = 'mpl-message pull-right';\n",
" toolbar.appendChild(status_bar);\n",
" this.message = status_bar;\n",
"\n",
" // Add the close button to the window.\n",
" var buttongrp = document.createElement('div');\n",
" buttongrp.classList = 'btn-group inline pull-right';\n",
" button = document.createElement('button');\n",
" button.classList = 'btn btn-mini btn-primary';\n",
" button.href = '#';\n",
" button.title = 'Stop Interaction';\n",
" button.innerHTML = '<i class=\"fa fa-power-off icon-remove icon-large\"></i>';\n",
" button.addEventListener('click', function (_evt) {\n",
" fig.handle_close(fig, {});\n",
" });\n",
" button.addEventListener(\n",
" 'mouseover',\n",
" on_mouseover_closure('Stop Interaction')\n",
" );\n",
" buttongrp.appendChild(button);\n",
" var titlebar = this.root.querySelector('.ui-dialog-titlebar');\n",
" titlebar.insertBefore(buttongrp, titlebar.firstChild);\n",
"};\n",
"\n",
"mpl.figure.prototype._remove_fig_handler = function (event) {\n",
" var fig = event.data.fig;\n",
" if (event.target !== this) {\n",
" // Ignore bubbled events from children.\n",
" return;\n",
" }\n",
" fig.close_ws(fig, {});\n",
"};\n",
"\n",
"mpl.figure.prototype._root_extra_style = function (el) {\n",
" el.style.boxSizing = 'content-box'; // override notebook setting of border-box.\n",
"};\n",
"\n",
"mpl.figure.prototype._canvas_extra_style = function (el) {\n",
" // this is important to make the div 'focusable\n",
" el.setAttribute('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",
" } else {\n",
" // location in version 2\n",
" IPython.keyboard_manager.register_events(el);\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",
"\n",
" // Check for shift+enter\n",
" if (event.shiftKey && event.which === 13) {\n",
" this.canvas_div.blur();\n",
" // select the cell after this one\n",
" var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n",
" IPython.notebook.select(index + 1);\n",
" }\n",
"};\n",
"\n",
"mpl.figure.prototype.handle_save = function (fig, _msg) {\n",
" fig.ondownload(fig, null);\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(\n",
" 'matplotlib',\n",
" mpl.mpl_figure_comm\n",
" );\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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
],
"text/plain": [
"<IPython.core.display.HTML object>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"<matplotlib.collections.PathCollection at 0x7f44fc8f7dc0>"
]
},
"execution_count": 326,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# t = [mpii['act'][v[1]]['act_id'][0][0] for v in vectors]\n",
"t = [cats.index(get_catname(mpii['act'][v[1]])) for v in vectors]\n",
"\n",
"fig = plt.figure()\n",
"ax = fig.add_subplot(1,3,(1,2))\n",
"ax_figures = fig.add_subplot(1,3,3)\n",
"\n",
"kdtree= scipy.spatial.KDTree(principalComponents[:,[0,1]]) # CHOICE only consider first two dimensions...\n",
"\n",
"\n",
"def show_closest(event):\n",
" closest = kdtree.query([event.xdata, event.ydata], workers=-1)\n",
" ax_figures.clear()\n",
" \n",
" distance, vector_idx = closest\n",
" annotation_idx = vectors[vector_idx][1]\n",
" points_idx = vectors[vector_idx][2]\n",
" anno_points = np.array(list(vector_points[points_idx].values()))\n",
" ax_figures.plot(anno_points[:,0], anno_points[:,1]*-1, 'o')\n",
" \n",
" for bone in bones:\n",
" if not all([bone[0] in vector_points[points_idx], bone[1] in vector_points[points_idx]]):\n",
" continue\n",
" ax_figures.plot([vector_points[points_idx][bone[0]][0], vector_points[points_idx][bone[1]][0]], [-vector_points[points_idx][bone[0]][1], -vector_points[points_idx][bone[1]][1]], color=bone[2])\n",
"\n",
"# ax_figures.plot(np.random.rand(10))\n",
"\n",
"\n",
"def onclick(event):\n",
" show_closest(event)\n",
"\n",
"processing = Lock()\n",
"def onmove(event):\n",
" if not event.xdata or not event.ydata:\n",
" return\n",
" \n",
" if processing.acquire(blocking=False):\n",
" try:\n",
" show_closest(event)\n",
" finally:\n",
" processing.release()\n",
" \n",
"\n",
"cid = fig.canvas.mpl_connect('motion_notify_event', onmove)\n",
"cid = fig.canvas.mpl_connect('button_press_event', onclick)\n",
"\n",
"ax.scatter(principalComponents[:,0], principalComponents[:,1], c=t, cmap=\"viridis\",alpha=.3, marker='x', linewidth=.5)\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 308,
"id": "618794d1",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(17486, 17486)"
]
},
"execution_count": 308,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"closest[1], closest_old[1]"
]
},
{
"cell_type": "code",
"execution_count": 321,
"id": "660af381",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[[18.323586368221292,\n",
" 20.398791852918905,\n",
" 4.987799082127334,\n",
" 0.40959807507019436,\n",
" 12.429795844069234,\n",
" 16.96079790482587,\n",
" 5.768238809731072,\n",
" 3.234665667673784,\n",
" 2.764261279400277,\n",
" 28.889880637691366,\n",
" 6.257973328552808,\n",
" 0.954098950748553,\n",
" 11.425504813879593,\n",
" 30.728268671099034,\n",
" 7.83325651958665e-12],\n",
" 579,\n",
" 379]"
]
},
"execution_count": 321,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import random"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "33a24435",
"metadata": {
"scrolled": true
},
"outputs": [],
"source": [
"nr = random.randint(0, len(vectors)-1)\n",
"\n",
"imgidx = vectors[nr][1]\n",
"principalComponents[nr]\n",
"# vectors[6]\n",
"annotations = mpii['annolist'][0,imgidx]\n",
"anno_file = str(annotations[0]['name'][0][0][0])\n",
"filename = '/home/ruben/Documents/Projecten/2020/Security Vision/tryouts/MPII Human Pose Dataset/images/'+anno_file\n",
"print(mpii['act'][imgidx]['cat_name'],\n",
"mpii['act'][imgidx]['act_name'], mpii['act'][imgidx]['act_id'],\n",
"int(mpii['act'][imgidx]['act_id'][0][0])\n",
" )\n",
"Image.open(filename)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c02cb9d3",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "mpii",
"language": "python",
"name": "mpii"
},
"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.9.2"
}
},
"nbformat": 4,
"nbformat_minor": 5
}