{ "cells": [ { "cell_type": "markdown", "metadata": { "toc": "true" }, "source": [ "# Table of Contents\n", "

1  pythonによる最小2乗法
1.1  python code
2  最小2乗法の原理
3  $\\chi^2$の極小値から(2変数の例)
4  正規方程式(Normal Equations)による解
4.1  python codeによる具体例
5  特異値分解(Singular Value Decomposition)による解
6  scipy.linalg.lstsq
6.1  正規方程式によるのも...
7  2次元曲面へのフィット
7.1  具体例
8  課題
8.1  1次元の線形最小二乗法
8.2  2次元の最小二乗フィット
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "
\n", "線形最小2乗法(LeastSquareFit)\n", "
\n", "
\n", "
\n", "file:/Users/bob/Github/TeamNishitani/jupyter_num_calc/leastsquarefit\n", "
\n", "https://github.com/daddygongon/jupyter_num_calc/tree/master/notebooks_python\n", "
\n", "cc by Shigeto R. Nishitani 2017-19 \n", "
\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# pythonによる最小2乗法\n", "\n", "前章では,データに多項式を完全にフィットする補間についてみた.今回は,近似的にフィットする最小二乗法について詳しくみていく.図のようなデータに直線をフィットする場合を考えよう.\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## python code\n", "\n", "x = [1,2,3,4], y=[0,5,15,24]に$y=a0+a1\\,x$をフィットする例を考える.\n", "pythonのcodeは以下の通り." ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[-9.5 8.2]\n" ] }, { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "%matplotlib inline\n", "import numpy as np\n", "import matplotlib.pyplot as plt\n", "from scipy.optimize import curve_fit\n", "\n", "def f(x, a0, a1): #, a2):\n", " return a0 + a1*x #+ a2*x**2\n", "\n", "xdata = np.array([1,2,3,4])\n", "ydata = np.array([0,5,15,24])\n", "plt.plot(xdata,ydata, 'o', color='r')\n", "\n", "params, cov = curve_fit(f, xdata, ydata)\n", "print(params)\n", "\n", "x =np.linspace(0,4,20)\n", "y = f(x,params[0],params[1]) #,params[2])\n", "plt.plot(x,y, color='b')\n", "\n", "plt.grid()\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "結果,a0=-9.5, a1=8.2にfitされることがわかる." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 最小2乗法の原理\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "もっとも簡単な例で原理を解説する.近似関数として,\n", "\n", "$$\n", "F(x) = a_0+a_1\\,x\n", "$$\n", "という直線近似を考える.もっともらしい関数は$N$点の測定データとの差$d_i = F(x_i)-y_i$を最小にすればよさそうであるが,これはプラスマイナスですぐに消えて不定になる.そこで,\n", "\n", "$$\n", "\\chi^{2}=\\sum_i^N d_i^2=\\sum_i^N\\left(a_0+a_1\\,x_i-y_i\\right)^2\n", "$$\n", "という関数を考える.この$\\chi^2$(カイ二乗)関数が,$a_0, a_1$をパラメータとして変えた時に最小となる$a_0, a_1$を求める.これは,それらの微分がそれぞれ0となる場合である.これは$\\chi^2$の和$\\sum$(sum)の中身を展開し,\n", "\n", " \n", "\n", "$\\chi^2=$\n", "\n", " \n", "\n", "$a_0, a_1$でそれぞれ微分すれば\n", "\n", " \n", "\n", "$ \\frac{\\partial}{\\partial a_0} \\chi^2=$\n", "\n", " \n", "\n", "$ \\frac{\\partial}{\\partial a_1} \\chi^2=$\n", "\n", " \n", "\n", "という$a_0, a_1$を未知変数とする2元の連立方程式が得られる.これは前に説明した通り逆行列で解くことができる.\n", "\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# $\\chi^2$の極小値から(2変数の例)\n", "\n", "先ほどの例をもとに何をしているか別の角度からみる.\n", "データを関数に入れてsumをとると次のような関数が得られる." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(a0 + a1)**2 + (a0 + 2*a1 - 5.0)**2 + (a0 + 3*a1 - 15.0)**2 + (a0 + 4*a1 - 24.0)**2\n", "4*a0**2 + 20*a0*a1 - 88.0*a0 + 30*a1**2 - 302.0*a1 + 826.0\n" ] } ], "source": [ "%matplotlib notebook\n", "from mpl_toolkits.mplot3d import Axes3D\n", "import matplotlib.pyplot as plt\n", "import numpy as np\n", "from sympy import *\n", "\n", "a0, a1 = symbols('a0, a1')\n", "def func(x):\n", " return a0+a1*x\n", "\n", "def z_surf(xx,yy):\n", " sum = 0\n", " for i in range(0,4):\n", " tmp = xx[i] - yy[i]\n", " sum = sum + tmp*tmp\n", " return sum\n", "\n", "x1 = np.array([1,2,3,4])\n", "y1 = np.array([0,5,15,24])\n", "eq = z_surf(func(x1),y1)\n", "print(eq)\n", "print(expand(eq))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "これはa0,a1を変数とする関数となっている.\n", "データ点(xi,yi)はすでに数値を持っており,未知なのはa0,a1である.\n", "そうすると$\\chi^2(a0,a1)$, つまりa0,a1をパラメータとして,$\\chi^2$の値をz軸とする3次元関数とみなすことができて,それをplotすると次の通り." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "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 = $('
');\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", " this.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", " '
');\n", " var titletext = $(\n", " '
');\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 = $('
');\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 = $('');\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 = $('');\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 = $('
')\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 = $('');\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 = $('');\n", " nav_element.append(status_bar);\n", " this.message = status_bar[0];\n", "\n", " // Add the close button to the window.\n", " var buttongrp = $('
');\n", " var 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", " // 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", "\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= 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": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%matplotlib notebook\n", "from mpl_toolkits.mplot3d import Axes3D\n", "import matplotlib.pyplot as plt\n", "import numpy as np\n", "\n", "fig = plt.figure()\n", "plot3d = Axes3D(fig)\n", "plot3d.scatter3D(np.array(x),np.array(y),z) \n", "\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "array([ -9.18521214e-13, -6.39644676e-06, 6.39644220e-06,\n", " -5.45955358e+00, 2.57696284e+01, 2.57696284e+01])\n" ] }, { "data": { "text/plain": [ "array([ -9.18525708e-13, -6.39644676e-06, 6.39644220e-06,\n", " -5.45955358e+00, 2.57696284e+01, 2.57696284e+01])" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from pprint import pprint\n", "import scipy.linalg as linalg\n", "\n", "n = z.size\n", "n_j = 6\n", "bb=np.zeros([n])\n", "A=np.zeros([n,n_j])\n", "for i in range(0,n):\n", " A[i,0]=1\n", " A[i,1]=x[i]\n", " A[i,2]=y[i]\n", " A[i,3]=x[i]*y[i]\n", " A[i,4]=x[i]**2\n", " A[i,5]=y[i]**2\n", " bb[i]=z[i]\n", "\n", "c, resid, rank, sigma = linalg.lstsq(A, bb)\n", "pprint(c)\n", "\n", "Ai = linalg.inv(np.dot(np.transpose(A),A))\n", "b = np.dot(np.transpose(A),bb)\n", "np.dot(Ai,b)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": 7, "metadata": { "scrolled": false }, "outputs": [ { "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 = $('
');\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", " this.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", " '
');\n", " var titletext = $(\n", " '
');\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 = $('
');\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 = $('');\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 = $('');\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 = $('
')\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 = $('