{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Visualization" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## hvPlot" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "* 以 Bokeh 為基礎的高階 Library\n", "* 轉成 PDF 會顯示不出來,但因為能互動,適合作研究用\n", " * [這裡](https://github.com/holoviz/holoviews/issues/1057)說加下面這個就會好,但實測失敗\n", "* [把動畫放上 RTD 的例子](https://scikit-fdiff.readthedocs.io/en/latest/introduction.html#quickstart),不過 code 在 GitLab 上\n", " " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import holoviews as hv\n", "hv.notebook_extension(display_formats=['html','png'])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Bokeh\n", "\n", "This does not render in RTD. Possible solutions are [here](https://stackoverflow.com/questions/37096106/how-to-load-external-javascript-in-sphinx-doc) which [this issue](https://github.com/spatialaudio/nbsphinx/issues/61) mentioned." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "
\n", " \n", " Loading BokehJS ...\n", "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", "(function(root) {\n", " function now() {\n", " return new Date();\n", " }\n", "\n", " var force = true;\n", "\n", " if (typeof root._bokeh_onload_callbacks === \"undefined\" || force === true) {\n", " root._bokeh_onload_callbacks = [];\n", " root._bokeh_is_loading = undefined;\n", " }\n", "\n", " var JS_MIME_TYPE = 'application/javascript';\n", " var HTML_MIME_TYPE = 'text/html';\n", " var EXEC_MIME_TYPE = 'application/vnd.bokehjs_exec.v0+json';\n", " var CLASS_NAME = 'output_bokeh rendered_html';\n", "\n", " /**\n", " * Render data to the DOM node\n", " */\n", " function render(props, node) {\n", " var script = document.createElement(\"script\");\n", " node.appendChild(script);\n", " }\n", "\n", " /**\n", " * Handle when an output is cleared or removed\n", " */\n", " function handleClearOutput(event, handle) {\n", " var cell = handle.cell;\n", "\n", " var id = cell.output_area._bokeh_element_id;\n", " var server_id = cell.output_area._bokeh_server_id;\n", " // Clean up Bokeh references\n", " if (id != null && id in Bokeh.index) {\n", " Bokeh.index[id].model.document.clear();\n", " delete Bokeh.index[id];\n", " }\n", "\n", " if (server_id !== undefined) {\n", " // Clean up Bokeh references\n", " var cmd = \"from bokeh.io.state import curstate; print(curstate().uuid_to_server['\" + server_id + \"'].get_sessions()[0].document.roots[0]._id)\";\n", " cell.notebook.kernel.execute(cmd, {\n", " iopub: {\n", " output: function(msg) {\n", " var id = msg.content.text.trim();\n", " if (id in Bokeh.index) {\n", " Bokeh.index[id].model.document.clear();\n", " delete Bokeh.index[id];\n", " }\n", " }\n", " }\n", " });\n", " // Destroy server and session\n", " var cmd = \"import bokeh.io.notebook as ion; ion.destroy_server('\" + server_id + \"')\";\n", " cell.notebook.kernel.execute(cmd);\n", " }\n", " }\n", "\n", " /**\n", " * Handle when a new output is added\n", " */\n", " function handleAddOutput(event, handle) {\n", " var output_area = handle.output_area;\n", " var output = handle.output;\n", "\n", " // limit handleAddOutput to display_data with EXEC_MIME_TYPE content only\n", " if ((output.output_type != \"display_data\") || (!output.data.hasOwnProperty(EXEC_MIME_TYPE))) {\n", " return\n", " }\n", "\n", " var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n", "\n", " if (output.metadata[EXEC_MIME_TYPE][\"id\"] !== undefined) {\n", " toinsert[toinsert.length - 1].firstChild.textContent = output.data[JS_MIME_TYPE];\n", " // store reference to embed id on output_area\n", " output_area._bokeh_element_id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n", " }\n", " if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n", " var bk_div = document.createElement(\"div\");\n", " bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n", " var script_attrs = bk_div.children[0].attributes;\n", " for (var i = 0; i < script_attrs.length; i++) {\n", " toinsert[toinsert.length - 1].firstChild.setAttribute(script_attrs[i].name, script_attrs[i].value);\n", " toinsert[toinsert.length - 1].firstChild.textContent = bk_div.children[0].textContent\n", " }\n", " // store reference to server id on output_area\n", " output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n", " }\n", " }\n", "\n", " function register_renderer(events, OutputArea) {\n", "\n", " function append_mime(data, metadata, element) {\n", " // create a DOM node to render to\n", " var toinsert = this.create_output_subarea(\n", " metadata,\n", " CLASS_NAME,\n", " EXEC_MIME_TYPE\n", " );\n", " this.keyboard_manager.register_events(toinsert);\n", " // Render to node\n", " var props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n", " render(props, toinsert[toinsert.length - 1]);\n", " element.append(toinsert);\n", " return toinsert\n", " }\n", "\n", " /* Handle when an output is cleared or removed */\n", " events.on('clear_output.CodeCell', handleClearOutput);\n", " events.on('delete.Cell', handleClearOutput);\n", "\n", " /* Handle when a new output is added */\n", " events.on('output_added.OutputArea', handleAddOutput);\n", "\n", " /**\n", " * Register the mime type and append_mime function with output_area\n", " */\n", " OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n", " /* Is output safe? */\n", " safe: true,\n", " /* Index of renderer in `output_area.display_order` */\n", " index: 0\n", " });\n", " }\n", "\n", " // register the mime type if in Jupyter Notebook environment and previously unregistered\n", " if (root.Jupyter !== undefined) {\n", " var events = require('base/js/events');\n", " var OutputArea = require('notebook/js/outputarea').OutputArea;\n", "\n", " if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n", " register_renderer(events, OutputArea);\n", " }\n", " }\n", "\n", " \n", " if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n", " root._bokeh_timeout = Date.now() + 5000;\n", " root._bokeh_failed_load = false;\n", " }\n", "\n", " var NB_LOAD_WARNING = {'data': {'text/html':\n", " \"
\\n\"+\n", " \"

\\n\"+\n", " \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n", " \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n", " \"

\\n\"+\n", " \"\\n\"+\n", " \"\\n\"+\n", " \"from bokeh.resources import INLINE\\n\"+\n", " \"output_notebook(resources=INLINE)\\n\"+\n", " \"\\n\"+\n", " \"
\"}};\n", "\n", " function display_loaded() {\n", " var el = document.getElementById(\"1001\");\n", " if (el != null) {\n", " el.textContent = \"BokehJS is loading...\";\n", " }\n", " if (root.Bokeh !== undefined) {\n", " if (el != null) {\n", " el.textContent = \"BokehJS \" + root.Bokeh.version + \" successfully loaded.\";\n", " }\n", " } else if (Date.now() < root._bokeh_timeout) {\n", " setTimeout(display_loaded, 100)\n", " }\n", " }\n", "\n", "\n", " function run_callbacks() {\n", " try {\n", " root._bokeh_onload_callbacks.forEach(function(callback) {\n", " if (callback != null)\n", " callback();\n", " });\n", " } finally {\n", " delete root._bokeh_onload_callbacks\n", " }\n", " console.debug(\"Bokeh: all callbacks have finished\");\n", " }\n", "\n", " function load_libs(css_urls, js_urls, callback) {\n", " if (css_urls == null) css_urls = [];\n", " if (js_urls == null) js_urls = [];\n", "\n", " root._bokeh_onload_callbacks.push(callback);\n", " if (root._bokeh_is_loading > 0) {\n", " console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n", " return null;\n", " }\n", " if (js_urls == null || js_urls.length === 0) {\n", " run_callbacks();\n", " return null;\n", " }\n", " console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n", " root._bokeh_is_loading = css_urls.length + js_urls.length;\n", "\n", " function on_load() {\n", " root._bokeh_is_loading--;\n", " if (root._bokeh_is_loading === 0) {\n", " console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n", " run_callbacks()\n", " }\n", " }\n", "\n", " function on_error() {\n", " console.error(\"failed to load \" + url);\n", " }\n", "\n", " for (var i = 0; i < css_urls.length; i++) {\n", " var url = css_urls[i];\n", " const element = document.createElement(\"link\");\n", " element.onload = on_load;\n", " element.onerror = on_error;\n", " element.rel = \"stylesheet\";\n", " element.type = \"text/css\";\n", " element.href = url;\n", " console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n", " document.body.appendChild(element);\n", " }\n", "\n", " const hashes = {\"https://cdn.bokeh.org/bokeh/release/bokeh-2.2.3.min.js\": \"T2yuo9Oe71Cz/I4X9Ac5+gpEa5a8PpJCDlqKYO0CfAuEszu1JrXLl8YugMqYe3sM\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.2.3.min.js\": \"98GDGJ0kOMCUMUePhksaQ/GYgB3+NH9h996V88sh3aOiUNX3N+fLXAtry6xctSZ6\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.2.3.min.js\": \"89bArO+nlbP3sgakeHjCo1JYxYR5wufVgA3IbUvDY+K7w4zyxJqssu7wVnfeKCq8\"};\n", "\n", " for (var i = 0; i < js_urls.length; i++) {\n", " var url = js_urls[i];\n", " var element = document.createElement('script');\n", " element.onload = on_load;\n", " element.onerror = on_error;\n", " element.async = false;\n", " element.src = url;\n", " if (url in hashes) {\n", " element.crossOrigin = \"anonymous\";\n", " element.integrity = \"sha384-\" + hashes[url];\n", " }\n", " console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n", " document.head.appendChild(element);\n", " }\n", " };\n", "\n", " function inject_raw_css(css) {\n", " const element = document.createElement(\"style\");\n", " element.appendChild(document.createTextNode(css));\n", " document.body.appendChild(element);\n", " }\n", "\n", " \n", " var js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-2.2.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.2.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.2.3.min.js\"];\n", " var css_urls = [];\n", " \n", "\n", " var inline_js = [\n", " function(Bokeh) {\n", " Bokeh.set_log_level(\"info\");\n", " },\n", " function(Bokeh) {\n", " \n", " \n", " }\n", " ];\n", "\n", " function run_inline_js() {\n", " \n", " if (root.Bokeh !== undefined || force === true) {\n", " \n", " for (var i = 0; i < inline_js.length; i++) {\n", " inline_js[i].call(root, root.Bokeh);\n", " }\n", " if (force === true) {\n", " display_loaded();\n", " }} else if (Date.now() < root._bokeh_timeout) {\n", " setTimeout(run_inline_js, 100);\n", " } else if (!root._bokeh_failed_load) {\n", " console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n", " root._bokeh_failed_load = true;\n", " } else if (force !== true) {\n", " var cell = $(document.getElementById(\"1001\")).parents('.cell').data().cell;\n", " cell.output_area.append_execute_result(NB_LOAD_WARNING)\n", " }\n", "\n", " }\n", "\n", " if (root._bokeh_is_loading === 0) {\n", " console.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n", " run_inline_js();\n", " } else {\n", " load_libs(css_urls, js_urls, function() {\n", " console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n", " run_inline_js();\n", " });\n", " }\n", "}(window));" ], "application/vnd.bokehjs_load.v0+json": "\n(function(root) {\n function now() {\n return new Date();\n }\n\n var force = true;\n\n if (typeof root._bokeh_onload_callbacks === \"undefined\" || force === true) {\n root._bokeh_onload_callbacks = [];\n root._bokeh_is_loading = undefined;\n }\n\n \n\n \n if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n root._bokeh_timeout = Date.now() + 5000;\n root._bokeh_failed_load = false;\n }\n\n var NB_LOAD_WARNING = {'data': {'text/html':\n \"
\\n\"+\n \"

\\n\"+\n \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n \"

\\n\"+\n \"\\n\"+\n \"\\n\"+\n \"from bokeh.resources import INLINE\\n\"+\n \"output_notebook(resources=INLINE)\\n\"+\n \"\\n\"+\n \"
\"}};\n\n function display_loaded() {\n var el = document.getElementById(\"1001\");\n if (el != null) {\n el.textContent = \"BokehJS is loading...\";\n }\n if (root.Bokeh !== undefined) {\n if (el != null) {\n el.textContent = \"BokehJS \" + root.Bokeh.version + \" successfully loaded.\";\n }\n } else if (Date.now() < root._bokeh_timeout) {\n setTimeout(display_loaded, 100)\n }\n }\n\n\n function run_callbacks() {\n try {\n root._bokeh_onload_callbacks.forEach(function(callback) {\n if (callback != null)\n callback();\n });\n } finally {\n delete root._bokeh_onload_callbacks\n }\n console.debug(\"Bokeh: all callbacks have finished\");\n }\n\n function load_libs(css_urls, js_urls, callback) {\n if (css_urls == null) css_urls = [];\n if (js_urls == null) js_urls = [];\n\n root._bokeh_onload_callbacks.push(callback);\n if (root._bokeh_is_loading > 0) {\n console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n return null;\n }\n if (js_urls == null || js_urls.length === 0) {\n run_callbacks();\n return null;\n }\n console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n root._bokeh_is_loading = css_urls.length + js_urls.length;\n\n function on_load() {\n root._bokeh_is_loading--;\n if (root._bokeh_is_loading === 0) {\n console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n run_callbacks()\n }\n }\n\n function on_error() {\n console.error(\"failed to load \" + url);\n }\n\n for (var i = 0; i < css_urls.length; i++) {\n var url = css_urls[i];\n const element = document.createElement(\"link\");\n element.onload = on_load;\n element.onerror = on_error;\n element.rel = \"stylesheet\";\n element.type = \"text/css\";\n element.href = url;\n console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n document.body.appendChild(element);\n }\n\n const hashes = {\"https://cdn.bokeh.org/bokeh/release/bokeh-2.2.3.min.js\": \"T2yuo9Oe71Cz/I4X9Ac5+gpEa5a8PpJCDlqKYO0CfAuEszu1JrXLl8YugMqYe3sM\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.2.3.min.js\": \"98GDGJ0kOMCUMUePhksaQ/GYgB3+NH9h996V88sh3aOiUNX3N+fLXAtry6xctSZ6\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.2.3.min.js\": \"89bArO+nlbP3sgakeHjCo1JYxYR5wufVgA3IbUvDY+K7w4zyxJqssu7wVnfeKCq8\"};\n\n for (var i = 0; i < js_urls.length; i++) {\n var url = js_urls[i];\n var element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error;\n element.async = false;\n element.src = url;\n if (url in hashes) {\n element.crossOrigin = \"anonymous\";\n element.integrity = \"sha384-\" + hashes[url];\n }\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\n }\n };\n\n function inject_raw_css(css) {\n const element = document.createElement(\"style\");\n element.appendChild(document.createTextNode(css));\n document.body.appendChild(element);\n }\n\n \n var js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-2.2.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.2.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.2.3.min.js\"];\n var css_urls = [];\n \n\n var inline_js = [\n function(Bokeh) {\n Bokeh.set_log_level(\"info\");\n },\n function(Bokeh) {\n \n \n }\n ];\n\n function run_inline_js() {\n \n if (root.Bokeh !== undefined || force === true) {\n \n for (var i = 0; i < inline_js.length; i++) {\n inline_js[i].call(root, root.Bokeh);\n }\n if (force === true) {\n display_loaded();\n }} else if (Date.now() < root._bokeh_timeout) {\n setTimeout(run_inline_js, 100);\n } else if (!root._bokeh_failed_load) {\n console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n root._bokeh_failed_load = true;\n } else if (force !== true) {\n var cell = $(document.getElementById(\"1001\")).parents('.cell').data().cell;\n cell.output_area.append_execute_result(NB_LOAD_WARNING)\n }\n\n }\n\n if (root._bokeh_is_loading === 0) {\n console.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n run_inline_js();\n } else {\n load_libs(css_urls, js_urls, function() {\n console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n run_inline_js();\n });\n }\n}(window));" }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "
\n" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "(function(root) {\n", " function embed_document(root) {\n", " \n", " var docs_json = {\"a566191f-8b3f-4fca-84df-a1317e302e0d\":{\"roots\":{\"references\":[{\"attributes\":{\"children\":[{\"id\":\"1091\"},{\"id\":\"1004\"}]},\"id\":\"1092\",\"type\":\"Column\"},{\"attributes\":{\"text\":\"\"},\"id\":\"1054\",\"type\":\"Title\"},{\"attributes\":{},\"id\":\"1022\",\"type\":\"ResetTool\"},{\"attributes\":{},\"id\":\"1011\",\"type\":\"LinearScale\"},{\"attributes\":{},\"id\":\"1063\",\"type\":\"Selection\"},{\"attributes\":{},\"id\":\"1086\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"label\":{\"value\":\"MLE\"},\"renderers\":[{\"id\":\"1072\"}]},\"id\":\"1089\",\"type\":\"LegendItem\"},{\"attributes\":{\"angle\":{\"field\":\"em_th\",\"units\":\"rad\"},\"fill_alpha\":{\"value\":0},\"fill_color\":{\"value\":\"#1f77b4\"},\"height\":{\"field\":\"em_h\",\"units\":\"data\"},\"line_alpha\":{\"field\":\"em_alpha\"},\"line_color\":{\"value\":\"green\"},\"line_width\":{\"value\":2.5},\"width\":{\"field\":\"em_w\",\"units\":\"data\"},\"x\":{\"value\":0},\"y\":{\"value\":0}},\"id\":\"1045\",\"type\":\"Ellipse\"},{\"attributes\":{},\"id\":\"1087\",\"type\":\"Selection\"},{\"attributes\":{\"data_source\":{\"id\":\"1003\"},\"glyph\":{\"id\":\"1045\"},\"hover_glyph\":null,\"muted_glyph\":null,\"nonselection_glyph\":{\"id\":\"1046\"},\"selection_glyph\":null,\"view\":{\"id\":\"1048\"}},\"id\":\"1047\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"axis\":{\"id\":\"1013\"},\"ticker\":null},\"id\":\"1016\",\"type\":\"Grid\"},{\"attributes\":{},\"id\":\"1014\",\"type\":\"BasicTicker\"},{\"attributes\":{\"source\":{\"id\":\"1003\"}},\"id\":\"1038\",\"type\":\"CDSView\"},{\"attributes\":{\"data\":{\"x\":[-20],\"y\":[0]},\"selected\":{\"id\":\"1087\"},\"selection_policy\":{\"id\":\"1086\"}},\"id\":\"1069\",\"type\":\"ColumnDataSource\"},{\"attributes\":{},\"id\":\"1058\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{\"items\":[{\"id\":\"1068\"},{\"id\":\"1089\"}]},\"id\":\"1067\",\"type\":\"Legend\"},{\"attributes\":{\"formatter\":{\"id\":\"1056\"},\"ticker\":{\"id\":\"1014\"}},\"id\":\"1013\",\"type\":\"LinearAxis\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"value\":\"black\"},\"line_alpha\":{\"value\":0.1},\"line_color\":{\"value\":null},\"size\":{\"units\":\"screen\",\"value\":6},\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"1031\",\"type\":\"Circle\"},{\"attributes\":{\"data\":{\"index\":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249],\"x\":{\"__ndarray__\":\"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\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[250]},\"y\":{\"__ndarray__\":\"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\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[250]}},\"selected\":{\"id\":\"1061\"},\"selection_policy\":{\"id\":\"1060\"}},\"id\":\"1002\",\"type\":\"ColumnDataSource\"},{\"attributes\":{},\"id\":\"1018\",\"type\":\"BasicTicker\"},{\"attributes\":{},\"id\":\"1060\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"data_source\":{\"id\":\"1002\"},\"glyph\":{\"id\":\"1030\"},\"hover_glyph\":null,\"muted_glyph\":null,\"nonselection_glyph\":{\"id\":\"1031\"},\"selection_glyph\":null,\"view\":{\"id\":\"1033\"}},\"id\":\"1032\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"end\":10,\"start\":-10},\"id\":\"1005\",\"type\":\"Range1d\"},{\"attributes\":{\"end\":10,\"start\":-10},\"id\":\"1007\",\"type\":\"Range1d\"},{\"attributes\":{\"data\":{\"em_alpha\":[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\"em_h\":{\"__ndarray__\":\"PR8a9IDAGEDPyX4b7PEZQMUnvdxDWBxAqPap9X/HHEDvwD3OmMQcQGmBOBuQxxxAcYpRwyrRHEDW+D70nsQcQKDHTDsVUx1ApXODVK1KHUAgpH5oT04dQMuCI5gDUh1ANg137HVLHUCauoVC9HAdQE/RRy/LgR1ADwZJpV+JHUDQ3zVbF5AdQIATujIEiB1A3Qb3oM3eHUCfmsTVltIdQA==\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[20]},\"em_th\":{\"__ndarray__\":\"KKJjma6xhz91WFSFib+pP9j93eJCL8U/0DxPeyTewT8XpHhnGfjAPxtmHgIBhcE/Nqap/yM2wj/jswng3jXCP55Z2/GhAcA/7D6Sqvvhvj9PWDwJh2rAP731GwDLZ8E/sbAGyytUwT8grlitIg3CP+LwOJM07MA/1S/hoRYLwD/UW1FEg1O+PxAo/+Z0jL4/W3K9rXdeuT8XvPBpTrG4Pw==\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[20]},\"em_w\":{\"__ndarray__\":\"HleijJceJkD1O7/K6E8mQL89U02mPSdAfqwgXr9uJ0AxEPwY6pMnQGZr2L+HlCdA2GhGsf+WJ0ATgUQfPYsnQMNq/+T3lCdAC82T++isJ0B1FlBs3sUnQNykNTCz4CdAAM4HhJDVJ0AAjJaQFdEnQB5ppvBD4idAyEdx1MfvJ0A5GkWksP4nQBCDOVqg9CdAJRgLGnwYKEA8Ytbp8zUoQA==\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[20]},\"index\":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19],\"mcd_alpha\":[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\"mcd_h\":{\"__ndarray__\":\"msWTo5q9GEAh7g8OQcEYQCHuDw5BwRhAIe4PDkHBGEAcfqLPr7gYQMeiOxxxyBhA/XexBr7hGEAQZNnLMtcYQBBk2csy1xhAJ4bS7f/MGECoyTBgKuIYQIJXobVT9xhA0VtxoUzzGEAYHTv4VywZQJoZeqzYRRlAc+vFBsk+GUCC0pXnxUIZQLL1lpA0SRlAEQAbnNg+GUCRxuPm7zIZQA==\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[20]},\"mcd_th\":{\"__ndarray__\":\"TcGTQHdBmz/Bg0HiRiyTP8GDQeJGLJM/wYNB4kYskz/qXc5sTWeNP7IVptLH6ZM/gQrPKQVWmj8Hi8l820maPweLyXzbSZo/BBKy3w9ylz/ziT0TA8SgP2LaZAee6KU/+7U5EKWHpT/hefeyGGOoP22OJWBS450/EJsZXq3QoD/kziRBhDSbP2+vv4jdaZI/mK0XW7MgnD+QKdmnCeCaPw==\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[20]},\"mcd_w\":{\"__ndarray__\":\"sf1jfvKDJUCkcTnuOKYlQKRxOe44piVApHE57jimJUA02tBq2dMlQMWcHBQx1CVAJMMJGQ7WJUAXgLwj98olQBeAvCP3yiVAvDOi1MPoJUDza1563AImQCCB9H7+HiZA5YUGeMUUJkCXghiziQ8mQDMjM9ggUiZA8YE77Ko6JkA7dyo4Rk8mQEZGdl7MbyZAhNBSGpdFJkAAuixgt2gmQA==\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[20]},\"pt_alpha\":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\"x\":{\"__ndarray__\":\"vimxah53EECjMNCMbrQfwBBAujJklBNAFDOfjUZcEED/IcMXyh/9P6MO4t7byv6/KrQJnPKJsr85d7yYm1EJQECJ3eojEAzAClgQ/+lrCkCqFau4ux8LQEm9fJGneOG/Op7sch+I878cc/nHfcsKwA3lzdn01gjAAsKOfBF0CcBtJjBO2HjjP4bx+8hWmBFA/7wcdzqZDkB+R0QDoBQBwA==\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[20]},\"y\":{\"__ndarray__\":\"jJRIAMB2FUBEOWVzfBEhwCT0AapGXQbAqvX0i1O44L+wJyRPZjL5Pwg6vc0FWf2/c7UM/Bb12j9S/ej5lcwMwD7AzaexXdc/A+jXkquh/D/YJHyiT1D9P++i3BmGruo/6WfK2YsoBMBQuKWuceT1P0Hdl5yXHvI/APogPQPX8T+A8pctwV/sPy4IAnNTsQbA0GHT7ctTuL83p8sKOhwRQA==\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[20]}},\"selected\":{\"id\":\"1063\"},\"selection_policy\":{\"id\":\"1062\"}},\"id\":\"1003\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"value\":\"red\"},\"line_alpha\":{\"value\":0.1},\"line_color\":{\"value\":null},\"size\":{\"units\":\"screen\",\"value\":6},\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"1036\",\"type\":\"Circle\"},{\"attributes\":{\"source\":{\"id\":\"1003\"}},\"id\":\"1048\",\"type\":\"CDSView\"},{\"attributes\":{},\"id\":\"1065\",\"type\":\"Selection\"},{\"attributes\":{\"formatter\":{\"id\":\"1058\"},\"ticker\":{\"id\":\"1018\"}},\"id\":\"1017\",\"type\":\"LinearAxis\"},{\"attributes\":{},\"id\":\"1023\",\"type\":\"SaveTool\"},{\"attributes\":{\"line_alpha\":0.1,\"line_color\":\"green\",\"line_width\":2.5,\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"1071\",\"type\":\"Line\"},{\"attributes\":{\"angle\":{\"field\":\"mcd_th\",\"units\":\"rad\"},\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"value\":\"#1f77b4\"},\"height\":{\"field\":\"mcd_h\",\"units\":\"data\"},\"line_alpha\":{\"value\":0.1},\"line_color\":{\"value\":\"orange\"},\"line_width\":{\"value\":2.5},\"width\":{\"field\":\"mcd_w\",\"units\":\"data\"},\"x\":{\"value\":0},\"y\":{\"value\":0}},\"id\":\"1041\",\"type\":\"Ellipse\"},{\"attributes\":{},\"id\":\"1064\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"bottom_units\":\"screen\",\"fill_alpha\":0.5,\"fill_color\":\"lightgrey\",\"left_units\":\"screen\",\"level\":\"overlay\",\"line_alpha\":1.0,\"line_color\":\"black\",\"line_dash\":[4,4],\"line_width\":2,\"right_units\":\"screen\",\"top_units\":\"screen\"},\"id\":\"1024\",\"type\":\"BoxAnnotation\"},{\"attributes\":{\"source\":{\"id\":\"1069\"}},\"id\":\"1073\",\"type\":\"CDSView\"},{\"attributes\":{\"data_source\":{\"id\":\"1069\"},\"glyph\":{\"id\":\"1070\"},\"hover_glyph\":null,\"muted_glyph\":null,\"nonselection_glyph\":{\"id\":\"1071\"},\"selection_glyph\":null,\"view\":{\"id\":\"1073\"}},\"id\":\"1072\",\"type\":\"GlyphRenderer\"},{\"attributes\":{},\"id\":\"1009\",\"type\":\"LinearScale\"},{\"attributes\":{\"active_drag\":\"auto\",\"active_inspect\":\"auto\",\"active_multi\":null,\"active_scroll\":\"auto\",\"active_tap\":\"auto\",\"tools\":[{\"id\":\"1021\"},{\"id\":\"1022\"},{\"id\":\"1023\"}]},\"id\":\"1025\",\"type\":\"Toolbar\"},{\"attributes\":{\"data\":{\"x\":[-20],\"y\":[0]},\"selected\":{\"id\":\"1065\"},\"selection_policy\":{\"id\":\"1064\"}},\"id\":\"1049\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"line_color\":\"green\",\"line_width\":2.5,\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"1070\",\"type\":\"Line\"},{\"attributes\":{\"label\":{\"value\":\"MCD\"},\"renderers\":[{\"id\":\"1052\"}]},\"id\":\"1068\",\"type\":\"LegendItem\"},{\"attributes\":{},\"id\":\"1062\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"args\":{\"src_out\":{\"id\":\"1003\"}},\"code\":\"\\n var data = src_out.data\\n var n_outliers = cb_obj.value\\n var pt_alpha = data['pt_alpha']\\n var em_alpha = data['em_alpha']\\n var mcd_alpha = data['mcd_alpha']\\n \\n for (var i = 0; i < pt_alpha.length; i++) {\\n em_alpha[i] = 0\\n mcd_alpha[i] = 0\\n if (i < n_outliers)\\n pt_alpha[i] = 1\\n else\\n pt_alpha[i] = 0\\n }\\n em_alpha[n_outliers] = 1\\n mcd_alpha[n_outliers] = 1\\n \\n src_out.change.emit()\\n\"},\"id\":\"1090\",\"type\":\"CustomJS\"},{\"attributes\":{\"source\":{\"id\":\"1049\"}},\"id\":\"1053\",\"type\":\"CDSView\"},{\"attributes\":{\"source\":{\"id\":\"1002\"}},\"id\":\"1033\",\"type\":\"CDSView\"},{\"attributes\":{\"fill_alpha\":{\"field\":\"pt_alpha\"},\"fill_color\":{\"value\":\"red\"},\"line_color\":{\"value\":null},\"size\":{\"units\":\"screen\",\"value\":6},\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"1035\",\"type\":\"Circle\"},{\"attributes\":{\"line_alpha\":0.1,\"line_color\":\"orange\",\"line_width\":2.5,\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"1051\",\"type\":\"Line\"},{\"attributes\":{\"line_color\":\"orange\",\"line_width\":2.5,\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"1050\",\"type\":\"Line\"},{\"attributes\":{\"angle\":{\"field\":\"mcd_th\",\"units\":\"rad\"},\"fill_alpha\":{\"value\":0},\"fill_color\":{\"value\":\"#1f77b4\"},\"height\":{\"field\":\"mcd_h\",\"units\":\"data\"},\"line_alpha\":{\"field\":\"mcd_alpha\"},\"line_color\":{\"value\":\"orange\"},\"line_width\":{\"value\":2.5},\"width\":{\"field\":\"mcd_w\",\"units\":\"data\"},\"x\":{\"value\":0},\"y\":{\"value\":0}},\"id\":\"1040\",\"type\":\"Ellipse\"},{\"attributes\":{\"end\":19,\"format\":\"0[.]00\",\"js_property_callbacks\":{\"change:value\":[{\"id\":\"1090\"}]},\"start\":0,\"title\":\"n_outliers\",\"value\":0},\"id\":\"1091\",\"type\":\"Slider\"},{\"attributes\":{\"overlay\":{\"id\":\"1024\"}},\"id\":\"1021\",\"type\":\"BoxZoomTool\"},{\"attributes\":{\"data_source\":{\"id\":\"1003\"},\"glyph\":{\"id\":\"1040\"},\"hover_glyph\":null,\"muted_glyph\":null,\"nonselection_glyph\":{\"id\":\"1041\"},\"selection_glyph\":null,\"view\":{\"id\":\"1043\"}},\"id\":\"1042\",\"type\":\"GlyphRenderer\"},{\"attributes\":{},\"id\":\"1056\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{},\"id\":\"1061\",\"type\":\"Selection\"},{\"attributes\":{\"below\":[{\"id\":\"1013\"}],\"center\":[{\"id\":\"1016\"},{\"id\":\"1020\"},{\"id\":\"1067\"}],\"left\":[{\"id\":\"1017\"}],\"plot_height\":400,\"plot_width\":400,\"renderers\":[{\"id\":\"1032\"},{\"id\":\"1037\"},{\"id\":\"1042\"},{\"id\":\"1047\"},{\"id\":\"1052\"},{\"id\":\"1072\"}],\"title\":{\"id\":\"1054\"},\"toolbar\":{\"id\":\"1025\"},\"x_range\":{\"id\":\"1005\"},\"x_scale\":{\"id\":\"1009\"},\"y_range\":{\"id\":\"1007\"},\"y_scale\":{\"id\":\"1011\"}},\"id\":\"1004\",\"subtype\":\"Figure\",\"type\":\"Plot\"},{\"attributes\":{\"data_source\":{\"id\":\"1049\"},\"glyph\":{\"id\":\"1050\"},\"hover_glyph\":null,\"muted_glyph\":null,\"nonselection_glyph\":{\"id\":\"1051\"},\"selection_glyph\":null,\"view\":{\"id\":\"1053\"}},\"id\":\"1052\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"fill_color\":{\"value\":\"black\"},\"line_color\":{\"value\":null},\"size\":{\"units\":\"screen\",\"value\":6},\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"1030\",\"type\":\"Circle\"},{\"attributes\":{\"source\":{\"id\":\"1003\"}},\"id\":\"1043\",\"type\":\"CDSView\"},{\"attributes\":{\"axis\":{\"id\":\"1017\"},\"dimension\":1,\"ticker\":null},\"id\":\"1020\",\"type\":\"Grid\"},{\"attributes\":{\"angle\":{\"field\":\"em_th\",\"units\":\"rad\"},\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"value\":\"#1f77b4\"},\"height\":{\"field\":\"em_h\",\"units\":\"data\"},\"line_alpha\":{\"value\":0.1},\"line_color\":{\"value\":\"green\"},\"line_width\":{\"value\":2.5},\"width\":{\"field\":\"em_w\",\"units\":\"data\"},\"x\":{\"value\":0},\"y\":{\"value\":0}},\"id\":\"1046\",\"type\":\"Ellipse\"},{\"attributes\":{\"data_source\":{\"id\":\"1003\"},\"glyph\":{\"id\":\"1035\"},\"hover_glyph\":null,\"muted_glyph\":null,\"nonselection_glyph\":{\"id\":\"1036\"},\"selection_glyph\":null,\"view\":{\"id\":\"1038\"}},\"id\":\"1037\",\"type\":\"GlyphRenderer\"}],\"root_ids\":[\"1092\"]},\"title\":\"Bokeh Application\",\"version\":\"2.2.3\"}};\n", " var render_items = [{\"docid\":\"a566191f-8b3f-4fca-84df-a1317e302e0d\",\"root_ids\":[\"1092\"],\"roots\":{\"1092\":\"3b127335-cc6c-481f-b7e4-f3121eb8ebf1\"}}];\n", " root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n", "\n", " }\n", " if (root.Bokeh !== undefined) {\n", " embed_document(root);\n", " } else {\n", " var attempts = 0;\n", " var timer = setInterval(function(root) {\n", " if (root.Bokeh !== undefined) {\n", " clearInterval(timer);\n", " embed_document(root);\n", " } else {\n", " attempts++;\n", " if (attempts > 100) {\n", " clearInterval(timer);\n", " console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n", " }\n", " }\n", " }, 10, root)\n", " }\n", "})(window);" ], "application/vnd.bokehjs_exec.v0+json": "" }, "metadata": { "application/vnd.bokehjs_exec.v0+json": { "id": "1092" } }, "output_type": "display_data" } ], "source": [ "from bokeh.layouts import column\n", "# from ipywidgets import interact\n", "from bokeh.io import push_notebook, output_notebook, output_file, show\n", "from bokeh.plotting import figure\n", "from math import pi\n", "from bokeh.models import CustomJS, ColumnDataSource, Slider\n", "from sklearn.covariance import EmpiricalCovariance, MinCovDet\n", "from pandas import DataFrame\n", "import numpy as np\n", "\n", "# output_file('mcd.html')\n", "# output_notebook(hide_banner=True)\n", "output_notebook()\n", "\n", "n_inliers = 250\n", "n_all_outliers = 20\n", "\n", "np.random.seed(20)\n", "\n", "# generate data with 20 outliers\n", "inliers_cov = [[2, 0], [0, 1]]\n", "outliers_cov = [[1, 4], [4, 1]]\n", "inliers = np.dot(np.random.randn(n_inliers, 2), inliers_cov)\n", "outliers = np.dot(np.random.randn(n_all_outliers, 2), outliers_cov)\n", "\n", "df_in = DataFrame(inliers, columns=['x', 'y'])\n", "df_out = DataFrame(outliers, columns=['x', 'y'])\n", "df_out['pt_alpha'] = 0\n", "df_out['em_alpha'] = 0\n", "df_out['mcd_alpha'] = 0\n", "df_out.loc[0, 'em_alpha'] = 1\n", "df_out.loc[0, 'mcd_alpha'] = 1\n", "\n", "em_ellipse_param = []\n", "mcd_ellipse_param = []\n", "for n_outliers in range(n_all_outliers):\n", " cov = EmpiricalCovariance(assume_centered=True).fit(np.append(inliers, outliers[:n_outliers, :], axis=0)).covariance_\n", " cov_inv = np.linalg.inv(cov)\n", " z11, z22, z12 = cov_inv[0, 0], cov_inv[1, 1], cov_inv[0, 1]\n", " theta = np.arctan(2*z12/(z11-z22))/2\n", " rot = np.array([[np.cos(theta), -np.sin(theta)], [np.sin(theta), np.cos(theta)]])\n", " wh = rot.transpose() @ cov_inv @ rot\n", " width, height = 6/np.sqrt([wh[0, 0], wh[1, 1]])\n", " em_ellipse_param.append((height, width, theta))\n", "\n", " cov = MinCovDet(assume_centered=True).fit(np.append(inliers, outliers[:n_outliers, :], axis=0)).covariance_\n", " cov_inv = np.linalg.inv(cov)\n", " z11, z22, z12 = cov_inv[0, 0], cov_inv[1, 1], cov_inv[0, 1]\n", " theta = np.arctan(2*z12/(z11-z22))/2\n", " rot = np.array([[np.cos(theta), -np.sin(theta)], [np.sin(theta), np.cos(theta)]])\n", " wh = rot.transpose() @ cov_inv @ rot\n", " width, height = 6/np.sqrt([wh[0, 0], wh[1, 1]])\n", " mcd_ellipse_param.append((height, width, theta))\n", "\n", "df_out['em_h'], df_out['em_w'], df_out['em_th'] = np.array(em_ellipse_param).T\n", "df_out['mcd_h'], df_out['mcd_w'], df_out['mcd_th'] = np.array(mcd_ellipse_param).T\n", "\n", "src_in = ColumnDataSource(df_in)\n", "src_out = ColumnDataSource(df_out)\n", "\n", "TOOLTIPS = [(\"(x, y)\", \"(@x, @y)\")]\n", "p = figure(tools='box_zoom,reset,save', \n", "# tooltips=TOOLTIPS, \n", " plot_height=400, \n", " plot_width=400, \n", " x_range=(-10, 10), y_range=(-10, 10)\n", " )\n", "p.circle(x='x', y='y', fill_color='black', line_color=None, size=6, source=src_in)\n", "p.circle(x='x', y='y', fill_color='red', line_color=None, size=6, source=src_out, fill_alpha='pt_alpha')\n", "p.ellipse(x=0, y=0, width='mcd_w', height='mcd_h', angle='mcd_th', line_alpha='mcd_alpha', line_color='orange', fill_alpha=0, line_width=2.5, source=src_out)\n", "p.ellipse(x=0, y=0, width='em_w', height='em_h', angle='em_th', line_alpha='em_alpha', line_color='green', fill_alpha=0, line_width=2.5, source=src_out)\n", "p.line(x=[-20], y=[0], line_width=2.5, color='orange', legend_label='MCD')\n", "p.line(x=[-20], y=[0], line_width=2.5, color='green', legend_label='MLE')\n", "p.legend.location = \"top_right\"\n", "\n", "callback_code = \"\"\"\n", " var data = src_out.data\n", " var n_outliers = cb_obj.value\n", " var pt_alpha = data['pt_alpha']\n", " var em_alpha = data['em_alpha']\n", " var mcd_alpha = data['mcd_alpha']\n", " \n", " for (var i = 0; i < pt_alpha.length; i++) {\n", " em_alpha[i] = 0\n", " mcd_alpha[i] = 0\n", " if (i < n_outliers)\n", " pt_alpha[i] = 1\n", " else\n", " pt_alpha[i] = 0\n", " }\n", " em_alpha[n_outliers] = 1\n", " mcd_alpha[n_outliers] = 1\n", " \n", " src_out.change.emit()\n", "\"\"\"\n", "callback = CustomJS(args=dict(src_out=src_out), code=callback_code)\n", "slider = Slider(start=0, end=n_outliers, value=0, step=1, title='n_outliers')\n", "slider.js_on_change('value', callback)\n", "\n", "layout = column(slider, p)\n", "\n", "show(layout)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ipywidgets" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "0ad87d069f0140e29d44f5a04d773f9c", "version_major": 2, "version_minor": 0 }, "text/plain": [ "interactive(children=(FloatSlider(value=0.0, description='m', max=2.0, min=-2.0), FloatSlider(value=0.0, descr…" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%matplotlib inline\n", "from ipywidgets import interactive\n", "import matplotlib.pyplot as plt\n", "import numpy as np\n", "\n", "def f(m, b):\n", " plt.figure(2)\n", " x = np.linspace(-10, 10, num=1000)\n", " plt.plot(x, m * x + b)\n", " plt.ylim(-5, 5)\n", " plt.show()\n", "\n", "interactive_plot = interactive(f, m=(-2.0, 2.0), b=(-3, 3, 0.5))\n", "output = interactive_plot.children[-1]\n", "output.layout.height = '350px'\n", "interactive_plot\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### [SGT](https://en.wikipedia.org/wiki/Skewed_generalized_t_distribution)\n", "\n", "Theodossiou's Skewed Generalized $t$ Distribution. See [this notebook](https://github.com/beginnerSC/mscf/blob/master/FDS%20II/Homeworks/2/chunyuac_HW2.ipynb) for cdf, ppf and more." ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "9b302abf1fb64018b5e1c5ef1a3c9780", "version_major": 2, "version_minor": 0 }, "text/plain": [ "interactive(children=(FloatSlider(value=0.0, description='mu', max=3.0, min=-3.0), FloatSlider(value=0.5, desc…" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%matplotlib inline\n", "\n", "from pandas import DataFrame\n", "from scipy.special import beta\n", "from ipywidgets import interact\n", "import matplotlib.pyplot as plt\n", "import numpy as np\n", "\n", "def pdf(x, mu, k, n, lam, sigma2):\n", " '''\n", " k > 0, n > 2, sigma2 > 0, -1 < lam < 1\n", " '''\n", " sigma = np.sqrt(sigma2)\n", " S = np.sqrt(1 + 3*(lam**2) - 4*(lam**2)*((beta(2/k, (n-1)/k)**2)/(beta(1/k, n/k)*beta(3/k, (n-2)/k))))\n", " c = 0.5*k*np.sqrt((beta(1/k, n/k)**(-3))*beta(3/k, (n-2)/k))*S/sigma\n", " theta = ((k/(n-2))**(1/k))*np.sqrt(beta(1/k, n/k)/beta(3/k, (n-2)/k))/S\n", " return c*(1+(k/(n-2))*(np.abs(x-mu)/(sigma*theta*(1 + np.sign(x-mu)*lam)))**k)**(-(n+1)/k)\n", "\n", "@interact(mu=(-3, 3, 0.1), k=(0.1, 5, 0.1), n=(2.1, 10, 0.1), sigma2=(0.1, 3, 0.1), lam=(-0.9, 0.9, 0.1))\n", "def f(mu=0, k=0.5, n=2.5, sigma2=0.1, lam=0):\n", " fig, ax = plt.subplots()\n", " DataFrame([(x, pdf(x, mu, k, n, lam, sigma2)) for x in np.linspace(-2, 2, 500)], columns=['x', 'pdf']).set_index('x').plot(ax=ax)\n", " ax.set(xlim=(-2, 2), ylim=(0, 20))\n", " plt.show()" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.10" } }, "nbformat": 4, "nbformat_minor": 4 }